Whamcloud - gitweb
LU-15021 quota: protect lqe_glbl_data in lqe 98/45098/9
authorHongchao Zhang <hongchao@whamcloud.com>
Wed, 13 Oct 2021 09:02:23 +0000 (17:02 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 17 Mar 2022 07:02:44 +0000 (07:02 +0000)
The lqe_glbl_data in "struct lquota_entry" is allocated in
qmt_lvbo_init and freed in qmt_lvbo_free, it could be freed
during qmt_seed_glbe called by qmt_set_id_notify, and cause
panic because of using freed memory.

Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Change-Id: I274f07ee8609c83852572be51625cc929a9130ec
Reviewed-on: https://review.whamcloud.com/45098
Reviewed-by: Sergey Cheremencev <sergey.cheremencev@hpe.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/quota/lquota_internal.h
lustre/quota/qmt_entry.c
lustre/quota/qmt_handler.c
lustre/quota/qmt_lock.c
lustre/quota/qsd_entry.c

index f10ed72..442b19e 100644 (file)
@@ -189,6 +189,8 @@ struct lquota_entry {
                        lqe_is_global:1,  /* lqe belongs to global pool "0x0"*/
                        lqe_is_deleted:1; /* lqe will be deleted soon */
 
+       /* the lock to protect lqe_glbl_data */
+       struct mutex             lqe_glbl_data_lock;
        struct lqe_glbl_data    *lqe_glbl_data;
 };
 
index 4ad1ef0..a37bf48 100644 (file)
@@ -44,6 +44,7 @@ static void qmt_lqe_init(struct lquota_entry *lqe, void *arg)
 
        lqe->lqe_revoke_time = 0;
        init_rwsem(&lqe->lqe_sem);
+       mutex_init(&lqe->lqe_glbl_data_lock);
 }
 
 /* Apply the default quota setting to the specified quota entry
@@ -841,8 +842,13 @@ bool qmt_adjust_edquot_qunit_notify(const struct lu_env *env,
                return need_reseed;
        }
 
-       if (lqe_gl->lqe_glbl_data && need_reseed) {
-               qmt_seed_glbe_all(env, lqe_gl->lqe_glbl_data, qunit, edquot);
+       if (need_reseed) {
+               mutex_lock(&lqe_gl->lqe_glbl_data_lock);
+               if (lqe_gl->lqe_glbl_data)
+                       qmt_seed_glbe_all(env, lqe_gl->lqe_glbl_data, qunit,
+                                         edquot);
+               mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
                qmt_id_lock_notify(qmt, lqe_gl);
        }
        return need_reseed;
@@ -879,17 +885,23 @@ void qmt_revalidate_lqes(const struct lu_env *env,
        for (i = 0; i < qti_lqes_cnt(env); i++)
                need_notify |= qmt_revalidate(env, qti_lqes(env)[i]);
 
+       if (!need_notify)
+               return;
+
        /* There could be no ID lock to the moment of reconciliation.
         * As a result lqe global data is not initialised yet. It is ok
         * for release and report requests. */
        if (!lqe_gl->lqe_glbl_data &&
-           (req_is_rel(qb_flags) || req_has_rep(qb_flags)))
+           (req_is_rel(qb_flags) || req_has_rep(qb_flags))) {
                return;
+       }
 
-       if (need_notify) {
+       mutex_lock(&lqe_gl->lqe_glbl_data_lock);
+       if (lqe_gl->lqe_glbl_data)
                qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
-               qmt_id_lock_notify(qmt, lqe_gl);
-       }
+       mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
+       qmt_id_lock_notify(qmt, lqe_gl);
 }
 
 void qti_lqes_init(const struct lu_env *env)
index 40679e0..d2789ce 100644 (file)
@@ -122,8 +122,11 @@ static void qmt_set_id_notify(const struct lu_env *env, struct qmt_device *qmt,
        if (!lqe_gl)
                GOTO(lqes_fini, rc);
 
+       mutex_lock(&lqe_gl->lqe_glbl_data_lock);
        if (lqe_gl->lqe_glbl_data)
                qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
+       mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
        /* Even if slaves haven't enqueued quota lock yet,
         * it is needed to set lqe_revoke_time in qmt_id_lock_glimpse
         * in case of reaching qpi_least_qunit */
index 38bde58..49421e3 100644 (file)
@@ -520,10 +520,13 @@ int qmt_lvbo_free(struct lu_device *ld, struct ldlm_resource *res)
                struct lquota_entry *lqe = res->lr_lvb_data;
                struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
 
-               /* release lqe reference */
+               mutex_lock(&lqe->lqe_glbl_data_lock);
                lqe->lqe_glbl_data = NULL;
-               lqe_putref(lqe);
                qmt_free_lqe_gd(lgd);
+               mutex_unlock(&lqe->lqe_glbl_data_lock);
+
+               /* release lqe reference */
+               lqe_putref(lqe);
        } else {
                struct dt_object *obj = res->lr_lvb_data;
                /* release object reference */
index ae724ec..12b877d 100644 (file)
@@ -50,6 +50,7 @@ static void qsd_lqe_init(struct lquota_entry *lqe, void *arg)
        init_waitqueue_head(&lqe->lqe_waiters);
        lqe->lqe_usage    = 0;
        lqe->lqe_nopreacq = false;
+       mutex_init(&lqe->lqe_glbl_data_lock);
 }
 
 /*