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