From: Sergey Cheremencev Date: Mon, 6 May 2024 13:05:36 +0000 (+0300) Subject: LU-17356 quota: fix qmt_pool_new_conn X-Git-Tag: 2.15.64~142 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=b64bc2c6f35f9fee35da6eec1e476eab76ad7646;p=fs%2Flustre-release.git LU-17356 quota: fix qmt_pool_new_conn Wrong argument passed into qmt_dom from qmt_pool_new_conn caused a panic: qmt_sarr_get_idx()) ASSERTION( arr_idx < qpi->qpi_sarr.osts.op_count && arr_idx >= 0 ) failed: idx invalid 0 op_count 0 Add conf-sanity_33d that reproduces above assertion without the fix. Fixes: 67f90e4288 ("LU-17034 quota: lqeg_arr memmory corruption") Signed-off-by: Sergey Cheremencev Change-Id: I48801f1fb7e69097cbfbe083f1d31a4639d4bf4d Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55019 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Alexander Boyko Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index 5b4d724..06da9ef 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -1626,7 +1626,7 @@ struct quota_body { #define QUOTA_DQACQ_FL_REPORT 0x8 /* report usage */ /* Quota types currently supported */ -enum { +enum lquota_type { LQUOTA_TYPE_USR = 0x00, /* maps to USRQUOTA */ LQUOTA_TYPE_GRP = 0x01, /* maps to GRPQUOTA */ LQUOTA_TYPE_PRJ = 0x02, /* maps to PRJQUOTA */ @@ -1637,7 +1637,7 @@ enum { * - inodes on the MDTs * - blocks on the OSTs */ -enum { +enum lquota_res_type { LQUOTA_RES_MD = 0x01, /* skip 0 to avoid null oid in FID */ LQUOTA_RES_DT = 0x02, LQUOTA_LAST_RES, diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index 28bbff8..11566ac 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -212,7 +212,8 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) if (fid_is_acct(fid)) { seq_printf(p, "%s:\n", oid2name(fid_oid(fid))); } else if (fid_seq(fid) == FID_SEQ_QUOTA_GLB) { - int rtype, qtype; + enum lquota_res_type rtype; + enum lquota_type qtype; rc = lquota_extract_fid(fid, &rtype, &qtype); if (rc) diff --git a/lustre/quota/lquota_disk.c b/lustre/quota/lquota_disk.c index c00611d..4fa8428 100644 --- a/lustre/quota/lquota_disk.c +++ b/lustre/quota/lquota_disk.c @@ -404,7 +404,8 @@ struct dt_object *lquota_disk_slv_find_create(const struct lu_env *env, qti->qti_fid.f_seq = FID_SEQ_QUOTA; qti->qti_fid.f_ver = 0; if (local) { - int pool_type, qtype; + enum lquota_res_type pool_type; + enum lquota_type qtype; rc = lquota_extract_fid(glb_fid, &pool_type, &qtype); if (rc) diff --git a/lustre/quota/lquota_internal.h b/lustre/quota/lquota_internal.h index 323cec8..054d9a3 100644 --- a/lustre/quota/lquota_internal.h +++ b/lustre/quota/lquota_internal.h @@ -447,7 +447,8 @@ void lquota_lqe_debug0(struct lquota_entry *lqe, struct dt_object *acct_obj_lookup(const struct lu_env *, struct dt_device *, int); void lquota_generate_fid(struct lu_fid *, int, int); -int lquota_extract_fid(const struct lu_fid *, int *, int *); +int lquota_extract_fid(const struct lu_fid *, enum lquota_res_type *, + enum lquota_type *); const struct dt_index_features *glb_idx_feature(struct lu_fid *); int lquota_obj_iter(const struct lu_env *env, struct dt_device *dev, struct dt_object *obj, struct obd_quotactl *oqctl, diff --git a/lustre/quota/lquota_lib.c b/lustre/quota/lquota_lib.c index 9181bb2..da90b7e 100644 --- a/lustre/quota/lquota_lib.c +++ b/lustre/quota/lquota_lib.c @@ -491,8 +491,9 @@ void lquota_generate_fid(struct lu_fid *fid, int pool_type, int quota_type) * Helper routine used to extract pool type and quota type from a * given FID. */ -int lquota_extract_fid(const struct lu_fid *fid, int *pool_type, - int *quota_type) +int lquota_extract_fid(const struct lu_fid *fid, + enum lquota_res_type *pool_type, + enum lquota_type *quota_type) { unsigned int lqtype; ENTRY; diff --git a/lustre/quota/qmt_handler.c b/lustre/quota/qmt_handler.c index ed55ea1..cdfb742 100644 --- a/lustre/quota/qmt_handler.c +++ b/lustre/quota/qmt_handler.c @@ -1182,7 +1182,7 @@ out: * \retval slave type(QMT_STYPE_MDT or QMT_STYPE_OST) * \retval -EINVAL wrong uuid */ -int qmt_uuid2idx(struct obd_uuid *uuid, int *idx) +enum qmt_stype qmt_uuid2idx(struct obd_uuid *uuid, int *idx) { char *uuid_str, *name, *dash; int rc = -EINVAL; @@ -1236,8 +1236,10 @@ static int qmt_dqacq(const struct lu_env *env, struct lu_device *ld, struct quota_body *qbody, *repbody; struct obd_uuid *uuid; struct ldlm_lock *lock; - int rtype, qtype; - int rc, idx, stype; + enum lquota_res_type rtype; + enum lquota_type qtype; + enum qmt_stype stype; + int rc, idx; struct obd_device *obd = NULL; ENTRY; diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index 52714fa..9426a74 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -93,7 +93,7 @@ union qmt_sarray { /* Since DOM support, data resources can exist * on both MDT and OST targets. */ -enum { +enum qmt_stype { QMT_STYPE_MDT, QMT_STYPE_OST, QMT_STYPE_CNT @@ -532,7 +532,7 @@ int qmt_set_with_lqe(const struct lu_env *env, struct qmt_device *qmt, __u64 time, __u32 valid, bool is_default, bool is_updated); int qmt_dqacq0(const struct lu_env *, struct qmt_device *, struct obd_uuid *, __u32, __u64, __u64, struct quota_body *, int); -int qmt_uuid2idx(struct obd_uuid *, int *); +enum qmt_stype qmt_uuid2idx(struct obd_uuid *, int *); /* qmt_lock.c */ int qmt_intent_policy(const struct lu_env *, struct lu_device *, diff --git a/lustre/quota/qmt_lock.c b/lustre/quota/qmt_lock.c index d847529..dced6a7 100644 --- a/lustre/quota/qmt_lock.c +++ b/lustre/quota/qmt_lock.c @@ -90,9 +90,10 @@ int qmt_intent_policy(const struct lu_env *env, struct lu_device *ld, switch (it->opc) { case IT_QUOTA_DQACQ: { - struct lquota_entry *lqe; - struct ldlm_lock *lock; - int idx, stype; + struct lquota_entry *lqe; + struct ldlm_lock *lock; + enum qmt_stype stype; + int idx; if (res->lr_name.name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] == 0) /* acquire on global lock? something is wrong ... */ @@ -178,11 +179,12 @@ out: */ int qmt_lvbo_init(struct lu_device *ld, struct ldlm_resource *res) { - struct lu_env *env; - struct qmt_thread_info *qti; - struct qmt_device *qmt = lu2qmt_dev(ld); - int pool_type, qtype; - int rc; + struct lu_env *env; + struct qmt_thread_info *qti; + struct qmt_device *qmt = lu2qmt_dev(ld); + enum lquota_res_type pool_type; + enum lquota_type qtype; + int rc; ENTRY; LASSERT(res != NULL); @@ -350,15 +352,16 @@ static bool qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe_gl, int qmt_lvbo_update(struct lu_device *ld, struct ldlm_resource *res, struct ptlrpc_request *req, int increase_only) { - struct lu_env *env; - struct qmt_thread_info *qti; - struct qmt_device *qmt = lu2qmt_dev(ld); - struct lquota_entry *lqe; - struct lquota_lvb *lvb; - struct ldlm_lock *lock; - struct obd_export *exp; - bool need_revoke; - int rc = 0, idx, stype; + struct lu_env *env; + struct qmt_thread_info *qti; + struct qmt_device *qmt = lu2qmt_dev(ld); + struct lquota_entry *lqe; + struct lquota_lvb *lvb; + struct ldlm_lock *lock; + struct obd_export *exp; + bool need_revoke; + enum qmt_stype stype; + int rc = 0, idx; ENTRY; LASSERT(res != NULL); @@ -505,16 +508,17 @@ int qmt_lvbo_fill(struct lu_device *ld, struct ldlm_lock *lock, void *lvb, struct lquota_entry *lqe = res->lr_lvb_data; struct qmt_device *qmt; struct obd_uuid *uuid; + enum qmt_stype stype; int idx; uuid = &(lock)->l_export->exp_client_uuid; - rc = qmt_uuid2idx(uuid, &idx); - if (rc < 0) - RETURN(rc); + stype = qmt_uuid2idx(uuid, &idx); + if (stype < 0) + RETURN(stype); qmt = lu2qmt_dev(ld); /* return current qunit value & edquot flags in lvb */ lqe_getref(lqe); - rc = qmt_pool_lqes_lookup(env, qmt, lqe_rtype(lqe), rc, + rc = qmt_pool_lqes_lookup(env, qmt, lqe_rtype(lqe), stype, lqe_qtype(lqe), &lqe->lqe_id, NULL, idx); if (!rc) { @@ -661,7 +665,8 @@ static void qmt_setup_id_desc(struct ldlm_lock *lock, union ldlm_gl_desc *desc, struct lquota_entry *lqe) { struct obd_uuid *uuid = &(lock)->l_export->exp_client_uuid; - int idx, stype; + enum qmt_stype stype; + int idx; __u64 qunit; bool edquot; @@ -884,9 +889,10 @@ static int qmt_id_lock_cb(struct ldlm_lock *lock, struct lquota_entry *lqe) { struct obd_uuid *uuid = &(lock)->l_export->exp_client_uuid; struct lqe_glbl_data *lgd = lqe->lqe_glbl_data; + enum qmt_stype stype; int idx; - int stype = qmt_uuid2idx(uuid, &idx); + stype = qmt_uuid2idx(uuid, &idx); LASSERT(stype == QMT_STYPE_OST || stype == QMT_STYPE_MDT); CDEBUG(D_QUOTA, "stype %d rtype %d idx %d uuid %s\n", diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index 6d08e9e..f64a741 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -60,7 +60,7 @@ static inline int qmt_sarr_pool_init(struct qmt_pool_info *qpi); #define qmt_sarr_pool_add_locked(qpi, idx, stype) \ _qmt_sarr_pool_add(qpi, idx, stype, true) static inline int _qmt_sarr_pool_add(struct qmt_pool_info *qpi, - int idx, int min, bool locked); + int idx, enum qmt_stype min, bool locked); static inline int qmt_sarr_pool_rem(struct qmt_pool_info *qpi, int idx); static inline void qmt_sarr_pool_free(struct qmt_pool_info *qpi); static inline int qmt_sarr_check_idx(struct qmt_pool_info *qpi, int idx); @@ -519,8 +519,9 @@ static int qmt_slv_add(const struct lu_env *env, struct lu_fid *glb_fid, { struct obd_uuid uuid; struct qmt_pool_info *qpi = arg; - int stype, qtype, idx; - int rc; + enum lquota_type qtype; + enum qmt_stype stype; + int idx, rc; rc = lquota_extract_fid(glb_fid, NULL, &qtype); LASSERT(!rc); @@ -786,11 +787,13 @@ int qmt_pool_new_conn(const struct lu_env *env, struct qmt_device *qmt, struct lu_fid *glb_fid, struct lu_fid *slv_fid, __u64 *slv_ver, struct obd_uuid *uuid) { - struct qmt_pool_info *pool; - struct dt_object *slv_obj; - int pool_type, qtype, stype; - bool created = false; - int idx, i, rc = 0; + struct qmt_pool_info *pool; + struct dt_object *slv_obj; + enum lquota_res_type pool_type; + enum lquota_type qtype; + enum qmt_stype stype; + bool created = false; + int idx, i, rc = 0; stype = qmt_uuid2idx(uuid, &idx); if (stype < 0) @@ -833,7 +836,7 @@ int qmt_pool_new_conn(const struct lu_env *env, struct qmt_device *qmt, CDEBUG(D_QUOTA, "add tgt idx:%d pool_type:%d qtype:%d stype:%d\n", idx, pool_type, qtype, stype); - if (!qmt_dom(qtype, stype)) { + if (!qmt_dom(pool_type, stype)) { qmt_sarr_write_down(pool); rc = qmt_sarr_pool_add_locked(pool, idx, stype); if (!rc) { @@ -1636,7 +1639,8 @@ static inline int qmt_sarr_pool_init(struct qmt_pool_info *qpi) } static inline int -_qmt_sarr_pool_add(struct qmt_pool_info *qpi, int idx, int stype, bool locked) +_qmt_sarr_pool_add(struct qmt_pool_info *qpi, int idx, enum qmt_stype stype, + bool locked) { /* We don't have an array for DOM */ if (qmt_dom(qpi->qpi_rtype, stype)) diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index 17ee50e..2d42f25 100755 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -3175,6 +3175,19 @@ test_33c() { } run_test 33c "Mount ost with a large index number" +test_33d() { + setup + stack_trap cleanup + + mkdir_on_mdt0 $DIR/$tdir || error "cannot create $DIR/$tdir" + touch $DIR/$tfile + $LFS setquota -p 1 -I1K $MOUNT + + do_facet mgs $LCTL set_param osd*.*.quota_slave.enabled=p + $LFS project -p 1 $DIR/ +} +run_test 33d "Don't panic when enable project quota" + test_34a() { setup do_facet client "bash runmultiop_bg_pause $DIR/file O_c"