Whamcloud - gitweb
LU-11843 tests: customise sanity-quota
[fs/lustre-release.git] / lustre / tests / sanity-quota.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6 # Run test by setting NOSETUP=true when ltest has setup env for us
7 set -e
8
9 SRCDIR=$(dirname $0)
10 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
11
12 ONLY=${ONLY:-"$*"}
13 # Bug number for skipped test:      LU-5152
14 ALWAYS_EXCEPT="$SANITY_QUOTA_EXCEPT 55"
15 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
16
17 [ "$ALWAYS_EXCEPT$EXCEPT" ] &&
18         echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
19
20 TMP=${TMP:-/tmp}
21
22 ORIG_PWD=${PWD}
23 TSTID=${TSTID:-60000}
24 TSTID2=${TSTID2:-60001}
25 TSTUSR=${TSTUSR:-"quota_usr"}
26 TSTUSR2=${TSTUSR2:-"quota_2usr"}
27 TSTPRJID=${TSTPRJID:-1000}
28 BLK_SZ=1024
29 MAX_DQ_TIME=604800
30 MAX_IQ_TIME=604800
31 QTYPE="ugp"
32
33 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
34 . $LUSTRE/tests/test-framework.sh
35 init_test_env $@
36 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
37 init_logging
38 DIRECTIO=${DIRECTIO:-$LUSTRE/tests/directio}
39
40 require_dsh_mds || exit 0
41 require_dsh_ost || exit 0
42
43 # Does e2fsprogs support quota feature?
44 if [ $(facet_fstype $SINGLEMDS) == ldiskfs ] &&
45         do_facet $SINGLEMDS "! $DEBUGFS -c -R supported_features |
46                 grep -q 'quota'"; then
47         skip_env "e2fsprogs doesn't support quota" && exit 0
48 fi
49
50 # Test duration:                   30 min
51 [ "$SLOW" = "no" ] && EXCEPT_SLOW="61"
52
53 if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then
54         # bug number for skipped test: LU-6836
55         ALWAYS_EXCEPT="$ALWAYS_EXCEPT  4a"
56
57         # bug number:                        LU-2887
58         # Test duration:                     21      9 min"
59         [ "$SLOW" = "no" ] && EXCEPT_SLOW+=" 12a     9"
60 fi
61
62 QUOTALOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log}
63
64 [ "$QUOTALOG" ] && rm -f $QUOTALOG || true
65
66 DIR=${DIR:-$MOUNT}
67 DIR2=${DIR2:-$MOUNT2}
68
69 QUOTA_AUTO_OLD=$QUOTA_AUTO
70 export QUOTA_AUTO=0
71
72 check_and_setup_lustre
73
74 ENABLE_PROJECT_QUOTAS=${ENABLE_PROJECT_QUOTAS:-true}
75 is_project_quota_supported() {
76         $ENABLE_PROJECT_QUOTAS || return 1
77         [ "$(facet_fstype $SINGLEMDS)" == "ldiskfs" ] &&
78                 [ $(lustre_version_code $SINGLEMDS) -gt \
79                 $(version_code 2.9.55) ] &&
80                 lfs --help | grep project >&/dev/null &&
81                 egrep -q "7." /etc/redhat-release && return 0
82
83         if [ "$(facet_fstype $SINGLEMDS)" == "zfs" ]; then
84                 [ $(lustre_version_code $SINGLEMDS) -le \
85                         $(version_code 2.10.53) ] && return 1
86
87                 $ZPOOL upgrade -v | grep project_quota && return 0
88         fi
89
90         return 1
91 }
92
93 SHOW_QUOTA_USER="$LFS quota -v -u $TSTUSR $DIR"
94 SHOW_QUOTA_USERID="$LFS quota -v -u $TSTID $DIR"
95 SHOW_QUOTA_GROUP="$LFS quota -v -g $TSTUSR $DIR"
96 SHOW_QUOTA_GROUPID="$LFS quota -v -g $TSTID $DIR"
97 SHOW_QUOTA_PROJID="eval is_project_quota_supported && $LFS quota -v -p $TSTPRJID $DIR"
98 SHOW_QUOTA_INFO_USER="$LFS quota -t -u $DIR"
99 SHOW_QUOTA_INFO_GROUP="$LFS quota -t -g $DIR"
100 SHOW_QUOTA_INFO_PROJID="eval is_project_quota_supported && $LFS quota -t -p $DIR"
101
102 build_test_filter
103
104 lustre_fail() {
105         local fail_node=$1
106         local fail_loc=$2
107         local fail_val=${3:-0}
108         local NODES=
109
110         case $fail_node in
111         mds_ost|mdt_ost) NODES="$(comma_list $(mdts_nodes) $(osts_nodes))";;
112         mds|mdt) NODES="$(comma_list $(mdts_nodes))";;
113         ost) NODES="$(comma_list $(osts_nodes))";;
114         esac
115
116         do_nodes $NODES "lctl set_param fail_val=$fail_val fail_loc=$fail_loc"
117 }
118
119 change_project()
120 {
121         echo "lfs project $*"
122         lfs project $* || error "lfs project $* failed"
123 }
124
125 RUNAS="runas -u $TSTID -g $TSTID"
126 RUNAS2="runas -u $TSTID2 -g $TSTID2"
127 DD="dd if=/dev/zero bs=1M"
128
129 FAIL_ON_ERROR=false
130
131 # clear quota limits for a user or a group
132 # usage: resetquota -u username
133 #        resetquota -g groupname
134 #        resetquota -p projid
135
136 resetquota() {
137         [ "$#" != 2 ] && error "resetquota: wrong number of arguments: $#"
138         [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] &&
139                 error "resetquota: wrong specifier $1 passed"
140
141         if [ $1 == "-p" ]; then
142                 is_project_quota_supported || return 0
143         fi
144
145         $LFS setquota "$1" "$2" -b 0 -B 0 -i 0 -I 0 $MOUNT ||
146                 error "clear quota for [type:$1 name:$2] failed"
147         # give a chance to slave to release space
148         sleep 1
149 }
150
151 quota_scan() {
152         local local_ugp=$1
153         local local_id=$2
154
155         if [ "$local_ugp" == "a" -o "$local_ugp" == "u" ]; then
156                 $LFS quota -v -u $local_id $DIR
157                 log "Files for user ($local_id):"
158                 ($LFS find --user $local_id $DIR | head -n 4 |
159                         xargs stat 2>/dev/null)
160         fi
161
162         if [ "$local_ugp" == "a" -o "$local_ugp" == "g" ]; then
163                 $LFS quota -v -g $local_id $DIR
164                 log "Files for group ($local_id):"
165                 ($LFS find --group $local_id $DIR | head -n 4 |
166                         xargs stat 2>/dev/null)
167         fi
168
169         if [ "$local_ugp" == "a" -o "$local_ugp" == "p" ]; then
170                 $LFS quota -v -p $TSTPRJID $DIR
171                 log "Files for project ($TSTPRJID):"
172                 ($LFS find --projid $TSTPRJID $DIR | head -n 4 |
173                         xargs stat 2>/dev/null)
174         fi
175 }
176
177 quota_error() {
178         quota_scan $1 $2
179         shift 2
180         error "$*"
181 }
182
183 quota_log() {
184         quota_scan $1 $2
185         shift 2
186         log "$*"
187 }
188
189 # get quota for a user or a group
190 # usage: getquota -u|-g|-p <username>|<groupname>|<projid> global|<obd_uuid> \
191 #                 bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace
192 getquota() {
193         local spec
194         local uuid
195
196         sync_all_data > /dev/null 2>&1 || true
197
198         [ "$#" != 4 ] && error "getquota: wrong number of arguments: $#"
199         [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] &&
200                 error "getquota: wrong u/g/p specifier $1 passed"
201
202         uuid="$3"
203
204         case "$4" in
205                 curspace)   spec=1;;
206                 bsoftlimit) spec=2;;
207                 bhardlimit) spec=3;;
208                 bgrace)     spec=4;;
209                 curinodes)  spec=5;;
210                 isoftlimit) spec=6;;
211                 ihardlimit) spec=7;;
212                 igrace)     spec=8;;
213                 *)          error "unknown quota parameter $4";;
214         esac
215
216         [ "$uuid" = "global" ] && uuid=$DIR
217
218         $LFS quota -v "$1" "$2" $DIR |
219                 awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") \
220                 { if (NF == 1) { getline } else { num++ } ; print $num;} }' \
221                 | tr -d "*"
222 }
223
224 # set mdt quota type
225 # usage: set_mdt_qtype ugp|u|g|p|none
226 set_mdt_qtype() {
227         local qtype=$1
228         local varsvc
229         local mdts=$(get_facets MDS)
230         local cmd
231         [[ "$qtype" =~ "p" ]] && ! is_project_quota_supported &&
232                 qtype=$(tr -d 'p' <<<$qtype)
233
234         if [[ $PERM_CMD == *"set_param -P"* ]]; then
235                 do_facet mgs $PERM_CMD \
236                         osd-*.$FSNAME-MDT*.quota_slave.enable=$qtype
237         else
238                 do_facet mgs $PERM_CMD $FSNAME.quota.mdt=$qtype
239         fi
240         # we have to make sure each MDT received config changes
241         for mdt in ${mdts//,/ }; do
242                 varsvc=${mdt}_svc
243                 cmd="$LCTL get_param -n "
244                 cmd=${cmd}osd-$(facet_fstype $mdt).${!varsvc}
245                 cmd=${cmd}.quota_slave.enabled
246
247                 if $(facet_up $mdt); then
248                         wait_update_facet $mdt "$cmd" "$qtype" || return 1
249                 fi
250         done
251         return 0
252 }
253
254 # set ost quota type
255 # usage: set_ost_qtype ugp|u|g|p|none
256 set_ost_qtype() {
257         local qtype=$1
258         local varsvc
259         local osts=$(get_facets OST)
260         local cmd
261         [[ "$qtype" =~ "p" ]] && ! is_project_quota_supported &&
262                 qtype=$(tr -d 'p' <<<$qtype)
263
264         if [[ $PERM_CMD == *"set_param -P"* ]]; then
265                 do_facet mgs $PERM_CMD \
266                         osd-*.$FSNAME-OST*.quota_slave.enable=$qtype
267         else
268                 do_facet mgs $PERM_CMD $FSNAME.quota.ost=$qtype
269         fi
270         # we have to make sure each OST received config changes
271         for ost in ${osts//,/ }; do
272                 varsvc=${ost}_svc
273                 cmd="$LCTL get_param -n "
274                 cmd=${cmd}osd-$(facet_fstype $ost).${!varsvc}
275                 cmd=${cmd}.quota_slave.enabled
276
277                 if $(facet_up $ost); then
278                         wait_update_facet $ost "$cmd" "$qtype" || return 1
279                 fi
280         done
281         return 0
282 }
283
284 wait_reintegration() {
285         local ntype=$1
286         local qtype=$2
287         local max=$3
288         local result="glb[1],slv[1],reint[0]"
289         local varsvc
290         local cmd
291         local tgts
292
293         if [ $ntype == "mdt" ]; then
294                 tgts=$(get_facets MDS)
295         else
296                 tgts=$(get_facets OST)
297         fi
298
299         for tgt in ${tgts//,/ }; do
300                 varsvc=${tgt}_svc
301                 cmd="$LCTL get_param -n "
302                 cmd=${cmd}osd-$(facet_fstype $tgt).${!varsvc}
303                 cmd=${cmd}.quota_slave.info
304
305                 if $(facet_up $tgt); then
306                         wait_update_facet $tgt "$cmd |
307                                 grep "$qtype" | awk '{ print \\\$3 }'" \
308                                         "$result" $max || return 1
309                 fi
310         done
311         return 0
312 }
313
314 wait_mdt_reint() {
315         local qtype=$1
316         local max=${2:-90}
317
318         if [[ "$qtype" =~ "u" ]]; then
319                 wait_reintegration "mdt" "user" $max || return 1
320         fi
321
322         if [[ "$qtype" =~ "g" ]]; then
323                 wait_reintegration "mdt" "group" $max || return 1
324         fi
325
326         if [[ "$qtype" =~ "p" ]]; then
327                 ! is_project_quota_supported && return 0
328                 wait_reintegration "mdt" "project" $max || return 1
329         fi
330         return 0
331 }
332
333 wait_ost_reint() {
334         local qtype=$1
335         local max=${2:-90}
336
337         if [[ "$qtype" =~ "u" ]]; then
338                 wait_reintegration "ost" "user" $max || return 1
339         fi
340
341         if [[ "$qtype" =~ "g" ]]; then
342                 wait_reintegration "ost" "group" $max || return 1
343         fi
344
345         if [[ "$qtype" =~ "p" ]]; then
346                 ! is_project_quota_supported && return 0
347                 wait_reintegration "ost" "project" $max || return 1
348         fi
349         return 0
350 }
351
352 disable_project_quota() {
353         is_project_quota_supported || return 0
354         [ "$(facet_fstype $SINGLEMDS)" != "ldiskfs" ] && return 0
355         stopall || error "failed to stopall (1)"
356
357         for num in $(seq $MDSCOUNT); do
358                 do_facet mds$num $TUNE2FS -Q ^prj $(mdsdevname $num) ||
359                         error "tune2fs $(mdsdevname $num) failed"
360         done
361
362         for num in $(seq $OSTCOUNT); do
363                 do_facet ost$num $TUNE2FS -Q ^prj $(ostdevname $num) ||
364                         error "tune2fs $(ostdevname $num) failed"
365         done
366
367         mount
368         setupall
369 }
370
371 setup_quota_test() {
372         wait_delete_completed
373         echo "Creating test directory"
374         mkdir $DIR/$tdir || return 1
375         chmod 0777 $DIR/$tdir || return 2
376         # always clear fail_loc in case of fail_loc isn't cleared
377         # properly when previous test failed
378         lustre_fail mds_ost 0
379 }
380
381 cleanup_quota_test() {
382         trap 0
383         echo "Delete files..."
384         rm -rf $DIR/$tdir
385         echo "Wait for unlink objects finished..."
386         wait_delete_completed
387         sync_all_data || true
388 }
389
390 quota_show_check() {
391         local bf=$1
392         local ugp=$2
393         local qid=$3
394         local usage
395
396         $LFS quota -v -$ugp $qid $DIR
397
398         if [ "$bf" == "a" -o "$bf" == "b" ]; then
399                 usage=$(getquota -$ugp $qid global curspace)
400                 if [ -z $usage ]; then
401                         quota_error $ugp $qid \
402                                 "Query block quota failed ($ugp:$qid)."
403                 else
404                         [ $usage -ne 0 ] && quota_log $ugp $qid \
405                                 "Block quota isn't 0 ($ugp:$qid:$usage)."
406                 fi
407         fi
408
409         if [ "$bf" == "a" -o "$bf" == "f" ]; then
410                 usage=$(getquota -$ugp $qid global curinodes)
411                 if [ -z $usage ]; then
412                         quota_error $ugp $qid \
413                                 "Query file quota failed ($ugp:$qid)."
414                 else
415                         [ $usage -ne 0 ] && quota_log $ugp $qid \
416                                 "File quota isn't 0 ($ugp:$qid:$usage)."
417                 fi
418         fi
419 }
420
421 enable_project_quota() {
422         is_project_quota_supported || return 0
423         [ "$(facet_fstype $SINGLEMDS)" != "ldiskfs" ] && return 0
424         stopall || error "failed to stopall (1)"
425
426         for num in $(seq $MDSCOUNT); do
427                 do_facet mds$num $TUNE2FS -O project $(mdsdevname $num) ||
428                         error "tune2fs $(mdsdevname $num) failed"
429         done
430
431         for num in $(seq $OSTCOUNT); do
432                 do_facet ost$num $TUNE2FS -O project $(ostdevname $num) ||
433                         error "tune2fs $(ostdevname $num) failed"
434         done
435
436         mount
437         setupall
438 }
439
440 project_quota_enabled () {
441         local rc=0
442         for num in $(seq $MDSCOUNT); do
443                 do_facet mds$num $DEBUGFS -R features $(mdsdevname $num) |
444                         grep -q project || rc=1
445         done
446         for num in $(seq $OSTCOUNT); do
447                 do_facet ost$num $DEBUGFS -R features $(ostdevname $num) |
448                         grep -q project || rc=1
449         done
450         [ $rc -eq 0 ] && PQ_CLEANUP=false || PQ_CLEANUP=true
451         return $rc
452 }
453
454 project_quota_enabled || enable_project_quota
455
456 reset_quota_settings() {
457         resetquota -u $TSTUSR
458         resetquota -g $TSTUSR
459         resetquota -u $TSTUSR2
460         resetquota -g $TSTUSR2
461         resetquota -p $TSTPRJID
462 }
463
464 # enable quota debug
465 quota_init() {
466         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota"
467 }
468 quota_init
469 reset_quota_settings
470
471 check_runas_id_ret $TSTUSR $TSTUSR $RUNAS ||
472         error "Please create user $TSTUSR($TSTID) and group $TSTUSR($TSTID)"
473 check_runas_id_ret $TSTUSR2 $TSTUSR2 $RUNAS2 ||
474         error "Please create user $TSTUSR2($TSTID2) and group $TSTUSR2($TSTID2)"
475
476 test_quota_performance() {
477         local TESTFILE="$DIR/$tdir/$tfile-0"
478         local size=$1 # in MB
479         local stime=$(date +%s)
480         $RUNAS $DD of=$TESTFILE count=$size conv=fsync ||
481                 quota_error u $TSTUSR "write failure"
482         local etime=$(date +%s)
483         delta=$((etime - stime))
484         if [ $delta -gt 0 ]; then
485             rate=$((size * 1024 / delta))
486             if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then
487                 # LU-2872 - see LU-2887 for fix
488                 [ $rate -gt 64 ] ||
489                         error "SLOW IO for $TSTUSR (user): $rate KB/sec"
490             else
491                 [ $rate -gt 1024 ] ||
492                         error "SLOW IO for $TSTUSR (user): $rate KB/sec"
493             fi
494         fi
495         rm -f $TESTFILE
496 }
497
498 # test basic quota performance b=21696
499 test_0() {
500         local MB=100 # 100M
501         [ "$SLOW" = "no" ] && MB=10
502
503         local free_space=$(lfs_df | grep "summary" | awk '{print $4}')
504         [ $free_space -le $((MB * 1024)) ] &&
505                 skip "not enough space ${free_space} KB, " \
506                         "required $((MB * 1024)) KB"
507         setup_quota_test || error "setup quota failed with $?"
508         trap cleanup_quota_test EXIT
509
510         set_ost_qtype "none" || error "disable ost quota failed"
511         test_quota_performance $MB
512
513         set_ost_qtype $QTYPE || error "enable ost quota failed"
514         $LFS setquota -u $TSTUSR -b 0 -B 10G -i 0 -I 0 $DIR ||
515                 error "set quota failed"
516         test_quota_performance $MB
517
518         cleanup_quota_test
519         resetquota -u $TSTUSR
520 }
521 run_test 0 "Test basic quota performance"
522
523 # test block hardlimit
524 test_1() {
525         local LIMIT=10  # 10M
526         local TESTFILE="$DIR/$tdir/$tfile-0"
527
528         setup_quota_test || error "setup quota failed with $?"
529         trap cleanup_quota_test EXIT
530
531         # enable ost quota
532         set_ost_qtype $QTYPE || error "enable ost quota failed"
533
534         # test for user
535         log "User quota (block hardlimit:$LIMIT MB)"
536         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
537                 error "set user quota failed"
538
539         # make sure the system is clean
540         local USED=$(getquota -u $TSTUSR global curspace)
541         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
542
543         $SETSTRIPE $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
544         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
545
546         log "Write..."
547         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) ||
548                 quota_error u $TSTUSR "user write failure, but expect success"
549         log "Write out of block quota ..."
550         # this time maybe cache write,  ignore it's failure
551         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true
552         # flush cache, ensure noquota flag is set on client
553         cancel_lru_locks osc
554         sync; sync_all_data || true
555         $RUNAS $DD of=$TESTFILE count=1 seek=$LIMIT &&
556                 quota_error u $TSTUSR "user write success, but expect EDQUOT"
557
558         rm -f $TESTFILE
559         wait_delete_completed || error "wait_delete_completed failed"
560         sync_all_data || true
561         USED=$(getquota -u $TSTUSR global curspace)
562         [ $USED -ne 0 ] && quota_error u $TSTUSR \
563                 "user quota isn't released after deletion"
564         resetquota -u $TSTUSR
565
566         # test for group
567         log "--------------------------------------"
568         log "Group quota (block hardlimit:$LIMIT MB)"
569         $LFS setquota -g $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
570                 error "set group quota failed"
571
572         TESTFILE="$DIR/$tdir/$tfile-1"
573         # make sure the system is clean
574         USED=$(getquota -g $TSTUSR global curspace)
575         [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTUSR isn't 0"
576
577         $SETSTRIPE $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
578         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
579
580         log "Write ..."
581         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) ||
582                 quota_error g $TSTUSR "Group write failure, but expect success"
583         log "Write out of block quota ..."
584         # this time maybe cache write, ignore it's failure
585         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true
586         cancel_lru_locks osc
587         sync; sync_all_data || true
588         $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT &&
589                 quota_error g $TSTUSR "Group write success, but expect EDQUOT"
590         rm -f $TESTFILE
591         wait_delete_completed || error "wait_delete_completed failed"
592         sync_all_data || true
593         USED=$(getquota -g $TSTUSR global curspace)
594         [ $USED -ne 0 ] && quota_error g $TSTUSR \
595                                 "Group quota isn't released after deletion"
596         resetquota -g $TSTUSR
597
598         if ! is_project_quota_supported; then
599                 echo "Project quota is not supported"
600                 cleanup_quota_test
601                 return 0
602         fi
603
604         TESTFILE="$DIR/$tdir/$tfile-2"
605         # make sure the system is clean
606         USED=$(getquota -p $TSTPRJID global curspace)
607         [ $USED -ne 0 ] &&
608                 error "used space($USED) for project $TSTPRJID isn't 0"
609
610         # test for Project
611         log "--------------------------------------"
612         log "Project quota (block hardlimit:$LIMIT mb)"
613         $LFS setquota -p $TSTPRJID -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
614                 error "set project quota failed"
615
616         $SETSTRIPE $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
617         chown $TSTUSR:$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
618         change_project -p $TSTPRJID $TESTFILE
619
620         log "write ..."
621         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) || quota_error p $TSTPRJID \
622                 "project write failure, but expect success"
623         log "write out of block quota ..."
624         # this time maybe cache write, ignore it's failure
625         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true
626         cancel_lru_locks osc
627         sync; sync_all_data || true
628         $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT && quota_error p \
629                 $TSTPRJID "project write success, but expect EDQUOT"
630
631         # cleanup
632         cleanup_quota_test
633
634         USED=$(getquota -p $TSTPRJID global curspace)
635         [ $USED -ne 0 ] && quota_error p $TSTPRJID \
636                 "project quota isn't released after deletion"
637
638         resetquota -p $TSTPRJID
639 }
640 run_test 1 "Block hard limit (normal use and out of quota)"
641
642 # test inode hardlimit
643 test_2() {
644         local LIMIT=$((1024 * 1024)) # 1M inodes
645         local TESTFILE="$DIR/$tdir/$tfile-0"
646
647         [ "$SLOW" = "no" ] && LIMIT=1024 # 1k inodes
648
649         local FREE_INODES=$(mdt_free_inodes 0)
650         echo "$FREE_INODES free inodes on master MDT"
651         [ $FREE_INODES -lt $LIMIT ] &&
652                 skip "not enough free inodes $FREE_INODES required $LIMIT"
653
654         setup_quota_test || error "setup quota failed with $?"
655         trap cleanup_quota_test EXIT
656
657         # enable mdt quota
658         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
659
660         # test for user
661         log "User quota (inode hardlimit:$LIMIT files)"
662         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
663                 error "set user quota failed"
664
665         # make sure the system is clean
666         local USED=$(getquota -u $TSTUSR global curinodes)
667         [ $USED -ne 0 ] && error "Used inodes($USED) for user $TSTUSR isn't 0."
668
669         log "Create $LIMIT files ..."
670         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
671                 quota_error u $TSTUSR "user create failure, but expect success"
672         log "Create out of file quota ..."
673         $RUNAS touch ${TESTFILE}_xxx &&
674                 quota_error u $TSTUSR "user create success, but expect EDQUOT"
675
676         # cleanup
677         unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed"
678         rm -f ${TESTFILE}_xxx
679         wait_delete_completed
680
681         USED=$(getquota -u $TSTUSR global curinodes)
682         [ $USED -ne 0 ] && quota_error u $TSTUSR \
683                 "user quota isn't released after deletion"
684         resetquota -u $TSTUSR
685
686         # test for group
687         log "--------------------------------------"
688         log "Group quota (inode hardlimit:$LIMIT files)"
689         $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
690                 error "set group quota failed"
691
692         TESTFILE=$DIR/$tdir/$tfile-1
693         # make sure the system is clean
694         USED=$(getquota -g $TSTUSR global curinodes)
695         [ $USED -ne 0 ] && error "Used inodes($USED) for group $TSTUSR isn't 0."
696
697         log "Create $LIMIT files ..."
698         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
699                 quota_error g $TSTUSR "group create failure, but expect success"
700         log "Create out of file quota ..."
701         $RUNAS touch ${TESTFILE}_xxx &&
702                 quota_error g $TSTUSR "group create success, but expect EDQUOT"
703
704         # cleanup
705         unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed"
706         rm -f ${TESTFILE}_xxx
707         wait_delete_completed
708
709         USED=$(getquota -g $TSTUSR global curinodes)
710         [ $USED -ne 0 ] && quota_error g $TSTUSR \
711                 "user quota isn't released after deletion"
712
713         resetquota -g $TSTUSR
714         ! is_project_quota_supported && cleanup_quota_test &&
715                 echo "Skip project quota is not supported" && return 0
716
717         # test for project
718         log "--------------------------------------"
719         log "Project quota (inode hardlimit:$LIMIT files)"
720         $LFS setquota -p $TSTPRJID -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
721                 error "set project quota failed"
722
723         TESTFILE=$DIR/$tdir/$tfile-1
724         # make sure the system is clean
725         USED=$(getquota -p $TSTPRJID global curinodes)
726         [ $USED -ne 0 ] &&
727                 error "Used inodes($USED) for project $TSTPRJID isn't 0"
728
729         change_project -sp $TSTPRJID $DIR/$tdir
730         log "Create $LIMIT files ..."
731         $RUNAS createmany -m ${TESTFILE} $((LIMIT-1)) || quota_error p \
732                 $TSTPRJID "project create fail, but expect success"
733         log "Create out of file quota ..."
734         $RUNAS touch ${TESTFILE}_xxx && quota_error p $TSTPRJID \
735                 "project create success, but expect EDQUOT"
736         change_project -C $DIR/$tdir
737
738         cleanup_quota_test
739         USED=$(getquota -p $TSTPRJID global curinodes)
740         [ $USED -ne 0 ] && quota_error p $TSTPRJID \
741                 "project quota isn't released after deletion"
742
743         resetquota -p $TSTPRJID
744
745 }
746 run_test 2 "File hard limit (normal use and out of quota)"
747
748 test_block_soft() {
749         local TESTFILE=$1
750         local TIMER=$(($2 * 3 / 2))
751         local LIMIT=$3
752         local OFFSET=0
753         local qtype=$4
754
755         setup_quota_test
756         trap cleanup_quota_test EXIT
757
758         $SETSTRIPE $TESTFILE -c 1 -i 0
759         chown $TSTUSR.$TSTUSR $TESTFILE
760         [ "$qtype" == "p" ] && is_project_quota_supported &&
761                 change_project -p $TSTPRJID $TESTFILE
762
763         echo "Write up to soft limit"
764         $RUNAS $DD of=$TESTFILE count=$LIMIT ||
765                 quota_error a $TSTUSR "write failure, but expect success"
766         OFFSET=$((LIMIT * 1024))
767         cancel_lru_locks osc
768
769         echo "Write to exceed soft limit"
770         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET ||
771                 quota_error a $TSTUSR "write failure, but expect success"
772         OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block
773         cancel_lru_locks osc
774
775         $SHOW_QUOTA_USER
776         $SHOW_QUOTA_GROUP
777         $SHOW_QUOTA_PROJID
778         $SHOW_QUOTA_INFO_USER
779         $SHOW_QUOTA_INFO_GROUP
780         $SHOW_QUOTA_INFO_PROJID
781
782         echo "Write before timer goes off"
783         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET ||
784                 quota_error a $TSTUSR "write failure, but expect success"
785         OFFSET=$((OFFSET + 1024))
786         cancel_lru_locks osc
787
788         echo "Sleep $TIMER seconds ..."
789         sleep $TIMER
790
791         $SHOW_QUOTA_USER
792         $SHOW_QUOTA_GROUP
793         $SHOW_QUOTA_PROJID
794         $SHOW_QUOTA_INFO_USER
795         $SHOW_QUOTA_INFO_GROUP
796         $SHOW_QUOTA_INFO_PROJID
797
798         echo "Write after timer goes off"
799         # maybe cache write, ignore.
800         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || true
801         OFFSET=$((OFFSET + 1024))
802         cancel_lru_locks osc
803         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET &&
804                 quota_error a $TSTUSR "write success, but expect EDQUOT"
805
806         $SHOW_QUOTA_USER
807         $SHOW_QUOTA_GROUP
808         $SHOW_QUOTA_PROJID
809         $SHOW_QUOTA_INFO_USER
810         $SHOW_QUOTA_INFO_GROUP
811         $SHOW_QUOTA_INFO_PROJID
812
813         echo "Unlink file to stop timer"
814         rm -f $TESTFILE
815         wait_delete_completed
816         sync_all_data || true
817
818         $SHOW_QUOTA_USER
819         $SHOW_QUOTA_GROUP
820         $SHOW_QUOTA_PROJID
821         $SHOW_QUOTA_INFO_USER
822         $SHOW_QUOTA_INFO_GROUP
823         $SHOW_QUOTA_INFO_PROJID
824
825         $SETSTRIPE $TESTFILE -c 1 -i 0
826         chown $TSTUSR.$TSTUSR $TESTFILE
827         [ "$qtype" == "p" ] && change_project -p $TSTPRJID $TESTFILE
828
829         echo "Write ..."
830         $RUNAS $DD of=$TESTFILE count=$LIMIT ||
831                 quota_error a $TSTUSR "write failure, but expect success"
832         # cleanup
833         cleanup_quota_test
834 }
835
836 # block soft limit
837 test_3() {
838         local LIMIT=1  # 1MB
839         local GRACE=20 # 20s
840         local TESTFILE=$DIR/$tdir/$tfile-0
841
842         set_ost_qtype $QTYPE || error "enable ost quota failed"
843
844         echo "User quota (soft limit:$LIMIT MB  grace:$GRACE seconds)"
845         # make sure the system is clean
846         local USED=$(getquota -u $TSTUSR global curspace)
847         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
848
849         $LFS setquota -t -u --block-grace $GRACE --inode-grace \
850                 $MAX_IQ_TIME $DIR || error "set user grace time failed"
851         $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
852                 error "set user quota failed"
853
854         test_block_soft $TESTFILE $GRACE $LIMIT "u"
855         resetquota -u $TSTUSR
856
857         echo "Group quota (soft limit:$LIMIT MB  grace:$GRACE seconds)"
858         TESTFILE=$DIR/$tdir/$tfile-1
859         # make sure the system is clean
860         USED=$(getquota -g $TSTUSR global curspace)
861         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0."
862
863         $LFS setquota -t -g --block-grace $GRACE --inode-grace \
864                 $MAX_IQ_TIME $DIR || error "set group grace time failed"
865         $LFS setquota -g $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
866                 error "set group quota failed"
867
868         test_block_soft $TESTFILE $GRACE $LIMIT "g"
869         resetquota -g $TSTUSR
870
871         if is_project_quota_supported; then
872                 echo "Project quota (soft limit:$LIMIT MB  grace:$GRACE sec)"
873                 TESTFILE=$DIR/$tdir/$tfile-2
874                 # make sure the system is clean
875                 USED=$(getquota -p $TSTPRJID global curspace)
876                 [ $USED -ne 0 ] && error \
877                         "Used space($USED) for project $TSTPRJID isn't 0."
878
879                 $LFS setquota -t -p --block-grace $GRACE --inode-grace \
880                         $MAX_IQ_TIME $DIR ||
881                                 error "set project grace time failed"
882                 $LFS setquota -p $TSTPRJID -b ${LIMIT}M -B 0 -i 0 -I 0 \
883                         $DIR || error "set project quota failed"
884
885                 test_block_soft $TESTFILE $GRACE $LIMIT "p"
886                 resetquota -p $TSTPRJID
887                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
888                         $MAX_IQ_TIME $DIR ||
889                                 error "restore project grace time failed"
890         fi
891
892         # cleanup
893         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
894                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
895         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
896                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
897 }
898 run_test 3 "Block soft limit (start timer, timer goes off, stop timer)"
899
900 test_file_soft() {
901         local TESTFILE=$1
902         local LIMIT=$2
903         local grace=$3
904         local TIMER=$(($grace * 3 / 2))
905
906         setup_quota_test
907         trap cleanup_quota_test EXIT
908         is_project_quota_supported && change_project -sp $TSTPRJID $DIR/$tdir
909
910         echo "Create files to exceed soft limit"
911         $RUNAS createmany -m ${TESTFILE}_ $((LIMIT + 1)) ||
912                 quota_error a $TSTUSR "create failure, but expect success"
913         local trigger_time=$(date +%s)
914
915         sync_all_data || true
916
917         local cur_time=$(date +%s)
918         [ $(($cur_time - $trigger_time)) -ge $grace ] &&
919                 error "Passed grace time $grace, $trigger_time, $cur_time"
920
921         echo "Create file before timer goes off"
922         $RUNAS touch ${TESTFILE}_before ||
923                 quota_error a $TSTUSR "failed create before timer expired," \
924                         "but expect success. $trigger_time, $cur_time"
925         sync_all_data || true
926
927         echo "Sleep $TIMER seconds ..."
928         sleep $TIMER
929
930         $SHOW_QUOTA_USER
931         $SHOW_QUOTA_GROUP
932         $SHOW_QUOTA_PROJID
933         $SHOW_QUOTA_INFO_USER
934         $SHOW_QUOTA_INFO_GROUP
935         $SHOW_QUOTA_INFO_PROJID
936
937         echo "Create file after timer goes off"
938         # There is a window that space is accounted in the quota usage but
939         # hasn't been decreased from the pending write, if we acquire quota
940         # in this window, we'll acquire more than we needed.
941         $RUNAS touch ${TESTFILE}_after_1 ${TESTFILE}_after_2 || true
942         sync_all_data || true
943         $RUNAS touch ${TESTFILE}_after_3 &&
944                 quota_error a $TSTUSR "create after timer expired," \
945                         "but expect EDQUOT"
946         sync_all_data || true
947
948         $SHOW_QUOTA_USER
949         $SHOW_QUOTA_GROUP
950         $SHOW_QUOTA_PROJID
951         $SHOW_QUOTA_INFO_USER
952         $SHOW_QUOTA_INFO_GROUP
953         $SHOW_QUOTA_INFO_PROJID
954
955         echo "Unlink files to stop timer"
956         find $(dirname $TESTFILE) -name "$(basename ${TESTFILE})*" | xargs rm -f
957         wait_delete_completed
958
959         echo "Create file"
960         $RUNAS touch ${TESTFILE}_xxx ||
961                 quota_error a $TSTUSR "touch after timer stop failure," \
962                         "but expect success"
963         sync_all_data || true
964
965         # cleanup
966         cleanup_quota_test
967 }
968
969 # file soft limit
970 test_4a() {
971         local LIMIT=10 # inodes
972         local TESTFILE=$DIR/$tdir/$tfile-0
973         local GRACE=12
974
975         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
976
977         echo "User quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
978         # make sure the system is clean
979         local USED=$(getquota -u $TSTUSR global curinodes)
980         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
981
982         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
983                 $GRACE $DIR || error "set user grace time failed"
984         $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
985                 error "set user quota failed"
986
987         test_file_soft $TESTFILE $LIMIT $GRACE
988         resetquota -u $TSTUSR
989
990         echo "Group quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
991         # make sure the system is clean
992         USED=$(getquota -g $TSTUSR global curinodes)
993         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0."
994
995         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
996                 $GRACE $DIR || error "set group grace time failed"
997         $LFS setquota -g $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
998                 error "set group quota failed"
999         TESTFILE=$DIR/$tdir/$tfile-1
1000
1001         test_file_soft $TESTFILE $LIMIT $GRACE
1002         resetquota -g $TSTUSR
1003
1004         if is_project_quota_supported; then
1005                 echo "Project quota (soft limit:$LIMIT files grace:$GRACE sec)"
1006                 # make sure the system is clean
1007                 USED=$(getquota -p $TSTPRJID global curinodes)
1008                 [ $USED -ne 0 ] && error \
1009                         "Used space($USED) for project $TSTPRJID isn't 0."
1010
1011                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1012                         $GRACE $DIR || error "set project grace time failed"
1013                 $LFS setquota -p $TSTPRJID -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
1014                         error "set project quota failed"
1015
1016                 TESTFILE=$DIR/$tdir/$tfile-1
1017                 # one less than limit, because of parent directory included.
1018                 test_file_soft $TESTFILE $((LIMIT-1)) $GRACE
1019                 resetquota -p $TSTPRJID
1020                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1021                         $MAX_IQ_TIME $DIR ||
1022                                 error "restore project grace time failed"
1023         fi
1024
1025         # cleanup
1026         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1027                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1028         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1029                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1030 }
1031 run_test 4a "File soft limit (start timer, timer goes off, stop timer)"
1032
1033 test_4b() {
1034         local GR_STR1="1w3d"
1035         local GR_STR2="1000s"
1036         local GR_STR3="5s"
1037         local GR_STR4="1w2d3h4m5s"
1038         local GR_STR5="5c"
1039         local GR_STR6="18446744073709551615"
1040         local GR_STR7="-1"
1041
1042         wait_delete_completed
1043
1044         # test of valid grace strings handling
1045         echo "Valid grace strings test"
1046         $LFS setquota -t -u --block-grace $GR_STR1 --inode-grace \
1047                 $GR_STR2 $DIR || error "set user grace time failed"
1048         $LFS quota -u -t $DIR | grep "Block grace time: $GR_STR1"
1049         $LFS setquota -t -g --block-grace $GR_STR3 --inode-grace \
1050                 $GR_STR4 $DIR || error "set group grace time quota failed"
1051         $LFS quota -g -t $DIR | grep "Inode grace time: $GR_STR4"
1052
1053         # test of invalid grace strings handling
1054         echo "  Invalid grace strings test"
1055         ! $LFS setquota -t -u --block-grace $GR_STR4 --inode-grace $GR_STR5 $DIR
1056         ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace $GR_STR6 $DIR
1057         ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace \
1058                 $GR_STR7 $DIR
1059
1060         # cleanup
1061         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1062                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1063         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1064                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1065 }
1066 run_test 4b "Grace time strings handling"
1067
1068 # chown & chgrp (chown & chgrp successfully even out of block/file quota)
1069 test_5() {
1070         local BLIMIT=10 # 10M
1071         local ILIMIT=10 # 10 inodes
1072
1073         setup_quota_test || error "setup quota failed with $?"
1074         trap cleanup_quota_test EXIT
1075
1076         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1077         set_ost_qtype $QTYPE || error "enable ost quota failed"
1078
1079         echo "Set quota limit (0 ${BLIMIT}M 0 $ILIMIT) for $TSTUSR.$TSTUSR"
1080         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
1081                 error "set user quota failed"
1082         $LFS setquota -g $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
1083         if is_project_quota_supported; then
1084                 error "set group quota failed"
1085                 $LFS setquota -p $TSTPRJID -b 0 -B ${BLIMIT}M -i 0 \
1086                         -I $ILIMIT $DIR || error "set project quota failed"
1087         fi
1088
1089         # make sure the system is clean
1090         local USED=$(getquota -u $TSTUSR global curinodes)
1091         [ $USED -ne 0 ] && error "Used inode($USED) for user $TSTUSR isn't 0."
1092         USED=$(getquota -g $TSTUSR global curinodes)
1093         [ $USED -ne 0 ] && error "Used inode($USED) for group $TSTUSR isn't 0."
1094         USED=$(getquota -u $TSTUSR global curspace)
1095         [ $USED -ne 0 ] && error "Used block($USED) for user $TSTUSR isn't 0."
1096         USED=$(getquota -g $TSTUSR global curspace)
1097         [ $USED -ne 0 ] && error "Used block($USED) for group $TSTUSR isn't 0."
1098         if is_project_quota_supported; then
1099                 USED=$(getquota -p $TSTPRJID global curinodes)
1100                 [ $USED -ne 0 ] &&
1101                         error "Used inode($USED) for project $TSTPRJID isn't 0."
1102                 USED=$(getquota -p $TSTPRJID global curspace)
1103                 [ $USED -ne 0 ] &&
1104                         error "Used block($USED) for project $TSTPRJID isn't 0."
1105         fi
1106
1107         echo "Create more than $ILIMIT files and more than $BLIMIT MB ..."
1108         createmany -m $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) ||
1109                 error "create failure, expect success"
1110         if is_project_quota_supported; then
1111                 touch $DIR/$tdir/$tfile-0_1
1112                 change_project -p $TSTPRJID $DIR/$tdir/$tfile-0_1
1113         fi
1114         $DD of=$DIR/$tdir/$tfile-0_1 count=$((BLIMIT+1)) ||
1115                 error "write failure, expect success"
1116
1117         echo "Chown files to $TSTUSR.$TSTUSR ..."
1118         for i in $(seq 0 $ILIMIT); do
1119                 chown $TSTUSR.$TSTUSR $DIR/$tdir/$tfile-0_$i ||
1120                         quota_error a $TSTUSR "chown failure, expect success"
1121         done
1122
1123         # cleanup
1124         unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) ||
1125                 error "unlinkmany $DIR/$tdir/$tfile-0_ failed"
1126         cleanup_quota_test
1127
1128         resetquota -u $TSTUSR
1129         resetquota -g $TSTUSR
1130         resetquota -p $TSTPRJID
1131 }
1132 run_test 5 "Chown & chgrp successfully even out of block/file quota"
1133
1134 # test dropping acquire request on master
1135 test_6() {
1136         local LIMIT=3 # 3M
1137
1138         # Clear dmesg so watchdog is not triggered by previous
1139         # test output
1140         do_facet ost1 dmesg -c > /dev/null
1141
1142         setup_quota_test || error "setup quota failed with $?"
1143         trap cleanup_quota_test EXIT
1144
1145         # make sure the system is clean
1146         local USED=$(getquota -u $TSTUSR global curspace)
1147         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1148
1149         # make sure no granted quota on ost
1150         set_ost_qtype $QTYPE || error "enable ost quota failed"
1151         resetquota -u $TSTUSR
1152
1153         # create file for $TSTUSR
1154         local TESTFILE=$DIR/$tdir/$tfile-$TSTUSR
1155         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1156         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1157
1158         # create file for $TSTUSR2
1159         local TESTFILE2=$DIR/$tdir/$tfile-$TSTUSR2
1160         $SETSTRIPE $TESTFILE2 -c 1 -i 0 || error "setstripe $TESTFILE2 failed"
1161         chown $TSTUSR2.$TSTUSR2 $TESTFILE2 || error "chown $TESTFILE2 failed"
1162
1163         # cache per-ID lock for $TSTUSR on slave
1164         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1165                 error "set quota failed"
1166         $RUNAS $DD of=$TESTFILE count=1 ||
1167                 error "write $TESTFILE failure, expect success"
1168         $RUNAS2 $DD of=$TESTFILE2 count=1 ||
1169                 error "write $TESTFILE2 failure, expect success"
1170         sync; sync
1171         sync_all_data || true
1172
1173         #define QUOTA_DQACQ 601
1174         #define OBD_FAIL_PTLRPC_DROP_REQ_OPC 0x513
1175         lustre_fail mds 0x513 601
1176
1177         # write to un-enforced ID ($TSTUSR2) should succeed
1178         $RUNAS2 $DD of=$TESTFILE2 count=$LIMIT seek=1 oflag=sync conv=notrunc ||
1179                 error "write failure, expect success"
1180
1181         # write to enforced ID ($TSTUSR) in background, exceeding limit
1182         # to make sure DQACQ is sent
1183         $RUNAS $DD of=$TESTFILE count=$LIMIT seek=1 oflag=sync conv=notrunc &
1184         DDPID=$!
1185
1186         # watchdog timer uses a factor of 2
1187         echo "Sleep for $((TIMEOUT * 2 + 1)) seconds ..."
1188         sleep $((TIMEOUT * 2 + 1))
1189
1190         # write should be blocked and never finished
1191         if ! ps -p $DDPID  > /dev/null 2>&1; then
1192                 lustre_fail mds 0 0
1193                 error "write finished incorrectly!"
1194         fi
1195
1196         lustre_fail mds 0 0
1197
1198         # no watchdog is triggered
1199         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
1200         watchdog=$(awk '/Service thread pid/ && /was inactive/ \
1201                         { print; }' $TMP/lustre-log-${TESTNAME}.log)
1202         [ -z "$watchdog" ] || error "$watchdog"
1203
1204         rm -f $TMP/lustre-log-${TESTNAME}.log
1205
1206         # write should continue then fail with EDQUOT
1207         local count=0
1208         local c_size
1209         while [ true ]; do
1210                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1211                 if [ $count -ge 240 ]; then
1212                         quota_error u $TSTUSR "dd not finished in $count secs"
1213                 fi
1214                 count=$((count + 1))
1215                 if [ $((count % 30)) -eq 0 ]; then
1216                         c_size=$(stat -c %s $TESTFILE)
1217                         echo "Waiting $count secs. $c_size"
1218                         $SHOW_QUOTA_USER
1219                 fi
1220                 sleep 1
1221         done
1222
1223         cleanup_quota_test
1224         resetquota -u $TSTUSR
1225 }
1226 run_test 6 "Test dropping acquire request on master"
1227
1228 # quota reintegration (global index)
1229 test_7a() {
1230         local TESTFILE=$DIR/$tdir/$tfile
1231         local LIMIT=20 # 20M
1232
1233         [ "$SLOW" = "no" ] && LIMIT=5
1234
1235         setup_quota_test || error "setup quota failed with $?"
1236         trap cleanup_quota_test EXIT
1237
1238         # make sure the system is clean
1239         local USED=$(getquota -u $TSTUSR global curspace)
1240         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1241
1242         # make sure no granted quota on ost1
1243         set_ost_qtype $QTYPE || error "enable ost quota failed"
1244         resetquota -u $TSTUSR
1245         set_ost_qtype "none" || error "disable ost quota failed"
1246
1247         local OSTUUID=$(ostuuid_from_index 0)
1248         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1249         [ $USED -ne 0 ] &&
1250                 error "limit($USED) on $OSTUUID for user $TSTUSR isn't 0"
1251
1252         # create test file
1253         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1254         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1255
1256         echo "Stop ost1..."
1257         stop ost1
1258
1259         echo "Enable quota & set quota limit for $TSTUSR"
1260         set_ost_qtype $QTYPE || error "enable ost quota failed"
1261         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1262                 error "set quota failed"
1263
1264         echo "Start ost1..."
1265         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1266         quota_init
1267
1268         wait_ost_reint $QTYPE || error "reintegration failed"
1269
1270         # hardlimit should have been fetched by slave during global
1271         # reintegration, write will exceed quota
1272         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
1273                 quota_error u $TSTUSR "write success, but expect EDQUOT"
1274
1275         rm -f $TESTFILE
1276         wait_delete_completed
1277         sync_all_data || true
1278         sleep 3
1279
1280         echo "Stop ost1..."
1281         stop ost1
1282
1283         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
1284                 error "clear quota failed"
1285
1286         echo "Start ost1..."
1287         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1288         quota_init
1289
1290         wait_ost_reint $QTYPE || error "reintegration failed"
1291
1292         # hardlimit should be cleared on slave during reintegration
1293         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync ||
1294                 quota_error u $TSTUSR "write error, but expect success"
1295
1296         cleanup_quota_test
1297         resetquota -u $TSTUSR
1298 }
1299 run_test 7a "Quota reintegration (global index)"
1300
1301 # quota reintegration (slave index)
1302 test_7b() {
1303         local LIMIT="100G"
1304         local TESTFILE=$DIR/$tdir/$tfile
1305
1306         setup_quota_test || error "setup quota failed with $?"
1307         trap cleanup_quota_test EXIT
1308
1309         # make sure the system is clean
1310         local USED=$(getquota -u $TSTUSR global curspace)
1311         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1312
1313         # make sure no granted quota on ost1
1314         set_ost_qtype $QTYPE || error "enable ost quota failed"
1315         resetquota -u $TSTUSR
1316         set_ost_qtype "none" || error "disable ost quota failed"
1317
1318         local OSTUUID=$(ostuuid_from_index 0)
1319         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1320         [ $USED -ne 0 ] &&
1321                 error "limit($USED) on $OSTUUID for user $TSTUSR isn't 0"
1322
1323         # create test file
1324         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1325         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1326
1327         # consume some space to make sure the granted space will not
1328         # be released during reconciliation
1329         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
1330                 error "consume space failure, expect success"
1331
1332         # define OBD_FAIL_QUOTA_EDQUOT 0xa02
1333         lustre_fail mds 0xa02
1334
1335         set_ost_qtype $QTYPE || error "enable ost quota failed"
1336         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1337                 error "set quota failed"
1338
1339         # ignore the write error
1340         $RUNAS $DD of=$TESTFILE count=1 seek=1 oflag=sync conv=notrunc
1341
1342         local old_used=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1343
1344         lustre_fail mds 0
1345
1346         echo "Restart ost to trigger reintegration..."
1347         stop ost1
1348         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1349         quota_init
1350
1351         wait_ost_reint $QTYPE || error "reintegration failed"
1352
1353         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1354         [ $USED -gt $old_used ] || error "limit on $OSTUUID $USED <= $old_used"
1355
1356         cleanup_quota_test
1357         resetquota -u $TSTUSR
1358         $SHOW_QUOTA_USER
1359 }
1360 run_test 7b "Quota reintegration (slave index)"
1361
1362 # quota reintegration (restart mds during reintegration)
1363 test_7c() {
1364         local LIMIT=20 # 20M
1365         local TESTFILE=$DIR/$tdir/$tfile
1366
1367         [ "$SLOW" = "no" ] && LIMIT=5
1368
1369         setup_quota_test || error "setup quota failed with $?"
1370         trap cleanup_quota_test EXIT
1371
1372         # make sure the system is clean
1373         local USED=$(getquota -u $TSTUSR global curspace)
1374         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1375
1376         set_ost_qtype "none" || error "disable ost quota failed"
1377         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1378                 error "set quota failed"
1379
1380         # define OBD_FAIL_QUOTA_DELAY_REINT 0xa03
1381         lustre_fail ost 0xa03
1382
1383         # enable ost quota
1384         set_ost_qtype $QTYPE || error "enable ost quota failed"
1385         # trigger reintegration
1386         local procf="osd-$(facet_fstype ost1).$FSNAME-OST*."
1387         procf=${procf}quota_slave.force_reint
1388         do_facet ost1 $LCTL set_param $procf=1 ||
1389                 error "force reintegration failed"
1390
1391         echo "Stop mds..."
1392         stop mds1
1393
1394         lustre_fail ost 0
1395
1396         echo "Start mds..."
1397         start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
1398         quota_init
1399
1400         # wait longer than usual to make sure the reintegration
1401         # is triggered by quota wb thread.
1402         wait_ost_reint $QTYPE 200 || error "reintegration failed"
1403
1404         # hardlimit should have been fetched by slave during global
1405         # reintegration, write will exceed quota
1406         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
1407                 quota_error u $TSTUSR "write success, but expect EDQUOT"
1408
1409         cleanup_quota_test
1410         resetquota -u $TSTUSR
1411 }
1412 run_test 7c "Quota reintegration (restart mds during reintegration)"
1413
1414 # Quota reintegration (Transfer index in multiple bulks)
1415 test_7d(){
1416         local TESTFILE=$DIR/$tdir/$tfile
1417         local TESTFILE1="$DIR/$tdir/$tfile"-1
1418         local limit=20 #20M
1419
1420         setup_quota_test || error "setup quota failed with $?"
1421         trap cleanup_quota_test EXIT
1422
1423         set_ost_qtype "none" || error "disable ost quota failed"
1424         $LFS setquota -u $TSTUSR -B ${limit}M $DIR ||
1425                 error "set quota for $TSTUSR failed"
1426         $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR ||
1427                 error "set quota for $TSTUSR2 failed"
1428
1429         #define OBD_FAIL_OBD_IDX_READ_BREAK 0x608
1430         lustre_fail mds 0x608 0
1431
1432         # enable quota to tirgger reintegration
1433         set_ost_qtype "u" || error "enable ost quota failed"
1434         wait_ost_reint "u" || error "reintegration failed"
1435
1436         lustre_fail mds 0
1437
1438         # hardlimit should have been fetched by slave during global
1439         # reintegration, write will exceed quota
1440         $RUNAS $DD of=$TESTFILE count=$((limit + 1)) oflag=sync &&
1441                 quota_error u $TSTUSR "$TSTUSR write success, expect EDQUOT"
1442
1443         $RUNAS2 $DD of=$TESTFILE1 count=$((limit + 1)) oflag=sync &&
1444                 quota_error u $TSTUSR2 "$TSTUSR2 write success, expect EDQUOT"
1445
1446         cleanup_quota_test
1447         resetquota -u $TSTUSR
1448         resetquota -u $TSTUSR2
1449 }
1450 run_test 7d "Quota reintegration (Transfer index in multiple bulks)"
1451
1452 # quota reintegration (inode limits)
1453 test_7e() {
1454         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
1455
1456         # LU-2435: skip this quota test if underlying zfs version has not
1457         # supported native dnode accounting
1458         [ "$(facet_fstype mds1)" == "zfs" ] && {
1459                 local F="feature@userobj_accounting"
1460                 local pool=$(zpool_name mds1)
1461                 local feature=$(do_facet mds1 $ZPOOL get -H $F $pool)
1462
1463                 [[ "$feature" != *" active "* ]] &&
1464                         skip "requires zpool with active userobj_accounting"
1465         }
1466
1467         local ilimit=$((1024 * 2)) # 2k inodes
1468         local TESTFILE=$DIR/${tdir}-1/$tfile
1469
1470         setup_quota_test || error "setup quota failed with $?"
1471         trap cleanup_quota_test EXIT
1472
1473         # make sure the system is clean
1474         local USED=$(getquota -u $TSTUSR global curinodes)
1475         [ $USED -ne 0 ] && error "Used inode($USED) for user $TSTUSR isn't 0."
1476
1477         # make sure no granted quota on mdt1
1478         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1479         resetquota -u $TSTUSR
1480         set_mdt_qtype "none" || error "disable mdt quota failed"
1481
1482         local MDTUUID=$(mdtuuid_from_index $((MDSCOUNT - 1)))
1483         USED=$(getquota -u $TSTUSR $MDTUUID ihardlimit)
1484         [ $USED -ne 0 ] && error "limit($USED) on $MDTUUID for user" \
1485                 "$TSTUSR isn't 0."
1486
1487         echo "Stop mds${MDSCOUNT}..."
1488         stop mds${MDSCOUNT}
1489
1490         echo "Enable quota & set quota limit for $TSTUSR"
1491         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1492         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $ilimit $DIR ||
1493                 error "set quota failed"
1494
1495         echo "Start mds${MDSCOUNT}..."
1496         start mds${MDSCOUNT} $(mdsdevname $MDSCOUNT) $MDS_MOUNT_OPTS
1497         quota_init
1498
1499         wait_mdt_reint $QTYPE || error "reintegration failed"
1500
1501         echo "create remote dir"
1502         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/${tdir}-1 ||
1503                 error "create remote dir failed"
1504         chmod 0777 $DIR/${tdir}-1
1505
1506         # hardlimit should have been fetched by slave during global
1507         # reintegration, create will exceed quota
1508         $RUNAS createmany -m $TESTFILE $((ilimit + 1)) &&
1509                 quota_error u $TSTUSR "create succeeded, expect EDQUOT"
1510
1511         $RUNAS unlinkmany $TESTFILE $ilimit || error "unlink files failed"
1512         wait_delete_completed
1513         sync_all_data || true
1514
1515         echo "Stop mds${MDSCOUNT}..."
1516         stop mds${MDSCOUNT}
1517
1518         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
1519                 error "clear quota failed"
1520
1521         echo "Start mds${MDSCOUNT}..."
1522         start mds${MDSCOUNT} $(mdsdevname $MDSCOUNT) $MDS_MOUNT_OPTS
1523         quota_init
1524
1525         wait_mdt_reint $QTYPE || error "reintegration failed"
1526
1527         # hardlimit should be cleared on slave during reintegration
1528         $RUNAS createmany -m $TESTFILE $((ilimit + 1)) ||
1529                 quota_error u $TSTUSR "create failed, expect success"
1530
1531         $RUNAS unlinkmany $TESTFILE $((ilimit + 1)) || error "unlink failed"
1532         rmdir $DIR/${tdir}-1 || error "unlink remote dir failed"
1533
1534         cleanup_quota_test
1535         resetquota -u $TSTUSR
1536 }
1537 run_test 7e "Quota reintegration (inode limits)"
1538
1539 # run dbench with quota enabled
1540 test_8() {
1541         local BLK_LIMIT="100g" #100G
1542         local FILE_LIMIT=1000000
1543
1544         setup_quota_test || error "setup quota failed with $?"
1545         trap cleanup_quota_test EXIT
1546
1547         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1548         set_ost_qtype $QTYPE || error "enable ost quota failed"
1549
1550         echo "Set enough high limit for user: $TSTUSR"
1551         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1552                 error "set user quota failed"
1553         echo "Set enough high limit for group: $TSTUSR"
1554         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1555                 error "set group quota failed"
1556         if is_project_quota_supported; then
1557                 change_project -sp $TSTPRJID $DIR/$tdir
1558                 echo "Set enough high limit for project: $TSTPRJID"
1559                 $LFS setquota -p $TSTPRJID -b 0 \
1560                         -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1561                         error "set project quota failed"
1562         fi
1563
1564         local duration=""
1565         [ "$SLOW" = "no" ] && duration=" -t 120"
1566         $RUNAS bash rundbench -D $DIR/$tdir 3 $duration ||
1567                 quota_error a $TSTUSR "dbench failed!"
1568
1569         is_project_quota_supported && change_project -C $DIR/$tdir
1570         cleanup_quota_test
1571         resetquota -u $TSTUSR
1572         resetquota -g $TSTUSR
1573         resetquota -p $TSTPRJID
1574 }
1575 run_test 8 "Run dbench with quota enabled"
1576
1577 # this check is just for test_9
1578 OST0_MIN=4900000 #4.67G
1579
1580 check_whether_skip () {
1581         local OST0_SIZE=$($LFS df $DIR | awk '/\[OST:0\]/ {print $4}')
1582         log "OST0_SIZE: $OST0_SIZE  required: $OST0_MIN"
1583         if [ $OST0_SIZE -lt $OST0_MIN ]; then
1584                 echo "WARN: OST0 has less than $OST0_MIN free, skip this test."
1585                 return 0
1586         else
1587                 return 1
1588         fi
1589 }
1590
1591 # run for fixing bug10707, it needs a big room. test for 64bit
1592 test_9() {
1593         local filesize=$((1024 * 9 / 2)) # 4.5G
1594
1595         check_whether_skip && return 0
1596
1597         setup_quota_test || error "setup quota failed with $?"
1598         trap cleanup_quota_test EXIT
1599
1600         set_ost_qtype "ug" || error "enable ost quota failed"
1601
1602         local TESTFILE="$DIR/$tdir/$tfile-0"
1603         local BLK_LIMIT=100G #100G
1604         local FILE_LIMIT=1000000
1605
1606         echo "Set block limit $BLK_LIMIT bytes to $TSTUSR.$TSTUSR"
1607
1608         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
1609                 "for user: $TSTUSR"
1610         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1611                 error "set user quota failed"
1612
1613         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
1614                 "for group: $TSTUSR"
1615         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1616                 error "set group quota failed"
1617
1618         quota_show_check a u $TSTUSR
1619         quota_show_check a g $TSTUSR
1620
1621         echo "Create test file"
1622         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1623         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1624
1625         log "Write the big file of 4.5G ..."
1626         $RUNAS $DD of=$TESTFILE count=$filesize ||
1627                 quota_error a $TSTUSR "write 4.5G file failure, expect success"
1628
1629         $SHOW_QUOTA_USER
1630         $SHOW_QUOTA_GROUP
1631
1632         cleanup_quota_test
1633         resetquota -u $TSTUSR
1634         resetquota -g $TSTUSR
1635
1636         $SHOW_QUOTA_USER
1637         $SHOW_QUOTA_GROUP
1638 }
1639 run_test 9 "Block limit larger than 4GB (b10707)"
1640
1641 test_10() {
1642         local TESTFILE=$DIR/$tdir/$tfile
1643
1644         setup_quota_test || error "setup quota failed with $?"
1645         trap cleanup_quota_test EXIT
1646
1647         # set limit to root user should fail
1648         $LFS setquota -u root -b 100G -B 500G -i 1K -I 1M $DIR &&
1649                 error "set limit for root user successfully, expect failure"
1650         $LFS setquota -g root -b 1T -B 10T -i 5K -I 100M $DIR &&
1651                 error "set limit for root group successfully, expect failure"
1652         $LFS setquota -p 0 -b 1T -B 10T -i 5K -I 100M $DIR &&
1653                 error "set limit for project 0 successfully, expect failure"
1654
1655         # root user can overrun quota
1656         set_ost_qtype "ug" || error "enable ost quota failed"
1657
1658         $LFS setquota -u $TSTUSR -b 0 -B 2M -i 0 -I 0 $DIR ||
1659                 error "set quota failed"
1660         quota_show_check b u $TSTUSR
1661
1662         $SETSTRIPE $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
1663         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1664
1665         runas -u 0 -g 0 $DD of=$TESTFILE count=3 oflag=sync ||
1666                 error "write failure, expect success"
1667
1668         cleanup_quota_test
1669         resetquota -u $TSTUSR
1670 }
1671 run_test 10 "Test quota for root user"
1672
1673 test_11() {
1674         local TESTFILE=$DIR/$tdir/$tfile
1675         setup_quota_test || error "setup quota failed with $?"
1676         trap cleanup_quota_test EXIT
1677
1678         set_mdt_qtype "ug" || error "enable mdt quota failed"
1679         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 1 $DIR ||
1680                 error "set quota failed"
1681
1682         touch "$TESTFILE"-0 || error "touch $TESTFILE-0 failed"
1683         touch "$TESTFILE"-1 || error "touch $TESTFILE-0 failed"
1684
1685         chown $TSTUSR.$TSTUSR "$TESTFILE"-0 || error "chown $TESTFILE-0 failed"
1686         chown $TSTUSR.$TSTUSR "$TESTFILE"-1 || error "chown $TESTFILE-1 failed"
1687
1688         $SHOW_QUOTA_USER
1689         local USED=$(getquota -u $TSTUSR global curinodes)
1690         [ $USED -ge 2 ] || error "Used inodes($USED) is less than 2"
1691
1692         cleanup_quota_test
1693         resetquota -u $TSTUSR
1694 }
1695 run_test 11 "Chown/chgrp ignores quota"
1696
1697 test_12a() {
1698         [ "$OSTCOUNT" -lt "2" ] && skip "needs >= 2 OSTs"
1699
1700         local blimit=22 # 22M
1701         local blk_cnt=$((blimit - 5))
1702         local TESTFILE0="$DIR/$tdir/$tfile"-0
1703         local TESTFILE1="$DIR/$tdir/$tfile"-1
1704
1705         setup_quota_test || error "setup quota failed with $?"
1706         trap cleanup_quota_test EXIT
1707
1708         set_ost_qtype "u" || error "enable ost quota failed"
1709         quota_show_check b u $TSTUSR
1710
1711         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $DIR ||
1712                 error "set quota failed"
1713
1714         $SETSTRIPE $TESTFILE0 -c 1 -i 0 || error "setstripe $TESTFILE0 failed"
1715         $SETSTRIPE $TESTFILE1 -c 1 -i 1 || error "setstripe $TESTFILE1 failed"
1716         chown $TSTUSR.$TSTUSR $TESTFILE0 || error "chown $TESTFILE0 failed"
1717         chown $TSTUSR.$TSTUSR $TESTFILE1 || error "chown $TESTFILE1 failed"
1718
1719         echo "Write to ost0..."
1720         $RUNAS $DD of=$TESTFILE0 count=$blk_cnt oflag=sync ||
1721                 quota_error a $TSTUSR "dd failed"
1722
1723         echo "Write to ost1..."
1724         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync &&
1725                 quota_error a $TSTUSR "dd succeed, expect EDQUOT"
1726
1727         echo "Free space from ost0..."
1728         rm -f $TESTFILE0
1729         wait_delete_completed
1730         sync_all_data || true
1731
1732         echo "Write to ost1 after space freed from ost0..."
1733         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync ||
1734                 quota_error a $TSTUSR "rebalancing failed"
1735
1736         cleanup_quota_test
1737         resetquota -u $TSTUSR
1738 }
1739 run_test 12a "Block quota rebalancing"
1740
1741 test_12b() {
1742         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
1743
1744         local ilimit=$((1024 * 2)) # 2k inodes
1745         local TESTFILE0=$DIR/$tdir/$tfile
1746         local TESTFILE1=$DIR/${tdir}-1/$tfile
1747
1748         setup_quota_test || error "setup quota failed with $?"
1749         trap cleanup_quota_test EXIT
1750
1751         $LFS mkdir -i 1 $DIR/${tdir}-1 || error "create remote dir failed"
1752         chmod 0777 $DIR/${tdir}-1
1753
1754         set_mdt_qtype "u" || error "enable mdt quota failed"
1755         quota_show_check f u $TSTUSR
1756
1757         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $ilimit $DIR ||
1758                 error "set quota failed"
1759
1760         echo "Create $ilimit files on mdt0..."
1761         $RUNAS createmany -m $TESTFILE0 $ilimit ||
1762                 quota_error u $TSTUSR "create failed, but expect success"
1763
1764         echo "Create files on mdt1..."
1765         $RUNAS createmany -m $TESTFILE1 1 &&
1766                 quota_error a $TSTUSR "create succeeded, expect EDQUOT"
1767
1768         echo "Free space from mdt0..."
1769         $RUNAS unlinkmany $TESTFILE0 $ilimit || error "unlink mdt0 files failed"
1770         wait_delete_completed
1771         sync_all_data || true
1772
1773         echo "Create files on mdt1 after space freed from mdt0..."
1774         $RUNAS createmany -m $TESTFILE1 $((ilimit / 2)) ||
1775                 quota_error a $TSTUSR "rebalancing failed"
1776
1777         $RUNAS unlinkmany $TESTFILE1 $((ilimit / 2)) ||
1778                 error "unlink mdt1 files failed"
1779         rmdir $DIR/${tdir}-1 || error "unlink remote dir failed"
1780
1781         cleanup_quota_test
1782         resetquota -u $TSTUSR
1783 }
1784 run_test 12b "Inode quota rebalancing"
1785
1786 test_13(){
1787         local TESTFILE=$DIR/$tdir/$tfile
1788         # the name of lwp on ost1 name is MDT0000-lwp-OST0000
1789         local procf="ldlm.namespaces.*MDT0000-lwp-OST0000.lru_size"
1790
1791         setup_quota_test || error "setup quota failed with $?"
1792         trap cleanup_quota_test EXIT
1793
1794         set_ost_qtype "u" || error "enable ost quota failed"
1795         quota_show_check b u $TSTUSR
1796
1797         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
1798                 error "set quota failed"
1799         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1800         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1801
1802         # clear the locks in cache first
1803         do_facet ost1 $LCTL set_param -n $procf=clear
1804         local nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1805         [ $nlock -eq 0 ] || error "$nlock cached locks"
1806
1807         # write to acquire the per-ID lock
1808         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
1809                 quota_error a $TSTUSR "dd failed"
1810
1811         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1812         [ $nlock -eq 1 ] || error "lock count($nlock) isn't 1"
1813
1814         # clear quota doesn't trigger per-ID lock cancellation
1815         resetquota -u $TSTUSR
1816         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1817         [ $nlock -eq 1 ] || error "per-ID lock is lost on quota clear"
1818
1819         # clear the per-ID lock
1820         do_facet ost1 $LCTL set_param -n $procf=clear
1821         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1822         [ $nlock -eq 0 ] || error "per-ID lock isn't cleared"
1823
1824         # spare quota should be released
1825         local OSTUUID=$(ostuuid_from_index 0)
1826         local limit=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1827         local space=$(getquota -u $TSTUSR $OSTUUID curspace)
1828         [ $limit -le $space ] ||
1829                 error "spare quota isn't released, limit:$limit, space:$space"
1830
1831         cleanup_quota_test
1832 }
1833 run_test 13 "Cancel per-ID lock in the LRU list"
1834
1835 test_15(){
1836         local LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB
1837
1838         wait_delete_completed
1839         sync_all_data || true
1840
1841         # test for user
1842         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1843                 error "set user quota failed"
1844         local TOTAL_LIMIT=$(getquota -u $TSTUSR global bhardlimit)
1845         [ $TOTAL_LIMIT -eq $LIMIT ] ||
1846                 error "(user) limit:$TOTAL_LIMIT, expect:$LIMIT, failed!"
1847         resetquota -u $TSTUSR
1848
1849         # test for group
1850         $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1851                 error "set group quota failed"
1852         TOTAL_LIMIT=$(getquota -g $TSTUSR global bhardlimit)
1853         [ $TOTAL_LIMIT -eq $LIMIT ] ||
1854                 error "(group) limits:$TOTAL_LIMIT, expect:$LIMIT, failed!"
1855         resetquota -g $TSTUSR
1856 }
1857 run_test 15 "Set over 4T block quota"
1858
1859 test_17sub() {
1860         local err_code=$1
1861         local BLKS=1    # 1M less than limit
1862         local TESTFILE=$DIR/$tdir/$tfile
1863
1864         setup_quota_test || error "setup quota failed with $?"
1865         trap cleanup_quota_test EXIT
1866
1867         # make sure the system is clean
1868         local USED=$(getquota -u $TSTUSR global curspace)
1869         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1870
1871         set_ost_qtype "ug" || error "enable ost quota failed"
1872         # make sure no granted quota on ost
1873         resetquota -u $TSTUSR
1874         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
1875                 error "set quota failed"
1876
1877         quota_show_check b u $TSTUSR
1878
1879         #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xa04
1880         lustre_fail mds 0xa04 $err_code
1881
1882         # write in background
1883         $RUNAS $DD of=$TESTFILE count=$BLKS oflag=direct &
1884         local DDPID=$!
1885
1886         sleep 2
1887         # write should be blocked and never finished
1888         if ! ps -p $DDPID  > /dev/null 2>&1; then
1889                 lustre_fail mds 0 0
1890                 quota_error u $TSTUSR "write finished incorrectly!"
1891         fi
1892
1893         lustre_fail mds 0 0
1894
1895         local count=0
1896         local timeout=30
1897         while [ true ]; do
1898                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1899                 count=$((count+1))
1900                 if [ $count -gt $timeout ]; then
1901                         quota_error u $TSTUSR "dd is not finished!"
1902                 fi
1903                 sleep 1
1904         done
1905
1906         sync; sync_all_data || true
1907
1908         USED=$(getquota -u $TSTUSR global curspace)
1909         [ $USED -ge $((BLKS * 1024)) ] || quota_error u $TSTUSR \
1910                 "Used space(${USED}K) is less than ${BLKS}M"
1911
1912         cleanup_quota_test
1913         resetquota -u $TSTUSR
1914 }
1915
1916 # DQACQ return recoverable error
1917 test_17() {
1918         echo "DQACQ return -ENOLCK"
1919         #define ENOLCK  37
1920         test_17sub 37 || error "Handle -ENOLCK failed"
1921
1922         echo "DQACQ return -EAGAIN"
1923         #define EAGAIN  11
1924         test_17sub 11 || error "Handle -EAGAIN failed"
1925
1926         echo "DQACQ return -ETIMEDOUT"
1927         #define ETIMEDOUT 110
1928         test_17sub 110 || error "Handle -ETIMEDOUT failed"
1929
1930         echo "DQACQ return -ENOTCONN"
1931         #define ENOTCONN 107
1932         test_17sub 107 || error "Handle -ENOTCONN failed"
1933 }
1934
1935 run_test 17 "DQACQ return recoverable error"
1936
1937 test_18_sub () {
1938         local io_type=$1
1939         local blimit="200m" # 200M
1940         local TESTFILE="$DIR/$tdir/$tfile"
1941
1942         setup_quota_test || error "setup quota failed with $?"
1943         trap cleanup_quota_test EXIT
1944
1945         set_ost_qtype "u" || error "enable ost quota failed"
1946         log "User quota (limit: $blimit)"
1947         $LFS setquota -u $TSTUSR -b 0 -B $blimit -i 0 -I 0 $MOUNT ||
1948                 error "set quota failed"
1949         quota_show_check b u $TSTUSR
1950
1951         $SETSTRIPE $TESTFILE -i 0 -c 1 || error "setstripe $TESTFILE failed"
1952         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1953
1954         local timeout=$(sysctl -n lustre.timeout)
1955
1956         if [ $io_type = "directio" ]; then
1957                 log "Write 100M (directio) ..."
1958                 $RUNAS $DD of=$TESTFILE count=100 oflag=direct &
1959         else
1960                 log "Write 100M (buffered) ..."
1961                 $RUNAS $DD of=$TESTFILE count=100 &
1962         fi
1963         local DDPID=$!
1964
1965         replay_barrier $SINGLEMDS
1966         log "Fail mds for $((2 * timeout)) seconds"
1967         fail $SINGLEMDS $((2 * timeout))
1968
1969         local count=0
1970         if at_is_enabled; then
1971                 timeout=$(at_max_get mds)
1972         else
1973                 timeout=$(lctl get_param -n timeout)
1974         fi
1975
1976         while [ true ]; do
1977                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1978                 if [ $((++count % (2 * timeout) )) -eq 0 ]; then
1979                         log "it took $count second"
1980                 fi
1981                 sleep 1
1982         done
1983
1984         log "(dd_pid=$DDPID, time=$count, timeout=$timeout)"
1985         sync
1986         cancel_lru_locks mdc
1987         cancel_lru_locks osc
1988         $SHOW_QUOTA_USER
1989
1990         local testfile_size=$(stat -c %s $TESTFILE)
1991         if [ $testfile_size -ne $((BLK_SZ * 1024 * 100)) ] ; then
1992                 quota_error u $TSTUSR "expect $((BLK_SZ * 1024 * 100))," \
1993                         "got ${testfile_size}. Verifying file failed!"
1994         fi
1995         cleanup_quota_test
1996         resetquota -u $TSTUSR
1997 }
1998
1999 # test when mds does failover, the ost still could work well
2000 # this test shouldn't trigger watchdog b=14840
2001 test_18() {
2002         # Clear dmesg so watchdog is not triggered by previous
2003         # test output
2004         do_facet ost1 dmesg -c > /dev/null
2005
2006         test_18_sub normal
2007         test_18_sub directio
2008
2009         # check if watchdog is triggered
2010         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
2011         local watchdog=$(awk '/Service thread pid/ && /was inactive/ \
2012                         { print; }' $TMP/lustre-log-${TESTNAME}.log)
2013         [ -z "$watchdog" ] || error "$watchdog"
2014         rm -f $TMP/lustre-log-${TESTNAME}.log
2015 }
2016 run_test 18 "MDS failover while writing, no watchdog triggered (b14840)"
2017
2018 test_19() {
2019         local blimit=5 # 5M
2020         local TESTFILE=$DIR/$tdir/$tfile
2021
2022         setup_quota_test || error "setup quota failed with $?"
2023         trap cleanup_quota_test EXIT
2024
2025         set_ost_qtype $QTYPE || error "enable ost quota failed"
2026
2027         # bind file to a single OST
2028         $SETSTRIPE -c 1 $TESTFILE || error "setstripe $TESTFILE failed"
2029         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2030
2031         echo "Set user quota (limit: ${blimit}M)"
2032         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2033                 error "set user quota failed"
2034         quota_show_check b u $TSTUSR
2035         echo "Update quota limits"
2036         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2037                 error "set group quota failed"
2038         quota_show_check b u $TSTUSR
2039
2040         # first wirte might be cached
2041         $RUNAS $DD of=$TESTFILE count=$((blimit + 1))
2042         cancel_lru_locks osc
2043         $SHOW_QUOTA_USER
2044         $RUNAS $DD of=$TESTFILE count=$((blimit + 1)) seek=$((blimit + 1)) &&
2045                 quota_error u $TSTUSR "Write success, expect failure"
2046         $SHOW_QUOTA_USER
2047
2048         cleanup_quota_test
2049         resetquota -u $TSTUSR
2050 }
2051 run_test 19 "Updating admin limits doesn't zero operational limits(b14790)"
2052
2053 test_20() { # b15754
2054         local LSTR=(2g 1t 4k 3m) # limits strings
2055         # limits values
2056         local LVAL=($((2*1024*1024)) $((1*1024*1024*1024)) $((4*1024)) \
2057                     $((3*1024*1024)))
2058
2059         resetquota -u $TSTUSR
2060
2061         $LFS setquota -u $TSTUSR --block-softlimit ${LSTR[0]} \
2062                 $MOUNT || error "could not set quota limits"
2063         $LFS setquota -u $TSTUSR --block-hardlimit ${LSTR[1]} \
2064                                 --inode-softlimit ${LSTR[2]} \
2065                                 --inode-hardlimit ${LSTR[3]} \
2066                                 $MOUNT || error "could not set quota limits"
2067
2068         [ "$(getquota -u $TSTUSR global bsoftlimit)" = "${LVAL[0]}" ] ||
2069                 error "bsoftlimit was not set properly"
2070         [ "$(getquota -u $TSTUSR global bhardlimit)" = "${LVAL[1]}" ] ||
2071                 error "bhardlimit was not set properly"
2072         [ "$(getquota -u $TSTUSR global isoftlimit)" = "${LVAL[2]}" ] ||
2073                 error "isoftlimit was not set properly"
2074         [ "$(getquota -u $TSTUSR global ihardlimit)" = "${LVAL[3]}" ] ||
2075                 error "ihardlimit was not set properly"
2076
2077         resetquota -u $TSTUSR
2078 }
2079 run_test 20 "Test if setquota specifiers work properly (b15754)"
2080
2081 test_21_sub() {
2082         local testfile=$1
2083         local blk_number=$2
2084         local seconds=$3
2085
2086         local time=$(($(date +%s) + seconds))
2087         while [ $(date +%s) -lt $time ]; do
2088                 $RUNAS $DD of=$testfile count=$blk_number > /dev/null 2>&1
2089         done
2090 }
2091
2092 # run for fixing bug16053, setquota shouldn't fail when writing and
2093 # deleting are happening
2094 test_21() {
2095         local TESTFILE="$DIR/$tdir/$tfile"
2096         local BLIMIT=10 # 10G
2097         local ILIMIT=1000000
2098
2099         setup_quota_test || error "setup quota failed with $?"
2100         trap cleanup_quota_test EXIT
2101
2102         set_ost_qtype $QTYPE || error "Enable ost quota failed"
2103
2104         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for user: $TSTUSR"
2105         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}G -i 0 -I $ILIMIT $MOUNT ||
2106                 error "set user quota failed"
2107         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for group: $TSTUSR"
2108         $LFS setquota -g $TSTUSR -b 0 -B $BLIMIT -i 0 -I $ILIMIT $MOUNT ||
2109                 error "set group quota failed"
2110         if is_project_quota_supported; then
2111                 log "Set limit(block:${BLIMIT}G; file:$LIMIT) for " \
2112                         "project: $TSTPRJID"
2113                 $LFS setquota -p $TSTPRJID -b 0 -B $BLIMIT -i 0 -I $ILIMIT \
2114                          $MOUNT || error "set project quota failed"
2115         fi
2116
2117         # repeat writing on a 1M file
2118         test_21_sub ${TESTFILE}_1 1 30 &
2119         local DDPID1=$!
2120         # repeat writing on a 128M file
2121         test_21_sub ${TESTFILE}_2 128 30 &
2122         local DDPID2=$!
2123
2124         local time=$(($(date +%s) + 30))
2125         local i=1
2126         while [ $(date +%s) -lt $time ]; do
2127                 log "Set quota for $i times"
2128                 $LFS setquota -u $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
2129                         -I $((ILIMIT + i)) $MOUNT ||
2130                                 error "Set user quota failed"
2131                 $LFS setquota -g $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
2132                         -I $((ILIMIT + i)) $MOUNT ||
2133                                 error "Set group quota failed"
2134                 if is_project_quota_supported; then
2135                         $LFS setquota -p $TSTPRJID -b 0 -B \
2136                         "$((BLIMIT + i))G"  -i 0 -I $((ILIMIT + i)) $MOUNT ||
2137                                 error "Set project quota failed"
2138                 fi
2139                 i=$((i+1))
2140                 sleep 1
2141         done
2142
2143         local count=0
2144         while [ true ]; do
2145                 if ! ps -p ${DDPID1} > /dev/null 2>&1; then break; fi
2146                 count=$((count+1))
2147                 if [ $count -gt 60 ]; then
2148                         quota_error a $TSTUSR "dd should be finished!"
2149                 fi
2150                 sleep 1
2151         done
2152         echo "(dd_pid=$DDPID1, time=$count)successful"
2153
2154         count=0
2155         while [ true ]; do
2156                 if ! ps -p ${DDPID2} > /dev/null 2>&1; then break; fi
2157                 count=$((count+1))
2158                 if [ $count -gt 60 ]; then
2159                         quota_error a $TSTUSR "dd should be finished!"
2160                 fi
2161                 sleep 1
2162         done
2163         echo "(dd_pid=$DDPID2, time=$count)successful"
2164
2165         cleanup_quota_test
2166         resetquota -u $TSTUSR
2167         resetquota -g $TSTUSR
2168         resetquota -p $TSTPRJID
2169 }
2170 run_test 21 "Setquota while writing & deleting (b16053)"
2171
2172 # enable/disable quota enforcement permanently
2173 test_22() {
2174         echo "Set both mdt & ost quota type as ug"
2175         local qtype="ug"
2176         is_project_quota_supported && qtype=$QTYPE
2177         set_mdt_qtype $qtype || error "enable mdt quota failed"
2178         set_ost_qtype $qtype || error "enable ost quota failed"
2179
2180         echo "Restart..."
2181         stopall || error "failed to stopall (1)"
2182         mount
2183         setupall
2184
2185         echo "Verify if quota is enabled"
2186         local qtype1=$(mdt_quota_type)
2187         [ $qtype1 != $qtype ] && error "mdt quota setting is lost"
2188         qtype=$(ost_quota_type)
2189         [ $qtype1 != $qtype ] && error "ost quota setting is lost"
2190
2191         echo "Set both mdt & ost quota type as none"
2192         set_mdt_qtype "none" || error "disable mdt quota failed"
2193         set_ost_qtype "none" || error "disable ost quota failed"
2194
2195         echo "Restart..."
2196         stopall || error "failed to stopall (2)"
2197         mount
2198         setupall
2199         quota_init
2200
2201         echo "Verify if quota is disabled"
2202         qtype=$(mdt_quota_type)
2203         [ $qtype != "none" ] && error "mdt quota setting is lost"
2204         qtype=$(ost_quota_type)
2205         [ $qtype != "none" ] && error "ost quota setting is lost"
2206
2207         return 0
2208 }
2209 run_test 22 "enable/disable quota by 'lctl conf_param/set_param -P'"
2210
2211 test_23_sub() {
2212         local TESTFILE="$DIR/$tdir/$tfile"
2213         local LIMIT=$1
2214
2215         setup_quota_test || error "setup quota failed with $?"
2216         trap cleanup_quota_test EXIT
2217
2218         set_ost_qtype $QTYPE || error "Enable ost quota failed"
2219
2220         # test for user
2221         log "User quota (limit: $LIMIT MB)"
2222         $LFS setquota -u $TSTUSR -b 0 -B "$LIMIT"M -i 0 -I 0 $DIR ||
2223                 error "set quota failed"
2224         quota_show_check b u $TSTUSR
2225
2226         $SETSTRIPE $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
2227         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2228
2229         log "Step1: trigger EDQUOT with O_DIRECT"
2230         log "Write half of file"
2231         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) oflag=direct ||
2232                 quota_error u $TSTUSR "(1) Write failure, expect success." \
2233                         "limit=$LIMIT"
2234         log "Write out of block quota ..."
2235         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 + 1)) seek=$((LIMIT/2)) \
2236                 oflag=direct conv=notrunc &&
2237                 quota_error u $TSTUSR "(2) Write success, expect EDQUOT." \
2238                         "limit=$LIMIT"
2239         log "Step1: done"
2240
2241         log "Step2: rewrite should succeed"
2242         $RUNAS $DD of=$TESTFILE count=1 oflag=direct conv=notrunc||
2243                 quota_error u $TSTUSR "(3) Write failure, expect success." \
2244                         "limit=$LIMIT"
2245         log "Step2: done"
2246
2247         cleanup_quota_test
2248
2249         local OST0_UUID=$(ostuuid_from_index 0)
2250         local OST0_QUOTA_USED=$(getquota -u $TSTUSR $OST0_UUID curspace)
2251         [ $OST0_QUOTA_USED -ne 0 ] &&
2252                 ($SHOW_QUOTA_USER; \
2253                 quota_error u $TSTUSR "quota isn't released")
2254         $SHOW_QUOTA_USER
2255         resetquota -u $TSTUSR
2256 }
2257
2258 test_23() {
2259         [ $(facet_fstype ost1) == "zfs" ] &&
2260                 skip "Overwrite in place is not guaranteed to be " \
2261                 "space neutral on ZFS"
2262
2263         local OST0_MIN=$((6 * 1024)) # 6MB, extra space for meta blocks.
2264         check_whether_skip && return 0
2265         log "run for 4MB test file"
2266         test_23_sub 4
2267
2268         OST0_MIN=$((60 * 1024)) # 60MB, extra space for meta blocks.
2269         check_whether_skip && return 0
2270         log "run for 40MB test file"
2271         test_23_sub 40
2272 }
2273 run_test 23 "Quota should be honored with directIO (b16125)"
2274
2275 test_24() {
2276         local blimit=5 # 5M
2277         local TESTFILE="$DIR/$tdir/$tfile"
2278
2279         setup_quota_test || error "setup quota failed with $?"
2280         trap cleanup_quota_test EXIT
2281
2282         set_ost_qtype $QTYPE || error "enable ost quota failed"
2283
2284         # bind file to a single OST
2285         $SETSTRIPE -c 1 $TESTFILE || error "setstripe $TESTFILE failed"
2286         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2287
2288         echo "Set user quota (limit: ${blimit}M)"
2289         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2290                 error "set quota failed"
2291
2292         # overrun quota by root user
2293         runas -u 0 -g 0 $DD of=$TESTFILE count=$((blimit + 1)) ||
2294                 error "write failure, expect success"
2295         cancel_lru_locks osc
2296         sync_all_data || true
2297
2298         $SHOW_QUOTA_USER | grep '*' || error "no matching *"
2299
2300         cleanup_quota_test
2301         resetquota -u $TSTUSR
2302 }
2303 run_test 24 "lfs draws an asterix when limit is reached (b16646)"
2304
2305 test_27a() { # b19612
2306         $LFS quota $TSTUSR $DIR &&
2307                 error "lfs succeeded with no type, but should have failed"
2308         $LFS setquota $TSTUSR $DIR &&
2309                 error "lfs succeeded with no type, but should have failed"
2310         return 0
2311 }
2312 run_test 27a "lfs quota/setquota should handle wrong arguments (b19612)"
2313
2314 test_27b() { # b20200
2315         $LFS setquota -u $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
2316                 error "lfs setquota failed with uid argument"
2317         $LFS setquota -g $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
2318                 error "lfs stequota failed with gid argument"
2319         if is_project_quota_supported; then
2320                 $LFS setquota -p $TSTPRJID -b 1000 -B 1000 -i 1000 -I \
2321                         1000 $DIR || error \
2322                                 "lfs stequota failed with projid argument"
2323         fi
2324         $SHOW_QUOTA_USERID || error "lfs quota failed with uid argument"
2325         $SHOW_QUOTA_GROUPID || error "lfs quota failed with gid argument"
2326         if is_project_quota_supported; then
2327                 $SHOW_QUOTA_PROJID ||
2328                         error "lfs quota failed with projid argument"
2329         fi
2330         resetquota -u $TSTUSR
2331         resetquota -g $TSTUSR
2332         resetquota -p $TSTPRJID
2333         return 0
2334 }
2335 run_test 27b "lfs quota/setquota should handle user/group/project ID (b20200)"
2336
2337 test_27c() {
2338         local limit
2339
2340         $LFS setquota -u $TSTID -b 30M -B 3T $DIR ||
2341                 error "lfs setquota failed"
2342
2343         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $3}')
2344         [ $limit != "30M" ] && error "softlimit $limit isn't human-readable"
2345         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $4}')
2346         [ $limit != "3T" ] && error "hardlimit $limit isn't human-readable"
2347
2348         $LFS setquota -u $TSTID -b 1500M -B 18500G $DIR ||
2349                 error "lfs setquota for $TSTID failed"
2350
2351         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $3}')
2352         [ $limit != "1.465G" ] && error "wrong softlimit $limit"
2353         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $4}')
2354         [ $limit != "18.07T" ] && error "wrong hardlimit $limit"
2355
2356         $LFS quota -u $TSTID -v -h $DIR | grep -q "Total allocated" ||
2357                 error "total allocated inode/block limit not printed"
2358
2359         resetquota -u $TSTUSR
2360 }
2361 run_test 27c "lfs quota should support human-readable output"
2362
2363 test_27d() {
2364         local softlimit=1.5
2365         local hardlimit=2.3
2366         local limit
2367
2368         $LFS setquota -u $TSTID -b ${softlimit}p -B ${hardlimit}P $DIR ||
2369                 error "set fraction block limit failed"
2370         limit=$($LFS quota -u $TSTID -h $DIR | grep $DIR | awk '{print $3}')
2371         [ $limit == ${softlimit}P ] || error "get fraction softlimit failed"
2372         limit=$($LFS quota -u $TSTID -h $DIR | grep $DIR | awk '{print $4}')
2373         [ $limit == ${hardlimit}P ] || error "get fraction hardlimit failed"
2374
2375         resetquota -u $TSTUSR
2376 }
2377 run_test 27d "lfs setquota should support fraction block limit"
2378
2379 test_30() {
2380         local LIMIT=4 # 4MB
2381         local TESTFILE="$DIR/$tdir/$tfile"
2382         local GRACE=10
2383
2384         setup_quota_test || error "setup quota failed with $?"
2385         trap cleanup_quota_test EXIT
2386
2387         set_ost_qtype "u" || error "enable ost quota failed"
2388
2389         $SETSTRIPE $TESTFILE -i 0 -c 1 || error "setstripe $TESTFILE failed"
2390         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2391
2392         $LFS setquota -t -u --block-grace $GRACE --inode-grace \
2393                 $MAX_IQ_TIME $DIR || error "set grace time failed"
2394         $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
2395                 error "set quota failed"
2396         $RUNAS $DD of=$TESTFILE count=$((LIMIT * 2)) || true
2397         cancel_lru_locks osc
2398         sleep $GRACE
2399         $LFS setquota -u $TSTUSR -B 0 $DIR || error "clear quota failed"
2400         # over-quota flag has not yet settled since we do not trigger async
2401         # events based on grace time period expiration
2402         $SHOW_QUOTA_USER
2403         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=4 || true
2404         cancel_lru_locks osc
2405         # now over-quota flag should be settled and further writes should fail
2406         $SHOW_QUOTA_USER
2407         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=4 &&
2408                 error "grace times were reset"
2409         # cleanup
2410         cleanup_quota_test
2411         resetquota -u $TSTUSR
2412         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
2413                 $MAX_IQ_TIME $DIR || error "restore grace time failed"
2414 }
2415 run_test 30 "Hard limit updates should not reset grace times"
2416
2417 # basic usage tracking for user & group
2418 test_33() {
2419         local INODES=10 # 10 files
2420         local BLK_CNT=2 # of 2M each
2421         local TOTAL_BLKS=$((INODES * BLK_CNT * 1024))
2422
2423         setup_quota_test || error "setup quota failed with $?"
2424         trap cleanup_quota_test EXIT
2425
2426         # make sure the system is clean
2427         local USED=$(getquota -u $TSTID global curspace)
2428         [ $USED -ne 0 ] &&
2429                 error "Used space ($USED) for user $TSTID isn't 0."
2430         USED=$(getquota -g $TSTID global curspace)
2431         [ $USED -ne 0 ] &&
2432                 error "Used space ($USED) for group $TSTID isn't 0."
2433         if is_project_quota_supported; then
2434                 USED=$(getquota -p $TSTPRJID global curspace)
2435                 [ $USED -ne 0 ] && error \
2436                         "Used space ($USED) for project $TSTPRJID isn't 0."
2437         fi
2438
2439         echo "Write files..."
2440         for i in $(seq 0 $INODES); do
2441                 $RUNAS $DD of=$DIR/$tdir/$tfile-$i count=$BLK_CNT 2>/dev/null ||
2442                         error "write failed"
2443                         is_project_quota_supported &&
2444                                 change_project -p $TSTPRJID $DIR/$tdir/$tfile-$i
2445                 echo "Iteration $i/$INODES completed"
2446         done
2447         cancel_lru_locks osc
2448
2449         echo "Wait for setattr on objects finished..."
2450         wait_delete_completed
2451
2452         sync; sync_all_data || true
2453
2454         echo "Verify disk usage after write"
2455         USED=$(getquota -u $TSTID global curspace)
2456         [ $USED -lt $TOTAL_BLKS ] &&
2457                 error "Used space for user $TSTID:$USED, expected:$TOTAL_BLKS"
2458         USED=$(getquota -g $TSTID global curspace)
2459         [ $USED -lt $TOTAL_BLKS ] &&
2460                 error "Used space for group $TSTID:$USED, expected:$TOTAL_BLKS"
2461         if is_project_quota_supported; then
2462                 USED=$(getquota -p $TSTPRJID global curspace)
2463                 [ $USED -lt $TOTAL_BLKS ] && error \
2464                         "Used space for project $TSTPRJID:$USED, expected:$TOTAL_BLKS"
2465         fi
2466
2467         echo "Verify inode usage after write"
2468         USED=$(getquota -u $TSTID global curinodes)
2469         [ $USED -lt $INODES ] &&
2470                 error "Used inode for user $TSTID is $USED, expected $INODES"
2471         USED=$(getquota -g $TSTID global curinodes)
2472         [ $USED -lt $INODES ] &&
2473                 error "Used inode for group $TSTID is $USED, expected $INODES"
2474         if is_project_quota_supported; then
2475                 USED=$(getquota -p $TSTPRJID global curinodes)
2476                 [ $USED -lt $INODES ] && error \
2477                         "Used inode for project $TSTPRJID is $USED, expected $INODES"
2478         fi
2479
2480         cleanup_quota_test
2481
2482         echo "Verify disk usage after delete"
2483         USED=$(getquota -u $TSTID global curspace)
2484         [ $USED -eq 0 ] || error "Used space for user $TSTID isn't 0. $USED"
2485         USED=$(getquota -u $TSTID global curinodes)
2486         [ $USED -eq 0 ] || error "Used inodes for user $TSTID isn't 0. $USED"
2487         USED=$(getquota -g $TSTID global curspace)
2488         [ $USED -eq 0 ] || error "Used space for group $TSTID isn't 0. $USED"
2489         USED=$(getquota -g $TSTID global curinodes)
2490         [ $USED -eq 0 ] || error "Used inodes for group $TSTID isn't 0. $USED"
2491         if is_project_quota_supported; then
2492                 USED=$(getquota -p $TSTPRJID global curspace)
2493                 [ $USED -eq 0 ] ||
2494                         error "Used space for project $TSTPRJID isn't 0. $USED"
2495                 USED=$(getquota -p $TSTPRJID global curinodes)
2496                 [ $USED -eq 0 ] ||
2497                         error "Used inodes for project $TSTPRJID isn't 0. $USED"
2498         fi
2499 }
2500 run_test 33 "Basic usage tracking for user & group & project"
2501
2502 # usage transfer test for user & group & project
2503 test_34() {
2504         local BLK_CNT=2 # 2MB
2505         local project_supported="no"
2506
2507         is_project_quota_supported && project_supported="yes"
2508         setup_quota_test || error "setup quota failed with $?"
2509         trap cleanup_quota_test EXIT
2510
2511         # make sure the system is clean
2512         local USED=$(getquota -u $TSTID global curspace)
2513         [ $USED -ne 0 ] && error "Used space ($USED) for user $TSTID isn't 0."
2514         USED=$(getquota -g $TSTID global curspace)
2515         [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTID isn't 0."
2516
2517         local USED=$(getquota -u $TSTID2 global curspace)
2518         [ $USED -ne 0 ] && error "Used space ($USED) for user $TSTID2 isn't 0."
2519         if [ $project_supported == "yes" ]; then
2520                 USED=$(getquota -p $TSTPRJID global curspace)
2521                 [ $USED -ne 0 ] && error \
2522                         "Used space ($USED) for Project $TSTPRJID isn't 0."
2523         fi
2524
2525         echo "Write file..."
2526         $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
2527                 error "write failed"
2528         cancel_lru_locks osc
2529         sync; sync_all_data || true
2530
2531         echo "chown the file to user $TSTID"
2532         chown $TSTID $DIR/$tdir/$tfile || error "chown failed"
2533
2534         echo "Wait for setattr on objects finished..."
2535         wait_delete_completed
2536
2537         BLK_CNT=$((BLK_CNT * 1024))
2538
2539         echo "Verify disk usage for user $TSTID"
2540         USED=$(getquota -u $TSTID global curspace)
2541         [ $USED -lt $BLK_CNT ] &&
2542                 error "Used space for user $TSTID is ${USED}, expected $BLK_CNT"
2543         USED=$(getquota -u $TSTID global curinodes)
2544         [ $USED -ne 1 ] &&
2545                 error "Used inodes for user $TSTID is $USED, expected 1"
2546
2547         echo "chgrp the file to group $TSTID"
2548         chgrp $TSTID $DIR/$tdir/$tfile || error "chgrp failed"
2549
2550         echo "Wait for setattr on objects finished..."
2551         wait_delete_completed
2552
2553         echo "Verify disk usage for group $TSTID"
2554         USED=$(getquota -g $TSTID global curspace)
2555         [ $USED -ge $BLK_CNT ] ||
2556                 error "Used space for group $TSTID is $USED, expected $BLK_CNT"
2557         USED=$(getquota -g $TSTID global curinodes)
2558         [ $USED -eq 1 ] ||
2559                 error "Used inodes for group $TSTID is $USED, expected 1"
2560
2561         # chown won't change the ost object group. LU-4345 */
2562         echo "chown the file to user $TSTID2"
2563         chown $TSTID2 $DIR/$tdir/$tfile || error "chown to $TSTID2 failed"
2564
2565         echo "Wait for setattr on objects finished..."
2566         wait_delete_completed
2567
2568         echo "change_project project id to $TSTPRJID"
2569         [ $project_supported == "yes" ] &&
2570                 change_project -p $TSTPRJID $DIR/$tdir/$tfile
2571         echo "Wait for setattr on objects finished..."
2572         wait_delete_completed
2573
2574         echo "Verify disk usage for user $TSTID2/$TSTID and group $TSTID"
2575         USED=$(getquota -u $TSTID2 global curspace)
2576         [ $USED -lt $BLK_CNT ] &&
2577                 error "Used space for user $TSTID2 is $USED, expected $BLK_CNT"
2578         USED=$(getquota -u $TSTID global curspace)
2579         [ $USED -ne 0 ] &&
2580                 error "Used space for user $TSTID is $USED, expected 0"
2581         USED=$(getquota -g $TSTID global curspace)
2582         [ $USED -lt $BLK_CNT ] &&
2583                 error "Used space for group $TSTID is $USED, expected $BLK_CNT"
2584         if [ $project_supported == "yes" ]; then
2585                 USED=$(getquota -p $TSTPRJID global curspace)
2586                 [ $USED -lt $BLK_CNT ] && error \
2587                         "Used space for group $TSTPRJID is $USED, expected $BLK_CNT"
2588         fi
2589
2590         cleanup_quota_test
2591 }
2592 run_test 34 "Usage transfer for user & group & project"
2593
2594 # usage is still accessible across restart
2595 test_35() {
2596         local BLK_CNT=2 # 2 MB
2597
2598         setup_quota_test || error "setup quota failed with $?"
2599         trap cleanup_quota_test EXIT
2600
2601         echo "Write file..."
2602         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
2603                 error "write failed"
2604         is_project_quota_supported &&
2605                 change_project -p $TSTPRJID $DIR/$tdir/$tfile
2606         cancel_lru_locks osc
2607
2608         echo "Wait for setattr on objects finished..."
2609         wait_delete_completed
2610
2611         sync; sync_all_data || true
2612
2613         echo "Save disk usage before restart"
2614         local ORIG_USR_SPACE=$(getquota -u $TSTID global curspace)
2615         [ $ORIG_USR_SPACE -eq 0 ] &&
2616                 error "Used space for user $TSTID is 0, expected ${BLK_CNT}M"
2617         local ORIG_USR_INODES=$(getquota -u $TSTID global curinodes)
2618         [ $ORIG_USR_INODES -eq 0 ] &&
2619                 error "Used inodes for user $TSTID is 0, expected 1"
2620         echo "User $TSTID: ${ORIG_USR_SPACE}KB $ORIG_USR_INODES inodes"
2621         local ORIG_GRP_SPACE=$(getquota -g $TSTID global curspace)
2622         [ $ORIG_GRP_SPACE -eq 0 ] &&
2623                 error "Used space for group $TSTID is 0, expected ${BLK_CNT}M"
2624         local ORIG_GRP_INODES=$(getquota -g $TSTID global curinodes)
2625         [ $ORIG_GRP_INODES -eq 0 ] &&
2626                 error "Used inodes for group $TSTID is 0, expected 1"
2627         echo "Group $TSTID: ${ORIG_GRP_SPACE}KB $ORIG_GRP_INODES inodes"
2628
2629         if is_project_quota_supported; then
2630                 local ORIG_PRJ_SPACE=$(getquota -p $TSTPRJID global curspace)
2631                 [ $ORIG_PRJ_SPACE -eq 0 ] && error \
2632                         "Used space for project $TSTPRJID is 0, expected ${BLK_CNT}M"
2633                 local ORIG_PRJ_INODES=$(getquota -p $TSTPRJID global curinodes)
2634                 [ $ORIG_PRJ_INODES -eq 0 ] && error \
2635                         "Used inodes for project $TSTPRJID is 0, expected 1"
2636                 echo "Project $TSTPRJID: ${ORIG_PRJ_SPACE}KB $ORIG_PRJ_INODES inodes"
2637         fi
2638
2639         log "Restart..."
2640         stopall
2641         setupall
2642         quota_init
2643
2644         echo "Verify disk usage after restart"
2645         local USED=$(getquota -u $TSTID global curspace)
2646         [ $USED -eq $ORIG_USR_SPACE ] ||
2647                 error "Used space for user $TSTID changed from " \
2648                         "$ORIG_USR_SPACE to $USED"
2649         USED=$(getquota -u $TSTID global curinodes)
2650         [ $USED -eq $ORIG_USR_INODES ] ||
2651                 error "Used inodes for user $TSTID changed from " \
2652                         "$ORIG_USR_INODES to $USED"
2653         USED=$(getquota -g $TSTID global curspace)
2654         [ $USED -eq $ORIG_GRP_SPACE ] ||
2655                 error "Used space for group $TSTID changed from " \
2656                         "$ORIG_GRP_SPACE to $USED"
2657         USED=$(getquota -g $TSTID global curinodes)
2658         [ $USED -eq $ORIG_GRP_INODES ] ||
2659                 error "Used inodes for group $TSTID changed from " \
2660                         "$ORIG_GRP_INODES to $USED"
2661         if [ $project_supported == "yes" ]; then
2662                 USED=$(getquota -p $TSTPRJID global curinodes)
2663                 [ $USED -eq $ORIG_PRJ_INODES ] ||
2664                         error "Used inodes for project $TSTPRJID " \
2665                                 "changed from $ORIG_PRJ_INODES to $USED"
2666                 USED=$(getquota -p $TSTPRJID global curspace)
2667                 [ $USED -eq $ORIG_PRJ_SPACE ] ||
2668                         error "Used space for project $TSTPRJID "\
2669                                 "changed from $ORIG_PRJ_SPACE to $USED"
2670         fi
2671
2672         # check if the vfs_dq_init() is called before writing
2673         echo "Append to the same file..."
2674         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT seek=1 2>/dev/null ||
2675                 error "write failed"
2676         cancel_lru_locks osc
2677         sync; sync_all_data || true
2678
2679         echo "Verify space usage is increased"
2680         USED=$(getquota -u $TSTID global curspace)
2681         [ $USED -gt $ORIG_USR_SPACE ] ||
2682                 error "Used space for user $TSTID isn't increased" \
2683                         "orig:$ORIG_USR_SPACE, now:$USED"
2684         USED=$(getquota -g $TSTID global curspace)
2685         [ $USED -gt $ORIG_GRP_SPACE ] ||
2686                 error "Used space for group $TSTID isn't increased" \
2687                         "orig:$ORIG_GRP_SPACE, now:$USED"
2688         if [ $project_supported == "yes" ]; then
2689                 USED=$(getquota -p $TSTPRJID global curspace)
2690                 [ $USED -gt $ORIG_PRJ_SPACE ] ||
2691                         error "Used space for project $TSTPRJID isn't " \
2692                                 "increased orig:$ORIG_PRJ_SPACE, now:$USED"
2693         fi
2694
2695         cleanup_quota_test
2696 }
2697 run_test 35 "Usage is still accessible across reboot"
2698
2699 # chown/chgrp to the file created with MDS_OPEN_DELAY_CREATE
2700 # LU-5006
2701 test_37() {
2702         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.93) ] &&
2703                 skip "Old server doesn't have LU-5006 fix."
2704
2705         setup_quota_test || error "setup quota failed with $?"
2706         trap cleanup_quota_test EXIT
2707
2708         # make sure the system is clean
2709         local USED=$(getquota -u $TSTID global curspace)
2710         [ $USED -ne 0 ] &&
2711                 error "Used space ($USED) for user $TSTID isn't 0."
2712
2713         # create file with MDS_OPEN_DELAY_CREATE flag
2714         $SETSTRIPE -c 1 -i 0 $DIR/$tdir/$tfile ||
2715                 error "Create file failed"
2716         # write to file
2717         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 conv=notrunc \
2718                 oflag=sync || error "Write file failed"
2719         # chown to the file
2720         chown $TSTID $DIR/$tdir/$tfile || error "Chown to file failed"
2721
2722         # wait for setattr on objects finished..."
2723         wait_delete_completed
2724
2725         USED=$(getquota -u $TSTID global curspace)
2726         [ $USED -ne 0 ] || quota_error u $TSTUSR "Used space is 0"
2727
2728         cleanup_quota_test
2729 }
2730 run_test 37 "Quota accounted properly for file created by 'lfs setstripe'"
2731
2732 # LU-8801
2733 test_38() {
2734         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.8.60) ] &&
2735                 skip "Old server doesn't have LU-8801 fix."
2736
2737         [ "$UID" != 0 ] && skip_env "must run as root" && return
2738
2739         setup_quota_test || error "setup quota failed with $?"
2740         trap cleanup_quota_test EXIT
2741
2742         # make sure the system is clean
2743         local USED=$(getquota -u $TSTID global curspace)
2744         [ $USED -ne 0 ] &&
2745                 error "Used space ($USED) for user $TSTID isn't 0."
2746         USED=$(getquota -u $TSTID2 global curspace)
2747         [ $USED -ne 0 ] &&
2748                 error "Used space ($USED) for user $TSTID2 isn't 0."
2749
2750         local TESTFILE="$DIR/$tdir/$tfile"
2751         local file_cnt=10000
2752
2753         # Generate id entries in accounting file
2754         echo "Create $file_cnt files..."
2755         for i in `seq $file_cnt`; do
2756                 touch $TESTFILE-$i
2757                 chown $((file_cnt - i)):$((file_cnt - i)) $TESTFILE-$i ||
2758                         error "failed to chown $TESTFILE-$i"
2759         done
2760         cancel_lru_locks osc
2761         sync; sync_all_data || true
2762
2763         local procf="osd-$(facet_fstype $SINGLEMDS).$FSNAME-MDT0000"
2764         procf=${procf}.quota_slave.acct_user
2765         local accnt_cnt
2766
2767         acct_cnt=$(do_facet mds1 $LCTL get_param $procf | grep "id:" | \
2768                    awk '{if ($3 < 10000) {print $3}}' | wc -l)
2769         echo "Found $acct_cnt id entries"
2770
2771         [ $file_cnt -eq $acct_cnt ] || {
2772                 do_facet mds1 $LCTL get_param $procf
2773                 error "skipped id entries"
2774         }
2775
2776         cleanup_quota_test
2777 }
2778 run_test 38 "Quota accounting iterator doesn't skip id entries"
2779
2780 test_39() {
2781         local TESTFILE="$DIR/$tdir/project"
2782         ! is_project_quota_supported &&
2783                 skip "Project quota is not supported"
2784
2785         setup_quota_test || error "setup quota failed with $?"
2786
2787         touch $TESTFILE
2788         projectid=$(lfs project $TESTFILE | awk '{print $1}')
2789         [ $projectid -ne 0 ] &&
2790                 error "Project id should be 0 not $projectid"
2791         change_project -p 1024 $TESTFILE
2792         projectid=$(lfs project $TESTFILE | awk '{print $1}')
2793         [ $projectid -ne 1024 ] &&
2794                 error "Project id should be 1024 not $projectid"
2795
2796         stopall || error "failed to stopall (1)"
2797         mount
2798         setupall
2799         projectid=$(lfs project $TESTFILE | awk '{print $1}')
2800         [ $projectid -ne 1024 ] &&
2801                 error "Project id should be 1024 not $projectid"
2802
2803         cleanup_quota_test
2804 }
2805 run_test 39 "Project ID interface works correctly"
2806
2807 test_40a() {
2808         ! is_project_quota_supported &&
2809                 skip "Project quota is not supported"
2810         local dir1="$DIR/$tdir/dir1"
2811         local dir2="$DIR/$tdir/dir2"
2812
2813         setup_quota_test || error "setup quota failed with $?"
2814
2815         mkdir -p $dir1 $dir2
2816         change_project -sp 1 $dir1 && touch $dir1/1
2817         change_project -sp 2 $dir2
2818
2819         ln $dir1/1 $dir2/1_link &&
2820                 error "Hard link across different project quota should fail"
2821         rm -rf $dir1 $dir2
2822
2823         cleanup_quota_test
2824 }
2825 run_test 40a "Hard link across different project ID"
2826
2827 test_40b() {
2828         ! is_project_quota_supported &&
2829                 skip "Project quota is not supported"
2830         local dir1="$DIR/$tdir/dir1"
2831         local dir2="$DIR/$tdir/dir2"
2832
2833         setup_quota_test || error "setup quota failed with $?"
2834         mkdir -p $dir1 $dir2
2835         change_project -sp 1 $dir1 && touch $dir1/1
2836         change_project -sp 2 $dir2
2837
2838         mv $dir1/1 $dir2/2 || error "mv failed $?"
2839         local projid=$(lfs project $dir2/2 | awk '{print $1}')
2840         if [ "$projid" != "2" ]; then
2841                 error "project id expected 2 not $projid"
2842         fi
2843         rm -rf $dir1 $dir2
2844         cleanup_quota_test
2845 }
2846 run_test 40b "Mv across different project ID"
2847
2848 test_40c() {
2849         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
2850                 ! is_project_quota_supported &&
2851                         skip "Project quota is not supported"
2852
2853         setup_quota_test || error "setup quota failed with $?"
2854         local dir="$DIR/$tdir/dir"
2855
2856         mkdir -p $dir && change_project -sp 1 $dir
2857         $LFS mkdir -i 1 $dir/remote_dir || error "create remote dir failed"
2858         local projid=$(lfs project -d $dir/remote_dir | awk '{print $1}')
2859         [ "$projid" != "1" ] && error "projid id expected 1 not $projid"
2860         touch $dir/remote_dir/file
2861         #verify inherit works file for remote dir.
2862         local projid=$(lfs project -d $dir/remote_dir/file | awk '{print $1}')
2863         [ "$projid" != "1" ] &&
2864                 error "file under remote dir expected 1 not $projid"
2865
2866         #Agent inode should be ignored for project quota
2867         USED=$(getquota -p 1 global curinodes)
2868         [ "$USED" != "3" ] &&
2869                 error "file count expected 3 got $USED"
2870
2871         rm -rf $dir
2872         cleanup_quota_test
2873         return 0
2874 }
2875 run_test 40c "Remote child Dir inherit project quota properly"
2876
2877 test_50() {
2878         ! is_project_quota_supported &&
2879                 skip "Project quota is not supported"
2880
2881         setup_quota_test || error "setup quota failed with $?"
2882         local dir="$DIR/$tdir/dir"
2883
2884         mkdir $dir && change_project -p 1 $dir
2885         count=$($LFS find --projid 1 $DIR | wc -l)
2886         [ "$count" != 1 ] && error "expected 1 but got $count"
2887
2888         rm -rf $dir
2889         cleanup_quota_test
2890 }
2891 run_test 50 "Test if lfs find --projid works"
2892
2893 test_51() {
2894         ! is_project_quota_supported &&
2895                 skip "Project quota is not supported"
2896         setup_quota_test || error "setup quota failed with $?"
2897         local dir="$DIR/$tdir/dir"
2898
2899         mkdir $dir && change_project -sp 1 $dir
2900         local used=$(getquota -p 1 global curinodes)
2901         [ $used != "1" ] && error "expected 1 got $used"
2902
2903         touch $dir/1
2904         touch $dir/2
2905         cp $dir/2 $dir/3
2906         used=$(getquota -p 1 global curinodes)
2907         [ $used != "4" ] && error "expected 4 got $used"
2908
2909         $DD if=/dev/zero of=$DIR/$tdir/6 bs=1M count=1
2910         #try cp to dir
2911         cp $DIR/$tdir/6 $dir/6
2912         used=$(getquota -p 1 global curinodes)
2913         [ $used != "5" ] && error "expected 5 got $used"
2914
2915         #try mv to dir
2916         mv $DIR/$tdir/6 $dir/7
2917         used=$(getquota -p 1 global curinodes)
2918         [ $used != "6" ] && error "expected 6 got $used"
2919
2920         rm -rf $dir
2921         cleanup_quota_test
2922 }
2923 run_test 51 "Test project accounting with mv/cp"
2924
2925 test_52() {
2926         ! is_project_quota_supported &&
2927                 skip "Project quota is not supported"
2928         setup_quota_test || error "setup quota failed with $?"
2929         local dir="$DIR/$tdir/dir"
2930         mkdir $dir && change_project -sp 1 $dir
2931
2932         touch $DIR/$tdir/file
2933         #Try renaming a file into the project.  This should fail.
2934         for num in $(seq 1 2000); do
2935                 mrename $DIR/$tdir/file $dir/file >&/dev/null &&
2936                         error "rename should fail"
2937         done
2938         rm -rf $dir
2939         cleanup_quota_test
2940 }
2941 run_test 52 "Rename across different project ID"
2942
2943 test_53() {
2944         ! is_project_quota_supported &&
2945                 skip "Project quota is not supported"
2946         setup_quota_test || error "setup quota failed with $?"
2947         local dir="$DIR/$tdir/dir"
2948         mkdir $dir && change_project -s $dir
2949         lfs project -d $dir | grep P || error "inherit attribute should be set"
2950
2951         change_project -C $dir
2952         lfs project -d $dir | grep P &&
2953                 error "inherit attribute should be cleared"
2954
2955         rm -rf $dir
2956         cleanup_quota_test
2957 }
2958 run_test 53 "Project inherit attribute could be cleared"
2959
2960 test_54() {
2961         ! is_project_quota_supported &&
2962                 skip "Project quota is not supported"
2963         setup_quota_test || error "setup quota failed with $?"
2964         trap cleanup_quota_test EXIT
2965         local testfile="$DIR/$tdir/$tfile-0"
2966
2967         #set project ID/inherit attribute
2968         change_project -sp $TSTPRJID $DIR/$tdir
2969         $RUNAS createmany -m ${testfile} 100 ||
2970                 error "create many files failed"
2971
2972         local proj_count=$(lfs project -r $DIR/$tdir | wc -l)
2973         # one more count for directory itself */
2974         ((proj_count++))
2975
2976         #check project
2977         local proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
2978         [ $proj_count1 -eq 0 ] || error "c1: expected 0 got $proj_count1"
2979
2980         proj_count1=$(lfs project -rcp $((TSTPRJID+1)) $DIR/$tdir | wc -l)
2981         [ $proj_count1 -eq $proj_count ] ||
2982                         error "c2: expected $proj_count got $proj_count1"
2983
2984         #clear project but with kept projid
2985         change_project -rCk $DIR/$tdir
2986         proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
2987         [ $proj_count1 -eq $proj_count ] ||
2988                         error "c3: expected $proj_count got $proj_count1"
2989
2990         #verify projid untouched.
2991         proj_count1=$(lfs project -r $DIR/$tdir | grep -c $TSTPRJID)
2992         ((proj_count1++))
2993         [ $proj_count1 -eq $proj_count ] ||
2994                         error "c4: expected $proj_count got $proj_count1"
2995
2996         # test -0 option
2997         lfs project $DIR/$tdir -cr -0 | xargs -0 lfs project -s
2998         proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
2999         [ $proj_count1 -eq 0 ] || error "c5: expected 0 got $proj_count1"
3000
3001         #this time clear all
3002         change_project -rC $DIR/$tdir
3003         proj_count1=$(lfs project -r $DIR/$tdir | grep -c $TSTPRJID)
3004         [ $proj_count1 -eq 0 ] ||
3005                         error "c6: expected 0 got $proj_count1"
3006         #cleanup
3007         unlinkmany ${testfile} 100 ||
3008                 error "unlink many files failed"
3009
3010         cleanup_quota_test
3011 }
3012 run_test 54 "basic lfs project interface test"
3013
3014 test_55() {
3015         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.10.58) ] &&
3016                 skip "Not supported before 2.10.58."
3017         setup_quota_test || error "setup quota failed with $?"
3018
3019         set_ost_qtype $QTYPE || error "enable ost quota failed"
3020         quota_init
3021
3022         #add second group to TSTUSR
3023         usermod -G $TSTUSR,$TSTUSR2 $TSTUSR
3024
3025         #prepare test file
3026         $RUNAS dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1024 count=100000 ||
3027         error "failed to dd"
3028
3029         cancel_lru_locks osc
3030         sync; sync_all_data || true
3031
3032         $LFS setquota -g $TSTUSR2 -b 0 -B 50M $DIR ||
3033         error "failed to setquota on group $TSTUSR2"
3034
3035         $LFS quota -v -g $TSTUSR2 $DIR
3036
3037         runas -u $TSTUSR -g $TSTUSR2 chgrp $TSTUSR2 $DIR/$tdir/$tfile &&
3038         error "chgrp should failed with -EDQUOT"
3039
3040         USED=$(getquota -g $TSTUSR2 global curspace)
3041         echo "$USED"
3042
3043         $LFS setquota -g $TSTUSR2 -b 0 -B 300M $DIR ||
3044         error "failed to setquota on group $TSTUSR2"
3045
3046         $LFS quota -v -g $TSTUSR2 $DIR
3047
3048         runas -u $TSTUSR -g $TSTUSR2 chgrp $TSTUSR2 $DIR/$tdir/$tfile ||
3049         error "chgrp should succeed"
3050
3051         $LFS quota -v -g $TSTUSR2 $DIR
3052
3053         resetquota -g $TSTUSR2
3054         cleanup_quota_test
3055 }
3056 run_test 55 "Chgrp should be affected by group quota"
3057
3058 test_56() {
3059         setup_quota_test || error "setup quota failed with $?"
3060
3061         set_ost_qtype $QTYPE || error "enable ost quota failed"
3062         quota_init
3063
3064         $LFS setquota -t -u -b 10 -i 10 $DIR ||
3065                 erro "failed to set grace time for usr quota"
3066         grace_time=$($LFS quota -t -u $DIR | grep "Block grace time:" |
3067                      awk '{print $4 $8}')
3068         if [ "x$grace_time" != "x10s;10s" ]; then
3069                 $LFS quota -t -u $DIR
3070                 error "expected grace time: 10s;10s, got:$grace_time"
3071         fi
3072
3073         cleanup_quota_test
3074 }
3075 run_test 56 "lfs quota -t should work well"
3076
3077 test_57() {
3078         setup_quota_test || error "setup quota failed with $?"
3079
3080         local dir="$DIR/$tdir/dir"
3081         mkdir -p $dir
3082         mkfifo $dir/pipe
3083         #try to change pipe file should not hang and return failure
3084         wait_update_facet client "$LFS project -sp 1 $dir/pipe 2>&1 |
3085                 awk -F ':' '{ print \\\$2 }'" \
3086                         " failed to get xattr for '$dir/pipe'" || return 1
3087         #command can process further if it hit some errors
3088         touch $dir/aaa $dir/bbb
3089         mkdir $dir/subdir -p
3090         touch $dir/subdir/aaa $dir/subdir/bbb
3091         #create one invalid link file
3092         ln -s $dir/not_exist_file $dir/ccc
3093         local cnt=$(lfs project -r $dir 2>/dev/null | wc -l)
3094         [ $cnt -eq 5 ] || error "expected 5 got $cnt"
3095
3096         cleanup_quota_test
3097 }
3098 run_test 57 "lfs project could tolerate errors"
3099
3100 test_59() {
3101         [ "$(facet_fstype $SINGLEMDS)" != "ldiskfs" ] &&
3102                 skip "ldiskfs only test"
3103         disable_project_quota
3104         setup_quota_test || error "setup quota failed with $?"
3105         quota_init
3106
3107         local testfile="$DIR/$tdir/$tfile-0"
3108         #make sure it did not crash kernel
3109         touch $testfile && lfs project -sp 1 $testfile
3110
3111         enable_project_quota
3112         cleanup_quota_test
3113 }
3114 run_test 59 "lfs project dosen't crash kernel with project disabled"
3115
3116 test_60() {
3117         setup_quota_test || error "setup quota failed with $?"
3118         trap cleanup_quota_test EXIT
3119         local testfile=$DIR/$tdir/$tfile
3120         local limit=100
3121
3122         set_mdt_qtype "ug" || error "enable mdt quota failed"
3123
3124         $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $limit $DIR ||
3125                 error "set quota failed"
3126         quota_show_check a g $TSTUSR
3127
3128         chown $TSTUSR.$TSTUSR $DIR/$tdir || error "chown $DIR/$tdir failed"
3129         chmod g+s $DIR/$tdir || error "chmod g+s failed"
3130         $RUNAS createmany -m ${testfile} $((limit-1)) ||
3131                 error "create many files failed"
3132
3133         $RUNAS touch $DIR/$tdir/foo && error "regular user should fail"
3134
3135         # root user can overrun quota
3136         runas -u 0 -g 0 touch $DIR/$tdir/foo ||
3137                 error "root user should succeed"
3138
3139         cleanup_quota_test
3140         resetquota -g $TSTUSR
3141 }
3142 run_test 60 "Test quota for root with setgid"
3143
3144 # test default quota
3145 test_default_quota() {
3146         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.51) ] &&
3147                 skip "Not supported before 2.11.51."
3148
3149         local qtype=$1
3150         local qpool=$2
3151         local qid=$TSTUSR
3152         local qprjid=$TSTPRJID
3153         local qdtype="-U"
3154         local qs="-b"
3155         local qh="-B"
3156         local LIMIT=20480 #20M disk space
3157         local TESTFILE="$DIR/$tdir/$tfile-0"
3158
3159         [ $qtype == "-p" ] && ! is_project_quota_supported &&
3160                 echo "Project quota is not supported" && return 0
3161
3162         [ $qtype == "-u" ] && qdtype="-U"
3163         [ $qtype == "-g" ] && qdtype="-G"
3164         [ $qtype == "-p" ] && {
3165                 qdtype="-P"
3166                 qid=$qprjid
3167         }
3168
3169         [ $qpool == "meta" ] && {
3170                 LIMIT=10240 #10K inodes
3171                 qs="-i"
3172                 qh="-I"
3173         }
3174
3175         setup_quota_test || error "setup quota failed with $?"
3176         trap cleanup_quota_test EXIT
3177
3178         quota_init
3179
3180         # enable mdt/ost quota
3181         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
3182         set_ost_qtype $QTYPE || error "enable ost quota failed"
3183
3184         log "set to use default quota"
3185         $LFS setquota $qtype $qid -d $DIR ||
3186                 error "set $qid to use default quota failed"
3187
3188         log "set default quota"
3189         $LFS setquota $qdtype $qs ${LIMIT} $qh ${LIMIT} $DIR ||
3190                 error "set $qid default quota failed"
3191
3192         log "get default quota"
3193         $LFS quota $qdtype $DIR || error "get default quota failed"
3194
3195         if [ $qpool == "data" ]; then
3196                 local SLIMIT=$($LFS quota $qdtype $DIR | grep "$MOUNT" | \
3197                                                         awk '{print $2}')
3198                 [ $SLIMIT -eq $LIMIT ] ||
3199                         error "the returned default quota is wrong"
3200         else
3201                 local SLIMIT=$($LFS quota $qdtype $DIR | grep "$MOUNT" | \
3202                                                         awk '{print $5}')
3203                 [ $SLIMIT -eq $LIMIT ] ||
3204                         error "the returned default quota is wrong"
3205         fi
3206
3207         # make sure the system is clean
3208         local USED=$(getquota $qtype $qid global curspace)
3209         [ $USED -ne 0 ] && error "Used space for $qid isn't 0."
3210
3211         $SETSTRIPE $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
3212         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
3213
3214         [ $qtype == "-p" ] && change_project -sp $TSTPRJID $DIR/$tdir
3215
3216         log "Test not out of quota"
3217         if [ $qpool == "data" ]; then
3218                 $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 >> 10)) oflag=sync ||
3219                         quota_error $qtype $qid "write failed, expect succeed"
3220         else
3221                 $RUNAS createmany -m $TESTFILE $((LIMIT/2)) ||
3222                         quota_error $qtype $qid "create failed, expect succeed"
3223
3224                 unlinkmany $TESTFILE $((LIMIT/2))
3225         fi
3226
3227         log "Test out of quota"
3228         # flush cache, ensure noquota flag is set on client
3229         cancel_lru_locks osc
3230         cancel_lru_locks mdc
3231         sync; sync_all_data || true
3232         if [ $qpool == "data" ]; then
3233                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync &&
3234                         quota_error $qtype $qid "write succeed, expect EDQUOT"
3235         else
3236                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) &&
3237                         quota_error $qtype $qid "create succeed, expect EDQUOT"
3238
3239                 unlinkmany $TESTFILE $((LIMIT*2))
3240         fi
3241
3242         log "Increase default quota"
3243         # increase default quota
3244         $LFS setquota $qdtype $qs $((LIMIT*3)) $qh $((LIMIT*3)) $DIR ||
3245                 error "set default quota failed"
3246
3247         cancel_lru_locks osc
3248         cancel_lru_locks mdc
3249         sync; sync_all_data || true
3250         if [ $qpool == "data" ]; then
3251                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync ||
3252                         quota_error $qtype $qid "write failed, expect succeed"
3253         else
3254                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) ||
3255                         quota_error $qtype $qid "create failed, expect succeed"
3256
3257                 unlinkmany $TESTFILE $((LIMIT*2))
3258         fi
3259
3260         log "Set quota to override default quota"
3261         $LFS setquota $qtype $qid $qs ${LIMIT} $qh ${LIMIT} $DIR ||
3262                 error "set $qid quota failed"
3263
3264         cancel_lru_locks osc
3265         cancel_lru_locks mdc
3266         sync; sync_all_data || true
3267         if [ $qpool == "data" ]; then
3268                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync &&
3269                         quota_error $qtype $qid "write succeed, expect EQUOT"
3270         else
3271                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) &&
3272                         quota_error $qtype $qid "create succeed, expect EQUOT"
3273
3274                 unlinkmany $TESTFILE $((LIMIT*2))
3275         fi
3276
3277         log "Set to use default quota again"
3278         $LFS setquota $qtype $qid -d $DIR ||
3279                 error "set $qid to use default quota failed"
3280
3281         cancel_lru_locks osc
3282         cancel_lru_locks mdc
3283         sync; sync_all_data || true
3284         if [ $qpool == "data" ]; then
3285                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync ||
3286                         quota_error $qtype $qid "write failed, expect succeed"
3287         else
3288                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) ||
3289                         quota_error $qtype $qid "create failed, expect succeed"
3290
3291                 unlinkmany $TESTFILE $((LIMIT*2))
3292         fi
3293
3294         log "Cleanup"
3295         rm -f $TESTFILE
3296         wait_delete_completed || error "wait_delete_completed failed"
3297         sync_all_data || true
3298         $LFS setquota $qdtype -b 0 -B 0 -i 0 -I 0 $DIR ||
3299                 error "reset default quota failed"
3300         $LFS setquota $qtype $qid -b 0 -B 0 -i 0 -I 0 $DIR ||
3301                 error "reset quota failed"
3302
3303         cleanup_quota_test
3304 }
3305
3306 test_61() {
3307         test_default_quota "-u" "data"
3308         test_default_quota "-u" "meta"
3309         test_default_quota "-g" "data"
3310         test_default_quota "-g" "meta"
3311         test_default_quota "-p" "data"
3312         test_default_quota "-p" "meta"
3313 }
3314 run_test 61 "default quota tests"
3315
3316 test_62() {
3317         ! is_project_quota_supported &&
3318                 skip "Project quota is not supported"
3319          [[ "$(chattr -h 2>&1)" =~ "project" ]] ||
3320                 skip "chattr did not support project quota"
3321         setup_quota_test || error "setup quota failed with $?"
3322         local testdir=$DIR/$tdir/
3323
3324         $RUNAS mkdir -p $testdir || error "failed to mkdir"
3325         change_project -s $testdir
3326         [[ $($LFS project -d $testdir) =~ "P" ]] ||
3327                 error "inherit attribute should be set"
3328         # chattr used FS_IOC_SETFLAGS ioctl
3329         $RUNAS chattr -P $testdir &&
3330                 error "regular user clear inherit should fail"
3331         [[ $($LFS project -d $testdir) =~ "P" ]] ||
3332                 error "inherit attribute should still be set"
3333         chattr -P $testdir || error "root failed to clear inherit"
3334         [[ $($LFS project -d $testdir) =~ "P" ]] &&
3335                 error "inherit attribute should be cleared"
3336         cleanup_quota_test
3337 }
3338 run_test 62 "Project inherit should be only changed by root"
3339
3340 test_dom() {
3341         [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.55) ] &&
3342                 skip "Not supported before 2.11.55" && return
3343
3344         local qtype=$1
3345         local qid=$TSTUSR
3346         local dd_failed=false
3347         local tdir_dom=${tdir}_dom
3348         local LIMIT=20480 #20M
3349
3350         [ $qtype == "p" ] && ! is_project_quota_supported &&
3351                 echo "Project quota is not supported" && return 0
3352
3353         [ $qtype == "p" ] && qid=$TSTPRJID
3354
3355         setup_quota_test || error "setup quota failed with $?"
3356         trap cleanup_quota_test EXIT
3357
3358         quota_init
3359
3360         # enable mdt/ost quota
3361         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
3362         set_ost_qtype $QTYPE || error "enable ost quota failed"
3363
3364         # make sure the system is clean
3365         local USED=$(getquota -$qtype $qid global curspace)
3366         [ $USED -ne 0 ] && error "Used space for $qid isn't 0."
3367
3368         chown $TSTUSR.$TSTUSR $DIR/$tdir || error "chown $tdir failed"
3369
3370         mkdir $DIR/$tdir_dom || error "mkdir $tdir_dom failed"
3371         $SETSTRIPE -E 1M -L mdt $DIR/$tdir_dom ||
3372                 error "setstripe $tdir_dom failed"
3373         chown $TSTUSR.$TSTUSR $DIR/$tdir_dom || error "chown $tdir_dom failed"
3374
3375         [ $qtype == "p" ] && {
3376                 change_project -sp $TSTPRJID $DIR/$tdir
3377                 change_project -sp $TSTPRJID $DIR/$tdir_dom
3378         }
3379
3380         $LFS setquota -$qtype $qid -b $LIMIT -B $LIMIT $DIR ||
3381                 error "set $qid quota failed"
3382
3383         for ((i = 0; i < $((LIMIT/2048)); i++)); do
3384                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3385                                                                 dd_failed=true
3386         done
3387
3388         $dd_failed && quota_error $qtype $qid "write failed, expect succeed"
3389
3390         for ((i = $((LIMIT/2048)); i < $((LIMIT/1024 + 10)); i++)); do
3391                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3392                                                                 dd_failed=true
3393         done
3394
3395         $dd_failed || quota_error $qtype $qid "write succeed, expect EDQUOT"
3396
3397         rm -f $DIR/$tdir_dom/*
3398
3399         # flush cache, ensure noquota flag is set on client
3400         cancel_lru_locks osc
3401         cancel_lru_locks mdc
3402         sync; sync_all_data || true
3403
3404         dd_failed=false
3405
3406         $RUNAS $DD of=$DIR/$tdir/file count=$((LIMIT/2048)) oflag=sync ||
3407                 quota_error $qtype $qid "write failed, expect succeed"
3408
3409         for ((i = 0; i < $((LIMIT/2048 + 10)); i++)); do
3410                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3411                                                                 dd_failed=true
3412         done
3413
3414         $dd_failed || quota_error $qtype $TSTID "write succeed, expect EDQUOT"
3415
3416         rm -f $DIR/$tdir/*
3417         rm -f $DIR/$tdir_dom/*
3418
3419         # flush cache, ensure noquota flag is set on client
3420         cancel_lru_locks osc
3421         cancel_lru_locks mdc
3422         sync; sync_all_data || true
3423
3424         dd_failed=false
3425
3426         for ((i = 0; i < $((LIMIT/2048)); i++)); do
3427                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3428                                                                 dd_failed=true
3429         done
3430
3431         $dd_failed && quota_error $qtype $qid "write failed, expect succeed"
3432
3433         $RUNAS $DD of=$DIR/$tdir/file count=$((LIMIT/2048 + 10)) oflag=sync &&
3434                 quota_error $qtype $qid "write succeed, expect EDQUOT"
3435
3436         rm -f $DIR/$tdir/*
3437         rm -fr $DIR/$tdir_dom
3438
3439         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
3440                 error "reset usr quota failed"
3441
3442         cleanup_quota_test
3443 }
3444
3445 test_63() {
3446         test_dom "u"
3447         test_dom "g"
3448         test_dom "p"
3449 }
3450 run_test 63 "quota on DoM tests"
3451
3452 quota_fini()
3453 {
3454         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
3455         if $PQ_CLEANUP; then
3456                 disable_project_quota
3457         fi
3458 }
3459 reset_quota_settings
3460 quota_fini
3461
3462 cd $ORIG_PWD
3463 complete $SECONDS
3464 check_and_cleanup_lustre
3465 export QUOTA_AUTO=$QUOTA_AUTO_OLD
3466 exit_status