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