X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Ftests%2Fsanity-quota.sh;h=36aebe0b1a70c125a1b787252a06690693423790;hp=46890181202cc222ec86a3fb98716f0e7982937e;hb=e8a7386e143097456c473533df1064099c430271;hpb=9fb6818fe3d1e0130e147c5cf740e5e9a2631166 diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 4689018..36aebe0 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -39,6 +39,12 @@ BLK_SZ=1024 MAX_DQ_TIME=604800 MAX_IQ_TIME=604800 QTYPE="ugp" +# QP exists since this version. Should be finally set before landing. +VERSION_WITH_QP="2.13.53" +mds_supports_qp() { + [ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ] && + skip "Needs MDS version $VERSION_WITH_QP or later." +} require_dsh_mds || exit 0 require_dsh_ost || exit 0 @@ -161,14 +167,17 @@ quota_log() { # get quota for a user or a group # usage: getquota -u|-g|-p || global| \ -# bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace +# bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace \ +# getquota() { local spec local uuid + local pool_arg sync_all_data > /dev/null 2>&1 || true - [ "$#" != 4 ] && error "getquota: wrong number of arguments: $#" + [ "$#" != 4 -a "$#" != 5 ] && + error "getquota: wrong number of arguments: $#" [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] && error "getquota: wrong u/g/p specifier $1 passed" @@ -186,9 +195,10 @@ getquota() { *) error "unknown quota parameter $4";; esac + [ ! -z "$5" ] && pool_arg="--pool $5 " [ "$uuid" = "global" ] && uuid=$DIR - $LFS quota -v "$1" "$2" $DIR | + $LFS quota -v "$1" "$2" $pool_arg $DIR | awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") \ { if (NF == 1) { getline } else { num++ } ; print $num;} }' \ | tr -d "*" @@ -325,8 +335,10 @@ wait_ost_reint() { wait_grace_time() { local qtype=$1 local flavour=$2 - local extrasleep=${3:-5} + local pool=${3:-} + local extrasleep=${4:-5} local qarg + local parg case $qtype in u|g) qarg=$TSTUSR ;; @@ -334,9 +346,15 @@ wait_grace_time() { *) error "get_grace_time: Invalid quota type: $qtype" esac + if [ $pool ]; then + parg="--pool "$pool + echo "Quota info for $pool:" + $LFS quota -$qtype $qarg $parg $DIR + fi + case $flavour in block) - time=$(lfs quota -$qtype $qarg $DIR| + time=$(lfs quota -$qtype $qarg $parg $DIR| awk 'NR == 3{ print $5 }'| sed 's/s$//') ;; file) @@ -348,6 +366,14 @@ wait_grace_time() { ;; esac + # from lfs.c:__sec2str() + # const char spec[] = "smhdw"; + # {1, 60, 60*60, 24*60*60, 7*24*60*60}; + [[ $time == *m* ]] && time=${time//m/} && time=$((time*60)); + [[ $time == *h* ]] && time=${time//h/} && time=$((time*60*60)); + [[ $time == *d* ]] && time=${time//d/} && time=$((time*24*60*60)); + [[ $time == *w* ]] && time=${time//w/} && time=$((time*7*24*60*60)); + echo "Sleep through grace ..." [ "$time" == "-" ] && error "Grace timeout was not set or quota not exceeded" @@ -371,7 +397,6 @@ setup_quota_test() { } cleanup_quota_test() { - trap 0 echo "Delete files..." rm -rf $DIR/$tdir echo "Wait for unlink objects finished..." @@ -451,7 +476,7 @@ reset_quota_settings() { # enable quota debug quota_init() { - do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota" + do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota+trace" } quota_init reset_quota_settings @@ -507,10 +532,36 @@ test_0() { } run_test 0 "Test basic quota performance" +# usage: test_1_check_write tfile user|group|project +test_1_check_write() { + local testfile="$1" + local qtype="$2" + local limit=$3 + local short_qtype=${qtype:0:1} + + log "Write..." + $RUNAS $DD of=$testfile count=$((limit/2)) || + quota_error $short_qtype $TSTUSR \ + "$qtype write failure, but expect success" + log "Write out of block quota ..." + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((limit/2)) seek=$((limit/2)) || true + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + # sync means client wrote all it's cache, but id doesn't + # garantee that slave got new edquot trough glimpse. + # so wait a little to be sure slave got it. + sleep 5 + $RUNAS $DD of=$testfile count=1 seek=$limit && + quota_error $short_qtype $TSTUSR \ + "user write success, but expect EDQUOT" +} + # test block hardlimit -test_1() { - local LIMIT=10 # 10M - local TESTFILE="$DIR/$tdir/$tfile-0" +test_1a() { + local limit=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" setup_quota_test || error "setup quota failed with $?" trap cleanup_quota_test EXIT @@ -519,66 +570,47 @@ test_1() { set_ost_qtype $QTYPE || error "enable ost quota failed" # test for user - log "User quota (block hardlimit:$LIMIT MB)" - $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set user quota failed" # make sure the system is clean - local USED=$(getquota -u $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0." + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" - log "Write..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || - quota_error u $TSTUSR "user write failure, but expect success" - log "Write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - # flush cache, ensure noquota flag is set on client - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=1 seek=$LIMIT && - quota_error u $TSTUSR "user write success, but expect EDQUOT" + test_1_check_write $testfile "user" $limit - rm -f $TESTFILE + rm -f $testfile wait_delete_completed || error "wait_delete_completed failed" sync_all_data || true - USED=$(getquota -u $TSTUSR global curspace) - [ $USED -ne 0 ] && quota_error u $TSTUSR \ + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ "user quota isn't released after deletion" resetquota -u $TSTUSR # test for group log "--------------------------------------" - log "Group quota (block hardlimit:$LIMIT MB)" - $LFS setquota -g $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "Group quota (block hardlimit:$limit MB)" + $LFS setquota -g $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set group quota failed" - TESTFILE="$DIR/$tdir/$tfile-1" + testfile="$DIR/$tdir/$tfile-1" # make sure the system is clean - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTUSR isn't 0" + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0" - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" - log "Write ..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || - quota_error g $TSTUSR "Group write failure, but expect success" - log "Write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT && - quota_error g $TSTUSR "Group write success, but expect EDQUOT" - rm -f $TESTFILE + test_1_check_write $testfile "group" $limit + rm -f $testfile wait_delete_completed || error "wait_delete_completed failed" sync_all_data || true - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && quota_error g $TSTUSR \ + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error g $TSTUSR \ "Group quota isn't released after deletion" resetquota -g $TSTUSR @@ -588,48 +620,397 @@ test_1() { return 0 fi - TESTFILE="$DIR/$tdir/$tfile-2" + testfile="$DIR/$tdir/$tfile-2" # make sure the system is clean - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -ne 0 ] && - error "used space($USED) for project $TSTPRJID isn't 0" + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && + error "used space($used) for project $TSTPRJID isn't 0" # test for Project log "--------------------------------------" - log "Project quota (block hardlimit:$LIMIT mb)" - $LFS setquota -p $TSTPRJID -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR || + log "Project quota (block hardlimit:$limit mb)" + $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M -i 0 -I 0 $DIR || error "set project quota failed" - $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed" - chown $TSTUSR:$TSTUSR $TESTFILE || error "chown $TESTFILE failed" - change_project -p $TSTPRJID $TESTFILE - - log "write ..." - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || quota_error p $TSTPRJID \ - "project write failure, but expect success" - log "write out of block quota ..." - # this time maybe cache write, ignore it's failure - $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true - cancel_lru_locks osc - sync; sync_all_data || true - $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT && quota_error p \ - $TSTPRJID "project write success, but expect EDQUOT" + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed" + change_project -p $TSTPRJID $testfile + + test_1_check_write $testfile "project" $limit # cleanup cleanup_quota_test - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -eq 0 ] || quota_error p $TSTPRJID \ + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && quota_error p $TSTPRJID \ "project quota isn't released after deletion" + + resetquota -p $TSTPRJID } -run_test 1 "Block hard limit (normal use and out of quota)" +run_test 1a "Block hard limit (normal use and out of quota)" + +test_1b() { + local limit=10 # 10M + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "user" $limit + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # test for group + log "--------------------------------------" + log "Group quota (block hardlimit:$global_limit MB)" + $LFS setquota -g $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set group quota failed" + + $LFS setquota -g $TSTUSR -b 0 -B ${limit}M -o $qpool $DIR || + error "set group quota failed" + + testfile="$DIR/$tdir/$tfile-1" + # make sure the system is clean + used=$(getquota -g $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0" + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "group" $limit + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -g $TSTUSR global curspace $qpool) + [ $used -ne 0 ] && quota_error g $TSTUSR \ + "Group quota isn't released after deletion" + resetquota -g $TSTUSR + + if ! is_project_quota_supported; then + echo "Project quota is not supported" + cleanup_quota_test + return 0 + fi + + testfile="$DIR/$tdir/$tfile-2" + # make sure the system is clean + used=$(getquota -p $TSTPRJID global curspace $qpool) + [ $used -ne 0 ] && + error "used space($used) for project $TSTPRJID isn't 0" + + # test for Project + log "--------------------------------------" + log "Project quota (block hardlimit:$global_limit mb)" + $LFS setquota -p $TSTPRJID -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set project quota failed" + + $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M -o $qpool $DIR || + error "set project quota failed" + + + $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed" + chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed" + change_project -p $TSTPRJID $testfile + + test_1_check_write $testfile "project" $limit + + # cleanup + cleanup_quota_test + + used=$(getquota -p $TSTPRJID global curspace) + [ $used -eq 0 ] || quota_error p $TSTPRJID \ + "project quota isn't released after deletion" +} +run_test 1b "Quota pools: Block hard limit (normal use and out of quota)" + +test_1c() { + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool1="qpool1" + local qpool2="qpool2" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + # create pools without hard limit + # initially such case raised several bugs + $LFS setquota -u $TSTUSR -B 0M -o $qpool1 $DIR || + error "set user quota failed" + + $LFS setquota -u $TSTUSR -B 0M -o $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + test_1_check_write $testfile "user" $global_limit + + used=$(getquota -u $TSTUSR global curspace $qpool1) + echo "qpool1 used $used" + used=$(getquota -u $TSTUSR global curspace $qpool2) + echo "qpool2 used $used" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1c "Quota pools: check 3 pools with hardlimit only for global" + +test_1d() { + local limit1=10 # 10M + local limit2=12 # 12M + local global_limit=20 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool1="qpool1" + local qpool2="qpool2" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + error "set user quota failed" + + $LFS setquota -u $TSTUSR -B ${limit2}M -o $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + echo "used $used" + [ $used -ne 0 ] && error "used space($used) for user $TSTUSR isn't 0." + + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + test_1_check_write $testfile "user" $limit1 + + used=$(getquota -u $TSTUSR global curspace $qpool1) + echo "qpool1 used $used" + used=$(getquota -u $TSTUSR global curspace $qpool2) + echo "qpool2 used $used" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1d "Quota pools: check block hardlimit on different pools" + +test_1e() { + local limit1=10 # 10M + local global_limit=200 # 200M + local testfile="$DIR/$tdir/$tfile-0" + local testfile2="$DIR/$tdir/$tfile-1" + local qpool1="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # global_limit is much greater than limit1 to get + # different qunit's on osts. Since 1st qunit shrinking + # on OST1(that belongs to qpool1), this qunit should + # be sent to OST1. + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 1 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + $LFS setstripe $testfile -c 1 -i 1 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + test_1_check_write $testfile "user" $limit1 + + $LFS setstripe $testfile2 -c 1 -i 0 || + error "setstripe $testfile2 failed" + chown $TSTUSR.$TSTUSR $testfile2 || error "chown $testfile2 failed" + # Now write to file with a stripe on OST0, that doesn't belong to qpool1 + log "Write..." + $RUNAS $DD of=$testfile2 count=20 || + quota_error $short_qtype $TSTUSR \ + "$qtype write failure, but expect success" + + rm -f $testfile + rm -f $testfile2 + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + used=$(getquota -u $TSTUSR global curspace $qpool1) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + # cleanup + cleanup_quota_test +} +run_test 1e "Quota pools: global pool high block limit vs quota pool with small" + +test_1f() { + local global_limit=200 # 200M + local limit1=10 # 10M + local TESTDIR="$DIR/$tdir/" + local testfile="$TESTDIR/$tfile-0" + local qpool1="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool1 || error "pool_add failed" + pool_add_targets $qpool1 0 0 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + $LFS setstripe $TESTDIR -c 1 -i 0 || error "setstripe $TESTDIR failed" + + test_1_check_write $testfile "user" $limit1 + + pool_remove_target $qpool1 0 + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + + pool_add_targets $qpool1 0 0 || error "pool_add_targets failed" + # qunit for appropriate element in lgd array should be set + # correctly(4096). Earlier it was not changed continuing to be 1024. + # This caused write to hung when it hit limit1 - qunit shrinking to 1024 + # for qpool1 lqe didn't cause changing qunit for OST0 in gld array + # as it already was 1024. As flag "need_update" for this qunit was + # not set, new qunit wasn't sent to OST0. Thus revoke was not set + # for "qpool1" lqe and it couldn't set EDQUOT despite granted + # became > 10M. QMT returned EINPROGRESS in a loop. + # Check that it doesn't hung anymore. + test_1_check_write $testfile "user" $limit1 + + # cleanup + cleanup_quota_test +} +run_test 1f "Quota pools: correct qunit after removing/adding OST" # test inode hardlimit test_2() { - local LIMIT=$((1024 * 1024)) # 1M inodes local TESTFILE="$DIR/$tdir/$tfile-0" + local LIMIT=$(do_facet mds1 $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.md-0x0.info | + awk '/least qunit/{ print $3 }') + local L2=$(do_facet mds1 $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.md-0x0.soft_least_qunit) - [ "$SLOW" = "no" ] && LIMIT=1024 # 1k inodes + [ $L2 -le $LIMIT ] || LIMIT=$L2 + + [ "$SLOW" = "no" ] || LIMIT=$((LIMIT * 1024)) local FREE_INODES=$(mdt_free_inodes 0) echo "$FREE_INODES free inodes on master MDT" @@ -729,32 +1110,38 @@ test_2() { run_test 2 "File hard limit (normal use and out of quota)" test_block_soft() { - local TESTFILE=$1 - local GRACE=$2 - local LIMIT=$3 + local testfile=$1 + local grace=$2 + local limit=$3 local OFFSET=0 local qtype=$4 + local pool=$5 setup_quota_test - trap cleanup_quota_test EXIT + stack_trap cleanup_quota_test EXIT - $LFS setstripe $TESTFILE -c 1 -i 0 - chown $TSTUSR.$TSTUSR $TESTFILE + $LFS setstripe $testfile -c 1 -i 0 + chown $TSTUSR.$TSTUSR $testfile [ "$qtype" == "p" ] && is_project_quota_supported && - change_project -p $TSTPRJID $TESTFILE + change_project -p $TSTPRJID $testfile echo "Write up to soft limit" - $RUNAS $DD of=$TESTFILE count=$LIMIT || + $RUNAS $DD of=$testfile count=$limit || quota_error a $TSTUSR "write failure, but expect success" - OFFSET=$((LIMIT * 1024)) + OFFSET=$((limit * 1024)) cancel_lru_locks osc echo "Write to exceed soft limit" - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || quota_error a $TSTUSR "write failure, but expect success" OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block cancel_lru_locks osc + echo "mmap write when over soft limit" + $RUNAS $MULTIOP $testfile.mmap OT40960SMW || + quota_error a $TSTUSR "mmap write failure, but expect success" + cancel_lru_locks osc + $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP $SHOW_QUOTA_PROJID @@ -763,12 +1150,12 @@ test_block_soft() { $SHOW_QUOTA_INFO_PROJID echo "Write before timer goes off" - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || quota_error a $TSTUSR "write failure, but expect success" OFFSET=$((OFFSET + 1024)) cancel_lru_locks osc - wait_grace_time $qtype "block" + wait_grace_time $qtype "block" $pool $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP @@ -777,12 +1164,13 @@ test_block_soft() { $SHOW_QUOTA_INFO_GROUP $SHOW_QUOTA_INFO_PROJID - echo "Write after timer goes off" + log "Write after timer goes off" # maybe cache write, ignore. - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || true + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || true OFFSET=$((OFFSET + 1024)) cancel_lru_locks osc - $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET && + log "Write after cancel lru locks" + $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET && quota_error a $TSTUSR "write success, but expect EDQUOT" $SHOW_QUOTA_USER @@ -793,7 +1181,7 @@ test_block_soft() { $SHOW_QUOTA_INFO_PROJID echo "Unlink file to stop timer" - rm -f $TESTFILE + rm -f $testfile wait_delete_completed sync_all_data || true @@ -804,71 +1192,71 @@ test_block_soft() { $SHOW_QUOTA_INFO_GROUP $SHOW_QUOTA_INFO_PROJID - $LFS setstripe $TESTFILE -c 1 -i 0 - chown $TSTUSR.$TSTUSR $TESTFILE - [ "$qtype" == "p" ] && change_project -p $TSTPRJID $TESTFILE + $LFS setstripe $testfile -c 1 -i 0 + chown $TSTUSR.$TSTUSR $testfile + [ "$qtype" == "p" ] && change_project -p $TSTPRJID $testfile echo "Write ..." - $RUNAS $DD of=$TESTFILE count=$LIMIT || + $RUNAS $DD of=$testfile count=$limit || quota_error a $TSTUSR "write failure, but expect success" # cleanup cleanup_quota_test } # block soft limit -test_3() { - local GRACE=20 # 20s +test_3a() { + local grace=20 # 20s if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then - GRACE=60 + grace=60 fi - local TESTFILE=$DIR/$tdir/$tfile-0 + local testfile=$DIR/$tdir/$tfile-0 # get minimum soft qunit size - local LIMIT=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) set_ost_qtype $QTYPE || error "enable ost quota failed" - echo "User quota (soft limit:$LIMIT MB grace:$GRACE seconds)" + echo "User quota (soft limit:$limit MB grace:$grace seconds)" # make sure the system is clean - local USED=$(getquota -u $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0." + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." - $LFS setquota -t -u --block-grace $GRACE --inode-grace \ + $LFS setquota -t -u --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set user grace time failed" - $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR || + $LFS setquota -u $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR || error "set user quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "u" + test_block_soft $testfile $grace $limit "u" - echo "Group quota (soft limit:$LIMIT MB grace:$GRACE seconds)" - TESTFILE=$DIR/$tdir/$tfile-1 + echo "Group quota (soft limit:$limit MB grace:$grace seconds)" + testfile=$DIR/$tdir/$tfile-1 # make sure the system is clean - USED=$(getquota -g $TSTUSR global curspace) - [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0." + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0." - $LFS setquota -t -g --block-grace $GRACE --inode-grace \ + $LFS setquota -t -g --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set group grace time failed" - $LFS setquota -g $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR || + $LFS setquota -g $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR || error "set group quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "g" + test_block_soft $testfile $grace $limit "g" if is_project_quota_supported; then - echo "Project quota (soft limit:$LIMIT MB grace:$GRACE sec)" - TESTFILE=$DIR/$tdir/$tfile-2 + echo "Project quota (soft limit:$limit MB grace:$grace sec)" + testfile=$DIR/$tdir/$tfile-2 # make sure the system is clean - USED=$(getquota -p $TSTPRJID global curspace) - [ $USED -ne 0 ] && error \ - "Used space($USED) for project $TSTPRJID isn't 0." + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && error \ + "Used space($used) for project $TSTPRJID isn't 0." - $LFS setquota -t -p --block-grace $GRACE --inode-grace \ + $LFS setquota -t -p --block-grace $grace --inode-grace \ $MAX_IQ_TIME $DIR || error "set project grace time failed" - $LFS setquota -p $TSTPRJID -b ${LIMIT}M -B 0 -i 0 -I 0 \ + $LFS setquota -p $TSTPRJID -b ${limit}M -B 0 -i 0 -I 0 \ $DIR || error "set project quota failed" - test_block_soft $TESTFILE $GRACE $LIMIT "p" + test_block_soft $testfile $grace $limit "p" resetquota -p $TSTPRJID $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \ $MAX_IQ_TIME $DIR || @@ -881,7 +1269,172 @@ test_3() { $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \ $MAX_IQ_TIME $DIR || error "restore group grace time failed" } -run_test 3 "Block soft limit (start timer, timer goes off, stop timer)" +run_test 3a "Block soft limit (start timer, timer goes off, stop timer)" + +test_3b() { + local grace=20 # 20s + local qpool="qpool1" + if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then + grace=60 + fi + local testfile=$DIR/$tdir/$tfile-0 + + mds_supports_qp + # get minimum soft qunit size + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) + local glbl_limit=$((2*limit)) + local glbl_grace=$((2*grace)) + echo "limit $limit glbl_limit $glbl_limit" + echo "grace $grace glbl_grace $glbl_grace" + + set_ost_qtype $QTYPE || error "enable ost quota failed" + + echo "User quota in $qpool(soft limit:$limit MB grace:$grace seconds)" + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace \ + -o $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 || + error "set user quota failed" + + test_block_soft $testfile $grace $limit "u" $qpool + + echo "Group quota in $qpool(soft limit:$limit MB grace:$grace seconds)" + testfile=$DIR/$tdir/$tfile-1 + # make sure the system is clean + used=$(getquota -g $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0." + + $LFS setquota -t -g --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set group grace time failed" + $LFS setquota -t -g --block-grace $grace \ + -o $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 || + error "set group quota failed" + + test_block_soft $testfile $grace $limit "g" $qpool + + if is_project_quota_supported; then + echo "Project quota in $qpool(soft:$limit MB grace:$grace sec)" + testfile=$DIR/$tdir/$tfile-2 + # make sure the system is clean + used=$(getquota -p $TSTPRJID global curspace) + [ $used -ne 0 ] && error \ + "Used space($used) for project $TSTPRJID isn't 0." + + $LFS setquota -t -p --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || + error "set project grace time failed" + $LFS setquota -t -p --block-grace $grace \ + -o $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" + + 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" + 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" + $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" +} +run_test 3b "Quota pools: Block soft limit (start timer, expires, stop timer)" + +test_3c() { + local grace=20 # 20s + local qpool="qpool1" + local qpool2="qpool2" + if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then + grace=60 + fi + local testfile=$DIR/$tdir/$tfile-0 + + mds_supports_qp + # get minimum soft qunit size + local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \ + qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 )) + local limit2=$((limit+4)) + local glbl_limit=$((limit+8)) + local grace1=$((grace+10)) + local grace2=$grace + local glbl_grace=$((grace+20)) + echo "limit $limit limit2 $limit2 glbl_limit $glbl_limit" + echo "grace1 $grace1 grace2 $grace2 glbl_grace $glbl_grace" + + set_ost_qtype $QTYPE || error "enable ost quota failed" + + echo "User quota in qpool2(soft:$limit2 MB grace:$grace2 seconds)" + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + pool_add $qpool2 || error "pool_add failed" + pool_add_targets $qpool2 0 1 || + error "pool_add_targets failed" + + + $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \ + $MAX_IQ_TIME $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace1 \ + -o $qpool $DIR || error "set user grace time failed" + $LFS setquota -t -u --block-grace $grace2 \ + -o $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 || + error "set user quota failed" + # qpool has minimum soft limit, but it's grace is grater than + # grace period of qpool2. Thus write shouldn't fail when + # hit qpool soft limit - only when reaches up qpool2 limit + # after grace2 seconds. + $LFS setquota -u $TSTUSR -b ${limit2}M -B 0 -o $qpool2 $DIR || + error "set user quota failed" + + test_block_soft $testfile $grace2 $limit2 "u" $qpool2 + + # cleanup + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \ + $MAX_IQ_TIME $DIR || error "restore user grace time failed" + $LFS setquota -t -u --block-grace $MAX_DQ_TIME \ + -o $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" +} +run_test 3c "Quota pools: check block soft limit on different pools" test_file_soft() { local TESTFILE=$1 @@ -3489,6 +4042,8 @@ run_test 65 "Check lfs quota result" test_66() { ! is_project_quota_supported && skip "Project quota is not supported" + [ "$MDS1_VERSION" -lt $(version_code 2.12.4) ] && + skip "Not supported before 2.12.4" setup_quota_test || error "setup quota failed with $?" stack_trap cleanup_quota_test EXIT local old=$(do_facet mds1 $LCTL get_param -n \ @@ -3530,6 +4085,481 @@ test_66() { } run_test 66 "nonroot user can not change project state in default" +test_67_write() { + local file="$1" + local qtype="$2" + local size=$3 + local _runas="" + local short_qtype=${qtype:0:1} + + echo "file "$file + echo "0 $0 1 $1 2 $2 3 $3 4 $4" + case "$4" in + quota_usr) _runas=$RUNAS;; + quota_2usr) _runas=$RUNAS2;; + *) error "unknown quota parameter $4";; + esac + + log "Write..." + date + $_runas $DD of=$file count=$size || + quota_error $short_qtype $TSTUSR \ + "$qtype write failure, but expect success" + date + cancel_lru_locks osc + date + sync; sync_all_data || true + date +} + +getgranted() { + local pool=$1 + local ptype=$2 + local userid=$3 + local qtype=$4 + local param=qmt.$FSNAME-QMT0000.$ptype-$pool.glb-$qtype + + do_facet mds1 $LCTL get_param $param | + grep -A2 $userid | awk -F'[, ]*' 'NR==2{print $9}' +} + +test_67() { + local limit=20 # 20M + local testfile="$DIR/$tdir/$tfile-0" + local testfile2="$DIR/$tdir/$tfile-1" + local testfile3="$DIR/$tdir/$tfile-2" + local qpool="qpool1" + local used + local granted + local granted_mb + + mds_supports_qp + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + + setup_quota_test || error "setup quota failed with $?" + trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + # make sure the system is clean + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + granted=$(getgranted "0x0" "dt" $TSTID "usr") + echo "granted 0x0 before write $granted" + + # trigger reintegration + local procf="osd-$(facet_fstype ost1).$FSNAME-OST*." + procf=${procf}quota_slave.force_reint + do_facet ost1 $LCTL set_param $procf=1 || + error "force reintegration failed" + wait_ost_reint "u" || error "reintegration failed" + granted=$(getgranted "0x0" "dt" $TSTID "usr") + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR in $qpool isn't 0." + + $LFS setstripe $testfile -c 1 -i 0 || error "setstripe $testfile failed" + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # write 10 MB to testfile + test_67_write "$testfile" "user" 10 "quota_usr" + + # create qpool and add OST1 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 1 1 || error "pool_add_targets failed" + # as quota_usr hasn't limits, lqe may absent. But it should be + # created after the 1st direct qmt_get. + used=$(getquota -u $TSTUSR global bhardlimit $qpool) + + # check granted - should be 0, as testfile is located only on OST0 + granted=$(getgranted "0x0" "dt" $TSTID "usr") + echo "global granted $granted" + granted=$(getgranted $qpool "dt" $TSTID "usr") + echo "$qpool granted $granted" + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR in $qpool isn't 0." + + # add OST0 to qpool and check granted space + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024)) + echo "Granted $granted_mb MB" + #should be 10M + qunit for each OST + [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] || + error "Granted($granted_mb) for $TSTUSR in $qpool is wrong." + + $LFS setstripe $testfile2 -c 1 -i 1 || + error "setstripe $testfile2 failed" + chown $TSTUSR2.$TSTUSR2 $testfile2 || error "chown $testfile2 failed" + # Write from another user and check that qpool1 + # shows correct granted, despite quota_2usr hasn't limits in qpool1. + test_67_write "$testfile2" "user" 10 "quota_2usr" + used=$(getquota -u $TSTUSR2 global curspace $qpool) + granted=$(getgranted $qpool "dt" $TSTID2 "usr") + [ $granted -ne 0 ] && + error "Granted($granted) for $TSTUSR2 in $qpool isn't 0." + + # Granted space for quota_2usr in qpool1 should appear only + # when global lqe for this user becomes enforced. + $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR || + error "set user quota failed" + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + echo "granted_mb $granted_mb" + [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] || + error "Granted($granted) for $TSTUSR in $qpool is wrong." + + $LFS setstripe $testfile3 -c 1 -i 0 || + error "setstripe $testfile3 failed" + chown $TSTUSR2.$TSTUSR2 $testfile3 || error "chown $testfile3 failed" + test_67_write "$testfile3" "user" 10 "quota_2usr" + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + echo "$testfile3 granted_mb $granted_mb" + [ $granted_mb -eq $limit ] || + error "Granted($granted_mb) for $TSTUSR2 is not equal to 20M" + + # remove OST1 from the qpool1 and check granted space + # should be 0 for TSTUSR and 10M for TSTUSR2 + pool_remove_target $qpool 0 + granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024)) + [ $granted_mb -eq 0 ] || + error "Granted($granted_mb) for $TSTUSR in $qpool != 0." + granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024)) + [ $granted_mb -eq 10 ] || + error "Granted($granted_mb) for $TSTUSR2 is not equal to 10M" + + rm -f $testfile + wait_delete_completed || error "wait_delete_completed failed" + sync_all_data || true + used=$(getquota -u $TSTUSR global curspace) + [ $used -ne 0 ] && quota_error u $TSTUSR \ + "user quota isn't released after deletion" + resetquota -u $TSTUSR + + cleanup_quota_test +} +run_test 67 "quota pools recalculation" + +get_slave_nr() { + local pool=$1 + local qtype=$2 + local nr + + do_facet mds1 $LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$pool.info | + awk '/usr/ {getline; print $2}' +} + +test_68() +{ + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # check slave number for glbal pool + local nr=$(get_slave_nr "0x0" "usr") + echo "nr result $nr" + [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] && + error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)" + + # create qpool and add OST1 + pool_add $qpool || error "pool_add failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0" + + # add OST1 to qpool + pool_add_targets $qpool 1 1 || error "pool_add_targets failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1" + + # add OST0 to qpool + pool_add_targets $qpool 0 1 || error "pool_add_targets failed" + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 2 ]] && error "Slave number $nr for $qpool != 2" + + # remove OST0 + pool_remove_target $qpool 0 + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1" + + # remove OST1 + pool_remove_target $qpool 1 + nr=$(get_slave_nr $qpool "usr") + [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0" + + # Check again that all is fine with global pool + nr=$(get_slave_nr "0x0" "usr") + [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] && + error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)" + + cleanup_quota_test +} +run_test 68 "slave number in quota pool changed after each add/remove OST" + +test_69() +{ + local global_limit=200 # 200M + local limit=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" + local dom0="$DIR/$tdir/dom0" + local qpool="qpool1" + + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + set_mdt_qtype $QTYPE || error "enable mdt quota failed" + + # Save DOM only at MDT0 + $LFS setdirstripe -c 1 -i 0 $dom0 || error "cannot create $dom0" + $LFS setstripe -E 1M $dom0 -L mdt || error "setstripe to $dom0 failed" + chmod 0777 $dom0 + $LFS setstripe -c 1 -i 0 "$DIR/$tdir/" + + # create qpool and add OST0 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 0 || error "pool_add_targets failed" + + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + log "User quota (block hardlimit:$limit MB)" + $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR || + error "set user quota failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 oflag=sync || + quota_error u $TSTUSR "write failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + $RUNAS $DD of=$testfile count=$limit || true + + # flush cache, ensure noquota flag is set on client + cancel_lru_locks osc + sync; sync_all_data || true + + # MDT0 shouldn't get EDQUOT with glimpse. + $RUNAS $DD of=$testfile count=$limit seek=$limit && + quota_error u $TSTUSR \ + "user write success, but expect EDQUOT" + + # Now all members of qpool1 should get EDQUOT. Expect success + # when write to DOM on MDT0, as it belongs to global pool. + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \ + oflag=sync || quota_error u $TSTUSR "write failed" + + cleanup_quota_test +} +run_test 69 "EDQUOT at one of pools shouldn't affect DOM" + +test_70() +{ + local qpool="qpool1" + local limit=20 + local err=0 + local bhard + + [[ CLIENT_VERSION -lt $(version_code $VERSION_WITH_QP) ]] && + skip "Needs a client >= $VERSION_WITH_QP" + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # MDS returns EFAULT for unsupported quotactl command + [[ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ]] && err=14 + + # create qpool and add OST0 + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 0 || error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR + rc=$? + [ $rc -eq $err ] || error "setquota res $rc != $err" + + # If MDS supports QP, check that limit was set properly. + if [[ $MDS1_VERSION -ge $(version_code $VERSION_WITH_QP) ]]; then + bhard=$(getquota -u $TSTUSR global bhardlimit $qpool) + echo "hard limit $bhard limit $limit" + [ $bhard -ne $((limit*1024)) ] && + error "bhard:$bhard for $qpool!=$((limit*1024))" + fi + + $LFS quota -u $TSTUSR --pool $qpool $DIR + rc=$? + [ $rc -eq $err ] || error "quota res $rc != $err" + + cleanup_quota_test +} +run_test 70 "check lfs setquota/quota with a pool option" + +test_71a() +{ + local limit=10 # 10M + local global_limit=100 # 100M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + local qpool2="qpool2" + + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit}M -o $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 -o $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 $short_qtype $TSTUSR \ + "write failure, but expect success" + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((2*limit)) seek=10 || true + cancel_lru_locks osc + sync; sync_all_data || true + # write over limit in qpool2(2nd component 10-30M) + $RUNAS $DD of=$testfile count=1 seek=$((10 + 2*limit)) && + quota_error u $TSTUSR "user write success, but expect EDQUOT" + # write to the 1st component - OST0 is empty + $RUNAS $DD of=$testfile count=$limit seek=0 || + quota_error u $TSTUSR "write failed" + + cleanup_quota_test +} +run_test 71a "Check PFL with quota pools" + +test_71b() +{ + local global_limit=1000 # 1G + local limit1=160 # 160M + local limit2=10 # 10M + local testfile="$DIR/$tdir/$tfile-0" + local qpool="qpool1" + local qpool2="qpool2" + + [ "$ost1_FSTYPE" == zfs ] && + skip "ZFS grants some block space together with inode" + [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return + mds_supports_qp + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + # test for user + log "User quota (block hardlimit:$global_limit MB)" + $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR || + error "set user quota failed" + + pool_add $qpool || error "pool_add failed" + pool_add_targets $qpool 0 1 || + error "pool_add_targets failed" + + $LFS setquota -u $TSTUSR -B ${limit1}M -o $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 -o $qpool2 $DIR || + error "set user quota failed" + + # make sure the system is clean + local used=$(getquota -u $TSTUSR global curspace) + + echo "used $used" + [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0." + + # First component is on OST0, 2nd on OST1 + $LFS setstripe -E 128M -i 0 -z 64M -E -1 -i 1 -z 64M $testfile + chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed" + + # fill the 1st component on OST0 + $RUNAS $DD of=$testfile count=128 || + quota_error u $TSTUSR "write failed" + # write to the 2nd cmpnt on OST1 + $RUNAS $DD of=$testfile count=$((limit2/2)) seek=128 || + quota_error u $TSTUSR "write failed" + # this time maybe cache write, ignore it's failure + $RUNAS $DD of=$testfile count=$((limit2/2)) seek=$((128 + limit2/2)) || + true + cancel_lru_locks osc + sync; sync_all_data || true + # write over limit in qpool2 + $RUNAS $DD of=$testfile count=2 seek=$((128 + limit2)) && + quota_error u $TSTUSR "user write success, but expect EDQUOT" + + cleanup_quota_test +} +run_test 71b "Check SEL with quota pools" + quota_fini() { do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"