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