From e3511c6dbfb097308f48957e2e2df8c25f87030a Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Tue, 25 Apr 2023 22:10:21 +0400 Subject: [PATCH] LU-16772 quota: protect lqe_glbl_data in qmt_site_recalc_cb lqe_glbl_data should be protected with lqe_glbl_data_lock in qmt_site_reaclc_sb like it did in other places. Otherwise it may cause following panic: BUG: unable to handle kernel NULL pointer at 00000000000000f8 qmt_site_recalc_cb+0x2f8/0x790 [lquota] cfs_hash_for_each_tight+0x121/0x310 [libcfs] qmt_pool_recalc+0x372/0x9f0 [lquota] Also protect lqe_glbl_data access with lqe_glbl_data_lock in qmt_lvbo_free(). Fixes: 1dbcbd70f8 ("LU-15021 quota: protect lqe_glbl_data in lqe") Signed-off-by: Sergey Cheremencev Change-Id: I030f14b02062151f1708a03ac7414a9991f798f6 --- lustre/quota/qmt_entry.c | 3 +++ lustre/quota/qmt_lock.c | 5 +++-- lustre/quota/qmt_pool.c | 12 ++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index a8f0672..1871d29 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -1118,6 +1118,9 @@ struct lqe_glbl_data *qmt_alloc_lqe_gd(struct qmt_pool_info *pool, int qtype) void qmt_free_lqe_gd(struct lqe_glbl_data *lgd) { + if (unlikely(!lgd)) + return; + OBD_FREE(lgd->lqeg_arr, sizeof(struct lqe_glbl_entry) * lgd->lqeg_num_alloc); OBD_FREE(lgd, sizeof(struct lqe_glbl_data)); diff --git a/lustre/quota/qmt_lock.c b/lustre/quota/qmt_lock.c index c551aa8..033ed5b 100644 --- a/lustre/quota/qmt_lock.c +++ b/lustre/quota/qmt_lock.c @@ -520,12 +520,13 @@ int qmt_lvbo_free(struct lu_device *ld, struct ldlm_resource *res) if (res->lr_name.name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] != 0) { struct lquota_entry *lqe = res->lr_lvb_data; - struct lqe_glbl_data *lgd = lqe->lqe_glbl_data; + struct lqe_glbl_data *lgd; mutex_lock(&lqe->lqe_glbl_data_lock); + lgd = lqe->lqe_glbl_data; lqe->lqe_glbl_data = NULL; - qmt_free_lqe_gd(lgd); mutex_unlock(&lqe->lqe_glbl_data_lock); + qmt_free_lqe_gd(lgd); /* release lqe reference */ lqe_putref(lqe); diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index decd399d..232f616 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -1088,10 +1088,14 @@ static int qmt_site_recalc_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd, /* Find all lqes with lqe_id to reseed lgd array */ rc = qmt_pool_lqes_lookup_spec(env, qmt, lqe_rtype(lqe), lqe_qtype(lqe), &lqe->lqe_id); - if (!rc && qti_lqes_glbl(env)->lqe_glbl_data) { - qmt_seed_glbe(env, - qti_lqes_glbl(env)->lqe_glbl_data); - qmt_id_lock_notify(qmt, qti_lqes_glbl(env)); + if (!rc) { + struct lquota_entry *lqeg = qti_lqes_glbl(env); + + mutex_lock(&lqeg->lqe_glbl_data_lock); + if (lqeg->lqe_glbl_data) + qmt_seed_glbe(env, lqeg->lqe_glbl_data); + mutex_unlock(&lqeg->lqe_glbl_data_lock); + qmt_id_lock_notify(qmt, lqeg); } qti_lqes_fini(env); } -- 1.8.3.1