X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Ftests%2Fsanity-quota.sh;h=210a5796332511ecc2c6186b1438b2b2c0c0aca2;hp=c0577692304e12c3200b862e03a7f2605bfc649f;hb=e5c8f6670fbeea9ec8c6092dfa4369508da54485;hpb=d8226b9353dbc1448af8d23c13cae5f21cbe3a86 diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index c057769..210a579 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -20,7 +20,7 @@ ALWAYS_EXCEPT+=" 55" # Test duration: 30 min [ "$SLOW" = "no" ] && EXCEPT_SLOW="61" -if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then +if [ "$mds1_FSTYPE" = zfs ]; then # bug number: LU-2887 # Test duration: 21 9 min" [ "$SLOW" = "no" ] && EXCEPT_SLOW+=" 12a 9" @@ -39,15 +39,21 @@ BLK_SZ=1024 MAX_DQ_TIME=604800 MAX_IQ_TIME=604800 QTYPE="ugp" +# QP exists since this version. Should be finally set before landing. +VERSION_WITH_QP="2.13.53" +mds_supports_qp() { + [ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ] && + skip "Needs MDS version $VERSION_WITH_QP or later." +} require_dsh_mds || exit 0 require_dsh_ost || exit 0 # Does e2fsprogs support quota feature? -if [ $(facet_fstype $SINGLEMDS) == ldiskfs ] && +if [ "$mds1_FSTYPE" == ldiskfs ] && do_facet $SINGLEMDS "! $DEBUGFS -c -R supported_features | grep -q 'quota'"; then - skip_env "e2fsprogs doesn't support quota" && exit 0 + skip_env "e2fsprogs doesn't support quota" fi QUOTALOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log} @@ -138,6 +144,7 @@ quota_scan() { xargs stat 2>/dev/null) fi + is_project_quota_supported || return 0 if [ "$local_ugp" == "a" -o "$local_ugp" == "p" ]; then $LFS quota -v -p $TSTPRJID $DIR log "Files for project ($TSTPRJID):" @@ -160,14 +167,17 @@ quota_log() { # get quota for a user or a group # usage: getquota -u|-g|-p || global| \ -# bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace +# bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace \ +# getquota() { local spec local uuid + local pool_arg sync_all_data > /dev/null 2>&1 || true - [ "$#" != 4 ] && error "getquota: wrong number of arguments: $#" + [ "$#" != 4 -a "$#" != 5 ] && + error "getquota: wrong number of arguments: $#" [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] && error "getquota: wrong u/g/p specifier $1 passed" @@ -185,9 +195,10 @@ getquota() { *) error "unknown quota parameter $4";; esac + [ ! -z "$5" ] && pool_arg="--pool $5 " [ "$uuid" = "global" ] && uuid=$DIR - $LFS quota -v "$1" "$2" $DIR | + $LFS quota -v "$1" "$2" $pool_arg $DIR | awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") \ { if (NF == 1) { getline } else { num++ } ; print $num;} }' \ | tr -d "*" @@ -324,8 +335,10 @@ wait_ost_reint() { wait_grace_time() { local qtype=$1 local flavour=$2 - local extrasleep=${3:-5} + local pool=${3:-} + local extrasleep=${4:-5} local qarg + local parg case $qtype in u|g) qarg=$TSTUSR ;; @@ -333,9 +346,15 @@ wait_grace_time() { *) error "get_grace_time: Invalid quota type: $qtype" esac + if [ $pool ]; then + parg="--pool "$pool + echo "Quota info for $pool:" + $LFS quota -$qtype $qarg $parg $DIR + fi + case $flavour in block) - time=$(lfs quota -$qtype $qarg $DIR| + time=$(lfs quota -$qtype $qarg $parg $DIR| awk 'NR == 3{ print $5 }'| sed 's/s$//') ;; file) @@ -347,6 +366,14 @@ wait_grace_time() { ;; esac + # from lfs.c:__sec2str() + # const char spec[] = "smhdw"; + # {1, 60, 60*60, 24*60*60, 7*24*60*60}; + [[ $time == *m* ]] && time=${time//m/} && time=$((time*60)); + [[ $time == *h* ]] && time=${time//h/} && time=$((time*60*60)); + [[ $time == *d* ]] && time=${time//d/} && time=$((time*24*60*60)); + [[ $time == *w* ]] && time=${time//w/} && time=$((time*7*24*60*60)); + echo "Sleep through grace ..." [ "$time" == "-" ] && error "Grace timeout was not set or quota not exceeded" @@ -370,7 +397,6 @@ setup_quota_test() { } cleanup_quota_test() { - trap 0 echo "Delete files..." rm -rf $DIR/$tdir echo "Wait for unlink objects finished..." @@ -412,13 +438,23 @@ quota_show_check() { project_quota_enabled () { local rc=0 - for num in $(seq $MDSCOUNT); do - do_facet mds$num $DEBUGFS -R features $(mdsdevname $num) | - grep -q project || rc=1 - done - for num in $(seq $OSTCOUNT); do - do_facet ost$num $DEBUGFS -R features $(ostdevname $num) | - grep -q project || rc=1 + local zfeat="feature@project_quota" + + for facet in $(seq -f mds%g $MDSCOUNT) $(seq -f ost%g $OSTCOUNT); do + local facet_fstype=${facet:0:3}1_FSTYPE + local devname + + if [ "${!facet_fstype}" = "zfs" ]; then + devname=$(zpool_name ${facet}) + do_facet ${facet} $ZPOOL get -H "$zfeat" $devname | + grep -wq active || rc=1 + else + [ ${facet:0:3} == "mds" ] && + devname=$(mdsdevname ${facet:3}) || + devname=$(ostdevname ${facet:3}) + do_facet ${facet} $DEBUGFS -R features $devname | + grep -q project || rc=1 + fi done [ $rc -eq 0 ] && PQ_CLEANUP=false || PQ_CLEANUP=true return $rc @@ -428,15 +464,19 @@ project_quota_enabled || enable_project_quota reset_quota_settings() { resetquota -u $TSTUSR + resetquota -u $TSTID resetquota -g $TSTUSR + resetquota -g $TSTID resetquota -u $TSTUSR2 + resetquota -u $TSTID2 resetquota -g $TSTUSR2 + resetquota -g $TSTID2 resetquota -p $TSTPRJID } # enable quota debug quota_init() { - do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota" + do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota+trace" } quota_init reset_quota_settings @@ -455,15 +495,15 @@ test_quota_performance() { local etime=$(date +%s) delta=$((etime - stime)) if [ $delta -gt 0 ]; then - rate=$((size * 1024 / delta)) - if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then - # LU-2872 - see LU-2887 for fix - [ $rate -gt 64 ] || - error "SLOW IO for $TSTUSR (user): $rate KB/sec" - else - [ $rate -gt 1024 ] || - error "SLOW IO for $TSTUSR (user): $rate KB/sec" - fi + rate=$((size * 1024 / delta)) + if [ "$mds1_FSTYPE" = zfs ]; then + # LU-2872 - see LU-2887 for fix + [ $rate -gt 64 ] || + error "SLOW IO for $TSTUSR (user): $rate KB/sec" + else + [ $rate -gt 1024 ] || + error "SLOW IO for $TSTUSR (user): $rate KB/sec" + fi fi rm -f $TESTFILE } @@ -492,10 +532,58 @@ test_0() { } run_test 0 "Test basic quota performance" +# usage: test_1_check_write tfile user|group|project +test_1_check_write() { + local testfile="$1" + local qtype="$2" + local limit=$3 + local short_qtype=${qtype:0:1} + + log "Write..." + $RUNAS $DD of=$testfile count=$((limit/2)) || + quota_error $short_qtype $TSTUSR \ + "$qtype write failure, but expect success" + log "Write out of block quota ..." + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((limit/2)) seek=$((limit/2)) || true + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + # sync means client wrote all it's cache, but id doesn't + # garantee that slave got new edquot trough glimpse. + # so wait a little to be sure slave got it. + sleep 5 + $RUNAS $DD of=$testfile count=1 seek=$limit && + quota_error $short_qtype $TSTUSR \ + "user write success, but expect EDQUOT" +} + +check_write_fallocate() { + local testfile="$1" + local qtype="$2" + local limit=$3 + local short_qtype=${qtype:0:1} + + count=$((limit/2)) + log "Write ${count}MiB Using Fallocate" + $RUNAS fallocate -l${count}MiB $testfile || + quota_error $short_qtype $TSTUSR "Write ${count}MiB fail" + + cancel_lru_locks osc + sync; sync_all_data || true + sleep 2 + + count=$((limit + 1)) + log "Write ${count}MiB Using Fallocate" + $RUNAS fallocate -l${count}MiB $testfile && + quota_error $short_qtype $TSTUSR \ + "Write success, expect EDQUOT" || true +} + # test block hardlimit -test_1() { - local LIMIT=10 # 10M - local TESTFILE="$DIR/$tdir/$tfile-0" +test_1a() { + local limit=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" setup_quota_test || error "setup quota failed with $?" trap cleanup_quota_test EXIT @@ -504,66 +592,47 @@ test_1() { set_ost_qtype $QTYPE || error "enable ost quota failed" # test for user - log "User quota (block hardlimit:$LIMIT MB)" - $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set user 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 isn't 0." + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" - log "Write..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || - quota_error u $TSTUSR "user write failure, but expect success" - log "Write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - # flush cache, ensure noquota flag is set on client - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=1 seek=$LIMIT && - quota_error u $TSTUSR "user write success, but expect EDQUOT" + test_1_check_write $testfile "user" $limit - rm -f $TESTFILE + rm -f $testfile wait_delete_completed || error "wait_delete_completed failed" sync_all_data || true - USED=$(getquota -u $TSTUSR global curspace) - [ $USED -ne 0 ] && quota_error u $TSTUSR \ + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ "user quota isn't released after deletion" resetquota -u $TSTUSR # test for group log "--------------------------------------" - log "Group quota (block hardlimit:$LIMIT MB)" - $LFS setquota -g $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "Group quota (block hardlimit:$limit MB)" + $LFS setquota -g $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set group quota failed" - TESTFILE="$DIR/$tdir/$tfile-1" + testfile="$DIR/$tdir/$tfile-1" # make sure the system is clean - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTUSR isn't 0" + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0" - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" - log "Write ..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || - quota_error g $TSTUSR "Group write failure, but expect success" - log "Write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT && - quota_error g $TSTUSR "Group write success, but expect EDQUOT" - rm -f $TESTFILE + test_1_check_write $testfile "group" $limit + rm -f $testfile wait_delete_completed || error "wait_delete_completed failed" sync_all_data || true - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && quota_error g $TSTUSR \ + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error g $TSTUSR \ "Group quota isn't released after deletion" resetquota -g $TSTUSR @@ -573,48 +642,498 @@ test_1() { return 0 fi - TESTFILE="$DIR/$tdir/$tfile-2" + testfile="$DIR/$tdir/$tfile-2" # make sure the system is clean - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -ne 0 ] && - error "used space($USED) for project $TSTPRJID isn't 0" + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && + error "used space($used) for project $TSTPRJID isn't 0" # test for Project log "--------------------------------------" - log "Project quota (block hardlimit:$LIMIT mb)" - $LFS setquota -p $TSTPRJID -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "Project quota (block hardlimit:$limit mb)" + $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set project quota failed" - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR:$TSTUSR $TESTFILE || error "chown $TESTFILE failed" - change_project -p $TSTPRJID $TESTFILE - - log "write ..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || quota_error p $TSTPRJID \ - "project write failure, but expect success" - log "write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT && quota_error p \ - $TSTPRJID "project write success, but expect EDQUOT" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed" + change_project -p $TSTPRJID $testfile + + test_1_check_write $testfile "project" $limit # cleanup cleanup_quota_test - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -eq 0 ] || quota_error p $TSTPRJID \ + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && quota_error p $TSTPRJID \ + "project quota isn't released after deletion" + + resetquota -p $TSTPRJID +} +run_test 1a "Block hard limit (normal use and out of quota)" + +test_1b() { + local limit=10 # 10M + 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 $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "user" $limit + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # test for group + log "--------------------------------------" + log "Group quota (block hardlimit:$global_limit MB)" + $LFS setquota -g $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set group quota failed" + + $LFS setquota -g $TSTUSR -b 0 -B ${limit}M --pool $qpool $DIR || + error "set group quota failed" + + testfile="$DIR/$tdir/$tfile-1" + # make sure the system is clean + used=$(getquota -g $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0" + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "group" $limit + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -g $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && quota_error g $TSTUSR \ + "Group quota isn't released after deletion" + resetquota -g $TSTUSR + + if ! is_project_quota_supported; then + echo "Project quota is not supported" + cleanup_quota_test + return 0 + fi + + testfile="$DIR/$tdir/$tfile-2" + # make sure the system is clean + used=$(getquota -p $TSTPRJID global curspace $qpool) + [ $used -ne 0 ] && + error "used space($used) for project $TSTPRJID isn't 0" + + # test for Project + log "--------------------------------------" + log "Project quota (block hardlimit:$global_limit mb)" + $LFS setquota -p $TSTPRJID -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set project quota failed" + + $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M --pool $qpool $DIR || + error "set project quota failed" + + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed" + change_project -p $TSTPRJID $testfile + + test_1_check_write $testfile "project" $limit + + # cleanup + cleanup_quota_test + + used=$(getquota -p $TSTPRJID global curspace) + [ $used -eq 0 ] || quota_error p $TSTPRJID \ "project quota isn't released after deletion" } -run_test 1 "Block hard limit (normal use and out of quota)" +run_test 1b "Quota pools: Block hard limit (normal use and out of quota)" + +test_1c() { + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool1="qpool1" + local qpool2="qpool2" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + # create pools without hard limit + # initially such case raised several bugs + $LFS setquota -u $TSTUSR -B 0M --pool $qpool1 $DIR || + error "set user quota failed" + + $LFS setquota -u $TSTUSR -B 0M --pool $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + test_1_check_write $testfile "user" $global_limit + + used=$(getquota -u $TSTUSR global curspace $qpool1) + echo "qpool1 used $used" + used=$(getquota -u $TSTUSR global curspace $qpool2) + echo "qpool2 used $used" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1c "Quota pools: check 3 pools with hardlimit only for global" + +test_1d() { + local limit1=10 # 10M + local limit2=12 # 12M + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool1="qpool1" + local qpool2="qpool2" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || + error "set user quota failed" + + $LFS setquota -u $TSTUSR -B ${limit2}M --pool $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + test_1_check_write $testfile "user" $limit1 + + used=$(getquota -u $TSTUSR global curspace $qpool1) + echo "qpool1 used $used" + used=$(getquota -u $TSTUSR global curspace $qpool2) + echo "qpool2 used $used" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1d "Quota pools: check block hardlimit on different pools" + +test_1e() { + local limit1=10 # 10M + local global_limit=200 # 200M + local testfile="$DIR/$tdir/$tfile-0" + local testfile2="$DIR/$tdir/$tfile-1" + local qpool1="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # global_limit is much greater than limit1 to get + # different qunit's on osts. Since 1st qunit shrinking + # on OST1(that belongs to qpool1), this qunit should + # be sent to OST1. + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 1 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || + error "set user 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 isn't 0." + + $LFS setstripe $testfile -c 1 -i 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "user" $limit1 + + $LFS setstripe $testfile2 -c 1 -i 0 || + error "setstripe $testfile2 failed" + chown $TSTUSR.$TSTUSR $testfile2 || error "chown $testfile2 failed" + # Now write to file with a stripe on OST0, that doesn't belong to qpool1 + log "Write..." + $RUNAS $DD of=$testfile2 count=20 || + quota_error u $TSTUSR \ + "$qtype write failure, but expect success" + + rm -f $testfile + rm -f $testfile2 + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1e "Quota pools: global pool high block limit vs quota pool with small" + +test_1f() { + local global_limit=200 # 200M + local limit1=10 # 10M + local TESTDIR="$DIR/$tdir/" + local testfile="$TESTDIR/$tfile-0" + local qpool1="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 0 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || + error "set user 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 isn't 0." + + $LFS setstripe $TESTDIR -c 1 -i 0 || error "setstripe $TESTDIR failed" + + test_1_check_write $testfile "user" $limit1 + + pool_remove_target $qpool1 0 + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + pool_add_targets $qpool1 0 0 || error "pool_add_targets failed" + # qunit for appropriate element in lgd array should be set + # correctly(4096). Earlier it was not changed continuing to be 1024. + # This caused write to hung when it hit limit1 - qunit shrinking to 1024 + # for qpool1 lqe didn't cause changing qunit for OST0 in gld array + # as it already was 1024. As flag "need_update" for this qunit was + # not set, new qunit wasn't sent to OST0. Thus revoke was not set + # for "qpool1" lqe and it couldn't set EDQUOT despite granted + # became > 10M. QMT returned EINPROGRESS in a loop. + # Check that it doesn't hung anymore. + test_1_check_write $testfile "user" $limit1 + + # cleanup + cleanup_quota_test +} +run_test 1f "Quota pools: correct qunit after removing/adding OST" + +test_1g() { + local limit=20 # 20M + local global_limit=40 # 40M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + local mdmb_param="osc.*.max_dirty_mb" + local max_dirty_mb=$($LCTL get_param -n $mdmb_param | head -1) + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + $LCTL set_param $mdmb_param=1 + stack_trap "$LCTL set_param $mdmb_param=$max_dirty_mb" EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + $LFS setstripe $testfile -C 200 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + log "Write..." + $RUNAS $DD of=$testfile count=$((limit/2)) || + quota_error u $TSTUSR \ + "$qtype write failure, but expect success" + log "Write out of block quota ..." + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((limit/2)) seek=$((limit/2)) || true + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + sleep 5 + $RUNAS $DD of=$testfile count=$OSTCOUNT seek=$limit && + quota_error u $TSTUSR \ + "user write success, but expect EDQUOT" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + return 0 +} +run_test 1g "Quota pools: Block hard limit with wide striping" + +test_1h() { + local limit=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" + + [ "$ost1_FSTYPE" != ldiskfs ] && skip "non-ldiskfs backend" + [ $OST1_VERSION -lt $(version_code 2.13.50) ] && + skip "Need OST version at least 2.13.53" + + setup_quota_test || error "setup quota failed with $?" + trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || + error "set user 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 isn't 0." + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + check_write_fallocate $testfile "user" $limit + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR +} +run_test 1h "Block hard limit test using fallocate" # test inode hardlimit test_2() { - local LIMIT=$((1024 * 1024)) # 1M inodes local TESTFILE="$DIR/$tdir/$tfile-0" + local LIMIT=$(do_facet mds1 $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.md-0x0.info | + awk '/least qunit/{ print $3 }') + local L2=$(do_facet mds1 $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.md-0x0.soft_least_qunit) + + [ $L2 -le $LIMIT ] || LIMIT=$L2 - [ "$SLOW" = "no" ] && LIMIT=1024 # 1k inodes + [ "$SLOW" = "no" ] || LIMIT=$((LIMIT * 1024)) local FREE_INODES=$(mdt_free_inodes 0) echo "$FREE_INODES free inodes on master MDT" @@ -714,32 +1233,38 @@ test_2() { run_test 2 "File hard limit (normal use and out of quota)" test_block_soft() { - local TESTFILE=$1 - local GRACE=$2 - local LIMIT=$3 + local testfile=$1 + local grace=$2 + local limit=$3 local OFFSET=0 local qtype=$4 + local pool=$5 setup_quota_test - trap cleanup_quota_test EXIT + stack_trap cleanup_quota_test EXIT - $LFS setstripe $TESTFILE -c 1 -i 0 - chown $TSTUSR.$TSTUSR $TESTFILE + $LFS setstripe $testfile -c 1 -i 0 + chown $TSTUSR.$TSTUSR $testfile [ "$qtype" == "p" ] && is_project_quota_supported && - change_project -p $TSTPRJID $TESTFILE + change_project -p $TSTPRJID $testfile echo "Write up to soft limit" - $RUNAS $DD of=$TESTFILE count=$LIMIT || + $RUNAS $DD of=$testfile count=$limit || quota_error a $TSTUSR "write failure, but expect success" - OFFSET=$((LIMIT * 1024)) + OFFSET=$((limit * 1024)) cancel_lru_locks osc echo "Write to exceed soft limit" - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || quota_error a $TSTUSR "write failure, but expect success" OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block cancel_lru_locks osc + echo "mmap write when over soft limit" + $RUNAS $MULTIOP $testfile.mmap OT40960SMW || + quota_error a $TSTUSR "mmap write failure, but expect success" + cancel_lru_locks osc + $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP $SHOW_QUOTA_PROJID @@ -748,12 +1273,12 @@ test_block_soft() { $SHOW_QUOTA_INFO_PROJID echo "Write before timer goes off" - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || quota_error a $TSTUSR "write failure, but expect success" OFFSET=$((OFFSET + 1024)) cancel_lru_locks osc - wait_grace_time $qtype "block" + wait_grace_time $qtype "block" $pool $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP @@ -762,12 +1287,13 @@ test_block_soft() { $SHOW_QUOTA_INFO_GROUP $SHOW_QUOTA_INFO_PROJID - echo "Write after timer goes off" + log "Write after timer goes off" # maybe cache write, ignore. - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || true + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || true OFFSET=$((OFFSET + 1024)) cancel_lru_locks osc - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET && + log "Write after cancel lru locks" + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET && quota_error a $TSTUSR "write success, but expect EDQUOT" $SHOW_QUOTA_USER @@ -778,7 +1304,7 @@ test_block_soft() { $SHOW_QUOTA_INFO_PROJID echo "Unlink file to stop timer" - rm -f $TESTFILE + rm -f $testfile wait_delete_completed sync_all_data || true @@ -789,71 +1315,71 @@ test_block_soft() { $SHOW_QUOTA_INFO_GROUP $SHOW_QUOTA_INFO_PROJID - $LFS setstripe $TESTFILE -c 1 -i 0 - chown $TSTUSR.$TSTUSR $TESTFILE - [ "$qtype" == "p" ] && change_project -p $TSTPRJID $TESTFILE + $LFS setstripe $testfile -c 1 -i 0 + chown $TSTUSR.$TSTUSR $testfile + [ "$qtype" == "p" ] && change_project -p $TSTPRJID $testfile echo "Write ..." - $RUNAS $DD of=$TESTFILE count=$LIMIT || + $RUNAS $DD of=$testfile count=$limit || quota_error a $TSTUSR "write failure, but expect success" # cleanup cleanup_quota_test } # block soft limit -test_3() { - local GRACE=20 # 20s +test_3a() { + local grace=20 # 20s if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then - GRACE=60 + grace=60 fi - local TESTFILE=$DIR/$tdir/$tfile-0 + local testfile=$DIR/$tdir/$tfile-0 # get minimum soft qunit size - local LIMIT=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) set_ost_qtype $QTYPE || error "enable ost quota failed" - echo "User quota (soft limit:$LIMIT MB grace:$GRACE seconds)" + echo "User quota (soft limit:$limit MB grace:$grace seconds)" # make sure the system is clean - local USED=$(getquota -u $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0." + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." - $LFS setquota -t -u --block-grace $GRACE --inode-grace \ + $LFS setquota -t -u --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set user grace time failed" - $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR || + $LFS setquota -u $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR || error "set user quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "u" + test_block_soft $testfile $grace $limit "u" - echo "Group quota (soft limit:$LIMIT MB grace:$GRACE seconds)" - TESTFILE=$DIR/$tdir/$tfile-1 + echo "Group quota (soft limit:$limit MB grace:$grace seconds)" + testfile=$DIR/$tdir/$tfile-1 # make sure the system is clean - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0." + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0." - $LFS setquota -t -g --block-grace $GRACE --inode-grace \ + $LFS setquota -t -g --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set group grace time failed" - $LFS setquota -g $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR || + $LFS setquota -g $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR || error "set group quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "g" + test_block_soft $testfile $grace $limit "g" if is_project_quota_supported; then - echo "Project quota (soft limit:$LIMIT MB grace:$GRACE sec)" - TESTFILE=$DIR/$tdir/$tfile-2 + echo "Project quota (soft limit:$limit MB grace:$grace sec)" + testfile=$DIR/$tdir/$tfile-2 # make sure the system is clean - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -ne 0 ] && error \ - "Used space($USED) for project $TSTPRJID isn't 0." + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && error \ + "Used space($used) for project $TSTPRJID isn't 0." - $LFS setquota -t -p --block-grace $GRACE --inode-grace \ + $LFS setquota -t -p --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set project grace time failed" - $LFS setquota -p $TSTPRJID -b ${LIMIT}M -B 0 -i 0 -I 0 \ + $LFS setquota -p $TSTPRJID -b ${limit}M -B 0 -i 0 -I 0 \ $DIR || error "set project quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "p" + test_block_soft $testfile $grace $limit "p" resetquota -p $TSTPRJID $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \ $MAX_IQ_TIME $DIR || @@ -866,7 +1392,173 @@ test_3() { $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \ $MAX_IQ_TIME $DIR || error "restore group grace time failed" } -run_test 3 "Block soft limit (start timer, timer goes off, stop timer)" +run_test 3a "Block soft limit (start timer, timer goes off, stop timer)" + +test_3b() { + local grace=20 # 20s + local qpool="qpool1" + if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then + grace=60 + fi + local testfile=$DIR/$tdir/$tfile-0 + + mds_supports_qp + # get minimum soft qunit size + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) + local glbl_limit=$((2*limit)) + local glbl_grace=$((2*grace)) + echo "limit $limit glbl_limit $glbl_limit" + echo "grace $grace glbl_grace $glbl_grace" + + set_ost_qtype $QTYPE || error "enable ost quota failed" + + echo "User quota in $qpool(soft limit:$limit MB grace:$grace seconds)" + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace \ + --pool $qpool $DIR || error "set user grace time failed" + + $LFS setquota -u $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR || + error "set user quota failed" + $LFS setquota -u $TSTUSR -b ${limit}M -B 0 --pool $qpool $DIR || + error "set user quota failed" + + test_block_soft $testfile $grace $limit "u" $qpool + + echo "Group quota in $qpool(soft limit:$limit MB grace:$grace seconds)" + testfile=$DIR/$tdir/$tfile-1 + # make sure the system is clean + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0." + + $LFS setquota -t -g --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set group grace time failed" + $LFS setquota -t -g --block-grace $grace \ + --pool $qpool $DIR || error "set group grace time failed" + + $LFS setquota -g $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR || + error "set group quota failed" + $LFS setquota -g $TSTUSR -b ${limit}M -B 0 --pool $qpool $DIR || + error "set group quota failed" + + test_block_soft $testfile $grace $limit "g" $qpool + + if is_project_quota_supported; then + echo "Project quota in $qpool(soft:$limit MB grace:$grace sec)" + testfile=$DIR/$tdir/$tfile-2 + # make sure the system is clean + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && error \ + "Used space($used) for project $TSTPRJID isn't 0." + + $LFS setquota -t -p --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || + error "set project grace time failed" + $LFS setquota -t -p --block-grace $grace \ + --pool $qpool $DIR || + error "set project grace time failed" + + $LFS setquota -p $TSTPRJID -b ${glbl_limit}M -B 0 -i 0 -I 0 \ + $DIR || error "set project quota failed" + $LFS setquota -p $TSTPRJID -b ${limit}M -B 0 \ + --pool $qpool $DIR || error "set project quota failed" + + test_block_soft $testfile $grace $limit "p" $qpool + resetquota -p $TSTPRJID + $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \ + $MAX_IQ_TIME $DIR || + error "restore project grace time failed" + $LFS setquota -t -p --block-grace $MAX_DQ_TIME --pool $qpool \ + $DIR || error "set project grace time failed" + fi + + # cleanup + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \ + $MAX_IQ_TIME $DIR || error "restore user grace time failed" + $LFS setquota -t -u --block-grace $MAX_DQ_TIME \ + --pool $qpool $DIR || error "restore user grace time failed" + $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \ + $MAX_IQ_TIME $DIR || error "restore group grace time failed" + $LFS setquota -t -g --block-grace $MAX_DQ_TIME \ + --pool $qpool $DIR || error "restore group grace time failed" +} +run_test 3b "Quota pools: Block soft limit (start timer, expires, stop timer)" + +test_3c() { + local grace=20 # 20s + local qpool="qpool1" + local qpool2="qpool2" + if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then + grace=60 + fi + local testfile=$DIR/$tdir/$tfile-0 + + mds_supports_qp + # get minimum soft qunit size + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) + local limit2=$((limit+4)) + local glbl_limit=$((limit+8)) + local grace1=$((grace+10)) + local grace2=$grace + local glbl_grace=$((grace+20)) + echo "limit $limit limit2 $limit2 glbl_limit $glbl_limit" + echo "grace1 $grace1 grace2 $grace2 glbl_grace $glbl_grace" + + set_ost_qtype $QTYPE || error "enable ost quota failed" + + echo "User quota in qpool2(soft:$limit2 MB grace:$grace2 seconds)" + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 1 || + error "pool_add_targets failed" + + + $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace1 \ + --pool $qpool $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace2 \ + --pool $qpool2 $DIR || error "set user grace time failed" + + $LFS setquota -u $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR || + error "set user quota failed" + $LFS setquota -u $TSTUSR -b ${limit}M -B 0 --pool $qpool $DIR || + error "set user quota failed" + # qpool has minimum soft limit, but it's grace is grater than + # grace period of qpool2. Thus write shouldn't fail when + # hit qpool soft limit - only when reaches up qpool2 limit + # after grace2 seconds. + $LFS setquota -u $TSTUSR -b ${limit2}M -B 0 --pool $qpool2 $DIR || + error "set user quota failed" + + test_block_soft $testfile $grace2 $limit2 "u" $qpool2 + + # cleanup + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \ + $MAX_IQ_TIME $DIR || error "restore user grace time failed" + $LFS setquota -t -u --block-grace $MAX_DQ_TIME \ + --pool $qpool $DIR || error "restore user grace time failed" + $LFS setquota -t -u --block-grace $MAX_DQ_TIME \ + --pool $qpool2 $DIR || error "restore user grace time failed" +} +run_test 3c "Quota pools: check block soft limit on different pools" test_file_soft() { local TESTFILE=$1 @@ -955,7 +1647,7 @@ test_4a() { $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR || error "set user quota failed" - [ $(facet_fstype $SINGLEMDS) = "zfs" ] && GRACE=20 + [ "$mds1_FSTYPE" = zfs ] && GRACE=20 test_file_soft $TESTFILE $LIMIT $GRACE "u" @@ -1134,6 +1826,19 @@ test_6() { error "write $TESTFILE failure, expect success" $RUNAS2 $DD of=$TESTFILE2 count=1 || error "write $TESTFILE2 failure, expect success" + + if at_is_enabled; then + at_max_saved=$(at_max_get ost1) + at_max_set $TIMEOUT ost1 + + # write to enforced ID ($TSTUSR) to exceed limit to make sure + # DQACQ is sent, which makes at_max to take effect + $RUNAS $DD of=$TESTFILE count=$LIMIT seek=1 oflag=sync \ + conv=notrunc + rm -f $TESTFILE + wait_delete_completed + fi + sync; sync sync_all_data || true @@ -1141,11 +1846,6 @@ test_6() { #define OBD_FAIL_PTLRPC_DROP_REQ_OPC 0x513 lustre_fail mds 0x513 601 - if at_is_enabled; then - at_max_saved=$(at_max_get ost1) - at_max_set $TIMEOUT ost1 - fi - do_facet ost1 $LCTL set_param \ osd-*.$FSNAME-OST*.quota_slave.timeout=$((TIMEOUT / 2)) @@ -1174,7 +1874,7 @@ test_6() { # no watchdog is triggered do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log - watchdog=$(awk '/Service thread pid/ && /was inactive/ \ + watchdog=$(awk '/[Ss]ervice thread pid/ && /was inactive/ \ { print; }' $TMP/lustre-log-${TESTNAME}.log) [ -z "$watchdog" ] || error "$watchdog" @@ -1357,7 +2057,7 @@ test_7c() { # enable ost quota set_ost_qtype $QTYPE || error "enable ost quota failed" # trigger reintegration - local procf="osd-$(facet_fstype ost1).$FSNAME-OST*." + local procf="osd-$ost1_FSTYPE.$FSNAME-OST*." procf=${procf}quota_slave.force_reint do_facet ost1 $LCTL set_param $procf=1 || error "force reintegration failed" @@ -1426,7 +2126,7 @@ test_7e() { # LU-2435: skip this quota test if underlying zfs version has not # supported native dnode accounting - [ "$(facet_fstype mds1)" == "zfs" ] && { + [ "$mds1_FSTYPE" == zfs ] && { local F="feature@userobj_accounting" local pool=$(zpool_name mds1) local feature=$(do_facet mds1 $ZPOOL get -H $F $pool) @@ -1967,7 +2667,7 @@ test_18() { # check if watchdog is triggered do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log - local watchdog=$(awk '/Service thread pid/ && /was inactive/ \ + local watchdog=$(awk '/[Ss]ervice thread pid/ && /was inactive/ \ { print; }' $TMP/lustre-log-${TESTNAME}.log) [ -z "$watchdog" ] || error "$watchdog" rm -f $TMP/lustre-log-${TESTNAME}.log @@ -2210,7 +2910,7 @@ test_23_sub() { } test_23() { - [ $(facet_fstype ost1) == "zfs" ] && + [ "$ost1_FSTYPE" == zfs ] && skip "Overwrite in place is not guaranteed to be " \ "space neutral on ZFS" @@ -2280,8 +2980,8 @@ test_27b() { # b20200 $SHOW_QUOTA_PROJID || error "lfs quota failed with projid argument" fi - resetquota -u $TSTUSR - resetquota -g $TSTUSR + resetquota -u $TSTID + resetquota -g $TSTID resetquota -p $TSTPRJID return 0 } @@ -2651,7 +3351,7 @@ run_test 35 "Usage is still accessible across reboot" # chown/chgrp to the file created with MDS_OPEN_DELAY_CREATE # LU-5006 test_37() { - [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.93) ] && + [ "$MDS1_VERSION" -lt $(version_code 2.6.93) ] && skip "Old server doesn't have LU-5006 fix." setup_quota_test || error "setup quota failed with $?" @@ -2683,7 +3383,7 @@ run_test 37 "Quota accounted properly for file created by 'lfs setstripe'" # LU-8801 test_38() { - [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.8.60) ] && + [ "$MDS1_VERSION" -lt $(version_code 2.8.60) ] && skip "Old server doesn't have LU-8801 fix." [ "$UID" != 0 ] && skip_env "must run as root" && return @@ -2712,7 +3412,7 @@ test_38() { cancel_lru_locks osc sync; sync_all_data || true - local procf="osd-$(facet_fstype $SINGLEMDS).$FSNAME-MDT0000" + local procf="osd-$mds1_FSTYPE.$FSNAME-MDT0000" procf=${procf}.quota_slave.acct_user local accnt_cnt @@ -2826,6 +3526,85 @@ test_40c() { } run_test 40c "Remote child Dir inherit project quota properly" +test_40d() { + [ "$MDSCOUNT" -lt "2" ] && skip_env "needs >= 2 MDTs" + is_project_quota_supported || skip "Project quota is not supported" + + setup_quota_test || error "setup quota failed with $?" + local dir="$DIR/$tdir/dir" + + mkdir -p $dir + $LFS setdirstripe -D -c 2 -i -1 $dir || error "setdirstripe failed" + change_project -sp $TSTPRJID $dir || + error "change project on $dir failed" + for i in $(seq 5); do + mkdir -p $dir/d$i/d$i || + error "mkdir $dir/d$i/d$i failed" + local projid=$($LFS project -d $dir/d$i/d$i | + awk '{print $1}') + [ "$projid" == "$TSTPRJID" ] || + error "projid id expected $TSTPRJID not $projid" + touch $dir/d$i/d$i/file + #verify inherit works file for stripe dir. + local projid=$($LFS project -d $dir/d$i/d$i/file | awk '{print $1}') + [ "$projid" == "$TSTPRJID" ] || + error "file under remote dir expected 1 not $projid" + done + + # account should be 1 + (2 + 1) *10 + 1 * 5 + USED=$(getquota -p $TSTPRJID global curinodes) + [ "$USED" == "36" ] || + error "file count expected 36 got $USED" + + rm -rf $dir + cleanup_quota_test +} +run_test 40d "Stripe Directory inherit project quota properly" + +test_41() { + is_project_quota_supported || + skip "Project quota is not supported" + setup_quota_test || error "setup quota failed with $?" + trap cleanup_quota_test EXIT + local dir="$DIR/$tdir/dir" + local blimit=102400 + local ilimit=4096 + local projid=$((testnum * 1000)) + + quota_init + + # enable mdt/ost quota + set_mdt_qtype ugp || error "enable mdt quota failed" + set_ost_qtype ugp || error "enable ost quota failed" + + test_mkdir -p $dir && change_project -sp $projid $dir + $LFS setquota -p $projid -b 0 -B ${blimit}K -i 0 -I $ilimit $dir || + error "set project quota failed" + + sync; sync_all_data + sleep_maxage + + # check if df output works as expected + echo "== global statfs: $MOUNT ==" + df -kP $MOUNT; df -iP $MOUNT; $LFS quota -p $projid $dir + echo + echo "== project statfs (prjid=$projid): $dir ==" + df -kP $dir; df -iP $dir + local bused=$(getquota -p $projid global curspace) + local iused=$(getquota -p $projid global curinodes) + # note trailing space to match double printf from awk + local expected="$blimit $bused $ilimit $iused " + + wait_update $HOSTNAME \ + "{ df -kP $dir; df -iP $dir; } | + awk '/$FSNAME/ { printf \\\"%d %d \\\", \\\$2,\\\$3 }'" \ + "$expected" || + error "failed to get correct statfs for project quota" + + cleanup_quota_test +} +run_test 41 "df should return projid-specific values" + test_50() { ! is_project_quota_supported && skip "Project quota is not supported" @@ -2976,7 +3755,7 @@ test_54() { run_test 54 "basic lfs project interface test" test_55() { - [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.10.58) ] && + [ "$MDS1_VERSION" -lt $(version_code 2.10.58) ] && skip "Not supported before 2.10.58." setup_quota_test || error "setup quota failed with $?" @@ -3061,7 +3840,7 @@ test_57() { run_test 57 "lfs project could tolerate errors" test_59() { - [ "$(facet_fstype $SINGLEMDS)" != "ldiskfs" ] && + [ "$mds1_FSTYPE" != ldiskfs ] && skip "ldiskfs only test" disable_project_quota setup_quota_test || error "setup quota failed with $?" @@ -3108,7 +3887,7 @@ run_test 60 "Test quota for root with setgid" # test default quota test_default_quota() { - [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.51) ] && + [ "$MDS1_VERSION" -lt $(version_code 2.11.51) ] && skip "Not supported before 2.11.51." local qtype=$1 @@ -3303,8 +4082,8 @@ test_62() { run_test 62 "Project inherit should be only changed by root" test_dom() { - [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.55) ] && - skip "Not supported before 2.11.55" && return + [ "$MDS1_VERSION" -lt $(version_code 2.11.55) ] && + skip "Not supported before 2.11.55" local qtype=$1 local qid=$TSTUSR @@ -3433,6 +4212,604 @@ test_64() { } run_test 64 "lfs project on symlink files should fail" +test_65() { + local SIZE=10 #10M + local TESTFILE="$DIR/$tdir/$tfile-0" + + setup_quota_test || error "setup quota failed with $?" + set_ost_qtype $QTYPE || error "enable ost quota failed" + quota_init + + echo "Write..." + $RUNAS $DD of=$TESTFILE count=$SIZE || + error "failed to write" + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + + local quota_u=$($LFS quota -u $TSTUSR $DIR) + local quota_g=$($LFS quota -g $TSTUSR $DIR) + local quota_all=$($RUNAS $LFS quota $DIR) + + [ "$(echo "$quota_all" | head -n3)" != "$quota_u" ] && + error "usr quota not match" + [ "$(echo "$quota_all" | tail -n3)" != "$quota_g" ] && + error "grp quota not match" + + rm -f $TESTFILE + # cleanup + cleanup_quota_test +} +run_test 65 "Check lfs quota result" + +test_66() { + ! is_project_quota_supported && + skip "Project quota is not supported" + [ "$MDS1_VERSION" -lt $(version_code 2.12.4) ] && + skip "Not supported before 2.12.4" + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + local old=$(do_facet mds1 $LCTL get_param -n \ + mdt.*.enable_chprojid_gid | head -1) + local testdir=$DIR/$tdir/foo + + do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=0 + stack_trap "do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=0" \ + EXIT + + test_mkdir -i 0 -c 1 $testdir || error "failed to mkdir" + chown -R $TSTID:$TSTID $testdir + change_project -sp $TSTPRJID $testdir + $RUNAS mkdir $testdir/foo || error "failed to mkdir foo" + + $RUNAS lfs project -p 0 $testdir/foo && + error "nonroot user should fail to set projid" + + $RUNAS lfs project -C $testdir/foo && + error "nonroot user should fail to clear projid" + + change_project -C $testdir/foo || error "failed to clear project" + + do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=-1 + $RUNAS lfs project -p $TSTPRJID $testdir/foo || error \ + "failed to set projid with normal user when enable_chprojid_gid=-1" + + $RUNAS lfs project -rC $testdir/ || error \ +"failed to clear project state with normal user when enable_chprojid_gid=-1" + + touch $testdir/bar || error "failed touch $testdir/bar" + $RUNAS lfs project -p $TSTPRJID $testdir/bar && error \ + "normal user should not be able to set projid on root owned file" + + change_project -p $TSTPRJID $testdir/bar || error \ + "root should be able to change its own file's projid" + + cleanup_quota_test +} +run_test 66 "nonroot user can not change project state in default" + +test_67_write() { + local file="$1" + local qtype="$2" + local size=$3 + local _runas="" + local short_qtype=${qtype:0:1} + + echo "file "$file + echo "0 $0 1 $1 2 $2 3 $3 4 $4" + case "$4" in + quota_usr) _runas=$RUNAS;; + quota_2usr) _runas=$RUNAS2;; + *) error "unknown quota parameter $4";; + esac + + log "Write..." + date + $_runas $DD of=$file count=$size || + quota_error $short_qtype $TSTUSR \ + "$qtype write failure, but expect success" + date + cancel_lru_locks osc + date + sync; sync_all_data || true + date +} + +getgranted() { + local pool=$1 + local ptype=$2 + local userid=$3 + local qtype=$4 + local param=qmt.$FSNAME-QMT0000.$ptype-$pool.glb-$qtype + + do_facet mds1 $LCTL get_param $param | + grep -A2 $userid | awk -F'[, ]*' 'NR==2{print $9}' +} + +test_67() { + local limit=20 # 20M + local testfile="$DIR/$tdir/$tfile-0" + local testfile2="$DIR/$tdir/$tfile-1" + local testfile3="$DIR/$tdir/$tfile-2" + local qpool="qpool1" + local used + local granted + local granted_mb + + mds_supports_qp + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + + setup_quota_test || error "setup quota failed with $?" + trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + # make sure the system is clean + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + granted=$(getgranted "0x0" "dt" $TSTID "usr") + echo "granted 0x0 before write $granted" + + # trigger reintegration + local procf="osd-$(facet_fstype ost1).$FSNAME-OST*." + procf=${procf}quota_slave.force_reint + do_facet ost1 $LCTL set_param $procf=1 || + error "force reintegration failed" + wait_ost_reint "u" || error "reintegration failed" + granted=$(getgranted "0x0" "dt" $TSTID "usr") + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR in $qpool isn't 0." + + $LFS setstripe $testfile -c 1 -i 0 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # write 10 MB to testfile + test_67_write "$testfile" "user" 10 "quota_usr" + + # create qpool and add OST1 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 1 1 || error "pool_add_targets failed" + # as quota_usr hasn't limits, lqe may absent. But it should be + # created after the 1st direct qmt_get. + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + # check granted - should be 0, as testfile is located only on OST0 + granted=$(getgranted "0x0" "dt" $TSTID "usr") + echo "global granted $granted" + granted=$(getgranted $qpool "dt" $TSTID "usr") + echo "$qpool granted $granted" + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR in $qpool isn't 0." + + # add OST0 to qpool and check granted space + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024)) + echo "Granted $granted_mb MB" + #should be 10M + qunit for each OST + [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] || + error "Granted($granted_mb) for $TSTUSR in $qpool is wrong." + + $LFS setstripe $testfile2 -c 1 -i 1 || + error "setstripe $testfile2 failed" + chown $TSTUSR2.$TSTUSR2 $testfile2 || error "chown $testfile2 failed" + # Write from another user and check that qpool1 + # shows correct granted, despite quota_2usr hasn't limits in qpool1. + test_67_write "$testfile2" "user" 10 "quota_2usr" + used=$(getquota -u $TSTUSR2 global curspace $qpool) + granted=$(getgranted $qpool "dt" $TSTID2 "usr") + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR2 in $qpool isn't 0." + + # Granted space for quota_2usr in qpool1 should appear only + # when global lqe for this user becomes enforced. + $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR || + error "set user quota failed" + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + echo "granted_mb $granted_mb" + [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] || + error "Granted($granted) for $TSTUSR in $qpool is wrong." + + $LFS setstripe $testfile3 -c 1 -i 0 || + error "setstripe $testfile3 failed" + chown $TSTUSR2.$TSTUSR2 $testfile3 || error "chown $testfile3 failed" + test_67_write "$testfile3" "user" 10 "quota_2usr" + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + echo "$testfile3 granted_mb $granted_mb" + [ $granted_mb -eq $limit ] || + error "Granted($granted_mb) for $TSTUSR2 is not equal to 20M" + + # remove OST1 from the qpool1 and check granted space + # should be 0 for TSTUSR and 10M for TSTUSR2 + pool_remove_target $qpool 0 + granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024)) + [ $granted_mb -eq 0 ] || + error "Granted($granted_mb) for $TSTUSR in $qpool != 0." + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + [ $granted_mb -eq 10 ] || + error "Granted($granted_mb) for $TSTUSR2 is not equal to 10M" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + cleanup_quota_test +} +run_test 67 "quota pools recalculation" + +get_slave_nr() { + local pool=$1 + local qtype=$2 + local nr + + do_facet mds1 $LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$pool.info | + awk '/usr/ {getline; print $2}' +} + +test_68() +{ + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # check slave number for glbal pool + local nr=$(get_slave_nr "0x0" "usr") + echo "nr result $nr" + [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] && + error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)" + + # create qpool and add OST1 + pool_add $qpool || error "pool_add failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0" + + # add OST1 to qpool + pool_add_targets $qpool 1 1 || error "pool_add_targets failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1" + + # add OST0 to qpool + pool_add_targets $qpool 0 1 || error "pool_add_targets failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 2 ]] && error "Slave number $nr for $qpool != 2" + + # remove OST0 + pool_remove_target $qpool 0 + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1" + + # remove OST1 + pool_remove_target $qpool 1 + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0" + + # Check again that all is fine with global pool + nr=$(get_slave_nr "0x0" "usr") + [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] && + error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)" + + cleanup_quota_test +} +run_test 68 "slave number in quota pool changed after each add/remove OST" + +test_69() +{ + local global_limit=200 # 200M + local limit=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" + local dom0="$DIR/$tdir/dom0" + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + set_mdt_qtype $QTYPE || error "enable mdt quota failed" + + # Save DOM only at MDT0 + $LFS setdirstripe -c 1 -i 0 $dom0 || error "cannot create $dom0" + $LFS setstripe -E 1M $dom0 -L mdt || error "setstripe to $dom0 failed" + chmod 0777 $dom0 + $LFS setstripe -c 1 -i 0 "$DIR/$tdir/" + + # create qpool and add OST0 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 0 || error "pool_add_targets failed" + + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || + error "set user quota failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 oflag=sync || + quota_error u $TSTUSR "write failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + $RUNAS $DD of=$testfile count=$limit || true + + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + + # MDT0 shouldn't get EDQUOT with glimpse. + $RUNAS $DD of=$testfile count=$limit seek=$limit && + quota_error u $TSTUSR \ + "user write success, but expect EDQUOT" + + # Now all members of qpool1 should get EDQUOT. Expect success + # when write to DOM on MDT0, as it belongs to global pool. + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + cleanup_quota_test +} +run_test 69 "EDQUOT at one of pools shouldn't affect DOM" + +test_70() +{ + local qpool="qpool1" + local limit=20 + local err=0 + local bhard + + [[ CLIENT_VERSION -lt $(version_code $VERSION_WITH_QP) ]] && + skip "Needs a client >= $VERSION_WITH_QP" + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # MDS returns EFAULT for unsupported quotactl command + [[ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ]] && err=14 + + # create qpool and add OST0 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 0 || error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR + rc=$? + [ $rc -eq $err ] || error "setquota res $rc != $err" + + # If MDS supports QP, check that limit was set properly. + if [[ $MDS1_VERSION -ge $(version_code $VERSION_WITH_QP) ]]; then + bhard=$(getquota -u $TSTUSR global bhardlimit $qpool) + echo "hard limit $bhard limit $limit" + [ $bhard -ne $((limit*1024)) ] && + error "bhard:$bhard for $qpool!=$((limit*1024))" + fi + + $LFS quota -u $TSTUSR --pool $qpool $DIR + rc=$? + [ $rc -eq $err ] || error "quota res $rc != $err" + + cleanup_quota_test +} +run_test 70 "check lfs setquota/quota with a pool option" + +test_71a() +{ + local limit=10 # 10M + local global_limit=100 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + local qpool2="qpool2" + + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || + error "set user quota failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 1 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + # create 1st component 1-10M + $LFS setstripe -E 10M -S 1M -c 1 -i 0 $testfile + #create 2nd component 10-30M + $LFS setstripe --component-add -E 30M -c 1 -i 1 $testfile + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # сheck normal use and out of quota with PFL + # 1st element is in qppol1(OST0), 2nd in qpool2(OST2). + test_1_check_write $testfile "user" $((limit*2)) + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + + # create 1st component 1-10M + $LFS setstripe -E 10M -S 1M -c 1 -i 0 $testfile + # create 2nd component 10-30M + $LFS setstripe --component-add -E 30M -c 1 -i 1 $testfile + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # write to the 2nd component + $RUNAS $DD of=$testfile count=$limit seek=10 || + quota_error u $TSTUSR \ + "write failure, but expect success" + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((2*limit)) seek=10 || true + cancel_lru_locks osc + sync; sync_all_data || true + # write over limit in qpool2(2nd component 10-30M) + $RUNAS $DD of=$testfile count=1 seek=$((10 + 2*limit)) && + quota_error u $TSTUSR "user write success, but expect EDQUOT" + # write to the 1st component - OST0 is empty + $RUNAS $DD of=$testfile count=$limit seek=0 || + quota_error u $TSTUSR "write failed" + + cleanup_quota_test +} +run_test 71a "Check PFL with quota pools" + +test_71b() +{ + local global_limit=1000 # 1G + local limit1=160 # 160M + local limit2=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + local qpool2="qpool2" + + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool $DIR || + error "set user quota failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 1 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit2}M --pool $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + # First component is on OST0, 2nd on OST1 + $LFS setstripe -E 128M -i 0 -z 64M -E -1 -i 1 -z 64M $testfile + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # fill the 1st component on OST0 + $RUNAS $DD of=$testfile count=128 || + quota_error u $TSTUSR "write failed" + # write to the 2nd cmpnt on OST1 + $RUNAS $DD of=$testfile count=$((limit2/2)) seek=128 || + quota_error u $TSTUSR "write failed" + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((limit2/2)) seek=$((128 + limit2/2)) || + true + cancel_lru_locks osc + sync; sync_all_data || true + # write over limit in qpool2 + $RUNAS $DD of=$testfile count=2 seek=$((128 + limit2)) && + quota_error u $TSTUSR "user write success, but expect EDQUOT" + + cleanup_quota_test +} +run_test 71b "Check SEL with quota pools" + +test_72() +{ + local limit=10 # 10M + local global_limit=50 # 50M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # 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 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 1 1 || error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + $LFS setstripe $testfile -c 1 -i 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + test_1_check_write $testfile "user" $limit + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + echo "used $used" + [ $used -ge $limit ] || error "used($used) is less than limit($limit)" + # check that lfs quota -uv --pool prints only OST that + # was added in a pool + lfs quota -v -u quota_usr --pool $qpool $DIR | grep -v "OST0001" | + grep "OST\|MDT" && error "$qpool consists wrong targets" + + cleanup_quota_test +} +run_test 72 "lfs quota --pool prints only pool's OSTs" + quota_fini() { do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"