Whamcloud - gitweb
LU-17356 quota: fix qmt_pool_new_conn 19/55019/3
authorSergey Cheremencev <scherementsev@ddn.com>
Mon, 6 May 2024 13:05:36 +0000 (16:05 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 5 Jun 2024 04:44:43 +0000 (04:44 +0000)
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 <scherementsev@ddn.com>
Change-Id: I48801f1fb7e69097cbfbe083f1d31a4639d4bf4d
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55019
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alexander Boyko <alexander.boyko@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/quota/lproc_quota.c
lustre/quota/lquota_disk.c
lustre/quota/lquota_internal.h
lustre/quota/lquota_lib.c
lustre/quota/qmt_handler.c
lustre/quota/qmt_internal.h
lustre/quota/qmt_lock.c
lustre/quota/qmt_pool.c
lustre/tests/conf-sanity.sh

index 5b4d724..06da9ef 100644 (file)
@@ -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,
index 28bbff8..11566ac 100644 (file)
@@ -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)
index c00611d..4fa8428 100644 (file)
@@ -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)
index 323cec8..054d9a3 100644 (file)
@@ -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,
index 9181bb2..da90b7e 100644 (file)
@@ -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;
index ed55ea1..cdfb742 100644 (file)
@@ -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;
index 52714fa..9426a74 100644 (file)
@@ -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 *,
index d847529..dced6a7 100644 (file)
@@ -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",
index 6d08e9e..f64a741 100644 (file)
@@ -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))
index 17ee50e..2d42f25 100755 (executable)
@@ -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"