From 862f0baa7c21cb631b98d3886ef9e938f4519573 Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Mon, 20 Sep 2021 15:08:20 +0300 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 HPE-bug-id: LUS-10294 Change-Id: If72042a620d9ded693fcb669bc9148d1f96126a4 Signed-off-by: Sergey Cheremencev Reviewed-on: https://review.whamcloud.com/45256 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alexander Boyko Reviewed-by: Alexey Lyashkov Reviewed-by: Andriy Skulysh Reviewed-by: Oleg Drokin --- 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 d34d0f0..1774f7e 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_RECOVERABLE_ERR 0xA04 #define OBD_FAIL_QUOTA_INIT 0xA05 #define OBD_FAIL_QUOTA_PREACQ 0xA06 +#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 bf9241c..c4398a5 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); } @@ -1179,6 +1181,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); @@ -1364,6 +1367,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 13837ed..f0e310b 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -5070,7 +5070,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" @@ -5193,6 +5192,34 @@ test_80() } run_test 80 "check for EDQUOT after OST failover" +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" + quota_fini() { do_nodes $(comma_list $(nodes_list)) \ -- 1.8.3.1