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