From ec44ddf38cc0d018a2e98dddabed94b382a05200 Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Wed, 19 Oct 2022 19:18:04 +0800 Subject: [PATCH] LU-15097 quota: stop pool_recalc before killing pool qmt_start_pool_recalc holds a refrence on a pool while it is running. This thread should be stopped before putting the last pool reference in qmt_pool_free to be sure that pool can finally freed. Patch helps to avoid following ASSERTION: qmt_pool_fini() ASSERTION(list_empty(&qmt->qmt_pool_list)) failed Lustre-change: https://review.whamcloud.com/45256 Lustre-commit: 862f0baa7c21cb631b98d3886ef9e938f4519573 Change-Id: If72042a620d9ded693fcb669bc9148d1f96126a4 Signed-off-by: Sergey Cheremencev Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/46656 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger --- lustre/include/obd_support.h | 1 + lustre/quota/qmt_pool.c | 6 ++++++ lustre/tests/sanity-quota.sh | 29 ++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index d61ab11..2dfc2cd 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -536,6 +536,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_QUOTA_DELAY_REINT 0xA03 #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xA04 #define OBD_FAIL_QUOTA_INIT 0xA05 +#define OBD_FAIL_QUOTA_RECALC 0xA07 #define OBD_FAIL_LPROC_REMOVE 0xB00 diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index e31787c..436d0a7 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -466,6 +466,8 @@ void qmt_pool_fini(const struct lu_env *env, struct qmt_device *qmt) /* parse list of pool and destroy each element */ list_for_each_entry_safe(pool, tmp, &qmt->qmt_pool_list, qpi_linkage) { + /* stop all recalc threads - it may hold qpi reference */ + qmt_stop_pool_recalc(pool); /* release extra reference taken in qmt_pool_alloc */ qpi_putref(env, pool); } @@ -1191,6 +1193,7 @@ static int qmt_pool_recalc(void *args) while (obd->obd_process_conf) schedule_timeout_uninterruptible(cfs_time_seconds(1)); + OBD_FAIL_TIMEOUT(OBD_FAIL_QUOTA_RECALC, cfs_fail_val); sem = qmt_sarr_rwsem(pool); LASSERT(sem); down_read(sem); @@ -1376,6 +1379,9 @@ static int qmt_pool_add_rem(struct obd_device *obd, char *poolname, int rc, idx; ENTRY; + if (qmt->qmt_stopping) + RETURN(0); + if (strnlen(poolname, LOV_MAXPOOLNAME + 1) > LOV_MAXPOOLNAME) RETURN(-ENAMETOOLONG); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 491ea0e..148eba4 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -5279,7 +5279,6 @@ test_78() check_set_fallocate_or_skip setup_quota_test || error "setup quota failed with $?" - stack_trap cleanup_quota_test # enable ost quota set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -5314,6 +5313,34 @@ test_78() } run_test 78 "Check fallocate increase quota usage" +test_81() { + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -B 1G $DIR || error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + #define OBD_FAIL_QUOTA_RECALC 0xA07 + do_facet mds1 $LCTL set_param fail_loc=0x80000A07 fail_val=30 + # added OST casues to start pool recalculation + pool_add_targets $qpool 0 0 1 + stop mds1 -f || error "MDS umount failed" + + #start mds1 back to destroy created pool + start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS + clients_up || true +} +run_test 81 "Race qmt_start_pool_recalc with qmt_pool_free" + test_grace_with_default_quota() { local qtype=$1 -- 1.8.3.1