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