Whamcloud - gitweb
LU-15031 quota: reseed glbe in qmt_lvbo_udate 32/45032/13
authorSergey Cheremencev <sergey.cheremencev@hpe.com>
Tue, 25 May 2021 22:44:48 +0000 (01:44 +0300)
committerOleg Drokin <green@whamcloud.com>
Thu, 6 Jan 2022 22:02:19 +0000 (22:02 +0000)
Reseed glbe array in qmt_lvbo_update after changing edquot.
Without a fix edquot flag wasn't set in glbe array. Later,
when edquot was cleared, need_update(nu) flag wasn't set
in glbe array to notify OSTs with a new edquot.

The patch also adds test 80 to check that OST gets correct
edquot value after failover.

HPE-bug-id: LUS-10029
Change-Id: I5b7e1a553e3351c22649431860d51b5a671c6fd9
Reviewed-by: Shaun Tancheff <stancheff@cray.com>
Reviewed-by: Alexander Boyko <c17825@cray.com>
Signed-off-by: Sergey Cheremencev <sergey.cheremencev@hpe.com>
Reviewed-on: https://review.whamcloud.com/45032
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alexander Boyko <alexander.boyko@hpe.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/obd_support.h
lustre/quota/qmt_handler.c
lustre/quota/qmt_lock.c
lustre/tests/sanity-quota.sh

index cdf406f..d34d0f0 100644 (file)
@@ -535,6 +535,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_DELAY_REINT       0xA03
 #define OBD_FAIL_QUOTA_RECOVERABLE_ERR   0xA04
 #define OBD_FAIL_QUOTA_INIT              0xA05
+#define OBD_FAIL_QUOTA_PREACQ            0xA06
 
 #define OBD_FAIL_LPROC_REMOVE            0xB00
 
 
 #define OBD_FAIL_LPROC_REMOVE            0xB00
 
index 2ed9051..718fbdf 100644 (file)
@@ -652,6 +652,10 @@ int qmt_dqacq0(const struct lu_env *env, struct qmt_device *qmt,
        if (OBD_FAIL_CHECK(OBD_FAIL_QUOTA_RECOVERABLE_ERR))
                RETURN(-cfs_fail_val);
 
        if (OBD_FAIL_CHECK(OBD_FAIL_QUOTA_RECOVERABLE_ERR))
                RETURN(-cfs_fail_val);
 
+       if (OBD_FAIL_CHECK(OBD_FAIL_QUOTA_PREACQ) &&
+          (req_is_preacq(qb_flags) || req_is_rel(qb_flags)))
+               RETURN(-EAGAIN);
+
        if (qti_lqes_restore_init(env))
                RETURN(-ENOMEM);
 
        if (qti_lqes_restore_init(env))
                RETURN(-ENOMEM);
 
index c28b0b2..171d42d 100644 (file)
@@ -287,11 +287,12 @@ static bool qmt_clear_lgeg_arr_nu(struct lquota_entry *lqe, int stype, int idx)
        return false;
 }
 
        return false;
 }
 
-static void qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe,
+static bool qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe,
                          int stype, int idx)
 {
        unsigned long least_qunit = lqe2qpi(lqe)->qpi_least_qunit;
        struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
                          int stype, int idx)
 {
        unsigned long least_qunit = lqe2qpi(lqe)->qpi_least_qunit;
        struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
+       bool notify = false;
 
        if (lgd->lqeg_arr[idx].lge_qunit == least_qunit) {
                int i;
 
        if (lgd->lqeg_arr[idx].lge_qunit == least_qunit) {
                int i;
@@ -305,12 +306,13 @@ static void qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe,
                        if (qti_lqes(env)[i]->lqe_qunit == least_qunit) {
                                qti_lqes(env)[i]->lqe_revoke_time =
                                                        ktime_get_seconds();
                        if (qti_lqes(env)[i]->lqe_qunit == least_qunit) {
                                qti_lqes(env)[i]->lqe_revoke_time =
                                                        ktime_get_seconds();
-                               qmt_adjust_edquot(qti_lqes(env)[i],
+                               notify |= qmt_adjust_edquot(qti_lqes(env)[i],
                                                  ktime_get_real_seconds());
                        }
                }
                qti_lqes_write_unlock(env);
        }
                                                  ktime_get_real_seconds());
                        }
                }
                qti_lqes_write_unlock(env);
        }
