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