Whamcloud - gitweb
LU-15097 quota: stop pool_recalc before killing pool
authorSergey Cheremencev <sergey.cheremencev@hpe.com>
Wed, 19 Oct 2022 11:18:04 +0000 (19:18 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Thu, 27 Oct 2022 03:22:04 +0000 (03:22 +0000)
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 <sergey.cheremencev@hpe.com>
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/46656
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/include/obd_support.h
lustre/quota/qmt_pool.c
lustre/tests/sanity-quota.sh

index d61ab11..2dfc2cd 100644 (file)
@@ -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
 
index e31787c..436d0a7 100644 (file)
@@ -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);
 
index 491ea0e..148eba4 100755 (executable)
@@ -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