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