X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Ftests%2Fsanity-quota.sh;h=0b5e2f34cea356c518a1ef8f96274c62dd3ca3a8;hb=b54b7ce43929ce7ff6e48cd219623c264ca6b6b3;hp=43eafd83199475be631ab631c525d9dbce84b2b5;hpb=33e500cfb33406b8dddac46e1dfb5a3d59ff01c5;p=fs%2Flustre-release.git diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 43eafd8..0b5e2f3 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -13,8 +13,8 @@ init_test_env $@ init_logging ALWAYS_EXCEPT="$SANITY_QUOTA_EXCEPT " -# Bug number for skipped test: LU-5152 -ALWAYS_EXCEPT+=" 55" +# Bug number for skipped test: +ALWAYS_EXCEPT+="" # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT! # Test duration: 30 min @@ -39,7 +39,6 @@ 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) ] && @@ -129,17 +128,20 @@ resetquota() { quota_scan() { local local_ugp=$1 local local_id=$2 + local count if [ "$local_ugp" == "a" -o "$local_ugp" == "u" ]; then $LFS quota -v -u $local_id $DIR - log "Files for user ($local_id):" + count=$($LFS find --user $local_id $DIR | wc -l) + log "Files for user ($local_id), count=$count:" ($LFS find --user $local_id $DIR | head -n 4 | xargs stat 2>/dev/null) fi if [ "$local_ugp" == "a" -o "$local_ugp" == "g" ]; then $LFS quota -v -g $local_id $DIR - log "Files for group ($local_id):" + count=$($LFS find --group $local_id $DIR | wc -l) + log "Files for group ($local_id), count=$count:" ($LFS find --group $local_id $DIR | head -n 4 | xargs stat 2>/dev/null) fi @@ -147,7 +149,8 @@ quota_scan() { 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):" + count=$($LFS find --projid $TSTPRJID $DIR | wc -l) + log "Files for project ($TSTPRJID), count=$count:" ($LFS find --projid $TSTPRJID $DIR | head -n 4 | xargs stat 2>/dev/null) fi @@ -216,7 +219,7 @@ set_mdt_qtype() { if [[ $PERM_CMD == *"set_param -P"* ]]; then do_facet mgs $PERM_CMD \ - osd-*.$FSNAME-MDT*.quota_slave.enable=$qtype + osd-*.$FSNAME-MDT*.quota_slave.enabled=$qtype else do_facet mgs $PERM_CMD $FSNAME.quota.mdt=$qtype fi @@ -246,7 +249,7 @@ set_ost_qtype() { if [[ $PERM_CMD == *"set_param -P"* ]]; then do_facet mgs $PERM_CMD \ - osd-*.$FSNAME-OST*.quota_slave.enable=$qtype + osd-*.$FSNAME-OST*.quota_slave.enabled=$qtype else do_facet mgs $PERM_CMD $FSNAME.quota.ost=$qtype fi @@ -355,50 +358,66 @@ wait_grace_time() { case $flavour in block) time=$(lfs quota -$qtype $qarg $parg $DIR| - awk 'NR == 3{ print $5 }'| sed 's/s$//') + awk 'NR == 3{ print $5 }') ;; file) time=$(lfs quota -$qtype $qarg $DIR| - awk 'NR == 3{ print $9 }'| sed 's/s$//') + awk 'NR == 3{ print $9 }') ;; *) error "Unknown quota type: $flavour" ;; esac + local sleep_seconds=0 + local orig_time=$time + + echo "Grace time is $time" # 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)); + [[ $time == *w* ]] && w_time=${time%w*} && + let sleep_seconds+=$((w_time*7*24*60*60)); + time=${time#*w} + [[ $time == *d* ]] && d_time=${time%d*} && + let sleep_seconds+=$((d_time*24*60*60)); + time=${time#*d} + [[ $time == *h* ]] && h_time=${time%h*} && + let sleep_seconds+=$((h_time*60*60)); + time=${time#*h} + [[ $time == *m* ]] && m_time=${time%m*} && + let sleep_seconds+=$((m_time*60)); + time=${time#*m} + [[ $time == *s* ]] && s_time=${time%s*} && + let sleep_seconds+=$s_time echo "Sleep through grace ..." - [ "$time" == "-" ] && + [ "$orig_time" == "-" ] && error "Grace timeout was not set or quota not exceeded" - if [ "$time" == "none" ]; then + if [ "$orig_time" == "none" ]; then echo "...Grace timeout already expired" else - let time+=$extrasleep - echo "...sleep $time seconds" - sleep $time + let sleep_seconds+=$extrasleep + echo "...sleep $sleep_seconds seconds" + sleep $sleep_seconds fi } setup_quota_test() { wait_delete_completed echo "Creating test directory" - mkdir $DIR/$tdir || return 1 + mkdir_on_mdt0 $DIR/$tdir || return 1 chmod 0777 $DIR/$tdir || return 2 # always clear fail_loc in case of fail_loc isn't cleared # properly when previous test failed lustre_fail mds_ost 0 + stack_trap cleanup_quota_test EXIT } cleanup_quota_test() { echo "Delete files..." rm -rf $DIR/$tdir + [ -d $DIR/${tdir}_dom ] && rm -rf $DIR/${tdir}_dom echo "Wait for unlink objects finished..." wait_delete_completed sync_all_data || true @@ -476,7 +495,8 @@ reset_quota_settings() { # enable quota debug quota_init() { - do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota+trace" + do_nodes $(comma_list $(nodes_list)) \ + "$LCTL set_param -n debug=+quota,trace" } quota_init reset_quota_settings @@ -510,7 +530,7 @@ test_quota_performance() { # test basic quota performance b=21696 test_0() { - local MB=100 # 100M + local MB=100 # MB [ "$SLOW" = "no" ] && MB=10 local free_space=$(lfs_df | grep "summary" | awk '{print $4}') @@ -518,7 +538,6 @@ test_0() { skip "not enough space ${free_space} KB, " \ "required $((MB * 1024)) KB" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "none" || error "disable ost quota failed" test_quota_performance $MB @@ -527,8 +546,6 @@ test_0() { $LFS setquota -u $TSTUSR -b 0 -B 10G -i 0 -I 0 $DIR || error "set quota failed" test_quota_performance $MB - - cleanup_quota_test } run_test 0 "Test basic quota performance" @@ -550,21 +567,43 @@ test_1_check_write() { 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. + # guarantee that slave received new edquot through 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" + return 0 +} + +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_1a() { - local limit=10 # 10M + local limit=10 # MB local testfile="$DIR/$tdir/$tfile-0" 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" @@ -616,7 +655,6 @@ test_1a() { if ! is_project_quota_supported; then echo "Project quota is not supported" - cleanup_quota_test return 0 fi @@ -650,14 +688,13 @@ test_1a() { run_test 1a "Block hard limit (normal use and out of quota)" test_1b() { - local limit=10 # 10M - local global_limit=20 # 100M + local limit=10 # MB + local global_limit=20 # MB 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" @@ -671,7 +708,13 @@ test_1b() { pool_add_targets $qpool 0 $(($OSTCOUNT - 1)) || error "pool_add_targets failed" - $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR || + # check qmt_pool_add dmesg error + local msg_rgx="QMT0000: can't add to $FSNAME-OST0000.*pool.*$qpool" + local dmesg_err + dmesg_err=$(do_facet mds1 dmesg | grep "$msg_rgx" | tail -1) + [[ -z "$dmesg_err" ]] || error "found qmt_pool_add error: $dmesg_err" + + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR || error "set user quota failed" # make sure the system is clean @@ -700,7 +743,7 @@ test_1b() { $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 -o $qpool $DIR || + $LFS setquota -g $TSTUSR -b 0 -B ${limit}M --pool $qpool $DIR || error "set group quota failed" testfile="$DIR/$tdir/$tfile-1" @@ -723,7 +766,6 @@ test_1b() { if ! is_project_quota_supported; then echo "Project quota is not supported" - cleanup_quota_test return 0 fi @@ -739,7 +781,7 @@ test_1b() { $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 -o $qpool $DIR || + $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M --pool $qpool $DIR || error "set project quota failed" @@ -759,14 +801,13 @@ test_1b() { run_test 1b "Quota pools: Block hard limit (normal use and out of quota)" test_1c() { - local global_limit=20 # 100M + local global_limit=20 # MB 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" @@ -786,10 +827,10 @@ test_1c() { # create pools without hard limit # initially such case raised several bugs - $LFS setquota -u $TSTUSR -B 0M -o $qpool1 $DIR || + $LFS setquota -u $TSTUSR -B 0M --pool $qpool1 $DIR || error "set user quota failed" - $LFS setquota -u $TSTUSR -B 0M -o $qpool2 $DIR || + $LFS setquota -u $TSTUSR -B 0M --pool $qpool2 $DIR || error "set user quota failed" # make sure the system is clean @@ -811,26 +852,21 @@ test_1c() { sync_all_data || true used=$(getquota -u $TSTUSR global curspace $qpool1) - [ $used -ne 0 ] && quota_error u $TSTUSR \ + [ $used -eq 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 limit1=10 # MB + local limit2=12 # MB + local global_limit=20 # MB 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" @@ -848,10 +884,10 @@ test_1d() { pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) || error "pool_add_targets failed" - $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || error "set user quota failed" - $LFS setquota -u $TSTUSR -B ${limit2}M -o $qpool2 $DIR || + $LFS setquota -u $TSTUSR -B ${limit2}M --pool $qpool2 $DIR || error "set user quota failed" # make sure the system is clean @@ -873,25 +909,20 @@ test_1d() { sync_all_data || true used=$(getquota -u $TSTUSR global curspace $qpool1) - [ $used -ne 0 ] && quota_error u $TSTUSR \ + [ $used -eq 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 limit1=10 # MB + local global_limit=53000000 # MB 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" @@ -908,7 +939,7 @@ test_1e() { pool_add_targets $qpool1 1 1 || error "pool_add_targets failed" - $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || error "set user quota failed" # make sure the system is clean @@ -926,7 +957,7 @@ test_1e() { # 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 $short_qtype $TSTUSR \ + quota_error u $TSTUSR \ "$qtype write failure, but expect success" rm -f $testfile @@ -935,25 +966,20 @@ test_1e() { sync_all_data || true used=$(getquota -u $TSTUSR global curspace $qpool1) - [ $used -ne 0 ] && quota_error u $TSTUSR \ + [ $used -eq 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 global_limit=200 # MB + local limit1=10 # MB 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" @@ -966,7 +992,7 @@ test_1f() { pool_add_targets $qpool1 0 0 || error "pool_add_targets failed" - $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || error "set user quota failed" # make sure the system is clean @@ -993,117 +1019,289 @@ test_1f() { # 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 # MB + local global_limit=40 # MB + 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 $?" + $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 # MB + local testfile="$DIR/$tdir/$tfile-0" + + check_set_fallocate_or_skip + + 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:$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 -eq 0 ] || quota_error u $TSTUSR \ + "user quota isn't released after deletion" +} +run_test 1h "Block hard limit test using fallocate" + +test_1i() { + local global_limit=200 # 200M + local limit1=10 # 10M + local TESTDIR="$DIR/$tdir/" + local testfile="$TESTDIR/$tfile-0" + local testfile1="$TESTDIR/$tfile-1" + local testfile2="$TESTDIR/$tfile-2" + 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" + + # hit pool limit + test_1_check_write $testfile "user" $limit1 + $LFS setquota -u $TSTUSR -B 0 --pool $qpool1 $DIR || + error "set user quota failed" + + $LFS quota -uv $TSTUSR --pool $qpool1 $DIR + $RUNAS $DD of=$testfile1 count=$((limit1/2)) || + quota_error u $TSTUSR "write failure, but expect success" + + rm -f $testfile + rm -f $testfile1 + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || + error "set user quota failed" + test_1_check_write $testfile "user" $limit1 + local tmp_limit=$(($limit1*2)) + # increase pool limit + $LFS setquota -u $TSTUSR -B ${tmp_limit}M --pool $qpool1 $DIR || + error "set user quota failed" + # now write shouldn't fail + $RUNAS $DD of=$testfile1 count=$((limit1/3)) || + quota_error u $TSTUSR "write failure, but expect success" + # decrease pool limit + $LFS setquota -u $TSTUSR -B ${limit1}M --pool $qpool1 $DIR || + error "set user quota failed" + $RUNAS $DD of=$testfile2 count=$((limit1/3)) + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + $RUNAS $DD of=$testfile2 seek=$((limit1/3)) count=1 && + quota_error u $TSTUSR "write success, but expect failure" + return 0 +} +run_test 1i "Quota pools: different limit and usage relations" + # test inode hardlimit test_2() { - local TESTFILE="$DIR/$tdir/$tfile-0" - local LIMIT=$(do_facet mds1 $LCTL get_param -n \ + local testfile="$DIR/$tdir/$tfile-0" + local least_qunit=$(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 + sed -e 's/least qunit/least_qunit/' | + awk '/least_qunit/{ print $2 }') + local limit - [ "$SLOW" = "no" ] || LIMIT=$((LIMIT * 1024)) + [ "$SLOW" = "no" ] && limit=$((least_qunit * 2)) || + limit=$((least_qunit * 1024)) + echo "least_qunit: '$least_qunit', limit: '$limit'" - local FREE_INODES=$(mdt_free_inodes 0) - echo "$FREE_INODES free inodes on master MDT" - [ $FREE_INODES -lt $LIMIT ] && - skip "not enough free inodes $FREE_INODES required $LIMIT" + local free_inodes=$(mdt_free_inodes 0) + echo "$free_inodes free inodes on master MDT" + [ $free_inodes -lt $limit ] && + skip "not enough free inodes $free_inodes required $limit" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # enable mdt quota set_mdt_qtype $QTYPE || error "enable mdt quota failed" # test for user - log "User quota (inode hardlimit:$LIMIT files)" - $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR || + log "User quota (inode hardlimit:$limit files)" + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $limit $DIR || error "set user quota failed" # make sure the system is clean - local USED=$(getquota -u $TSTUSR global curinodes) - [ $USED -ne 0 ] && error "Used inodes($USED) for user $TSTUSR isn't 0." + local used=$(getquota -u $TSTUSR global curinodes) + [ $used -ne 0 ] && error "Used inodes($used) for user $TSTUSR isn't 0." - log "Create $LIMIT files ..." - $RUNAS createmany -m ${TESTFILE} $LIMIT || + log "Create $((limit - least_qunit)) files ..." + $RUNAS createmany -m ${testfile} $((limit - least_qunit)) || quota_error u $TSTUSR "user create failure, but expect success" + # it is ok, if it fails on the last qunit + $RUNAS createmany -m ${testfile}_yyy $least_qunit || true log "Create out of file quota ..." - $RUNAS touch ${TESTFILE}_xxx && + $RUNAS touch ${testfile}_xxx && quota_error u $TSTUSR "user create success, but expect EDQUOT" # cleanup - unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed" - rm -f ${TESTFILE}_xxx + unlinkmany ${testfile} $((limit - least_qunit)) || + error "unlinkmany $testfile failed" + # if 2nd createmany got EDQUOT, not all of nodes would be created + unlinkmany ${testfile}_yyy $least_qunit || true + rm -f ${testfile}_xxx wait_delete_completed - USED=$(getquota -u $TSTUSR global curinodes) - [ $USED -ne 0 ] && quota_error u $TSTUSR \ + used=$(getquota -u $TSTUSR global curinodes) + [ $used -ne 0 ] && quota_error u $TSTUSR \ "user quota isn't released after deletion" resetquota -u $TSTUSR # test for group log "--------------------------------------" - log "Group quota (inode hardlimit:$LIMIT files)" - $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR || + log "Group quota (inode hardlimit:$limit files)" + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $limit $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 curinodes) - [ $USED -ne 0 ] && error "Used inodes($USED) for group $TSTUSR isn't 0." + used=$(getquota -g $TSTUSR global curinodes) + [ $used -ne 0 ] && error "Used inodes($used) for group $TSTUSR isn't 0." - log "Create $LIMIT files ..." - $RUNAS createmany -m ${TESTFILE} $LIMIT || + log "Create $limit files ..." + $RUNAS createmany -m ${testfile} $((limit - least_qunit)) || quota_error g $TSTUSR "group create failure, but expect success" + $RUNAS createmany -m ${testfile}_yyy $least_qunit || log "Create out of file quota ..." - $RUNAS touch ${TESTFILE}_xxx && + $RUNAS touch ${testfile}_xxx && quota_error g $TSTUSR "group create success, but expect EDQUOT" # cleanup - unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed" - rm -f ${TESTFILE}_xxx + unlinkmany ${testfile} $((limit - least_qunit)) || + error "unlinkmany $testfile failed" + unlinkmany ${testfile}_yyy $least_qunit || true + rm -f ${testfile}_xxx wait_delete_completed - USED=$(getquota -g $TSTUSR global curinodes) - [ $USED -ne 0 ] && quota_error g $TSTUSR \ + used=$(getquota -g $TSTUSR global curinodes) + [ $used -ne 0 ] && quota_error g $TSTUSR \ "user quota isn't released after deletion" resetquota -g $TSTUSR - ! is_project_quota_supported && cleanup_quota_test && + ! is_project_quota_supported && echo "Skip project quota is not supported" && return 0 # test for project log "--------------------------------------" - log "Project quota (inode hardlimit:$LIMIT files)" - $LFS setquota -p $TSTPRJID -b 0 -B 0 -i 0 -I $LIMIT $DIR || + log "Project quota (inode hardlimit:$limit files)" + $LFS setquota -p $TSTPRJID -b 0 -B 0 -i 0 -I $limit $DIR || error "set project quota failed" - TESTFILE=$DIR/$tdir/$tfile-1 + testfile=$DIR/$tdir/$tfile-1 # make sure the system is clean - USED=$(getquota -p $TSTPRJID global curinodes) - [ $USED -ne 0 ] && - error "Used inodes($USED) for project $TSTPRJID isn't 0" + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -ne 0 ] && + error "Used inodes($used) for project $TSTPRJID isn't 0" change_project -sp $TSTPRJID $DIR/$tdir - log "Create $LIMIT files ..." - $RUNAS createmany -m ${TESTFILE} $((LIMIT-1)) || quota_error p \ - $TSTPRJID "project create fail, but expect success" + log "Create $limit files ..." + $RUNAS createmany -m ${testfile} $((limit-least_qunit)) || + quota_error p $TSTPRJID \ + "project create fail, but expect success" + $RUNAS createmany -m ${testfile}_yyy $least_qunit || true log "Create out of file quota ..." - $RUNAS touch ${TESTFILE}_xxx && quota_error p $TSTPRJID \ + $RUNAS touch ${testfile}_xxx && quota_error p $TSTPRJID \ "project create success, but expect EDQUOT" change_project -C $DIR/$tdir cleanup_quota_test - USED=$(getquota -p $TSTPRJID global curinodes) - [ $USED -eq 0 ] || quota_error p $TSTPRJID \ + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 0 ] || quota_error p $TSTPRJID \ "project quota isn't released after deletion" } @@ -1116,9 +1314,10 @@ test_block_soft() { local OFFSET=0 local qtype=$4 local pool=$5 + local soft_limit=$(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) setup_quota_test - stack_trap cleanup_quota_test EXIT $LFS setstripe $testfile -c 1 -i 0 chown $TSTUSR.$TSTUSR $testfile @@ -1166,8 +1365,11 @@ test_block_soft() { log "Write after timer goes off" # maybe cache write, ignore. - $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || true - OFFSET=$((OFFSET + 1024)) + # write up to soft least quint to consume all + # possible slave granted space. + $RUNAS dd if=/dev/zero of=$testfile bs=1K \ + count=$soft_limit seek=$OFFSET || true + OFFSET=$((OFFSET + soft_limit)) cancel_lru_locks osc log "Write after cancel lru locks" $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET && @@ -1205,7 +1407,7 @@ test_block_soft() { # block soft limit test_3a() { - local grace=20 # 20s + local grace=20 # seconds if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then grace=60 fi @@ -1272,7 +1474,7 @@ test_3a() { run_test 3a "Block soft limit (start timer, timer goes off, stop timer)" test_3b() { - local grace=20 # 20s + local grace=20 # seconds local qpool="qpool1" if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then grace=60 @@ -1302,11 +1504,11 @@ test_3b() { $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 \ - -o $qpool $DIR || error "set user grace time failed" + --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 -o $qpool $DIR || + $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 @@ -1320,11 +1522,11 @@ test_3b() { $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 \ - -o $qpool $DIR || error "set group grace time failed" + --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 -o $qpool $DIR || + $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 @@ -1341,36 +1543,37 @@ test_3b() { $MAX_IQ_TIME $DIR || error "set project grace time failed" $LFS setquota -t -p --block-grace $grace \ - -o $qpool $DIR || error "set project grace time failed" + --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 -o $qpool $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 -o $qpool $DIR || - error "set 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 \ - -o $qpool $DIR || error "restore user grace time failed" + --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 \ - -o $qpool $DIR || error "restore group grace time failed" + --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 grace=20 # seconds local qpool="qpool1" local qpool2="qpool2" if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then @@ -1409,19 +1612,19 @@ test_3c() { $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 \ - -o $qpool $DIR || error "set user grace time failed" + --pool $qpool $DIR || error "set user grace time failed" $LFS setquota -t -u --block-grace $grace2 \ - -o $qpool2 $DIR || error "set user grace time failed" + --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 -o $qpool $DIR || + $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 + # qpool has minimum soft limit, but its grace is greater than + # the 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 -o $qpool2 $DIR || + $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 @@ -1430,9 +1633,9 @@ test_3c() { $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 \ - -o $qpool $DIR || error "restore user grace time failed" + --pool $qpool $DIR || error "restore user grace time failed" $LFS setquota -t -u --block-grace $MAX_DQ_TIME \ - -o $qpool2 $DIR || error "restore user grace time failed" + --pool $qpool2 $DIR || error "restore user grace time failed" } run_test 3c "Quota pools: check block soft limit on different pools" @@ -1441,9 +1644,10 @@ test_file_soft() { local LIMIT=$2 local grace=$3 local qtype=$4 + local SOFT_LIMIT=$(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.md-0x0.soft_least_qunit) setup_quota_test - trap cleanup_quota_test EXIT is_project_quota_supported && change_project -sp $TSTPRJID $DIR/$tdir echo "Create files to exceed soft limit" @@ -1473,12 +1677,8 @@ test_file_soft() { $SHOW_QUOTA_INFO_PROJID echo "Create file after timer goes off" - # There is a window that space is accounted in the quota usage but - # hasn't been decreased from the pending write, if we acquire quota - # in this window, we'll acquire more than we needed. - $RUNAS touch ${TESTFILE}_after_1 ${TESTFILE}_after_2 || true - sync_all_data || true - $RUNAS touch ${TESTFILE}_after_3 && + # exceed least soft limit is possible + $RUNAS createmany -m ${TESTFILE}_after_3 $((SOFT_LIMIT + 1)) && quota_error a $TSTUSR "create after timer expired," \ "but expect EDQUOT" sync_all_data || true @@ -1511,6 +1711,7 @@ test_4a() { local TESTFILE=$DIR/$tdir/$tfile-0 local GRACE=12 + [ "$mds1_FSTYPE" = zfs ] && GRACE=20 set_mdt_qtype $QTYPE || error "enable mdt quota failed" echo "User quota (soft limit:$LIMIT files grace:$GRACE seconds)" @@ -1523,8 +1724,6 @@ test_4a() { $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR || error "set user quota failed" - [ "$mds1_FSTYPE" = zfs ] && GRACE=20 - test_file_soft $TESTFILE $LIMIT $GRACE "u" echo "Group quota (soft limit:$LIMIT files grace:$GRACE seconds)" @@ -1606,11 +1805,10 @@ run_test 4b "Grace time strings handling" # chown & chgrp (chown & chgrp successfully even out of block/file quota) test_5() { - local BLIMIT=10 # 10M - local ILIMIT=10 # 10 inodes + local BLIMIT=10 # MB + local ILIMIT=10 # inodes setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_mdt_qtype $QTYPE || error "enable mdt quota failed" set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -1662,20 +1860,18 @@ test_5() { # cleanup unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) || error "unlinkmany $DIR/$tdir/$tfile-0_ failed" - cleanup_quota_test } run_test 5 "Chown & chgrp successfully even out of block/file quota" # test dropping acquire request on master test_6() { - local LIMIT=3 # 3M + local LIMIT=3 # MB # Clear dmesg so watchdog is not triggered by previous # test output do_facet ost1 dmesg -c > /dev/null setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTUSR global curspace) @@ -1772,20 +1968,17 @@ test_6() { fi sleep 1 done - - cleanup_quota_test } run_test 6 "Test dropping acquire request on master" # quota reintegration (global index) test_7a() { local TESTFILE=$DIR/$tdir/$tfile - local LIMIT=20 # 20M + local LIMIT=20 # MB [ "$SLOW" = "no" ] && LIMIT=5 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTUSR global curspace) @@ -1844,18 +2037,15 @@ test_7a() { # hardlimit should be cleared on slave during reintegration $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync || quota_error u $TSTUSR "write error, but expect success" - - cleanup_quota_test } run_test 7a "Quota reintegration (global index)" # quota reintegration (slave index) test_7b() { - local LIMIT="100G" + local limit=100000 # MB local TESTFILE=$DIR/$tdir/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTUSR global curspace) @@ -1884,7 +2074,7 @@ test_7b() { lustre_fail mds 0xa02 set_ost_qtype $QTYPE || error "enable ost quota failed" - $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR || + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set quota failed" # ignore the write error @@ -1911,13 +2101,12 @@ run_test 7b "Quota reintegration (slave index)" # quota reintegration (restart mds during reintegration) test_7c() { - local LIMIT=20 # 20M + local LIMIT=20 # MB local TESTFILE=$DIR/$tdir/$tfile [ "$SLOW" = "no" ] && LIMIT=5 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTUSR global curspace) @@ -1955,8 +2144,7 @@ test_7c() { # reintegration, write will exceed quota $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync && quota_error u $TSTUSR "write success, but expect EDQUOT" - - cleanup_quota_test + return 0 } run_test 7c "Quota reintegration (restart mds during reintegration)" @@ -1964,10 +2152,9 @@ run_test 7c "Quota reintegration (restart mds during reintegration)" test_7d(){ local TESTFILE=$DIR/$tdir/$tfile local TESTFILE1="$DIR/$tdir/$tfile"-1 - local limit=20 #20M + local limit=20 # MB setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "none" || error "disable ost quota failed" $LFS setquota -u $TSTUSR -B ${limit}M $DIR || @@ -1991,8 +2178,7 @@ test_7d(){ $RUNAS2 $DD of=$TESTFILE1 count=$((limit + 1)) oflag=sync && quota_error u $TSTUSR2 "$TSTUSR2 write success, expect EDQUOT" - - cleanup_quota_test + return 0 } run_test 7d "Quota reintegration (Transfer index in multiple bulks)" @@ -2011,11 +2197,10 @@ test_7e() { skip "requires zpool with active userobj_accounting" } - local ilimit=$((1024 * 2)) # 2k inodes + local ilimit=$((1024 * 2)) # inodes local TESTFILE=$DIR/${tdir}-1/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTUSR global curinodes) @@ -2077,8 +2262,6 @@ test_7e() { $RUNAS unlinkmany $TESTFILE $((ilimit + 1)) || error "unlink failed" rmdir $DIR/${tdir}-1 || error "unlink remote dir failed" - - cleanup_quota_test } run_test 7e "Quota reintegration (inode limits)" @@ -2088,7 +2271,6 @@ test_8() { local FILE_LIMIT=1000000 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_mdt_qtype $QTYPE || error "enable mdt quota failed" set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -2113,7 +2295,6 @@ test_8() { quota_error a $TSTUSR "dbench failed!" is_project_quota_supported && change_project -C $DIR/$tdir - cleanup_quota_test } run_test 8 "Run dbench with quota enabled" @@ -2138,7 +2319,6 @@ test_9() { check_whether_skip && return 0 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "ug" || error "enable ost quota failed" @@ -2183,7 +2363,6 @@ test_10() { local TESTFILE=$DIR/$tdir/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # set limit to root user should fail $LFS setquota -u root -b 100G -B 500G -i 1K -I 1M $DIR && @@ -2205,15 +2384,12 @@ test_10() { runas -u 0 -g 0 $DD of=$TESTFILE count=3 oflag=sync || error "write failure, expect success" - - cleanup_quota_test } run_test 10 "Test quota for root user" test_11() { local TESTFILE=$DIR/$tdir/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_mdt_qtype "ug" || error "enable mdt quota failed" $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 1 $DIR || @@ -2228,26 +2404,23 @@ test_11() { $SHOW_QUOTA_USER local USED=$(getquota -u $TSTUSR global curinodes) [ $USED -ge 2 ] || error "Used inodes($USED) is less than 2" - - cleanup_quota_test } run_test 11 "Chown/chgrp ignores quota" test_12a() { [ "$OSTCOUNT" -lt "2" ] && skip "needs >= 2 OSTs" - local blimit=22 # 22M + local blimit=22 # MB local blk_cnt=$((blimit - 5)) local TESTFILE0="$DIR/$tdir/$tfile"-0 local TESTFILE1="$DIR/$tdir/$tfile"-1 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "u" || error "enable ost quota failed" quota_show_check b u $TSTUSR - $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $DIR || + $LFS setquota -u $TSTUSR -b 0 -B ${blimit}M -i 0 -I 0 $DIR || error "set quota failed" $LFS setstripe $TESTFILE0 -c 1 -i 0 || error "setstripe $TESTFILE0 failed" @@ -2271,20 +2444,17 @@ test_12a() { echo "Write to ost1 after space freed from ost0..." $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync || quota_error a $TSTUSR "rebalancing failed" - - cleanup_quota_test } run_test 12a "Block quota rebalancing" test_12b() { [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs" - local ilimit=$((1024 * 2)) # 2k inodes + local ilimit=$((1024 * 2)) # inodes local TESTFILE0=$DIR/$tdir/$tfile local TESTFILE1=$DIR/${tdir}-1/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT $LFS mkdir -i 1 $DIR/${tdir}-1 || error "create remote dir failed" chmod 0777 $DIR/${tdir}-1 @@ -2315,8 +2485,6 @@ test_12b() { $RUNAS unlinkmany $TESTFILE1 $((ilimit / 2)) || error "unlink mdt1 files failed" rmdir $DIR/${tdir}-1 || error "unlink remote dir failed" - - cleanup_quota_test } run_test 12b "Inode quota rebalancing" @@ -2326,7 +2494,6 @@ test_13(){ local procf="ldlm.namespaces.*MDT0000-lwp-OST0000.lru_size" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "u" || error "enable ost quota failed" quota_show_check b u $TSTUSR @@ -2364,8 +2531,6 @@ test_13(){ local space=$(getquota -u $TSTUSR $OSTUUID curspace) [ $limit -le $space ] || error "spare quota isn't released, limit:$limit, space:$space" - - cleanup_quota_test } run_test 13 "Cancel per-ID lock in the LRU list" @@ -2393,36 +2558,137 @@ test_15(){ } run_test 15 "Set over 4T block quota" -test_17sub() { - local err_code=$1 - local BLKS=1 # 1M less than limit - local TESTFILE=$DIR/$tdir/$tfile +test_16a() +{ + (( $CLIENT_VERSION < $(version_code 2.14.55) )) && + skip "Not supported Lustre client before 2.14.55" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT - # 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 setquota -u $TSTUSR -B 500M -I 10K $MOUNT || + error "failed to set quota for user $TSTUSR" + $LFS setquota -g $TSTUSR -B 500M -I 10K $MOUNT || + error "failed to set quota for group $TSTUSR" - set_ost_qtype "ug" || error "enable ost quota failed" - # make sure no granted quota on ost - resetquota -u $TSTUSR - $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR || - error "set quota failed" + $RUNAS $DD of=$DIR/$tdir/$tfile bs=1M count=50 || + quota_error u $TSTUSR "write failure" - quota_show_check b u $TSTUSR + $LFS quota -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota" - #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xa04 - lustre_fail mds 0xa04 $err_code + local OSC=$($LCTL dl | grep OST0000-osc-[^M] | awk '{print $4}') - # write in background - $RUNAS $DD of=$TESTFILE count=$BLKS oflag=direct & - local DDPID=$! + $LCTL --device %$OSC deactivate + stack_trap "$LCTL --device %$OSC activate" - sleep 2 - # write should be blocked and never finished - if ! ps -p $DDPID > /dev/null 2>&1; then + $LFS quota -v -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota after deactivate OSC" + $LFS quota -v -g $TSTUSR $MOUNT || + quota_error g $TSTUSR "failed to get quota after deactivate OSC" + + (( $MDSCOUNT > 1 )) || return 0 + + local MDC=$($LCTL dl | grep MDT0001-mdc-[^M] | awk '{print $4}') + + $LCTL --device %$MDC deactivate + stack_trap "$LCTL --device %$MDC activate" + + $LFS quota -v -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota after deactivate MDC" + $LFS quota -v -g $TSTUSR $MOUNT || + quota_error g $TSTUSR "failed to get quota after deactivate OSC" +} +run_test 16a "lfs quota should skip the inactive MDT/OST" + +cleanup_16b() +{ + stopall + formatall + setupall +} + +test_16b() +{ + (( $CLIENT_VERSION < $(version_code 2.14.55) )) && + skip "Not supported Lustre client before 2.14.55" + + (( $MDSCOUNT >= 3 )) || skip "needs >= 3 MDTs" + + stopall + if ! combined_mgs_mds ; then + format_mgs + start_mgs + fi + + add mds1 $(mkfs_opts mds1 $(mdsdevname 1)) --index=0 --reformat \ + $(mdsdevname 1) $(mdsvdevname 1) + add mds2 $(mkfs_opts mds2 $(mdsdevname 2)) --index=1 --reformat \ + $(mdsdevname 2) $(mdsvdevname 2) + add mds3 $(mkfs_opts mds3 $(mdsdevname 3)) --index=100 --reformat \ + $(mdsdevname 3) $(mdsvdevname 3) + + add ost1 $(mkfs_opts ost1 $(ostdevname 1)) --index=0 --reformat \ + $(ostdevname 1) $(ostvdevname 1) + add ost2 $(mkfs_opts ost2 $(ostdevname 2)) --index=100 --reformat \ + $(ostdevname 2) $(ostvdevname 2) + + stack_trap cleanup_16b + + start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS || error "MDT1 start failed" + start mds2 $(mdsdevname 2) $MDS_MOUNT_OPTS || error "MDT2 start failed" + start mds3 $(mdsdevname 3) $MDS_MOUNT_OPTS || error "MDT3 start failed" + start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "OST1 start failed" + start ost2 $(ostdevname 2) $OST_MOUNT_OPTS || error "OST2 start failed" + + mount_client $MOUNT || error "Unable to mount client" + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + $LFS setquota -u $TSTUSR -B 100M -I 10K $MOUNT || + error "failed to set quota for user $TSTUSR" + $LFS setquota -g $TSTUSR -B 100M -I 10K $MOUNT || + error "failed to set quota for group $TSTUSR" + + $RUNAS $DD of=$DIR/$tdir/$tfile bs=1M count=10 || + quota_error u $TSTUSR "write failure" + + cnt=$($LFS quota -v -u $TSTUSR $MOUNT | grep -ce "^$FSNAME-[MD|OS]T*") + [ $cnt -le 5 ] || quota_error u $TSTUSR "failed to get user quota" + cnt=$($LFS quota -v -g $TSTUSR $MOUNT | grep -ce "^$FSNAME-[MD|OS]T*") + [ $cnt -le 5 ] || quota_error g $TSTUSR "failed to get group quota" +} +run_test 16b "lfs quota should skip the nonexistent MDT/OST" + +test_17sub() { + local err_code=$1 + local BLKS=1 # 1M less than limit + local TESTFILE=$DIR/$tdir/$tfile + + setup_quota_test || error "setup quota failed with $?" + + # 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." + + set_ost_qtype "ug" || error "enable ost quota failed" + # make sure no granted quota on ost + resetquota -u $TSTUSR + $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR || + error "set quota failed" + + quota_show_check b u $TSTUSR + + #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xa04 + lustre_fail mds 0xa04 $err_code + + # write in background + $RUNAS $DD of=$TESTFILE count=$BLKS oflag=direct & + local DDPID=$! + + sleep 2 + # write should be blocked and never finished + if ! ps -p $DDPID > /dev/null 2>&1; then lustre_fail mds 0 0 quota_error u $TSTUSR "write finished incorrectly!" fi @@ -2472,15 +2738,14 @@ run_test 17 "DQACQ return recoverable error" test_18_sub () { local io_type=$1 - local blimit="200m" # 200M + local blimit=200 # MB local TESTFILE="$DIR/$tdir/$tfile" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "u" || error "enable ost quota failed" log "User quota (limit: $blimit)" - $LFS setquota -u $TSTUSR -b 0 -B $blimit -i 0 -I 0 $MOUNT || + $LFS setquota -u $TSTUSR -b 0 -B ${blimit}M -i 0 -I 0 $MOUNT || error "set quota failed" quota_show_check b u $TSTUSR @@ -2551,11 +2816,10 @@ test_18() { run_test 18 "MDS failover while writing, no watchdog triggered (b14840)" test_19() { - local blimit=5 # 5M + local blimit=5 # MB local TESTFILE=$DIR/$tdir/$tfile setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -2564,11 +2828,11 @@ test_19() { chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" echo "Set user quota (limit: ${blimit}M)" - $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT || + $LFS setquota -u $TSTUSR -b 0 -B ${blimit}M -i 0 -I 0 $MOUNT || error "set user quota failed" quota_show_check b u $TSTUSR echo "Update quota limits" - $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT || + $LFS setquota -u $TSTUSR -b 0 -B ${blimit}M -i 0 -I 0 $MOUNT || error "set group quota failed" quota_show_check b u $TSTUSR @@ -2579,8 +2843,6 @@ test_19() { $RUNAS $DD of=$TESTFILE count=$((blimit + 1)) seek=$((blimit + 1)) && quota_error u $TSTUSR "Write success, expect failure" $SHOW_QUOTA_USER - - cleanup_quota_test } run_test 19 "Updating admin limits doesn't zero operational limits(b14790)" @@ -2631,7 +2893,6 @@ test_21() { local ILIMIT=1000000 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype $QTYPE || error "Enable ost quota failed" @@ -2695,8 +2956,6 @@ test_21() { sleep 1 done echo "(dd_pid=$DDPID2, time=$count)successful" - - cleanup_quota_test } run_test 21 "Setquota while writing & deleting (b16053)" @@ -2744,7 +3003,6 @@ test_23_sub() { local LIMIT=$1 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype $QTYPE || error "Enable ost quota failed" @@ -2803,11 +3061,10 @@ test_23() { run_test 23 "Quota should be honored with directIO (b16125)" test_24() { - local blimit=5 # 5M + local blimit=5 # MB local TESTFILE="$DIR/$tdir/$tfile" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -2826,8 +3083,6 @@ test_24() { sync_all_data || true $SHOW_QUOTA_USER | grep '*' || error "no matching *" - - cleanup_quota_test } run_test 24 "lfs draws an asterix when limit is reached (b16646)" @@ -2906,12 +3161,11 @@ test_27d() { run_test 27d "lfs setquota should support fraction block limit" test_30() { - local LIMIT=4 # 4MB + local LIMIT=4 # MB local TESTFILE="$DIR/$tdir/$tfile" local GRACE=10 setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT set_ost_qtype "u" || error "enable ost quota failed" @@ -2935,8 +3189,6 @@ test_30() { $SHOW_QUOTA_USER $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=4 && error "grace times were reset" - # cleanup - cleanup_quota_test $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \ $MAX_IQ_TIME $DIR || error "restore grace time failed" } @@ -2944,12 +3196,11 @@ run_test 30 "Hard limit updates should not reset grace times" # basic usage tracking for user & group test_33() { - local INODES=10 # 10 files - local BLK_CNT=2 # of 2M each + local INODES=10 # files + local BLK_CNT=2 # MB each local TOTAL_BLKS=$((INODES * BLK_CNT * 1024)) setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTID global curspace) @@ -3029,12 +3280,11 @@ run_test 33 "Basic usage tracking for user & group & project" # usage transfer test for user & group & project test_34() { - local BLK_CNT=2 # 2MB + local BLK_CNT=2 # MB local project_supported="no" is_project_quota_supported && project_supported="yes" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTID global curspace) @@ -3114,17 +3364,15 @@ test_34() { [ $USED -lt $BLK_CNT ] && error \ "Used space for group $TSTPRJID is $USED, expected $BLK_CNT" fi - - cleanup_quota_test + return 0 } run_test 34 "Usage transfer for user & group & project" # usage is still accessible across restart test_35() { - local BLK_CNT=2 # 2 MB + local BLK_CNT=2 # MB setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT echo "Write file..." $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null || @@ -3219,8 +3467,6 @@ test_35() { error "Used space for project $TSTPRJID isn't " \ "increased orig:$ORIG_PRJ_SPACE, now:$USED" fi - - cleanup_quota_test } run_test 35 "Usage is still accessible across reboot" @@ -3231,7 +3477,6 @@ test_37() { skip "Old server doesn't have LU-5006 fix." setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTID global curspace) @@ -3252,8 +3497,6 @@ test_37() { USED=$(getquota -u $TSTID global curspace) [ $USED -ne 0 ] || quota_error u $TSTUSR "Used space is 0" - - cleanup_quota_test } run_test 37 "Quota accounted properly for file created by 'lfs setstripe'" @@ -3265,7 +3508,6 @@ test_38() { [ "$UID" != 0 ] && skip_env "must run as root" && return setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT # make sure the system is clean local USED=$(getquota -u $TSTID global curspace) @@ -3290,7 +3532,7 @@ test_38() { local procf="osd-$mds1_FSTYPE.$FSNAME-MDT0000" procf=${procf}.quota_slave.acct_user - local accnt_cnt + local acct_cnt acct_cnt=$(do_facet mds1 $LCTL get_param $procf | grep "id:" | \ awk '{if ($3 < 10000) {print $3}}' | wc -l) @@ -3300,8 +3542,6 @@ test_38() { do_facet mds1 $LCTL get_param $procf error "skipped id entries" } - - cleanup_quota_test } run_test 38 "Quota accounting iterator doesn't skip id entries" @@ -3325,10 +3565,8 @@ test_39() { mount setupall projectid=$(lfs project $TESTFILE | awk '{print $1}') - [ $projectid -ne 1024 ] && + [ $projectid -eq 1024 ] || error "Project id should be 1024 not $projectid" - - cleanup_quota_test } run_test 39 "Project ID interface works correctly" @@ -3346,9 +3584,7 @@ test_40a() { ln $dir1/1 $dir2/1_link && error "Hard link across different project quota should fail" - rm -rf $dir1 $dir2 - - cleanup_quota_test + return 0 } run_test 40a "Hard link across different project ID" @@ -3365,11 +3601,7 @@ test_40b() { mv $dir1/1 $dir2/2 || error "mv failed $?" local projid=$(lfs project $dir2/2 | awk '{print $1}') - if [ "$projid" != "2" ]; then - error "project id expected 2 not $projid" - fi - rm -rf $dir1 $dir2 - cleanup_quota_test + [ "$projid" -eq 2 ] || error "project id expected 2 not $projid" } run_test 40b "Mv across different project ID" @@ -3392,15 +3624,146 @@ test_40c() { error "file under remote dir expected 1 not $projid" #Agent inode should be ignored for project quota - USED=$(getquota -p 1 global curinodes) - [ "$USED" != "3" ] && - error "file count expected 3 got $USED" + local used=$(getquota -p 1 global curinodes) + [ $used -eq 3 ] || + error "file count expected 3 got $used" +} +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 + local used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 36 ] || + error "file count expected 36 got $used" +} +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 $?" + 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" +} +run_test 41 "df should return projid-specific values" + +test_delete_qid() +{ + local qslv_file=$1 + local qtype_file=$2 + local qtype=$3 + local qid=$4 + local osd="osd-ldiskfs" + + [ "$ost1_FSTYPE" = zfs ] && osd="osd-zfs" + + rm -f $DIR/$tdir/$tfile + $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile + chmod a+rw $DIR/$tdir/$tfile + + $LFS setquota $qtype $qid -B 300M $MOUNT + $RUNAS dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 || + error "failed to dd" + + do_facet $SINGLEMDS \ + "cat /proc/fs/lustre/qmt/$FSNAME-QMT0000/dt-0x0/$qtype_file | + grep -E 'id: *$qid'" || error "QMT: no qid $qid is found" + echo $osd + do_facet ost1 \ + "cat /proc/fs/lustre/$osd/$FSNAME-OST0000/$qslv_file | + grep -E 'id: *$qid'" || error "QSD: no qid $qid is found" + + $LFS setquota $qtype $qid --delete $MOUNT + do_facet $SINGLEMDS \ + "cat /proc/fs/lustre/qmt/$FSNAME-QMT0000/dt-0x0/$qtype_file | + grep -E 'id: *$qid'" && error "QMT: qid $qid is not deleted" + sleep 5 + do_facet ost1 \ + "cat /proc/fs/lustre/$osd/$FSNAME-OST0000/$qslv_file | + grep -E 'id: *$qid'" && error "QSD: qid $qid is not deleted" + + $LFS setquota $qtype $qid -B 500M $MOUNT + $RUNAS dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 || + error "failed to dd" + do_facet $SINGLEMDS \ + "cat /proc/fs/lustre/qmt/$FSNAME-QMT0000/dt-0x0/$qtype_file | + grep -E 'id: *$qid'" || error "QMT: qid $pid is not recreated" + cat /proc/fs/lustre/$osd/$FSNAME-OST0000/$qslv_file + do_facet ost1 \ + "cat /proc/fs/lustre/$osd/$FSNAME-OST0000/$qslv_file | + grep -E 'id: *$qid'" || error "QSD: qid $qid is not recreated" +} + +test_48() +{ + setup_quota_test || error "setup quota failed with $?" + set_ost_qtype $QTYPE || error "enable ost quota failed" + quota_init + + test_delete_qid "quota_slave/limit_user" "glb-usr" "-u" $TSTID + test_delete_qid "quota_slave/limit_group" "glb-grp" "-g" $TSTID + is_project_quota_supported && + test_delete_qid "quota_slave/limit_project" "glb-prj" "-p" "10000" - rm -rf $dir cleanup_quota_test - return 0 } -run_test 40c "Remote child Dir inherit project quota properly" +run_test 48 "lfs quota --delete should delete quota project ID" test_50() { ! is_project_quota_supported && @@ -3423,10 +3786,7 @@ test_50() { # 1(projid 0 dir) + 1(projid 2 dir) + 20(projid 2 files) count=$($LFS find ! --projid 1 $DIR/$tdir | wc -l) - [ "$count" != 22 ] && error "expected 22 but got $count" - - rm -rf $dir1 $dir2 - cleanup_quota_test + [ $count -eq 22 ] || error "expected 22 but got $count" } run_test 50 "Test if lfs find --projid works" @@ -3455,30 +3815,71 @@ test_51() { #try mv to dir mv $DIR/$tdir/6 $dir/7 used=$(getquota -p 1 global curinodes) - [ $used != "6" ] && error "expected 6 got $used" - - rm -rf $dir - cleanup_quota_test + [ $used -eq 6 ] || error "expected 6 got $used" } run_test 51 "Test project accounting with mv/cp" test_52() { ! is_project_quota_supported && skip "Project quota is not supported" + + (( MDS1_VERSION >= $(version_code 2.14.55) )) || + skip "Need MDS version at least 2.14.55" + setup_quota_test || error "setup quota failed with $?" - local dir="$DIR/$tdir/dir" - mkdir $dir && change_project -sp 1 $dir - touch $DIR/$tdir/file - #Try renaming a file into the project. This should fail. - for num in $(seq 1 2000); do - mrename $DIR/$tdir/file $dir/file >&/dev/null && - error "rename should fail" - done - rm -rf $dir - cleanup_quota_test + local dir1=$DIR/$tdir/t52_dir1 + local dir2=$DIR/$tdir/t52_dir2 + + mkdir $dir1 || error "failed to mkdir $dir1" + mkdir $dir2 || error "failed to mkdir $dir2" + + $LFS project -sp 1000 $dir1 || error "fail to set project on $dir1" + $LFS project -sp 1001 $dir2 || error "fail to set project on $dir2" + + $DD if=/dev/zero of=/$dir1/$tfile bs=1M count=100 || + error "failed to create and write $tdir1/$tfile" + + cancel_lru_locks osc + sync; sync_all_data || true + + local attrs=($(lsattr -p $dir1/$tfile)) + (( ${attrs[0]} == 1000 )) || + error "project ID on $dir1/$tfile is not inherited" + + $LFS quota -p 1000 $DIR + $LFS quota -p 1001 $DIR + + local prev_used=$(getquota -p 1000 global curspace) + local prev_used2=$(getquota -p 1001 global curspace) + + mrename $dir1 $dir2/tdir || log "rename directory return $?" + + local inum_before=$(ls -i $dir1/$tfile | awk '{print $1}') + mrename $dir1/$tfile $dir2/$tfile || error "failed to rename file" + local inum_after=$(ls -i $dir2/$tfile | awk '{print $1}') + + attrs=($(lsattr -p $dir2/$tfile)) + (( ${attrs[0]} == 1001 )) || + error "project ID is not updated after rename" + + (( $inum_before == $inum_after )) || + error "inode is changed after rename: $inum_before, $inum_after" + + sync_all_data || true + + $LFS quota -p 1000 $DIR + $LFS quota -p 1001 $DIR + + local new_used=$(getquota -p 1000 global curspace) + local new_used2=$(getquota -p 1001 global curspace) + + (( $prev_used >= $new_used + 102400 )) || + error "quota is not deducted from old project ID" + (( $prev_used2 <= $new_used2 - 102400 )) || + error "quota is not added for the new project ID" } -run_test 52 "Rename across different project ID" +run_test 52 "Rename normal file across project ID" test_53() { ! is_project_quota_supported && @@ -3486,14 +3887,12 @@ test_53() { setup_quota_test || error "setup quota failed with $?" local dir="$DIR/$tdir/dir" mkdir $dir && change_project -s $dir - lfs project -d $dir | grep P || error "inherit attribute should be set" + [[ $($LFS project -d $dir) =~ " P " ]] || + error "inherit attribute should be set" change_project -C $dir - lfs project -d $dir | grep P && + [[ $($LFS project -d $dir) =~ " - " ]] || error "inherit attribute should be cleared" - - rm -rf $dir - cleanup_quota_test } run_test 53 "Project inherit attribute could be cleared" @@ -3501,7 +3900,6 @@ test_54() { ! is_project_quota_supported && skip "Project quota is not supported" setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT local testfile="$DIR/$tdir/$tfile-0" #set project ID/inherit attribute @@ -3546,8 +3944,6 @@ test_54() { #cleanup unlinkmany ${testfile} 100 || error "unlink many files failed" - - cleanup_quota_test } run_test 54 "basic lfs project interface test" @@ -3589,8 +3985,6 @@ test_55() { error "chgrp should succeed" $LFS quota -v -g $TSTUSR2 $DIR - - cleanup_quota_test } run_test 55 "Chgrp should be affected by group quota" @@ -3608,8 +4002,6 @@ test_56() { $LFS quota -t -u $DIR error "expected grace time: 10s;10s, got:$grace_time" fi - - cleanup_quota_test } run_test 56 "lfs quota -t should work well" @@ -3619,20 +4011,15 @@ test_57() { local dir="$DIR/$tdir/dir" mkdir -p $dir mkfifo $dir/pipe - #try to change pipe file should not hang and return failure - wait_update_facet client "$LFS project -sp 1 $dir/pipe 2>&1 | - awk -F ':' '{ print \\\$2 }'" \ - " unable to get xattr for fifo '$dir/pipe'" || return 1 #command can process further if it hit some errors + $LFS project -sp 1 $dir/pipe touch $dir/aaa $dir/bbb mkdir $dir/subdir -p touch $dir/subdir/aaa $dir/subdir/bbb #create one invalid link file ln -s $dir/not_exist_file $dir/ccc local cnt=$(lfs project -r $dir 2>/dev/null | wc -l) - [ $cnt -eq 5 ] || error "expected 5 got $cnt" - - cleanup_quota_test + [ $cnt -eq 7 ] || error "expected 7 got $cnt" } run_test 57 "lfs project could tolerate errors" @@ -3648,7 +4035,6 @@ test_59() { touch $testfile && lfs project -sp 1 $testfile enable_project_quota - cleanup_quota_test } run_test 59 "lfs project dosen't crash kernel with project disabled" @@ -3656,7 +4042,6 @@ test_60() { [ $MDS1_VERSION -lt $(version_code 2.11.53) ] && skip "Needs MDS version 2.11.53 or later." setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT local testfile=$DIR/$tdir/$tfile local limit=100 @@ -3677,8 +4062,6 @@ test_60() { # root user can overrun quota runas -u 0 -g 0 touch $DIR/$tdir/foo || error "root user should succeed" - - cleanup_quota_test } run_test 60 "Test quota for root with setgid" @@ -3688,7 +4071,7 @@ test_default_quota() { skip "Not supported before 2.11.51." local qtype=$1 - local qpool=$2 + local qres_type=$2 local qid=$TSTUSR local qprjid=$TSTPRJID local qdtype="-U" @@ -3696,6 +4079,7 @@ test_default_quota() { local qh="-B" local LIMIT=20480 #20M disk space local TESTFILE="$DIR/$tdir/$tfile-0" + local $qpool_cmd [ $qtype == "-p" ] && ! is_project_quota_supported && echo "Project quota is not supported" && return 0 @@ -3707,14 +4091,19 @@ test_default_quota() { qid=$qprjid } - [ $qpool == "meta" ] && { + [ $qres_type == "meta" ] && { LIMIT=10240 #10K inodes qs="-i" qh="-I" } + [ ! -z "$3" ] && { + qpool_cmd="--pool $3" + # pool quotas don't work properly without global limit + $LFS setquota $qtype $qid -B1T -b1T $DIR || + error "set global limit failed" + } setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT quota_init @@ -3723,19 +4112,19 @@ test_default_quota() { set_ost_qtype $QTYPE || error "enable ost quota failed" log "set to use default quota" - $LFS setquota $qtype $qid -d $DIR || + $LFS setquota $qtype $qid -d $qpool_cmd $DIR || error "set $qid to use default quota failed" log "set default quota" - $LFS setquota $qdtype $qs ${LIMIT} $qh ${LIMIT} $DIR || + $LFS setquota $qdtype $qpool_cmd $qs ${LIMIT} $qh ${LIMIT} $DIR || error "set $qid default quota failed" log "get default quota" $LFS quota $qdtype $DIR || error "get default quota failed" - if [ $qpool == "data" ]; then - local SLIMIT=$($LFS quota $qdtype $DIR | grep "$MOUNT" | \ - awk '{print $2}') + if [ $qres_type == "data" ]; then + local SLIMIT=$($LFS quota $qpool_cmd $qdtype $DIR | \ + grep "$MOUNT" | awk '{print $2}') [ $SLIMIT -eq $LIMIT ] || error "the returned default quota is wrong" else @@ -3749,13 +4138,14 @@ test_default_quota() { local USED=$(getquota $qtype $qid global curspace) [ $USED -ne 0 ] && error "Used space for $qid isn't 0." - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" + $LFS setstripe $TESTFILE -c 1 $qpool_cmd || + error "setstripe $TESTFILE failed" chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" [ $qtype == "-p" ] && change_project -sp $TSTPRJID $DIR/$tdir log "Test not out of quota" - if [ $qpool == "data" ]; then + if [ $qres_type == "data" ]; then $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 >> 10)) oflag=sync || quota_error $qtype $qid "write failed, expect succeed" else @@ -3770,7 +4160,7 @@ test_default_quota() { cancel_lru_locks osc cancel_lru_locks mdc sync; sync_all_data || true - if [ $qpool == "data" ]; then + if [ $qres_type == "data" ]; then $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync && quota_error $qtype $qid "write succeed, expect EDQUOT" else @@ -3780,15 +4170,24 @@ test_default_quota() { unlinkmany $TESTFILE $((LIMIT*2)) fi + rm -f $TESTFILE + $LFS setstripe $TESTFILE -c 1 $qpool_cmd || + error "setstripe $TESTFILE failed" + chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" + log "Increase default quota" + + # LU-4505: sleep 5 seconds to enable quota acquire + sleep 5 + # increase default quota - $LFS setquota $qdtype $qs $((LIMIT*3)) $qh $((LIMIT*3)) $DIR || - error "set default quota failed" + $LFS setquota $qdtype $qpool_cmd $qs $((LIMIT*3)) \ + $qh $((LIMIT*3)) $DIR || error "set default quota failed" cancel_lru_locks osc cancel_lru_locks mdc sync; sync_all_data || true - if [ $qpool == "data" ]; then + if [ $qres_type == "data" ]; then $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync || quota_error $qtype $qid "write failed, expect succeed" else @@ -3799,13 +4198,13 @@ test_default_quota() { fi log "Set quota to override default quota" - $LFS setquota $qtype $qid $qs ${LIMIT} $qh ${LIMIT} $DIR || + $LFS setquota $qtype $qid $qpool_cmd $qs ${LIMIT} $qh ${LIMIT} $DIR || error "set $qid quota failed" cancel_lru_locks osc cancel_lru_locks mdc sync; sync_all_data || true - if [ $qpool == "data" ]; then + if [ $qres_type == "data" ]; then $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync && quota_error $qtype $qid "write succeed, expect EQUOT" else @@ -3816,13 +4215,17 @@ test_default_quota() { fi log "Set to use default quota again" - $LFS setquota $qtype $qid -d $DIR || + + # LU-4505: sleep 5 seconds to enable quota acquire + sleep 5 + + $LFS setquota $qtype $qid -d $qpool_cmd $DIR || error "set $qid to use default quota failed" cancel_lru_locks osc cancel_lru_locks mdc sync; sync_all_data || true - if [ $qpool == "data" ]; then + if [ $qres_type == "data" ]; then $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync || quota_error $qtype $qid "write failed, expect succeed" else @@ -3836,11 +4239,11 @@ test_default_quota() { rm -f $TESTFILE wait_delete_completed || error "wait_delete_completed failed" sync_all_data || true - $LFS setquota $qdtype -b 0 -B 0 -i 0 -I 0 $DIR || + + $LFS setquota $qdtype $qpool_cmd $qs 0 $qh 0 $DIR || error "reset default quota failed" - $LFS setquota $qtype $qid -b 0 -B 0 -i 0 -I 0 $DIR || + $LFS setquota $qtype $qid $qpool_cmd $qs 0 $qh 0 $DIR || error "reset quota failed" - cleanup_quota_test } @@ -3857,7 +4260,8 @@ run_test 61 "default quota tests" test_62() { ! is_project_quota_supported && skip "Project quota is not supported" - [[ "$(chattr -h 2>&1)" =~ "project" ]] || + [[ "$(chattr -h 2>&1)" =~ "project" || + "$(chattr -h 2>&1)" =~ "pRVf" ]] || skip "chattr did not support project quota" setup_quota_test || error "setup quota failed with $?" local testdir=$DIR/$tdir/ @@ -3874,7 +4278,7 @@ test_62() { chattr -P $testdir || error "root failed to clear inherit" [[ $($LFS project -d $testdir) =~ "P" ]] && error "inherit attribute should be cleared" - cleanup_quota_test + return 0 } run_test 62 "Project inherit should be only changed by root" @@ -3894,7 +4298,6 @@ test_dom() { [ $qtype == "p" ] && qid=$TSTPRJID setup_quota_test || error "setup quota failed with $?" - trap cleanup_quota_test EXIT quota_init @@ -3974,13 +4377,11 @@ test_dom() { $RUNAS $DD of=$DIR/$tdir/file count=$((LIMIT/2048 + 10)) oflag=sync && quota_error $qtype $qid "write succeed, expect EDQUOT" - rm -f $DIR/$tdir/* + rm -fr $DIR/$tdir rm -fr $DIR/$tdir_dom $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR || error "reset usr quota failed" - - cleanup_quota_test } test_63() { @@ -3998,19 +4399,23 @@ test_64() { touch $dir1/file ln -s $dir1/file $dir1/file_link + mkfifo $dir1/fifo - $LFS project -sp $TSTPRJID $dir1/file_link >&/dev/null && - error "set symlink file's project should fail" + $LFS project -srp $TSTPRJID $dir1 >&/dev/null || + error "set project should succeed" - $LFS project $TSTPRJID $dir1/file_link >&/dev/null && - error "get symlink file's project should fail" + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 4 ] || error "expected 4 got $used" + $LFS project -rC $dir1 >&/dev/null || + error "clear project should succeed" - cleanup_quota_test + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 0 ] || error "expected 0 got $used" } -run_test 64 "lfs project on symlink files should fail" +run_test 64 "lfs project on non dir/files should succeed" test_65() { - local SIZE=10 #10M + local SIZE=10 # MB local TESTFILE="$DIR/$tdir/$tfile-0" setup_quota_test || error "setup quota failed with $?" @@ -4028,14 +4433,10 @@ test_65() { local quota_g=$($LFS quota -g $TSTUSR $DIR) local quota_all=$($RUNAS $LFS quota $DIR) - [ "$(echo "$quota_all" | head -n3)" != "$quota_u" ] && + [ "$(echo "$quota_all" | head -n3)" == "$quota_u" ] || error "usr quota not match" - [ "$(echo "$quota_all" | tail -n3)" != "$quota_g" ] && + [ "$(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" @@ -4045,16 +4446,15 @@ test_66() { [ "$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 + stack_trap "do_facet mds1 $LCTL \ + set_param mdt.*.enable_chprojid_gid=$old" EXIT - test_mkdir -i 0 -c 1 $testdir || error "failed to mkdir" + mkdir_on_mdt0 $testdir || error "failed to mkdir" chown -R $TSTID:$TSTID $testdir change_project -sp $TSTPRJID $testdir $RUNAS mkdir $testdir/foo || error "failed to mkdir foo" @@ -4080,8 +4480,6 @@ test_66() { 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" @@ -4124,7 +4522,7 @@ getgranted() { } test_67() { - local limit=20 # 20M + local limit=20 # MB local testfile="$DIR/$tdir/$tfile-0" local testfile2="$DIR/$tdir/$tfile-1" local testfile3="$DIR/$tdir/$tfile-2" @@ -4138,7 +4536,6 @@ test_67() { 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" @@ -4238,11 +4635,8 @@ test_67() { 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 -eq 0 ] || quota_error u $TSTUSR \ "user quota isn't released after deletion" - resetquota -u $TSTUSR - - cleanup_quota_test } run_test 67 "quota pools recalculation" @@ -4251,6 +4645,11 @@ get_slave_nr() { local qtype=$2 local nr + wait_update_facet mds1 \ + "$LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$pool.info \ + >/dev/null 2>&1 || echo foo" "" || + error "mds1: failed to create quota pool $pool" + do_facet mds1 $LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$pool.info | awk '/usr/ {getline; print $2}' } @@ -4261,7 +4660,6 @@ test_68() 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" @@ -4299,24 +4697,21 @@ test_68() # Check again that all is fine with global pool nr=$(get_slave_nr "0x0" "usr") - [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] && + [[ $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 global_limit=200 # MB + local limit=10 # MB 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" @@ -4337,7 +4732,7 @@ test_69() error "set user quota failed" log "User quota (block hardlimit:$limit MB)" - $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR || + $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 || @@ -4364,15 +4759,13 @@ test_69() $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() +test_70a() { local qpool="qpool1" - local limit=20 + local limit=20 # MB local err=0 local bhard @@ -4380,7 +4773,6 @@ test_70() 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 @@ -4389,7 +4781,7 @@ test_70() 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 -o $qpool $DIR + $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR rc=$? [ $rc -eq $err ] || error "setquota res $rc != $err" @@ -4404,14 +4796,770 @@ test_70() $LFS quota -u $TSTUSR --pool $qpool $DIR rc=$? [ $rc -eq $err ] || error "quota res $rc != $err" +} +run_test 70a "check lfs setquota/quota with a pool option" - cleanup_quota_test +test_70b() +{ + local glbl_hard=200 # 200M + local glbl_soft=100 # 100M + local pool_hard=10 # 10M + local qpool="qpool1" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -b ${glbl_soft}M -B ${glbl_hard}M $DIR || + error "set user quota failed" + $LFS setquota -u $TSTUSR -B ${pool_hard}M --pool $qpool $DIR || + error "set user quota failed" + + local tmp=$(getquota -u $TSTUSR global bhardlimit $qpool) + [ $tmp -eq $((pool_hard * 1024)) ] || + error "wrong block hard limit $tmp for $qpool" + local tmp=$(getquota -u $TSTUSR global bsoftlimit $qpool) + # soft limit hasn't been set and should be zero + [ $tmp -eq 0 ] || error "wrong soft block limit $tmp for $qpool" +} +run_test 70b "lfs setquota pool works properly" + +test_71a() +{ + local limit=10 # MB + local global_limit=100 # MB + 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 $?" + + # 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" +} +run_test 71a "Check PFL with quota pools" + +test_71b() +{ + local global_limit=1000 # MB + local limit1=160 # MB + local limit2=10 # MB + 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 $?" + + # 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" + return 0 +} +run_test 71b "Check SEL with quota pools" + +test_72() +{ + local limit=10 # MB + local global_limit=50 # MB + 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 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" + return 0 +} +run_test 72 "lfs quota --pool prints only pool's OSTs" + +test_73a() +{ + local qpool="qpool1" + + mds_supports_qp + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 $((OSTCOUNT - 1)) || + error "pool_add_targets failed" + + test_default_quota "-u" "data" "qpool1" +} +run_test 73a "default limits at OST Pool Quotas" + +test_73b() +{ + local TESTFILE1="$DIR/$tdir/$tfile-1" + local limit=20 #20M + local qpool="qpool1" + + mds_supports_qp + + setup_quota_test || error "setup quota failed with $?" + quota_init + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # pool quotas don't work properly without global limit + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || + error "set global limit failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 $((OSTCOUNT - 1)) || + error "pool_add_targets failed" + + log "set default quota for $qpool" + $LFS setquota -U --pool $qpool -b ${limit}M -B ${limit}M $DIR || + error "set default quota failed" + + log "Write from user that hasn't lqe" + # Check that it doesn't cause a panic or a deadlock + # due to nested lqe lookups that rewrite 1st lqe in qti_lqes array. + # Have to use RUNAS_ID as resetquota creates lqes in + # the beginning for TSTUSR/TSTUSR2 when sets limits to 0. + runas -u $RUNAS_ID -g $RUNAS_GID $DD of=$TESTFILE1 count=10 + + cancel_lru_locks osc + sync; sync_all_data || true +} +run_test 73b "default OST Pool Quotas limit for new user" + +test_74() +{ + local global_limit=200 # 200M + local limit=10 # 10M + local limit2=50 # 50M + local qpool="qpool1" + local qpool2="qpool2" + local tmp=0 + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + $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 ${limit2}M --pool $qpool2 $DIR || + error "set user quota failed" + + tmp=$(getquota -u $TSTUSR global bhardlimit) + [ $tmp -eq $((global_limit * 1024)) ] || + error "wrong global limit $global_limit" + + tmp=$(getquota -u $TSTUSR global bhardlimit $qpool) + [ $tmp -eq $((limit * 1024)) ] || error "wrong limit $tmp for $qpool" + + tmp=$(getquota -u $TSTUSR global bhardlimit $qpool2) + [ $tmp -eq $((limit2 * 1024)) ] || error "wrong limit $tmp for $qpool2" + + # check limits in pools + tmp=$($LFS quota -u $TSTUSR --pool $DIR | \ + grep -A4 $qpool | awk 'NR == 4{print $4}') + echo "pool limit for $qpool $tmp" + [ $tmp -eq $((limit * 1024)) ] || error "wrong limit:tmp for $qpool" + tmp=$($LFS quota -u $TSTUSR --pool $DIR | \ + grep -A4 $qpool2 | awk 'NR == 4{print $4}') + echo "pool limit for $qpool2 $tmp" + [ $tmp -eq $((limit2 * 1024)) ] || error "wrong limit:$tmp for $qpool2" +} +run_test 74 "check quota pools per user" + +function cleanup_quota_test_75() +{ + do_facet mgs $LCTL nodemap_modify --name default \ + --property admin --value 1 + do_facet mgs $LCTL nodemap_modify --name default \ + --property trusted --value 1 + do_facet mgs $LCTL nodemap_modify --name default \ + --property squash_uid --value 99 + do_facet mgs $LCTL nodemap_modify --name default \ + --property squash_gid --value 99 + + wait_nm_sync default admin_nodemap + wait_nm_sync default trusted_nodemap + + do_facet mgs $LCTL nodemap_activate 0 + wait_nm_sync active + + resetquota -u $TSTUSR +} + +test_dom_75() { + local dd_failed=false + local LIMIT=20480 #20M + local qid=$TSTID + + for ((i = 0; i < $((LIMIT/2048-1)); i++)); do + $DD of=$DIR/$tdir_dom/$tfile-$i count=1 \ + oflag=sync || dd_failed=true + done + + $dd_failed && quota_error u $qid "write failed, expect succeed (1)" + + for ((i = $((LIMIT/2048-1)); i < $((LIMIT/1024 + 10)); i++)); do + $DD of=$DIR/$tdir_dom/$tfile-$i count=1 \ + oflag=sync || dd_failed=true + done + + $dd_failed || quota_error u $qid "write succeed, expect EDQUOT (1)" + + rm -f $DIR/$tdir_dom/* + + # flush cache, ensure noquota flag is set on client + cancel_lru_locks + sync; sync_all_data || true + + dd_failed=false + + $DD of=$DIR/$tdir/file count=$((LIMIT/2048-1)) oflag=sync || + quota_error u $qid "write failed, expect succeed (2)" + + for ((i = 0; i < $((LIMIT/2048 + 10)); i++)); do + $DD of=$DIR/$tdir_dom/$tfile-$i count=1 \ + oflag=sync || dd_failed=true + done + + $dd_failed || quota_error u $TSTID "write succeed, expect EDQUOT (2)" + + rm -f $DIR/$tdir/* + rm -f $DIR/$tdir_dom/* + + # flush cache, ensure noquota flag is set on client + cancel_lru_locks + sync; sync_all_data || true + + dd_failed=false + + for ((i = 0; i < $((LIMIT/2048-1)); i++)); do + $DD of=$DIR/$tdir_dom/$tfile-$i count=1 \ + oflag=sync || dd_failed=true + done + + $dd_failed && quota_error u $qid "write failed, expect succeed (3)" + + $DD of=$DIR/$tdir/file count=$((LIMIT/2048 + 10)) oflag=sync && + quota_error u $qid "write succeed, expect EDQUOT (3)" + true +} + +test_75() +{ + local soft_limit=10 # MB + local hard_limit=20 # MB + local limit=$soft_limit + local testfile="$DIR/$tdir/$tfile-0" + local grace=20 # seconds + local tdir_dom=${tdir}_dom + + if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then + grace=60 + fi + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test_75 EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + set_mdt_qtype $QTYPE || error "enable mdt quota failed" + + local used=$(getquota -u $TSTID global curspace) + $LFS setquota -t -u --block-grace $grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set user grace time failed" + $LFS setquota -u $TSTUSR -b $((soft_limit+used/1024))M \ + -B $((hard_limit+used/1024))M -i 0 -I 0 $DIR || + error "set user quota failed" + + chmod 777 $DIR/$tdir || error "chmod 777 $DIR/$tdir failed" + mkdir $DIR/$tdir_dom + chmod 777 $DIR/$tdir_dom + $LFS setstripe -E 1M -L mdt $DIR/$tdir_dom || + error "setstripe $tdir_dom failed" + + do_facet mgs $LCTL nodemap_activate 1 + wait_nm_sync active + do_facet mgs $LCTL nodemap_modify --name default \ + --property admin --value 0 + do_facet mgs $LCTL nodemap_modify --name default \ + --property trusted --value 0 + do_facet mgs $LCTL nodemap_modify --name default \ + --property deny_unknown --value 0 + do_facet mgs $LCTL nodemap_modify --name default \ + --property squash_uid --value $TSTID + do_facet mgs $LCTL nodemap_modify --name default \ + --property squash_gid --value $TSTID + cancel_lru_locks mdc + wait_nm_sync default admin_nodemap + wait_nm_sync default trusted_nodemap + wait_nm_sync default squash_uid + + # mmap write when over soft limit + limit=$soft_limit + $DD of=$testfile count=${limit} || + quota_error a "root write failure, but expect success (1)" + OFFSET=$((limit * 1024)) + cancel_lru_locks osc + + echo "Write to exceed soft limit" + dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || + quota_error a $TSTUSR "root write failure, but expect success (2)" + OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block + cancel_lru_locks osc + + echo "mmap write when over soft limit" + $MULTIOP $testfile.mmap OT40960SMW || + quota_error a $TSTUSR "mmap write failure, but expect success" + cancel_lru_locks osc + rm -f $testfile* + wait_delete_completed || error "wait_delete_completed failed (1)" + sync_all_data || true + + # test for user hard limit + limit=$hard_limit + log "Write..." + $DD of=$testfile bs=1M count=$((limit/2)) || + quota_error u $TSTID \ + "root write failure, but expect success (3)" + + log "Write out of block quota ..." + # possibly a cache write, ignore failure + $DD of=$testfile bs=1M 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 forced cache flush, but did not guarantee that slave + # got new edquot through glimpse, so wait to make sure + sleep 5 + $DD of=$testfile bs=1M count=1 seek=$limit conv=fsync && + quota_error u $TSTID \ + "user write success, but expect EDQUOT" + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed (2)" + sync_all_data || true + [ $(getquota -u $TSTUSR global curspace) -eq $used ] || + quota_error u $TSTID "user quota not released after deletion" + + test_dom_75 +} +run_test 75 "nodemap squashed root respects quota enforcement" + +test_76() { + ! is_project_quota_supported && + skip "skip project quota unsupported" + + setup_quota_test || error "setup quota failed with $?" + quota_init + + local testfile="$DIR/$tdir/$tfile-0" + + touch $testfile + $LFS project -p 4294967295 $testfile && + error "set project ID should fail" + return 0 +} +run_test 76 "project ID 4294967295 should be not allowed" + +test_77() +{ + mount_client $MOUNT2 "ro" + lfs setquota -u quota_usr -b 100M -B 100M -i 10K -I 10K $MOUNT2 && + error "lfs setquota should fail in read-only Lustre mount" + umount $MOUNT2 +} +run_test 77 "lfs setquota should fail in Lustre mount with 'ro'" + +test_78() +{ + (( $OST1_VERSION >= $(version_code 2.14.55) )) || + skip "need OST at least 2.14.55" + check_set_fallocate_or_skip + + setup_quota_test || error "setup quota failed with $?" + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + mkdir -p $DIR/$tdir || error "failed to create $tdir" + chown $TSTUSR $DIR/$tdir || error "failed to chown $tdir" + + # setup quota limit + $LFS setquota -u $TSTUSR -b25M -B25M $DIR/$tdir || + error "lfs setquota failed" + + # call fallocate + runas -u $TSTUSR -g $TSTUSR fallocate -l 204800 $DIR/$tdir/$tfile + + kbytes=$(lfs quota -u $TSTUSR $DIR | + awk -v pattern=$DIR 'match($0, pattern) {printf $2}') + echo "kbytes returned:$kbytes" + + # For file size of 204800. We should be having roughly 200 kbytes + # returned. Anything alarmingly low (50 taken as arbitrary value) + # would bail out this TC. Also this also avoids $kbytes of 0 + # to be used in calculation below. + (( $kbytes > 50 )) || + error "fallocate did not use quota. kbytes returned:$kbytes" + + local expect_lo=$(($kbytes * 95 / 100)) # 5% below + local expect_hi=$(($kbytes * 105 / 100)) # 5% above + + # Verify kbytes is 200 (204800/1024). With a permited 5% drift + (( $kbytes >= $expect_lo && $kbytes <= $expect_hi )) || + error "fallocate did not use quota correctly" +} +run_test 78 "Check fallocate increase quota usage" + +test_78a() +{ + (( $CLIENT_VERSION >= $(version_code 2.15.0) )) || + skip "need client at least 2.15.0" + (( $OST1_VERSION >= $(version_code 2.15.0) )) || + skip "need OST at least 2.15.0" + check_set_fallocate_or_skip + + setup_quota_test || error "setup quota failed with $?" + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + mkdir -p $DIR/$tdir || error "failed to create $tdir" + + local projectid=5200 # Random project id to test + + change_project -sp $projectid $DIR/$tdir + + # setup quota limit + $LFS setquota -p $projectid -b25M -B25M $DIR/$tdir || + error "lfs setquota project failed" + + # call fallocate + fallocate -l 204800 $DIR/$tdir/$tfile + + # Get curspace (kbytes) for $projectid + local kbytes=$(getquota -p $projectid global curspace) + + echo "kbytes returned:$kbytes" + + # For file size of 204800. We should be having roughly 200 kbytes + # returned. Anything alarmingly low (50 taken as arbitrary value) + # would bail out this TC. Also this also avoids $kbytes of 0 + # to be used in calculation below. + (( $kbytes > 50 )) || + error "fallocate did not use projectid. kbytes returned:$kbytes" + + local expect_lo=$(($kbytes * 95 / 100)) # 5% below + local expect_hi=$(($kbytes * 105 / 100)) # 5% above + + # Verify kbytes is 200 (204800/1024). With a permited 5% drift + (( $kbytes >= $expect_lo && $kbytes <= $expect_hi )) || + error "fallocate did not use quota projectid correctly" +} +run_test 78a "Check fallocate increase projectid usage" + +test_79() +{ + local qpool="qpool1" + local cmd="$LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$qpool.info" + local stopf=$TMP/$tfile + + do_facet mds1 "touch $stopf" + stack_trap "do_facet mds1 'rm -f $stopf'" + do_facet mds1 "while [ -e $stopf ]; do $cmd &>/dev/null; done"& + local pid=$! + pool_add $qpool || error "pool_add failed" + do_facet mds1 "rm $stopf" + wait $pid +} +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" + +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_82() +{ + (( $MDS1_VERSION >= $(version_code 2.14.55) )) || + skip "need MDS 2.14.55 or later" + is_project_quota_supported || + skip "skip project quota unsupported" + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test + quota_init + + local parent_dir="$DIR/$tdir.parent" + local child_dir="$parent_dir/child" + + mkdir -p $child_dir + stack_trap "chown -R 0:0 $parent_dir" + + chown $TSTUSR:$TSTUSR $parent_dir || + error "failed to chown on $parent_dir" + chown $TSTUSR2:$TSTUSRS2 $child_dir || + error "failed to chown on $parent_dir" + + $LFS project -p 1000 $parent_dir || + error "failed to set project id on $parent_dir" + $LFS project -p 1001 $child_dir || + error "failed to set project id on $child_dir" + + rmdir $child_dir || error "cannot remove child dir, test failed" } -run_test 70 "check lfs setquota/quota with a pool option" +run_test 82 "verify more than 8 qids for single operation" quota_fini() { - do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota" + do_nodes $(comma_list $(nodes_list)) \ + "lctl set_param -n debug=-quota,trace" if $PQ_CLEANUP; then disable_project_quota fi