From: Hongchao Zhang Date: Wed, 13 Oct 2021 09:02:23 +0000 (+0800) Subject: LU-15021 quota: protect lqe_glbl_data in lqe X-Git-Tag: 2.15.0-RC3~30 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=1dbcbd70f87b7390998cd3b1fa546ece9d2a493e;p=fs%2Flustre-release.git LU-15021 quota: protect lqe_glbl_data in lqe 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 Change-Id: I274f07ee8609c83852572be51625cc929a9130ec Reviewed-on: https://review.whamcloud.com/45098 Reviewed-by: Sergey Cheremencev Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/quota/lquota_internal.h b/lustre/quota/lquota_internal.h index f10ed72..442b19e 100644 --- a/lustre/quota/lquota_internal.h +++ b/lustre/quota/lquota_internal.h @@ -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; }; diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 4ad1ef0..a37bf48 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -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) diff --git a/lustre/quota/qmt_handler.c b/lustre/quota/qmt_handler.c index 40679e0..d2789ce 100644 --- a/lustre/quota/qmt_handler.c +++ b/lustre/quota/qmt_handler.c @@ -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 */ diff --git a/lustre/quota/qmt_lock.c b/lustre/quota/qmt_lock.c index 38bde58..49421e3 100644 --- a/lustre/quota/qmt_lock.c +++ b/lustre/quota/qmt_lock.c @@ -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 */ diff --git a/lustre/quota/qsd_entry.c b/lustre/quota/qsd_entry.c index ae724ec..12b877d 100644 --- a/lustre/quota/qsd_entry.c +++ b/lustre/quota/qsd_entry.c @@ -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); } /*