From: James Simmons Date: Mon, 11 Oct 2021 15:10:04 +0000 (-0400) Subject: LU-14927 quota: move qsd_transfer to lquota module X-Git-Tag: 2.14.56~136 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=d2e8208e22f21bb7354a9207f381217c222d3df3 LU-14927 quota: move qsd_transfer to lquota module With osd-zfs inheriting the tainted state of ZFS we can no longer directly use kernel internals that exported GPL only. The osd-zfs modules quota code uses some of these internal functions. The osd-zfs qsd_transfer() function is generic enough that we can move it to the lquota modules. Change-Id: I735db0266306477cd5558968f1f3ed1f6e1b32da Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/44735 Reviewed-by: Andreas Dilger Tested-by: jenkins Reviewed-by: Alex Zhuravlev Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre_quota.h b/lustre/include/lustre_quota.h index 53b6312..9844dbf 100644 --- a/lustre/include/lustre_quota.h +++ b/lustre/include/lustre_quota.h @@ -196,6 +196,10 @@ void qsd_op_end(const struct lu_env *, struct qsd_instance *, struct lquota_trans *); void qsd_op_adjust(const struct lu_env *, struct qsd_instance *, union lquota_id *, int); +int qsd_transfer(const struct lu_env *env, struct qsd_instance *qsd, + struct lquota_trans *trans, unsigned int qtype, + u64 orig_id, u64 new_id, u64 bspace, + struct lquota_id_info *qi); int qsd_reserve_or_free_quota(const struct lu_env *env, struct qsd_instance *qsd, struct lquota_id_info *qi); diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index 85bb856..34dfae4 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -1048,67 +1048,6 @@ out: return rc; } -/* Simple wrapper on top of qsd API which implement quota transfer for osd - * setattr needs. As a reminder, only the root user can change ownership of - * a file, that's why EDQUOT & EINPROGRESS errors are discarded */ -static inline int qsd_transfer(const struct lu_env *env, - struct qsd_instance *qsd, - struct lquota_trans *trans, int qtype, - __u64 orig_id, __u64 new_id, __u64 bspace, - struct lquota_id_info *qi) -{ - int rc; - - if (unlikely(qsd == NULL)) - return 0; - - LASSERT(qtype >= 0 && qtype < LL_MAXQUOTAS); - qi->lqi_type = qtype; - - /* inode accounting */ - qi->lqi_is_blk = false; - - /* one more inode for the new owner ... */ - qi->lqi_id.qid_uid = new_id; - qi->lqi_space = 1; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (rc == -EDQUOT || rc == -EINPROGRESS) - rc = 0; - if (rc) - return rc; - - /* and one less inode for the current id */ - qi->lqi_id.qid_uid = orig_id;; - qi->lqi_space = -1; - /* can't get EDQUOT when reducing usage */ - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (rc == -EINPROGRESS) - rc = 0; - if (rc) - return rc; - - /* block accounting */ - qi->lqi_is_blk = true; - - /* more blocks for the new owner ... */ - qi->lqi_id.qid_uid = new_id; - qi->lqi_space = bspace; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (rc == -EDQUOT || rc == -EINPROGRESS) - rc = 0; - if (rc) - return rc; - - /* and finally less blocks for the current owner */ - qi->lqi_id.qid_uid = orig_id; - qi->lqi_space = -bspace; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - /* can't get EDQUOT when reducing usage */ - if (rc == -EINPROGRESS) - rc = 0; - return rc; -} - static int osd_declare_attr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_attr *attr, @@ -1172,66 +1111,63 @@ static int osd_declare_attr_set(const struct lu_env *env, attr->la_uid, attr->la_gid, bspace, blksize); } /* to preserve locking order - qsd_transfer() may need to flush - * currently running transaction when we're out of quota. */ + * currently running transaction when we're out of quota. + */ up_read(&obj->oo_guard); - if (attr && attr->la_valid & LA_UID) { - /* quota enforcement for user */ - if (attr->la_uid != obj->oo_attr.la_uid) { - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, USRQUOTA, - obj->oo_attr.la_uid, attr->la_uid, - bspace, &info->oti_qi); - if (rc) - GOTO(out, rc); - } + /* quota enforcement for user */ + if (attr && attr->la_valid & LA_UID && + attr->la_uid != obj->oo_attr.la_uid) { + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, USRQUOTA, + obj->oo_attr.la_uid, attr->la_uid, + bspace, &info->oti_qi); + if (rc) + GOTO(out, rc); } - if (attr && attr->la_valid & LA_GID) { - /* quota enforcement for group */ - if (attr->la_gid != obj->oo_attr.la_gid) { - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, GRPQUOTA, - obj->oo_attr.la_gid, attr->la_gid, - bspace, &info->oti_qi); - if (rc) - GOTO(out, rc); - } + + /* quota enforcement for group */ + if (attr && attr->la_valid & LA_GID && + attr->la_gid != obj->oo_attr.la_gid) { + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, GRPQUOTA, + obj->oo_attr.la_gid, attr->la_gid, + bspace, &info->oti_qi); + if (rc) + GOTO(out, rc); } #ifdef ZFS_PROJINHERIT - if (attr && attr->la_valid & LA_PROJID) { - /* quota enforcement for project */ - if (attr->la_projid != obj->oo_attr.la_projid) { - if (!osd->od_projectused_dn) - GOTO(out, rc = -EOPNOTSUPP); - - if (!projid_valid(make_kprojid(&init_user_ns, attr->la_projid))) - GOTO(out, rc = -EINVAL); - - /* 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); - - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, PRJQUOTA, - obj->oo_attr.la_projid, - attr->la_projid, bspace, - &info->oti_qi); - if (rc) - GOTO(out, rc); - } + /* quota enforcement for project */ + if (attr && attr->la_valid & LA_PROJID && + attr->la_projid != obj->oo_attr.la_projid) { + 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); + + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, PRJQUOTA, + obj->oo_attr.la_projid, + attr->la_projid, bspace, + &info->oti_qi); + if (rc) + GOTO(out, rc); } #endif out: diff --git a/lustre/quota/qsd_handler.c b/lustre/quota/qsd_handler.c index ea75142..1c8e43a 100644 --- a/lustre/quota/qsd_handler.c +++ b/lustre/quota/qsd_handler.c @@ -1136,6 +1136,72 @@ void qsd_op_end(const struct lu_env *env, struct qsd_instance *qsd, } EXPORT_SYMBOL(qsd_op_end); +/* Simple wrapper on top of qsd API which implement quota transfer for osd + * setattr needs. As a reminder, only the root user can change ownership of + * a file, that's why EDQUOT & EINPROGRESS errors are discarded + */ +int qsd_transfer(const struct lu_env *env, struct qsd_instance *qsd, + struct lquota_trans *trans, unsigned int qtype, + u64 orig_id, u64 new_id, u64 bspace, + struct lquota_id_info *qi) +{ + int rc; + + if (unlikely(!qsd)) + return 0; + + LASSERT(qtype < LL_MAXQUOTAS); + if (qtype == PRJQUOTA) + if (!projid_valid(make_kprojid(&init_user_ns, new_id))) + return -EINVAL; + + qi->lqi_type = qtype; + + /* inode accounting */ + qi->lqi_is_blk = false; + + /* one more inode for the new owner ... */ + qi->lqi_id.qid_uid = new_id; + qi->lqi_space = 1; + rc = qsd_op_begin(env, qsd, trans, qi, NULL); + if (rc == -EDQUOT || rc == -EINPROGRESS) + rc = 0; + if (rc) + return rc; + + /* and one less inode for the current id */ + qi->lqi_id.qid_uid = orig_id; + qi->lqi_space = -1; + /* can't get EDQUOT when reducing usage */ + rc = qsd_op_begin(env, qsd, trans, qi, NULL); + if (rc == -EINPROGRESS) + rc = 0; + if (rc) + return rc; + + /* block accounting */ + qi->lqi_is_blk = true; + + /* more blocks for the new owner ... */ + qi->lqi_id.qid_uid = new_id; + qi->lqi_space = bspace; + rc = qsd_op_begin(env, qsd, trans, qi, NULL); + if (rc == -EDQUOT || rc == -EINPROGRESS) + rc = 0; + if (rc) + return rc; + + /* and finally less blocks for the current owner */ + qi->lqi_id.qid_uid = orig_id; + qi->lqi_space = -bspace; + rc = qsd_op_begin(env, qsd, trans, qi, NULL); + /* can't get EDQUOT when reducing usage */ + if (rc == -EINPROGRESS) + rc = 0; + return rc; +} +EXPORT_SYMBOL(qsd_transfer); + /** * Trigger pre-acquire/release if necessary. * It's only used by ldiskfs osd so far. When unlink a file in ldiskfs, the