From 9f5fb96b6cfef702122d046544535ed922318c7c Mon Sep 17 00:00:00 2001 From: tianzy Date: Tue, 1 Jul 2008 13:26:03 +0000 Subject: [PATCH] Branch b1_6 when setquota is executed, quota limitation on slaves is always reset which leads to this bug. Now only first setquota and cancelling quota will reset quota limitation on slaves. b=16053 i=andrew.perepechko i=johann --- lustre/quota/quota_context.c | 13 +++++-- lustre/quota/quota_master.c | 27 +++++++++------ lustre/tests/sanity-quota.sh | 80 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 14 deletions(-) diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c index 8be20ec..f638734 100644 --- a/lustre/quota/quota_context.c +++ b/lustre/quota/quota_context.c @@ -553,14 +553,23 @@ dqacq_completion(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, } CDEBUG(D_QUOTA, "hardlimt: "LPU64"\n", *hardlimit); + + if (*hardlimit == 0) + goto out_mem; + switch (opc) { case QUOTA_DQACQ: INC_QLIMIT(*hardlimit, count); break; case QUOTA_DQREL: LASSERTF(count < *hardlimit, - "count: "LPU64", hardlimit: "LPU64".\n", - count, *hardlimit); + "id(%u) flag(%u) type(%c) isblk(%c) " + "count("LPU64") qd_qunit("LPU64") " + "hardlimit("LPU64").\n", + qdata->qd_id, qdata->qd_flags, + QDATA_IS_GRP(qdata) ? 'g' : 'u', + QDATA_IS_BLK(qdata) ? 'b': 'i', + qdata->qd_count, qdata->qd_qunit, *hardlimit); *hardlimit -= count; break; default: diff --git a/lustre/quota/quota_master.c b/lustre/quota/quota_master.c index fbead72..4d67195 100644 --- a/lustre/quota/quota_master.c +++ b/lustre/quota/quota_master.c @@ -1063,7 +1063,7 @@ static int mds_init_slave_ilimits(struct obd_device *obd, /* if we are going to set zero limit, needn't init slaves */ if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit && - set) + !set) RETURN(0); OBD_ALLOC_PTR(ioqc); @@ -1071,7 +1071,7 @@ static int mds_init_slave_ilimits(struct obd_device *obd, RETURN(-ENOMEM); flag = oqctl->qc_dqblk.dqb_ihardlimit || - oqctl->qc_dqblk.dqb_isoftlimit || set; + oqctl->qc_dqblk.dqb_isoftlimit || !set; ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA; ioqc->qc_id = oqctl->qc_id; ioqc->qc_type = oqctl->qc_type; @@ -1130,7 +1130,7 @@ static int mds_init_slave_blimits(struct obd_device *obd, /* if we are going to set zero limit, needn't init slaves */ if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit && - set) + !set) RETURN(0); OBD_ALLOC_PTR(ioqc); @@ -1138,7 +1138,7 @@ static int mds_init_slave_blimits(struct obd_device *obd, RETURN(-ENOMEM); flag = oqctl->qc_dqblk.dqb_bhardlimit || - oqctl->qc_dqblk.dqb_bsoftlimit || set; + oqctl->qc_dqblk.dqb_bsoftlimit || !set; ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA; ioqc->qc_id = oqctl->qc_id; ioqc->qc_type = oqctl->qc_type; @@ -1199,7 +1199,10 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) time_t btime, itime; struct lustre_dquot *dquot; struct obd_dqblk *dqblk = &oqctl->qc_dqblk; - int set, rc, rc2 = 0, flag = 0; + /* orig_set means if quota was set before; now_set means we are + * setting/cancelling quota */ + int orig_set, now_set; + int rc, rc2 = 0, flag = 0; ENTRY; OBD_ALLOC_PTR(oqaq); @@ -1293,24 +1296,26 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) } up(&mds->mds_qonoff_sem); - if (dqblk->dqb_valid & QIF_ILIMITS) { - set = !(ihardlimit || isoftlimit); + orig_set = ihardlimit || isoftlimit; + now_set = dqblk->dqb_ihardlimit || dqblk->dqb_isoftlimit; + if (dqblk->dqb_valid & QIF_ILIMITS && orig_set != now_set) { down(&dquot->dq_sem); dquot->dq_dqb.dqb_curinodes = 0; up(&dquot->dq_sem); - rc = mds_init_slave_ilimits(obd, oqctl, set, oqaq); + rc = mds_init_slave_ilimits(obd, oqctl, orig_set, oqaq); if (rc) { CERROR("init slave ilimits failed! (rc:%d)\n", rc); goto revoke_out; } } - if (dqblk->dqb_valid & QIF_BLIMITS) { - set = !(bhardlimit || bsoftlimit); + orig_set = bhardlimit || bsoftlimit; + now_set = dqblk->dqb_bhardlimit || dqblk->dqb_bsoftlimit; + if (dqblk->dqb_valid & QIF_BLIMITS && orig_set != now_set) { down(&dquot->dq_sem); dquot->dq_dqb.dqb_curspace = 0; up(&dquot->dq_sem); - rc = mds_init_slave_blimits(obd, oqctl, set, oqaq); + rc = mds_init_slave_blimits(obd, oqctl, orig_set, oqaq); if (rc) { CERROR("init slave blimits failed! (rc:%d)\n", rc); goto revoke_out; diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 8da422a..a2b3576 100644 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -47,7 +47,7 @@ LUSTRE=${LUSTRE:-`dirname $0`/..} init_test_env $@ . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh} -[ "$SLOW" = "no" ] && EXCEPT_SLOW="9 10 11" +[ "$SLOW" = "no" ] && EXCEPT_SLOW="9 10 11 21" QUOTALOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log} @@ -1504,6 +1504,84 @@ test_20() } run_test 20 "test if setquota specifiers work properly (15754)" +test_21_sub() { + local testfile=$1 + local blk_number=$2 + local seconds=$3 + + time=$(($(date +%s) + seconds)) + while [ $(date +%s) -lt $time ]; do + $RUNAS dd if=/dev/zero of=$testfile bs=$BLK_SZ count=$blk_number > /dev/null 2>&1 + rm -f $testfile + done +} + +# run for fixing bug16053, setquota shouldn't fail when writing and +# deleting are happening +test_21() { + set_blk_tunesz 512 + set_blk_unitsz 1024 + + wait_delete_completed + + TESTFILE="$DIR/$tdir/$tfile" + + BLK_LIMIT=$((10 * 1024 * 1024)) # 10G + FILE_LIMIT=1000000 + + log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for user: $TSTUSR" + $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $MOUNT + log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for group: $TSTUSR" + $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $MOUNT + + # repeat writing on a 1M file + test_21_sub ${TESTFILE}_1 1024 30 & + DDPID1=$! + # repeat writing on a 128M file + test_21_sub ${TESTFILE}_2 $((1024 * 128)) 30 & + DDPID2=$! + + time=$(($(date +%s) + 30)) + i=1 + while [ $(date +%s) -lt $time ]; do + log " Set quota for $i times" + $LFS setquota -u $TSTUSR -b 0 -B $((BLK_LIMIT + 1024 * i)) -i 0 -I $((FILE_LIMIT + i)) $MOUNT + $LFS setquota -g $TSTUSR -b 0 -B $((BLK_LIMIT + 1024 * i)) -i 0 -I $((FILE_LIMIT + i)) $MOUNT + i=$((i+1)) + sleep 1 + done + + count=0 + while [ true ]; do + if [ $(ps -p ${DDPID1} | wc -l) -eq 1 ]; then break; fi + count=$[count+1] + if [ $count -gt 60 ]; then + error "dd should be finished!" + fi + sleep 1 + done + echo "(dd_pid=$DDPID1, time=$count)successful" + + count=0 + while [ true ]; do + if [ $(ps -p ${DDPID2} | wc -l) -eq 1 ]; then break; fi + count=$[count+1] + if [ $count -gt 60 ]; then + error "dd should be finished!" + fi + sleep 1 + done + echo "(dd_pid=$DDPID2, time=$count)successful" + + set_blk_unitsz $((128 * 1024)) + set_blk_tunesz $((128 * 1024 / 2)) + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $MOUNT + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $MOUNT + + return $RC +} +run_test 21 "run for fixing bug16053 ===========" + # turn off quota test_99() { -- 1.8.3.1