Whamcloud - gitweb
LU-11023 quota: quota pools for OSTs
[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 set -e
7
8 ONLY=${ONLY:-"$*"}
9
10 LUSTRE=${LUSTRE:-$(dirname $0)/..}
11 . $LUSTRE/tests/test-framework.sh
12 init_test_env $@
13 init_logging
14
15 ALWAYS_EXCEPT="$SANITY_QUOTA_EXCEPT "
16 # Bug number for skipped test:  LU-5152
17 ALWAYS_EXCEPT+="                55"
18 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
19
20 # Test duration:                   30 min
21 [ "$SLOW" = "no" ] && EXCEPT_SLOW="61"
22
23 if [ "$mds1_FSTYPE" = zfs ]; then
24         # bug number:                        LU-2887
25         # Test duration:                     21      9 min"
26         [ "$SLOW" = "no" ] && EXCEPT_SLOW+=" 12a     9"
27 fi
28
29 build_test_filter
30
31 DIRECTIO=${DIRECTIO:-$LUSTRE/tests/directio}
32 ORIG_PWD=${PWD}
33 TSTID=${TSTID:-60000}
34 TSTID2=${TSTID2:-60001}
35 TSTUSR=${TSTUSR:-"quota_usr"}
36 TSTUSR2=${TSTUSR2:-"quota_2usr"}
37 TSTPRJID=${TSTPRJID:-1000}
38 BLK_SZ=1024
39 MAX_DQ_TIME=604800
40 MAX_IQ_TIME=604800
41 QTYPE="ugp"
42 # QP exists since this version. Should be finally set before landing.
43 VERSION_WITH_QP="2.13.53"
44 mds_supports_qp() {
45         [ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ] &&
46                 skip "Needs MDS version $VERSION_WITH_QP or later."
47 }
48
49 require_dsh_mds || exit 0
50 require_dsh_ost || exit 0
51
52 # Does e2fsprogs support quota feature?
53 if [ "$mds1_FSTYPE" == ldiskfs ] &&
54         do_facet $SINGLEMDS "! $DEBUGFS -c -R supported_features |
55                 grep -q 'quota'"; then
56         skip_env "e2fsprogs doesn't support quota"
57 fi
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 ENABLE_PROJECT_QUOTAS=${ENABLE_PROJECT_QUOTAS:-true}
72
73 SHOW_QUOTA_USER="$LFS quota -v -u $TSTUSR $DIR"
74 SHOW_QUOTA_USERID="$LFS quota -v -u $TSTID $DIR"
75 SHOW_QUOTA_GROUP="$LFS quota -v -g $TSTUSR $DIR"
76 SHOW_QUOTA_GROUPID="$LFS quota -v -g $TSTID $DIR"
77 SHOW_QUOTA_PROJID="eval is_project_quota_supported && $LFS quota -v -p $TSTPRJID $DIR"
78 SHOW_QUOTA_INFO_USER="$LFS quota -t -u $DIR"
79 SHOW_QUOTA_INFO_GROUP="$LFS quota -t -g $DIR"
80 SHOW_QUOTA_INFO_PROJID="eval is_project_quota_supported && $LFS quota -t -p $DIR"
81
82 lustre_fail() {
83         local fail_node=$1
84         local fail_loc=$2
85         local fail_val=${3:-0}
86         local NODES=
87
88         case $fail_node in
89         mds_ost|mdt_ost) NODES="$(comma_list $(mdts_nodes) $(osts_nodes))";;
90         mds|mdt) NODES="$(comma_list $(mdts_nodes))";;
91         ost) NODES="$(comma_list $(osts_nodes))";;
92         esac
93
94         do_nodes $NODES "lctl set_param fail_val=$fail_val fail_loc=$fail_loc"
95 }
96
97 change_project()
98 {
99         echo "lfs project $*"
100         lfs project $* || error "lfs project $* failed"
101 }
102
103 RUNAS="runas -u $TSTID -g $TSTID"
104 RUNAS2="runas -u $TSTID2 -g $TSTID2"
105 DD="dd if=/dev/zero bs=1M"
106
107 FAIL_ON_ERROR=false
108
109 # clear quota limits for a user or a group
110 # usage: resetquota -u username
111 #        resetquota -g groupname
112 #        resetquota -p projid
113
114 resetquota() {
115         [ "$#" != 2 ] && error "resetquota: wrong number of arguments: $#"
116         [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] &&
117                 error "resetquota: wrong specifier $1 passed"
118
119         if [ $1 == "-p" ]; then
120                 is_project_quota_supported || return 0
121         fi
122
123         $LFS setquota "$1" "$2" -b 0 -B 0 -i 0 -I 0 $MOUNT ||
124                 error "clear quota for [type:$1 name:$2] failed"
125         # give a chance to slave to release space
126         sleep 1
127 }
128
129 quota_scan() {
130         local local_ugp=$1
131         local local_id=$2
132
133         if [ "$local_ugp" == "a" -o "$local_ugp" == "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_ugp" == "a" -o "$local_ugp" == "g" ]; then
141                 $LFS quota -v -g $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         is_project_quota_supported || return 0
148         if [ "$local_ugp" == "a" -o "$local_ugp" == "p" ]; then
149                 $LFS quota -v -p $TSTPRJID $DIR
150                 log "Files for project ($TSTPRJID):"
151                 ($LFS find --projid $TSTPRJID $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|-p <username>|<groupname>|<projid> global|<obd_uuid> \
170 #                 bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace \
171 #                 <pool_name>
172 getquota() {
173         local spec
174         local uuid
175         local pool_arg
176
177         sync_all_data > /dev/null 2>&1 || true
178
179         [ "$#" != 4 -a "$#" != 5 ] &&
180                 error "getquota: wrong number of arguments: $#"
181         [ "$1" != "-u" -a "$1" != "-g" -a "$1" != "-p" ] &&
182                 error "getquota: wrong u/g/p specifier $1 passed"
183
184         uuid="$3"
185
186         case "$4" in
187                 curspace)   spec=1;;
188                 bsoftlimit) spec=2;;
189                 bhardlimit) spec=3;;
190                 bgrace)     spec=4;;
191                 curinodes)  spec=5;;
192                 isoftlimit) spec=6;;
193                 ihardlimit) spec=7;;
194                 igrace)     spec=8;;
195                 *)          error "unknown quota parameter $4";;
196         esac
197
198         [ ! -z "$5" ] && pool_arg="--pool $5 "
199         [ "$uuid" = "global" ] && uuid=$DIR
200
201         $LFS quota -v "$1" "$2" $pool_arg $DIR |
202                 awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") \
203                 { if (NF == 1) { getline } else { num++ } ; print $num;} }' \
204                 | tr -d "*"
205 }
206
207 # set mdt quota type
208 # usage: set_mdt_qtype ugp|u|g|p|none
209 set_mdt_qtype() {
210         local qtype=$1
211         local varsvc
212         local mdts=$(get_facets MDS)
213         local cmd
214         [[ "$qtype" =~ "p" ]] && ! is_project_quota_supported &&
215                 qtype=$(tr -d 'p' <<<$qtype)
216
217         if [[ $PERM_CMD == *"set_param -P"* ]]; then
218                 do_facet mgs $PERM_CMD \
219                         osd-*.$FSNAME-MDT*.quota_slave.enable=$qtype
220         else
221                 do_facet mgs $PERM_CMD $FSNAME.quota.mdt=$qtype
222         fi
223         # we have to make sure each MDT received config changes
224         for mdt in ${mdts//,/ }; do
225                 varsvc=${mdt}_svc
226                 cmd="$LCTL get_param -n "
227                 cmd=${cmd}osd-$(facet_fstype $mdt).${!varsvc}
228                 cmd=${cmd}.quota_slave.enabled
229
230                 if $(facet_up $mdt); then
231                         wait_update_facet $mdt "$cmd" "$qtype" || return 1
232                 fi
233         done
234         return 0
235 }
236
237 # set ost quota type
238 # usage: set_ost_qtype ugp|u|g|p|none
239 set_ost_qtype() {
240         local qtype=$1
241         local varsvc
242         local osts=$(get_facets OST)
243         local cmd
244         [[ "$qtype" =~ "p" ]] && ! is_project_quota_supported &&
245                 qtype=$(tr -d 'p' <<<$qtype)
246
247         if [[ $PERM_CMD == *"set_param -P"* ]]; then
248                 do_facet mgs $PERM_CMD \
249                         osd-*.$FSNAME-OST*.quota_slave.enable=$qtype
250         else
251                 do_facet mgs $PERM_CMD $FSNAME.quota.ost=$qtype
252         fi
253         # we have to make sure each OST received config changes
254         for ost in ${osts//,/ }; do
255                 varsvc=${ost}_svc
256                 cmd="$LCTL get_param -n "
257                 cmd=${cmd}osd-$(facet_fstype $ost).${!varsvc}
258                 cmd=${cmd}.quota_slave.enabled
259
260                 if $(facet_up $ost); then
261                         wait_update_facet $ost "$cmd" "$qtype" || return 1
262                 fi
263         done
264         return 0
265 }
266
267 wait_reintegration() {
268         local ntype=$1
269         local qtype=$2
270         local max=$3
271         local result="glb[1],slv[1],reint[0]"
272         local varsvc
273         local cmd
274         local tgts
275
276         if [ $ntype == "mdt" ]; then
277                 tgts=$(get_facets MDS)
278         else
279                 tgts=$(get_facets OST)
280         fi
281
282         for tgt in ${tgts//,/ }; do
283                 varsvc=${tgt}_svc
284                 cmd="$LCTL get_param -n "
285                 cmd=${cmd}osd-$(facet_fstype $tgt).${!varsvc}
286                 cmd=${cmd}.quota_slave.info
287
288                 if $(facet_up $tgt); then
289                         wait_update_facet $tgt "$cmd |
290                                 grep "$qtype" | awk '{ print \\\$3 }'" \
291                                         "$result" $max || return 1
292                 fi
293         done
294         return 0
295 }
296
297 wait_mdt_reint() {
298         local qtype=$1
299         local max=${2:-90}
300
301         if [[ "$qtype" =~ "u" ]]; then
302                 wait_reintegration "mdt" "user" $max || return 1
303         fi
304
305         if [[ "$qtype" =~ "g" ]]; then
306                 wait_reintegration "mdt" "group" $max || return 1
307         fi
308
309         if [[ "$qtype" =~ "p" ]]; then
310                 ! is_project_quota_supported && return 0
311                 wait_reintegration "mdt" "project" $max || return 1
312         fi
313         return 0
314 }
315
316 wait_ost_reint() {
317         local qtype=$1
318         local max=${2:-90}
319
320         if [[ "$qtype" =~ "u" ]]; then
321                 wait_reintegration "ost" "user" $max || return 1
322         fi
323
324         if [[ "$qtype" =~ "g" ]]; then
325                 wait_reintegration "ost" "group" $max || return 1
326         fi
327
328         if [[ "$qtype" =~ "p" ]]; then
329                 ! is_project_quota_supported && return 0
330                 wait_reintegration "ost" "project" $max || return 1
331         fi
332         return 0
333 }
334
335 wait_grace_time() {
336         local qtype=$1
337         local flavour=$2
338         local pool=${3:-}
339         local extrasleep=${4:-5}
340         local qarg
341         local parg
342
343         case $qtype in
344                 u|g) qarg=$TSTUSR ;;
345                 p) qarg=$TSTPRJID ;;
346                 *) error "get_grace_time: Invalid quota type: $qtype"
347         esac
348
349         if [ $pool ]; then
350                 parg="--pool "$pool
351                 echo "Quota info for $pool:"
352                 $LFS quota -$qtype $qarg $parg $DIR
353         fi
354
355         case $flavour in
356                 block)
357                         time=$(lfs quota -$qtype $qarg $parg $DIR|
358                                    awk 'NR == 3{ print $5 }'| sed 's/s$//')
359                         ;;
360                 file)
361                         time=$(lfs quota -$qtype $qarg $DIR|
362                                    awk 'NR == 3{ print $9 }'| sed 's/s$//')
363                         ;;
364                 *)
365                         error "Unknown quota type: $flavour"
366                         ;;
367         esac
368
369         echo "Sleep through grace ..."
370         [ "$time" == "-" ] &&
371             error "Grace timeout was not set or quota not exceeded"
372         if [ "$time" == "none" ]; then
373             echo "...Grace timeout already expired"
374         else
375                 let time+=$extrasleep
376                 echo "...sleep $time seconds"
377                 sleep $time
378         fi
379 }
380
381 setup_quota_test() {
382         wait_delete_completed
383         echo "Creating test directory"
384         mkdir $DIR/$tdir || return 1
385         chmod 0777 $DIR/$tdir || return 2
386         # always clear fail_loc in case of fail_loc isn't cleared
387         # properly when previous test failed
388         lustre_fail mds_ost 0
389 }
390
391 cleanup_quota_test() {
392         echo "Delete files..."
393         rm -rf $DIR/$tdir
394         echo "Wait for unlink objects finished..."
395         wait_delete_completed
396         sync_all_data || true
397         reset_quota_settings
398 }
399
400 quota_show_check() {
401         local bf=$1
402         local ugp=$2
403         local qid=$3
404         local usage
405
406         $LFS quota -v -$ugp $qid $DIR
407
408         if [ "$bf" == "a" -o "$bf" == "b" ]; then
409                 usage=$(getquota -$ugp $qid global curspace)
410                 if [ -z $usage ]; then
411                         quota_error $ugp $qid \
412                                 "Query block quota failed ($ugp:$qid)."
413                 else
414                         [ $usage -ne 0 ] && quota_log $ugp $qid \
415                                 "Block quota isn't 0 ($ugp:$qid:$usage)."
416                 fi
417         fi
418
419         if [ "$bf" == "a" -o "$bf" == "f" ]; then
420                 usage=$(getquota -$ugp $qid global curinodes)
421                 if [ -z $usage ]; then
422                         quota_error $ugp $qid \
423                                 "Query file quota failed ($ugp:$qid)."
424                 else
425                         [ $usage -ne 0 ] && quota_log $ugp $qid \
426                                 "File quota isn't 0 ($ugp:$qid:$usage)."
427                 fi
428         fi
429 }
430
431 project_quota_enabled () {
432         local rc=0
433         local zfeat="feature@project_quota"
434
435         for facet in $(seq -f mds%g $MDSCOUNT) $(seq -f ost%g $OSTCOUNT); do
436                 local facet_fstype=${facet:0:3}1_FSTYPE
437                 local devname
438
439                 if [ "${!facet_fstype}" = "zfs" ]; then
440                         devname=$(zpool_name ${facet})
441                         do_facet ${facet} $ZPOOL get -H "$zfeat" $devname |
442                                 grep -wq active || rc=1
443                 else
444                         [ ${facet:0:3} == "mds" ] &&
445                                 devname=$(mdsdevname ${facet:3}) ||
446                                 devname=$(ostdevname ${facet:3})
447                         do_facet ${facet} $DEBUGFS -R features $devname |
448                                 grep -q project || rc=1
449                 fi
450         done
451         [ $rc -eq 0 ] && PQ_CLEANUP=false || PQ_CLEANUP=true
452         return $rc
453 }
454
455 project_quota_enabled || enable_project_quota
456
457 reset_quota_settings() {
458         resetquota -u $TSTUSR
459         resetquota -u $TSTID
460         resetquota -g $TSTUSR
461         resetquota -g $TSTID
462         resetquota -u $TSTUSR2
463         resetquota -u $TSTID2
464         resetquota -g $TSTUSR2
465         resetquota -g $TSTID2
466         resetquota -p $TSTPRJID
467 }
468
469 # enable quota debug
470 quota_init() {
471         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=+quota+trace"
472 }
473 quota_init
474 reset_quota_settings
475
476 check_runas_id_ret $TSTUSR $TSTUSR $RUNAS ||
477         error "Please create user $TSTUSR($TSTID) and group $TSTUSR($TSTID)"
478 check_runas_id_ret $TSTUSR2 $TSTUSR2 $RUNAS2 ||
479         error "Please create user $TSTUSR2($TSTID2) and group $TSTUSR2($TSTID2)"
480
481 test_quota_performance() {
482         local TESTFILE="$DIR/$tdir/$tfile-0"
483         local size=$1 # in MB
484         local stime=$(date +%s)
485         $RUNAS $DD of=$TESTFILE count=$size conv=fsync ||
486                 quota_error u $TSTUSR "write failure"
487         local etime=$(date +%s)
488         delta=$((etime - stime))
489         if [ $delta -gt 0 ]; then
490                 rate=$((size * 1024 / delta))
491                 if [ "$mds1_FSTYPE" = zfs ]; then
492                         # LU-2872 - see LU-2887 for fix
493                         [ $rate -gt 64 ] ||
494                                 error "SLOW IO for $TSTUSR (user): $rate KB/sec"
495                 else
496                         [ $rate -gt 1024 ] ||
497                                 error "SLOW IO for $TSTUSR (user): $rate KB/sec"
498                 fi
499         fi
500         rm -f $TESTFILE
501 }
502
503 # test basic quota performance b=21696
504 test_0() {
505         local MB=100 # 100M
506         [ "$SLOW" = "no" ] && MB=10
507
508         local free_space=$(lfs_df | grep "summary" | awk '{print $4}')
509         [ $free_space -le $((MB * 1024)) ] &&
510                 skip "not enough space ${free_space} KB, " \
511                         "required $((MB * 1024)) KB"
512         setup_quota_test || error "setup quota failed with $?"
513         trap cleanup_quota_test EXIT
514
515         set_ost_qtype "none" || error "disable ost quota failed"
516         test_quota_performance $MB
517
518         set_ost_qtype $QTYPE || error "enable ost quota failed"
519         $LFS setquota -u $TSTUSR -b 0 -B 10G -i 0 -I 0 $DIR ||
520                 error "set quota failed"
521         test_quota_performance $MB
522
523         cleanup_quota_test
524 }
525 run_test 0 "Test basic quota performance"
526
527 # usage: test_1_check_write tfile user|group|project
528 test_1_check_write() {
529         local testfile="$1"
530         local qtype="$2"
531         local limit=$3
532         local short_qtype=${qtype:0:1}
533
534         log "Write..."
535         $RUNAS $DD of=$testfile count=$((limit/2)) ||
536                 quota_error $short_qtype $TSTUSR \
537                         "$qtype write failure, but expect success"
538         log "Write out of block quota ..."
539         # this time maybe cache write,  ignore it's failure
540         $RUNAS $DD of=$testfile count=$((limit/2)) seek=$((limit/2)) || true
541         # flush cache, ensure noquota flag is set on client
542         cancel_lru_locks osc
543         sync; sync_all_data || true
544         # sync means client wrote all it's cache, but id doesn't
545         # garantee that slave got new edquot trough glimpse.
546         # so wait a little to be sure slave got it.
547         sleep 5
548         $RUNAS $DD of=$testfile count=1 seek=$limit &&
549                 quota_error $short_qtype $TSTUSR \
550                         "user write success, but expect EDQUOT"
551 }
552
553 # test block hardlimit
554 test_1a() {
555         local limit=10  # 10M
556         local testfile="$DIR/$tdir/$tfile-0"
557
558         setup_quota_test || error "setup quota failed with $?"
559         trap cleanup_quota_test EXIT
560
561         # enable ost quota
562         set_ost_qtype $QTYPE || error "enable ost quota failed"
563
564         # test for user
565         log "User quota (block hardlimit:$limit MB)"
566         $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR ||
567                 error "set user quota failed"
568
569         # make sure the system is clean
570         local used=$(getquota -u $TSTUSR global curspace)
571         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
572
573         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
574         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
575
576         test_1_check_write $testfile "user" $limit
577
578         rm -f $testfile
579         wait_delete_completed || error "wait_delete_completed failed"
580         sync_all_data || true
581         used=$(getquota -u $TSTUSR global curspace)
582         [ $used -ne 0 ] && quota_error u $TSTUSR \
583                 "user quota isn't released after deletion"
584         resetquota -u $TSTUSR
585
586         # test for group
587         log "--------------------------------------"
588         log "Group quota (block hardlimit:$limit MB)"
589         $LFS setquota -g $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR ||
590                 error "set group quota failed"
591
592         testfile="$DIR/$tdir/$tfile-1"
593         # make sure the system is clean
594         used=$(getquota -g $TSTUSR global curspace)
595         [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0"
596
597         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
598         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
599
600         test_1_check_write $testfile "group" $limit
601         rm -f $testfile
602         wait_delete_completed || error "wait_delete_completed failed"
603         sync_all_data || true
604         used=$(getquota -g $TSTUSR global curspace)
605         [ $used -ne 0 ] && quota_error g $TSTUSR \
606                                 "Group quota isn't released after deletion"
607         resetquota -g $TSTUSR
608
609         if ! is_project_quota_supported; then
610                 echo "Project quota is not supported"
611                 cleanup_quota_test
612                 return 0
613         fi
614
615         testfile="$DIR/$tdir/$tfile-2"
616         # make sure the system is clean
617         used=$(getquota -p $TSTPRJID global curspace)
618         [ $used -ne 0 ] &&
619                 error "used space($used) for project $TSTPRJID isn't 0"
620
621         # test for Project
622         log "--------------------------------------"
623         log "Project quota (block hardlimit:$limit mb)"
624         $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M -i 0 -I 0 $DIR ||
625                 error "set project quota failed"
626
627         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
628         chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed"
629         change_project -p $TSTPRJID $testfile
630
631         test_1_check_write $testfile "project" $limit
632
633         # cleanup
634         cleanup_quota_test
635
636         used=$(getquota -p $TSTPRJID global curspace)
637         [ $used -ne 0 ] && quota_error p $TSTPRJID \
638                 "project quota isn't released after deletion"
639
640         resetquota -p $TSTPRJID
641 }
642 run_test 1a "Block hard limit (normal use and out of quota)"
643
644 test_1b() {
645         local limit=10  # 10M
646         local global_limit=20  # 100M
647         local testfile="$DIR/$tdir/$tfile-0"
648         local qpool="qpool1"
649
650         mds_supports_qp
651         setup_quota_test || error "setup quota failed with $?"
652         stack_trap cleanup_quota_test EXIT
653
654         # enable ost quota
655         set_ost_qtype $QTYPE || error "enable ost quota failed"
656
657         # test for user
658         log "User quota (block hardlimit:$global_limit MB)"
659         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
660                 error "set user quota failed"
661
662         pool_add $qpool || error "pool_add failed"
663         pool_add_targets $qpool 0 $(($OSTCOUNT - 1)) ||
664                 error "pool_add_targets failed"
665
666         $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR ||
667                 error "set user quota failed"
668
669         # make sure the system is clean
670         local used=$(getquota -u $TSTUSR global curspace)
671         echo "used $used"
672         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
673
674         used=$(getquota -u $TSTUSR global bhardlimit $qpool)
675
676         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
677         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
678
679         test_1_check_write $testfile "user" $limit
680
681         rm -f $testfile
682         wait_delete_completed || error "wait_delete_completed failed"
683         sync_all_data || true
684         used=$(getquota -u $TSTUSR global curspace $qpool)
685         [ $used -ne 0 ] && quota_error u $TSTUSR \
686                 "user quota isn't released after deletion"
687         resetquota -u $TSTUSR
688
689         # test for group
690         log "--------------------------------------"
691         log "Group quota (block hardlimit:$global_limit MB)"
692         $LFS setquota -g $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
693                 error "set group quota failed"
694
695         $LFS setquota -g $TSTUSR -b 0 -B ${limit}M -o $qpool $DIR ||
696                 error "set group quota failed"
697
698         testfile="$DIR/$tdir/$tfile-1"
699         # make sure the system is clean
700         used=$(getquota -g $TSTUSR global curspace $qpool)
701         [ $used -ne 0 ] && error "Used space ($used) for group $TSTUSR isn't 0"
702
703         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
704         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
705
706         test_1_check_write $testfile "group" $limit
707
708         rm -f $testfile
709         wait_delete_completed || error "wait_delete_completed failed"
710         sync_all_data || true
711         used=$(getquota -g $TSTUSR global curspace $qpool)
712         [ $used -ne 0 ] && quota_error g $TSTUSR \
713                                 "Group quota isn't released after deletion"
714         resetquota -g $TSTUSR
715
716         if ! is_project_quota_supported; then
717                 echo "Project quota is not supported"
718                 cleanup_quota_test
719                 return 0
720         fi
721
722         testfile="$DIR/$tdir/$tfile-2"
723         # make sure the system is clean
724         used=$(getquota -p $TSTPRJID global curspace $qpool)
725         [ $used -ne 0 ] &&
726                 error "used space($used) for project $TSTPRJID isn't 0"
727
728         # test for Project
729         log "--------------------------------------"
730         log "Project quota (block hardlimit:$global_limit mb)"
731         $LFS setquota -p $TSTPRJID -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
732                 error "set project quota failed"
733
734         $LFS setquota -p $TSTPRJID -b 0 -B ${limit}M -o $qpool $DIR ||
735                 error "set project quota failed"
736
737
738         $LFS setstripe $testfile -c 1 || error "setstripe $testfile failed"
739         chown $TSTUSR:$TSTUSR $testfile || error "chown $testfile failed"
740         change_project -p $TSTPRJID $testfile
741
742         test_1_check_write $testfile "project" $limit
743
744         # cleanup
745         cleanup_quota_test
746
747         used=$(getquota -p $TSTPRJID global curspace)
748         [ $used -eq 0 ] || quota_error p $TSTPRJID \
749                 "project quota isn't released after deletion"
750 }
751 run_test 1b "Quota pools: Block hard limit (normal use and out of quota)"
752
753 test_1c() {
754         local global_limit=20  # 100M
755         local testfile="$DIR/$tdir/$tfile-0"
756         local qpool1="qpool1"
757         local qpool2="qpool2"
758
759         mds_supports_qp
760         setup_quota_test || error "setup quota failed with $?"
761         stack_trap cleanup_quota_test EXIT
762
763         # enable ost quota
764         set_ost_qtype $QTYPE || error "enable ost quota failed"
765
766         # test for user
767         log "User quota (block hardlimit:$global_limit MB)"
768         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
769                 error "set user quota failed"
770
771         pool_add $qpool1 || error "pool_add failed"
772         pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) ||
773                 error "pool_add_targets failed"
774
775         pool_add $qpool2 || error "pool_add failed"
776         pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) ||
777                 error "pool_add_targets failed"
778
779         # create pools without hard limit
780         # initially such case raised several bugs
781         $LFS setquota -u $TSTUSR -B 0M -o $qpool1 $DIR ||
782                 error "set user quota failed"
783
784         $LFS setquota -u $TSTUSR -B 0M -o $qpool2 $DIR ||
785                 error "set user quota failed"
786
787         # make sure the system is clean
788         local used=$(getquota -u $TSTUSR global curspace)
789         echo "used $used"
790         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
791
792         used=$(getquota -u $TSTUSR global bhardlimit $qpool)
793
794         test_1_check_write $testfile "user" $global_limit
795
796         used=$(getquota -u $TSTUSR global curspace $qpool1)
797         echo "qpool1 used $used"
798         used=$(getquota -u $TSTUSR global curspace $qpool2)
799         echo "qpool2 used $used"
800
801         rm -f $testfile
802         wait_delete_completed || error "wait_delete_completed failed"
803         sync_all_data || true
804
805         used=$(getquota -u $TSTUSR global curspace $qpool1)
806         [ $used -ne 0 ] && quota_error u $TSTUSR \
807                 "user quota isn't released after deletion"
808         resetquota -u $TSTUSR
809
810         # cleanup
811         cleanup_quota_test
812 }
813 run_test 1c "Quota pools: check 3 pools with hardlimit only for global"
814
815 test_1d() {
816         local limit1=10  # 10M
817         local limit2=12  # 12M
818         local global_limit=20  # 100M
819         local testfile="$DIR/$tdir/$tfile-0"
820         local qpool1="qpool1"
821         local qpool2="qpool2"
822
823         mds_supports_qp
824         setup_quota_test || error "setup quota failed with $?"
825         stack_trap cleanup_quota_test EXIT
826
827         # enable ost quota
828         set_ost_qtype $QTYPE || error "enable ost quota failed"
829
830         # test for user
831         log "User quota (block hardlimit:$global_limit MB)"
832         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
833                 error "set user quota failed"
834
835         pool_add $qpool1 || error "pool_add failed"
836         pool_add_targets $qpool1 0 $(($OSTCOUNT - 1)) ||
837                 error "pool_add_targets failed"
838
839         pool_add $qpool2 || error "pool_add failed"
840         pool_add_targets $qpool2 0 $(($OSTCOUNT - 1)) ||
841                 error "pool_add_targets failed"
842
843         $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR ||
844                 error "set user quota failed"
845
846         $LFS setquota -u $TSTUSR -B ${limit2}M -o $qpool2 $DIR ||
847         error "set user quota failed"
848
849         # make sure the system is clean
850         local used=$(getquota -u $TSTUSR global curspace)
851         echo "used $used"
852         [ $used -ne 0 ] && error "used space($used) for user $TSTUSR isn't 0."
853
854         used=$(getquota -u $TSTUSR global bhardlimit $qpool)
855
856         test_1_check_write $testfile "user" $limit1
857
858         used=$(getquota -u $TSTUSR global curspace $qpool1)
859         echo "qpool1 used $used"
860         used=$(getquota -u $TSTUSR global curspace $qpool2)
861         echo "qpool2 used $used"
862
863         rm -f $testfile
864         wait_delete_completed || error "wait_delete_completed failed"
865         sync_all_data || true
866
867         used=$(getquota -u $TSTUSR global curspace $qpool1)
868         [ $used -ne 0 ] && quota_error u $TSTUSR \
869                 "user quota isn't released after deletion"
870         resetquota -u $TSTUSR
871
872         # cleanup
873         cleanup_quota_test
874 }
875 run_test 1d "Quota pools: check block hardlimit on different pools"
876
877 test_1e() {
878         local limit1=10  # 10M
879         local global_limit=200  # 200M
880         local testfile="$DIR/$tdir/$tfile-0"
881         local testfile2="$DIR/$tdir/$tfile-1"
882         local qpool1="qpool1"
883
884         mds_supports_qp
885         setup_quota_test || error "setup quota failed with $?"
886         stack_trap cleanup_quota_test EXIT
887
888         # enable ost quota
889         set_ost_qtype $QTYPE || error "enable ost quota failed"
890
891         # global_limit is much greater than limit1 to get
892         # different qunit's on osts. Since 1st qunit shrinking
893         # on OST1(that belongs to qpool1), this qunit should
894         # be sent to OST1.
895         log "User quota (block hardlimit:$global_limit MB)"
896         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
897                 error "set user quota failed"
898
899         pool_add $qpool1 || error "pool_add failed"
900         pool_add_targets $qpool1 1 1 ||
901                 error "pool_add_targets failed"
902
903         $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR ||
904                 error "set user quota failed"
905
906         # make sure the system is clean
907         local used=$(getquota -u $TSTUSR global curspace)
908         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
909
910         $LFS setstripe $testfile -c 1 -i 1 || error "setstripe $testfile failed"
911         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
912
913         test_1_check_write $testfile "user" $limit1
914
915         $LFS setstripe $testfile2 -c 1 -i 0 ||
916                 error "setstripe $testfile2 failed"
917         chown $TSTUSR.$TSTUSR $testfile2 || error "chown $testfile2 failed"
918         # Now write to file with a stripe on OST0, that doesn't belong to qpool1
919         log "Write..."
920         $RUNAS $DD of=$testfile2 count=20 ||
921                 quota_error $short_qtype $TSTUSR \
922                         "$qtype write failure, but expect success"
923
924         rm -f $testfile
925         rm -f $testfile2
926         wait_delete_completed || error "wait_delete_completed failed"
927         sync_all_data || true
928
929         used=$(getquota -u $TSTUSR global curspace $qpool1)
930         [ $used -ne 0 ] && quota_error u $TSTUSR \
931                 "user quota isn't released after deletion"
932         resetquota -u $TSTUSR
933
934         # cleanup
935         cleanup_quota_test
936 }
937 run_test 1e "Quota pools: global pool high block limit vs quota pool with small"
938
939 test_1f() {
940         local global_limit=200  # 200M
941         local limit1=10  # 10M
942         local TESTDIR="$DIR/$tdir/"
943         local testfile="$TESTDIR/$tfile-0"
944         local qpool1="qpool1"
945
946         mds_supports_qp
947         setup_quota_test || error "setup quota failed with $?"
948         stack_trap cleanup_quota_test EXIT
949
950         # enable ost quota
951         set_ost_qtype $QTYPE || error "enable ost quota failed"
952
953         log "User quota (block hardlimit:$global_limit MB)"
954         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
955                 error "set user quota failed"
956
957         pool_add $qpool1 || error "pool_add failed"
958         pool_add_targets $qpool1 0 0 ||
959                 error "pool_add_targets failed"
960
961         $LFS setquota -u $TSTUSR -B ${limit1}M -o $qpool1 $DIR ||
962                 error "set user quota failed"
963
964         # make sure the system is clean
965         local used=$(getquota -u $TSTUSR global curspace)
966         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
967
968         $LFS setstripe $TESTDIR -c 1 -i 0 || error "setstripe $TESTDIR failed"
969
970         test_1_check_write $testfile "user" $limit1
971
972         pool_remove_target $qpool1 0
973         rm -f $testfile
974         wait_delete_completed || error "wait_delete_completed failed"
975         sync_all_data || true
976
977         pool_add_targets $qpool1 0 0 || error "pool_add_targets failed"
978         # qunit for appropriate element in lgd array should be set
979         # correctly(4096). Earlier it was not changed continuing to be 1024.
980         # This caused write to hung when it hit limit1 - qunit shrinking to 1024
981         # for qpool1 lqe didn't cause changing qunit for OST0 in gld array
982         # as it already was 1024. As flag "need_update" for this qunit was
983         # not set, new qunit wasn't sent to OST0. Thus revoke was not set
984         # for "qpool1" lqe and it couldn't set EDQUOT despite granted
985         # became > 10M. QMT returned EINPROGRESS in a loop.
986         # Check that it doesn't hung anymore.
987         test_1_check_write $testfile "user" $limit1
988
989         # cleanup
990         cleanup_quota_test
991 }
992 run_test 1f "Quota pools: correct qunit after removing/adding OST"
993
994 # test inode hardlimit
995 test_2() {
996         local LIMIT=$((1024 * 1024)) # 1M inodes
997         local TESTFILE="$DIR/$tdir/$tfile-0"
998
999         [ "$SLOW" = "no" ] && LIMIT=1024 # 1k inodes
1000
1001         local FREE_INODES=$(mdt_free_inodes 0)
1002         echo "$FREE_INODES free inodes on master MDT"
1003         [ $FREE_INODES -lt $LIMIT ] &&
1004                 skip "not enough free inodes $FREE_INODES required $LIMIT"
1005
1006         setup_quota_test || error "setup quota failed with $?"
1007         trap cleanup_quota_test EXIT
1008
1009         # enable mdt quota
1010         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1011
1012         # test for user
1013         log "User quota (inode hardlimit:$LIMIT files)"
1014         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
1015                 error "set user quota failed"
1016
1017         # make sure the system is clean
1018         local USED=$(getquota -u $TSTUSR global curinodes)
1019         [ $USED -ne 0 ] && error "Used inodes($USED) for user $TSTUSR isn't 0."
1020
1021         log "Create $LIMIT files ..."
1022         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
1023                 quota_error u $TSTUSR "user create failure, but expect success"
1024         log "Create out of file quota ..."
1025         $RUNAS touch ${TESTFILE}_xxx &&
1026                 quota_error u $TSTUSR "user create success, but expect EDQUOT"
1027
1028         # cleanup
1029         unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed"
1030         rm -f ${TESTFILE}_xxx
1031         wait_delete_completed
1032
1033         USED=$(getquota -u $TSTUSR global curinodes)
1034         [ $USED -ne 0 ] && quota_error u $TSTUSR \
1035                 "user quota isn't released after deletion"
1036         resetquota -u $TSTUSR
1037
1038         # test for group
1039         log "--------------------------------------"
1040         log "Group quota (inode hardlimit:$LIMIT files)"
1041         $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
1042                 error "set group quota failed"
1043
1044         TESTFILE=$DIR/$tdir/$tfile-1
1045         # make sure the system is clean
1046         USED=$(getquota -g $TSTUSR global curinodes)
1047         [ $USED -ne 0 ] && error "Used inodes($USED) for group $TSTUSR isn't 0."
1048
1049         log "Create $LIMIT files ..."
1050         $RUNAS createmany -m ${TESTFILE} $LIMIT ||
1051                 quota_error g $TSTUSR "group create failure, but expect success"
1052         log "Create out of file quota ..."
1053         $RUNAS touch ${TESTFILE}_xxx &&
1054                 quota_error g $TSTUSR "group create success, but expect EDQUOT"
1055
1056         # cleanup
1057         unlinkmany ${TESTFILE} $LIMIT || error "unlinkmany $TESTFILE failed"
1058         rm -f ${TESTFILE}_xxx
1059         wait_delete_completed
1060
1061         USED=$(getquota -g $TSTUSR global curinodes)
1062         [ $USED -ne 0 ] && quota_error g $TSTUSR \
1063                 "user quota isn't released after deletion"
1064
1065         resetquota -g $TSTUSR
1066         ! is_project_quota_supported && cleanup_quota_test &&
1067                 echo "Skip project quota is not supported" && return 0
1068
1069         # test for project
1070         log "--------------------------------------"
1071         log "Project quota (inode hardlimit:$LIMIT files)"
1072         $LFS setquota -p $TSTPRJID -b 0 -B 0 -i 0 -I $LIMIT $DIR ||
1073                 error "set project quota failed"
1074
1075         TESTFILE=$DIR/$tdir/$tfile-1
1076         # make sure the system is clean
1077         USED=$(getquota -p $TSTPRJID global curinodes)
1078         [ $USED -ne 0 ] &&
1079                 error "Used inodes($USED) for project $TSTPRJID isn't 0"
1080
1081         change_project -sp $TSTPRJID $DIR/$tdir
1082         log "Create $LIMIT files ..."
1083         $RUNAS createmany -m ${TESTFILE} $((LIMIT-1)) || quota_error p \
1084                 $TSTPRJID "project create fail, but expect success"
1085         log "Create out of file quota ..."
1086         $RUNAS touch ${TESTFILE}_xxx && quota_error p $TSTPRJID \
1087                 "project create success, but expect EDQUOT"
1088         change_project -C $DIR/$tdir
1089
1090         cleanup_quota_test
1091         USED=$(getquota -p $TSTPRJID global curinodes)
1092         [ $USED -eq 0 ] || quota_error p $TSTPRJID \
1093                 "project quota isn't released after deletion"
1094
1095 }
1096 run_test 2 "File hard limit (normal use and out of quota)"
1097
1098 test_block_soft() {
1099         local testfile=$1
1100         local grace=$2
1101         local limit=$3
1102         local OFFSET=0
1103         local qtype=$4
1104         local pool=$5
1105
1106         setup_quota_test
1107         stack_trap cleanup_quota_test EXIT
1108
1109         $LFS setstripe $testfile -c 1 -i 0
1110         chown $TSTUSR.$TSTUSR $testfile
1111         [ "$qtype" == "p" ] && is_project_quota_supported &&
1112                 change_project -p $TSTPRJID $testfile
1113
1114         echo "Write up to soft limit"
1115         $RUNAS $DD of=$testfile count=$limit ||
1116                 quota_error a $TSTUSR "write failure, but expect success"
1117         OFFSET=$((limit * 1024))
1118         cancel_lru_locks osc
1119
1120         echo "Write to exceed soft limit"
1121         $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET ||
1122                 quota_error a $TSTUSR "write failure, but expect success"
1123         OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block
1124         cancel_lru_locks osc
1125
1126         echo "mmap write when over soft limit"
1127         $RUNAS $MULTIOP $testfile.mmap OT40960SMW ||
1128                 quota_error a $TSTUSR "mmap write failure, but expect success"
1129         cancel_lru_locks osc
1130
1131         $SHOW_QUOTA_USER
1132         $SHOW_QUOTA_GROUP
1133         $SHOW_QUOTA_PROJID
1134         $SHOW_QUOTA_INFO_USER
1135         $SHOW_QUOTA_INFO_GROUP
1136         $SHOW_QUOTA_INFO_PROJID
1137
1138         echo "Write before timer goes off"
1139         $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET ||
1140                 quota_error a $TSTUSR "write failure, but expect success"
1141         OFFSET=$((OFFSET + 1024))
1142         cancel_lru_locks osc
1143
1144         wait_grace_time $qtype "block" $pool
1145
1146         $SHOW_QUOTA_USER
1147         $SHOW_QUOTA_GROUP
1148         $SHOW_QUOTA_PROJID
1149         $SHOW_QUOTA_INFO_USER
1150         $SHOW_QUOTA_INFO_GROUP
1151         $SHOW_QUOTA_INFO_PROJID
1152
1153         log "Write after timer goes off"
1154         # maybe cache write, ignore.
1155         $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET || true
1156         OFFSET=$((OFFSET + 1024))
1157         cancel_lru_locks osc
1158         log "Write after cancel lru locks"
1159         $RUNAS dd if=/dev/zero of=$testfile bs=1K count=10 seek=$OFFSET &&
1160                 quota_error a $TSTUSR "write success, but expect EDQUOT"
1161
1162         $SHOW_QUOTA_USER
1163         $SHOW_QUOTA_GROUP
1164         $SHOW_QUOTA_PROJID
1165         $SHOW_QUOTA_INFO_USER
1166         $SHOW_QUOTA_INFO_GROUP
1167         $SHOW_QUOTA_INFO_PROJID
1168
1169         echo "Unlink file to stop timer"
1170         rm -f $testfile
1171         wait_delete_completed
1172         sync_all_data || true
1173
1174         $SHOW_QUOTA_USER
1175         $SHOW_QUOTA_GROUP
1176         $SHOW_QUOTA_PROJID
1177         $SHOW_QUOTA_INFO_USER
1178         $SHOW_QUOTA_INFO_GROUP
1179         $SHOW_QUOTA_INFO_PROJID
1180
1181         $LFS setstripe $testfile -c 1 -i 0
1182         chown $TSTUSR.$TSTUSR $testfile
1183         [ "$qtype" == "p" ] && change_project -p $TSTPRJID $testfile
1184
1185         echo "Write ..."
1186         $RUNAS $DD of=$testfile count=$limit ||
1187                 quota_error a $TSTUSR "write failure, but expect success"
1188         # cleanup
1189         cleanup_quota_test
1190 }
1191
1192 # block soft limit
1193 test_3a() {
1194         local grace=20 # 20s
1195         if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then
1196             grace=60
1197         fi
1198         local testfile=$DIR/$tdir/$tfile-0
1199
1200         # get minimum soft qunit size
1201         local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \
1202                 qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 ))
1203
1204         set_ost_qtype $QTYPE || error "enable ost quota failed"
1205
1206         echo "User quota (soft limit:$limit MB  grace:$grace seconds)"
1207         # make sure the system is clean
1208         local used=$(getquota -u $TSTUSR global curspace)
1209         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
1210
1211         $LFS setquota -t -u --block-grace $grace --inode-grace \
1212                 $MAX_IQ_TIME $DIR || error "set user grace time failed"
1213         $LFS setquota -u $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR ||
1214                 error "set user quota failed"
1215
1216         test_block_soft $testfile $grace $limit "u"
1217
1218         echo "Group quota (soft limit:$limit MB  grace:$grace seconds)"
1219         testfile=$DIR/$tdir/$tfile-1
1220         # make sure the system is clean
1221         used=$(getquota -g $TSTUSR global curspace)
1222         [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0."
1223
1224         $LFS setquota -t -g --block-grace $grace --inode-grace \
1225                 $MAX_IQ_TIME $DIR || error "set group grace time failed"
1226         $LFS setquota -g $TSTUSR -b ${limit}M -B 0 -i 0 -I 0 $DIR ||
1227                 error "set group quota failed"
1228
1229         test_block_soft $testfile $grace $limit "g"
1230
1231         if is_project_quota_supported; then
1232                 echo "Project quota (soft limit:$limit MB  grace:$grace sec)"
1233                 testfile=$DIR/$tdir/$tfile-2
1234                 # make sure the system is clean
1235                 used=$(getquota -p $TSTPRJID global curspace)
1236                 [ $used -ne 0 ] && error \
1237                         "Used space($used) for project $TSTPRJID isn't 0."
1238
1239                 $LFS setquota -t -p --block-grace $grace --inode-grace \
1240                         $MAX_IQ_TIME $DIR ||
1241                                 error "set project grace time failed"
1242                 $LFS setquota -p $TSTPRJID -b ${limit}M -B 0 -i 0 -I 0 \
1243                         $DIR || error "set project quota failed"
1244
1245                 test_block_soft $testfile $grace $limit "p"
1246                 resetquota -p $TSTPRJID
1247                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1248                         $MAX_IQ_TIME $DIR ||
1249                                 error "restore project grace time failed"
1250         fi
1251
1252         # cleanup
1253         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1254                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1255         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1256                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1257 }
1258 run_test 3a "Block soft limit (start timer, timer goes off, stop timer)"
1259
1260 test_3b() {
1261         local grace=20 # 20s
1262         local qpool="qpool1"
1263         if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then
1264                 grace=60
1265         fi
1266         local testfile=$DIR/$tdir/$tfile-0
1267
1268         mds_supports_qp
1269         # get minimum soft qunit size
1270         local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \
1271                 qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 ))
1272         local glbl_limit=$((2*limit))
1273         local glbl_grace=$((2*grace))
1274         echo "limit $limit glbl_limit $glbl_limit"
1275         echo "grace $grace glbl_grace $glbl_grace"
1276
1277         set_ost_qtype $QTYPE || error "enable ost quota failed"
1278
1279         echo "User quota in $qpool(soft limit:$limit MB  grace:$grace seconds)"
1280         # make sure the system is clean
1281         local used=$(getquota -u $TSTUSR global curspace)
1282         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
1283
1284         pool_add $qpool || error "pool_add failed"
1285         pool_add_targets $qpool 0 1 ||
1286                 error "pool_add_targets failed"
1287
1288         $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \
1289                 $MAX_IQ_TIME $DIR || error "set user grace time failed"
1290         $LFS setquota -t -u --block-grace $grace \
1291                 -o $qpool $DIR || error "set user grace time failed"
1292
1293         $LFS setquota -u $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR ||
1294                 error "set user quota failed"
1295         $LFS setquota -u $TSTUSR -b ${limit}M -B 0 -o $qpool $DIR ||
1296                 error "set user quota failed"
1297
1298         test_block_soft $testfile $grace $limit "u" $qpool
1299
1300         echo "Group quota in $qpool(soft limit:$limit MB  grace:$grace seconds)"
1301         testfile=$DIR/$tdir/$tfile-1
1302         # make sure the system is clean
1303         used=$(getquota -g $TSTUSR global curspace)
1304         [ $used -ne 0 ] && error "Used space($used) for group $TSTUSR isn't 0."
1305
1306         $LFS setquota -t -g --block-grace $glbl_grace --inode-grace \
1307                 $MAX_IQ_TIME $DIR || error "set group grace time failed"
1308         $LFS setquota -t -g --block-grace $grace \
1309                 -o $qpool $DIR || error "set group grace time failed"
1310
1311         $LFS setquota -g $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR ||
1312                 error "set group quota failed"
1313         $LFS setquota -g $TSTUSR -b ${limit}M -B 0 -o $qpool $DIR ||
1314                 error "set group quota failed"
1315
1316         test_block_soft $testfile $grace $limit "g" $qpool
1317
1318         if is_project_quota_supported; then
1319                 echo "Project quota in $qpool(soft:$limit MB  grace:$grace sec)"
1320                 testfile=$DIR/$tdir/$tfile-2
1321                 # make sure the system is clean
1322                 used=$(getquota -p $TSTPRJID global curspace)
1323                 [ $used -ne 0 ] && error \
1324                         "Used space($used) for project $TSTPRJID isn't 0."
1325
1326                 $LFS setquota -t -p --block-grace $glbl_grace --inode-grace \
1327                         $MAX_IQ_TIME $DIR ||
1328                                 error "set project grace time failed"
1329                 $LFS setquota -t -p --block-grace $grace \
1330                         -o $qpool $DIR || error "set project grace time failed"
1331
1332                 $LFS setquota -p $TSTPRJID -b ${glbl_limit}M -B 0 -i 0 -I 0 \
1333                         $DIR || error "set project quota failed"
1334                 $LFS setquota -p $TSTPRJID -b ${limit}M -B 0 -o $qpool $DIR ||
1335                         error "set project quota failed"
1336
1337                 test_block_soft $testfile $grace $limit "p" $qpool
1338                 resetquota -p $TSTPRJID
1339                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1340                         $MAX_IQ_TIME $DIR ||
1341                                 error "restore project grace time failed"
1342                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME -o $qpool $DIR ||
1343                         error "set project grace time failed"
1344         fi
1345
1346         # cleanup
1347         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1348                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1349         $LFS setquota -t -u --block-grace $MAX_DQ_TIME \
1350                 -o $qpool $DIR || error "restore user grace time failed"
1351         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1352                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1353         $LFS setquota -t -g --block-grace $MAX_DQ_TIME \
1354                 -o $qpool $DIR || error "restore group grace time failed"
1355 }
1356 run_test 3b "Quota pools: Block soft limit (start timer, expires, stop timer)"
1357
1358 test_3c() {
1359         local grace=20 # 20s
1360         local qpool="qpool1"
1361         local qpool2="qpool2"
1362         if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then
1363                 grace=60
1364         fi
1365         local testfile=$DIR/$tdir/$tfile-0
1366
1367         mds_supports_qp
1368         # get minimum soft qunit size
1369         local limit=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \
1370                 qmt.$FSNAME-QMT0000.dt-0x0.soft_least_qunit) / 1024 ))
1371         local limit2=$((limit+4))
1372         local glbl_limit=$((limit+8))
1373         local grace1=$((grace+10))
1374         local grace2=$grace
1375         local glbl_grace=$((grace+20))
1376         echo "limit $limit limit2 $limit2 glbl_limit $glbl_limit"
1377         echo "grace1 $grace1 grace2 $grace2 glbl_grace $glbl_grace"
1378
1379         set_ost_qtype $QTYPE || error "enable ost quota failed"
1380
1381         echo "User quota in qpool2(soft:$limit2 MB grace:$grace2 seconds)"
1382         # make sure the system is clean
1383         local used=$(getquota -u $TSTUSR global curspace)
1384         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
1385
1386         pool_add $qpool || error "pool_add failed"
1387         pool_add_targets $qpool 0 1 ||
1388                 error "pool_add_targets failed"
1389
1390         pool_add $qpool2 || error "pool_add failed"
1391         pool_add_targets $qpool2 0 1 ||
1392                 error "pool_add_targets failed"
1393
1394
1395         $LFS setquota -t -u --block-grace $glbl_grace --inode-grace \
1396                 $MAX_IQ_TIME $DIR || error "set user grace time failed"
1397         $LFS setquota -t -u --block-grace $grace1 \
1398                 -o $qpool $DIR || error "set user grace time failed"
1399         $LFS setquota -t -u --block-grace $grace2 \
1400                 -o $qpool2 $DIR || error "set user grace time failed"
1401
1402         $LFS setquota -u $TSTUSR -b ${glbl_limit}M -B 0 -i 0 -I 0 $DIR ||
1403                 error "set user quota failed"
1404         $LFS setquota -u $TSTUSR -b ${limit}M -B 0 -o $qpool $DIR ||
1405                 error "set user quota failed"
1406         # qpool has minimum soft limit, but it's grace is grater than
1407         # grace period of qpool2. Thus write shouldn't fail when
1408         # hit qpool soft limit - only when reaches up qpool2 limit
1409         # after grace2 seconds.
1410         $LFS setquota -u $TSTUSR -b ${limit2}M -B 0 -o $qpool2 $DIR ||
1411                 error "set user quota failed"
1412
1413         test_block_soft $testfile $grace2 $limit2 "u" $qpool2
1414
1415         # cleanup
1416         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1417                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1418         $LFS setquota -t -u --block-grace $MAX_DQ_TIME \
1419                 -o $qpool $DIR || error "restore user grace time failed"
1420         $LFS setquota -t -u --block-grace $MAX_DQ_TIME \
1421                 -o $qpool2 $DIR || error "restore user grace time failed"
1422 }
1423 run_test 3c "Quota pools: check block soft limit on different pools"
1424
1425 test_file_soft() {
1426         local TESTFILE=$1
1427         local LIMIT=$2
1428         local grace=$3
1429         local qtype=$4
1430
1431         setup_quota_test
1432         trap cleanup_quota_test EXIT
1433         is_project_quota_supported && change_project -sp $TSTPRJID $DIR/$tdir
1434
1435         echo "Create files to exceed soft limit"
1436         $RUNAS createmany -m ${TESTFILE}_ $((LIMIT + 1)) ||
1437                 quota_error a $TSTUSR "create failure, but expect success"
1438         local trigger_time=$(date +%s)
1439
1440         sync_all_data || true
1441
1442         local cur_time=$(date +%s)
1443         [ $(($cur_time - $trigger_time)) -ge $grace ] &&
1444                 error "Passed grace time $grace, $trigger_time, $cur_time"
1445
1446         echo "Create file before timer goes off"
1447         $RUNAS touch ${TESTFILE}_before ||
1448                 quota_error a $TSTUSR "failed create before timer expired," \
1449                         "but expect success. $trigger_time, $cur_time"
1450         sync_all_data || true
1451
1452         wait_grace_time $qtype "file"
1453
1454         $SHOW_QUOTA_USER
1455         $SHOW_QUOTA_GROUP
1456         $SHOW_QUOTA_PROJID
1457         $SHOW_QUOTA_INFO_USER
1458         $SHOW_QUOTA_INFO_GROUP
1459         $SHOW_QUOTA_INFO_PROJID
1460
1461         echo "Create file after timer goes off"
1462         # There is a window that space is accounted in the quota usage but
1463         # hasn't been decreased from the pending write, if we acquire quota
1464         # in this window, we'll acquire more than we needed.
1465         $RUNAS touch ${TESTFILE}_after_1 ${TESTFILE}_after_2 || true
1466         sync_all_data || true
1467         $RUNAS touch ${TESTFILE}_after_3 &&
1468                 quota_error a $TSTUSR "create after timer expired," \
1469                         "but expect EDQUOT"
1470         sync_all_data || true
1471
1472         $SHOW_QUOTA_USER
1473         $SHOW_QUOTA_GROUP
1474         $SHOW_QUOTA_PROJID
1475         $SHOW_QUOTA_INFO_USER
1476         $SHOW_QUOTA_INFO_GROUP
1477         $SHOW_QUOTA_INFO_PROJID
1478
1479         echo "Unlink files to stop timer"
1480         find $(dirname $TESTFILE) -name "$(basename ${TESTFILE})*" | xargs rm -f
1481         wait_delete_completed
1482
1483         echo "Create file"
1484         $RUNAS touch ${TESTFILE}_xxx ||
1485                 quota_error a $TSTUSR "touch after timer stop failure," \
1486                         "but expect success"
1487         sync_all_data || true
1488
1489         # cleanup
1490         cleanup_quota_test
1491 }
1492
1493 # file soft limit
1494 test_4a() {
1495         local LIMIT=$(do_facet $SINGLEMDS $LCTL get_param -n \
1496                 qmt.$FSNAME-QMT0000.md-0x0.soft_least_qunit)
1497         local TESTFILE=$DIR/$tdir/$tfile-0
1498         local GRACE=12
1499
1500         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1501
1502         echo "User quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
1503         # make sure the system is clean
1504         local USED=$(getquota -u $TSTUSR global curinodes)
1505         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1506
1507         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1508                 $GRACE $DIR || error "set user grace time failed"
1509         $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
1510                 error "set user quota failed"
1511
1512         [ "$mds1_FSTYPE" = zfs ] && GRACE=20
1513
1514         test_file_soft $TESTFILE $LIMIT $GRACE "u"
1515
1516         echo "Group quota (soft limit:$LIMIT files  grace:$GRACE seconds)"
1517         # make sure the system is clean
1518         USED=$(getquota -g $TSTUSR global curinodes)
1519         [ $USED -ne 0 ] && error "Used space($USED) for group $TSTUSR isn't 0."
1520
1521         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1522                 $GRACE $DIR || error "set group grace time failed"
1523         $LFS setquota -g $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
1524                 error "set group quota failed"
1525         TESTFILE=$DIR/$tdir/$tfile-1
1526
1527         test_file_soft $TESTFILE $LIMIT $GRACE "g"
1528
1529         if is_project_quota_supported; then
1530                 echo "Project quota (soft limit:$LIMIT files grace:$GRACE sec)"
1531                 # make sure the system is clean
1532                 USED=$(getquota -p $TSTPRJID global curinodes)
1533                 [ $USED -ne 0 ] && error \
1534                         "Used space($USED) for project $TSTPRJID isn't 0."
1535
1536                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1537                         $GRACE $DIR || error "set project grace time failed"
1538                 $LFS setquota -p $TSTPRJID -b 0 -B 0 -i $LIMIT -I 0 $DIR ||
1539                         error "set project quota failed"
1540
1541                 TESTFILE=$DIR/$tdir/$tfile-1
1542                 # one less than limit, because of parent directory included.
1543                 test_file_soft $TESTFILE $((LIMIT-1)) $GRACE "p"
1544                 resetquota -p $TSTPRJID
1545                 $LFS setquota -t -p --block-grace $MAX_DQ_TIME --inode-grace \
1546                         $MAX_IQ_TIME $DIR ||
1547                                 error "restore project grace time failed"
1548         fi
1549
1550         # cleanup
1551         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1552                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1553         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1554                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1555 }
1556 run_test 4a "File soft limit (start timer, timer goes off, stop timer)"
1557
1558 test_4b() {
1559         local GR_STR1="1w3d"
1560         local GR_STR2="1000s"
1561         local GR_STR3="5s"
1562         local GR_STR4="1w2d3h4m5s"
1563         local GR_STR5="5c"
1564         local GR_STR6="18446744073709551615"
1565         local GR_STR7="-1"
1566
1567         wait_delete_completed
1568
1569         # test of valid grace strings handling
1570         echo "Valid grace strings test"
1571         $LFS setquota -t -u --block-grace $GR_STR1 --inode-grace \
1572                 $GR_STR2 $DIR || error "set user grace time failed"
1573         $LFS quota -u -t $DIR | grep "Block grace time: $GR_STR1"
1574         $LFS setquota -t -g --block-grace $GR_STR3 --inode-grace \
1575                 $GR_STR4 $DIR || error "set group grace time quota failed"
1576         $LFS quota -g -t $DIR | grep "Inode grace time: $GR_STR4"
1577
1578         # test of invalid grace strings handling
1579         echo "  Invalid grace strings test"
1580         ! $LFS setquota -t -u --block-grace $GR_STR4 --inode-grace $GR_STR5 $DIR
1581         ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace $GR_STR6 $DIR
1582         ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace \
1583                 $GR_STR7 $DIR
1584
1585         # cleanup
1586         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
1587                 $MAX_IQ_TIME $DIR || error "restore user grace time failed"
1588         $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace \
1589                 $MAX_IQ_TIME $DIR || error "restore group grace time failed"
1590 }
1591 run_test 4b "Grace time strings handling"
1592
1593 # chown & chgrp (chown & chgrp successfully even out of block/file quota)
1594 test_5() {
1595         local BLIMIT=10 # 10M
1596         local ILIMIT=10 # 10 inodes
1597
1598         setup_quota_test || error "setup quota failed with $?"
1599         trap cleanup_quota_test EXIT
1600
1601         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
1602         set_ost_qtype $QTYPE || error "enable ost quota failed"
1603
1604         echo "Set quota limit (0 ${BLIMIT}M 0 $ILIMIT) for $TSTUSR.$TSTUSR"
1605         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
1606                 error "set user quota failed"
1607         $LFS setquota -g $TSTUSR -b 0 -B ${BLIMIT}M -i 0 -I $ILIMIT $DIR ||
1608         if is_project_quota_supported; then
1609                 error "set group quota failed"
1610                 $LFS setquota -p $TSTPRJID -b 0 -B ${BLIMIT}M -i 0 \
1611                         -I $ILIMIT $DIR || error "set project quota failed"
1612         fi
1613
1614         # make sure the system is clean
1615         local USED=$(getquota -u $TSTUSR global curinodes)
1616         [ $USED -ne 0 ] && error "Used inode($USED) for user $TSTUSR isn't 0."
1617         USED=$(getquota -g $TSTUSR global curinodes)
1618         [ $USED -ne 0 ] && error "Used inode($USED) for group $TSTUSR isn't 0."
1619         USED=$(getquota -u $TSTUSR global curspace)
1620         [ $USED -ne 0 ] && error "Used block($USED) for user $TSTUSR isn't 0."
1621         USED=$(getquota -g $TSTUSR global curspace)
1622         [ $USED -ne 0 ] && error "Used block($USED) for group $TSTUSR isn't 0."
1623         if is_project_quota_supported; then
1624                 USED=$(getquota -p $TSTPRJID global curinodes)
1625                 [ $USED -ne 0 ] &&
1626                         error "Used inode($USED) for project $TSTPRJID isn't 0."
1627                 USED=$(getquota -p $TSTPRJID global curspace)
1628                 [ $USED -ne 0 ] &&
1629                         error "Used block($USED) for project $TSTPRJID isn't 0."
1630         fi
1631
1632         echo "Create more than $ILIMIT files and more than $BLIMIT MB ..."
1633         createmany -m $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) ||
1634                 error "create failure, expect success"
1635         if is_project_quota_supported; then
1636                 touch $DIR/$tdir/$tfile-0_1
1637                 change_project -p $TSTPRJID $DIR/$tdir/$tfile-0_1
1638         fi
1639         $DD of=$DIR/$tdir/$tfile-0_1 count=$((BLIMIT+1)) ||
1640                 error "write failure, expect success"
1641
1642         echo "Chown files to $TSTUSR.$TSTUSR ..."
1643         for i in $(seq 0 $ILIMIT); do
1644                 chown $TSTUSR.$TSTUSR $DIR/$tdir/$tfile-0_$i ||
1645                         quota_error a $TSTUSR "chown failure, expect success"
1646         done
1647
1648         # cleanup
1649         unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) ||
1650                 error "unlinkmany $DIR/$tdir/$tfile-0_ failed"
1651         cleanup_quota_test
1652 }
1653 run_test 5 "Chown & chgrp successfully even out of block/file quota"
1654
1655 # test dropping acquire request on master
1656 test_6() {
1657         local LIMIT=3 # 3M
1658
1659         # Clear dmesg so watchdog is not triggered by previous
1660         # test output
1661         do_facet ost1 dmesg -c > /dev/null
1662
1663         setup_quota_test || error "setup quota failed with $?"
1664         trap cleanup_quota_test EXIT
1665
1666         # make sure the system is clean
1667         local USED=$(getquota -u $TSTUSR global curspace)
1668         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1669
1670         # make sure no granted quota on ost
1671         set_ost_qtype $QTYPE || error "enable ost quota failed"
1672         resetquota -u $TSTUSR
1673
1674         # create file for $TSTUSR
1675         local TESTFILE=$DIR/$tdir/$tfile-$TSTUSR
1676         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1677         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1678
1679         # create file for $TSTUSR2
1680         local TESTFILE2=$DIR/$tdir/$tfile-$TSTUSR2
1681         $LFS setstripe $TESTFILE2 -c 1 -i 0 || error "setstripe $TESTFILE2 failed"
1682         chown $TSTUSR2.$TSTUSR2 $TESTFILE2 || error "chown $TESTFILE2 failed"
1683
1684         # cache per-ID lock for $TSTUSR on slave
1685         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1686                 error "set quota failed"
1687         $RUNAS $DD of=$TESTFILE count=1 ||
1688                 error "write $TESTFILE failure, expect success"
1689         $RUNAS2 $DD of=$TESTFILE2 count=1 ||
1690                 error "write $TESTFILE2 failure, expect success"
1691
1692         if at_is_enabled; then
1693                 at_max_saved=$(at_max_get ost1)
1694                 at_max_set $TIMEOUT ost1
1695
1696                 # write to enforced ID ($TSTUSR) to exceed limit to make sure
1697                 # DQACQ is sent, which makes at_max to take effect
1698                 $RUNAS $DD of=$TESTFILE count=$LIMIT seek=1 oflag=sync \
1699                                                                 conv=notrunc
1700                 rm -f $TESTFILE
1701                 wait_delete_completed
1702         fi
1703
1704         sync; sync
1705         sync_all_data || true
1706
1707         #define QUOTA_DQACQ 601
1708         #define OBD_FAIL_PTLRPC_DROP_REQ_OPC 0x513
1709         lustre_fail mds 0x513 601
1710
1711         do_facet ost1 $LCTL set_param \
1712                         osd-*.$FSNAME-OST*.quota_slave.timeout=$((TIMEOUT / 2))
1713
1714         # write to un-enforced ID ($TSTUSR2) should succeed
1715         $RUNAS2 $DD of=$TESTFILE2 count=$LIMIT seek=1 oflag=sync conv=notrunc ||
1716                 error "write failure, expect success"
1717
1718         # write to enforced ID ($TSTUSR) in background, exceeding limit
1719         # to make sure DQACQ is sent
1720         $RUNAS $DD of=$TESTFILE count=$LIMIT seek=1 oflag=sync conv=notrunc &
1721         DDPID=$!
1722
1723         # watchdog timer uses a factor of 2
1724         echo "Sleep for $((TIMEOUT * 2 + 1)) seconds ..."
1725         sleep $((TIMEOUT * 2 + 1))
1726
1727         [ $at_max_saved -ne 0 ] && at_max_set $at_max_saved ost1
1728
1729         # write should be blocked and never finished
1730         if ! ps -p $DDPID  > /dev/null 2>&1; then
1731                 lustre_fail mds 0 0
1732                 error "write finished incorrectly!"
1733         fi
1734
1735         lustre_fail mds 0 0
1736
1737         # no watchdog is triggered
1738         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
1739         watchdog=$(awk '/[Ss]ervice thread pid/ && /was inactive/ \
1740                         { print; }' $TMP/lustre-log-${TESTNAME}.log)
1741         [ -z "$watchdog" ] || error "$watchdog"
1742
1743         rm -f $TMP/lustre-log-${TESTNAME}.log
1744
1745         # write should continue then fail with EDQUOT
1746         local count=0
1747         local c_size
1748         while [ true ]; do
1749                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
1750                 if [ $count -ge 240 ]; then
1751                         quota_error u $TSTUSR "dd not finished in $count secs"
1752                 fi
1753                 count=$((count + 1))
1754                 if [ $((count % 30)) -eq 0 ]; then
1755                         c_size=$(stat -c %s $TESTFILE)
1756                         echo "Waiting $count secs. $c_size"
1757                         $SHOW_QUOTA_USER
1758                 fi
1759                 sleep 1
1760         done
1761
1762         cleanup_quota_test
1763 }
1764 run_test 6 "Test dropping acquire request on master"
1765
1766 # quota reintegration (global index)
1767 test_7a() {
1768         local TESTFILE=$DIR/$tdir/$tfile
1769         local LIMIT=20 # 20M
1770
1771         [ "$SLOW" = "no" ] && LIMIT=5
1772
1773         setup_quota_test || error "setup quota failed with $?"
1774         trap cleanup_quota_test EXIT
1775
1776         # make sure the system is clean
1777         local USED=$(getquota -u $TSTUSR global curspace)
1778         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1779
1780         # make sure no granted quota on ost1
1781         set_ost_qtype $QTYPE || error "enable ost quota failed"
1782         resetquota -u $TSTUSR
1783         set_ost_qtype "none" || error "disable ost quota failed"
1784
1785         local OSTUUID=$(ostuuid_from_index 0)
1786         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1787         [ $USED -ne 0 ] &&
1788                 error "limit($USED) on $OSTUUID for user $TSTUSR isn't 0"
1789
1790         # create test file
1791         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1792         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1793
1794         echo "Stop ost1..."
1795         stop ost1
1796
1797         echo "Enable quota & set quota limit for $TSTUSR"
1798         set_ost_qtype $QTYPE || error "enable ost quota failed"
1799         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1800                 error "set quota failed"
1801
1802         echo "Start ost1..."
1803         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1804         quota_init
1805
1806         wait_ost_reint $QTYPE || error "reintegration failed"
1807
1808         # hardlimit should have been fetched by slave during global
1809         # reintegration, write will exceed quota
1810         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
1811                 quota_error u $TSTUSR "write success, but expect EDQUOT"
1812
1813         rm -f $TESTFILE
1814         wait_delete_completed
1815         sync_all_data || true
1816         sleep 3
1817
1818         echo "Stop ost1..."
1819         stop ost1
1820
1821         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
1822                 error "clear quota failed"
1823
1824         echo "Start ost1..."
1825         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1826         quota_init
1827
1828         wait_ost_reint $QTYPE || error "reintegration failed"
1829
1830         # hardlimit should be cleared on slave during reintegration
1831         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync ||
1832                 quota_error u $TSTUSR "write error, but expect success"
1833
1834         cleanup_quota_test
1835 }
1836 run_test 7a "Quota reintegration (global index)"
1837
1838 # quota reintegration (slave index)
1839 test_7b() {
1840         local LIMIT="100G"
1841         local TESTFILE=$DIR/$tdir/$tfile
1842
1843         setup_quota_test || error "setup quota failed with $?"
1844         trap cleanup_quota_test EXIT
1845
1846         # make sure the system is clean
1847         local USED=$(getquota -u $TSTUSR global curspace)
1848         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1849
1850         # make sure no granted quota on ost1
1851         set_ost_qtype $QTYPE || error "enable ost quota failed"
1852         resetquota -u $TSTUSR
1853         set_ost_qtype "none" || error "disable ost quota failed"
1854
1855         local OSTUUID=$(ostuuid_from_index 0)
1856         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1857         [ $USED -ne 0 ] &&
1858                 error "limit($USED) on $OSTUUID for user $TSTUSR isn't 0"
1859
1860         # create test file
1861         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
1862         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
1863
1864         # consume some space to make sure the granted space will not
1865         # be released during reconciliation
1866         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
1867                 error "consume space failure, expect success"
1868
1869         # define OBD_FAIL_QUOTA_EDQUOT 0xa02
1870         lustre_fail mds 0xa02
1871
1872         set_ost_qtype $QTYPE || error "enable ost quota failed"
1873         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
1874                 error "set quota failed"
1875
1876         # ignore the write error
1877         $RUNAS $DD of=$TESTFILE count=1 seek=1 oflag=sync conv=notrunc
1878
1879         local old_used=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1880
1881         lustre_fail mds 0
1882
1883         echo "Restart ost to trigger reintegration..."
1884         stop ost1
1885         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "start ost1 failed"
1886         quota_init
1887
1888         wait_ost_reint $QTYPE || error "reintegration failed"
1889
1890         USED=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
1891         [ $USED -gt $old_used ] || error "limit on $OSTUUID $USED <= $old_used"
1892
1893         cleanup_quota_test
1894         $SHOW_QUOTA_USER
1895 }
1896 run_test 7b "Quota reintegration (slave index)"
1897
1898 # quota reintegration (restart mds during reintegration)
1899 test_7c() {
1900         local LIMIT=20 # 20M
1901         local TESTFILE=$DIR/$tdir/$tfile
1902
1903         [ "$SLOW" = "no" ] && LIMIT=5
1904
1905         setup_quota_test || error "setup quota failed with $?"
1906         trap cleanup_quota_test EXIT
1907
1908         # make sure the system is clean
1909         local USED=$(getquota -u $TSTUSR global curspace)
1910         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
1911
1912         set_ost_qtype "none" || error "disable ost quota failed"
1913         $LFS setquota -u $TSTUSR -b 0 -B ${LIMIT}M -i 0 -I 0 $DIR ||
1914                 error "set quota failed"
1915
1916         # define OBD_FAIL_QUOTA_DELAY_REINT 0xa03
1917         lustre_fail ost 0xa03
1918
1919         # enable ost quota
1920         set_ost_qtype $QTYPE || error "enable ost quota failed"
1921         # trigger reintegration
1922         local procf="osd-$ost1_FSTYPE.$FSNAME-OST*."
1923         procf=${procf}quota_slave.force_reint
1924         do_facet ost1 $LCTL set_param $procf=1 ||
1925                 error "force reintegration failed"
1926
1927         echo "Stop mds..."
1928         stop mds1
1929
1930         lustre_fail ost 0
1931
1932         echo "Start mds..."
1933         start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
1934         quota_init
1935
1936         # wait longer than usual to make sure the reintegration
1937         # is triggered by quota wb thread.
1938         wait_ost_reint $QTYPE 200 || error "reintegration failed"
1939
1940         # hardlimit should have been fetched by slave during global
1941         # reintegration, write will exceed quota
1942         $RUNAS $DD of=$TESTFILE count=$((LIMIT + 1)) oflag=sync &&
1943                 quota_error u $TSTUSR "write success, but expect EDQUOT"
1944
1945         cleanup_quota_test
1946 }
1947 run_test 7c "Quota reintegration (restart mds during reintegration)"
1948
1949 # Quota reintegration (Transfer index in multiple bulks)
1950 test_7d(){
1951         local TESTFILE=$DIR/$tdir/$tfile
1952         local TESTFILE1="$DIR/$tdir/$tfile"-1
1953         local limit=20 #20M
1954
1955         setup_quota_test || error "setup quota failed with $?"
1956         trap cleanup_quota_test EXIT
1957
1958         set_ost_qtype "none" || error "disable ost quota failed"
1959         $LFS setquota -u $TSTUSR -B ${limit}M $DIR ||
1960                 error "set quota for $TSTUSR failed"
1961         $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR ||
1962                 error "set quota for $TSTUSR2 failed"
1963
1964         #define OBD_FAIL_OBD_IDX_READ_BREAK 0x608
1965         lustre_fail mds 0x608 0
1966
1967         # enable quota to tirgger reintegration
1968         set_ost_qtype "u" || error "enable ost quota failed"
1969         wait_ost_reint "u" || error "reintegration failed"
1970
1971         lustre_fail mds 0
1972
1973         # hardlimit should have been fetched by slave during global
1974         # reintegration, write will exceed quota
1975         $RUNAS $DD of=$TESTFILE count=$((limit + 1)) oflag=sync &&
1976                 quota_error u $TSTUSR "$TSTUSR write success, expect EDQUOT"
1977
1978         $RUNAS2 $DD of=$TESTFILE1 count=$((limit + 1)) oflag=sync &&
1979                 quota_error u $TSTUSR2 "$TSTUSR2 write success, expect EDQUOT"
1980
1981         cleanup_quota_test
1982 }
1983 run_test 7d "Quota reintegration (Transfer index in multiple bulks)"
1984
1985 # quota reintegration (inode limits)
1986 test_7e() {
1987         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
1988
1989         # LU-2435: skip this quota test if underlying zfs version has not
1990         # supported native dnode accounting
1991         [ "$mds1_FSTYPE" == zfs ] && {
1992                 local F="feature@userobj_accounting"
1993                 local pool=$(zpool_name mds1)
1994                 local feature=$(do_facet mds1 $ZPOOL get -H $F $pool)
1995
1996                 [[ "$feature" != *" active "* ]] &&
1997                         skip "requires zpool with active userobj_accounting"
1998         }
1999
2000         local ilimit=$((1024 * 2)) # 2k inodes
2001         local TESTFILE=$DIR/${tdir}-1/$tfile
2002
2003         setup_quota_test || error "setup quota failed with $?"
2004         trap cleanup_quota_test EXIT
2005
2006         # make sure the system is clean
2007         local USED=$(getquota -u $TSTUSR global curinodes)
2008         [ $USED -ne 0 ] && error "Used inode($USED) for user $TSTUSR isn't 0."
2009
2010         # make sure no granted quota on mdt1
2011         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
2012         resetquota -u $TSTUSR
2013         set_mdt_qtype "none" || error "disable mdt quota failed"
2014
2015         local MDTUUID=$(mdtuuid_from_index $((MDSCOUNT - 1)))
2016         USED=$(getquota -u $TSTUSR $MDTUUID ihardlimit)
2017         [ $USED -ne 0 ] && error "limit($USED) on $MDTUUID for user" \
2018                 "$TSTUSR isn't 0."
2019
2020         echo "Stop mds${MDSCOUNT}..."
2021         stop mds${MDSCOUNT}
2022
2023         echo "Enable quota & set quota limit for $TSTUSR"
2024         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
2025         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $ilimit $DIR ||
2026                 error "set quota failed"
2027
2028         echo "Start mds${MDSCOUNT}..."
2029         start mds${MDSCOUNT} $(mdsdevname $MDSCOUNT) $MDS_MOUNT_OPTS
2030         quota_init
2031
2032         wait_mdt_reint $QTYPE || error "reintegration failed"
2033
2034         echo "create remote dir"
2035         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/${tdir}-1 ||
2036                 error "create remote dir failed"
2037         chmod 0777 $DIR/${tdir}-1
2038
2039         # hardlimit should have been fetched by slave during global
2040         # reintegration, create will exceed quota
2041         $RUNAS createmany -m $TESTFILE $((ilimit + 1)) &&
2042                 quota_error u $TSTUSR "create succeeded, expect EDQUOT"
2043
2044         $RUNAS unlinkmany $TESTFILE $ilimit || error "unlink files failed"
2045         wait_delete_completed
2046         sync_all_data || true
2047
2048         echo "Stop mds${MDSCOUNT}..."
2049         stop mds${MDSCOUNT}
2050
2051         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
2052                 error "clear quota failed"
2053
2054         echo "Start mds${MDSCOUNT}..."
2055         start mds${MDSCOUNT} $(mdsdevname $MDSCOUNT) $MDS_MOUNT_OPTS
2056         quota_init
2057
2058         wait_mdt_reint $QTYPE || error "reintegration failed"
2059
2060         # hardlimit should be cleared on slave during reintegration
2061         $RUNAS createmany -m $TESTFILE $((ilimit + 1)) ||
2062                 quota_error u $TSTUSR "create failed, expect success"
2063
2064         $RUNAS unlinkmany $TESTFILE $((ilimit + 1)) || error "unlink failed"
2065         rmdir $DIR/${tdir}-1 || error "unlink remote dir failed"
2066
2067         cleanup_quota_test
2068 }
2069 run_test 7e "Quota reintegration (inode limits)"
2070
2071 # run dbench with quota enabled
2072 test_8() {
2073         local BLK_LIMIT="100g" #100G
2074         local FILE_LIMIT=1000000
2075
2076         setup_quota_test || error "setup quota failed with $?"
2077         trap cleanup_quota_test EXIT
2078
2079         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
2080         set_ost_qtype $QTYPE || error "enable ost quota failed"
2081
2082         echo "Set enough high limit for user: $TSTUSR"
2083         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
2084                 error "set user quota failed"
2085         echo "Set enough high limit for group: $TSTUSR"
2086         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
2087                 error "set group quota failed"
2088         if is_project_quota_supported; then
2089                 change_project -sp $TSTPRJID $DIR/$tdir
2090                 echo "Set enough high limit for project: $TSTPRJID"
2091                 $LFS setquota -p $TSTPRJID -b 0 \
2092                         -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
2093                         error "set project quota failed"
2094         fi
2095
2096         local duration=""
2097         [ "$SLOW" = "no" ] && duration=" -t 120"
2098         $RUNAS bash rundbench -D $DIR/$tdir 3 $duration ||
2099                 quota_error a $TSTUSR "dbench failed!"
2100
2101         is_project_quota_supported && change_project -C $DIR/$tdir
2102         cleanup_quota_test
2103 }
2104 run_test 8 "Run dbench with quota enabled"
2105
2106 # this check is just for test_9
2107 OST0_MIN=4900000 #4.67G
2108
2109 check_whether_skip () {
2110         local OST0_SIZE=$($LFS df $DIR | awk '/\[OST:0\]/ {print $4}')
2111         log "OST0_SIZE: $OST0_SIZE  required: $OST0_MIN"
2112         if [ $OST0_SIZE -lt $OST0_MIN ]; then
2113                 echo "WARN: OST0 has less than $OST0_MIN free, skip this test."
2114                 return 0
2115         else
2116                 return 1
2117         fi
2118 }
2119
2120 # run for fixing bug10707, it needs a big room. test for 64bit
2121 test_9() {
2122         local filesize=$((1024 * 9 / 2)) # 4.5G
2123
2124         check_whether_skip && return 0
2125
2126         setup_quota_test || error "setup quota failed with $?"
2127         trap cleanup_quota_test EXIT
2128
2129         set_ost_qtype "ug" || error "enable ost quota failed"
2130
2131         local TESTFILE="$DIR/$tdir/$tfile-0"
2132         local BLK_LIMIT=100G #100G
2133         local FILE_LIMIT=1000000
2134
2135         echo "Set block limit $BLK_LIMIT bytes to $TSTUSR.$TSTUSR"
2136
2137         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
2138                 "for user: $TSTUSR"
2139         $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
2140                 error "set user quota failed"
2141
2142         log "Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT)" \
2143                 "for group: $TSTUSR"
2144         $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR ||
2145                 error "set group quota failed"
2146
2147         quota_show_check a u $TSTUSR
2148         quota_show_check a g $TSTUSR
2149
2150         echo "Create test file"
2151         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
2152         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2153
2154         log "Write the big file of 4.5G ..."
2155         $RUNAS $DD of=$TESTFILE count=$filesize ||
2156                 quota_error a $TSTUSR "write 4.5G file failure, expect success"
2157
2158         $SHOW_QUOTA_USER
2159         $SHOW_QUOTA_GROUP
2160
2161         cleanup_quota_test
2162
2163         $SHOW_QUOTA_USER
2164         $SHOW_QUOTA_GROUP
2165 }
2166 run_test 9 "Block limit larger than 4GB (b10707)"
2167
2168 test_10() {
2169         local TESTFILE=$DIR/$tdir/$tfile
2170
2171         setup_quota_test || error "setup quota failed with $?"
2172         trap cleanup_quota_test EXIT
2173
2174         # set limit to root user should fail
2175         $LFS setquota -u root -b 100G -B 500G -i 1K -I 1M $DIR &&
2176                 error "set limit for root user successfully, expect failure"
2177         $LFS setquota -g root -b 1T -B 10T -i 5K -I 100M $DIR &&
2178                 error "set limit for root group successfully, expect failure"
2179         $LFS setquota -p 0 -b 1T -B 10T -i 5K -I 100M $DIR &&
2180                 error "set limit for project 0 successfully, expect failure"
2181
2182         # root user can overrun quota
2183         set_ost_qtype "ug" || error "enable ost quota failed"
2184
2185         $LFS setquota -u $TSTUSR -b 0 -B 2M -i 0 -I 0 $DIR ||
2186                 error "set quota failed"
2187         quota_show_check b u $TSTUSR
2188
2189         $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
2190         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2191
2192         runas -u 0 -g 0 $DD of=$TESTFILE count=3 oflag=sync ||
2193                 error "write failure, expect success"
2194
2195         cleanup_quota_test
2196 }
2197 run_test 10 "Test quota for root user"
2198
2199 test_11() {
2200         local TESTFILE=$DIR/$tdir/$tfile
2201         setup_quota_test || error "setup quota failed with $?"
2202         trap cleanup_quota_test EXIT
2203
2204         set_mdt_qtype "ug" || error "enable mdt quota failed"
2205         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 1 $DIR ||
2206                 error "set quota failed"
2207
2208         touch "$TESTFILE"-0 || error "touch $TESTFILE-0 failed"
2209         touch "$TESTFILE"-1 || error "touch $TESTFILE-0 failed"
2210
2211         chown $TSTUSR.$TSTUSR "$TESTFILE"-0 || error "chown $TESTFILE-0 failed"
2212         chown $TSTUSR.$TSTUSR "$TESTFILE"-1 || error "chown $TESTFILE-1 failed"
2213
2214         $SHOW_QUOTA_USER
2215         local USED=$(getquota -u $TSTUSR global curinodes)
2216         [ $USED -ge 2 ] || error "Used inodes($USED) is less than 2"
2217
2218         cleanup_quota_test
2219 }
2220 run_test 11 "Chown/chgrp ignores quota"
2221
2222 test_12a() {
2223         [ "$OSTCOUNT" -lt "2" ] && skip "needs >= 2 OSTs"
2224
2225         local blimit=22 # 22M
2226         local blk_cnt=$((blimit - 5))
2227         local TESTFILE0="$DIR/$tdir/$tfile"-0
2228         local TESTFILE1="$DIR/$tdir/$tfile"-1
2229
2230         setup_quota_test || error "setup quota failed with $?"
2231         trap cleanup_quota_test EXIT
2232
2233         set_ost_qtype "u" || error "enable ost quota failed"
2234         quota_show_check b u $TSTUSR
2235
2236         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $DIR ||
2237                 error "set quota failed"
2238
2239         $LFS setstripe $TESTFILE0 -c 1 -i 0 || error "setstripe $TESTFILE0 failed"
2240         $LFS setstripe $TESTFILE1 -c 1 -i 1 || error "setstripe $TESTFILE1 failed"
2241         chown $TSTUSR.$TSTUSR $TESTFILE0 || error "chown $TESTFILE0 failed"
2242         chown $TSTUSR.$TSTUSR $TESTFILE1 || error "chown $TESTFILE1 failed"
2243
2244         echo "Write to ost0..."
2245         $RUNAS $DD of=$TESTFILE0 count=$blk_cnt oflag=sync ||
2246                 quota_error a $TSTUSR "dd failed"
2247
2248         echo "Write to ost1..."
2249         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync &&
2250                 quota_error a $TSTUSR "dd succeed, expect EDQUOT"
2251
2252         echo "Free space from ost0..."
2253         rm -f $TESTFILE0
2254         wait_delete_completed
2255         sync_all_data || true
2256
2257         echo "Write to ost1 after space freed from ost0..."
2258         $RUNAS $DD of=$TESTFILE1 count=$blk_cnt oflag=sync ||
2259                 quota_error a $TSTUSR "rebalancing failed"
2260
2261         cleanup_quota_test
2262 }
2263 run_test 12a "Block quota rebalancing"
2264
2265 test_12b() {
2266         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
2267
2268         local ilimit=$((1024 * 2)) # 2k inodes
2269         local TESTFILE0=$DIR/$tdir/$tfile
2270         local TESTFILE1=$DIR/${tdir}-1/$tfile
2271
2272         setup_quota_test || error "setup quota failed with $?"
2273         trap cleanup_quota_test EXIT
2274
2275         $LFS mkdir -i 1 $DIR/${tdir}-1 || error "create remote dir failed"
2276         chmod 0777 $DIR/${tdir}-1
2277
2278         set_mdt_qtype "u" || error "enable mdt quota failed"
2279         quota_show_check f u $TSTUSR
2280
2281         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $ilimit $DIR ||
2282                 error "set quota failed"
2283
2284         echo "Create $ilimit files on mdt0..."
2285         $RUNAS createmany -m $TESTFILE0 $ilimit ||
2286                 quota_error u $TSTUSR "create failed, but expect success"
2287
2288         echo "Create files on mdt1..."
2289         $RUNAS createmany -m $TESTFILE1 1 &&
2290                 quota_error a $TSTUSR "create succeeded, expect EDQUOT"
2291
2292         echo "Free space from mdt0..."
2293         $RUNAS unlinkmany $TESTFILE0 $ilimit || error "unlink mdt0 files failed"
2294         wait_delete_completed
2295         sync_all_data || true
2296
2297         echo "Create files on mdt1 after space freed from mdt0..."
2298         $RUNAS createmany -m $TESTFILE1 $((ilimit / 2)) ||
2299                 quota_error a $TSTUSR "rebalancing failed"
2300
2301         $RUNAS unlinkmany $TESTFILE1 $((ilimit / 2)) ||
2302                 error "unlink mdt1 files failed"
2303         rmdir $DIR/${tdir}-1 || error "unlink remote dir failed"
2304
2305         cleanup_quota_test
2306 }
2307 run_test 12b "Inode quota rebalancing"
2308
2309 test_13(){
2310         local TESTFILE=$DIR/$tdir/$tfile
2311         # the name of lwp on ost1 name is MDT0000-lwp-OST0000
2312         local procf="ldlm.namespaces.*MDT0000-lwp-OST0000.lru_size"
2313
2314         setup_quota_test || error "setup quota failed with $?"
2315         trap cleanup_quota_test EXIT
2316
2317         set_ost_qtype "u" || error "enable ost quota failed"
2318         quota_show_check b u $TSTUSR
2319
2320         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
2321                 error "set quota failed"
2322         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
2323         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2324
2325         # clear the locks in cache first
2326         do_facet ost1 $LCTL set_param -n $procf=clear
2327         local nlock=$(do_facet ost1 $LCTL get_param -n $procf)
2328         [ $nlock -eq 0 ] || error "$nlock cached locks"
2329
2330         # write to acquire the per-ID lock
2331         $RUNAS $DD of=$TESTFILE count=1 oflag=sync ||
2332                 quota_error a $TSTUSR "dd failed"
2333
2334         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
2335         [ $nlock -eq 1 ] || error "lock count($nlock) isn't 1"
2336
2337         # clear quota doesn't trigger per-ID lock cancellation
2338         resetquota -u $TSTUSR
2339         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
2340         [ $nlock -eq 1 ] || error "per-ID lock is lost on quota clear"
2341
2342         # clear the per-ID lock
2343         do_facet ost1 $LCTL set_param -n $procf=clear
2344         nlock=$(do_facet ost1 $LCTL get_param -n $procf)
2345         [ $nlock -eq 0 ] || error "per-ID lock isn't cleared"
2346
2347         # spare quota should be released
2348         local OSTUUID=$(ostuuid_from_index 0)
2349         local limit=$(getquota -u $TSTUSR $OSTUUID bhardlimit)
2350         local space=$(getquota -u $TSTUSR $OSTUUID curspace)
2351         [ $limit -le $space ] ||
2352                 error "spare quota isn't released, limit:$limit, space:$space"
2353
2354         cleanup_quota_test
2355 }
2356 run_test 13 "Cancel per-ID lock in the LRU list"
2357
2358 test_15(){
2359         local LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB
2360
2361         wait_delete_completed
2362         sync_all_data || true
2363
2364         # test for user
2365         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
2366                 error "set user quota failed"
2367         local TOTAL_LIMIT=$(getquota -u $TSTUSR global bhardlimit)
2368         [ $TOTAL_LIMIT -eq $LIMIT ] ||
2369                 error "(user) limit:$TOTAL_LIMIT, expect:$LIMIT, failed!"
2370         resetquota -u $TSTUSR
2371
2372         # test for group
2373         $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR ||
2374                 error "set group quota failed"
2375         TOTAL_LIMIT=$(getquota -g $TSTUSR global bhardlimit)
2376         [ $TOTAL_LIMIT -eq $LIMIT ] ||
2377                 error "(group) limits:$TOTAL_LIMIT, expect:$LIMIT, failed!"
2378         resetquota -g $TSTUSR
2379 }
2380 run_test 15 "Set over 4T block quota"
2381
2382 test_17sub() {
2383         local err_code=$1
2384         local BLKS=1    # 1M less than limit
2385         local TESTFILE=$DIR/$tdir/$tfile
2386
2387         setup_quota_test || error "setup quota failed with $?"
2388         trap cleanup_quota_test EXIT
2389
2390         # make sure the system is clean
2391         local USED=$(getquota -u $TSTUSR global curspace)
2392         [ $USED -ne 0 ] && error "Used space($USED) for user $TSTUSR isn't 0."
2393
2394         set_ost_qtype "ug" || error "enable ost quota failed"
2395         # make sure no granted quota on ost
2396         resetquota -u $TSTUSR
2397         $LFS setquota -u $TSTUSR -b 0 -B 10M -i 0 -I 0 $DIR ||
2398                 error "set quota failed"
2399
2400         quota_show_check b u $TSTUSR
2401
2402         #define OBD_FAIL_QUOTA_RECOVERABLE_ERR 0xa04
2403         lustre_fail mds 0xa04 $err_code
2404
2405         # write in background
2406         $RUNAS $DD of=$TESTFILE count=$BLKS oflag=direct &
2407         local DDPID=$!
2408
2409         sleep 2
2410         # write should be blocked and never finished
2411         if ! ps -p $DDPID  > /dev/null 2>&1; then
2412                 lustre_fail mds 0 0
2413                 quota_error u $TSTUSR "write finished incorrectly!"
2414         fi
2415
2416         lustre_fail mds 0 0
2417
2418         local count=0
2419         local timeout=30
2420         while [ true ]; do
2421                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
2422                 count=$((count+1))
2423                 if [ $count -gt $timeout ]; then
2424                         quota_error u $TSTUSR "dd is not finished!"
2425                 fi
2426                 sleep 1
2427         done
2428
2429         sync; sync_all_data || true
2430
2431         USED=$(getquota -u $TSTUSR global curspace)
2432         [ $USED -ge $((BLKS * 1024)) ] || quota_error u $TSTUSR \
2433                 "Used space(${USED}K) is less than ${BLKS}M"
2434
2435         cleanup_quota_test
2436 }
2437
2438 # DQACQ return recoverable error
2439 test_17() {
2440         echo "DQACQ return -ENOLCK"
2441         #define ENOLCK  37
2442         test_17sub 37 || error "Handle -ENOLCK failed"
2443
2444         echo "DQACQ return -EAGAIN"
2445         #define EAGAIN  11
2446         test_17sub 11 || error "Handle -EAGAIN failed"
2447
2448         echo "DQACQ return -ETIMEDOUT"
2449         #define ETIMEDOUT 110
2450         test_17sub 110 || error "Handle -ETIMEDOUT failed"
2451
2452         echo "DQACQ return -ENOTCONN"
2453         #define ENOTCONN 107
2454         test_17sub 107 || error "Handle -ENOTCONN failed"
2455 }
2456
2457 run_test 17 "DQACQ return recoverable error"
2458
2459 test_18_sub () {
2460         local io_type=$1
2461         local blimit="200m" # 200M
2462         local TESTFILE="$DIR/$tdir/$tfile"
2463
2464         setup_quota_test || error "setup quota failed with $?"
2465         trap cleanup_quota_test EXIT
2466
2467         set_ost_qtype "u" || error "enable ost quota failed"
2468         log "User quota (limit: $blimit)"
2469         $LFS setquota -u $TSTUSR -b 0 -B $blimit -i 0 -I 0 $MOUNT ||
2470                 error "set quota failed"
2471         quota_show_check b u $TSTUSR
2472
2473         $LFS setstripe $TESTFILE -i 0 -c 1 || error "setstripe $TESTFILE failed"
2474         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2475
2476         local timeout=$(sysctl -n lustre.timeout)
2477
2478         if [ $io_type = "directio" ]; then
2479                 log "Write 100M (directio) ..."
2480                 $RUNAS $DD of=$TESTFILE count=100 oflag=direct &
2481         else
2482                 log "Write 100M (buffered) ..."
2483                 $RUNAS $DD of=$TESTFILE count=100 &
2484         fi
2485         local DDPID=$!
2486
2487         replay_barrier $SINGLEMDS
2488         log "Fail mds for $((2 * timeout)) seconds"
2489         fail $SINGLEMDS $((2 * timeout))
2490
2491         local count=0
2492         if at_is_enabled; then
2493                 timeout=$(at_max_get mds)
2494         else
2495                 timeout=$(lctl get_param -n timeout)
2496         fi
2497
2498         while [ true ]; do
2499                 if ! ps -p ${DDPID} > /dev/null 2>&1; then break; fi
2500                 if [ $((++count % (2 * timeout) )) -eq 0 ]; then
2501                         log "it took $count second"
2502                 fi
2503                 sleep 1
2504         done
2505
2506         log "(dd_pid=$DDPID, time=$count, timeout=$timeout)"
2507         sync
2508         cancel_lru_locks mdc
2509         cancel_lru_locks osc
2510         $SHOW_QUOTA_USER
2511
2512         local testfile_size=$(stat -c %s $TESTFILE)
2513         if [ $testfile_size -ne $((BLK_SZ * 1024 * 100)) ] ; then
2514                 quota_error u $TSTUSR "expect $((BLK_SZ * 1024 * 100))," \
2515                         "got ${testfile_size}. Verifying file failed!"
2516         fi
2517         cleanup_quota_test
2518 }
2519
2520 # test when mds does failover, the ost still could work well
2521 # this test shouldn't trigger watchdog b=14840
2522 test_18() {
2523         # Clear dmesg so watchdog is not triggered by previous
2524         # test output
2525         do_facet ost1 dmesg -c > /dev/null
2526
2527         test_18_sub normal
2528         test_18_sub directio
2529
2530         # check if watchdog is triggered
2531         do_facet ost1 dmesg > $TMP/lustre-log-${TESTNAME}.log
2532         local watchdog=$(awk '/[Ss]ervice thread pid/ && /was inactive/ \
2533                         { print; }' $TMP/lustre-log-${TESTNAME}.log)
2534         [ -z "$watchdog" ] || error "$watchdog"
2535         rm -f $TMP/lustre-log-${TESTNAME}.log
2536 }
2537 run_test 18 "MDS failover while writing, no watchdog triggered (b14840)"
2538
2539 test_19() {
2540         local blimit=5 # 5M
2541         local TESTFILE=$DIR/$tdir/$tfile
2542
2543         setup_quota_test || error "setup quota failed with $?"
2544         trap cleanup_quota_test EXIT
2545
2546         set_ost_qtype $QTYPE || error "enable ost quota failed"
2547
2548         # bind file to a single OST
2549         $LFS setstripe -c 1 $TESTFILE || error "setstripe $TESTFILE failed"
2550         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2551
2552         echo "Set user quota (limit: ${blimit}M)"
2553         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2554                 error "set user quota failed"
2555         quota_show_check b u $TSTUSR
2556         echo "Update quota limits"
2557         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2558                 error "set group quota failed"
2559         quota_show_check b u $TSTUSR
2560
2561         # first wirte might be cached
2562         $RUNAS $DD of=$TESTFILE count=$((blimit + 1))
2563         cancel_lru_locks osc
2564         $SHOW_QUOTA_USER
2565         $RUNAS $DD of=$TESTFILE count=$((blimit + 1)) seek=$((blimit + 1)) &&
2566                 quota_error u $TSTUSR "Write success, expect failure"
2567         $SHOW_QUOTA_USER
2568
2569         cleanup_quota_test
2570 }
2571 run_test 19 "Updating admin limits doesn't zero operational limits(b14790)"
2572
2573 test_20() { # b15754
2574         local LSTR=(2g 1t 4k 3m) # limits strings
2575         # limits values
2576         local LVAL=($((2*1024*1024)) $((1*1024*1024*1024)) $((4*1024)) \
2577                     $((3*1024*1024)))
2578
2579         resetquota -u $TSTUSR
2580
2581         $LFS setquota -u $TSTUSR --block-softlimit ${LSTR[0]} \
2582                 $MOUNT || error "could not set quota limits"
2583         $LFS setquota -u $TSTUSR --block-hardlimit ${LSTR[1]} \
2584                                 --inode-softlimit ${LSTR[2]} \
2585                                 --inode-hardlimit ${LSTR[3]} \
2586                                 $MOUNT || error "could not set quota limits"
2587
2588         [ "$(getquota -u $TSTUSR global bsoftlimit)" = "${LVAL[0]}" ] ||
2589                 error "bsoftlimit was not set properly"
2590         [ "$(getquota -u $TSTUSR global bhardlimit)" = "${LVAL[1]}" ] ||
2591                 error "bhardlimit was not set properly"
2592         [ "$(getquota -u $TSTUSR global isoftlimit)" = "${LVAL[2]}" ] ||
2593                 error "isoftlimit was not set properly"
2594         [ "$(getquota -u $TSTUSR global ihardlimit)" = "${LVAL[3]}" ] ||
2595                 error "ihardlimit was not set properly"
2596
2597         resetquota -u $TSTUSR
2598 }
2599 run_test 20 "Test if setquota specifiers work properly (b15754)"
2600
2601 test_21_sub() {
2602         local testfile=$1
2603         local blk_number=$2
2604         local seconds=$3
2605
2606         local time=$(($(date +%s) + seconds))
2607         while [ $(date +%s) -lt $time ]; do
2608                 $RUNAS $DD of=$testfile count=$blk_number > /dev/null 2>&1
2609         done
2610 }
2611
2612 # run for fixing bug16053, setquota shouldn't fail when writing and
2613 # deleting are happening
2614 test_21() {
2615         local TESTFILE="$DIR/$tdir/$tfile"
2616         local BLIMIT=10 # 10G
2617         local ILIMIT=1000000
2618
2619         setup_quota_test || error "setup quota failed with $?"
2620         trap cleanup_quota_test EXIT
2621
2622         set_ost_qtype $QTYPE || error "Enable ost quota failed"
2623
2624         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for user: $TSTUSR"
2625         $LFS setquota -u $TSTUSR -b 0 -B ${BLIMIT}G -i 0 -I $ILIMIT $MOUNT ||
2626                 error "set user quota failed"
2627         log "Set limit(block:${BLIMIT}G; file:$ILIMIT) for group: $TSTUSR"
2628         $LFS setquota -g $TSTUSR -b 0 -B $BLIMIT -i 0 -I $ILIMIT $MOUNT ||
2629                 error "set group quota failed"
2630         if is_project_quota_supported; then
2631                 log "Set limit(block:${BLIMIT}G; file:$LIMIT) for " \
2632                         "project: $TSTPRJID"
2633                 $LFS setquota -p $TSTPRJID -b 0 -B $BLIMIT -i 0 -I $ILIMIT \
2634                          $MOUNT || error "set project quota failed"
2635         fi
2636
2637         # repeat writing on a 1M file
2638         test_21_sub ${TESTFILE}_1 1 30 &
2639         local DDPID1=$!
2640         # repeat writing on a 128M file
2641         test_21_sub ${TESTFILE}_2 128 30 &
2642         local DDPID2=$!
2643
2644         local time=$(($(date +%s) + 30))
2645         local i=1
2646         while [ $(date +%s) -lt $time ]; do
2647                 log "Set quota for $i times"
2648                 $LFS setquota -u $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
2649                         -I $((ILIMIT + i)) $MOUNT ||
2650                                 error "Set user quota failed"
2651                 $LFS setquota -g $TSTUSR -b 0 -B "$((BLIMIT + i))G" -i 0 \
2652                         -I $((ILIMIT + i)) $MOUNT ||
2653                                 error "Set group quota failed"
2654                 if is_project_quota_supported; then
2655                         $LFS setquota -p $TSTPRJID -b 0 -B \
2656                         "$((BLIMIT + i))G"  -i 0 -I $((ILIMIT + i)) $MOUNT ||
2657                                 error "Set project quota failed"
2658                 fi
2659                 i=$((i+1))
2660                 sleep 1
2661         done
2662
2663         local count=0
2664         while [ true ]; do
2665                 if ! ps -p ${DDPID1} > /dev/null 2>&1; then break; fi
2666                 count=$((count+1))
2667                 if [ $count -gt 60 ]; then
2668                         quota_error a $TSTUSR "dd should be finished!"
2669                 fi
2670                 sleep 1
2671         done
2672         echo "(dd_pid=$DDPID1, time=$count)successful"
2673
2674         count=0
2675         while [ true ]; do
2676                 if ! ps -p ${DDPID2} > /dev/null 2>&1; then break; fi
2677                 count=$((count+1))
2678                 if [ $count -gt 60 ]; then
2679                         quota_error a $TSTUSR "dd should be finished!"
2680                 fi
2681                 sleep 1
2682         done
2683         echo "(dd_pid=$DDPID2, time=$count)successful"
2684
2685         cleanup_quota_test
2686 }
2687 run_test 21 "Setquota while writing & deleting (b16053)"
2688
2689 # enable/disable quota enforcement permanently
2690 test_22() {
2691         echo "Set both mdt & ost quota type as ug"
2692         local qtype="ug"
2693         is_project_quota_supported && qtype=$QTYPE
2694         set_mdt_qtype $qtype || error "enable mdt quota failed"
2695         set_ost_qtype $qtype || error "enable ost quota failed"
2696
2697         echo "Restart..."
2698         stopall || error "failed to stopall (1)"
2699         mount
2700         setupall
2701
2702         echo "Verify if quota is enabled"
2703         local qtype1=$(mdt_quota_type)
2704         [ $qtype1 != $qtype ] && error "mdt quota setting is lost"
2705         qtype=$(ost_quota_type)
2706         [ $qtype1 != $qtype ] && error "ost quota setting is lost"
2707
2708         echo "Set both mdt & ost quota type as none"
2709         set_mdt_qtype "none" || error "disable mdt quota failed"
2710         set_ost_qtype "none" || error "disable ost quota failed"
2711
2712         echo "Restart..."
2713         stopall || error "failed to stopall (2)"
2714         mount
2715         setupall
2716         quota_init
2717
2718         echo "Verify if quota is disabled"
2719         qtype=$(mdt_quota_type)
2720         [ $qtype != "none" ] && error "mdt quota setting is lost"
2721         qtype=$(ost_quota_type)
2722         [ $qtype != "none" ] && error "ost quota setting is lost"
2723
2724         return 0
2725 }
2726 run_test 22 "enable/disable quota by 'lctl conf_param/set_param -P'"
2727
2728 test_23_sub() {
2729         local TESTFILE="$DIR/$tdir/$tfile"
2730         local LIMIT=$1
2731
2732         setup_quota_test || error "setup quota failed with $?"
2733         trap cleanup_quota_test EXIT
2734
2735         set_ost_qtype $QTYPE || error "Enable ost quota failed"
2736
2737         # test for user
2738         log "User quota (limit: $LIMIT MB)"
2739         $LFS setquota -u $TSTUSR -b 0 -B "$LIMIT"M -i 0 -I 0 $DIR ||
2740                 error "set quota failed"
2741         quota_show_check b u $TSTUSR
2742
2743         $LFS setstripe $TESTFILE -c 1 -i 0 || error "setstripe $TESTFILE failed"
2744         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2745
2746         log "Step1: trigger EDQUOT with O_DIRECT"
2747         log "Write half of file"
2748         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2)) oflag=direct ||
2749                 quota_error u $TSTUSR "(1) Write failure, expect success." \
2750                         "limit=$LIMIT"
2751         log "Write out of block quota ..."
2752         $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 + 1)) seek=$((LIMIT/2)) \
2753                 oflag=direct conv=notrunc &&
2754                 quota_error u $TSTUSR "(2) Write success, expect EDQUOT." \
2755                         "limit=$LIMIT"
2756         log "Step1: done"
2757
2758         log "Step2: rewrite should succeed"
2759         $RUNAS $DD of=$TESTFILE count=1 oflag=direct conv=notrunc||
2760                 quota_error u $TSTUSR "(3) Write failure, expect success." \
2761                         "limit=$LIMIT"
2762         log "Step2: done"
2763
2764         cleanup_quota_test
2765
2766         local OST0_UUID=$(ostuuid_from_index 0)
2767         local OST0_QUOTA_USED=$(getquota -u $TSTUSR $OST0_UUID curspace)
2768         [ $OST0_QUOTA_USED -ne 0 ] &&
2769                 ($SHOW_QUOTA_USER; \
2770                 quota_error u $TSTUSR "quota isn't released")
2771         $SHOW_QUOTA_USER
2772 }
2773
2774 test_23() {
2775         [ "$ost1_FSTYPE" == zfs ] &&
2776                 skip "Overwrite in place is not guaranteed to be " \
2777                 "space neutral on ZFS"
2778
2779         local OST0_MIN=$((6 * 1024)) # 6MB, extra space for meta blocks.
2780         check_whether_skip && return 0
2781         log "run for 4MB test file"
2782         test_23_sub 4
2783
2784         OST0_MIN=$((60 * 1024)) # 60MB, extra space for meta blocks.
2785         check_whether_skip && return 0
2786         log "run for 40MB test file"
2787         test_23_sub 40
2788 }
2789 run_test 23 "Quota should be honored with directIO (b16125)"
2790
2791 test_24() {
2792         local blimit=5 # 5M
2793         local TESTFILE="$DIR/$tdir/$tfile"
2794
2795         setup_quota_test || error "setup quota failed with $?"
2796         trap cleanup_quota_test EXIT
2797
2798         set_ost_qtype $QTYPE || error "enable ost quota failed"
2799
2800         # bind file to a single OST
2801         $LFS setstripe -c 1 $TESTFILE || error "setstripe $TESTFILE failed"
2802         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2803
2804         echo "Set user quota (limit: ${blimit}M)"
2805         $LFS setquota -u $TSTUSR -b 0 -B "$blimit"M -i 0 -I 0 $MOUNT ||
2806                 error "set quota failed"
2807
2808         # overrun quota by root user
2809         runas -u 0 -g 0 $DD of=$TESTFILE count=$((blimit + 1)) ||
2810                 error "write failure, expect success"
2811         cancel_lru_locks osc
2812         sync_all_data || true
2813
2814         $SHOW_QUOTA_USER | grep '*' || error "no matching *"
2815
2816         cleanup_quota_test
2817 }
2818 run_test 24 "lfs draws an asterix when limit is reached (b16646)"
2819
2820 test_27a() { # b19612
2821         $LFS quota $TSTUSR $DIR &&
2822                 error "lfs succeeded with no type, but should have failed"
2823         $LFS setquota $TSTUSR $DIR &&
2824                 error "lfs succeeded with no type, but should have failed"
2825         return 0
2826 }
2827 run_test 27a "lfs quota/setquota should handle wrong arguments (b19612)"
2828
2829 test_27b() { # b20200
2830         $LFS setquota -u $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
2831                 error "lfs setquota failed with uid argument"
2832         $LFS setquota -g $TSTID -b 1000 -B 1000 -i 1000 -I 1000 $DIR ||
2833                 error "lfs stequota failed with gid argument"
2834         if is_project_quota_supported; then
2835                 $LFS setquota -p $TSTPRJID -b 1000 -B 1000 -i 1000 -I \
2836                         1000 $DIR || error \
2837                                 "lfs stequota failed with projid argument"
2838         fi
2839         $SHOW_QUOTA_USERID || error "lfs quota failed with uid argument"
2840         $SHOW_QUOTA_GROUPID || error "lfs quota failed with gid argument"
2841         if is_project_quota_supported; then
2842                 $SHOW_QUOTA_PROJID ||
2843                         error "lfs quota failed with projid argument"
2844         fi
2845         resetquota -u $TSTID
2846         resetquota -g $TSTID
2847         resetquota -p $TSTPRJID
2848         return 0
2849 }
2850 run_test 27b "lfs quota/setquota should handle user/group/project ID (b20200)"
2851
2852 test_27c() {
2853         local limit
2854
2855         $LFS setquota -u $TSTID -b 30M -B 3T $DIR ||
2856                 error "lfs setquota failed"
2857
2858         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $3}')
2859         [ $limit != "30M" ] && error "softlimit $limit isn't human-readable"
2860         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $4}')
2861         [ $limit != "3T" ] && error "hardlimit $limit isn't human-readable"
2862
2863         $LFS setquota -u $TSTID -b 1500M -B 18500G $DIR ||
2864                 error "lfs setquota for $TSTID failed"
2865
2866         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $3}')
2867         [ $limit != "1.465G" ] && error "wrong softlimit $limit"
2868         limit=$($LFS quota -u $TSTID -v -h $DIR | grep $DIR | awk '{print $4}')
2869         [ $limit != "18.07T" ] && error "wrong hardlimit $limit"
2870
2871         $LFS quota -u $TSTID -v -h $DIR | grep -q "Total allocated" ||
2872                 error "total allocated inode/block limit not printed"
2873
2874         resetquota -u $TSTUSR
2875 }
2876 run_test 27c "lfs quota should support human-readable output"
2877
2878 test_27d() {
2879         local softlimit=1.5
2880         local hardlimit=2.3
2881         local limit
2882
2883         $LFS setquota -u $TSTID -b ${softlimit}p -B ${hardlimit}P $DIR ||
2884                 error "set fraction block limit failed"
2885         limit=$($LFS quota -u $TSTID -h $DIR | grep $DIR | awk '{print $3}')
2886         [ $limit == ${softlimit}P ] || error "get fraction softlimit failed"
2887         limit=$($LFS quota -u $TSTID -h $DIR | grep $DIR | awk '{print $4}')
2888         [ $limit == ${hardlimit}P ] || error "get fraction hardlimit failed"
2889
2890         resetquota -u $TSTUSR
2891 }
2892 run_test 27d "lfs setquota should support fraction block limit"
2893
2894 test_30() {
2895         local LIMIT=4 # 4MB
2896         local TESTFILE="$DIR/$tdir/$tfile"
2897         local GRACE=10
2898
2899         setup_quota_test || error "setup quota failed with $?"
2900         trap cleanup_quota_test EXIT
2901
2902         set_ost_qtype "u" || error "enable ost quota failed"
2903
2904         $LFS setstripe $TESTFILE -i 0 -c 1 || error "setstripe $TESTFILE failed"
2905         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
2906
2907         $LFS setquota -t -u --block-grace $GRACE --inode-grace \
2908                 $MAX_IQ_TIME $DIR || error "set grace time failed"
2909         $LFS setquota -u $TSTUSR -b ${LIMIT}M -B 0 -i 0 -I 0 $DIR ||
2910                 error "set quota failed"
2911         $RUNAS $DD of=$TESTFILE count=$((LIMIT * 2)) || true
2912         cancel_lru_locks osc
2913         sleep $GRACE
2914         $LFS setquota -u $TSTUSR -B 0 $DIR || error "clear quota failed"
2915         # over-quota flag has not yet settled since we do not trigger async
2916         # events based on grace time period expiration
2917         $SHOW_QUOTA_USER
2918         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=4 || true
2919         cancel_lru_locks osc
2920         # now over-quota flag should be settled and further writes should fail
2921         $SHOW_QUOTA_USER
2922         $RUNAS $DD of=$TESTFILE conv=notrunc oflag=append count=4 &&
2923                 error "grace times were reset"
2924         # cleanup
2925         cleanup_quota_test
2926         $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace \
2927                 $MAX_IQ_TIME $DIR || error "restore grace time failed"
2928 }
2929 run_test 30 "Hard limit updates should not reset grace times"
2930
2931 # basic usage tracking for user & group
2932 test_33() {
2933         local INODES=10 # 10 files
2934         local BLK_CNT=2 # of 2M each
2935         local TOTAL_BLKS=$((INODES * BLK_CNT * 1024))
2936
2937         setup_quota_test || error "setup quota failed with $?"
2938         trap cleanup_quota_test EXIT
2939
2940         # make sure the system is clean
2941         local USED=$(getquota -u $TSTID global curspace)
2942         [ $USED -ne 0 ] &&
2943                 error "Used space ($USED) for user $TSTID isn't 0."
2944         USED=$(getquota -g $TSTID global curspace)
2945         [ $USED -ne 0 ] &&
2946                 error "Used space ($USED) for group $TSTID isn't 0."
2947         if is_project_quota_supported; then
2948                 USED=$(getquota -p $TSTPRJID global curspace)
2949                 [ $USED -ne 0 ] && error \
2950                         "Used space ($USED) for project $TSTPRJID isn't 0."
2951         fi
2952
2953         echo "Write files..."
2954         for i in $(seq 0 $INODES); do
2955                 $RUNAS $DD of=$DIR/$tdir/$tfile-$i count=$BLK_CNT 2>/dev/null ||
2956                         error "write failed"
2957                         is_project_quota_supported &&
2958                                 change_project -p $TSTPRJID $DIR/$tdir/$tfile-$i
2959                 echo "Iteration $i/$INODES completed"
2960         done
2961         cancel_lru_locks osc
2962
2963         echo "Wait for setattr on objects finished..."
2964         wait_delete_completed
2965
2966         sync; sync_all_data || true
2967
2968         echo "Verify disk usage after write"
2969         USED=$(getquota -u $TSTID global curspace)
2970         [ $USED -lt $TOTAL_BLKS ] &&
2971                 error "Used space for user $TSTID:$USED, expected:$TOTAL_BLKS"
2972         USED=$(getquota -g $TSTID global curspace)
2973         [ $USED -lt $TOTAL_BLKS ] &&
2974                 error "Used space for group $TSTID:$USED, expected:$TOTAL_BLKS"
2975         if is_project_quota_supported; then
2976                 USED=$(getquota -p $TSTPRJID global curspace)
2977                 [ $USED -lt $TOTAL_BLKS ] && error \
2978                         "Used space for project $TSTPRJID:$USED, expected:$TOTAL_BLKS"
2979         fi
2980
2981         echo "Verify inode usage after write"
2982         USED=$(getquota -u $TSTID global curinodes)
2983         [ $USED -lt $INODES ] &&
2984                 error "Used inode for user $TSTID is $USED, expected $INODES"
2985         USED=$(getquota -g $TSTID global curinodes)
2986         [ $USED -lt $INODES ] &&
2987                 error "Used inode for group $TSTID is $USED, expected $INODES"
2988         if is_project_quota_supported; then
2989                 USED=$(getquota -p $TSTPRJID global curinodes)
2990                 [ $USED -lt $INODES ] && error \
2991                         "Used inode for project $TSTPRJID is $USED, expected $INODES"
2992         fi
2993
2994         cleanup_quota_test
2995
2996         echo "Verify disk usage after delete"
2997         USED=$(getquota -u $TSTID global curspace)
2998         [ $USED -eq 0 ] || error "Used space for user $TSTID isn't 0. $USED"
2999         USED=$(getquota -u $TSTID global curinodes)
3000         [ $USED -eq 0 ] || error "Used inodes for user $TSTID isn't 0. $USED"
3001         USED=$(getquota -g $TSTID global curspace)
3002         [ $USED -eq 0 ] || error "Used space for group $TSTID isn't 0. $USED"
3003         USED=$(getquota -g $TSTID global curinodes)
3004         [ $USED -eq 0 ] || error "Used inodes for group $TSTID isn't 0. $USED"
3005         if is_project_quota_supported; then
3006                 USED=$(getquota -p $TSTPRJID global curspace)
3007                 [ $USED -eq 0 ] ||
3008                         error "Used space for project $TSTPRJID isn't 0. $USED"
3009                 USED=$(getquota -p $TSTPRJID global curinodes)
3010                 [ $USED -eq 0 ] ||
3011                         error "Used inodes for project $TSTPRJID isn't 0. $USED"
3012         fi
3013 }
3014 run_test 33 "Basic usage tracking for user & group & project"
3015
3016 # usage transfer test for user & group & project
3017 test_34() {
3018         local BLK_CNT=2 # 2MB
3019         local project_supported="no"
3020
3021         is_project_quota_supported && project_supported="yes"
3022         setup_quota_test || error "setup quota failed with $?"
3023         trap cleanup_quota_test EXIT
3024
3025         # make sure the system is clean
3026         local USED=$(getquota -u $TSTID global curspace)
3027         [ $USED -ne 0 ] && error "Used space ($USED) for user $TSTID isn't 0."
3028         USED=$(getquota -g $TSTID global curspace)
3029         [ $USED -ne 0 ] && error "Used space ($USED) for group $TSTID isn't 0."
3030
3031         local USED=$(getquota -u $TSTID2 global curspace)
3032         [ $USED -ne 0 ] && error "Used space ($USED) for user $TSTID2 isn't 0."
3033         if [ $project_supported == "yes" ]; then
3034                 USED=$(getquota -p $TSTPRJID global curspace)
3035                 [ $USED -ne 0 ] && error \
3036                         "Used space ($USED) for Project $TSTPRJID isn't 0."
3037         fi
3038
3039         echo "Write file..."
3040         $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
3041                 error "write failed"
3042         cancel_lru_locks osc
3043         sync; sync_all_data || true
3044
3045         echo "chown the file to user $TSTID"
3046         chown $TSTID $DIR/$tdir/$tfile || error "chown failed"
3047
3048         echo "Wait for setattr on objects finished..."
3049         wait_delete_completed
3050
3051         BLK_CNT=$((BLK_CNT * 1024))
3052
3053         echo "Verify disk usage for user $TSTID"
3054         USED=$(getquota -u $TSTID global curspace)
3055         [ $USED -lt $BLK_CNT ] &&
3056                 error "Used space for user $TSTID is ${USED}, expected $BLK_CNT"
3057         USED=$(getquota -u $TSTID global curinodes)
3058         [ $USED -ne 1 ] &&
3059                 error "Used inodes for user $TSTID is $USED, expected 1"
3060
3061         echo "chgrp the file to group $TSTID"
3062         chgrp $TSTID $DIR/$tdir/$tfile || error "chgrp failed"
3063
3064         echo "Wait for setattr on objects finished..."
3065         wait_delete_completed
3066
3067         echo "Verify disk usage for group $TSTID"
3068         USED=$(getquota -g $TSTID global curspace)
3069         [ $USED -ge $BLK_CNT ] ||
3070                 error "Used space for group $TSTID is $USED, expected $BLK_CNT"
3071         USED=$(getquota -g $TSTID global curinodes)
3072         [ $USED -eq 1 ] ||
3073                 error "Used inodes for group $TSTID is $USED, expected 1"
3074
3075         # chown won't change the ost object group. LU-4345 */
3076         echo "chown the file to user $TSTID2"
3077         chown $TSTID2 $DIR/$tdir/$tfile || error "chown to $TSTID2 failed"
3078
3079         echo "Wait for setattr on objects finished..."
3080         wait_delete_completed
3081
3082         echo "change_project project id to $TSTPRJID"
3083         [ $project_supported == "yes" ] &&
3084                 change_project -p $TSTPRJID $DIR/$tdir/$tfile
3085         echo "Wait for setattr on objects finished..."
3086         wait_delete_completed
3087
3088         echo "Verify disk usage for user $TSTID2/$TSTID and group $TSTID"
3089         USED=$(getquota -u $TSTID2 global curspace)
3090         [ $USED -lt $BLK_CNT ] &&
3091                 error "Used space for user $TSTID2 is $USED, expected $BLK_CNT"
3092         USED=$(getquota -u $TSTID global curspace)
3093         [ $USED -ne 0 ] &&
3094                 error "Used space for user $TSTID is $USED, expected 0"
3095         USED=$(getquota -g $TSTID global curspace)
3096         [ $USED -lt $BLK_CNT ] &&
3097                 error "Used space for group $TSTID is $USED, expected $BLK_CNT"
3098         if [ $project_supported == "yes" ]; then
3099                 USED=$(getquota -p $TSTPRJID global curspace)
3100                 [ $USED -lt $BLK_CNT ] && error \
3101                         "Used space for group $TSTPRJID is $USED, expected $BLK_CNT"
3102         fi
3103
3104         cleanup_quota_test
3105 }
3106 run_test 34 "Usage transfer for user & group & project"
3107
3108 # usage is still accessible across restart
3109 test_35() {
3110         local BLK_CNT=2 # 2 MB
3111
3112         setup_quota_test || error "setup quota failed with $?"
3113         trap cleanup_quota_test EXIT
3114
3115         echo "Write file..."
3116         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT 2>/dev/null ||
3117                 error "write failed"
3118         is_project_quota_supported &&
3119                 change_project -p $TSTPRJID $DIR/$tdir/$tfile
3120         cancel_lru_locks osc
3121
3122         echo "Wait for setattr on objects finished..."
3123         wait_delete_completed
3124
3125         sync; sync_all_data || true
3126
3127         echo "Save disk usage before restart"
3128         local ORIG_USR_SPACE=$(getquota -u $TSTID global curspace)
3129         [ $ORIG_USR_SPACE -eq 0 ] &&
3130                 error "Used space for user $TSTID is 0, expected ${BLK_CNT}M"
3131         local ORIG_USR_INODES=$(getquota -u $TSTID global curinodes)
3132         [ $ORIG_USR_INODES -eq 0 ] &&
3133                 error "Used inodes for user $TSTID is 0, expected 1"
3134         echo "User $TSTID: ${ORIG_USR_SPACE}KB $ORIG_USR_INODES inodes"
3135         local ORIG_GRP_SPACE=$(getquota -g $TSTID global curspace)
3136         [ $ORIG_GRP_SPACE -eq 0 ] &&
3137                 error "Used space for group $TSTID is 0, expected ${BLK_CNT}M"
3138         local ORIG_GRP_INODES=$(getquota -g $TSTID global curinodes)
3139         [ $ORIG_GRP_INODES -eq 0 ] &&
3140                 error "Used inodes for group $TSTID is 0, expected 1"
3141         echo "Group $TSTID: ${ORIG_GRP_SPACE}KB $ORIG_GRP_INODES inodes"
3142
3143         if is_project_quota_supported; then
3144                 local ORIG_PRJ_SPACE=$(getquota -p $TSTPRJID global curspace)
3145                 [ $ORIG_PRJ_SPACE -eq 0 ] && error \
3146                         "Used space for project $TSTPRJID is 0, expected ${BLK_CNT}M"
3147                 local ORIG_PRJ_INODES=$(getquota -p $TSTPRJID global curinodes)
3148                 [ $ORIG_PRJ_INODES -eq 0 ] && error \
3149                         "Used inodes for project $TSTPRJID is 0, expected 1"
3150                 echo "Project $TSTPRJID: ${ORIG_PRJ_SPACE}KB $ORIG_PRJ_INODES inodes"
3151         fi
3152
3153         log "Restart..."
3154         stopall
3155         setupall
3156         quota_init
3157
3158         echo "Verify disk usage after restart"
3159         local USED=$(getquota -u $TSTID global curspace)
3160         [ $USED -eq $ORIG_USR_SPACE ] ||
3161                 error "Used space for user $TSTID changed from " \
3162                         "$ORIG_USR_SPACE to $USED"
3163         USED=$(getquota -u $TSTID global curinodes)
3164         [ $USED -eq $ORIG_USR_INODES ] ||
3165                 error "Used inodes for user $TSTID changed from " \
3166                         "$ORIG_USR_INODES to $USED"
3167         USED=$(getquota -g $TSTID global curspace)
3168         [ $USED -eq $ORIG_GRP_SPACE ] ||
3169                 error "Used space for group $TSTID changed from " \
3170                         "$ORIG_GRP_SPACE to $USED"
3171         USED=$(getquota -g $TSTID global curinodes)
3172         [ $USED -eq $ORIG_GRP_INODES ] ||
3173                 error "Used inodes for group $TSTID changed from " \
3174                         "$ORIG_GRP_INODES to $USED"
3175         if [ $project_supported == "yes" ]; then
3176                 USED=$(getquota -p $TSTPRJID global curinodes)
3177                 [ $USED -eq $ORIG_PRJ_INODES ] ||
3178                         error "Used inodes for project $TSTPRJID " \
3179                                 "changed from $ORIG_PRJ_INODES to $USED"
3180                 USED=$(getquota -p $TSTPRJID global curspace)
3181                 [ $USED -eq $ORIG_PRJ_SPACE ] ||
3182                         error "Used space for project $TSTPRJID "\
3183                                 "changed from $ORIG_PRJ_SPACE to $USED"
3184         fi
3185
3186         # check if the vfs_dq_init() is called before writing
3187         echo "Append to the same file..."
3188         $RUNAS $DD of=$DIR/$tdir/$tfile count=$BLK_CNT seek=1 2>/dev/null ||
3189                 error "write failed"
3190         cancel_lru_locks osc
3191         sync; sync_all_data || true
3192
3193         echo "Verify space usage is increased"
3194         USED=$(getquota -u $TSTID global curspace)
3195         [ $USED -gt $ORIG_USR_SPACE ] ||
3196                 error "Used space for user $TSTID isn't increased" \
3197                         "orig:$ORIG_USR_SPACE, now:$USED"
3198         USED=$(getquota -g $TSTID global curspace)
3199         [ $USED -gt $ORIG_GRP_SPACE ] ||
3200                 error "Used space for group $TSTID isn't increased" \
3201                         "orig:$ORIG_GRP_SPACE, now:$USED"
3202         if [ $project_supported == "yes" ]; then
3203                 USED=$(getquota -p $TSTPRJID global curspace)
3204                 [ $USED -gt $ORIG_PRJ_SPACE ] ||
3205                         error "Used space for project $TSTPRJID isn't " \
3206                                 "increased orig:$ORIG_PRJ_SPACE, now:$USED"
3207         fi
3208
3209         cleanup_quota_test
3210 }
3211 run_test 35 "Usage is still accessible across reboot"
3212
3213 # chown/chgrp to the file created with MDS_OPEN_DELAY_CREATE
3214 # LU-5006
3215 test_37() {
3216         [ "$MDS1_VERSION" -lt $(version_code 2.6.93) ] &&
3217                 skip "Old server doesn't have LU-5006 fix."
3218
3219         setup_quota_test || error "setup quota failed with $?"
3220         trap cleanup_quota_test EXIT
3221
3222         # make sure the system is clean
3223         local USED=$(getquota -u $TSTID global curspace)
3224         [ $USED -ne 0 ] &&
3225                 error "Used space ($USED) for user $TSTID isn't 0."
3226
3227         # create file with MDS_OPEN_DELAY_CREATE flag
3228         $LFS setstripe -c 1 -i 0 $DIR/$tdir/$tfile ||
3229                 error "Create file failed"
3230         # write to file
3231         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 conv=notrunc \
3232                 oflag=sync || error "Write file failed"
3233         # chown to the file
3234         chown $TSTID $DIR/$tdir/$tfile || error "Chown to file failed"
3235
3236         # wait for setattr on objects finished..."
3237         wait_delete_completed
3238
3239         USED=$(getquota -u $TSTID global curspace)
3240         [ $USED -ne 0 ] || quota_error u $TSTUSR "Used space is 0"
3241
3242         cleanup_quota_test
3243 }
3244 run_test 37 "Quota accounted properly for file created by 'lfs setstripe'"
3245
3246 # LU-8801
3247 test_38() {
3248         [ "$MDS1_VERSION" -lt $(version_code 2.8.60) ] &&
3249                 skip "Old server doesn't have LU-8801 fix."
3250
3251         [ "$UID" != 0 ] && skip_env "must run as root" && return
3252
3253         setup_quota_test || error "setup quota failed with $?"
3254         trap cleanup_quota_test EXIT
3255
3256         # make sure the system is clean
3257         local USED=$(getquota -u $TSTID global curspace)
3258         [ $USED -ne 0 ] &&
3259                 error "Used space ($USED) for user $TSTID isn't 0."
3260         USED=$(getquota -u $TSTID2 global curspace)
3261         [ $USED -ne 0 ] &&
3262                 error "Used space ($USED) for user $TSTID2 isn't 0."
3263
3264         local TESTFILE="$DIR/$tdir/$tfile"
3265         local file_cnt=10000
3266
3267         # Generate id entries in accounting file
3268         echo "Create $file_cnt files..."
3269         for i in `seq $file_cnt`; do
3270                 touch $TESTFILE-$i
3271                 chown $((file_cnt - i)):$((file_cnt - i)) $TESTFILE-$i ||
3272                         error "failed to chown $TESTFILE-$i"
3273         done
3274         cancel_lru_locks osc
3275         sync; sync_all_data || true
3276
3277         local procf="osd-$mds1_FSTYPE.$FSNAME-MDT0000"
3278         procf=${procf}.quota_slave.acct_user
3279         local accnt_cnt
3280
3281         acct_cnt=$(do_facet mds1 $LCTL get_param $procf | grep "id:" | \
3282                    awk '{if ($3 < 10000) {print $3}}' | wc -l)
3283         echo "Found $acct_cnt id entries"
3284
3285         [ $file_cnt -eq $acct_cnt ] || {
3286                 do_facet mds1 $LCTL get_param $procf
3287                 error "skipped id entries"
3288         }
3289
3290         cleanup_quota_test
3291 }
3292 run_test 38 "Quota accounting iterator doesn't skip id entries"
3293
3294 test_39() {
3295         local TESTFILE="$DIR/$tdir/project"
3296         ! is_project_quota_supported &&
3297                 skip "Project quota is not supported"
3298
3299         setup_quota_test || error "setup quota failed with $?"
3300
3301         touch $TESTFILE
3302         projectid=$(lfs project $TESTFILE | awk '{print $1}')
3303         [ $projectid -ne 0 ] &&
3304                 error "Project id should be 0 not $projectid"
3305         change_project -p 1024 $TESTFILE
3306         projectid=$(lfs project $TESTFILE | awk '{print $1}')
3307         [ $projectid -ne 1024 ] &&
3308                 error "Project id should be 1024 not $projectid"
3309
3310         stopall || error "failed to stopall (1)"
3311         mount
3312         setupall
3313         projectid=$(lfs project $TESTFILE | awk '{print $1}')
3314         [ $projectid -ne 1024 ] &&
3315                 error "Project id should be 1024 not $projectid"
3316
3317         cleanup_quota_test
3318 }
3319 run_test 39 "Project ID interface works correctly"
3320
3321 test_40a() {
3322         ! is_project_quota_supported &&
3323                 skip "Project quota is not supported"
3324         local dir1="$DIR/$tdir/dir1"
3325         local dir2="$DIR/$tdir/dir2"
3326
3327         setup_quota_test || error "setup quota failed with $?"
3328
3329         mkdir -p $dir1 $dir2
3330         change_project -sp 1 $dir1 && touch $dir1/1
3331         change_project -sp 2 $dir2
3332
3333         ln $dir1/1 $dir2/1_link &&
3334                 error "Hard link across different project quota should fail"
3335         rm -rf $dir1 $dir2
3336
3337         cleanup_quota_test
3338 }
3339 run_test 40a "Hard link across different project ID"
3340
3341 test_40b() {
3342         ! is_project_quota_supported &&
3343                 skip "Project quota is not supported"
3344         local dir1="$DIR/$tdir/dir1"
3345         local dir2="$DIR/$tdir/dir2"
3346
3347         setup_quota_test || error "setup quota failed with $?"
3348         mkdir -p $dir1 $dir2
3349         change_project -sp 1 $dir1 && touch $dir1/1
3350         change_project -sp 2 $dir2
3351
3352         mv $dir1/1 $dir2/2 || error "mv failed $?"
3353         local projid=$(lfs project $dir2/2 | awk '{print $1}')
3354         if [ "$projid" != "2" ]; then
3355                 error "project id expected 2 not $projid"
3356         fi
3357         rm -rf $dir1 $dir2
3358         cleanup_quota_test
3359 }
3360 run_test 40b "Mv across different project ID"
3361
3362 test_40c() {
3363         [ "$MDSCOUNT" -lt "2" ] && skip "needs >= 2 MDTs"
3364                 ! is_project_quota_supported &&
3365                         skip "Project quota is not supported"
3366
3367         setup_quota_test || error "setup quota failed with $?"
3368         local dir="$DIR/$tdir/dir"
3369
3370         mkdir -p $dir && change_project -sp 1 $dir
3371         $LFS mkdir -i 1 $dir/remote_dir || error "create remote dir failed"
3372         local projid=$(lfs project -d $dir/remote_dir | awk '{print $1}')
3373         [ "$projid" != "1" ] && error "projid id expected 1 not $projid"
3374         touch $dir/remote_dir/file
3375         #verify inherit works file for remote dir.
3376         local projid=$(lfs project -d $dir/remote_dir/file | awk '{print $1}')
3377         [ "$projid" != "1" ] &&
3378                 error "file under remote dir expected 1 not $projid"
3379
3380         #Agent inode should be ignored for project quota
3381         USED=$(getquota -p 1 global curinodes)
3382         [ "$USED" != "3" ] &&
3383                 error "file count expected 3 got $USED"
3384
3385         rm -rf $dir
3386         cleanup_quota_test
3387         return 0
3388 }
3389 run_test 40c "Remote child Dir inherit project quota properly"
3390
3391 test_50() {
3392         ! is_project_quota_supported &&
3393                 skip "Project quota is not supported"
3394
3395         setup_quota_test || error "setup quota failed with $?"
3396         local dir1="$DIR/$tdir/dir1"
3397         local dir2="$DIR/$tdir/dir2"
3398
3399         mkdir -p $dir1 && change_project -sp 1 $dir1
3400         mkdir -p $dir2 && change_project -sp 2 $dir2
3401         for num in $(seq 1 10); do
3402                 touch $dir1/file_$num $dir2/file_$num
3403                 ln -s $dir1/file_$num $dir1/file_$num"_link"
3404                 ln -s $dir2/file_$num $dir2/file_$num"_link"
3405         done
3406
3407         count=$($LFS find --projid 1 $DIR | wc -l)
3408         [ "$count" != 21 ] && error "expected 21 but got $count"
3409
3410         # 1(projid 0 dir) + 1(projid 2 dir) + 20(projid 2 files)
3411         count=$($LFS find ! --projid 1 $DIR/$tdir | wc -l)
3412         [ "$count" != 22 ] && error "expected 22 but got $count"
3413
3414         rm -rf $dir1 $dir2
3415         cleanup_quota_test
3416 }
3417 run_test 50 "Test if lfs find --projid works"
3418
3419 test_51() {
3420         ! is_project_quota_supported &&
3421                 skip "Project quota is not supported"
3422         setup_quota_test || error "setup quota failed with $?"
3423         local dir="$DIR/$tdir/dir"
3424
3425         mkdir $dir && change_project -sp 1 $dir
3426         local used=$(getquota -p 1 global curinodes)
3427         [ $used != "1" ] && error "expected 1 got $used"
3428
3429         touch $dir/1
3430         touch $dir/2
3431         cp $dir/2 $dir/3
3432         used=$(getquota -p 1 global curinodes)
3433         [ $used != "4" ] && error "expected 4 got $used"
3434
3435         $DD if=/dev/zero of=$DIR/$tdir/6 bs=1M count=1
3436         #try cp to dir
3437         cp $DIR/$tdir/6 $dir/6
3438         used=$(getquota -p 1 global curinodes)
3439         [ $used != "5" ] && error "expected 5 got $used"
3440
3441         #try mv to dir
3442         mv $DIR/$tdir/6 $dir/7
3443         used=$(getquota -p 1 global curinodes)
3444         [ $used != "6" ] && error "expected 6 got $used"
3445
3446         rm -rf $dir
3447         cleanup_quota_test
3448 }
3449 run_test 51 "Test project accounting with mv/cp"
3450
3451 test_52() {
3452         ! is_project_quota_supported &&
3453                 skip "Project quota is not supported"
3454         setup_quota_test || error "setup quota failed with $?"
3455         local dir="$DIR/$tdir/dir"
3456         mkdir $dir && change_project -sp 1 $dir
3457
3458         touch $DIR/$tdir/file
3459         #Try renaming a file into the project.  This should fail.
3460         for num in $(seq 1 2000); do
3461                 mrename $DIR/$tdir/file $dir/file >&/dev/null &&
3462                         error "rename should fail"
3463         done
3464         rm -rf $dir
3465         cleanup_quota_test
3466 }
3467 run_test 52 "Rename across different project ID"
3468
3469 test_53() {
3470         ! is_project_quota_supported &&
3471                 skip "Project quota is not supported"
3472         setup_quota_test || error "setup quota failed with $?"
3473         local dir="$DIR/$tdir/dir"
3474         mkdir $dir && change_project -s $dir
3475         lfs project -d $dir | grep P || error "inherit attribute should be set"
3476
3477         change_project -C $dir
3478         lfs project -d $dir | grep P &&
3479                 error "inherit attribute should be cleared"
3480
3481         rm -rf $dir
3482         cleanup_quota_test
3483 }
3484 run_test 53 "Project inherit attribute could be cleared"
3485
3486 test_54() {
3487         ! is_project_quota_supported &&
3488                 skip "Project quota is not supported"
3489         setup_quota_test || error "setup quota failed with $?"
3490         trap cleanup_quota_test EXIT
3491         local testfile="$DIR/$tdir/$tfile-0"
3492
3493         #set project ID/inherit attribute
3494         change_project -sp $TSTPRJID $DIR/$tdir
3495         $RUNAS createmany -m ${testfile} 100 ||
3496                 error "create many files failed"
3497
3498         local proj_count=$(lfs project -r $DIR/$tdir | wc -l)
3499         # one more count for directory itself */
3500         ((proj_count++))
3501
3502         #check project
3503         local proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
3504         [ $proj_count1 -eq 0 ] || error "c1: expected 0 got $proj_count1"
3505
3506         proj_count1=$(lfs project -rcp $((TSTPRJID+1)) $DIR/$tdir | wc -l)
3507         [ $proj_count1 -eq $proj_count ] ||
3508                         error "c2: expected $proj_count got $proj_count1"
3509
3510         #clear project but with kept projid
3511         change_project -rCk $DIR/$tdir
3512         proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
3513         [ $proj_count1 -eq 1 ] ||
3514                         error "c3: expected 1 got $proj_count1"
3515
3516         #verify projid untouched.
3517         proj_count1=$(lfs project -r $DIR/$tdir | grep -c $TSTPRJID)
3518         ((proj_count1++))
3519         [ $proj_count1 -eq $proj_count ] ||
3520                         error "c4: expected $proj_count got $proj_count1"
3521
3522         # test -0 option
3523         lfs project $DIR/$tdir -cr -0 | xargs -0 lfs project -s
3524         proj_count1=$(lfs project -rcp $TSTPRJID $DIR/$tdir | wc -l)
3525         [ $proj_count1 -eq 0 ] || error "c5: expected 0 got $proj_count1"
3526
3527         #this time clear all
3528         change_project -rC $DIR/$tdir
3529         proj_count1=$(lfs project -r $DIR/$tdir | grep -c $TSTPRJID)
3530         [ $proj_count1 -eq 0 ] ||
3531                         error "c6: expected 0 got $proj_count1"
3532         #cleanup
3533         unlinkmany ${testfile} 100 ||
3534                 error "unlink many files failed"
3535
3536         cleanup_quota_test
3537 }
3538 run_test 54 "basic lfs project interface test"
3539
3540 test_55() {
3541         [ "$MDS1_VERSION" -lt $(version_code 2.10.58) ] &&
3542                 skip "Not supported before 2.10.58."
3543         setup_quota_test || error "setup quota failed with $?"
3544
3545         set_ost_qtype $QTYPE || error "enable ost quota failed"
3546         quota_init
3547
3548         #add second group to TSTUSR
3549         usermod -G $TSTUSR,$TSTUSR2 $TSTUSR
3550
3551         #prepare test file
3552         $RUNAS dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1024 count=100000 ||
3553         error "failed to dd"
3554
3555         cancel_lru_locks osc
3556         sync; sync_all_data || true
3557
3558         $LFS setquota -g $TSTUSR2 -b 0 -B 50M $DIR ||
3559         error "failed to setquota on group $TSTUSR2"
3560
3561         $LFS quota -v -g $TSTUSR2 $DIR
3562
3563         runas -u $TSTUSR -g $TSTUSR2 chgrp $TSTUSR2 $DIR/$tdir/$tfile &&
3564         error "chgrp should failed with -EDQUOT"
3565
3566         USED=$(getquota -g $TSTUSR2 global curspace)
3567         echo "$USED"
3568
3569         $LFS setquota -g $TSTUSR2 -b 0 -B 300M $DIR ||
3570         error "failed to setquota on group $TSTUSR2"
3571
3572         $LFS quota -v -g $TSTUSR2 $DIR
3573
3574         runas -u $TSTUSR -g $TSTUSR2 chgrp $TSTUSR2 $DIR/$tdir/$tfile ||
3575         error "chgrp should succeed"
3576
3577         $LFS quota -v -g $TSTUSR2 $DIR
3578
3579         cleanup_quota_test
3580 }
3581 run_test 55 "Chgrp should be affected by group quota"
3582
3583 test_56() {
3584         setup_quota_test || error "setup quota failed with $?"
3585
3586         set_ost_qtype $QTYPE || error "enable ost quota failed"
3587         quota_init
3588
3589         $LFS setquota -t -u -b 10 -i 10 $DIR ||
3590                 erro "failed to set grace time for usr quota"
3591         grace_time=$($LFS quota -t -u $DIR | grep "Block grace time:" |
3592                      awk '{print $4 $8}')
3593         if [ "x$grace_time" != "x10s;10s" ]; then
3594                 $LFS quota -t -u $DIR
3595                 error "expected grace time: 10s;10s, got:$grace_time"
3596         fi
3597
3598         cleanup_quota_test
3599 }
3600 run_test 56 "lfs quota -t should work well"
3601
3602 test_57() {
3603         setup_quota_test || error "setup quota failed with $?"
3604
3605         local dir="$DIR/$tdir/dir"
3606         mkdir -p $dir
3607         mkfifo $dir/pipe
3608         #try to change pipe file should not hang and return failure
3609         wait_update_facet client "$LFS project -sp 1 $dir/pipe 2>&1 |
3610                 awk -F ':' '{ print \\\$2 }'" \
3611                         " unable to get xattr for fifo '$dir/pipe'" || return 1
3612         #command can process further if it hit some errors
3613         touch $dir/aaa $dir/bbb
3614         mkdir $dir/subdir -p
3615         touch $dir/subdir/aaa $dir/subdir/bbb
3616         #create one invalid link file
3617         ln -s $dir/not_exist_file $dir/ccc
3618         local cnt=$(lfs project -r $dir 2>/dev/null | wc -l)
3619         [ $cnt -eq 5 ] || error "expected 5 got $cnt"
3620
3621         cleanup_quota_test
3622 }
3623 run_test 57 "lfs project could tolerate errors"
3624
3625 test_59() {
3626         [ "$mds1_FSTYPE" != ldiskfs ] &&
3627                 skip "ldiskfs only test"
3628         disable_project_quota
3629         setup_quota_test || error "setup quota failed with $?"
3630         quota_init
3631
3632         local testfile="$DIR/$tdir/$tfile-0"
3633         #make sure it did not crash kernel
3634         touch $testfile && lfs project -sp 1 $testfile
3635
3636         enable_project_quota
3637         cleanup_quota_test
3638 }
3639 run_test 59 "lfs project dosen't crash kernel with project disabled"
3640
3641 test_60() {
3642         [ $MDS1_VERSION -lt $(version_code 2.11.53) ] &&
3643                 skip "Needs MDS version 2.11.53 or later."
3644         setup_quota_test || error "setup quota failed with $?"
3645         trap cleanup_quota_test EXIT
3646
3647         local testfile=$DIR/$tdir/$tfile
3648         local limit=100
3649
3650         set_mdt_qtype "ug" || error "enable mdt quota failed"
3651
3652         $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $limit $DIR ||
3653                 error "set quota failed"
3654         quota_show_check a g $TSTUSR
3655
3656         chown $TSTUSR.$TSTUSR $DIR/$tdir || error "chown $DIR/$tdir failed"
3657         chmod g+s $DIR/$tdir || error "chmod g+s failed"
3658         $RUNAS createmany -m ${testfile} $((limit-1)) ||
3659                 error "create many files failed"
3660
3661         $RUNAS touch $DIR/$tdir/foo && error "regular user should fail"
3662
3663         # root user can overrun quota
3664         runas -u 0 -g 0 touch $DIR/$tdir/foo ||
3665                 error "root user should succeed"
3666
3667         cleanup_quota_test
3668 }
3669 run_test 60 "Test quota for root with setgid"
3670
3671 # test default quota
3672 test_default_quota() {
3673         [ "$MDS1_VERSION" -lt $(version_code 2.11.51) ] &&
3674                 skip "Not supported before 2.11.51."
3675
3676         local qtype=$1
3677         local qpool=$2
3678         local qid=$TSTUSR
3679         local qprjid=$TSTPRJID
3680         local qdtype="-U"
3681         local qs="-b"
3682         local qh="-B"
3683         local LIMIT=20480 #20M disk space
3684         local TESTFILE="$DIR/$tdir/$tfile-0"
3685
3686         [ $qtype == "-p" ] && ! is_project_quota_supported &&
3687                 echo "Project quota is not supported" && return 0
3688
3689         [ $qtype == "-u" ] && qdtype="-U"
3690         [ $qtype == "-g" ] && qdtype="-G"
3691         [ $qtype == "-p" ] && {
3692                 qdtype="-P"
3693                 qid=$qprjid
3694         }
3695
3696         [ $qpool == "meta" ] && {
3697                 LIMIT=10240 #10K inodes
3698                 qs="-i"
3699                 qh="-I"
3700         }
3701
3702         setup_quota_test || error "setup quota failed with $?"
3703         trap cleanup_quota_test EXIT
3704
3705         quota_init
3706
3707         # enable mdt/ost quota
3708         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
3709         set_ost_qtype $QTYPE || error "enable ost quota failed"
3710
3711         log "set to use default quota"
3712         $LFS setquota $qtype $qid -d $DIR ||
3713                 error "set $qid to use default quota failed"
3714
3715         log "set default quota"
3716         $LFS setquota $qdtype $qs ${LIMIT} $qh ${LIMIT} $DIR ||
3717                 error "set $qid default quota failed"
3718
3719         log "get default quota"
3720         $LFS quota $qdtype $DIR || error "get default quota failed"
3721
3722         if [ $qpool == "data" ]; then
3723                 local SLIMIT=$($LFS quota $qdtype $DIR | grep "$MOUNT" | \
3724                                                         awk '{print $2}')
3725                 [ $SLIMIT -eq $LIMIT ] ||
3726                         error "the returned default quota is wrong"
3727         else
3728                 local SLIMIT=$($LFS quota $qdtype $DIR | grep "$MOUNT" | \
3729                                                         awk '{print $5}')
3730                 [ $SLIMIT -eq $LIMIT ] ||
3731                         error "the returned default quota is wrong"
3732         fi
3733
3734         # make sure the system is clean
3735         local USED=$(getquota $qtype $qid global curspace)
3736         [ $USED -ne 0 ] && error "Used space for $qid isn't 0."
3737
3738         $LFS setstripe $TESTFILE -c 1 || error "setstripe $TESTFILE failed"
3739         chown $TSTUSR.$TSTUSR $TESTFILE || error "chown $TESTFILE failed"
3740
3741         [ $qtype == "-p" ] && change_project -sp $TSTPRJID $DIR/$tdir
3742
3743         log "Test not out of quota"
3744         if [ $qpool == "data" ]; then
3745                 $RUNAS $DD of=$TESTFILE count=$((LIMIT/2 >> 10)) oflag=sync ||
3746                         quota_error $qtype $qid "write failed, expect succeed"
3747         else
3748                 $RUNAS createmany -m $TESTFILE $((LIMIT/2)) ||
3749                         quota_error $qtype $qid "create failed, expect succeed"
3750
3751                 unlinkmany $TESTFILE $((LIMIT/2))
3752         fi
3753
3754         log "Test out of quota"
3755         # flush cache, ensure noquota flag is set on client
3756         cancel_lru_locks osc
3757         cancel_lru_locks mdc
3758         sync; sync_all_data || true
3759         if [ $qpool == "data" ]; then
3760                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync &&
3761                         quota_error $qtype $qid "write succeed, expect EDQUOT"
3762         else
3763                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) &&
3764                         quota_error $qtype $qid "create succeed, expect EDQUOT"
3765
3766                 unlinkmany $TESTFILE $((LIMIT*2))
3767         fi
3768
3769         log "Increase default quota"
3770         # increase default quota
3771         $LFS setquota $qdtype $qs $((LIMIT*3)) $qh $((LIMIT*3)) $DIR ||
3772                 error "set default quota failed"
3773
3774         cancel_lru_locks osc
3775         cancel_lru_locks mdc
3776         sync; sync_all_data || true
3777         if [ $qpool == "data" ]; then
3778                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync ||
3779                         quota_error $qtype $qid "write failed, expect succeed"
3780         else
3781                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) ||
3782                         quota_error $qtype $qid "create failed, expect succeed"
3783
3784                 unlinkmany $TESTFILE $((LIMIT*2))
3785         fi
3786
3787         log "Set quota to override default quota"
3788         $LFS setquota $qtype $qid $qs ${LIMIT} $qh ${LIMIT} $DIR ||
3789                 error "set $qid quota failed"
3790
3791         cancel_lru_locks osc
3792         cancel_lru_locks mdc
3793         sync; sync_all_data || true
3794         if [ $qpool == "data" ]; then
3795                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync &&
3796                         quota_error $qtype $qid "write succeed, expect EQUOT"
3797         else
3798                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) &&
3799                         quota_error $qtype $qid "create succeed, expect EQUOT"
3800
3801                 unlinkmany $TESTFILE $((LIMIT*2))
3802         fi
3803
3804         log "Set to use default quota again"
3805         $LFS setquota $qtype $qid -d $DIR ||
3806                 error "set $qid to use default quota failed"
3807
3808         cancel_lru_locks osc
3809         cancel_lru_locks mdc
3810         sync; sync_all_data || true
3811         if [ $qpool == "data" ]; then
3812                 $RUNAS $DD of=$TESTFILE count=$((LIMIT*2 >> 10)) oflag=sync ||
3813                         quota_error $qtype $qid "write failed, expect succeed"
3814         else
3815                 $RUNAS createmany -m $TESTFILE $((LIMIT*2)) ||
3816                         quota_error $qtype $qid "create failed, expect succeed"
3817
3818                 unlinkmany $TESTFILE $((LIMIT*2))
3819         fi
3820
3821         log "Cleanup"
3822         rm -f $TESTFILE
3823         wait_delete_completed || error "wait_delete_completed failed"
3824         sync_all_data || true
3825         $LFS setquota $qdtype -b 0 -B 0 -i 0 -I 0 $DIR ||
3826                 error "reset default quota failed"
3827         $LFS setquota $qtype $qid -b 0 -B 0 -i 0 -I 0 $DIR ||
3828                 error "reset quota failed"
3829
3830         cleanup_quota_test
3831 }
3832
3833 test_61() {
3834         test_default_quota "-u" "data"
3835         test_default_quota "-u" "meta"
3836         test_default_quota "-g" "data"
3837         test_default_quota "-g" "meta"
3838         test_default_quota "-p" "data"
3839         test_default_quota "-p" "meta"
3840 }
3841 run_test 61 "default quota tests"
3842
3843 test_62() {
3844         ! is_project_quota_supported &&
3845                 skip "Project quota is not supported"
3846          [[ "$(chattr -h 2>&1)" =~ "project" ]] ||
3847                 skip "chattr did not support project quota"
3848         setup_quota_test || error "setup quota failed with $?"
3849         local testdir=$DIR/$tdir/
3850
3851         $RUNAS mkdir -p $testdir || error "failed to mkdir"
3852         change_project -s $testdir
3853         [[ $($LFS project -d $testdir) =~ "P" ]] ||
3854                 error "inherit attribute should be set"
3855         # chattr used FS_IOC_SETFLAGS ioctl
3856         $RUNAS chattr -P $testdir &&
3857                 error "regular user clear inherit should fail"
3858         [[ $($LFS project -d $testdir) =~ "P" ]] ||
3859                 error "inherit attribute should still be set"
3860         chattr -P $testdir || error "root failed to clear inherit"
3861         [[ $($LFS project -d $testdir) =~ "P" ]] &&
3862                 error "inherit attribute should be cleared"
3863         cleanup_quota_test
3864 }
3865 run_test 62 "Project inherit should be only changed by root"
3866
3867 test_dom() {
3868         [ "$MDS1_VERSION" -lt $(version_code 2.11.55) ] &&
3869                 skip "Not supported before 2.11.55"
3870
3871         local qtype=$1
3872         local qid=$TSTUSR
3873         local dd_failed=false
3874         local tdir_dom=${tdir}_dom
3875         local LIMIT=20480 #20M
3876
3877         [ $qtype == "p" ] && ! is_project_quota_supported &&
3878                 echo "Project quota is not supported" && return 0
3879
3880         [ $qtype == "p" ] && qid=$TSTPRJID
3881
3882         setup_quota_test || error "setup quota failed with $?"
3883         trap cleanup_quota_test EXIT
3884
3885         quota_init
3886
3887         # enable mdt/ost quota
3888         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
3889         set_ost_qtype $QTYPE || error "enable ost quota failed"
3890
3891         # make sure the system is clean
3892         local USED=$(getquota -$qtype $qid global curspace)
3893         [ $USED -ne 0 ] && error "Used space for $qid isn't 0."
3894
3895         chown $TSTUSR.$TSTUSR $DIR/$tdir || error "chown $tdir failed"
3896
3897         mkdir $DIR/$tdir_dom || error "mkdir $tdir_dom failed"
3898         $LFS setstripe -E 1M -L mdt $DIR/$tdir_dom ||
3899                 error "setstripe $tdir_dom failed"
3900         chown $TSTUSR.$TSTUSR $DIR/$tdir_dom || error "chown $tdir_dom failed"
3901
3902         [ $qtype == "p" ] && {
3903                 change_project -sp $TSTPRJID $DIR/$tdir
3904                 change_project -sp $TSTPRJID $DIR/$tdir_dom
3905         }
3906
3907         $LFS setquota -$qtype $qid -b $LIMIT -B $LIMIT $DIR ||
3908                 error "set $qid quota failed"
3909
3910         for ((i = 0; i < $((LIMIT/2048)); i++)); do
3911                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3912                                                                 dd_failed=true
3913         done
3914
3915         $dd_failed && quota_error $qtype $qid "write failed, expect succeed"
3916
3917         for ((i = $((LIMIT/2048)); i < $((LIMIT/1024 + 10)); i++)); do
3918                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3919                                                                 dd_failed=true
3920         done
3921
3922         $dd_failed || quota_error $qtype $qid "write succeed, expect EDQUOT"
3923
3924         rm -f $DIR/$tdir_dom/*
3925
3926         # flush cache, ensure noquota flag is set on client
3927         cancel_lru_locks osc
3928         cancel_lru_locks mdc
3929         sync; sync_all_data || true
3930
3931         dd_failed=false
3932
3933         $RUNAS $DD of=$DIR/$tdir/file count=$((LIMIT/2048)) oflag=sync ||
3934                 quota_error $qtype $qid "write failed, expect succeed"
3935
3936         for ((i = 0; i < $((LIMIT/2048 + 10)); i++)); do
3937                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3938                                                                 dd_failed=true
3939         done
3940
3941         $dd_failed || quota_error $qtype $TSTID "write succeed, expect EDQUOT"
3942
3943         rm -f $DIR/$tdir/*
3944         rm -f $DIR/$tdir_dom/*
3945
3946         # flush cache, ensure noquota flag is set on client
3947         cancel_lru_locks osc
3948         cancel_lru_locks mdc
3949         sync; sync_all_data || true
3950
3951         dd_failed=false
3952
3953         for ((i = 0; i < $((LIMIT/2048)); i++)); do
3954                 $RUNAS $DD of=$DIR/$tdir_dom/$tfile-$i count=1 oflag=sync ||
3955                                                                 dd_failed=true
3956         done
3957
3958         $dd_failed && quota_error $qtype $qid "write failed, expect succeed"
3959
3960         $RUNAS $DD of=$DIR/$tdir/file count=$((LIMIT/2048 + 10)) oflag=sync &&
3961                 quota_error $qtype $qid "write succeed, expect EDQUOT"
3962
3963         rm -f $DIR/$tdir/*
3964         rm -fr $DIR/$tdir_dom
3965
3966         $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR ||
3967                 error "reset usr quota failed"
3968
3969         cleanup_quota_test
3970 }
3971
3972 test_63() {
3973         test_dom "u"
3974         test_dom "g"
3975         test_dom "p"
3976 }
3977 run_test 63 "quota on DoM tests"
3978
3979 test_64() {
3980         ! is_project_quota_supported &&
3981                 skip "Project quota is not supported"
3982         setup_quota_test || error "setup quota failed with $?"
3983         local dir1="$DIR/$tdir/"
3984
3985         touch $dir1/file
3986         ln -s $dir1/file $dir1/file_link
3987
3988         $LFS project -sp $TSTPRJID $dir1/file_link >&/dev/null &&
3989                 error "set symlink file's project should fail"
3990
3991         $LFS project $TSTPRJID $dir1/file_link >&/dev/null &&
3992                 error "get symlink file's project should fail"
3993
3994         cleanup_quota_test
3995 }
3996 run_test 64 "lfs project on symlink files should fail"
3997
3998 test_65() {
3999         local SIZE=10 #10M
4000         local TESTFILE="$DIR/$tdir/$tfile-0"
4001
4002         setup_quota_test || error "setup quota failed with $?"
4003         set_ost_qtype $QTYPE || error "enable ost quota failed"
4004         quota_init
4005
4006         echo "Write..."
4007         $RUNAS $DD of=$TESTFILE count=$SIZE ||
4008                 error "failed to write"
4009         # flush cache, ensure noquota flag is set on client
4010         cancel_lru_locks osc
4011         sync; sync_all_data || true
4012
4013         local quota_u=$($LFS quota -u $TSTUSR $DIR)
4014         local quota_g=$($LFS quota -g $TSTUSR $DIR)
4015         local quota_all=$($RUNAS $LFS quota $DIR)
4016
4017         [ "$(echo "$quota_all" | head -n3)" != "$quota_u" ] &&
4018                 error "usr quota not match"
4019         [ "$(echo "$quota_all" | tail -n3)" != "$quota_g" ] &&
4020                 error "grp quota not match"
4021
4022         rm -f $TESTFILE
4023         # cleanup
4024         cleanup_quota_test
4025 }
4026 run_test 65 "Check lfs quota result"
4027
4028 test_66() {
4029         ! is_project_quota_supported &&
4030                 skip "Project quota is not supported"
4031         [ "$MDS1_VERSION" -lt $(version_code 2.12.4) ] &&
4032                 skip "Not supported before 2.12.4"
4033         setup_quota_test || error "setup quota failed with $?"
4034         stack_trap cleanup_quota_test EXIT
4035         local old=$(do_facet mds1 $LCTL get_param -n \
4036                     mdt.*.enable_chprojid_gid | head -1)
4037         local testdir=$DIR/$tdir/foo
4038
4039         do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=0
4040         stack_trap "do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=0" \
4041                 EXIT
4042
4043         test_mkdir -i 0 -c 1 $testdir || error "failed to mkdir"
4044         chown -R $TSTID:$TSTID $testdir
4045         change_project -sp $TSTPRJID $testdir
4046         $RUNAS mkdir $testdir/foo || error "failed to mkdir foo"
4047
4048         $RUNAS lfs project -p 0 $testdir/foo &&
4049                 error "nonroot user should fail to set projid"
4050
4051         $RUNAS lfs project -C $testdir/foo &&
4052                 error "nonroot user should fail to clear projid"
4053
4054         change_project -C $testdir/foo || error "failed to clear project"
4055
4056         do_facet mds1 $LCTL set_param mdt.*.enable_chprojid_gid=-1
4057         $RUNAS lfs project -p $TSTPRJID $testdir/foo || error \
4058         "failed to set projid with normal user when enable_chprojid_gid=-1"
4059
4060         $RUNAS lfs project -rC $testdir/ || error \
4061 "failed to clear project state with normal user when enable_chprojid_gid=-1"
4062
4063         touch $testdir/bar || error "failed touch $testdir/bar"
4064         $RUNAS lfs project -p $TSTPRJID $testdir/bar && error \
4065         "normal user should not be able to set projid on root owned file"
4066
4067         change_project -p $TSTPRJID $testdir/bar || error \
4068                 "root should be able to change its own file's projid"
4069
4070         cleanup_quota_test
4071 }
4072 run_test 66 "nonroot user can not change project state in default"
4073
4074 test_67_write() {
4075         local file="$1"
4076         local qtype="$2"
4077         local size=$3
4078         local _runas=""
4079         local short_qtype=${qtype:0:1}
4080
4081         echo "file "$file
4082         echo "0 $0 1 $1 2 $2 3 $3 4 $4"
4083         case "$4" in
4084                 quota_usr)  _runas=$RUNAS;;
4085                 quota_2usr) _runas=$RUNAS2;;
4086                 *)          error "unknown quota parameter $4";;
4087         esac
4088
4089         log "Write..."
4090         date
4091         $_runas $DD of=$file count=$size ||
4092                 quota_error $short_qtype $TSTUSR \
4093                         "$qtype write failure, but expect success"
4094         date
4095         cancel_lru_locks osc
4096         date
4097         sync; sync_all_data || true
4098         date
4099 }
4100
4101 getgranted() {
4102         local pool=$1
4103         local ptype=$2
4104         local userid=$3
4105         local qtype=$4
4106         local param=qmt.$FSNAME-QMT0000.$ptype-$pool.glb-$qtype
4107
4108         do_facet mds1 $LCTL get_param $param |
4109                 grep -A2 $userid | awk -F'[, ]*' 'NR==2{print $9}'
4110 }
4111
4112 test_67() {
4113         local limit=20  # 20M
4114         local testfile="$DIR/$tdir/$tfile-0"
4115         local testfile2="$DIR/$tdir/$tfile-1"
4116         local testfile3="$DIR/$tdir/$tfile-2"
4117         local qpool="qpool1"
4118         local used
4119         local granted
4120         local granted_mb
4121
4122         mds_supports_qp
4123         [ "$ost1_FSTYPE" == zfs ] &&
4124                 skip "ZFS grants some block space together with inode"
4125
4126         setup_quota_test || error "setup quota failed with $?"
4127         trap cleanup_quota_test EXIT
4128
4129         # enable ost quota
4130         set_ost_qtype $QTYPE || error "enable ost quota failed"
4131
4132         # test for user
4133         log "User quota (block hardlimit:$limit MB)"
4134         $LFS setquota -u $TSTUSR -b 0 -B ${limit}M -i 0 -I 0 $DIR ||
4135                 error "set user quota failed"
4136
4137         # make sure the system is clean
4138         used=$(getquota -u $TSTUSR global curspace)
4139         [ $used -ne 0 ] && error "Used space($used) for user $TSTUSR isn't 0."
4140
4141         granted=$(getgranted "0x0" "dt" $TSTID "usr")
4142         echo "granted 0x0 before write $granted"
4143
4144         # trigger reintegration
4145         local procf="osd-$(facet_fstype ost1).$FSNAME-OST*."
4146         procf=${procf}quota_slave.force_reint
4147         do_facet ost1 $LCTL set_param $procf=1 ||
4148                 error "force reintegration failed"
4149         wait_ost_reint "u" || error "reintegration failed"
4150         granted=$(getgranted "0x0" "dt" $TSTID "usr")
4151         [ $granted -ne 0 ] &&
4152                 error "Granted($granted) for $TSTUSR in $qpool isn't 0."
4153
4154         $LFS setstripe $testfile -c 1 -i 0 || error "setstripe $testfile failed"
4155         chown $TSTUSR.$TSTUSR $testfile || error "chown $testfile failed"
4156
4157         # write 10 MB to testfile
4158         test_67_write "$testfile" "user" 10 "quota_usr"
4159
4160         # create qpool and add OST1
4161         pool_add $qpool || error "pool_add failed"
4162         pool_add_targets $qpool 1 1 || error "pool_add_targets failed"
4163         # as quota_usr hasn't limits, lqe may absent. But it should be
4164         # created after the 1st direct qmt_get.
4165         used=$(getquota -u $TSTUSR global bhardlimit $qpool)
4166
4167         # check granted - should be 0, as testfile is located only on OST0
4168         granted=$(getgranted "0x0" "dt" $TSTID "usr")
4169         echo "global granted $granted"
4170         granted=$(getgranted $qpool "dt" $TSTID "usr")
4171         echo "$qpool granted $granted"
4172         [ $granted -ne 0 ] &&
4173                 error "Granted($granted) for $TSTUSR in $qpool isn't 0."
4174
4175         # add OST0 to qpool and check granted space
4176         pool_add_targets $qpool 0 1 ||
4177                 error "pool_add_targets failed"
4178         granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024))
4179         echo "Granted $granted_mb MB"
4180         #should be 10M + qunit for each OST
4181         [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] ||
4182                 error "Granted($granted_mb) for $TSTUSR in $qpool is wrong."
4183
4184         $LFS setstripe $testfile2 -c 1 -i 1 ||
4185                 error "setstripe $testfile2 failed"
4186         chown $TSTUSR2.$TSTUSR2 $testfile2 || error "chown $testfile2 failed"
4187         # Write from another user and check that qpool1
4188         # shows correct granted, despite quota_2usr hasn't limits in qpool1.
4189         test_67_write "$testfile2" "user" 10 "quota_2usr"
4190         used=$(getquota -u $TSTUSR2 global curspace $qpool)
4191         granted=$(getgranted $qpool "dt" $TSTID2 "usr")
4192         [ $granted -ne 0 ] &&
4193                 error "Granted($granted) for $TSTUSR2 in $qpool isn't 0."
4194
4195         # Granted space for quota_2usr in qpool1 should appear only
4196         # when global lqe for this user becomes enforced.
4197         $LFS setquota -u $TSTUSR2 -B ${limit}M $DIR ||
4198                 error "set user quota failed"
4199         granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024))
4200         echo "granted_mb $granted_mb"
4201         [ $granted_mb -ge 10 -a $granted_mb -lt $limit ] ||
4202                 error "Granted($granted) for $TSTUSR in $qpool is wrong."
4203
4204         $LFS setstripe $testfile3 -c 1 -i 0 ||
4205                 error "setstripe $testfile3 failed"
4206         chown $TSTUSR2.$TSTUSR2 $testfile3 || error "chown $testfile3 failed"
4207         test_67_write "$testfile3" "user" 10 "quota_2usr"
4208         granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024))
4209         echo "$testfile3 granted_mb $granted_mb"
4210         [ $granted_mb -eq $limit ] ||
4211                 error "Granted($granted_mb) for $TSTUSR2 is not equal to 20M"
4212
4213         # remove OST1 from the qpool1 and check granted space
4214         # should be 0 for TSTUSR and 10M for TSTUSR2
4215         pool_remove_target $qpool 0
4216         granted_mb=$(($(getgranted $qpool "dt" $TSTID "usr")/1024))
4217         [ $granted_mb -eq 0 ] ||
4218                 error "Granted($granted_mb) for $TSTUSR in $qpool != 0."
4219         granted_mb=$(($(getgranted $qpool "dt" $TSTID2 "usr")/1024))
4220         [ $granted_mb -eq 10 ] ||
4221                 error "Granted($granted_mb) for $TSTUSR2 is not equal to 10M"
4222
4223         rm -f $testfile
4224         wait_delete_completed || error "wait_delete_completed failed"
4225         sync_all_data || true
4226         used=$(getquota -u $TSTUSR global curspace)
4227         [ $used -ne 0 ] && quota_error u $TSTUSR \
4228                 "user quota isn't released after deletion"
4229         resetquota -u $TSTUSR
4230
4231         cleanup_quota_test
4232 }
4233 run_test 67 "quota pools recalculation"
4234
4235 get_slave_nr() {
4236         local pool=$1
4237         local qtype=$2
4238         local nr
4239
4240         do_facet mds1 $LCTL get_param -n qmt.$FSNAME-QMT0000.dt-$pool.info |
4241                 awk '/usr/ {getline; print $2}'
4242 }
4243
4244 test_68()
4245 {
4246         local qpool="qpool1"
4247
4248         mds_supports_qp
4249         setup_quota_test || error "setup quota failed with $?"
4250         stack_trap cleanup_quota_test EXIT
4251
4252         # enable ost quota
4253         set_ost_qtype $QTYPE || error "enable ost quota failed"
4254
4255         # check slave number for glbal pool
4256         local nr=$(get_slave_nr "0x0" "usr")
4257         echo "nr result $nr"
4258         [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] &&
4259                 error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)"
4260
4261         # create qpool and add OST1
4262         pool_add $qpool || error "pool_add failed"
4263         nr=$(get_slave_nr $qpool "usr")
4264         [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0"
4265
4266         # add OST1 to qpool
4267         pool_add_targets $qpool 1 1 || error "pool_add_targets failed"
4268         nr=$(get_slave_nr $qpool "usr")
4269         [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1"
4270
4271         # add OST0 to qpool
4272         pool_add_targets $qpool 0 1 || error "pool_add_targets failed"
4273         nr=$(get_slave_nr $qpool "usr")
4274         [[ $nr != 2 ]] && error "Slave number $nr for $qpool != 2"
4275
4276         # remove OST0
4277         pool_remove_target $qpool 0
4278         nr=$(get_slave_nr $qpool "usr")
4279         [[ $nr != 1 ]] && error "Slave number $nr for $qpool != 1"
4280
4281         # remove OST1
4282         pool_remove_target $qpool 1
4283         nr=$(get_slave_nr $qpool "usr")
4284         [[ $nr != 0 ]] && error "Slave number $nr for $qpool != 0"
4285
4286         # Check again that all is fine with global pool
4287         nr=$(get_slave_nr "0x0" "usr")
4288         [[ $nr != $((OSTCOUNT + MDSCOUNT)) ]] &&
4289                 error "Slave_nr $nr for global pool != ($OSTCOUNT + $MDSCOUNT)"
4290
4291         cleanup_quota_test
4292 }
4293 run_test 68 "slave number in quota pool changed after each add/remove OST"
4294
4295 test_69()
4296 {
4297         local global_limit=200  # 200M
4298         local limit=10  # 10M
4299         local testfile="$DIR/$tdir/$tfile-0"
4300         local dom0="$DIR/$tdir/dom0"
4301         local qpool="qpool1"
4302
4303         mds_supports_qp
4304         setup_quota_test || error "setup quota failed with $?"
4305         stack_trap cleanup_quota_test EXIT
4306
4307         # enable ost quota
4308         set_ost_qtype $QTYPE || error "enable ost quota failed"
4309         set_mdt_qtype $QTYPE || error "enable mdt quota failed"
4310
4311         # Save DOM only at MDT0
4312         $LFS setdirstripe -c 1 -i 0 $dom0 || error "cannot create $dom0"
4313         $LFS setstripe -E 1M $dom0 -L mdt || error "setstripe to $dom0 failed"
4314         chmod 0777 $dom0
4315         $LFS setstripe -c 1 -i 0 "$DIR/$tdir/"
4316
4317         # create qpool and add OST0
4318         pool_add $qpool || error "pool_add failed"
4319         pool_add_targets $qpool 0 0 || error "pool_add_targets failed"
4320
4321         log "User quota (block hardlimit:$global_limit MB)"
4322         $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
4323                 error "set user quota failed"
4324
4325         log "User quota (block hardlimit:$limit MB)"
4326         $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR ||
4327                 error "set user quota failed"
4328
4329         $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 oflag=sync ||
4330                 quota_error u $TSTUSR "write failed"
4331
4332         $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \
4333                 oflag=sync || quota_error u $TSTUSR "write failed"
4334
4335         $RUNAS $DD of=$testfile count=$limit || true
4336
4337         # flush cache, ensure noquota flag is set on client
4338         cancel_lru_locks osc
4339         sync; sync_all_data || true
4340
4341         # MDT0 shouldn't get EDQUOT with glimpse.
4342         $RUNAS $DD of=$testfile count=$limit seek=$limit &&
4343                 quota_error u $TSTUSR \
4344                         "user write success, but expect EDQUOT"
4345
4346         # Now all members of qpool1 should get EDQUOT. Expect success
4347         # when write to DOM on MDT0, as it belongs to global pool.
4348         $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 \
4349                 oflag=sync || quota_error u $TSTUSR "write failed"
4350
4351         $RUNAS dd if=/dev/zero of="$dom0/f1" bs=1K count=512 seek=512 \
4352                 oflag=sync || quota_error u $TSTUSR "write failed"
4353
4354         cleanup_quota_test
4355 }
4356 run_test 69 "EDQUOT at one of pools shouldn't affect DOM"
4357
4358 test_70()
4359 {
4360         local qpool="qpool1"
4361         local limit=20
4362         local err=0
4363         local bhard
4364
4365         [[ CLIENT_VERSION -lt $(version_code $VERSION_WITH_QP) ]] &&
4366                 skip "Needs a client >= $VERSION_WITH_QP"
4367
4368         setup_quota_test || error "setup quota failed with $?"
4369         stack_trap cleanup_quota_test EXIT
4370
4371         # MDS returns EFAULT for unsupported quotactl command
4372         [[ $MDS1_VERSION -lt $(version_code $VERSION_WITH_QP) ]] && err=14
4373
4374         # create qpool and add OST0
4375         pool_add $qpool || error "pool_add failed"
4376         pool_add_targets $qpool 0 0 || error "pool_add_targets failed"
4377
4378         $LFS setquota -u $TSTUSR -B ${limit}M -o $qpool $DIR
4379         rc=$?
4380         [ $rc -eq $err ] || error "setquota res $rc != $err"
4381
4382         # If MDS supports QP, check that limit was set properly.
4383         if [[ $MDS1_VERSION -ge $(version_code $VERSION_WITH_QP) ]]; then
4384                 bhard=$(getquota -u $TSTUSR global bhardlimit $qpool)
4385                 echo "hard limit $bhard limit $limit"
4386                 [ $bhard -ne $((limit*1024)) ] &&
4387                         error "bhard:$bhard for $qpool!=$((limit*1024))"
4388         fi
4389
4390         $LFS quota -u $TSTUSR --pool $qpool $DIR
4391         rc=$?
4392         [ $rc -eq $err ] || error "quota res $rc != $err"
4393
4394         cleanup_quota_test
4395 }
4396 run_test 70 "check lfs setquota/quota with a pool option"
4397
4398 quota_fini()
4399 {
4400         do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
4401         if $PQ_CLEANUP; then
4402                 disable_project_quota
4403         fi
4404 }
4405 reset_quota_settings
4406 quota_fini
4407
4408 cd $ORIG_PWD
4409 complete $SECONDS
4410 check_and_cleanup_lustre
4411 export QUOTA_AUTO=$QUOTA_AUTO_OLD
4412 exit_status