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