Whamcloud - gitweb
LU-797 tests: fix ost-pools test timeout issues on b1_8
[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 ALWAYS_EXCEPT="$SANITY_QUOTA_EXCEPT"
14 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
15
16 [ "$ALWAYS_EXCEPT$EXCEPT" ] &&
17         echo "Skipping tests: `echo $ALWAYS_EXCEPT $EXCEPT`"
18
19 TMP=${TMP:-/tmp}
20
21 ORIG_PWD=${PWD}
22 TSTID=${TSTID:-60000}
23 TSTID2=${TSTID2:-60001}
24 TSTUSR=${TSTUSR:-"quota_usr"}
25 TSTUSR2=${TSTUSR2:-"quota_2usr"}
26 BLK_SZ=1024
27 MAX_DQ_TIME=604800
28 MAX_IQ_TIME=604800
29
30 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
31 . $LUSTRE/tests/test-framework.sh
32 init_test_env $@
33 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
34 init_logging
35 DIRECTIO=${DIRECTIO:-$LUSTRE/tests/directio}
36 SINGLEMDS=mds
37
38 [ $MDSCOUNT -gt 1 ] && skip "CMD case" && exit 0
39
40 require_dsh_mds || exit 0
41 require_dsh_ost || exit 0
42
43 # XXX Once we drop the interoperability with old server (< 2.3.50), the
44 #     sanity-quota-old.sh should be removed.
45 if [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.50) ]; then
46         exec $LUSTRE/tests/sanity-quota-old.sh
47 fi
48
49 # if e2fsprogs support quota feature?
50 if [ "$FSTYPE" = "ldiskfs" ] &&
51         ! $DEBUGFS -c -R supported_features | grep -q 'quota'; then
52         skip "e2fsprogs doesn't support quota" && exit 0
53 fi
54
55 [ "$SLOW" = "no" ] && EXCEPT_SLOW="9 18 21"
56
57 QUOTALOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log}
58
59 [ "$QUOTALOG" ] && rm -f $QUOTALOG || true
60
61 DIR=${DIR:-$MOUNT}
62 DIR2=${DIR2:-$MOUNT2}
63
64 QUOTA_AUTO_OLD=$QUOTA_AUTO
65 export QUOTA_AUTO=0
66
67 check_and_setup_lustre
68
69 LOVNAME=`lctl get_param -n llite.*.lov.common_name | tail -n 1`
70 OSTCOUNT=`lctl get_param -n lov.$LOVNAME.numobd`
71
72 SHOW_QUOTA_USER="$LFS quota -v -u $TSTUSR $DIR"
73 SHOW_QUOTA_USERID="$LFS quota -v -u $TSTID $DIR"
74 SHOW_QUOTA_USER2="$LFS quota -v -u $TSTUSR2 $DIR"
75 SHOW_QUOTA_GROUP="$LFS quota -v -g $TSTUSR $DIR"
76 SHOW_QUOTA_GROUPID="$LFS quota -v -g $TSTID $DIR"
77 SHOW_QUOTA_GROUP2="$LFS quota -v -g $TSTUSR2 $DIR"
78 SHOW_QUOTA_INFO_USER="$LFS quota -t -u $DIR"
79 SHOW_QUOTA_INFO_GROUP="$LFS quota -t -g $DIR"
80
81 build_test_filter
82
83 lustre_fail() {
84         local fail_node=$1
85         local fail_loc=$2
86         local fail_val=${3:-0}
87
88         if [ $fail_node == "mds" ] || [ $fail_node == "mds_ost" ]; then
89                 do_facet $SINGLEMDS "lctl set_param fail_val=$fail_val"
90                 do_facet $SINGLEMDS "lctl set_param fail_loc=$fail_loc"
91         fi
92
93         if [ $fail_node == "ost" ] || [ $fail_node == "mds_ost" ]; then
94                 for num in `seq $OSTCOUNT`; do
95                         do_facet ost$num "lctl set_param fail_val=$fail_val"
96                         do_facet ost$num "lctl set_param fail_loc=$fail_loc"
97                 done
98         fi
99 }
100
101 RUNAS="runas -u $TSTID -g $TSTID"
102 RUNAS2="runas -u $TSTID2 -g $TSTID2"
103 DD="dd if=/dev/zero bs=1M"
104
105 FAIL_ON_ERROR=false
106
107 check_runas_id_ret $TSTUSR $TSTUSR $RUNAS ||
108         error "Please create user $TSTUSR($TSTID) and group $TSTUSR($TSTID)"
109 check_runas_id_ret $TSTUSR2 $TSTUSR2 $RUNAS2 ||
110         error "Please create user $TSTUSR2($TSTID2) and group $TSTUSR2($TSTID2)"
111
112 # clear quota limits for a user or a group
113 # usage: resetquota -u username
114 #        resetquota -g groupname
115
116 resetquota() {
117         [ "$#" != 2 ] && error "resetquota: wrong number of arguments: $#"
118         [ "$1" != "-u" -a "$1" != "-g" ] &&
119                 error "resetquota: wrong specifier $1 passed"
120
121         $LFS setquota "$1" "$2" -b 0 -B 0 -i 0 -I 0 $MOUNT ||
122                 error "clear quota for [type:$1 name:$2] failed"
123         # give a chance to slave to release space
124         sleep 1
125 }
126
127 quota_scan() {
128         local LOCAL_UG=$1
129         local LOCAL_ID=$2
130
131         if [ "$LOCAL_UG" == "a" -o "$LOCAL_UG" == "u" ]; then
132                 $LFS quota -v -u $LOCAL_ID $DIR
133                 log "Files for user ($LOCAL_ID):"
134                 ($LFS find -user $LOCAL_ID $DIR | head -n 4 |
135                         xargs stat 2>/dev/null)
136         fi
137
138         if [ "$LOCAL_UG" == "a" -o "$LOCAL_UG" == "g" ]; then
139                 $LFS quota -v -u $LOCAL_ID $DIR
140                 log "Files for group ($LOCAL_ID):"
141                 ($LFS find -group $LOCAL_ID $DIR | head -n 4 |
142                         xargs stat 2>/dev/null)
143         fi
144 }
145
146 quota_error() {
147         quota_scan $1 $2
148         shift 2
149         error "$*"
150 }
151
152 quota_log() {
153         quota_scan $1 $2
154         shift 2
155         log "$*"
156 }
157
158 # get quota for a user or a group
159 # usage: getquota -u|-g <username>|<groupname> global|<obd_uuid> \
160 #                 bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace
161 #
162 getquota() {
163         local spec
164         local uuid
165
166         [ "$#" != 4 ] && error "getquota: wrong number of arguments: $#"
167         [ "$1" != "-u" -a "$1" != "-g" ] &&
168                 error "getquota: wrong u/g specifier $1 passed"
169
170         uuid="$3"
171
172         case "$4" in
173                 curspace)   spec=1;;
174                 bsoftlimit) spec=2;;
175                 bhardlimit) spec=3;;
176                 bgrace)     spec=4;;
177                 curinodes)  spec=5;;
178                 isoftlimit) spec=6;;
179                 ihardlimit) spec=7;;
180                 igrace)     spec=8;;
181                 *)          error "unknown quota parameter $4";;
182         esac
183
184         [ "$uuid" = "global" ] && uuid=$DIR
185
186         $LFS quota -v "$1" "$2" $DIR |
187                 awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") \
188                 { if (NF == 1) { getline } else { num++ } ; print $num;} }' \
189                 | tr -d "*"
190 }
191
192 # set mdt quota type
193 # usage: set_mdt_qtype ug|u|g|none
194 set_mdt_qtype() {
195         local qtype=$1
196         local varsvc=${SINGLEMDS}_svc
197         local cmd
198         do_facet mgs $LCTL conf_param $FSNAME.quota.mdt=$qtype
199         if $(facet_up $SINGLEMDS); then
200                 cmd="$LCTL get_param -n "
201                 cmd=${cmd}osd-$FSTYPE.${!varsvc}
202                 cmd=${cmd}.quota_slave.enabled
203
204                 wait_update_facet $SINGLEMDS "$cmd" "$qtype" || return 1
205         fi
206         return 0
207 }
208
209 # set ost quota type
210 # usage: set_ost_quota_type ug|u|g|none
211 set_ost_qtype() {
212         local qtype=$1
213         local varsvc
214         local osts=$(get_facets OST)
215         local cmd
216         do_facet mgs $LCTL conf_param $FSNAME.quota.ost=$qtype
217         # we have to make sure each OST received config changes
218         for ost in ${osts//,/ }; do
219                 varsvc=${ost}_svc
220                 cmd="$LCTL get_param -n "
221                 cmd=${cmd}osd-$FSTYPE.${!varsvc}
222                 cmd=${cmd}.quota_slave.enabled
223
224                 if $(facet_up $ost); then
225                         wait_update_facet $ost "$cmd" "$qtype" || return 1
226                 fi
227         done
228         return 0
229 }
230
231 wait_reintegration() {
232         local ntype=$1
233         local qtype=$2
234         local max=$3
235         local result="glb[1],slv[1],reint[0]"
236         local varsvc
237         local cmd
238
239         if [ $ntype == "mdt" ]; then
240                 varsvc=${SINGLEMDS}_svc
241                 cmd="$LCTL get_param -n "
242                 cmd=${cmd}osd-$FSTYPE.${!varsvc}
243                 cmd=${cmd}.quota_slave.info
244
245                 if $(facet_up $SINGLEMDS); then
246                         wait_update_facet $SINGLEMDS "$cmd |
247                         grep "$qtype" | awk '{ print \\\$3 }'" \
248                                 "$result" $max || return 1
249                 fi
250         else
251                 local osts=$(get_facets OST)
252                 for ost in ${osts//,/ }; do
253                         varsvc=${ost}_svc
254                         cmd="$LCTL get_param -n "
255                         cmd=${cmd}osd-$FSTYPE.${!varsvc}
256                         cmd=${cmd}.quota_slave.info
257
258                         if $(facet_up $ost); then
259                                 wait_update_facet $ost "$cmd |
260                                 grep "$qtype" | awk '{ print \\\$3 }'" \
261                                         "$result" $max || return 1
262                         fi
263                 done
264         fi
265         return 0
266 }
267
268 wait_mdt_reint() {
269         local qtype=$1
270         local max=${2:-90}
271
272         if [ $qtype == "u" ] || [ $qtype == "ug" ]; then
273                 wait_reintegration "mdt" "user" $max || return 1
274         fi
275
276         if [ $qtype == "g" ] || [ $qtype == "ug" ]; then
277                 wait_reintegration "mdt" "group" $max || return 1
278         fi
279         return 0
280 }
281
282 wait_ost_reint() {
283         local qtype=$1
284         local max=${2:-90}
285
286         if [ $qtype == "u" ] || [ $qtype == "ug" ]; then
287                 wait_reintegration "ost" "user" $max || return 1
288         fi
289
290         if [ $qtype == "g" ] || [ $qtype == "ug" ]; then
291                 wait_reintegration "ost" "group" $max || return 1
292         fi
293         return 0
294 }
295
296 setup_quota_test() {
297         rm -rf $DIR/$tdir
298         wait_delete_completed
299         echo "Creating test directory"
300         mkdir -p $DIR/$tdir
301         chmod 077 $DIR/$tdir
302         # always clear fail_loc in case of fail_loc isn't cleared
303         # properly when previous test failed
304         lustre_fail mds_ost 0
305 }
306
307 cleanup_quota_test() {
308         trap 0
309         echo "Delete files..."
310         rm -rf $DIR/$tdir
311         echo "Wait for unlink objects finished..."
312         wait_delete_completed
313         sync_all_data || true
314 }
315
316 quota_show_check() {
317         local bf=$1
318         local ug=$2
319         local qid=$3
320         local usage
321
322         $LFS quota -v -$ug $qid $DIR
323
324         if [ "$bf" == "a" -o "$bf" == "b" ]; then
325                 usage=$(getquota -$ug $qid global curspace)
326                 if [ -z $usage ]; then
327                         quota_error $ug $qid \
328                                 "Query block quota failed ($ug:$qid)."
329                 else
330                         [ $usage -ne 0 ] && quota_log $ug $qid \
331                                 "Block quota isn't 0 ($ug:$qid:$usage)."
332                 fi
333         fi
334
335         if [ "$bf" == "a" -o "$bf" == "f" ]; then
336                 usage=$(getquota -$ug $qid global curinodes)
337                 if [ -z $usage ]; then
338                         quota_error $ug $qid \
339                                 "Query file quota failed ($ug:$qid)."
340                 else
341                         [ $usage -ne 0 ] && quota_log $ug $qid \
342                                 "File quota isn't 0 ($ug:$qid:$usage)."
343                 fi
344         fi
345 }
346
347 # enable quota debug
348 quota_init() {
349         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota"
350 }
351 quota_init
352
353 resetquota -u $TSTUSR
354 resetquota -g $TSTUSR
355 resetquota -u $TSTUSR2
356 resetquota -g $TSTUSR2
357
358 test_quota_performance() {
359         local TESTFILE="$DIR/$tdir/$tfile-0"
360         local size=$1 # in MB
361         local stime=$(date +%s)
362         $RUNAS $DD of=$TESTFILE count=$size conv=fsync ||
363                 quota_error u $TSTUSR "write failure"
364         local etime=$(date +%s)
365         delta=$((etime - stime))
366         if [ $delta -gt 0 ]; then
367             rate=$((size * 1024 / delta))
368             [ $rate -gt 1024 ] ||
369                 error "SLOW IO for $TSTUSR (user): $rate KB/sec"
370         fi
371         rm -f $TESTFILE
372 }
373
374 # test basic quota performance b=21696
375 test_0() {
376         local MB=100 # 100M
377         [ "$SLOW" = "no" ] && MB=10
378
379         local free_space=$(lfs_df | grep "summary" | awk '{print $5}')
380         [ $free_space -le $((MB * 1024)) ] &&
381                 skip "not enough space ${free_space} KB, " \
382                         "required $((MB * 1024)) KB" && return
383         setup_quota_test
384         trap cleanup_quota_test EXIT
385
386         set_ost_qtype "none" || error "disable ost quota failed"
387         test_quota_performance $MB
388
389         set_ost_qtype "ug" || error "enable ost quota failed"
390         $LFS setquota -u $TSTUSR -b 0 -B 10G -i 0 -I 0 $DIR ||
391                 error "set quota failed"
392         test_quota_performance $MB
393
394         cleanup_quota_test
395         resetquota -u $TSTUSR
396 }
397 run_test 0 "Test basic quota performance"
398
399 # test block hardlimit
400 test_1() {
401         local LIMIT=10  # 10M
402         local TESTFILE="$DIR/$tdir/$tfile-0"
403
404         setup_quota_test
405         trap cleanup_quota_test EXIT
406
407         # enable ost quota
408         set_ost_qtype "ug" || "enable ost quota failed"
409
410         # test for user
411         log "User quota (block hardlimit:$LIMIT MB)"
412         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
413                 error "set user quota failed"
414
415         # make sure the system is clean
416         local USED=$(getquota -u $TSTUSR global curspace)
417         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
418
419         $LFS setstripe $TESTFILE -c 1
420         chown $TSTUSR.$TSTUSR $TESTFILE
421
422         log "Write..."
423         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) ||
424                 quota_error u $TSTUSR "user write failure, but expect success"
425         log "Write out of block quota ..."
426         # this time maybe cache write,  ignore it's failure
427         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true
428         # flush cache, ensure noquota flag is set on client
429         cancel_lru_locks osc
430         $RUNAS $DD of=$TESTFILE count=1 seek=$LIMIT &&
431                 quota_error u $TSTUSR "user write success, but expect EDQUOT"
432
433         rm -f $TESTFILE
434         wait_delete_completed
435         sync_all_data || true
436         USED=$(getquota -u $TSTUSR global curspace)
437         [ $USED -ne 0 ] && quota_error u $TSTUSR \
438                 "user quota isn't released after deletion"
439         resetquota -u $TSTUSR
440
441         # test for group
442         log "--------------------------------------"
443         log "Group quota (block hardlimit:$LIMIT MB)"
444         $LFS setquota -g $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
445                 error "set group quota failed"
446
447         TESTFILE="$DIR/$tdir/$tfile-1"
448         # make sure the system is clean
449         USED=$(getquota -g $TSTUSR global curspace)
450         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0"
451
452         $LFS setstripe $TESTFILE -c 1
453         chown $TSTUSR.$TSTUSR $TESTFILE
454
455         log "Write ..."
456         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) ||
457                 quota_error g $TSTUSR "group write failure, but expect success"
458         log "Write out of block quota ..."
459         # this time maybe cache write, ignore it's failure
460         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) seek=$((LIMIT/2)) || true
461         cancel_lru_locks osc
462         $RUNAS $DD of=$TESTFILE count=10 seek=$LIMIT &&
463                 quota_error g $TSTUSR "group write success, but expect EDQUOT"
464
465         # cleanup
466         cleanup_quota_test
467
468         USED=$(getquota -g $TSTUSR global curspace)
469         [ $USED -ne 0 ] && quota_error g $TSTUSR \
470                 "group quota isn't released after deletion"
471
472         resetquota -g $TSTUSR
473 }
474 run_test 1 "Block hard limit (normal use and out of quota)"
475
476 # test inode hardlimit
477 test_2() {
478         local LIMIT=$((1024 * 1024)) # 1M inodes
479         local TESTFILE="$DIR/$tdir/$tfile-0"
480
481         [ "$SLOW" = "no" ] && LIMIT=1024 # 1k inodes
482
483         local FREE_INODES=$(lfs_df -i | grep "summary" | awk '{print $5}')
484         [ $FREE_INODES -lt $LIMIT ] &&
485                 skip "not enough free inodes $FREE_INODES required $LIMIT" &&
486                 return
487
488         setup_quota_test
489         trap cleanup_quota_test EXIT
490
491         # enable mdt quota
492         set_mdt_qtype "ug" || "enable mdt quota failed"
493
494         # test for user
495         log "User quota (inode hardlimit:$LIMIT files)"
496         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
497                 error "set user quota failed"
498
499         # make sure the system is clean
500         local USED=$(getquota -u $TSTUSR global curinodes)
501         [ $USED -ne 0 ] && error "Used inodes($USED) for user $TSTUSR isn't 0."
502
503         log "Create $LIMIT files ..."
504         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
505                 quota_error u $TSTUSR "user create failure, but expect success"
506         log "Create out of file quota ..."
507         $RUNAS touch ${TESTFILE}_xxx && \
508                 quota_error u $TSTUSR "user create success, but expect EDQUOT"
509
510         # cleanup
511         unlinkmany ${TESTFILE} $LIMIT
512         rm -f ${TESTFILE}_xxx
513         wait_delete_completed
514
515         USED=$(getquota -u $TSTUSR global curinodes)
516         [ $USED -ne 0 ] && quota_error u $TSTUSR \
517                 "user quota isn't released after deletion"
518         resetquota -u $TSTUSR
519
520         # test for group
521         log "--------------------------------------"
522         log "Group quota (inode hardlimit:$LIMIT files)"
523         $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
524                 error "set group quota failed"
525
526         TESTFILE=$DIR/$tdir/$tfile-1
527         # make sure the system is clean
528         USED=$(getquota -g $TSTUSR global curinodes)
529         [ $USED -ne 0 ] && error "Used inodes($USED) for group $TSTUSR isn't 0."
530
531         log "Create $LIMIT files ..."
532         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
533                 quota_error g $TSTUSR "group create failure, but expect success"
534         log "Create out of file quota ..."
535         $RUNAS touch ${TESTFILE}_xxx && \
536                 quota_error g $TSTUSR "group create success, but expect EDQUOT"
537
538         # cleanup
539         unlinkmany ${TESTFILE} $LIMIT
540         rm -f ${TESTFILE}_xxx
541         wait_delete_completed
542
543         USED=$(getquota -g $TSTUSR global curinodes)
544         [ $USED -ne 0 ] && quota_error g $TSTUSR \
545                 "user quota isn't released after deletion"
546
547         cleanup_quota_test
548         resetquota -g $TSTUSR
549 }
550 run_test 2 "File hard limit (normal use and out of quota)"
551
552 test_block_soft() {
553         local TESTFILE=$1
554         local TIMER=$(($2 * 3 / 2))
555         local LIMIT=$3
556         local OFFSET=0
557
558         setup_quota_test
559         trap cleanup_quota_test EXIT
560
561         $LFS setstripe $TESTFILE -c 1 -i 0
562         chown $TSTUSR.$TSTUSR $TESTFILE
563
564         echo "Write up to soft limit"
565         $RUNAS $DD of=$TESTFILE count=$LIMIT ||
566                 quota_error a $TSTUSR "write failure, but expect success"
567         OFFSET=$((LIMIT * 1024))
568         cancel_lru_locks osc
569
570         echo "Write to exceed soft limit"
571         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET ||
572                 quota_error a $TSTUSR "write failure, but expect success"
573         OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block
574         cancel_lru_locks osc
575
576         $SHOW_QUOTA_USER
577         $SHOW_QUOTA_GROUP
578         $SHOW_QUOTA_INFO_USER
579         $SHOW_QUOTA_INFO_GROUP
580
581         echo "Write before timer goes off"
582         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET ||
583                 quota_error a $TSTUSR "write failure, but expect success"
584         OFFSET=$((OFFSET + 1024))
585         cancel_lru_locks osc
586
587         echo "Sleep $TIMER seconds ..."
588         sleep $TIMER
589
590         $SHOW_QUOTA_USER
591         $SHOW_QUOTA_GROUP
592         $SHOW_QUOTA_INFO_USER
593         $SHOW_QUOTA_INFO_GROUP
594
595         echo "Write after timer goes off"
596         # maybe cache write, ignore.
597         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET || true
598         OFFSET=$((OFFSET + 1024))
599         cancel_lru_locks osc
600         $RUNAS dd if=/dev/zero of=$TESTFILE bs=1K count=10 seek=$OFFSET &&
601                 quota_error a $TSTUSR "write success, but expect EDQUOT"
602
603         $SHOW_QUOTA_USER
604         $SHOW_QUOTA_GROUP
605         $SHOW_QUOTA_INFO_USER
606         $SHOW_QUOTA_INFO_GROUP
607
608         echo "Unlink file to stop timer"
609         rm -f $TESTFILE
610         wait_delete_completed
611         sync_all_data || true
612
613         $SHOW_QUOTA_USER
614         $SHOW_QUOTA_GROUP
615         $SHOW_QUOTA_INFO_USER
616         $SHOW_QUOTA_INFO_GROUP
617
618         $LFS setstripe $TESTFILE -c 1 -i 0
619         chown $TSTUSR.$TSTUSR $TESTFILE
620
621         echo "Write ..."
622         $RUNAS $DD of=$TESTFILE count=$LIMIT ||
623                 quota_error a $TSTUSR "write failure, but expect success"
624         # cleanup
625         cleanup_quota_test
626 }
627
628 # block soft limit
629 test_3() {
630         local LIMIT=1  # 1MB
631         local GRACE=10 # 10s
632         local TESTFILE=$DIR/$tdir/$tfile-0
633
634         set_ost_qtype "ug" || error "enable ost quota failed"
635
636         echo "User quota (soft limit:$LIMIT MB  grace:$GRACE seconds)"
637         # make sure the system is clean
638         local USED=$(getquota -u $TSTUSR global curspace)
639         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
640
641         $LFS setquota -t -u --block-grace $GRACE --inode-grace \
642                 $MAX_IQ_TIME $DIR || error "set user grace time failed"
643         $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
644                 error "set user quota failed"
645
646         test_block_soft $TESTFILE $GRACE $LIMIT
647         resetquota -u $TSTUSR
648
649         echo "Group quota (soft limit:$LIMIT MB  grace:$GRACE seconds)"
650         TESTFILE=$DIR/$tdir/$tfile-1
651         # make sure the system is clean
652         USED=$(getquota -g $TSTUSR global curspace)
653         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0."
654
655         $LFS setquota -t -g --block-grace $GRACE --inode-grace \
656                 $MAX_IQ_TIME $DIR || error "set group grace time failed"
657         $LFS setquota -g $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
658                 error "set group quota failed"
659
660         test_block_soft $TESTFILE $GRACE $LIMIT
661         resetquota -g $TSTUSR
662
663         # cleanup
664         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
665                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
666         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
667                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
668 }
669 run_test 3 "Block soft limit (start timer, timer goes off, stop timer)"
670
671 test_file_soft() {
672         local TESTFILE=$1
673         local LIMIT=$2
674         local TIMER=$(($3 * 3 / 2))
675
676         setup_quota_test
677         trap cleanup_quota_test EXIT
678
679         echo "Create files to exceed soft limit"
680         $RUNAS createmany -m ${TESTFILE}_ $((LIMIT + 1)) ||
681                 quota_error a $TSTUSR "create failure, but expect success"
682         sync; sleep 1; sync
683
684         echo "Create file before timer goes off"
685         $RUNAS touch ${TESTFILE}_before ||
686                 quota_error a $TSTUSR "failed create before timer expired," \
687                         "but expect success"
688         sync; sleep 1; sync
689
690         echo "Sleep $TIMER seconds ..."
691         sleep $TIMER
692
693         $SHOW_QUOTA_USER
694         $SHOW_QUOTA_GROUP
695         $SHOW_QUOTA_INFO_USER
696         $SHOW_QUOTA_INFO_GROUP
697
698         echo "Create file after timer goes off"
699         # There is a window that space is accounted in the quota usage but
700         # hasn't been decreased from the pending write, if we acquire quota
701         # in this window, we'll acquire more than we needed.
702         $RUNAS touch ${TESTFILE}_after_1 ${TESTFILE}_after_2 || true
703         sync; sleep 1; sync
704         $RUNAS touch ${TESTFILE}_after_3 &&
705                 quota_error a $TSTUSR "create after timer expired," \
706                         "but expect EDQUOT"
707         sync; sleep 1; sync
708
709         $SHOW_QUOTA_USER
710         $SHOW_QUOTA_GROUP
711         $SHOW_QUOTA_INFO_USER
712         $SHOW_QUOTA_INFO_GROUP
713
714         echo "Unlink files to stop timer"
715         find $(dirname $TESTFILE) -name "$(basename ${TESTFILE})*" | xargs rm -f
716         wait_delete_completed
717
718         echo "Create file"
719         $RUNAS touch ${TESTFILE}_xxx ||
720                 quota_error a $TSTUSR "touch after timer stop failure," \
721                         "but expect success"
722         sync; sleep 1; sync
723
724         # cleanup
725         cleanup_quota_test
726 }
727
728 # file soft limit
729 test_4a() {
730         local LIMIT=10 # inodes
731         local TESTFILE=$DIR/$tdir/$tfile-0
732         local GRACE=5
733
734         set_mdt_qtype "ug" || error "enable mdt quota failed"
735
736         echo "User quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
737         # make sure the system is clean
738         local USED=$(getquota -u $TSTUSR global curinodes)
739         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
740
741         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
742                 $GRACE $DIR || error "set user grace time failed"
743         $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
744                 error "set user quota failed"
745
746         test_file_soft $TESTFILE $LIMIT $GRACE
747         resetquota -u $TSTUSR
748
749         echo "Group quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
750         # make sure the system is clean
751         USED=$(getquota -g $TSTUSR global curinodes)
752         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0."
753
754         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
755                 $GRACE $DIR || error "set group grace time failed"
756         $LFS setquota -g $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
757                 error "set group quota failed"
758         TESTFILE=$DIR/$tdir/$tfile-1
759
760         test_file_soft $TESTFILE $LIMIT $GRACE
761         resetquota -g $TSTUSR
762
763         # cleanup
764         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
765                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
766         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
767                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
768 }
769 run_test 4a "File soft limit (start timer, timer goes off, stop timer)"
770
771 test_4b() {
772         local GR_STR1="1w3d"
773         local GR_STR2="1000s"
774         local GR_STR3="5s"
775         local GR_STR4="1w2d3h4m5s"
776         local GR_STR5="5c"
777         local GR_STR6="1111111111111111"
778
779         wait_delete_completed
780
781         # test of valid grace strings handling
782         echo "Valid grace strings test"
783         $LFS setquota -t -u --block-grace $GR_STR1 --inode-grace \
784                 $GR_STR2 $DIR || error "set user grace time failed"
785         $LFS quota -u -t $DIR | grep "Block grace time: $GR_STR1"
786         $LFS setquota -t -g --block-grace $GR_STR3 --inode-grace \
787                 $GR_STR4 $DIR || error "set group grace time quota failed"
788         $LFS quota -g -t $DIR | grep "Inode grace time: $GR_STR4"
789
790         # test of invalid grace strings handling
791         echo "  Invalid grace strings test"
792         ! $LFS setquota -t -u --block-grace $GR_STR4 --inode-grace $GR_STR5 $DIR
793         ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace $GR_STR6 $DIR
794
795         # cleanup
796         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
797                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
798         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
799                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
800 }
801 run_test 4b "Grace time strings handling"
802
803 # chown & chgrp (chown & chgrp successfully even out of block/file quota)
804 test_5() {
805         local BLIMIT=10 # 10M
806         local ILIMIT=10 # 10 inodes
807
808         setup_quota_test
809         trap cleanup_quota_test EXIT
810
811         set_mdt_qtype "ug" || error "enable mdt quota failed"
812         set_ost_qtype "ug" || error "enable ost quota failed"
813
814         echo "Set quota limit (0 ${BLIMIT}M 0 $ILIMIT) for $TSTUSR.$TSTUSR"
815         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
816                 error "set user quota failed"
817         $LFS setquota -g $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
818                 error "set group quota failed"
819
820         # make sure the system is clean
821         local USED=$(getquota -u $TSTUSR global curinodes)
822         [ $USED -ne 0 ] && error "Used inode($USED) for user $TSTUSR isn't 0."
823         USED=$(getquota -g $TSTUSR global curinodes)
824         [ $USED -ne 0 ] && error "Used inode($USED) for group $TSTUSR isn't 0."
825         USED=$(getquota -u $TSTUSR global curspace)
826         [ $USED -ne 0 ] && error "Used block($USED) for user $TSTUSR isn't 0."
827         USED=$(getquota -g $TSTUSR global curspace)
828         [ $USED -ne 0 ] && error "Used block($USED) for group $TSTUSR isn't 0."
829
830         echo "Create more than $ILIMIT files and more than $BLIMIT MB ..."
831         createmany -m $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) ||
832                 error "create failure, expect success"
833         $DD of=$DIR/$tdir/$tfile-0_1 count=$((BLIMIT+1)) ||
834                 error "write failure, expect success"
835
836         echo "Chown files to $TSTUSR.$TSTUSR ..."
837         for i in `seq 0 $ILIMIT`; do
838                 chown $TSTUSR.$TSTUSR $DIR/$tdir/$tfile-0_$i ||
839                         quota_error a $TSTUSR "chown failure, expect success"
840         done
841
842         # cleanup
843         unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1))
844         cleanup_quota_test
845
846         resetquota -u $TSTUSR
847         resetquota -g $TSTUSR
848 }
849 run_test 5 "Chown & chgrp successfully even out of block/file quota"
850
851 # test dropping acquire request on master
852 test_6() {
853         local LIMIT=3 # 3M
854
855         setup_quota_test
856         trap cleanup_quota_test EXIT
857
858         # make sure the system is clean
859         local USED=$(getquota -u $TSTUSR global curspace)
860         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
861
862         # make sure no granted quota on ost
863         set_ost_qtype "ug" || error "enable ost quota failed"
864         resetquota -u $TSTUSR
865
866         # create file for $TSTUSR
867         local TESTFILE=$DIR/$tdir/$tfile-$TSTUSR
868         $LFS setstripe $TESTFILE -c 1 -i 0
869         chown $TSTUSR.$TSTUSR $TESTFILE
870
871         # create file for $TSTUSR2
872         local TESTFILE2=$DIR/$tdir/$tfile-$TSTUSR2
873         $LFS setstripe $TESTFILE2 -c 1 -i 0
874         chown $TSTUSR2.$TSTUSR2 $TESTFILE2
875
876         # cache per-ID lock for $TSTUSR on slave
877         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
878                 error "set quota failed"
879         $RUNAS $DD of=$TESTFILE count=1 ||
880                 error "write $TESTFILE failure, expect success"
881         $RUNAS2 $DD of=$TESTFILE2 count=1 ||
882                 error "write $TESTFILE2 failure, expect success"
883         sync; sync
884         sync_all_data || true
885
886         #define QUOTA_DQACQ 601
887         #define OBD_FAIL_PTLRPC_DROP_REQ_OPC 0x513
888         lustre_fail mds 0x513 601
889
890         # write to un-enforced ID ($TSTUSR2) should succeed
891         $RUNAS2 $DD of=$TESTFILE2 count=$LIMIT seek=1 oflag=sync conv=notrunc ||
892                 error "write failure, expect success"
893
894         # write to enforced ID ($TSTUSR) in background, exceeding limit
895         # to make sure DQACQ is sent
896         $RUNAS $DD of=$TESTFILE count=$LIMIT seek=1 oflag=sync conv=notrunc &
897         DDPID=$!
898
899         # watchdog timer uses a factor of 2
900         echo "Sleep for $((TIMEOUT * 2 + 1)) seconds ..."
901         sleep $((TIMEOUT * 2 + 1))
902
903         # write should be blocked and never finished
904         if ! ps -p $DDPID  > /dev/null 2>&1; then
905                 lustre_fail mds 0 0
906                 error "write finished incorrectly!"
907         fi
908
909         lustre_fail mds 0 0
910
911         # no watchdog is triggered
912         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
913         watchdog=$(awk '/sanity-quota test 6/ {start = 1;}
914                        /Service thread pid/ && /was inactive/ {
915                                if (start) {
916                                        print;
917                                }
918                        }' $TMP/lustre-log-${TESTNAME}.log)
919         [ -z "$watchdog" ] || error "$watchdog"
920
921         rm -f $TMP/lustre-log-${TESTNAME}.log
922
923         # write should continue & succeed
924         local count=0
925         while [ true ]; do
926                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
927                 if [ $count -ge 120 ]; then
928                         quota_error u $TSTUSR "dd not finished in $count secs"
929                 fi
930                 count=$((count + 1))
931                 [ $((count % 10)) -eq 0 ] && echo "Waiting $count secs"
932                 sleep 1
933         done
934
935         cleanup_quota_test
936         resetquota -u $TSTUSR
937 }
938 run_test 6 "Test dropping acquire request on master"
939
940 # quota reintegration (global index)
941 test_7a() {
942         local TESTFILE=$DIR/$tdir/$tfile
943         local LIMIT=20 # 20M
944
945         [ "$SLOW" = "no" ] && LIMIT=5
946
947         setup_quota_test
948         trap cleanup_quota_test EXIT
949
950         # make sure the system is clean
951         local USED=$(getquota -u $TSTUSR global curspace)
952         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
953
954         # make sure no granted quota on ost1
955         set_ost_qtype "ug" || error "enable ost quota failed"
956         resetquota -u $TSTUSR
957         set_ost_qtype "none" || error "disable ost quota failed"
958
959         local OSTUUID=$(ostuuid_from_index 0)
960         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
961         [ $USED -ne 0 ] && error "limit($USED) on $OSTUUID for user" \
962                 "$TSTUSR isn't 0."
963
964         # create test file
965         $LFS setstripe $TESTFILE -c 1 -i 0
966         chown $TSTUSR.$TSTUSR $TESTFILE
967
968         echo "Stop ost1..."
969         stop ost1
970
971         echo "Enable quota & set quota limit for $TSTUSR"
972         set_ost_qtype "ug" || error "enable ost quota failed"
973         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
974                 error "set quota failed"
975
976         echo "Start ost1..."
977         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS
978         quota_init
979
980         wait_ost_reint "ug" || error "reintegration failed"
981
982         # hardlimit should have been fetched by slave during global
983         # reintegration, write will exceed quota
984         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
985                 quota_error u $TSTUSR "write success, but expect EDQUOT"
986
987         rm -f $TESTFILE
988         wait_delete_completed
989         sync_all_data || true
990         sleep 3
991
992         echo "Stop ost1..."
993         stop ost1
994
995         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
996                 error "clear quota failed"
997
998         echo "Start ost1..."
999         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS
1000         quota_init
1001
1002         wait_ost_reint "ug" || error "reintegration failed"
1003
1004         # hardlimit should be cleared on slave during reintegration
1005         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync ||
1006                 quota_error u $TSTUSR "write error, but expect success"
1007
1008         cleanup_quota_test
1009         resetquota -u $TSTUSR
1010 }
1011 run_test 7a "Quota reintegration (global index)"
1012
1013 # quota reintegration (slave index)
1014 test_7b() {
1015         local LIMIT="100G"
1016         local TESTFILE=$DIR/$tdir/$tfile
1017
1018         setup_quota_test
1019         trap cleanup_quota_test EXIT
1020
1021         # make sure the system is clean
1022         local USED=$(getquota -u $TSTUSR global curspace)
1023         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1024
1025         # make sure no granted quota on ost1
1026         set_ost_qtype "ug" || error "enable ost quota failed"
1027         resetquota -u $TSTUSR
1028         set_ost_qtype "none" || error "disable ost quota failed"
1029
1030         local OSTUUID=$(ostuuid_from_index 0)
1031         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1032         [ $USED -ne 0 ] && error "limit($USED) on $OSTUUID for user" \
1033                 "$TSTUSR isn't 0."
1034
1035         # create test file
1036         $LFS setstripe $TESTFILE -c 1 -i 0
1037         chown $TSTUSR.$TSTUSR $TESTFILE
1038
1039         # consume some space to make sure the granted space will not
1040         # be released during reconciliation
1041         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
1042                 error "consume space failure, expect success"
1043
1044         # define OBD_FAIL_QUOTA_EDQUOT 0xa02
1045         lustre_fail mds 0xa02
1046
1047         set_ost_qtype "ug" || error "enable ost quota failed"
1048         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1049                 error "set quota failed"
1050
1051         # ignore the write error
1052         $RUNAS $DD of=$TESTFILE count=1 seek=1 oflag=sync conv=notrunc
1053
1054         local old_used=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1055
1056         lustre_fail mds 0
1057
1058         echo "Restart ost to trigger reintegration..."
1059         stop ost1
1060         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS
1061         quota_init
1062
1063         wait_ost_reint "ug" || error "reintegration failed"
1064
1065         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1066         [ $USED -gt $old_used ] || error "limit on $OSTUUID $USED <= $old_used"
1067
1068         cleanup_quota_test
1069         resetquota -u $TSTUSR
1070         $SHOW_QUOTA_USER
1071 }
1072 run_test 7b "Quota reintegration (slave index)"
1073
1074 # quota reintegration (restart mds during reintegration)
1075 test_7c() {
1076         local LIMIT=20 # 20M
1077         local TESTFILE=$DIR/$tdir/$tfile
1078
1079         [ "$SLOW" = "no" ] && LIMIT=5
1080
1081         setup_quota_test
1082         trap cleanup_quota_test EXIT
1083
1084         # make sure the system is clean
1085         local USED=$(getquota -u $TSTUSR global curspace)
1086         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1087
1088         set_ost_qtype "none" || error "disable ost quota failed"
1089         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1090                 error "set quota failed"
1091
1092         # define OBD_FAIL_QUOTA_DELAY_REINT 0xa03
1093         lustre_fail ost 0xa03
1094
1095         # enable ost quota
1096         set_ost_qtype "ug" || error "enable ost quota failed"
1097         # trigger reintegration
1098         local procf="osd-$FSTYPE.$FSNAME-OST*."
1099         procf=${procf}quota_slave.force_reint
1100         $LCTL set_param $procf=1 || "force reintegration failed"
1101
1102         echo "Stop mds..."
1103         stop mds1
1104
1105         lustre_fail ost 0
1106
1107         echo "Start mds..."
1108         start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
1109         quota_init
1110
1111         # wait longer than usual to make sure the reintegration
1112         # is triggered by quota wb thread.
1113         wait_ost_reint "ug" 200 || error "reintegration failed"
1114
1115         # hardlimit should have been fetched by slave during global
1116         # reintegration, write will exceed quota
1117         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
1118                 quota_error u $TSTUSR "write success, but expect EDQUOT"
1119
1120         cleanup_quota_test
1121         resetquota -u $TSTUSR
1122 }
1123 run_test 7c "Quota reintegration (restart mds during reintegration)"
1124
1125 # Quota reintegration (Transfer index in multiple bulks)
1126 test_7d(){
1127         local TESTFILE=$DIR/$tdir/$tfile
1128         local TESTFILE1="$DIR/$tdir/$tfile"-1
1129         local limit=20 #20M
1130
1131         setup_quota_test
1132         trap cleanup_quota_test EXIT
1133
1134         set_ost_qtype "none" || error "disable ost quota failed"
1135         $LFS setquota -u $TSTUSR -B ${limit}M $DIR ||
1136                 error "set quota for $TSTUSR failed"
1137         $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR ||
1138                 error "set quota for $TSTUSR2 failed"
1139
1140         #define OBD_FAIL_OBD_IDX_READ_BREAK 0x608
1141         lustre_fail mds 0x608 0
1142
1143         # enable quota to tirgger reintegration
1144         set_ost_qtype "u" || error "enable ost quota failed"
1145         wait_ost_reint "u" || error "reintegration failed"
1146
1147         lustre_fail mds 0
1148
1149         # hardlimit should have been fetched by slave during global
1150         # reintegration, write will exceed quota
1151         $RUNAS $DD of=$TESTFILE count=$((limit + 1)) oflag=sync &&
1152                 quota_error u $TSTUSR "$TSTUSR write success, expect EDQUOT"
1153
1154         $RUNAS2 $DD of=$TESTFILE1 count=$((limit + 1)) oflag=sync &&
1155                 quota_error u $TSTUSR2 "$TSTUSR2 write success, expect EDQUOT"
1156
1157         cleanup_quota_test
1158         resetquota -u $TSTUSR
1159         resetquota -u $TSTUSR2
1160 }
1161 run_test 7d "Quota reintegration (Transfer index in multiple bulks)"
1162
1163 # run dbench with quota enabled
1164 test_8() {
1165         local BLK_LIMIT="100g" #100G
1166         local FILE_LIMIT=1000000
1167
1168         setup_quota_test
1169         trap cleanup_quota_test EXIT
1170
1171         set_mdt_qtype "ug" || error "enable mdt quota failed"
1172         set_ost_qtype "ug" || error "enable ost quota failed"
1173
1174         echo "Set enough high limit for user: $TSTUSR"
1175         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1176                 error "set user quota failed"
1177         echo "Set enough high limit for group: $TSTUSR"
1178         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1179                 error "set group quota failed"
1180
1181         local duration=""
1182         [ "$SLOW" = "no" ] && duration=" -t 120"
1183         $RUNAS bash rundbench -D $DIR/$tdir 3 $duration ||
1184                 quota_error a $TSTUSR "dbench failed!"
1185
1186         cleanup_quota_test
1187         resetquota -u $TSTUSR
1188         resetquota -g $TSTUSR
1189 }
1190 run_test 8 "Run dbench with quota enabled"
1191
1192 # this check is just for test_9
1193 OST0_MIN=4900000 #4.67G
1194
1195 check_whether_skip () {
1196         local OST0_SIZE=$($LFS df $DIR | awk '/\[OST:0\]/ {print $4}')
1197         log "OST0_SIZE: $OST0_SIZE  required: $OST0_MIN"
1198         if [ $OST0_SIZE -lt $OST0_MIN ]; then
1199                 echo "WARN: OST0 has less than $OST0_MIN free, skip this test."
1200                 return 0
1201         else
1202                 return 1
1203         fi
1204 }
1205
1206 # run for fixing bug10707, it needs a big room. test for 64bit
1207 test_9() {
1208         local filesize=$((1024 * 9 / 2)) # 4.5G
1209
1210         check_whether_skip && return 0
1211
1212         setup_quota_test
1213         trap cleanup_quota_test EXIT
1214
1215         set_ost_qtype "ug" || error "enable ost quota failed"
1216
1217         local TESTFILE="$DIR/$tdir/$tfile-0"
1218         local BLK_LIMIT=100G #100G
1219         local FILE_LIMIT=1000000
1220
1221         echo "Set block limit $BLK_LIMIT bytes to $TSTUSR.$TSTUSR"
1222
1223         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
1224                 "for user: $TSTUSR"
1225         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1226                 error "set user quota failed"
1227
1228         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
1229                 "for group: $TSTUSR"
1230         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
1231                 error "set group quota failed"
1232
1233         quota_show_check a u $TSTUSR
1234         quota_show_check a g $TSTUSR
1235
1236         echo "Create test file"
1237         $LFS setstripe $TESTFILE -c 1 -i 0
1238         chown $TSTUSR.$TSTUSR $TESTFILE
1239
1240         log "Write the big file of 4.5G ..."
1241         $RUNAS $DD of=$TESTFILE count=$filesize ||
1242                 quota_error a $TSTUSR "write 4.5G file failure, expect success"
1243
1244         $SHOW_QUOTA_USER
1245         $SHOW_QUOTA_GROUP
1246
1247         cleanup_quota_test
1248         resetquota -u $TSTUSR
1249         resetquota -g $TSTUSR
1250
1251         $SHOW_QUOTA_USER
1252         $SHOW_QUOTA_GROUP
1253 }
1254 run_test 9 "Block limit larger than 4GB (b10707)"
1255
1256 test_10() {
1257         local TESTFILE=$DIR/$tdir/$tfile
1258
1259         setup_quota_test
1260         trap cleanup_quota_test EXIT
1261
1262         # set limit to root user should fail
1263         $LFS setquota -u root -b 100G -B 500G -i 1K -I 1M $DIR &&
1264                 error "set limit for root user successfully, expect failure"
1265         $LFS setquota -g root -b 1T -B 10T -i 5K -I 100M $DIR &&
1266                 error "set limit for root group successfully, expect failure"
1267
1268         # root user can overrun quota
1269         set_ost_qtype "ug" || "enable ost quota failed"
1270
1271         $LFS setquota -u $TSTUSR -b 0 -B 2M -i 0 -I 0 $DIR ||
1272                 error "set quota failed"
1273         quota_show_check b u $TSTUSR
1274
1275         $LFS setstripe $TESTFILE -c 1
1276         chown $TSTUSR.$TSTUSR $TESTFILE
1277
1278         runas -u 0 -g 0 $DD of=$TESTFILE count=3 oflag=sync ||
1279                 error "write failure, expect success"
1280
1281         cleanup_quota_test
1282         resetquota -u $TSTUSR
1283 }
1284 run_test 10 "Test quota for root user"
1285
1286 test_11() {
1287         local TESTFILE=$DIR/$tdir/$tfile
1288         setup_quota_test
1289         trap cleanup_quota_test EXIT
1290
1291         set_mdt_qtype "ug" || "enable mdt quota failed"
1292         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 1 $DIR ||
1293                 error "set quota failed"
1294
1295         touch "$TESTFILE"-0
1296         touch "$TESTFILE"-1
1297
1298         chown $TSTUSR.$TSTUSR "$TESTFILE"-0
1299         chown $TSTUSR.$TSTUSR "$TESTFILE"-1
1300
1301         $SHOW_QUOTA_USER
1302         local USED=$(getquota -u $TSTUSR global curinodes)
1303         [ $USED -ge 2 ] || error "Used inodes($USED) is less than 2"
1304
1305         cleanup_quota_test
1306         resetquota -u $TSTUSR
1307 }
1308 run_test 11 "Chown/chgrp ignores quota"
1309
1310 test_12() {
1311         [ "$OSTCOUNT" -lt "2" ] && skip "skipping rebalancing test" && return
1312
1313         local blimit=22 # 22M
1314         local blk_cnt=$((blimit - 5))
1315         local TESTFILE0="$DIR/$tdir/$tfile"-0
1316         local TESTFILE1="$DIR/$tdir/$tfile"-1
1317
1318         setup_quota_test
1319         trap cleanup_quota_test EXIT
1320
1321         set_ost_qtype "u" || "enable ost quota failed"
1322         quota_show_check b u $TSTUSR
1323
1324         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $DIR ||
1325                 error "set quota failed"
1326
1327         $LFS setstripe $TESTFILE0 -c 1 -i 0
1328         $LFS setstripe $TESTFILE1 -c 1 -i 1
1329         chown $TSTUSR.$TSTUSR $TESTFILE0
1330         chown $TSTUSR.$TSTUSR $TESTFILE1
1331
1332         echo "Write to ost0..."
1333         $RUNAS $DD of=$TESTFILE0 count=$blk_cnt oflag=sync ||
1334                 quota_error a $TSTUSR "dd failed"
1335
1336         echo "Write to ost1..."
1337         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync &&
1338                 quota_error a $TSTUSR "dd succeed, expect EDQUOT"
1339
1340         echo "Free space from ost0..."
1341         rm -f $TESTFILE0
1342         wait_delete_completed
1343         sync_all_data || true
1344
1345         echo "Write to ost1 after space freed from ost0..."
1346         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync ||
1347                 quota_error a $TSTUSR "rebalancing failed"
1348
1349         cleanup_quota_test
1350         resetquota -u $TSTUSR
1351 }
1352 run_test 12 "Block quota rebalancing"
1353
1354 test_13(){
1355         local TESTFILE=$DIR/$tdir/$tfile
1356         # the name of osp on ost1 name is MDT0000-osp-OST0000
1357         local procf="ldlm.namespaces.*MDT0000-osp-OST0000.lru_size"
1358
1359         setup_quota_test
1360         trap cleanup_quota_test EXIT
1361
1362         set_ost_qtype "u" || "enable ost quota failed"
1363         quota_show_check b u $TSTUSR
1364
1365         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
1366                 error "set quota failed"
1367         $LFS setstripe $TESTFILE -c 1 -i 0
1368         chown $TSTUSR.$TSTUSR $TESTFILE
1369
1370         # clear the locks in cache first
1371         do_facet ost1 $LCTL set_param -n $procf=clear
1372         local nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1373         [ $nlock -eq 0 ] || error "$nlock cached locks"
1374
1375         # write to acquire the per-ID lock
1376         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
1377                 quota_error a $TSTUSR "dd failed"
1378
1379         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1380         [ $nlock -eq 1 ] || error "lock count($nlock) isn't 1"
1381
1382         # clear quota doesn't trigger per-ID lock cancellation
1383         resetquota -u $TSTUSR
1384         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1385         [ $nlock -eq 1 ] || error "per-ID lock is lost on quota clear"
1386
1387         # clear the per-ID lock
1388         do_facet ost1 $LCTL set_param -n $procf=clear
1389         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
1390         [ $nlock -eq 0 ] || error "per-ID lock isn't cleared"
1391
1392         # spare quota should be released
1393         local OSTUUID=$(ostuuid_from_index 0)
1394         local limit=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1395         local space=$(getquota -u $TSTUSR $OSTUUID curspace)
1396         [ $limit -le $space ] ||
1397                 error "spare quota isn't released, limit:$limit, space:$space"
1398
1399         cleanup_quota_test
1400 }
1401 run_test 13 "Cancel per-ID lock in the LRU list"
1402
1403 test_15(){
1404         local LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB
1405
1406         wait_delete_completed
1407         sync_all_data || true
1408
1409         # test for user
1410         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1411                 error "set user quota failed"
1412         local TOTAL_LIMIT=$(getquota -u $TSTUSR global bhardlimit)
1413         [ $TOTAL_LIMIT -eq $LIMIT ] ||
1414                 error "(user) limit:$TOTAL_LIMIT, expect:$LIMIT, failed!"
1415         resetquota -u $TSTUSR
1416
1417         # test for group
1418         $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1419                 error "set group quota failed"
1420         TOTAL_LIMIT=$(getquota -g $TSTUSR global bhardlimit)
1421         [ $TOTAL_LIMIT -eq $LIMIT ] ||
1422                 error "(group) limits:$TOTAL_LIMIT, expect:$LIMIT, failed!"
1423         resetquota -g $TSTUSR
1424 }
1425 run_test 15 "Set over 4T block quota"
1426
1427 test_17sub() {
1428         local err_code=$1
1429         local BLKS=1    # 1M less than limit
1430         local TESTFILE=$DIR/$tdir/$tfile
1431
1432         setup_quota_test
1433         trap cleanup_quota_test EXIT
1434
1435         # make sure the system is clean
1436         local USED=$(getquota -u $TSTUSR global curspace)
1437         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1438
1439         set_ost_qtype "ug" || error "enable ost quota failed"
1440         # make sure no granted quota on ost
1441         resetquota -u $TSTUSR
1442         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
1443                 error "set quota failed"
1444
1445         quota_show_check b u $TSTUSR
1446
1447         #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xa04
1448         lustre_fail mds 0xa04 $err_code
1449
1450         # write in background
1451         $RUNAS $DD of=$TESTFILE count=$BLKS oflag=direct &
1452         local DDPID=$!
1453
1454         sleep 2
1455         # write should be blocked and never finished
1456         if ! ps -p $DDPID  > /dev/null 2>&1; then
1457                 lustre_fail mds 0 0
1458                 quota_error u $TSTUSR "write finished incorrectly!"
1459         fi
1460
1461         lustre_fail mds 0 0
1462
1463         local count=0
1464         local timeout=30
1465         while [ true ]; do
1466                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1467                 count=$((count+1))
1468                 if [ $count -gt $timeout ]; then
1469                         quota_error u $TSTUSR "dd is not finished!"
1470                 fi
1471                 sleep 1
1472         done
1473
1474         sync; sync_all_data || true
1475
1476         USED=$(getquota -u $TSTUSR global curspace)
1477         [ $USED -ge $(($BLKS * 1024)) ] || quota_error u $TSTUSR \
1478                 "Used space(${USED}K) is less than ${BLKS}M"
1479
1480         cleanup_quota_test
1481         resetquota -u $TSTUSR
1482 }
1483
1484 # DQACQ return recoverable error
1485 test_17() {
1486         echo "DQACQ return -ENOLCK"
1487         #define ENOLCK  37
1488         test_17sub 37 || error "Handle -ENOLCK failed"
1489
1490         echo "DQACQ return -EAGAIN"
1491         #define EAGAIN  11
1492         test_17sub 11 || error "Handle -EAGAIN failed"
1493
1494         echo "DQACQ return -ETIMEDOUT"
1495         #define ETIMEDOUT 110
1496         test_17sub 110 || error "Handle -ETIMEDOUT failed"
1497
1498         echo "DQACQ return -ENOTCONN"
1499         #define ENOTCONN 107
1500         test_17sub 107 || error "Handle -ENOTCONN failed"
1501 }
1502
1503 run_test 17 "DQACQ return recoverable error"
1504
1505 test_18_sub () {
1506         local io_type=$1
1507         local blimit="200m" # 200M
1508         local TESTFILE="$DIR/$tdir/$tfile"
1509
1510         setup_quota_test
1511         trap cleanup_quota_test EXIT
1512
1513         set_ost_qtype "u" || error "enable ost quota failed"
1514         log "User quota (limit: $blimit)"
1515         $LFS setquota -u $TSTUSR -b 0 -B $blimit -i 0 -I 0 $MOUNT ||
1516                 error "set quota failed"
1517         quota_show_check b u $TSTUSR
1518
1519         $LFS setstripe $TESTFILE -i 0 -c 1
1520         chown $TSTUSR.$TSTUSR $TESTFILE
1521
1522         local timeout=$(sysctl -n lustre.timeout)
1523
1524         if [ $io_type = "directio" ]; then
1525                 log "Write 100M (directio) ..."
1526                 $RUNAS $DD of=$TESTFILE count=100 oflag=direct &
1527         else
1528                 log "Write 100M (buffered) ..."
1529                 $RUNAS $DD of=$TESTFILE count=100 &
1530         fi
1531         local DDPID=$!
1532
1533         replay_barrier $SINGLEMDS
1534         log "Fail mds for $((2 * timeout)) seconds"
1535         fail $SINGLEMDS $((2 * timeout))
1536
1537         local count=0
1538         if at_is_enabled; then
1539                 timeout=$(at_max_get mds)
1540         else
1541                 timeout=$(lctl get_param -n timeout)
1542         fi
1543
1544         while [ true ]; do
1545                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1546                 if [ $((++count % (2 * timeout) )) -eq 0 ]; then
1547                         log "it took $count second"
1548                 fi
1549                 sleep 1
1550         done
1551
1552         log "(dd_pid=$DDPID, time=$count, timeout=$timeout)"
1553         sync
1554         cancel_lru_locks mdc
1555         cancel_lru_locks osc
1556         $SHOW_QUOTA_USER
1557
1558         local testfile_size=$(stat -c %s $TESTFILE)
1559         if [ $testfile_size -ne $((BLK_SZ * 1024 * 100)) ] ; then
1560                 quota_error u $TSTUSR "expect $((BLK_SZ * 1024 * 100)),"
1561                         "got ${testfile_size}. Verifying file failed!"
1562         fi
1563         cleanup_quota_test
1564         resetquota -u $TSTUSR
1565 }
1566
1567 # test when mds does failover, the ost still could work well
1568 # this test shouldn't trigger watchdog b=14840
1569 test_18() {
1570         test_18_sub normal
1571         test_18_sub directio
1572
1573         # check if watchdog is triggered
1574         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
1575         local watchdog=$(awk '/sanity-quota test 18/ {start = 1;}
1576                        /Service thread pid/ && /was inactive/ {
1577                                if (start) {
1578                                        print;
1579                                }
1580                        }' $TMP/lustre-log-${TESTNAME}.log)
1581         [ -z "$watchdog" ] || error "$watchdog"
1582         rm -f $TMP/lustre-log-${TESTNAME}.log
1583 }
1584 run_test 18 "MDS failover while writing, no watchdog triggered (b14840)"
1585
1586 test_19() {
1587         local blimit=5 # 5M
1588         local TESTFILE=$DIR/$tdir/$tfile
1589
1590         setup_quota_test
1591         trap cleanup_quota_test EXIT
1592
1593         set_ost_qtype "ug" || error "enable ost quota failed"
1594
1595         # bind file to a single OST
1596         $LFS setstripe -c 1 $TESTFILE
1597         chown $TSTUSR.$TSTUSR $TESTFILE
1598
1599         echo "Set user quota (limit: "$blimit"M)"
1600         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
1601                 error "set user quota failed"
1602         quota_show_check b u $TSTUSR
1603         echo "Update quota limits"
1604         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
1605                 error "set group quota failed"
1606         quota_show_check b u $TSTUSR
1607
1608         # first wirte might be cached
1609         $RUNAS $DD of=$TESTFILE count=$((blimit + 1))
1610         cancel_lru_locks osc
1611         $SHOW_QUOTA_USER
1612         $RUNAS $DD of=$TESTFILE count=$((blimit + 1)) seek=$((blimit + 1)) &&
1613                 quota_error u $TSTUSR "Write success, expect failure"
1614         $SHOW_QUOTA_USER
1615
1616         cleanup_quota_test
1617         resetquota -u $TSTUSR
1618 }
1619 run_test 19 "Updating admin limits doesn't zero operational limits(b14790)"
1620
1621 test_20() { # b15754
1622         local LSTR=(2g 1t 4k 3m) # limits strings
1623         # limits values
1624         local LVAL=($[2*1024*1024] $[1*1024*1024*1024] $[4*1024] $[3*1024*1024])
1625
1626         resetquota -u $TSTUSR
1627
1628         $LFS setquota -u $TSTUSR --block-softlimit ${LSTR[0]} \
1629                 $MOUNT || error "could not set quota limits"
1630         $LFS setquota -u $TSTUSR --block-hardlimit ${LSTR[1]} \
1631                                 --inode-softlimit ${LSTR[2]} \
1632                                 --inode-hardlimit ${LSTR[3]} \
1633                                 $MOUNT || error "could not set quota limits"
1634
1635         [ "$(getquota -u $TSTUSR global bsoftlimit)" = "${LVAL[0]}" ] ||
1636                 error "bsoftlimit was not set properly"
1637         [ "$(getquota -u $TSTUSR global bhardlimit)" = "${LVAL[1]}" ] ||
1638                 error "bhardlimit was not set properly"
1639         [ "$(getquota -u $TSTUSR global isoftlimit)" = "${LVAL[2]}" ] ||
1640                 error "isoftlimit was not set properly"
1641         [ "$(getquota -u $TSTUSR global ihardlimit)" = "${LVAL[3]}" ] ||
1642                 error "ihardlimit was not set properly"
1643
1644         resetquota -u $TSTUSR
1645 }
1646 run_test 20 "Test if setquota specifiers work properly (b15754)"
1647
1648 test_21_sub() {
1649         local testfile=$1
1650         local blk_number=$2
1651         local seconds=$3
1652
1653         local time=$(($(date +%s) + seconds))
1654         while [ $(date +%s) -lt $time ]; do
1655                 $RUNAS $DD of=$testfile count=$blk_number > /dev/null 2>&1
1656         done
1657 }
1658
1659 # run for fixing bug16053, setquota shouldn't fail when writing and
1660 # deleting are happening
1661 test_21() {
1662         local TESTFILE="$DIR/$tdir/$tfile"
1663         local BLIMIT=10 # 10G
1664         local ILIMIT=1000000
1665
1666         setup_quota_test
1667         trap cleanup_quota_test EXIT
1668
1669         set_ost_qtype "ug" || error "Enable ost quota failed"
1670
1671         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for user: $TSTUSR"
1672         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}G -i 0 -I $ILIMIT $MOUNT ||
1673                 error "set user quota failed"
1674         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for group: $TSTUSR"
1675         $LFS setquota -g $TSTUSR -b 0 -B $BLIMIT -i 0 -I $ILIMIT $MOUNT ||
1676                 error "set group quota failed"
1677
1678         # repeat writing on a 1M file
1679         test_21_sub ${TESTFILE}_1 1 30 &
1680         local DDPID1=$!
1681         # repeat writing on a 128M file
1682         test_21_sub ${TESTFILE}_2 128 30 &
1683         local DDPID2=$!
1684
1685         local time=$(($(date +%s) + 30))
1686         local i=1
1687         while [ $(date +%s) -lt $time ]; do
1688                 log "Set quota for $i times"
1689                 $LFS setquota -u $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
1690                         -I $((ILIMIT + i)) $MOUNT ||
1691                                 error "Set user quota failed"
1692                 $LFS setquota -g $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
1693                         -I $((ILIMIT + i)) $MOUNT ||
1694                                 error "Set group quota failed"
1695                 i=$((i+1))
1696                 sleep 1
1697         done
1698
1699         local count=0
1700         while [ true ]; do
1701                 if ! ps -p ${DDPID1} > /dev/null 2>&1; then break; fi
1702                 count=$((count+1))
1703                 if [ $count -gt 60 ]; then
1704                         quota_error a $TSTUSR "dd should be finished!"
1705                 fi
1706                 sleep 1
1707         done
1708         echo "(dd_pid=$DDPID1, time=$count)successful"
1709
1710         count=0
1711         while [ true ]; do
1712                 if ! ps -p ${DDPID2} > /dev/null 2>&1; then break; fi
1713                 count=$((count+1))
1714                 if [ $count -gt 60 ]; then
1715                         quota_error a $TSTUSR "dd should be finished!"
1716                 fi
1717                 sleep 1
1718         done
1719         echo "(dd_pid=$DDPID2, time=$count)successful"
1720
1721         cleanup_quota_test
1722         resetquota -u $TSTUSR
1723         resetquota -g $TSTUSR
1724 }
1725 run_test 21 "Setquota while writing & deleting (b16053)"
1726
1727 # enable/disable quota enforcement permanently
1728 test_22() {
1729         echo "Set both mdt & ost quota type as ug"
1730         set_mdt_qtype "ug" || error "enable mdt quota failed"
1731         set_ost_qtype "ug" || error "enable ost quota failed"
1732
1733         echo "Restart..."
1734         stopall
1735         mount
1736         setupall
1737
1738         echo "Verify if quota is enabled"
1739         local qtype=$(mdt_quota_type)
1740         [ $qtype != "ug" ] && error "mdt quota setting is lost"
1741         qtype=$(ost_quota_type)
1742         [ $qtype != "ug" ] && error "ost quota setting is lost"
1743
1744         echo "Set both mdt & ost quota type as none"
1745         set_mdt_qtype "none" || error "disable mdt quota failed"
1746         set_ost_qtype "none" || error "disable ost quota failed"
1747
1748         echo "Restart..."
1749         stopall
1750         mount
1751         setupall
1752         quota_init
1753
1754         echo "Verify if quota is disabled"
1755         qtype=$(mdt_quota_type)
1756         [ $qtype != "none" ] && error "mdt quota setting is lost"
1757         qtype=$(ost_quota_type)
1758         [ $qtype != "none" ] && error "ost quota setting is lost"
1759
1760         return 0
1761 }
1762 run_test 22 "enable/disable quota by 'lctl conf_param'"
1763
1764 test_23_sub() {
1765         local TESTFILE="$DIR/$tdir/$tfile"
1766         local LIMIT=$1
1767
1768         setup_quota_test
1769         trap cleanup_quota_test EXIT
1770
1771         set_ost_qtype "ug" || error "Enable ost quota failed"
1772
1773         # test for user
1774         log "User quota (limit: $LIMIT MB)"
1775         $LFS setquota -u $TSTUSR -b 0 -B "$LIMIT"M -i 0 -I 0 $DIR ||
1776                 error "set quota failed"
1777         quota_show_check b u $TSTUSR
1778
1779         $LFS setstripe $TESTFILE -c 1 -i 0
1780         chown $TSTUSR.$TSTUSR $TESTFILE
1781
1782         log "Step1: trigger EDQUOT with O_DIRECT"
1783         log "Write half of file"
1784         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) oflag=direct ||
1785                 quota_error u $TSTUSR "(1) Write failure, expect success." \
1786                         "limit=$LIMIT"
1787         log "Write out of block quota ..."
1788         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 + 1)) seek=$((LIMIT/2)) \
1789                 oflag=direct conv=notrunc &&
1790                 quota_error u $TSTUSR "(2) Write success, expect EDQUOT." \
1791                         "limit=$LIMIT"
1792         log "Step1: done"
1793
1794         log "Step2: rewrite should succeed"
1795         $RUNAS $DD of=$TESTFILE count=1 oflag=direct conv=notrunc||
1796                 quota_error u $TSTUSR "(3) Write failure, expect success." \
1797                         "limit=$LIMIT"
1798         log "Step2: done"
1799
1800         cleanup_quota_test
1801
1802         local OST0_UUID=$(ostuuid_from_index 0)
1803         local OST0_QUOTA_USED=$(getquota -u $TSTUSR $OST0_UUID curspace)
1804         [ $OST0_QUOTA_USED -ne 0 ] &&
1805                 ($SHOW_QUOTA_USER; \
1806                 quota_error u $TSTUSR "quota isn't released")
1807         $SHOW_QUOTA_USER
1808         resetquota -u $TSTUSR
1809 }
1810
1811 test_23() {
1812         local OST0_MIN=$((6 * 1024)) # 6MB, extra space for meta blocks.
1813         check_whether_skip && return 0
1814         log "run for 4MB test file"
1815         test_23_sub 4
1816
1817         OST0_MIN=$((60 * 1024)) # 60MB, extra space for meta blocks.
1818         check_whether_skip && return 0
1819         log "run for 40MB test file"
1820         test_23_sub 40
1821 }
1822 run_test 23 "Quota should be honored with directIO (b16125)"
1823
1824 test_24() {
1825         local blimit=5 # 5M
1826         local TESTFILE="$DIR/$tdir/$tfile"
1827
1828         setup_quota_test
1829         trap cleanup_quota_test EXIT
1830
1831         set_ost_qtype "ug" || error "enable ost quota failed"
1832
1833         # bind file to a single OST
1834         $LFS setstripe -c 1 $TESTFILE
1835         chown $TSTUSR.$TSTUSR $TESTFILE
1836
1837         echo "Set user quota (limit: "$blimit"M)"
1838         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
1839                 error "set quota failed"
1840
1841         # overrun quota by root user
1842         runas -u 0 -g 0 $DD of=$TESTFILE count=$((blimit + 1)) ||
1843                 error "write failure, expect success"
1844         cancel_lru_locks osc
1845         sync_all_data || true
1846
1847         $SHOW_QUOTA_USER | grep '*' || error "no matching *"
1848
1849         cleanup_quota_test
1850         resetquota -u $TSTUSR
1851 }
1852 run_test 24 "lfs draws an asterix when limit is reached (b16646)"
1853
1854 test_27a() { # b19612
1855         $LFS quota $TSTUSR $DIR &&
1856                 error "lfs succeeded with no type, but should have failed"
1857         $LFS setquota $TSTUSR $DIR &&
1858                 error "lfs succeeded with no type, but should have failed"
1859         return 0
1860 }
1861 run_test 27a "lfs quota/setquota should handle wrong arguments (b19612)"
1862
1863 test_27b() { # b20200
1864         $LFS setquota -u $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
1865                 error "lfs setquota failed with uid argument"
1866         $LFS setquota -g $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
1867                 error "lfs stequota failed with gid argument"
1868         $SHOW_QUOTA_USERID || error "lfs quota failed with uid argument"
1869         $SHOW_QUOTA_GROUPID || error "lfs quota failed with gid argument"
1870         resetquota -u $TSTUSR
1871         resetquota -g $TSTUSR
1872         return 0
1873 }
1874 run_test 27b "lfs quota/setquota should handle user/group ID (b20200)"
1875
1876 test_30() {
1877         local output
1878         local LIMIT=4 # 4MB
1879         local TESTFILE="$DIR/$tdir/$tfile"
1880         local GRACE=10
1881
1882         setup_quota_test
1883         trap cleanup_quota_test EXIT
1884
1885         set_ost_qtype "u" || error "enable ost quota failed"
1886
1887         $LFS setstripe $TESTFILE -i 0 -c 1
1888         chown $TSTUSR.$TSTUSR $TESTFILE
1889
1890         $LFS setquota -t -u --block-grace $GRACE --inode-grace \
1891                 $MAX_IQ_TIME $DIR || error "set grace time failed"
1892         $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
1893                 error "set quota failed"
1894         $RUNAS $DD of=$TESTFILE count=$((LIMIT * 2)) || true
1895         cancel_lru_locks osc
1896         sleep $GRACE
1897         $LFS setquota -u $TSTUSR -B 0 $DIR || error "clear quota failed"
1898         # over-quota flag has not yet settled since we do not trigger async
1899         # events based on grace time period expiration
1900         $SHOW_QUOTA_USER
1901         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=1 || true
1902         cancel_lru_locks osc
1903         # now over-quota flag should be settled and further writes should fail
1904         $SHOW_QUOTA_USER
1905         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=1 &&
1906                 error "grace times were reset"
1907         # cleanup
1908         cleanup_quota_test
1909         resetquota -u $TSTUSR
1910         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1911                 $MAX_IQ_TIME $DIR || error "restore grace time failed"
1912 }
1913 run_test 30 "Hard limit updates should not reset grace times"
1914
1915 # basic usage tracking for user & group
1916 test_33() {
1917         local INODES=10 # 10 files
1918         local BLK_CNT=2 # of 2M each
1919         local TOTAL_BLKS=$((INODES * BLK_CNT * 1024))
1920
1921         setup_quota_test
1922         trap cleanup_quota_test EXIT
1923
1924         # make sure the system is clean
1925         local USED=$(getquota -u $TSTID global curspace)
1926         [ $USED -ne 0 ] &&
1927                 error "Used space ($USED) for user $TSTID isn't 0."
1928         USED=$(getquota -g $TSTID global curspace)
1929         [ $USED -ne 0 ] &&
1930                 error "Used space ($USED) for group $TSTID isn't 0."
1931
1932         echo "Write files..."
1933         for i in `seq 0 $INODES`; do
1934                 $RUNAS $DD of=$DIR/$tdir/$tfile-$i count=$BLK_CNT 2>/dev/null ||
1935                         error "write failed"
1936                 echo "Iteration $i/$INODES completed"
1937         done
1938         cancel_lru_locks osc
1939         sync; sync_all_data || true
1940
1941         echo "Verify disk usage after write"
1942         USED=$(getquota -u $TSTID global curspace)
1943         [ $USED -lt $TOTAL_BLKS ] &&
1944                 error "Used space for user $TSTID:$USED, expected:$TOTAL_BLKS"
1945         USED=$(getquota -g $TSTID global curspace)
1946         [ $USED -lt $TOTAL_BLKS ] &&
1947                 error "Used space for group $TSTID:$USED, expected:$TOTAL_BLKS"
1948
1949         echo "Verify inode usage after write"
1950         USED=$(getquota -u $TSTID global curinodes)
1951         [ $USED -lt $INODES ] &&
1952                 error "Used inode for user $TSTID is $USED, expected $INODES"
1953         USED=$(getquota -g $TSTID global curinodes)
1954         [ $USED -lt $INODES ] &&
1955                 error "Used inode for group $TSTID is $USED, expected $INODES"
1956
1957         cleanup_quota_test
1958
1959         echo "Verify disk usage after delete"
1960         USED=$(getquota -u $TSTID global curspace)
1961         [ $USED -eq 0 ] || error "Used space for user $TSTID isn't 0. $USED"
1962         USED=$(getquota -u $TSTID global curinodes)
1963         [ $USED -eq 0 ] || error "Used inodes for user $TSTID isn't 0. $USED"
1964         USED=$(getquota -g $TSTID global curspace)
1965         [ $USED -eq 0 ] || error "Used space for group $TSTID isn't 0. $USED"
1966         USED=$(getquota -g $TSTID global curinodes)
1967         [ $USED -eq 0 ] || error "Used inodes for group $TSTID isn't 0. $USED"
1968 }
1969 run_test 33 "Basic usage tracking for user & group"
1970
1971 # usage transfer test for user & group
1972 test_34() {
1973         local BLK_CNT=2 # 2MB
1974
1975         setup_quota_test
1976         trap cleanup_quota_test EXIT
1977
1978         # make sure the system is clean
1979         local USED=$(getquota -u $TSTID global curspace)
1980         [ $USED -ne 0 ] && error "Used space ($USED) for user $TSTID isn't 0."
1981         USED=$(getquota -g $TSTID global curspace)
1982         [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTID isn't 0."
1983
1984         echo "Write file..."
1985         $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
1986                 error "write failed"
1987         cancel_lru_locks osc
1988         sync; sync_all_data || true
1989
1990         echo "chown the file to user $TSTID"
1991         chown $TSTID $DIR/$tdir/$tfile || error "chown failed"
1992
1993         echo "Wait for setattr on objects finished..."
1994         wait_delete_completed
1995
1996         BLK_CNT=$((BLK_CNT * 1024))
1997
1998         echo "Verify disk usage for user $TSTID"
1999         USED=$(getquota -u $TSTID global curspace)
2000         [ $USED -lt $BLK_CNT ] &&
2001                 error "Used space for user $TSTID is ${USED}, expected $BLK_CNT"
2002         USED=$(getquota -u $TSTID global curinodes)
2003         [ $USED -ne 1 ] &&
2004                 error "Used inodes for user $TSTID is $USED, expected 1"
2005
2006         echo "chgrp the file to group $TSTID"
2007         chgrp $TSTID $DIR/$tdir/$tfile || error "chgrp failed"
2008
2009         echo "Wait for setattr on objects finished..."
2010         wait_delete_completed
2011
2012         echo "Verify disk usage for group $TSTID"
2013         USED=$(getquota -g $TSTID global curspace)
2014         [ $USED -ge $BLK_CNT ] ||
2015                 error "Used space for group $TSTID is $USED, expected $BLK_CNT"
2016         USED=$(getquota -g $TSTID global curinodes)
2017         [ $USED -eq 1 ] ||
2018                 error "Used inodes for group $TSTID is $USED, expected 1"
2019
2020         cleanup_quota_test
2021 }
2022 run_test 34 "Usage transfer for user & group"
2023
2024 # usage is still accessible across restart
2025 test_35() {
2026         local BLK_CNT=2 # 2 MB
2027
2028         setup_quota_test
2029         trap cleanup_quota_test EXIT
2030
2031         echo "Write file..."
2032         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
2033                 error "write failed"
2034         cancel_lru_locks osc
2035         sync; sync_all_data || true
2036
2037         echo "Save disk usage before restart"
2038         local ORIG_USR_SPACE=$(getquota -u $TSTID global curspace)
2039         [ $ORIG_USR_SPACE -eq 0 ] &&
2040                 error "Used space for user $TSTID is 0, expected ${BLK_CNT}M"
2041         local ORIG_USR_INODES=$(getquota -u $TSTID global curinodes)
2042         [ $ORIG_USR_INODES -eq 0 ] &&
2043                 error "Used inodes for user $TSTID is 0, expected 1"
2044         echo "User $TSTID: ${ORIG_USR_SPACE}KB $ORIG_USR_INODES inodes"
2045         local ORIG_GRP_SPACE=$(getquota -g $TSTID global curspace)
2046         [ $ORIG_GRP_SPACE -eq 0 ] &&
2047                 error "Used space for group $TSTID is 0, expected ${BLK_CNT}M"
2048         local ORIG_GRP_INODES=$(getquota -g $TSTID global curinodes)
2049         [ $ORIG_GRP_INODES -eq 0 ] &&
2050                 error "Used inodes for group $TSTID is 0, expected 1"
2051         echo "Group $TSTID: ${ORIG_GRP_SPACE}KB $ORIG_GRP_INODES inodes"
2052
2053         log "Restart..."
2054         local ORIG_REFORMAT=$REFORMAT
2055         REFORMAT=""
2056         cleanup_and_setup_lustre
2057         REFORMAT=$ORIG_REFORMAT
2058         quota_init
2059
2060         echo "Verify disk usage after restart"
2061         local USED=$(getquota -u $TSTID global curspace)
2062         [ $USED -eq $ORIG_USR_SPACE ] ||
2063                 error "Used space for user $TSTID changed from " \
2064                         "$ORIG_USR_SPACE to $USED"
2065         USED=$(getquota -u $TSTID global curinodes)
2066         [ $USED -eq $ORIG_USR_INODES ] ||
2067                 error "Used inodes for user $TSTID changed from " \
2068                         "$ORIG_USR_INODES to $USED"
2069         USED=$(getquota -g $TSTID global curspace)
2070         [ $USED -eq $ORIG_GRP_SPACE ] ||
2071                 error "Used space for group $TSTID changed from " \
2072                         "$ORIG_GRP_SPACE to $USED"
2073         USED=$(getquota -g $TSTID global curinodes)
2074         [ $USED -eq $ORIG_GRP_INODES ] ||
2075                 error "Used inodes for group $TSTID changed from " \
2076                         "$ORIG_GRP_INODES to $USED"
2077
2078         # check if the vfs_dq_init() is called before writing
2079         echo "Append to the same file..."
2080         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT seek=1 2>/dev/null ||
2081                 error "write failed"
2082         cancel_lru_locks osc
2083         sync; sync_all_data || true
2084
2085         echo "Verify space usage is increased"
2086         USED=$(getquota -u $TSTID global curspace)
2087         [ $USED -gt $ORIG_USR_SPACE ] ||
2088                 error "Used space for user $TSTID isn't increased" \
2089                         "orig:$ORIG_USR_SPACE, now:$USED"
2090         USED=$(getquota -g $TSTID global curspace)
2091         [ $USED -gt $ORIG_GRP_SPACE ] ||
2092                 error "Used space for group $TSTID isn't increased" \
2093                         "orig:$ORIG_GRP_SPACE, now:$USED"
2094
2095         cleanup_quota_test
2096 }
2097 run_test 35 "Usage is still accessible across reboot"
2098
2099 # test migrating old amdin quota files (in Linux quota file format v2) into new
2100 # quota global index (in IAM format)
2101 test_36() {
2102         [ "$FSTYPE" != "ldiskfs" ] &&
2103                 skip "skipping migration test" && return
2104
2105         # get the mdt0 device name
2106         local mdt0_node=$(facet_active_host $SINGLEMDS)
2107         local mdt0_dev=$(mdsdevname ${SINGLEMDS//mds/})
2108
2109         echo "Reformat..."
2110         formatall
2111
2112         echo "Copy admin quota files into MDT0..."
2113         local mntpt=$(facet_mntpt $SINGLEMDS)
2114         local mdt0_fstype=$FSTYPE
2115         local opt
2116         if ! do_node $mdt0_node test -b $mdt0_fstype; then
2117                 opt="-o loop"
2118         fi
2119         echo "$mdt0_node, $mdt0_dev, $mntpt, $opt"
2120         do_node $mdt0_node mount -t $mdt0_fstype $opt $mdt0_dev $mntpt
2121         do_node $mdt0_node mkdir $mntpt/OBJECTS
2122         do_node $mdt0_node cp $LUSTRE/tests/admin_quotafile_v2.usr $mntpt/OBJECTS
2123         do_node $mdt0_node cp $LUSTRE/tests/admin_quotafile_v2.grp $mntpt/OBJECTS
2124         do_node $mdt0_node umount -f $mntpt
2125
2126         echo "Setup all..."
2127         setupall
2128
2129         echo "Verify global limits..."
2130         local id_cnt
2131         local limit
2132
2133         local proc="qmt.*.md-0x0.glb-usr"
2134         id_cnt=$(do_node $mdt0_node $LCTL get_param -n $proc | wc -l)
2135         [ $id_cnt -eq 403 ] || error "Migrate inode user limit failed: $id_cnt"
2136         limit=$(getquota -u 1 global isoftlimit)
2137         [ $limit -eq 1024 ] || error "User inode softlimit: $limit"
2138         limit=$(getquota -u 1 global ihardlimit)
2139         [ $limit -eq 2048 ] || error "User inode hardlimit: $limit"
2140
2141         proc="qmt.*.md-0x0.glb-grp"
2142         id_cnt=$(do_node $mdt0_node $LCTL get_param -n $proc | wc -l)
2143         [ $id_cnt -eq 403 ] || error "Migrate inode group limit failed: $id_cnt"
2144         limit=$(getquota -g 1 global isoftlimit)
2145         [ $limit -eq 1024 ] || error "Group inode softlimit: $limit"
2146         limit=$(getquota -g 1 global ihardlimit)
2147         [ $limit -eq 2048 ] || error "Group inode hardlimit: $limit"
2148
2149         proc=" qmt.*.dt-0x0.glb-usr"
2150         id_cnt=$(do_node $mdt0_node $LCTL get_param -n $proc | wc -l)
2151         [ $id_cnt -eq 403 ] || error "Migrate block user limit failed: $id_cnt"
2152         limit=$(getquota -u 60001 global bsoftlimit)
2153         [ $limit -eq 10485760 ] || error "User block softlimit: $limit"
2154         limit=$(getquota -u 60001 global bhardlimit)
2155         [ $limit -eq 20971520 ] || error "User block hardlimit: $limit"
2156
2157         proc="qmt.*.dt-0x0.glb-grp"
2158         id_cnt=$(do_node $mdt0_node $LCTL get_param -n $proc | wc -l)
2159         [ $id_cnt -eq 403 ] || error "Migrate block user limit failed: $id_cnt"
2160         limit=$(getquota -g 60001 global bsoftlimit)
2161         [ $limit -eq 10485760 ] || error "Group block softlimit: $limit"
2162         limit=$(getquota -g 60001 global bhardlimit)
2163         [ $limit -eq 20971520 ] || error "Group block hardlimit: $limit"
2164
2165         echo "Cleanup..."
2166         formatall
2167         setupall
2168 }
2169 run_test 36 "Migrate old admin files into new global indexes"
2170
2171 quota_fini()
2172 {
2173         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
2174 }
2175 quota_fini
2176
2177 cd $ORIG_PWD
2178 complete $(basename $0) $SECONDS
2179 check_and_cleanup_lustre
2180 export QUOTA_AUTO=$QUOTA_AUTO_OLD
2181 exit_status