+       return notify;
 }
 
 /*
 }
 
 /*
@@ -399,8 +401,11 @@ int qmt_lvbo_update(struct lu_device *ld, struct ldlm_resource *res,
        if (rc)
                GOTO(out_exp, rc);
 
        if (rc)
                GOTO(out_exp, rc);
 
-       if (need_revoke)
-               qmt_set_revoke(env, lqe, rc, idx);
+       if (need_revoke && qmt_set_revoke(env, lqe, rc, idx) &&
+           lqe->lqe_glbl_data) {
+               qmt_seed_glbe_edquot(env, lqe->lqe_glbl_data);
+               qmt_id_lock_notify(qmt, lqe);
+       }
 
        if (lvb->lvb_id_rel) {
                LQUOTA_DEBUG(lqe, "releasing:%llu may release:%llu",
 
        if (lvb->lvb_id_rel) {
                LQUOTA_DEBUG(lqe, "releasing:%llu may release:%llu",
index 614fd46..13837ed 100755 (executable)
@@ -5121,6 +5121,78 @@ test_79()
 }
 run_test 79 "access to non-existed dt-pool/info doesn't cause a panic"
 
 }
 run_test 79 "access to non-existed dt-pool/info doesn't cause a panic"
 
+test_80()
+{
+       local dir1="$DIR/$tdir/dir1"
+       local dir2="$DIR/$tdir/dir2"
+       local TESTFILE0="$dir1/$tfile-0"
+       local TESTFILE1="$dir1/$tfile-1"
+       local TESTFILE2="$dir1/$tfile-2"
+       local TESTFILE3="$dir2/$tfile-0"
+       local global_limit=100 # 100M
+       local limit=10 # 10M
+       local qpool="qpool1"
+
+       [ "$OSTCOUNT" -lt "2" ] && skip "needs >= 2 OSTs"
+       mds_supports_qp
+       [ "$ost1_FSTYPE" == zfs ] &&
+               skip "ZFS grants some block space together with inode"
+       setup_quota_test || error "setup quota failed with $?"
+       set_ost_qtype $QTYPE || error "enable ost quota failed"
+
+       # make sure the system is clean
+       local used=$(getquota -u $TSTUSR global curspace)
+       [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR is not 0."
+
+       pool_add $qpool || error "pool_add failed"
+       pool_add_targets $qpool 0 1 ||
+               error "pool_add_targets failed"
+
+       $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
+               error "set user quota failed"
+
+       $LFS setquota -u $TSTUSR -B ${global_limit}M --pool $qpool $DIR ||
+               error "set user quota failed"
+       $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR ||
+               error "set user quota failed"
+
+       mkdir -p $dir1 || error "failed to mkdir"
+       chown $TSTUSR.$TSTUSR $dir1 || error "chown $dir1 failed"
+       mkdir -p $dir2 || error "failed to mkdir"
+       chown $TSTUSR.$TSTUSR $dir2 || error "chown $dir2 failed"
+
+       $LFS setstripe $dir1 -i 1 -c 1|| error "setstripe $testfile failed"
+       $LFS setstripe $dir2 -i 0 -c 1|| error "setstripe $testfile failed"
+       lfs getstripe $dir1
+       lfs getstripe $dir2
+       sleep 3
+
+       $LFS quota -uv $TSTUSR $DIR
+       #define OBD_FAIL_QUOTA_PREACQ            0xA06
+       do_facet mds1 $LCTL set_param fail_loc=0xa06
+       $RUNAS $DD of=$TESTFILE3 count=3 ||
+               quota_error u $TSTUSR "write failed"
+       $RUNAS $DD of=$TESTFILE2 count=7 ||
+               quota_error u $TSTUSR "write failed"
+       $RUNAS $DD of=$TESTFILE1 count=1 oflag=direct ||
+               quota_error u $TSTUSR "write failed"
+       sync
+       sleep 3
+       $LFS quota -uv --pool $qpool $TSTUSR $DIR
+
+       rm -f $TESTFILE2
+       stop ost2
+       do_facet mds1 $LCTL set_param fail_loc=0
+       start ost2 $(ostdevname 2) $OST_MOUNT_OPTS || error "start ost2 failed"
+       $LFS quota -uv $TSTUSR --pool $qpool $DIR
+       # OST0 needs some time to update quota usage after removing TESTFILE2
+       sleep 4
+       $LFS quota -uv $TSTUSR --pool $qpool $DIR
+       $RUNAS $DD of=$TESTFILE0 count=2 oflag=direct ||
+               quota_error u $TSTUSR "write failure, but expect success"
+}
+run_test 80 "check for EDQUOT after OST failover"
+
 quota_fini()
 {
        do_nodes $(comma_list $(nodes_list)) \
 quota_fini()
 {
        do_nodes $(comma_list $(nodes_list)) \