From ec79791a7cda5b66649200b16a70167d86059e65 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 23 Jun 2022 16:36:19 +1000 Subject: [PATCH] LU-13189 osd-zfs: add project id for old objects without ZFS_PROJID After project quota zpool upgrade, the ZFS_PROJID flag could still be missing on some old objects. We used to check for this and return ENXIO in osd_declare_attr_set(), however the check is changed by "LU-12309 osd-zfs: Support disabled project quotas". Now if the target project id is the default project id 0, we will pass the check in osd_declare_attr_set() and trigger the assert in osd_attr_set() later. Instead of returning ENXIO, we could adjust the attribute layout of the old objects to accommodate project id. Also add back the logic from "LU-14740 quota: reject invalid project id on server side", which got removed by "LU-14927 quota: move qsd_transfer to lquota module", due to using GPL symbols. Change-Id: Ib62fdd2a0e07f15ae12daf564273a249a54dd8ea Fixes: 291e7196d3 ("LU-12309 osd-zfs: Support disabled project quotas") Fixes: d2e8208e22 ("LU-14927 quota: move qsd_transfer to lquota module") Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/47709 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: Nathaniel Clark Reviewed-by: Oleg Drokin --- lustre/osd-zfs/osd_object.c | 128 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 22 deletions(-) diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index 8b1310c..2a0e87d 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -1048,6 +1048,94 @@ out: return rc; } +#ifdef ZFS_PROJINHERIT +/* + * For the existed object that is upgraded from old system, its ondisk layout + * has no slot for the project ID attribute. But quota accounting logic needs + * to access related slots by offset directly. So we need to adjust these old + * objects' layout to make the project ID to some unified and fixed offset. + */ +static int osd_add_projid(const struct lu_env *env, struct osd_object *obj, + struct osd_thandle *oh, uint64_t projid) +{ + sa_bulk_attr_t *bulk = osd_oti_get(env)->oti_attr_bulk; + struct osa_attr *osa = &osd_oti_get(env)->oti_osa; + struct osd_device *osd = osd_obj2dev(obj); + uint64_t gen; + size_t sa_size; + char *dxattr = NULL; + int rc, cnt; + + rc = -sa_lookup(obj->oo_sa_hdl, SA_ZPL_PROJID(osd), &osa->projid, 8); + if (unlikely(rc == 0)) + rc = -EEXIST; + if (rc != -ENOENT) + GOTO(out, rc); + + gen = dmu_tx_get_txg(oh->ot_tx); + osa->atime[0] = obj->oo_attr.la_atime; + osa->ctime[0] = obj->oo_attr.la_ctime; + osa->mtime[0] = obj->oo_attr.la_mtime; + osa->btime[0] = obj->oo_attr.la_btime; + osa->mode = obj->oo_attr.la_mode; + osa->uid = obj->oo_attr.la_uid; + osa->gid = obj->oo_attr.la_gid; + osa->rdev = obj->oo_attr.la_rdev; + osa->nlink = obj->oo_attr.la_nlink; + osa->flags = attrs_fs2zfs(obj->oo_attr.la_flags) | ZFS_PROJID; + osa->size = obj->oo_attr.la_size; + osa->projid = projid; + + cnt = 0; + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MODE(osd), NULL, &osa->mode, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_SIZE(osd), NULL, &osa->size, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_GEN(osd), NULL, &gen, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_UID(osd), NULL, &osa->uid, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_GID(osd), NULL, &osa->gid, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PARENT(osd), NULL, + &obj->oo_parent, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_FLAGS(osd), NULL, &osa->flags, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, osa->btime, 16); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PROJID(osd), NULL, &osa->projid, 8); + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_RDEV(osd), NULL, &osa->rdev, 8); + LASSERT(cnt <= ARRAY_SIZE(osd_oti_get(env)->oti_attr_bulk)); + + if (obj->oo_sa_xattr == NULL) { + rc = __osd_xattr_load(osd, obj->oo_sa_hdl, &obj->oo_sa_xattr); + if (rc) + GOTO(out, rc); + } + + if (obj->oo_sa_xattr) { + rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR); + if (rc) + GOTO(out, rc); + + dxattr = osd_zio_buf_alloc(sa_size); + if (dxattr == NULL) + GOTO(out, rc = -ENOMEM); + + rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size, + NV_ENCODE_XDR, KM_SLEEP); + if (rc) + GOTO(out, rc); + + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_DXATTR(osd), + NULL, dxattr, sa_size); + } + + rc = -sa_replace_all_by_template(obj->oo_sa_hdl, bulk, cnt, oh->ot_tx); +out: + if (dxattr) + osd_zio_buf_free(dxattr, sa_size); + return rc; +} +#endif + static int osd_declare_attr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_attr *attr, @@ -1143,23 +1231,8 @@ static int osd_declare_attr_set(const struct lu_env *env, if (!osd->od_projectused_dn) GOTO(out, rc = -EOPNOTSUPP); - /* Usually, if project quota is upgradable for the - * device, then the upgrade will be done before or when - * mount the device. So when we come here, this project - * should have project ID attribute already (that is - * zero by default). Otherwise, there was something - * wrong during the former upgrade, let's return failure - * to report that. - * - * Please note that, different from other attributes, - * you can NOT simply set the project ID attribute under - * such case, because adding (NOT change) project ID - * attribute needs to change the object's attribute - * layout to match zfs backend quota accounting - * requirement. - */ - if (unlikely(!obj->oo_with_projid)) - GOTO(out, rc = -ENXIO); + if (!zpl_is_valid_projid(attr->la_projid)) + GOTO(out, rc = -EINVAL); rc = qsd_transfer(env, osd_def_qsd(osd), &oh->ot_quota_trans, PRJQUOTA, @@ -1297,11 +1370,22 @@ static int osd_attr_set(const struct lu_env *env, struct dt_object *dt, if (valid & LA_PROJID) { #ifdef ZFS_PROJINHERIT if (osd->od_projectused_dn) { - LASSERT(obj->oo_with_projid); - - osa->projid = obj->oo_attr.la_projid = la->la_projid; - SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PROJID(osd), NULL, - &osa->projid, 8); + if (obj->oo_with_projid) { + osa->projid = la->la_projid; + SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PROJID(osd), + NULL, &osa->projid, 8); + } else { + rc = osd_add_projid(env, obj, oh, + la->la_projid); + if (unlikely(rc == -EEXIST)) { + rc = 0; + } else if (rc != 0) { + write_unlock(&obj->oo_attr_lock); + GOTO(out, rc); + } + obj->oo_with_projid = 1; + } + obj->oo_attr.la_projid = la->la_projid; } else #endif valid &= ~LA_PROJID; -- 1.8.3.1