Whamcloud - gitweb
LU-19098 hsm: don't print progname twice with lhsmtool
[fs/lustre-release.git] / lustre / tests / sanity.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 # e.g. ONLY="22 23" or ONLY="`seq 32 39`" or EXCEPT="31"
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10
11 # Check Grants after these tests
12 GRANT_CHECK_LIST="$GRANT_CHECK_LIST 42a 42b 42c 42d 42e 63a 63b 64a 64b 64c 64d 64j"
13
14 OSC=${OSC:-"osc"}
15
16 CC=${CC:-cc}
17 CREATETEST=${CREATETEST:-createtest}
18 LVERIFY=${LVERIFY:-ll_dirstripe_verify}
19 OPENFILE=${OPENFILE:-openfile}
20 OPENUNLINK=${OPENUNLINK:-openunlink}
21 READS=${READS:-"reads"}
22 SOCKETSERVER=${SOCKETSERVER:-socketserver}
23 SOCKETCLIENT=${SOCKETCLIENT:-socketclient}
24 MEMHOG=${MEMHOG:-memhog}
25 DIRECTIO=${DIRECTIO:-directio}
26 ACCEPTOR_PORT=${ACCEPTOR_PORT:-988}
27 DEF_STRIPE_COUNT=-1
28 CHECK_GRANT=${CHECK_GRANT:-"yes"}
29 GRANT_CHECK_LIST=${GRANT_CHECK_LIST:-""}
30
31 TRACE=${TRACE:-""}
32 LUSTRE=${LUSTRE:-$(dirname $0)/..}
33 LUSTRE_TESTS_API_DIR=${LUSTRE_TESTS_API_DIR:-${LUSTRE}/tests/clientapi}
34 . $LUSTRE/tests/test-framework.sh
35 init_test_env "$@"
36
37 init_logging
38
39 ALWAYS_EXCEPT="$SANITY_EXCEPT "
40 always_except LU-9693  42a 42c
41 always_except LU-6493  42b
42 always_except LU-16515 118c 118d
43 always_except LU-8411  407
44 always_except LU-18032 119i
45
46 if $SHARED_KEY; then
47         always_except LU-14181 64e 64f
48         always_except LU-17127 39o
49 fi
50
51 # skip nfs tests on kernels >= 4.12.0 until they are fixed
52 if [ $LINUX_VERSION_CODE -ge $(version_code 4.12.0) ]; then
53         always_except LU-12661 817
54 fi
55 # skip cgroup tests on RHEL8.1 kernels until they are fixed
56 if (( $LINUX_VERSION_CODE >= $(version_code 4.18.0) &&
57       $LINUX_VERSION_CODE <  $(version_code 5.4.0) )); then
58         always_except LU-13063 411a
59 fi
60
61 # skip cgroup tests for kernels < v4.18.0
62 if (( $LINUX_VERSION_CODE < $(version_code 4.18.0) )); then
63         always_except LU-13063 411b
64 fi
65
66 # minutes runtime:                   5              12     8   12   15   10
67 [[ "$SLOW" = "no" ]] && EXCEPT_SLOW="27m 60i 64b 68 71 135 136 230d 300o 842"
68
69 if [[ "$mds1_FSTYPE" == "zfs" ]]; then
70         #                                               13    (min)"
71         [[ "$SLOW" == "no" ]] && EXCEPT_SLOW="$EXCEPT_SLOW 51b"
72 fi
73
74 if [[ "$ost1_FSTYPE" = "zfs" ]]; then
75         always_except LU-1941 130b 130c 130d 130e 130f 130g
76         always_except LU-9054 312
77 fi
78
79 # Check if running on specific distros to skip certain subtests
80 if [[ "$CLIENT_OS_ID_LIKE" =~ "rhel" ]]; then
81         if (( $CLIENT_OS_VERSION_CODE >= $(version_code 9.3.0) )); then
82                 # disable test_906 temporarily until rhel9.3 solves the
83                 # failure on fio io_uring I/O engine.
84                 always_except LU-17289 906
85         fi
86 fi
87
88 if [[ "$FSTYPE" = "wbcfs" ]]; then
89         # Lack of lprocfs support
90         always_except LU-18813 0f 27A 53 66 270a
91         # lack of lprocfs: osd.*.nonrotational
92         always_except LU-18813 119e 119f 119g 119h
93         # No stats (similar to openZFS)
94         always_except LU-18813 156
95         # MemFS-based OSD (wbcfs) cannot recovery from a server restart
96         always_except LU-18813 17o 27oo 27z 27F  60a 64i 232 257
97         always_except LU-18813 278 280  427 801c 818 820
98         # Symlink/CHR/SOCK/FIFO/BLK file types do not support
99         always_except LU-18813 17a 17b 17e 17g 17i 17p 21   25a
100         always_except LU-18813 25b 26a 26c 26d 26e 26f 27ga 27Q
101         always_except LU-18813 28  32e 32f 32g 32h 32m 32n  32o
102         always_except LU-18813 32p 48a 54a 54c 54d 56l 56m  56n  56rd
103         always_except LU-18813 56xb 56eb 56eg 56eh 56ei 133a 140 170b
104         always_except LU-18813 162a 226a
105         # Truncate operation is not supported yet.
106         always_except LU-18813 27p 27q 34a
107         # cross directory hardlink in DNE env
108         always_except LU-18813 31g 31l 31m
109         # FMD not expired: cannot reproduce on local testing
110         always_except LU-18813 36g
111         # Filemap is not supported yet.
112         always_except LU-18813 44f 130a 130b 130c 130d 130e 130i 430a
113         # inodes/blocks space usage accounting and statfs() is not supported
114         always_except LU-18813 51b 56ab 81b 220 413 418 806
115         # lsattr: append-only/immutable flags
116         always_except LU-18813 52a 52b
117         # xattr_list() is not implemented yet
118         always_except LU-18813 102a 102h 102i 102r 102t
119         # linkea and fid2path wrong...
120         always_except LU-18813 154B 154f 154g
121         # changelog related failures: wbcfs-target device label is not correct
122         always_except LU-18813 160 161c 161d 205a 65k 807 808 812
123         # DNE does not work well
124         always_except LU-18813 56 65e 65a 406
125         # user.job XATTR
126         always_except LU-18813 205h
127         # Exclusive open timeout
128         always_except LU-18813 208
129         # OFD access log failure
130         always_except LU-18813 165
131         # rename() operations: the source may not empty
132         # always_except LU-18813 214
133         # Data page cache has been updated during bulk write
134         always_except LU-18813 224d
135         # fid2path failure
136         always_except LU-18813 226d
137         # ladvise failure
138         always_except LU-18813 255
139         # sec related failure
140         always_except LU-18813 258
141         # DoM migration failure
142         always_except LU-18813 272
143         # Unkown reason timeout!
144         always_except LU-18813 275 277 311 410 414 419 831
145         # last_rcvd should fail
146         always_except LU-18813 313 314 315
147         # block accting is wrong...
148         always_except LU-18813 317
149         # Other timeouts
150         always_except LU-18813 200 350 398 399 403 404 408 432 433
151         # DIO locking issue?
152         always_except LU-18813 398a
153         # Layout swap is not working
154         always_except LU-18813 405
155         # Memory pressure under memcg control
156         always_except LU-18813 411
157         # rmfid in DNE and in large numbers
158         always_except LU-18813 421
159         # local testing passed but Maloo testing failed!
160         always_except LU-18813 27Cg 27U 422 424 425 426 428 429 434 442
161         # OOM failure
162         always_except LU-18813 430b 430c 431 814 833 850
163         # Expired barrier
164         always_except LU-18813 801a 801b
165         # ro is not implemented yet
166         always_except LU-18813 802b
167         # openZFS related partial page write
168         always_except LU-18813 810
169         # Quota is not supported yet...
170         always_except LU-18813 812b
171         # ldlm kunit test
172         always_except LU-18813 842
173         # fanotify does not work
174         always_except LU-18813 851
175         # MGC locks and client umount
176         always_except LU-18813 901
177         # destroy takes too much time
178         always_except LU-18813 903
179 fi
180
181 # Although every sanity.sh test has been run, we stop sooner for
182 # stability reasons. As we get farther, increment the STOP_AT value.
183 if [[ "$FSTYPE" = "wbcfs" ]]; then
184         export STOP_AT=${STOP_AT:-"440"}
185 fi
186
187 build_test_filter
188 FAIL_ON_ERROR=false
189
190 proc_regexp="/{proc,sys}/{fs,sys,kernel/debug}/{lustre,lnet}/"
191
192 cleanup() {
193         echo -n "cln.."
194         wait_update_facet client "pgrep ll_sa" "" 35 ||
195                 error "ll_sa thread is still running"
196         pgrep ll_sa > /dev/null && { echo "There are ll_sa thread not exit!"; exit 20; }
197         cleanupall ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
198 }
199 setup() {
200         echo -n "mnt.."
201         load_modules
202         setupall || exit 10
203         echo "done"
204 }
205
206 check_swap_layouts_support()
207 {
208         $LCTL get_param -n llite.*.sbi_flags | grep -q layout ||
209                 skip "Does not support layout lock."
210 }
211
212 check_swap_layout_no_dom()
213 {
214         local FOLDER=$1
215         local SUPP=$(lfs getstripe $FOLDER | grep "pattern:       mdt" | wc -l)
216         [ $SUPP -eq 0 ] || skip "layout swap does not support DOM files so far"
217 }
218
219 check_and_setup_lustre
220 DIR=${DIR:-$MOUNT}
221 assert_DIR
222
223 MAXFREE=${MAXFREE:-$((300000 * $OSTCOUNT))}
224
225 [ -f $DIR/d52a/foo ] && chattr -a $DIR/d52a/foo
226 [ -f $DIR/d52b/foo ] && chattr -i $DIR/d52b/foo
227 rm -rf $DIR/[Rdfs][0-9]*
228
229 # $RUNAS_ID may get set incorrectly somewhere else
230 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] &&
231         error "\$RUNAS_ID set to 0, but \$UID is also 0!"
232
233 check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
234
235 if [ "${ONLY}" = "MOUNT" ] ; then
236         echo "Lustre is up, please go on"
237         exit
238 fi
239
240 echo "preparing for tests involving mounts"
241 EXT2_DEV=${EXT2_DEV:-$TMP/SANITY.LOOP}
242 touch $EXT2_DEV
243 mke2fs -j -F $EXT2_DEV 8000 > /dev/null
244 echo # add a newline after mke2fs.
245
246 umask 077
247
248 OLDDEBUG=$(lctl get_param -n debug 2> /dev/null)
249
250 # ensure all internal functions know we want full debug
251 export PTLDEBUG=all
252 lctl set_param debug=$PTLDEBUG 2> /dev/null || true
253
254 test_0a() {
255         touch $DIR/$tfile
256         $CHECKSTAT -t file $DIR/$tfile || error "$tfile is not a file"
257         rm $DIR/$tfile
258         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
259 }
260 run_test 0a "touch; rm ====================="
261
262 test_0b() {
263         chmod 0755 $DIR || error "chmod 0755 $DIR failed"
264         $CHECKSTAT -p 0755 $DIR || error "$DIR permission is not 0755"
265 }
266 run_test 0b "chmod 0755 $DIR ============================="
267
268 test_0c() {
269         $LCTL get_param mdc.*.import | grep "state: FULL" ||
270                 error "import not FULL"
271         $LCTL get_param mdc.*.import | grep "target: $FSNAME-MDT" ||
272                 error "bad target"
273 }
274 run_test 0c "check import proc"
275
276 test_0d() { # LU-3397
277         [ $MGS_VERSION -lt $(version_code 2.10.57) ] &&
278                 skip "proc exports not supported before 2.10.57"
279
280         local mgs_exp="mgs.MGS.exports"
281         local client_uuid=$($LCTL get_param -n mgc.*.uuid)
282         local exp_uuid
283         local exp_client_version
284         local exp_val
285         local imp_val
286         local temp_imp=$DIR/$tfile.import
287         local temp_exp=$DIR/$tfile.export
288
289         # save mgc import file to $temp_imp
290         $LCTL get_param mgc.*.import | tee $temp_imp
291         # Check if client uuid is found in MGS export
292         for exp_uuid in $(do_facet mgs $LCTL get_param -N $mgs_exp.*.uuid); do
293                 echo $exp_uuid
294                 do_facet mgs $LCTL get_param -n $exp_uuid
295                 [[ $(do_facet mgs $LCTL get_param -n $exp_uuid) == \
296                    $client_uuid ]] && break
297         done
298         # save mgs export file to $temp_exp
299         do_facet mgs $LCTL get_param ${exp_uuid%.uuid}.export | tee $temp_exp
300
301         # Compare the value of field "connect_flags"
302         imp_val=$(grep "connect_flags" $temp_imp)
303         exp_val=$(grep "connect_flags" $temp_exp)
304         [ "$exp_val" == "$imp_val" ] ||
305                 error "export flags '$exp_val' != import flags '$imp_val'"
306
307         # Compare client versions.  Only compare top-3 fields for compatibility
308         exp_client_version=$(awk '/target_version:/ { print $2 }' $temp_exp)
309         exp_val=$(version_code $(cut -d. -f1,2,3 <<<$exp_client_version))
310         imp_val=$(version_code $(lustre_build_version client | cut -d. -f1,2,3))
311         [ "$exp_val" == "$imp_val" ] ||
312                 error "exp version '$exp_client_version'($exp_val) != " \
313                         "'$(lustre_build_version client)'($imp_val)"
314 }
315 run_test 0d "check export proc ============================="
316
317 test_0e() { # LU-13417
318         (( $MDSCOUNT > 1 )) ||
319                 skip "We need at least 2 MDTs for this test"
320
321         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
322                 skip "Need server version at least 2.14.51"
323
324         local default_lmv_count=$($LFS getdirstripe -D -c $MOUNT)
325         local default_lmv_index=$($LFS getdirstripe -D -i $MOUNT)
326
327         [ $default_lmv_count -eq 1 ] ||
328                 error "$MOUNT default stripe count $default_lmv_count"
329
330         [ $default_lmv_index -eq -1 ] ||
331                 error "$MOUNT default stripe index $default_lmv_index"
332
333         mkdir $MOUNT/$tdir.1 || error "mkdir $MOUNT/$tdir.1 failed"
334         mkdir $MOUNT/$tdir.2 || error "mkdir $MOUNT/$tdir.2 failed"
335
336         local mdt_index1=$($LFS getdirstripe -i $MOUNT/$tdir.1)
337         local mdt_index2=$($LFS getdirstripe -i $MOUNT/$tdir.2)
338
339         [ $mdt_index1 -eq $mdt_index2 ] &&
340                 error "directories are on the same MDT $mdt_index1=$mdt_index2"
341
342         rmdir $MOUNT/$tdir.1 $MOUNT/$tdir.2
343 }
344 run_test 0e "Enable DNE MDT balancing for mkdir in the ROOT"
345
346 test_1() {
347         test_mkdir $DIR/$tdir
348         test_mkdir $DIR/$tdir/d2
349         mkdir $DIR/$tdir/d2 && error "we expect EEXIST, but not returned"
350         $CHECKSTAT -t dir $DIR/$tdir/d2 || error "$tdir/d2 is not a dir"
351         rmdir $DIR/$tdir/d2
352         rmdir $DIR/$tdir
353         $CHECKSTAT -a $DIR/$tdir || error "$tdir was not removed"
354 }
355 run_test 1 "mkdir; remkdir; rmdir"
356
357 test_2() {
358         test_mkdir $DIR/$tdir
359         touch $DIR/$tdir/$tfile || error "touch $tdir/$tfile failed"
360         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "$tdir/$tfile not a file"
361         rm -r $DIR/$tdir
362         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$file is not removed"
363 }
364 run_test 2 "mkdir; touch; rmdir; check file"
365
366 test_3() {
367         test_mkdir $DIR/$tdir
368         $CHECKSTAT -t dir $DIR/$tdir || error "$tdir is not a directory"
369         touch $DIR/$tdir/$tfile
370         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "$tdir/$tfile not a file"
371         rm -r $DIR/$tdir
372         $CHECKSTAT -a $DIR/$tdir || error "$tdir is not removed"
373 }
374 run_test 3 "mkdir; touch; rmdir; check dir"
375
376 # LU-4471 - failed rmdir on remote directories still removes directory on MDT0
377 test_4() {
378         test_mkdir -i 1 $DIR/$tdir
379
380         touch $DIR/$tdir/$tfile ||
381                 error "Create file under remote directory failed"
382
383         rmdir $DIR/$tdir &&
384                 error "Expect error removing in-use dir $DIR/$tdir"
385
386         test -d $DIR/$tdir || error "Remote directory disappeared"
387
388         rm -rf $DIR/$tdir || error "remove remote dir error"
389 }
390 run_test 4 "mkdir; touch dir/file; rmdir; checkdir (expect error)"
391
392 test_5() {
393         test_mkdir $DIR/$tdir
394         test_mkdir $DIR/$tdir/d2
395         chmod 0707 $DIR/$tdir/d2 || error "chmod 0707 $tdir/d2 failed"
396         $CHECKSTAT -t dir -p 0707 $DIR/$tdir/d2 || error "$tdir/d2 not mode 707"
397         $CHECKSTAT -t dir $DIR/$tdir/d2 || error "$tdir/d2 is not a directory"
398 }
399 run_test 5 "mkdir .../d5 .../d5/d2; chmod .../d5/d2"
400
401 test_6a() {
402         touch $DIR/$tfile || error "touch $DIR/$tfile failed"
403         chmod 0666 $DIR/$tfile || error "chmod 0666 $tfile failed"
404         $CHECKSTAT -t file -p 0666 -u \#$UID $DIR/$tfile ||
405                 error "$tfile does not have perm 0666 or UID $UID"
406         $RUNAS chmod 0444 $DIR/$tfile && error "chmod $tfile worked on UID $UID"
407         $CHECKSTAT -t file -p 0666 -u \#$UID $DIR/$tfile ||
408                 error "$tfile should be 0666 and owned by UID $UID"
409 }
410 run_test 6a "touch f6a; chmod f6a; $RUNAS chmod f6a (should return error) =="
411
412 test_6c() {
413         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
414
415         touch $DIR/$tfile
416         chown $RUNAS_ID $DIR/$tfile || error "chown $RUNAS_ID $file failed"
417         $CHECKSTAT -t file -u \#$RUNAS_ID $DIR/$tfile ||
418                 error "$tfile should be owned by UID $RUNAS_ID"
419         $RUNAS chown $UID $DIR/$tfile && error "chown $UID $file succeeded"
420         $CHECKSTAT -t file -u \#$RUNAS_ID $DIR/$tfile ||
421                 error "$tfile should be owned by UID $RUNAS_ID"
422 }
423 run_test 6c "touch f6c; chown f6c; $RUNAS chown f6c (should return error) =="
424
425 test_6e() {
426         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
427
428         touch $DIR/$tfile
429         chgrp $RUNAS_ID $DIR/$tfile || error "chgrp $RUNAS_ID $file failed"
430         $CHECKSTAT -t file -u \#$UID -g \#$RUNAS_ID $DIR/$tfile ||
431                 error "$tfile should be owned by GID $UID"
432         $RUNAS chgrp $UID $DIR/$tfile && error "chgrp $UID $file succeeded"
433         $CHECKSTAT -t file -u \#$UID -g \#$RUNAS_ID $DIR/$tfile ||
434                 error "$tfile should be owned by UID $UID and GID $RUNAS_ID"
435 }
436 run_test 6e "touch+chgrp $tfile; $RUNAS chgrp $tfile (should return error)"
437
438 test_6g() {
439         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
440
441         test_mkdir $DIR/$tdir
442         chmod 777 $DIR/$tdir || error "chmod 0777 $tdir failed"
443         $RUNAS mkdir $DIR/$tdir/d || error "mkdir $tdir/d failed"
444         chmod g+s $DIR/$tdir/d || error "chmod g+s $tdir/d failed"
445         test_mkdir $DIR/$tdir/d/subdir
446         $CHECKSTAT -g \#$RUNAS_GID $DIR/$tdir/d/subdir ||
447                 error "$tdir/d/subdir should be GID $RUNAS_GID"
448         if [[ $MDSCOUNT -gt 1 ]]; then
449                 # check remote dir sgid inherite
450                 $LFS mkdir -i 0 $DIR/$tdir.local ||
451                         error "mkdir $tdir.local failed"
452                 chmod g+s $DIR/$tdir.local ||
453                         error "chmod $tdir.local failed"
454                 chgrp $RUNAS_GID $DIR/$tdir.local ||
455                         error "chgrp $tdir.local failed"
456                 $LFS mkdir -i 1 $DIR/$tdir.local/$tdir.remote ||
457                         error "mkdir $tdir.remote failed"
458                 $CHECKSTAT -g \#$RUNAS_GID $DIR/$tdir.local/$tdir.remote ||
459                         error "$tdir.remote should be owned by $UID.$RUNAS_ID"
460                 $CHECKSTAT -p 02755 $DIR/$tdir.local/$tdir.remote ||
461                         error "$tdir.remote should be mode 02755"
462         fi
463 }
464 run_test 6g "verify new dir in sgid dir inherits group"
465
466 test_6h() { # bug 7331
467         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
468
469         touch $DIR/$tfile || error "touch failed"
470         chown $RUNAS_ID:$RUNAS_GID $DIR/$tfile || error "initial chown failed"
471         $RUNAS -G$RUNAS_GID chown $RUNAS_ID:0 $DIR/$tfile &&
472                 error "chown $RUNAS_ID:0 $tfile worked as GID $RUNAS_GID"
473         $CHECKSTAT -t file -u \#$RUNAS_ID -g \#$RUNAS_GID $DIR/$tfile ||
474                 error "$tdir/$tfile should be UID $RUNAS_UID GID $RUNAS_GID"
475 }
476 run_test 6h "$RUNAS chown RUNAS_ID.0 .../$tfile (should return error)"
477
478 test_6i() {
479         (( MDS1_VERSION >= $(version_code 2.16.51) )) ||
480                 skip "Need MDS version at least 2.16.51"
481         (( $RUNAS_ID != $UID )) || skip_env "RUNAS_ID = UID = $UID"
482
483         touch $DIR/$tfile
484         chmod 444 $DIR/$tfile
485         chown $RUNAS_ID $DIR/$tfile || error "initial chown failed"
486         $RUNAS -u $RUNAS_ID -g $RUNAS_ID chgrp $RUNAS_ID $DIR/$tfile ||
487                 error "chgrp $RUNAS_ID $file failed"
488         $CHECKSTAT -t file -u \#$RUNAS_ID -g \#$RUNAS_ID $DIR/$tfile ||
489                 error "$tfile should be owned by GID $RUNAS_ID"
490 }
491 run_test 6i "touch+chmod+chgrp $tfile; chgrp read-only file should succeed"
492
493 test_7a() {
494         test_mkdir $DIR/$tdir
495         $MCREATE $DIR/$tdir/$tfile
496         chmod 0666 $DIR/$tdir/$tfile
497         $CHECKSTAT -t file -p 0666 $DIR/$tdir/$tfile ||
498                 error "$tdir/$tfile should be mode 0666"
499 }
500 run_test 7a "mkdir .../d7; mcreate .../d7/f; chmod .../d7/f ===="
501
502 test_7b() {
503         if [ ! -d $DIR/$tdir ]; then
504                 test_mkdir $DIR/$tdir
505         fi
506         $MCREATE $DIR/$tdir/$tfile
507         echo -n foo > $DIR/$tdir/$tfile
508         [ "$(cat $DIR/$tdir/$tfile)" = "foo" ] || error "$tdir/$tfile not 'foo'"
509         $CHECKSTAT -t file -s 3 $DIR/$tdir/$tfile || error "$tfile size not 3"
510 }
511 run_test 7b "mkdir .../d7; mcreate d7/f2; echo foo > d7/f2 ====="
512
513 test_8() {
514         test_mkdir $DIR/$tdir
515         touch $DIR/$tdir/$tfile
516         chmod 0666 $DIR/$tdir/$tfile
517         $CHECKSTAT -t file -p 0666 $DIR/$tdir/$tfile ||
518                 error "$tfile mode not 0666"
519 }
520 run_test 8 "mkdir .../d8; touch .../d8/f; chmod .../d8/f ======="
521
522 test_9() {
523         test_mkdir $DIR/$tdir
524         test_mkdir $DIR/$tdir/d2
525         test_mkdir $DIR/$tdir/d2/d3
526         $CHECKSTAT -t dir $DIR/$tdir/d2/d3 || error "$tdir/d2/d3 not a dir"
527 }
528 run_test 9 "mkdir .../d9 .../d9/d2 .../d9/d2/d3 ================"
529
530 test_10() {
531         test_mkdir $DIR/$tdir
532         test_mkdir $DIR/$tdir/d2
533         touch $DIR/$tdir/d2/$tfile
534         $CHECKSTAT -t file $DIR/$tdir/d2/$tfile ||
535                 error "$tdir/d2/$tfile not a file"
536 }
537 run_test 10 "mkdir .../d10 .../d10/d2; touch .../d10/d2/f ======"
538
539 test_11() {
540         test_mkdir $DIR/$tdir
541         test_mkdir $DIR/$tdir/d2
542         chmod 0666 $DIR/$tdir/d2
543         chmod 0705 $DIR/$tdir/d2
544         $CHECKSTAT -t dir -p 0705 $DIR/$tdir/d2 ||
545                 error "$tdir/d2 mode not 0705"
546 }
547 run_test 11 "mkdir .../d11 d11/d2; chmod .../d11/d2 ============"
548
549 test_12() {
550         test_mkdir $DIR/$tdir
551         touch $DIR/$tdir/$tfile
552         chmod 0666 $DIR/$tdir/$tfile
553         chmod 0654 $DIR/$tdir/$tfile
554         $CHECKSTAT -t file -p 0654 $DIR/$tdir/$tfile ||
555                 error "$tdir/d2 mode not 0654"
556 }
557 run_test 12 "touch .../d12/f; chmod .../d12/f .../d12/f ========"
558
559 test_13() {
560         test_mkdir $DIR/$tdir
561         dd if=/dev/zero of=$DIR/$tdir/$tfile count=10
562         >  $DIR/$tdir/$tfile
563         $CHECKSTAT -t file -s 0 $DIR/$tdir/$tfile ||
564                 error "$tdir/$tfile size not 0 after truncate"
565 }
566 run_test 13 "creat .../d13/f; dd .../d13/f; > .../d13/f ========"
567
568 test_14() {
569         test_mkdir $DIR/$tdir
570         touch $DIR/$tdir/$tfile
571         rm $DIR/$tdir/$tfile
572         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$tfile not removed"
573 }
574 run_test 14 "touch .../d14/f; rm .../d14/f; rm .../d14/f ======="
575
576 test_15() {
577         test_mkdir $DIR/$tdir
578         touch $DIR/$tdir/$tfile
579         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}_2
580         $CHECKSTAT -t file $DIR/$tdir/${tfile}_2 ||
581                 error "$tdir/${tfile_2} not a file after rename"
582         rm $DIR/$tdir/${tfile}_2 || error "unlink failed after rename"
583 }
584 run_test 15 "touch .../d15/f; mv .../d15/f .../d15/f2 =========="
585
586 test_16() {
587         test_mkdir $DIR/$tdir
588         touch $DIR/$tdir/$tfile
589         rm -rf $DIR/$tdir/$tfile
590         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$tfile not removed"
591 }
592 run_test 16 "touch .../d16/f; rm -rf .../d16/f"
593
594 test_17a() {
595         test_mkdir $DIR/$tdir
596         touch $DIR/$tdir/$tfile
597         ln -s $DIR/$tdir/$tfile $DIR/$tdir/l-exist
598         ls -l $DIR/$tdir
599         $CHECKSTAT -l $DIR/$tdir/$tfile $DIR/$tdir/l-exist ||
600                 error "$tdir/l-exist not a symlink"
601         $CHECKSTAT -f -t f $DIR/$tdir/l-exist ||
602                 error "$tdir/l-exist not referencing a file"
603         rm -f $DIR/$tdir/l-exist
604         $CHECKSTAT -a $DIR/$tdir/l-exist || error "$tdir/l-exist not removed"
605 }
606 run_test 17a "symlinks: create, remove (real)"
607
608 test_17b() {
609         test_mkdir $DIR/$tdir
610         ln -s no-such-file $DIR/$tdir/l-dangle
611         ls -l $DIR/$tdir
612         $CHECKSTAT -l no-such-file $DIR/$tdir/l-dangle ||
613                 error "$tdir/l-dangle not referencing no-such-file"
614         $CHECKSTAT -fa $DIR/$tdir/l-dangle ||
615                 error "$tdir/l-dangle not referencing non-existent file"
616         rm -f $DIR/$tdir/l-dangle
617         $CHECKSTAT -a $DIR/$tdir/l-dangle || error "$tdir/l-dangle not removed"
618 }
619 run_test 17b "symlinks: create, remove (dangling)"
620
621 test_17c() { # bug 3440 - don't save failed open RPC for replay
622         test_mkdir $DIR/$tdir
623         ln -s foo $DIR/$tdir/$tfile
624         cat $DIR/$tdir/$tfile && error "opened non-existent symlink" || true
625 }
626 run_test 17c "symlinks: open dangling (should return error)"
627
628 test_17d() {
629         test_mkdir $DIR/$tdir
630         ln -s foo $DIR/$tdir/$tfile
631         touch $DIR/$tdir/$tfile || error "creating to new symlink"
632 }
633 run_test 17d "symlinks: create dangling"
634
635 test_17e() {
636         test_mkdir $DIR/$tdir
637         local foo=$DIR/$tdir/$tfile
638         ln -s $foo $foo || error "create symlink failed"
639         ls -l $foo || error "ls -l failed"
640         ls $foo && error_ignore LU-18093 "ls not failed" || true
641 }
642 run_test 17e "symlinks: create recursive symlink (should return error)"
643
644 test_17f() {
645         test_mkdir $DIR/$tdir
646         ln -s 1234567890/2234567890/3234567890/4234567890 $DIR/$tdir/111
647         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890 $DIR/$tdir/222
648         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890 $DIR/$tdir/333
649         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890/9234567890/a234567890/b234567890 $DIR/$tdir/444
650         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890/9234567890/a234567890/b234567890/c234567890/d234567890/f234567890 $DIR/$tdir/555
651         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890/9234567890/a234567890/b234567890/c234567890/d234567890/f234567890/aaaaaaaaaa/bbbbbbbbbb/cccccccccc/dddddddddd/eeeeeeeeee/ffffffffff/ $DIR/$tdir/666
652         ls -l  $DIR/$tdir
653 }
654 run_test 17f "symlinks: long and very long symlink name"
655
656 # str_repeat(S, N) generate a string that is string S repeated N times
657 str_repeat() {
658         local s=$1
659         local n=$2
660         local ret=''
661         while [ $((n -= 1)) -ge 0 ]; do
662                 ret=$ret$s
663         done
664         echo $ret
665 }
666
667 # Long symlinks and LU-2241
668 test_17g() {
669         test_mkdir $DIR/$tdir
670         local TESTS="59 60 61 4094 4095"
671
672         # Fix for inode size boundary in 2.1.4
673         [ $MDS1_VERSION -lt $(version_code 2.1.4) ] &&
674                 TESTS="4094 4095"
675
676         # Patch not applied to 2.2 or 2.3 branches
677         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] &&
678         [ $MDS1_VERSION -le $(version_code 2.3.55) ] &&
679                 TESTS="4094 4095"
680
681         for i in $TESTS; do
682                 local SYMNAME=$(str_repeat 'x' $i)
683                 ln -s $SYMNAME $DIR/$tdir/f$i || error "failed $i-char symlink"
684                 readlink $DIR/$tdir/f$i || error "failed $i-char readlink"
685         done
686 }
687 run_test 17g "symlinks: really long symlink name and inode boundaries"
688
689 test_17h() { #bug 17378
690         [ $PARALLEL == "yes" ] && skip "skip parallel run"
691         remote_mds_nodsh && skip "remote MDS with nodsh"
692
693         local mdt_idx
694
695         test_mkdir $DIR/$tdir
696         mdt_idx=$($LFS getdirstripe -i $DIR/$tdir)
697         $LFS setstripe -c -1 $DIR/$tdir
698         #define OBD_FAIL_MDS_LOV_PREP_CREATE 0x141
699         do_facet mds$((mdt_idx + 1)) lctl set_param fail_loc=0x80000141
700         touch $DIR/$tdir/$tfile || true
701 }
702 run_test 17h "create objects: lov_free_memmd() doesn't lbug"
703
704 test_17i() { #bug 20018
705         [ $PARALLEL == "yes" ] && skip "skip parallel run"
706         remote_mds_nodsh && skip "remote MDS with nodsh"
707
708         local foo=$DIR/$tdir/$tfile
709         local mdt_idx
710
711         test_mkdir -c1 $DIR/$tdir
712         mdt_idx=$($LFS getdirstripe -i $DIR/$tdir)
713         ln -s $foo $foo || error "create symlink failed"
714 #define OBD_FAIL_MDS_READLINK_EPROTO     0x143
715         do_facet mds$((mdt_idx + 1)) lctl set_param fail_loc=0x80000143
716         ls -l $foo && error "error not detected"
717         return 0
718 }
719 run_test 17i "don't panic on short symlink (should return error)"
720
721 test_17k() { #bug 22301
722         [ $PARALLEL == "yes" ] && skip "skip parallel run"
723         [[ -z "$(which rsync 2>/dev/null)" ]] &&
724                 skip "no rsync command"
725         rsync --help | grep -q xattr ||
726                 skip_env "$(rsync --version | head -n1) does not support xattrs"
727         test_mkdir $DIR/$tdir
728         test_mkdir $DIR/$tdir.new
729         touch $DIR/$tdir/$tfile
730         ln -s $DIR/$tdir/$tfile $DIR/$tdir/$tfile.lnk
731         rsync -av -X $DIR/$tdir/ $DIR/$tdir.new ||
732                 error "rsync failed with xattrs enabled"
733 }
734 run_test 17k "symlinks: rsync with xattrs enabled"
735
736 test_17l() { # LU-279
737         [[ -z "$(which getfattr 2>/dev/null)" ]] &&
738                 skip "no getfattr command"
739
740         test_mkdir $DIR/$tdir
741         touch $DIR/$tdir/$tfile
742         ln -s $DIR/$tdir/$tfile $DIR/$tdir/$tfile.lnk
743         for path in "$DIR/$tdir" "$DIR/$tdir/$tfile" "$DIR/$tdir/$tfile.lnk"; do
744                 # -h to not follow symlinks. -m '' to list all the xattrs.
745                 # grep to remove first line: '# file: $path'.
746                 for xattr in `getfattr -hm '' $path 2>/dev/null | grep -v '^#'`;
747                 do
748                         lgetxattr_size_check $path $xattr ||
749                                 error "lgetxattr_size_check $path $xattr failed"
750                 done
751         done
752 }
753 run_test 17l "Ensure lgetxattr's returned xattr size is consistent"
754
755 # LU-1540
756 test_17m() {
757         [ $PARALLEL == "yes" ] && skip "skip parallel run"
758         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
759         remote_mds_nodsh && skip "remote MDS with nodsh"
760         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] &&
761         [ $MDS1_VERSION -le $(version_code 2.2.93) ] &&
762                 skip "MDS 2.2.0-2.2.93 do not NUL-terminate symlinks"
763
764         local short_sym="0123456789"
765         local wdir=$DIR/$tdir
766         local i
767
768         test_mkdir $wdir
769         long_sym=$short_sym
770         # create a long symlink file
771         for ((i = 0; i < 4; ++i)); do
772                 long_sym=${long_sym}${long_sym}
773         done
774
775         echo "create 512 short and long symlink files under $wdir"
776         for ((i = 0; i < 256; ++i)); do
777                 ln -sf ${long_sym}"a5a5" $wdir/long-$i
778                 ln -sf ${short_sym}"a5a5" $wdir/short-$i
779         done
780
781         echo "erase them"
782         rm -f $wdir/*
783         sync
784         wait_delete_completed
785
786         echo "recreate the 512 symlink files with a shorter string"
787         for ((i = 0; i < 512; ++i)); do
788                 # rewrite the symlink file with a shorter string
789                 ln -sf ${long_sym} $wdir/long-$i || error "long_sym failed"
790                 ln -sf ${short_sym} $wdir/short-$i || error "short_sym failed"
791         done
792
793         local mds_index=$(($($LFS getstripe -m $wdir) + 1))
794
795         echo "stop and checking mds${mds_index}:"
796         # e2fsck should not return error
797         stop mds${mds_index}
798         local devname=$(mdsdevname $mds_index)
799         run_e2fsck $(facet_active_host mds${mds_index}) $devname -n
800         rc=$?
801
802         start mds${mds_index} $devname $MDS_MOUNT_OPTS ||
803                 error "start mds${mds_index} failed"
804         df $MOUNT > /dev/null 2>&1
805         [ $rc -eq 0 ] ||
806                 error "e2fsck detected error for short/long symlink: rc=$rc"
807         rm -f $wdir/*
808 }
809 run_test 17m "run e2fsck against MDT which contains short/long symlink"
810
811 check_fs_consistency_17n() {
812         local mdt_index
813         local rc=0
814
815         # create/unlink in 17n only change 2 MDTs(MDT1/MDT2),
816         # so it only check MDT1/MDT2 instead of all of MDTs.
817         for mdt_index in 1 2; do
818                 # e2fsck should not return error
819                 stop mds${mdt_index}
820                 local devname=$(mdsdevname $mdt_index)
821                 run_e2fsck $(facet_active_host mds$mdt_index) $devname -n ||
822                         rc=$((rc + $?))
823
824                 start mds${mdt_index} $devname $MDS_MOUNT_OPTS ||
825                         error "mount mds$mdt_index failed"
826                 df $MOUNT > /dev/null 2>&1
827         done
828         return $rc
829 }
830
831 test_17n() {
832         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
833         [ $PARALLEL == "yes" ] && skip "skip parallel run"
834         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
835         remote_mds_nodsh && skip "remote MDS with nodsh"
836         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] &&
837         [ $MDS1_VERSION -le $(version_code 2.2.93) ] &&
838                 skip "MDS 2.2.0-2.2.93 do not NUL-terminate symlinks"
839
840         local i
841
842         test_mkdir $DIR/$tdir
843         for ((i=0; i<10; i++)); do
844                 $LFS mkdir -i1 -c2 $DIR/$tdir/remote_dir_${i} ||
845                         error "create remote dir error $i"
846                 createmany -o $DIR/$tdir/remote_dir_${i}/f 10 ||
847                         error "create files under remote dir failed $i"
848         done
849
850         check_fs_consistency_17n ||
851                 error "e2fsck report error after create files under remote dir"
852
853         for ((i = 0; i < 10; i++)); do
854                 rm -rf $DIR/$tdir/remote_dir_${i} ||
855                         error "destroy remote dir error $i"
856         done
857
858         check_fs_consistency_17n ||
859                 error "e2fsck report error after unlink files under remote dir"
860
861         [ $MDS1_VERSION -lt $(version_code 2.4.50) ] &&
862                 skip "lustre < 2.4.50 does not support migrate mv"
863
864         for ((i = 0; i < 10; i++)); do
865                 mkdir -p $DIR/$tdir/remote_dir_${i}
866                 createmany -o $DIR/$tdir/remote_dir_${i}/f 10 ||
867                         error "create files under remote dir failed $i"
868                 $LFS migrate --mdt-index 1 $DIR/$tdir/remote_dir_${i} ||
869                         error "migrate remote dir error $i"
870         done
871         check_fs_consistency_17n || error "e2fsck report error after migration"
872
873         for ((i = 0; i < 10; i++)); do
874                 rm -rf $DIR/$tdir/remote_dir_${i} ||
875                         error "destroy remote dir error $i"
876         done
877
878         check_fs_consistency_17n || error "e2fsck report error after unlink"
879 }
880 run_test 17n "run e2fsck against master/slave MDT which contains remote dir"
881
882 test_17o() {
883         remote_mds_nodsh && skip "remote MDS with nodsh"
884         [ $MDS1_VERSION -lt $(version_code 2.3.64) ] &&
885                 skip "Need MDS version at least 2.3.64"
886
887         local wdir=$DIR/${tdir}o
888         local mdt_index
889         local rc=0
890
891         test_mkdir $wdir
892         touch $wdir/$tfile
893         mdt_index=$($LFS getstripe -m $wdir/$tfile)
894         mdt_index=$((mdt_index + 1))
895
896         cancel_lru_locks mdc
897         #fail mds will wait the failover finish then set
898         #following fail_loc to avoid interfer the recovery process.
899         fail mds${mdt_index}
900
901         #define OBD_FAIL_OSD_LMA_INCOMPAT 0x194
902         do_facet mds${mdt_index} lctl set_param fail_loc=0x194
903         ls -l $wdir/$tfile && rc=1
904         do_facet mds${mdt_index} lctl set_param fail_loc=0
905         [[ $rc -eq 0 ]] || error "stat file should fail"
906 }
907 run_test 17o "stat file with incompat LMA feature"
908
909 # LU-17660: "cannot overwrite directory" when creating symlink
910 test_17p() {
911         touch $DIR/$tfile
912         test_mkdir $DIR/$tdir
913
914         # there is a kernel bug in el9.x series (9.0 - 9.4 as we know till now)
915         # kernel, we need to stat the target dir to cache it first
916         if [[ "$CLIENT_OS_ID_LIKE" =~ "rhel" ]]; then
917                 if (( $CLIENT_OS_VERSION_CODE >= $(version_code 9.0) &&
918                       $CLIENT_OS_VERSION_CODE <= $(version_code 9.5) )); then
919                         echo "stat $DIR/$tdir to cache it in el9.0-9.5"
920                         stat $DIR/$tdir
921                 fi
922         fi
923
924         strace ln -sf $DIR/$tfile $DIR/$tdir/ ||
925                 error "Failed to create symlink $DIR/$tfile under $DIR/$tdir/"
926 }
927 run_test 17p "symlink overwrite directory error message"
928
929 test_18() {
930         touch $DIR/$tfile || error "Failed to touch $DIR/$tfile: $?"
931         ls $DIR || error "Failed to ls $DIR: $?"
932 }
933 run_test 18 "touch .../f ; ls ... =============================="
934
935 test_19a() {
936         touch $DIR/$tfile
937         ls -l $DIR
938         rm $DIR/$tfile
939         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
940 }
941 run_test 19a "touch .../f19 ; ls -l ... ; rm .../f19 ==========="
942
943 test_19b() {
944         ls -l $DIR/$tfile && error "ls -l $tfile failed"|| true
945 }
946 run_test 19b "ls -l .../f19 (should return error) =============="
947
948 test_19c() {
949         [ $RUNAS_ID -eq $UID ] &&
950                 skip_env "RUNAS_ID = UID = $UID -- skipping"
951
952         $RUNAS touch $DIR/$tfile && error "create non-root file failed" || true
953 }
954 run_test 19c "$RUNAS touch .../f19 (should return error) =="
955
956 test_19d() {
957         cat $DIR/f19 && error || true
958 }
959 run_test 19d "cat .../f19 (should return error) =============="
960
961 test_20() {
962         touch $DIR/$tfile
963         rm $DIR/$tfile
964         touch $DIR/$tfile
965         rm $DIR/$tfile
966         touch $DIR/$tfile
967         rm $DIR/$tfile
968         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
969 }
970 run_test 20 "touch .../f ; ls -l ..."
971
972 test_21() {
973         test_mkdir $DIR/$tdir
974         [ -f $DIR/$tdir/dangle ] && rm -f $DIR/$tdir/dangle
975         ln -s dangle $DIR/$tdir/link
976         echo foo >> $DIR/$tdir/link
977         cat $DIR/$tdir/dangle
978         $CHECKSTAT -t link $DIR/$tdir/link || error "$tdir/link not a link"
979         $CHECKSTAT -f -t file $DIR/$tdir/link ||
980                 error "$tdir/link not linked to a file"
981 }
982 run_test 21 "write to dangling link"
983
984 test_22() {
985         local wdir=$DIR/$tdir
986         test_mkdir $wdir
987         chown $RUNAS_ID:$RUNAS_GID $wdir
988         (cd $wdir || error "cd $wdir failed";
989                 $RUNAS tar cf - /etc/hosts /etc/sysconfig/network |
990                 $RUNAS tar xf -)
991         ls -lR $wdir/etc || error "ls -lR $wdir/etc failed"
992         $CHECKSTAT -t dir $wdir/etc || error "checkstat -t dir failed"
993         $CHECKSTAT -u \#$RUNAS_ID -g \#$RUNAS_GID $wdir/etc ||
994                 error "checkstat -u failed"
995 }
996 run_test 22 "unpack tar archive as non-root user"
997
998 # was test_23
999 test_23a() {
1000         test_mkdir $DIR/$tdir
1001         local file=$DIR/$tdir/$tfile
1002
1003         openfile -f O_CREAT:O_EXCL $file || error "$file create failed"
1004         openfile -f O_CREAT:O_EXCL $file &&
1005                 error "$file recreate succeeded" || true
1006 }
1007 run_test 23a "O_CREAT|O_EXCL in subdir"
1008
1009 test_23b() { # bug 18988
1010         test_mkdir $DIR/$tdir
1011         local file=$DIR/$tdir/$tfile
1012
1013         rm -f $file
1014         echo foo > $file || error "write filed"
1015         echo bar >> $file || error "append filed"
1016         $CHECKSTAT -s 8 $file || error "wrong size"
1017         rm $file
1018 }
1019 run_test 23b "O_APPEND check"
1020
1021 # LU-9409, size with O_APPEND and tiny writes
1022 test_23c() {
1023         local file=$DIR/$tfile
1024
1025         # single dd
1026         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800
1027         $CHECKSTAT -s 6400 $file || error "wrong size, expected 6400"
1028         rm -f $file
1029
1030         # racing tiny writes
1031         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800 &
1032         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800 &
1033         wait
1034         $CHECKSTAT -s 12800 $file || error "wrong size, expected 12800"
1035         rm -f $file
1036
1037         #racing tiny & normal writes
1038         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=4096 count=4 &
1039         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=100 &
1040         wait
1041         $CHECKSTAT -s 17184 $file || error "wrong size, expected 17184"
1042         rm -f $file
1043
1044         #racing tiny & normal writes 2, ugly numbers
1045         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=4099 count=11 &
1046         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=17 count=173 &
1047         wait
1048         $CHECKSTAT -s 48030 $file || error "wrong size, expected 48030"
1049         rm -f $file
1050 }
1051 run_test 23c "O_APPEND size checks for tiny writes"
1052
1053 # LU-11069 file offset is correct after appending writes
1054 test_23d() {
1055         local file=$DIR/$tfile
1056         local offset
1057
1058         echo CentaurHauls > $file
1059         offset=$($MULTIOP $file oO_WRONLY:O_APPEND:w13Zp)
1060         if ((offset != 26)); then
1061                 error "wrong offset, expected 26, got '$offset'"
1062         fi
1063 }
1064 run_test 23d "file offset is correct after appending writes"
1065
1066 # rename sanity
1067 test_24a() {
1068         echo '-- same directory rename'
1069         test_mkdir $DIR/$tdir
1070         touch $DIR/$tdir/$tfile.1
1071         mv $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
1072         $CHECKSTAT -t file $DIR/$tdir/$tfile.2 || error "$tfile.2 not a file"
1073 }
1074 run_test 24a "rename file to non-existent target"
1075
1076 test_24b() {
1077         test_mkdir $DIR/$tdir
1078         touch $DIR/$tdir/$tfile.{1,2}
1079         mv $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
1080         $CHECKSTAT -a $DIR/$tdir/$tfile.1 || error "$tfile.1 exists"
1081         $CHECKSTAT -t file $DIR/$tdir/$tfile.2 || error "$tfile.2 not a file"
1082 }
1083 run_test 24b "rename file to existing target"
1084
1085 test_24c() {
1086         test_mkdir $DIR/$tdir
1087         test_mkdir $DIR/$tdir/d$testnum.1
1088         mv $DIR/$tdir/d$testnum.1 $DIR/$tdir/d$testnum.2
1089         $CHECKSTAT -a $DIR/$tdir/d$testnum.1 || error "d$testnum.1 exists"
1090         $CHECKSTAT -t dir $DIR/$tdir/d$testnum.2 || error "d$testnum.2 not dir"
1091 }
1092 run_test 24c "rename directory to non-existent target"
1093
1094 test_24d() {
1095         test_mkdir -c1 $DIR/$tdir
1096         test_mkdir -c1 $DIR/$tdir/d$testnum.1
1097         test_mkdir -c1 $DIR/$tdir/d$testnum.2
1098         mrename $DIR/$tdir/d$testnum.1 $DIR/$tdir/d$testnum.2
1099         $CHECKSTAT -a $DIR/$tdir/d$testnum.1 || error "d$testnum.1 exists"
1100         $CHECKSTAT -t dir $DIR/$tdir/d$testnum.2 || error "d$testnum.2 not dir"
1101 }
1102 run_test 24d "rename directory to existing target"
1103
1104 test_24e() {
1105         echo '-- cross directory renames --'
1106         test_mkdir $DIR/R5a
1107         test_mkdir $DIR/R5b
1108         touch $DIR/R5a/f
1109         mv $DIR/R5a/f $DIR/R5b/g
1110         $CHECKSTAT -a $DIR/R5a/f || error "$DIR/R5a/f exists"
1111         $CHECKSTAT -t file $DIR/R5b/g || error "$DIR/R5b/g not file type"
1112 }
1113 run_test 24e "touch .../R5a/f; rename .../R5a/f .../R5b/g ======"
1114
1115 test_24f() {
1116         test_mkdir $DIR/R6a
1117         test_mkdir $DIR/R6b
1118         touch $DIR/R6a/f $DIR/R6b/g
1119         mv $DIR/R6a/f $DIR/R6b/g
1120         $CHECKSTAT -a $DIR/R6a/f || error "$DIR/R6a/f exists"
1121         $CHECKSTAT -t file $DIR/R6b/g || error "$DIR/R6b/g not file type"
1122 }
1123 run_test 24f "touch .../R6a/f R6b/g; mv .../R6a/f .../R6b/g ===="
1124
1125 test_24g() {
1126         test_mkdir $DIR/R7a
1127         test_mkdir $DIR/R7b
1128         test_mkdir $DIR/R7a/d
1129         mv $DIR/R7a/d $DIR/R7b/e
1130         $CHECKSTAT -a $DIR/R7a/d || error "$DIR/R7a/d exists"
1131         $CHECKSTAT -t dir $DIR/R7b/e || error "$DIR/R7b/e not dir type"
1132 }
1133 run_test 24g "mkdir .../R7{a,b}/d; mv .../R7a/d .../R7b/e ======"
1134
1135 test_24h() {
1136         test_mkdir -c1 $DIR/R8a
1137         test_mkdir -c1 $DIR/R8b
1138         test_mkdir -c1 $DIR/R8a/d
1139         test_mkdir -c1 $DIR/R8b/e
1140         mrename $DIR/R8a/d $DIR/R8b/e
1141         $CHECKSTAT -a $DIR/R8a/d || error "$DIR/R8a/d exists"
1142         $CHECKSTAT -t dir $DIR/R8b/e || error "$DIR/R8b/e not dir type"
1143 }
1144 run_test 24h "mkdir .../R8{a,b}/{d,e}; rename .../R8a/d .../R8b/e"
1145
1146 test_24i() {
1147         echo "-- rename error cases"
1148         test_mkdir $DIR/R9
1149         test_mkdir $DIR/R9/a
1150         touch $DIR/R9/f
1151         mrename $DIR/R9/f $DIR/R9/a
1152         $CHECKSTAT -t file $DIR/R9/f || error "$DIR/R9/f not file type"
1153         $CHECKSTAT -t dir  $DIR/R9/a || error "$DIR/R9/a not dir type"
1154         $CHECKSTAT -a $DIR/R9/a/f || error "$DIR/R9/a/f exists"
1155 }
1156 run_test 24i "rename file to dir error: touch f ; mkdir a ; rename f a"
1157
1158 test_24j() {
1159         test_mkdir $DIR/R10
1160         mrename $DIR/R10/f $DIR/R10/g
1161         $CHECKSTAT -t dir $DIR/R10 || error "$DIR/R10 not dir type"
1162         $CHECKSTAT -a $DIR/R10/f || error "$DIR/R10/f exists"
1163         $CHECKSTAT -a $DIR/R10/g || error "$DIR/R10/g exists"
1164 }
1165 run_test 24j "source does not exist ============================"
1166
1167 test_24k() {
1168         test_mkdir $DIR/R11a
1169         test_mkdir $DIR/R11a/d
1170         touch $DIR/R11a/f
1171         mv $DIR/R11a/f $DIR/R11a/d
1172         $CHECKSTAT -a $DIR/R11a/f || error "$DIR/R11a/f exists"
1173         $CHECKSTAT -t file $DIR/R11a/d/f || error "$DIR/R11a/d/f not file type"
1174 }
1175 run_test 24k "touch .../R11a/f; mv .../R11a/f .../R11a/d ======="
1176
1177 # bug 2429 - rename foo foo foo creates invalid file
1178 test_24l() {
1179         f="$DIR/f24l"
1180         $MULTIOP $f OcNs || error "rename of ${f} to itself failed"
1181 }
1182 run_test 24l "Renaming a file to itself ========================"
1183
1184 test_24m() {
1185         f="$DIR/f24m"
1186         $MULTIOP $f OcLN ${f}2 ${f}2 || error "link ${f}2 ${f}2 failed"
1187         # on ext3 this does not remove either the source or target files
1188         # though the "expected" operation would be to remove the source
1189         $CHECKSTAT -t file ${f} || error "${f} missing"
1190         $CHECKSTAT -t file ${f}2 || error "${f}2 missing"
1191 }
1192 run_test 24m "Renaming a file to a hard link to itself ========="
1193
1194 test_24n() {
1195     f="$DIR/f24n"
1196     # this stats the old file after it was renamed, so it should fail
1197     touch ${f}
1198     $CHECKSTAT ${f} || error "${f} missing"
1199     mv ${f} ${f}.rename
1200     $CHECKSTAT ${f}.rename || error "${f}.rename missing"
1201     $CHECKSTAT -a ${f} || error "${f} exists"
1202 }
1203 run_test 24n "Statting the old file after renaming (Posix rename 2)"
1204
1205 test_24o() {
1206         test_mkdir $DIR/$tdir
1207         rename_many -s random -v -n 10 $DIR/$tdir
1208 }
1209 run_test 24o "rename of files during htree split"
1210
1211 test_24p() {
1212         test_mkdir $DIR/R12a
1213         test_mkdir $DIR/R12b
1214         DIRINO=`ls -lid $DIR/R12a | awk '{ print $1 }'`
1215         mrename $DIR/R12a $DIR/R12b
1216         $CHECKSTAT -a $DIR/R12a || error "$DIR/R12a exists"
1217         $CHECKSTAT -t dir $DIR/R12b || error "$DIR/R12b not dir type"
1218         DIRINO2=`ls -lid $DIR/R12b | awk '{ print $1 }'`
1219         [ "$DIRINO" = "$DIRINO2" ] || error "R12a $DIRINO != R12b $DIRINO2"
1220 }
1221 run_test 24p "mkdir .../R12{a,b}; rename .../R12a .../R12b"
1222
1223 cleanup_multiop_pause() {
1224         trap 0
1225         kill -USR1 $MULTIPID
1226 }
1227
1228 test_24q() {
1229         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1230
1231         test_mkdir $DIR/R13a
1232         test_mkdir $DIR/R13b
1233         local DIRINO=$(ls -lid $DIR/R13a | awk '{ print $1 }')
1234         multiop_bg_pause $DIR/R13b D_c || error "multiop failed to start"
1235         MULTIPID=$!
1236
1237         trap cleanup_multiop_pause EXIT
1238         mrename $DIR/R13a $DIR/R13b
1239         $CHECKSTAT -a $DIR/R13a || error "R13a still exists"
1240         $CHECKSTAT -t dir $DIR/R13b || error "R13b does not exist"
1241         local DIRINO2=$(ls -lid $DIR/R13b | awk '{ print $1 }')
1242         [ "$DIRINO" = "$DIRINO2" ] || error "R13a $DIRINO != R13b $DIRINO2"
1243         cleanup_multiop_pause
1244         wait $MULTIPID || error "multiop close failed"
1245 }
1246 run_test 24q "mkdir .../R13{a,b}; open R13b rename R13a R13b ==="
1247
1248 test_24r() { #bug 3789
1249         test_mkdir $DIR/R14a
1250         test_mkdir $DIR/R14a/b
1251         mrename $DIR/R14a $DIR/R14a/b && error "rename to subdir worked!"
1252         $CHECKSTAT -t dir $DIR/R14a || error "$DIR/R14a missing"
1253         $CHECKSTAT -t dir $DIR/R14a/b || error "$DIR/R14a/b missing"
1254 }
1255 run_test 24r "mkdir .../R14a/b; rename .../R14a .../R14a/b ====="
1256
1257 test_24s() {
1258         test_mkdir $DIR/R15a
1259         test_mkdir $DIR/R15a/b
1260         test_mkdir $DIR/R15a/b/c
1261         mrename $DIR/R15a $DIR/R15a/b/c && error "rename to sub-subdir worked!"
1262         $CHECKSTAT -t dir $DIR/R15a || error "$DIR/R15a missing"
1263         $CHECKSTAT -t dir $DIR/R15a/b/c || error "$DIR/R15a/b/c missing"
1264 }
1265 run_test 24s "mkdir .../R15a/b/c; rename .../R15a .../R15a/b/c ="
1266
1267 test_24t() {
1268         test_mkdir $DIR/R16a
1269         test_mkdir $DIR/R16a/b
1270         test_mkdir $DIR/R16a/b/c
1271         mrename $DIR/R16a/b/c $DIR/R16a && error "rename to sub-subdir worked!"
1272         $CHECKSTAT -t dir $DIR/R16a || error "$DIR/R16a missing"
1273         $CHECKSTAT -t dir $DIR/R16a/b/c || error "$DIR/R16a/b/c missing"
1274 }
1275 run_test 24t "mkdir .../R16a/b/c; rename .../R16a/b/c .../R16a ="
1276
1277 test_24u() { # bug12192
1278         stack_trap "rm -f $DIR/$tfile"
1279         $MULTIOP $DIR/$tfile C2w$((2048 * 1024))c || error "multiop failed"
1280         $CHECKSTAT -s $((2048 * 1024)) $DIR/$tfile || error "wrong file size"
1281 }
1282 run_test 24u "create stripe file"
1283
1284 simple_cleanup_common() {
1285         local createmany=$1
1286         local rc=0
1287
1288         [[ -z "$DIR" || -z "$tdir" || ! -d "$DIR/$tdir" ]] && return 0
1289
1290         local start=$SECONDS
1291
1292         [[ -n "$createmany" ]] && unlinkmany $DIR/$tdir/$tfile $createmany
1293         rm -rf $DIR/$tdir || error "cleanup $DIR/$tdir failed"
1294         rc=$?
1295         wait_delete_completed
1296         echo "cleanup time $((SECONDS - start))"
1297         return $rc
1298 }
1299
1300 max_pages_per_rpc() {
1301         local mdtname="$(printf "MDT%04x" ${1:-0})"
1302         $LCTL get_param -n mdc.*$mdtname*.max_pages_per_rpc
1303 }
1304
1305 test_24v() {
1306         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1307
1308         local nrfiles=${COUNT:-100000}
1309         local fname="$DIR/$tdir/$tfile"
1310
1311         # Performance issue on ZFS see LU-4072 (c.f. LU-2887)
1312         [ "$mds1_FSTYPE" = "zfs" ] && nrfiles=${COUNT:-10000}
1313
1314         test_mkdir "$(dirname $fname)"
1315         # assume MDT0000 has the fewest inodes
1316         local stripes=$($LFS getdirstripe -c $(dirname $fname))
1317         local free_inodes=$(($(mdt_free_inodes 0) * ${stripes/#0/1}))
1318         [[ $free_inodes -lt $nrfiles ]] && nrfiles=$free_inodes
1319
1320         stack_trap "simple_cleanup_common $nrfiles"
1321
1322         createmany -m "$fname" $nrfiles
1323
1324         cancel_lru_locks mdc
1325         lctl set_param mdc.*.stats clear
1326
1327         # was previously test_24D: LU-6101
1328         # readdir() returns correct number of entries after cursor reload
1329         local num_ls=$(ls $DIR/$tdir | wc -l)
1330         local num_uniq=$(ls $DIR/$tdir | sort -u | wc -l)
1331         local num_all=$(ls -a $DIR/$tdir | wc -l)
1332         if [ $num_ls -ne $nrfiles ] || [ $num_uniq -ne $nrfiles ] ||
1333                 [ $num_all -ne $((nrfiles + 2)) ]; then
1334                         error "Expected $nrfiles files, got $num_ls " \
1335                                 "($num_uniq unique $num_all .&..)"
1336         fi
1337         # LU-5 large readdir
1338         # dirent_size = 32 bytes for sizeof(struct lu_dirent) +
1339         #               N bytes for name (len($nrfiles) rounded to 8 bytes) +
1340         #               8 bytes for luda_type (4 bytes rounded to 8 bytes)
1341         # take into account of overhead in lu_dirpage header and end mark in
1342         # each page, plus one in rpc_num calculation.
1343         local dirent_size=$((32 + (${#tfile} | 7) + 1 + 8))
1344         local page_entries=$(((PAGE_SIZE - 24) / dirent_size))
1345         local mdt_idx=$($LFS getdirstripe -i $(dirname $fname))
1346         local rpc_pages=$(max_pages_per_rpc $mdt_idx)
1347         local rpc_max=$((nrfiles / (page_entries * rpc_pages) + stripes))
1348         local mds_readpage=$(calc_stats mdc.*.stats mds_readpage)
1349         echo "readpages: $mds_readpage rpc_max: $rpc_max-2/+1"
1350         (( $mds_readpage >= $rpc_max - 2 && $mds_readpage <= $rpc_max + 1)) ||
1351                 error "large readdir doesn't take effect: " \
1352                       "$mds_readpage should be about $rpc_max"
1353 }
1354 run_test 24v "list large directory (test hash collision, b=17560)"
1355
1356 test_24w() { # bug21506
1357         SZ1=234852
1358         stack_trap "rm -f $DIR/$tfile"
1359         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=4096 || return 1
1360         dd if=/dev/zero bs=$SZ1 count=1 >> $DIR/$tfile || return 2
1361         dd if=$DIR/$tfile of=$DIR/${tfile}_left bs=1M skip=4097 || return 3
1362         SZ2=`ls -l $DIR/${tfile}_left | awk '{print $5}'`
1363         [[ "$SZ1" -eq "$SZ2" ]] ||
1364                 error "Error reading at the end of the file $tfile"
1365 }
1366 run_test 24w "Reading a file larger than 4Gb"
1367
1368 test_24x() {
1369         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1370         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1371         [[ $MDS1_VERSION -lt $(version_code 2.7.56) ]] &&
1372                 skip "Need MDS version at least 2.7.56"
1373
1374         local MDTIDX=1
1375         local remote_dir=$DIR/$tdir/remote_dir
1376
1377         test_mkdir $DIR/$tdir
1378         $LFS mkdir -i $MDTIDX $remote_dir ||
1379                 error "create remote directory failed"
1380
1381         test_mkdir $DIR/$tdir/src_dir
1382         touch $DIR/$tdir/src_file
1383         test_mkdir $remote_dir/tgt_dir
1384         touch $remote_dir/tgt_file
1385
1386         mrename $DIR/$tdir/src_dir $remote_dir/tgt_dir ||
1387                 error "rename dir cross MDT failed!"
1388
1389         mrename $DIR/$tdir/src_file $remote_dir/tgt_file ||
1390                 error "rename file cross MDT failed!"
1391
1392         touch $DIR/$tdir/ln_file
1393         ln $DIR/$tdir/ln_file $remote_dir/ln_name ||
1394                 error "ln file cross MDT failed"
1395
1396         rm -rf $DIR/$tdir || error "Can not delete directories"
1397 }
1398 run_test 24x "cross MDT rename/link"
1399
1400 test_24y() {
1401         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1402         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1403
1404         local remote_dir=$DIR/$tdir/remote_dir
1405         local mdtidx=1
1406
1407         test_mkdir $DIR/$tdir
1408         $LFS mkdir -i $mdtidx $remote_dir ||
1409                 error "create remote directory failed"
1410
1411         test_mkdir $remote_dir/src_dir
1412         touch $remote_dir/src_file
1413         test_mkdir $remote_dir/tgt_dir
1414         touch $remote_dir/tgt_file
1415
1416         mrename $remote_dir/src_dir $remote_dir/tgt_dir ||
1417                 error "rename subdir in the same remote dir failed!"
1418
1419         mrename $remote_dir/src_file $remote_dir/tgt_file ||
1420                 error "rename files in the same remote dir failed!"
1421
1422         ln $remote_dir/tgt_file $remote_dir/tgt_file1 ||
1423                 error "link files in the same remote dir failed!"
1424
1425         rm -rf $DIR/$tdir || error "Can not delete directories"
1426 }
1427 run_test 24y "rename/link on the same dir should succeed"
1428
1429 test_24z() {
1430         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1431         [[ $MDS1_VERSION -lt $(version_code 2.12.51) ]] &&
1432                 skip "Need MDS version at least 2.12.51"
1433
1434         local index
1435
1436         for index in 0 1; do
1437                 $LFS mkdir -i $index $DIR/$tdir.$index || error "mkdir failed"
1438                 touch $DIR/$tdir.0/$tfile.$index || error "touch failed"
1439         done
1440
1441         mv $DIR/$tdir.0/$tfile.0 $DIR/$tdir.1 || error "mv $tfile.0 failed"
1442
1443         index=$($LFS getstripe -m $DIR/$tdir.1/$tfile.0)
1444         [ $index -eq 0 ] || error "$tfile.0 is on MDT$index"
1445
1446         local mdts=$(comma_list $(mdts_nodes))
1447
1448         do_nodes $mdts $LCTL set_param mdt.*.enable_remote_rename=0
1449         stack_trap "do_nodes $mdts $LCTL \
1450                 set_param mdt.*.enable_remote_rename=1" EXIT
1451
1452         mv $DIR/$tdir.0/$tfile.1 $DIR/$tdir.1 || error "mv $tfile.1 failed"
1453
1454         index=$($LFS getstripe -m $DIR/$tdir.1/$tfile.1)
1455         [ $index -eq 1 ] || error "$tfile.1 is on MDT$index"
1456 }
1457 run_test 24z "cross-MDT rename is done as cp"
1458
1459 test_24A() { # LU-3182
1460         local NFILES=5000
1461
1462         test_mkdir $DIR/$tdir
1463         stack_trap "simple_cleanup_common $NFILES"
1464         createmany -m $DIR/$tdir/$tfile $NFILES
1465         local t=$(ls $DIR/$tdir | wc -l)
1466         local u=$(ls $DIR/$tdir | sort -u | wc -l)
1467         local v=$(ls -ai $DIR/$tdir | sort -u | wc -l)
1468
1469         (( $t == $NFILES && $u == $NFILES && $v == NFILES + 2 )) ||
1470                 error "Expected $NFILES files, got $t ($u unique $v .&..)"
1471 }
1472 run_test 24A "readdir() returns correct number of entries."
1473
1474 test_24B() { # LU-4805
1475         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
1476
1477         local count
1478
1479         test_mkdir $DIR/$tdir
1480         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir/ ||
1481                 error "create striped dir failed"
1482
1483         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1484         [ $count -eq 2 ] || error "Expected 2, got $count"
1485
1486         touch $DIR/$tdir/striped_dir/a
1487
1488         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1489         [ $count -eq 3 ] || error "Expected 3, got $count"
1490
1491         touch $DIR/$tdir/striped_dir/.f
1492
1493         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1494         [ $count -eq 4 ] || error "Expected 4, got $count"
1495
1496         rm -rf $DIR/$tdir || error "Can not delete directories"
1497 }
1498 run_test 24B "readdir for striped dir return correct number of entries"
1499
1500 test_24C() {
1501         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
1502
1503         mkdir $DIR/$tdir
1504         mkdir $DIR/$tdir/d0
1505         mkdir $DIR/$tdir/d1
1506
1507         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/d0/striped_dir ||
1508                 error "create striped dir failed"
1509
1510         cd $DIR/$tdir/d0/striped_dir
1511
1512         local d0_ino=$(ls -i -l -a $DIR/$tdir | grep "d0" | awk '{print $1}')
1513         local d1_ino=$(ls -i -l -a $DIR/$tdir | grep "d1" | awk '{print $1}')
1514         local parent_ino=$(ls -i -l -a | grep "\.\." | awk '{print $1}')
1515
1516         [ "$d0_ino" = "$parent_ino" ] ||
1517                 error ".. wrong, expect $d0_ino, get $parent_ino"
1518
1519         mv $DIR/$tdir/d0/striped_dir $DIR/$tdir/d1/ ||
1520                 error "mv striped dir failed"
1521
1522         parent_ino=$(ls -i -l -a | grep "\.\." | awk '{print $1}')
1523
1524         [ "$d1_ino" = "$parent_ino" ] ||
1525                 error ".. wrong after mv, expect $d1_ino, get $parent_ino"
1526 }
1527 run_test 24C "check .. in striped dir"
1528
1529 test_24E() {
1530         [[ $MDSCOUNT -lt 4 ]] && skip_env "needs >= 4 MDTs"
1531         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1532
1533         mkdir -p $DIR/$tdir
1534         mkdir $DIR/$tdir/src_dir
1535         $LFS mkdir -i 1 $DIR/$tdir/src_dir/src_child ||
1536                 error "create remote source failed"
1537
1538         touch $DIR/$tdir/src_dir/src_child/a
1539
1540         $LFS mkdir -i 2 $DIR/$tdir/tgt_dir ||
1541                 error "create remote target dir failed"
1542
1543         $LFS mkdir -i 3 $DIR/$tdir/tgt_dir/tgt_child ||
1544                 error "create remote target child failed"
1545
1546         mrename $DIR/$tdir/src_dir/src_child $DIR/$tdir/tgt_dir/tgt_child ||
1547                 error "rename dir cross MDT failed!"
1548
1549         find $DIR/$tdir
1550
1551         $CHECKSTAT -t dir $DIR/$tdir/src_dir/src_child &&
1552                 error "src_child still exists after rename"
1553
1554         $CHECKSTAT -t file $DIR/$tdir/tgt_dir/tgt_child/a ||
1555                 error "missing file(a) after rename"
1556
1557         rm -rf $DIR/$tdir || error "Can not delete directories"
1558 }
1559 run_test 24E "cross MDT rename/link"
1560
1561 test_24F () {
1562         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return 0
1563
1564         local repeats=1000
1565         [ "$SLOW" = "no" ] && repeats=100
1566
1567         mkdir -p $DIR/$tdir
1568
1569         echo "$repeats repeats"
1570         for ((i = 0; i < repeats; i++)); do
1571                 $LFS mkdir -i0 -c2 $DIR/$tdir/test || error "mkdir fails"
1572                 touch $DIR/$tdir/test/a || error "touch fails"
1573                 mkdir $DIR/$tdir/test/b || error "mkdir fails"
1574                 rm -rf $DIR/$tdir/test || error "rmdir fails"
1575         done
1576
1577         true
1578 }
1579 run_test 24F "hash order vs readdir (LU-11330)"
1580
1581 test_24G () {
1582         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
1583
1584         (( $MDS1_VERSION >= $(version_code v2_13_56-59-g9adc02c016d2) )) ||
1585                 skip "Need MDS >= v2_13_56-59-g9adc02c016d2 for symlink migration"
1586
1587         local ino1
1588         local ino2
1589
1590         $LFS mkdir -i 0 $DIR/$tdir-0 || error "mkdir $tdir-0"
1591         $LFS mkdir -i 1 $DIR/$tdir-1 || error "mkdir $tdir-1"
1592         touch $DIR/$tdir-0/f1 || error "touch f1"
1593         ln -s $DIR/$tdir-0/f1 $DIR/$tdir-0/s1 || error "ln s1"
1594         ino1=$(stat -c%i $DIR/$tdir-0/s1)
1595         mv $DIR/$tdir-0/s1 $DIR/$tdir-1 || error "mv s1"
1596         ino2=$(stat -c%i $DIR/$tdir-1/s1)
1597         [ $ino1 -ne $ino2 ] || error "s1 should be migrated"
1598 }
1599 run_test 24G "migrate symlink in rename"
1600
1601 test_24H() {
1602         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
1603         [[ $(hostname) != $(facet_active_host mds2) ]] ||
1604                 skip "MDT1 should be on another node"
1605
1606         test_mkdir -i 1 -c 1 $DIR/$tdir
1607 #define OBD_FAIL_FLD_QUERY_REQ           0x1103
1608         do_facet mds2 $LCTL set_param fail_loc=0x80001103
1609         touch $DIR/$tdir/$tfile || error "touch failed"
1610 }
1611 run_test 24H "repeat FLD_QUERY rpc"
1612
1613 test_25a() {
1614         echo '== symlink sanity ============================================='
1615
1616         test_mkdir $DIR/d25
1617         ln -s d25 $DIR/s25
1618         touch $DIR/s25/foo ||
1619                 error "File creation in symlinked directory failed"
1620 }
1621 run_test 25a "create file in symlinked directory ==============="
1622
1623 test_25b() {
1624         [ ! -d $DIR/d25 ] && test_25a
1625         $CHECKSTAT -t file $DIR/s25/foo || error "$DIR/s25/foo not file type"
1626 }
1627 run_test 25b "lookup file in symlinked directory ==============="
1628
1629 test_26a() {
1630         test_mkdir $DIR/d26
1631         test_mkdir $DIR/d26/d26-2
1632         ln -s d26/d26-2 $DIR/s26
1633         touch $DIR/s26/foo || error "File creation failed"
1634 }
1635 run_test 26a "multiple component symlink ======================="
1636
1637 test_26b() {
1638         test_mkdir -p $DIR/$tdir/d26-2
1639         ln -s $tdir/d26-2/foo $DIR/s26-2
1640         touch $DIR/s26-2 || error "File creation failed"
1641 }
1642 run_test 26b "multiple component symlink at end of lookup ======"
1643
1644 test_26c() {
1645         test_mkdir $DIR/d26.2
1646         touch $DIR/d26.2/foo
1647         ln -s d26.2 $DIR/s26.2-1
1648         ln -s s26.2-1 $DIR/s26.2-2
1649         ln -s s26.2-2 $DIR/s26.2-3
1650         chmod 0666 $DIR/s26.2-3/foo
1651 }
1652 run_test 26c "chain of symlinks"
1653
1654 # recursive symlinks (bug 439)
1655 test_26d() {
1656         ln -s d26-3/foo $DIR/d26-3
1657 }
1658 run_test 26d "create multiple component recursive symlink"
1659
1660 test_26e() {
1661         [ ! -h $DIR/d26-3 ] && test_26d
1662         rm $DIR/d26-3
1663 }
1664 run_test 26e "unlink multiple component recursive symlink"
1665
1666 # recursive symlinks (bug 7022)
1667 test_26f() {
1668         test_mkdir $DIR/$tdir
1669         test_mkdir $DIR/$tdir/$tfile
1670         cd $DIR/$tdir/$tfile           || error "cd $DIR/$tdir/$tfile failed"
1671         test_mkdir -p lndir/bar1
1672         test_mkdir $DIR/$tdir/$tfile/$tfile
1673         cd $tfile                || error "cd $tfile failed"
1674         ln -s .. dotdot          || error "ln dotdot failed"
1675         ln -s dotdot/lndir lndir || error "ln lndir failed"
1676         cd $DIR/$tdir                 || error "cd $DIR/$tdir failed"
1677         output=`ls $tfile/$tfile/lndir/bar1`
1678         [ "$output" = bar1 ] && error "unexpected output"
1679         rm -r $tfile             || error "rm $tfile failed"
1680         $CHECKSTAT -a $DIR/$tfile || error "$tfile not gone"
1681 }
1682 run_test 26f "rm -r of a directory which has recursive symlink"
1683
1684 test_27a() {
1685         test_mkdir $DIR/$tdir
1686         $LFS getstripe $DIR/$tdir
1687         $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "setstripe failed"
1688         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1689         cp /etc/hosts $DIR/$tdir/$tfile || error "Can't copy to one stripe file"
1690 }
1691 run_test 27a "one stripe file"
1692
1693 test_27b() {
1694         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1695
1696         test_mkdir $DIR/$tdir
1697         $LFS setstripe -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
1698         $LFS getstripe -c $DIR/$tdir/$tfile
1699         [ $($LFS getstripe -c $DIR/$tdir/$tfile) -eq 2 ] ||
1700                 error "two-stripe file doesn't have two stripes"
1701
1702         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1703 }
1704 run_test 27b "create and write to two stripe file"
1705
1706 # 27c family tests specific striping, setstripe -o
1707 test_27ca() {
1708         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1709         test_mkdir -p $DIR/$tdir
1710         local osts="1"
1711
1712         $LFS setstripe -o $osts $DIR/$tdir/$tfile  || error "setstripe failed"
1713         $LFS getstripe -i $DIR/$tdir/$tfile
1714         [ $($LFS getstripe -i $DIR/$tdir/$tfile ) -eq $osts ] ||
1715                 error "stripe not on specified OST"
1716
1717         dd if=/dev/zero of=$DIR/$tdir/$tfile  bs=1M count=4 || error "dd failed"
1718 }
1719 run_test 27ca "one stripe on specified OST"
1720
1721 test_27cb() {
1722         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1723         test_mkdir -p $DIR/$tdir
1724         local osts="1,0"
1725         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1726         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1727         echo "$getstripe"
1728
1729         # Strip getstripe output to a space separated list of OSTs
1730         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1731                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1732         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1733                 error "stripes not on specified OSTs"
1734
1735         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1736 }
1737 run_test 27cb "two stripes on specified OSTs"
1738
1739 test_27cc() {
1740         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1741         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1742                 skip "server does not support overstriping"
1743
1744         test_mkdir -p $DIR/$tdir
1745         local osts="0,0"
1746         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1747         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1748         echo "$getstripe"
1749
1750         # Strip getstripe output to a space separated list of OSTs
1751         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1752                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1753         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1754                 error "stripes not on specified OSTs"
1755
1756         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1757 }
1758 run_test 27cc "two stripes on the same OST"
1759
1760 test_27cd() {
1761         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1762         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1763                 skip "server does not support overstriping"
1764         test_mkdir -p $DIR/$tdir
1765         local osts="0,1,1,0"
1766         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1767         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1768         echo "$getstripe"
1769
1770         # Strip getstripe output to a space separated list of OSTs
1771         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1772                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1773         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1774                 error "stripes not on specified OSTs"
1775
1776         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1777 }
1778 run_test 27cd "four stripes on two OSTs"
1779
1780 test_27ce() {
1781         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
1782                 skip_env "too many osts, skipping"
1783         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1784                 skip "server does not support overstriping"
1785         # We do one more stripe than we have OSTs
1786         [ $OSTCOUNT -lt 159 ] || large_xattr_enabled ||
1787                 skip_env "ea_inode feature disabled"
1788
1789         test_mkdir -p $DIR/$tdir
1790         local osts=""
1791         for i in $(seq 0 $OSTCOUNT);
1792         do
1793                 osts=$osts"0"
1794                 if [ $i -ne $OSTCOUNT ]; then
1795                         osts=$osts","
1796                 fi
1797         done
1798
1799         echo "$LFS setstripe -o $osts $DIR/$tdir/$tfile"
1800         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1801         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1802         echo "$getstripe"
1803
1804         # Strip getstripe output to a space separated list of OSTs
1805         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1806                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1807         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1808                 error "stripes '$getstripe_osts' not on given OSTs ${osts//,/ }"
1809
1810         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1811 }
1812 run_test 27ce "more stripes than OSTs with -o"
1813
1814 test_27cf() {
1815         local osp_proc="osp.$FSNAME-OST0000-osc-MDT000*.active"
1816         local pid=0
1817
1818         test_mkdir -p $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
1819         do_facet $SINGLEMDS "$LCTL set_param -n $osp_proc=0"
1820         stack_trap "do_facet $SINGLEMDS $LCTL set_param -n $osp_proc=1" EXIT
1821         wait_update_facet $SINGLEMDS "$LCTL get_param -n $osp_proc | grep 1" ||
1822                 error "failed to set $osp_proc=0"
1823
1824         $LFS setstripe -o 0 $DIR/$tdir/$tfile &
1825         pid=$!
1826         sleep 1
1827         do_facet $SINGLEMDS "$LCTL set_param -n $osp_proc=1"
1828         wait_update_facet $SINGLEMDS "$LCTL get_param -n $osp_proc | grep 0" ||
1829                 error "failed to set $osp_proc=1"
1830         wait $pid
1831         [[ $pid -ne 0 ]] ||
1832                 error "should return error due to $osp_proc=0"
1833 }
1834 run_test 27cf "'setstripe -o' on inactive OSTs should return error"
1835
1836 test_27cg() {
1837         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1838                 skip "server does not support overstriping"
1839         [[ $mds1_FSTYPE != "ldiskfs" ]] && skip_env "ldiskfs only test"
1840         large_xattr_enabled || skip_env "ea_inode feature disabled"
1841
1842         local osts="0"
1843
1844         for ((i=1;i<1000;i++)); do
1845                 osts+=",$((i % OSTCOUNT))"
1846         done
1847
1848         local mdts=$(comma_list $(mdts_nodes))
1849         local before=$(do_nodes $mdts \
1850                 "$LCTL get_param -n osd-ldiskfs.*MDT*.stats" |
1851                 awk '/many credits/{print $3}' |
1852                 calc_sum)
1853
1854         $LFS setstripe -o $osts $DIR/$tfile || error "setstripe failed"
1855         $LFS getstripe $DIR/$tfile | grep stripe
1856
1857         rm -f $DIR/$tfile || error "can't unlink"
1858
1859         after=$(do_nodes $mdts \
1860                 "$LCTL get_param -n osd-ldiskfs.*MDT*.stats" |
1861                 awk '/many credits/{print $3}' |
1862                 calc_sum)
1863
1864         (( before == after )) ||
1865                 error "too many credits happened: $after > $before"
1866 }
1867 run_test 27cg "1000 shouldn't cause too many credits"
1868
1869 test_27d() {
1870         test_mkdir $DIR/$tdir
1871         $LFS setstripe -c 0 -i -1 -S 0 $DIR/$tdir/$tfile ||
1872                 error "setstripe failed"
1873         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1874         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1875 }
1876 run_test 27d "create file with default settings"
1877
1878 test_27e() {
1879         # LU-5839 adds check for existed layout before setting it
1880         [[ $MDS1_VERSION -lt $(version_code 2.7.56) ]] &&
1881                 skip "Need MDS version at least 2.7.56"
1882
1883         test_mkdir $DIR/$tdir
1884         $LFS setstripe -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
1885         $LFS setstripe -c 2 $DIR/$tdir/$tfile && error "setstripe worked twice"
1886         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1887 }
1888 run_test 27e "setstripe existing file (should return error)"
1889
1890 test_27f() {
1891         test_mkdir $DIR/$tdir
1892         $LFS setstripe -S 100 -i 0 -c 1 $DIR/$tdir/$tfile &&
1893                 error "$LFS setstripe $DIR/$tdir/$tfile failed"
1894         $CHECKSTAT -t file $DIR/$tdir/$tfile &&
1895                 error "$CHECKSTAT -t file $DIR/$tdir/$tfile should fail"
1896         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1897         $LFS getstripe $DIR/$tdir/$tfile || error "$LFS getstripe failed"
1898 }
1899 run_test 27f "setstripe with bad stripe size (should return error)"
1900
1901 test_27g() {
1902         test_mkdir $DIR/$tdir
1903         $MCREATE $DIR/$tdir/$tfile || error "mcreate failed"
1904         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "no stripe info" ||
1905                 error "$DIR/$tdir/$tfile has object"
1906 }
1907 run_test 27g "$LFS getstripe with no objects"
1908
1909 test_27ga() {
1910         test_mkdir $DIR/$tdir
1911         touch $DIR/$tdir/$tfile || error "touch failed"
1912         ln -s bogus $DIR/$tdir/$tfile.2 || error "ln failed"
1913         $LFS getstripe -m $DIR/$tdir/$tfile $DIR/$tdir/$tfile.2
1914         local rc=$?
1915         (( rc == 2 )) || error "getstripe did not return ENOENT"
1916
1917         local err_msg=$($LFS getstripe $DIR/$tdir/typo $DIR/$tdir/$tfile \
1918                         2>&1 > /dev/null)
1919         [[ $err_msg =~ "typo" ]] ||
1920                 error "expected message with correct filename, got '$err_msg'"
1921 }
1922 run_test 27ga "$LFS getstripe with missing file (should return error)"
1923
1924 test_27i() {
1925         test_mkdir $DIR/$tdir
1926         touch $DIR/$tdir/$tfile || error "touch failed"
1927         [[ $($LFS getstripe -c $DIR/$tdir/$tfile) -gt 0 ]] ||
1928                 error "missing objects"
1929 }
1930 run_test 27i "$LFS getstripe with some objects"
1931
1932 test_27j() {
1933         test_mkdir $DIR/$tdir
1934         $LFS setstripe -i $OSTCOUNT $DIR/$tdir/$tfile &&
1935                 error "setstripe failed" || true
1936 }
1937 run_test 27j "setstripe with bad stripe offset (should return error)"
1938
1939 test_27k() { # bug 2844
1940         test_mkdir $DIR/$tdir
1941         local file=$DIR/$tdir/$tfile
1942         local ll_max_blksize=$((4 * 1024 * 1024))
1943         $LFS setstripe -S 67108864 $file || error "setstripe failed"
1944         local blksize=$(stat $file | awk '/IO Block:/ { print $7 }')
1945         [ $blksize -le $ll_max_blksize ] || error "1:$blksize > $ll_max_blksize"
1946         dd if=/dev/zero of=$file bs=4k count=1
1947         blksize=$(stat $file | awk '/IO Block:/ { print $7 }')
1948         [ $blksize -le $ll_max_blksize ] || error "2:$blksize > $ll_max_blksize"
1949 }
1950 run_test 27k "limit i_blksize for broken user apps"
1951
1952 test_27l() {
1953         mcreate $DIR/$tfile || error "creating file"
1954         $RUNAS $LFS setstripe -c 1 $DIR/$tfile &&
1955                 error "setstripe should have failed" || true
1956 }
1957 run_test 27l "check setstripe permissions (should return error)"
1958
1959 test_27m() {
1960         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1961
1962         [ -n "$RCLIENTS" -o -n "$MOUNT_2" ] &&
1963                 skip_env "multiple clients -- skipping"
1964
1965         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
1966                    head -n1)
1967         if [[ $ORIGFREE -gt $MAXFREE ]]; then
1968                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
1969         fi
1970         stack_trap simple_cleanup_common
1971         test_mkdir $DIR/$tdir
1972         $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile.1
1973         if check_fallocate_supported $ost1; then
1974                 fallocate -l ${MAXFREE}k $DIR/$tdir/$tfile.1 &&
1975                         error "fallocate should fill OST0"
1976         else
1977                 dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=1024 count=$MAXFREE &&
1978                         error "dd should fill OST0"
1979         fi
1980         i=2
1981         while $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile.$i; do
1982                 i=$((i + 1))
1983                 [ $i -gt 256 ] && break
1984         done
1985         i=$((i + 1))
1986         touch $DIR/$tdir/$tfile.$i
1987         [ $($LFS getstripe $DIR/$tdir/$tfile.$i | grep -A 10 obdidx |
1988             awk '{print $1}'| grep -w "0") ] &&
1989                 error "OST0 was full but new created file still use it"
1990         i=$((i + 1))
1991         touch $DIR/$tdir/$tfile.$i
1992         [ $($LFS getstripe $DIR/$tdir/$tfile.$i | grep -A 10 obdidx |
1993             awk '{print $1}'| grep -w "0") ] &&
1994                 error "OST0 was full but new created file still use it" || true
1995 }
1996 run_test 27m "create file while OST0 was full"
1997
1998 # OSCs keep a NOSPC flag that will be reset after ~5s (qos_maxage)
1999 # if the OST isn't full anymore.
2000 reset_enospc() {
2001         local ostidx=${1:-""}
2002         local delay
2003         local ready
2004         local get_prealloc
2005         local osts
2006
2007         [[ -n "$ostidx" ]] && osts=$(facet_host ost$((ostidx + 1))) ||
2008                 osts=$(osts_nodes)
2009
2010         do_nodes $osts lctl set_param fail_loc=0
2011         wait_delete_completed   # initiate all OST_DESTROYs from MDS to OST
2012         delay=$(do_facet $SINGLEMDS lctl get_param -n lov.*.qos_maxage |
2013                 awk '{print $1 * 2;exit;}')
2014         get_prealloc="$LCTL get_param -n osc.*MDT*.prealloc_status |
2015                         grep -v \"^0$\""
2016         wait_update_facet $SINGLEMDS "$get_prealloc" "" $delay
2017 }
2018
2019 test_27n() {
2020         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2021         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2022         remote_mds_nodsh && skip "remote MDS with nodsh"
2023         remote_ost_nodsh && skip "remote OST with nodsh"
2024
2025         reset_enospc
2026         rm -f $DIR/$tdir/$tfile
2027         exhaust_precreations 0 0x80000215
2028         $LFS setstripe -c -1 $DIR/$tdir || error "setstripe failed"
2029         touch $DIR/$tdir/$tfile || error "touch failed"
2030         $LFS getstripe $DIR/$tdir/$tfile
2031         reset_enospc
2032 }
2033 run_test 27n "create file with some full OSTs"
2034
2035 test_27o() {
2036         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2037         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2038         remote_mds_nodsh && skip "remote MDS with nodsh"
2039         remote_ost_nodsh && skip "remote OST with nodsh"
2040
2041         reset_enospc
2042         rm -f $DIR/$tdir/$tfile
2043         exhaust_all_precreations 0x215
2044
2045         touch $DIR/$tdir/$tfile && error "able to create $DIR/$tdir/$tfile"
2046
2047         reset_enospc
2048         rm -rf $DIR/$tdir/*
2049 }
2050 run_test 27o "create file with all full OSTs (should error)"
2051
2052 function create_and_checktime() {
2053         local fname=$1
2054         local loops=$2
2055         local i
2056
2057         for ((i=0; i < $loops; i++)); do
2058                 local start=$SECONDS
2059                 multiop $fname-$i Oc
2060                 ((SECONDS-start < TIMEOUT)) ||
2061                         error "creation took " $((SECONDS-$start)) && return 1
2062         done
2063 }
2064
2065 test_27oo() {
2066         local mdts=$(comma_list $(mdts_nodes))
2067
2068         [ $MDS1_VERSION -lt $(version_code 2.13.57) ] &&
2069                 skip "Need MDS version at least 2.13.57"
2070
2071         local f0=$DIR/${tfile}-0
2072         local f1=$DIR/${tfile}-1
2073
2074         wait_delete_completed
2075
2076         # refill precreated objects
2077         $LFS setstripe -i0 -c1 $f0
2078
2079         saved=$(do_facet mds1 $LCTL get_param -n lov.*0000*.qos_threshold_rr)
2080         # force QoS allocation policy
2081         do_nodes $mdts $LCTL set_param lov.*.qos_threshold_rr=0%
2082         stack_trap "do_nodes $mdts $LCTL set_param \
2083                 lov.*.qos_threshold_rr=$saved" EXIT
2084         sleep_maxage
2085
2086         # one OST is unavailable, but still have few objects preallocated
2087         stop ost1
2088         stack_trap "start ost1 $(ostdevname 1) $OST_MOUNT_OPTS; \
2089                 rm -rf $f1 $DIR/$tdir*" EXIT
2090
2091         for ((i=0; i < 7; i++)); do
2092                 mkdir $DIR/$tdir$i || error "can't create dir"
2093                 $LFS setstripe -c$((OSTCOUNT-1)) $DIR/$tdir$i ||
2094                         error "can't set striping"
2095         done
2096         for ((i=0; i < 7; i++)); do
2097                 create_and_checktime $DIR/$tdir$i/$tfile 100 &
2098         done
2099         wait
2100 }
2101 run_test 27oo "don't let few threads to reserve too many objects"
2102
2103 test_27p() {
2104         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2105         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2106         remote_mds_nodsh && skip "remote MDS with nodsh"
2107         remote_ost_nodsh && skip "remote OST with nodsh"
2108
2109         reset_enospc
2110         rm -f $DIR/$tdir/$tfile
2111         test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
2112
2113         $MCREATE $DIR/$tdir/$tfile || error "mcreate failed"
2114         $TRUNCATE $DIR/$tdir/$tfile 80000000 || error "truncate failed"
2115         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat failed"
2116
2117         exhaust_precreations 0 0x80000215
2118         echo foo >> $DIR/$tdir/$tfile || error "append failed"
2119         $CHECKSTAT -s 80000004 $DIR/$tdir/$tfile || error "checkstat failed"
2120         $LFS getstripe $DIR/$tdir/$tfile
2121
2122         reset_enospc
2123 }
2124 run_test 27p "append to a truncated file with some full OSTs"
2125
2126 test_27q() {
2127         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2128         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2129         remote_mds_nodsh && skip "remote MDS with nodsh"
2130         remote_ost_nodsh && skip "remote OST with nodsh"
2131
2132         reset_enospc
2133         rm -f $DIR/$tdir/$tfile
2134
2135         mkdir_on_mdt0 $DIR/$tdir
2136         $MCREATE $DIR/$tdir/$tfile || error "mcreate $DIR/$tdir/$tfile failed"
2137         $TRUNCATE $DIR/$tdir/$tfile 80000000 ||
2138                 error "truncate $DIR/$tdir/$tfile failed"
2139         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat failed"
2140
2141         exhaust_all_precreations 0x215
2142
2143         echo foo >> $DIR/$tdir/$tfile && error "append succeeded"
2144         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat 2 failed"
2145
2146         reset_enospc
2147 }
2148 run_test 27q "append to truncated file with all OSTs full (should error)"
2149
2150 test_27r() {
2151         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2152         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2153         remote_mds_nodsh && skip "remote MDS with nodsh"
2154         remote_ost_nodsh && skip "remote OST with nodsh"
2155
2156         reset_enospc
2157         rm -f $DIR/$tdir/$tfile
2158         exhaust_precreations 0 0x80000215
2159
2160         $LFS setstripe -i 0 -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
2161
2162         reset_enospc
2163 }
2164 run_test 27r "stripe file with some full OSTs (shouldn't LBUG) ="
2165
2166 test_27s() { # bug 10725
2167         test_mkdir $DIR/$tdir
2168         local stripe_size=$((4096 * 1024 * 1024))       # 2^32
2169         local stripe_count=0
2170         [ $OSTCOUNT -eq 1 ] || stripe_count=2
2171         $LFS setstripe -S $stripe_size -c $stripe_count $DIR/$tdir &&
2172                 error "stripe width >= 2^32 succeeded" || true
2173
2174 }
2175 run_test 27s "lsm_xfersize overflow (should error) (bug 10725)"
2176
2177 test_27t() { # bug 10864
2178         WDIR=$(pwd)
2179         WLFS=$(which lfs)
2180         cd $DIR
2181         touch $tfile
2182         $WLFS getstripe $tfile
2183         cd $WDIR
2184 }
2185 run_test 27t "check that utils parse path correctly"
2186
2187 test_27u() { # bug 4900
2188         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2189         remote_mds_nodsh && skip "remote MDS with nodsh"
2190
2191         local index
2192         local list=$(comma_list $(mdts_nodes))
2193
2194 #define OBD_FAIL_MDS_OSC_PRECREATE      0x139
2195         do_nodes $list $LCTL set_param fail_loc=0x139
2196         test_mkdir -p $DIR/$tdir
2197         stack_trap "simple_cleanup_common 1000"
2198         createmany -o $DIR/$tdir/$tfile 1000
2199         do_nodes $list $LCTL set_param fail_loc=0
2200
2201         TLOG=$TMP/$tfile.getstripe
2202         $LFS getstripe $DIR/$tdir > $TLOG
2203         OBJS=$(awk -vobj=0 '($1 == 0) { obj += 1 } END { print obj; }' $TLOG)
2204         [[ $OBJS -gt 0 ]] &&
2205                 error "$OBJS objects created on OST-0. See $TLOG" ||
2206                 rm -f $TLOG
2207 }
2208 run_test 27u "skip object creation on OSC w/o objects"
2209
2210 test_27v() { # bug 4900
2211         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2212         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2213         remote_mds_nodsh && skip "remote MDS with nodsh"
2214         remote_ost_nodsh && skip "remote OST with nodsh"
2215
2216         exhaust_all_precreations 0x215
2217         reset_enospc
2218
2219         $LFS setstripe -c 1 $DIR/$tdir         # 1 stripe / file
2220
2221         touch $DIR/$tdir/$tfile
2222         #define OBD_FAIL_TGT_DELAY_PRECREATE     0x705
2223         # all except ost1
2224         for (( i=1; i < OSTCOUNT; i++ )); do
2225                 do_facet ost$i lctl set_param fail_loc=0x705
2226         done
2227         local START=`date +%s`
2228         createmany -o $DIR/$tdir/$tfile 32
2229
2230         local FINISH=`date +%s`
2231         local TIMEOUT=`lctl get_param -n timeout`
2232         local PROCESS=$((FINISH - START))
2233         [ $PROCESS -ge $((TIMEOUT / 2)) ] && \
2234                error "$FINISH - $START >= $TIMEOUT / 2"
2235         sleep $((TIMEOUT / 2 - PROCESS))
2236         reset_enospc
2237 }
2238 run_test 27v "skip object creation on slow OST"
2239
2240 test_27w() { # bug 10997
2241         test_mkdir $DIR/$tdir
2242         $LFS setstripe -S 65536 $DIR/$tdir/f0 || error "setstripe failed"
2243         [ $($LFS getstripe -S $DIR/$tdir/f0) -ne 65536 ] &&
2244                 error "stripe size $size != 65536" || true
2245         [ $($LFS getstripe -d $DIR/$tdir | grep -c "stripe_count") -eq 0 ] &&
2246                 error "$LFS getstripe -d $DIR/$tdir no 'stripe_count'" || true
2247 }
2248 run_test 27w "check $LFS setstripe -S and getstrip -d options"
2249
2250 test_27wa() {
2251         [[ $OSTCOUNT -lt 2 ]] &&
2252                 skip_env "skipping multiple stripe count/offset test"
2253
2254         test_mkdir $DIR/$tdir
2255         for i in $(seq 1 $OSTCOUNT); do
2256                 offset=$((i - 1))
2257                 $LFS setstripe -c $i -i $offset $DIR/$tdir/f$i ||
2258                         error "setstripe -c $i -i $offset failed"
2259                 count=$($LFS getstripe -c $DIR/$tdir/f$i)
2260                 index=$($LFS getstripe -i $DIR/$tdir/f$i)
2261                 [ $count -ne $i ] && error "stripe count $count != $i" || true
2262                 [ $index -ne $offset ] &&
2263                         error "stripe offset $index != $offset" || true
2264         done
2265 }
2266 run_test 27wa "check $LFS setstripe -c -i options"
2267
2268 test_27x() {
2269         remote_ost_nodsh && skip "remote OST with nodsh"
2270         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2271         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2272
2273         OFFSET=$(($OSTCOUNT - 1))
2274         OSTIDX=0
2275         local OST=$(ostname_from_index $OSTIDX)
2276
2277         test_mkdir $DIR/$tdir
2278         $LFS setstripe -c 1 $DIR/$tdir  # 1 stripe per file
2279         do_facet ost$((OSTIDX + 1)) lctl set_param -n obdfilter.$OST.degraded 1
2280         sleep_maxage
2281         createmany -o $DIR/$tdir/$tfile $OSTCOUNT
2282         for i in $(seq 0 $OFFSET); do
2283                 [ $($LFS getstripe $DIR/$tdir/$tfile$i | grep -A 10 obdidx |
2284                         awk '{print $1}' | grep -w "$OSTIDX") ] &&
2285                 error "OST0 was degraded but new created file still use it"
2286         done
2287         do_facet ost$((OSTIDX + 1)) lctl set_param -n obdfilter.$OST.degraded 0
2288 }
2289 run_test 27x "create files while OST0 is degraded"
2290
2291 test_27y() {
2292         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2293         remote_mds_nodsh && skip "remote MDS with nodsh"
2294         remote_ost_nodsh && skip "remote OST with nodsh"
2295         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2296
2297         local mdtosc=$(get_mdtosc_proc_path $SINGLEMDS $FSNAME-OST0000)
2298         local last_id=$(do_facet $SINGLEMDS lctl get_param -n \
2299                 osp.$mdtosc.prealloc_last_id)
2300         local next_id=$(do_facet $SINGLEMDS lctl get_param -n \
2301                 osp.$mdtosc.prealloc_next_id)
2302         local fcount=$((last_id - next_id))
2303         [[ $fcount -eq 0 ]] && skip "not enough space on OST0"
2304         [[ $fcount -gt $OSTCOUNT ]] && fcount=$OSTCOUNT
2305
2306         local MDS_OSCS=$(do_facet $SINGLEMDS lctl dl |
2307                          awk '/[oO][sS][cC].*md[ts]/ { print $4 }')
2308         local OST_DEACTIVE_IDX=-1
2309         local OSC
2310         local OSTIDX
2311         local OST
2312
2313         for OSC in $MDS_OSCS; do
2314                 OST=$(osc_to_ost $OSC)
2315                 OSTIDX=$(index_from_ostuuid $OST)
2316                 if [ $OST_DEACTIVE_IDX == -1 ]; then
2317                         OST_DEACTIVE_IDX=$OSTIDX
2318                 fi
2319                 if [ $OSTIDX != $OST_DEACTIVE_IDX ]; then
2320                         echo $OSC "is Deactivated:"
2321                         do_facet $SINGLEMDS lctl --device  %$OSC deactivate
2322                 fi
2323         done
2324
2325         OSTIDX=$(index_from_ostuuid $OST)
2326         test_mkdir $DIR/$tdir
2327         $LFS setstripe -c 1 $DIR/$tdir      # 1 stripe / file
2328
2329         for OSC in $MDS_OSCS; do
2330                 OST=$(osc_to_ost $OSC)
2331                 OSTIDX=$(index_from_ostuuid $OST)
2332                 if [ $OSTIDX == $OST_DEACTIVE_IDX ]; then
2333                         echo $OST "is degraded:"
2334                         do_facet ost$((OSTIDX+1)) lctl set_param -n \
2335                                                 obdfilter.$OST.degraded=1
2336                 fi
2337         done
2338
2339         sleep_maxage
2340         createmany -o $DIR/$tdir/$tfile $fcount
2341
2342         for OSC in $MDS_OSCS; do
2343                 OST=$(osc_to_ost $OSC)
2344                 OSTIDX=$(index_from_ostuuid $OST)
2345                 if [ $OSTIDX == $OST_DEACTIVE_IDX ]; then
2346                         echo $OST "is recovered from degraded:"
2347                         do_facet ost$((OSTIDX+1)) lctl set_param -n \
2348                                                 obdfilter.$OST.degraded=0
2349                 else
2350                         do_facet $SINGLEMDS lctl --device %$OSC activate
2351                 fi
2352         done
2353
2354         # all osp devices get activated, hence -1 stripe count restored
2355         local stripe_count=0
2356
2357         # sleep 2*lod_qos_maxage seconds waiting for lod qos to notice osp
2358         # devices get activated.
2359         sleep_maxage
2360         $LFS setstripe -c -1 $DIR/$tfile
2361         stripe_count=$($LFS getstripe -c $DIR/$tfile)
2362         rm -f $DIR/$tfile
2363         [ $stripe_count -ne $OSTCOUNT ] &&
2364                 error "Of $OSTCOUNT OSTs, only $stripe_count is available"
2365         return 0
2366 }
2367 run_test 27y "create files while OST0 is degraded and the rest inactive"
2368
2369 test_27z() {
2370         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2371         remote_ost_nodsh && skip "remote OST with nodsh"
2372
2373         test_mkdir $DIR/$tdir
2374         $LFS setstripe -c 1 -i 0 -S 64k $DIR/$tdir/$tfile-1 ||
2375                 { error "setstripe -c -1 failed"; return 1; }
2376         # We need to send a write to every object to get parent FID info set.
2377         # This _should_ also work for setattr, but does not currently.
2378         # touch $DIR/$tdir/$tfile-1 ||
2379         dd if=/dev/zero of=$DIR/$tdir/$tfile-1 bs=1M count=1 ||
2380                 { error "dd $tfile-1 failed"; return 2; }
2381         $LFS setstripe -c -1 -i $((OSTCOUNT - 1)) -S 1M $DIR/$tdir/$tfile-2 ||
2382                 { error "setstripe -c -1 failed"; return 3; }
2383         dd if=/dev/zero of=$DIR/$tdir/$tfile-2 bs=1M count=$OSTCOUNT ||
2384                 { error "dd $tfile-2 failed"; return 4; }
2385
2386         # make sure write RPCs have been sent to OSTs
2387         sync; sleep 5; sync
2388
2389         check_seq_oid $DIR/$tdir/$tfile-1 || return 5
2390         check_seq_oid $DIR/$tdir/$tfile-2 || return 6
2391 }
2392 run_test 27z "check SEQ/OID on the MDT and OST filesystems"
2393
2394 test_27A() { # b=19102
2395         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2396
2397         save_layout_restore_at_exit $MOUNT
2398         $LFS setstripe -c 0 -i -1 -S 0 $MOUNT
2399         wait_update $HOSTNAME "$LFS getstripe -c $MOUNT | sed 's/  *//g'" "1" 20 ||
2400                 error "stripe count $($LFS getstripe -c $MOUNT) != 1"
2401         local default_size=$($LFS getstripe -S $MOUNT)
2402         local default_offset=$($LFS getstripe -i $MOUNT)
2403         local dsize=$(do_facet $SINGLEMDS \
2404                 "$LCTL get_param -n lod.$(facet_svc $SINGLEMDS)*.stripesize")
2405         [ $default_size -eq $dsize ] ||
2406                 error "stripe size $default_size != $dsize"
2407         [ $default_offset -eq -1 ] ||
2408                 error "stripe offset $default_offset != -1"
2409 }
2410 run_test 27A "check filesystem-wide default LOV EA values"
2411
2412 test_27B() { # LU-2523
2413         test_mkdir $DIR/$tdir
2414         rm -f $DIR/$tdir/f0 $DIR/$tdir/f1
2415         touch $DIR/$tdir/f0
2416         # open f1 with O_LOV_DELAY_CREATE
2417         # rename f0 onto f1
2418         # call setstripe ioctl on open file descriptor for f1
2419         # close
2420         multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:nB1c \
2421                 $DIR/$tdir/f0
2422
2423         rm -f $DIR/$tdir/f1
2424         # open f1 with O_LOV_DELAY_CREATE
2425         # unlink f1
2426         # call setstripe ioctl on open file descriptor for f1
2427         # close
2428         multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:uB1c
2429
2430         # Allow multiop to fail in imitation of NFS's busted semantics.
2431         true
2432 }
2433 run_test 27B "call setstripe on open unlinked file/rename victim"
2434
2435 # 27C family tests full striping and overstriping
2436 test_27Ca() { #LU-2871
2437         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2438
2439         declare -a ost_idx
2440         local index
2441         local found
2442         local i
2443         local j
2444
2445         test_mkdir $DIR/$tdir
2446         cd $DIR/$tdir
2447         for i in $(seq 0 $((OSTCOUNT - 1))); do
2448                 # set stripe across all OSTs starting from OST$i
2449                 $LFS setstripe -i $i -c -1 $tfile$i
2450                 # get striping information
2451                 ost_idx=($($LFS getstripe $tfile$i |
2452                          tail -n $((OSTCOUNT + 1)) | awk '{print $1}'))
2453                 echo "OST Index: ${ost_idx[*]}"
2454
2455                 # check the layout
2456                 [ ${#ost_idx[@]} -eq $OSTCOUNT ] ||
2457                         error "${#ost_idx[@]} != $OSTCOUNT"
2458
2459                 for index in $(seq 0 $((OSTCOUNT - 1))); do
2460                         found=0
2461                         for j in "${ost_idx[@]}"; do
2462                                 if [ $index -eq $j ]; then
2463                                         found=1
2464                                         break
2465                                 fi
2466                         done
2467                         [ $found = 1 ] ||
2468                                 error "Can not find $index in ${ost_idx[*]}"
2469                 done
2470         done
2471 }
2472 run_test 27Ca "check full striping across all OSTs"
2473
2474 test_27Cb() {
2475         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2476                 skip "server does not support overstriping"
2477         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
2478                 skip_env "too many osts, skipping"
2479
2480         test_mkdir -p $DIR/$tdir
2481         local setcount=$(($OSTCOUNT * 2))
2482         [ $setcount -lt 160 ] || large_xattr_enabled ||
2483                 skip_env "ea_inode feature disabled"
2484
2485         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2486                 error "setstripe failed"
2487
2488         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2489         [ $count -eq $setcount ] ||
2490                 error "stripe count $count, should be $setcount"
2491
2492         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2493                 error "overstriped should be set in pattern"
2494
2495         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2496                 error "dd failed"
2497 }
2498 run_test 27Cb "more stripes than OSTs with -C"
2499
2500 test_27Cc() {
2501         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2502                 skip "server does not support overstriping"
2503         [[ $OSTCOUNT -lt 2 ]] && skip_env "need > 1 OST"
2504
2505         test_mkdir -p $DIR/$tdir
2506         local setcount=$(($OSTCOUNT - 1))
2507
2508         [ $setcount -lt 160 ] || large_xattr_enabled ||
2509                 skip_env "ea_inode feature disabled"
2510
2511         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2512                 error "setstripe failed"
2513
2514         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2515         [ $count -eq $setcount ] ||
2516                 error "stripe count $count, should be $setcount"
2517
2518         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" &&
2519                 error "overstriped should not be set in pattern"
2520
2521         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2522                 error "dd failed"
2523 }
2524 run_test 27Cc "fewer stripes than OSTs does not set overstriping"
2525
2526 test_27Cd() {
2527         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2528                 skip "server does not support overstriping"
2529         [[ $OSTCOUNT -lt 2 ]] && skip_env "need > 1 OST"
2530         large_xattr_enabled || skip_env "ea_inode feature disabled"
2531
2532         force_new_seq_all
2533
2534         test_mkdir -p $DIR/$tdir
2535         local setcount=$LOV_MAX_STRIPE_COUNT
2536
2537         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2538                 error "setstripe failed"
2539
2540         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2541         [ $count -eq $setcount ] ||
2542                 error "stripe count $count, should be $setcount"
2543
2544         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2545                 error "overstriped should be set in pattern"
2546
2547         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2548                 error "dd failed"
2549
2550         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2551 }
2552 run_test 27Cd "test maximum stripe count"
2553
2554 test_27Ce() {
2555         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2556                 skip "server does not support overstriping"
2557         test_mkdir -p $DIR/$tdir
2558
2559         pool_add $TESTNAME || error "Pool creation failed"
2560         pool_add_targets $TESTNAME 0 || error "pool_add_targets failed"
2561
2562         local setcount=8
2563
2564         $LFS setstripe  -C $setcount -p "$TESTNAME" $DIR/$tdir/$tfile ||
2565                 error "setstripe failed"
2566
2567         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2568         [ $count -eq $setcount ] ||
2569                 error "stripe count $count, should be $setcount"
2570
2571         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2572                 error "overstriped should be set in pattern"
2573
2574         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2575                 error "dd failed"
2576
2577         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2578 }
2579 run_test 27Ce "test pool with overstriping"
2580
2581 test_27Cf() {
2582         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2583                 skip "server does not support overstriping"
2584         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
2585                 skip_env "too many osts, skipping"
2586
2587         test_mkdir -p $DIR/$tdir
2588
2589         local setcount=$(($OSTCOUNT * 2))
2590         [ $setcount -lt 160 ] || large_xattr_enabled ||
2591                 skip_env "ea_inode feature disabled"
2592
2593         $LFS setstripe  -C $setcount $DIR/$tdir/ ||
2594                 error "setstripe failed"
2595
2596         echo 1 > $DIR/$tdir/$tfile
2597
2598         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2599         [ $count -eq $setcount ] ||
2600                 error "stripe count $count, should be $setcount"
2601
2602         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2603                 error "overstriped should be set in pattern"
2604
2605         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2606                 error "dd failed"
2607
2608         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2609 }
2610 run_test 27Cf "test default inheritance with overstriping"
2611
2612 test_27Cg() {
2613         (( MDS1_VERSION >= $(version_code v2_15_55-80-gd96b98ee6b) )) ||
2614                 skip "need MDS version at least v2_15_55-80-gd96b98ee6b for fix"
2615
2616         $LFS setstripe -o 0,$OSTCOUNT $DIR/$tfile
2617         (( $? != 0 )) || error "must be an error for not existent OST#"
2618 }
2619 run_test 27Cg "test setstripe with wrong OST idx"
2620
2621 test_27Ci() {
2622         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2623                 skip "server does not support overstriping"
2624         local tf=$DIR/$tfile
2625
2626         stack_trap "rm -f $DIR/$tfile"
2627
2628         $LFS setstripe -E1M $tf || error "create $tf failed"
2629         $LFS setstripe -Eeof --component-add -C 100 $tf ||
2630                 error "add component failed"
2631
2632         $LFS getstripe -I2 $tf | awk '/lmm_pattern/ { print $2 }' |
2633                 grep "overstriped" || {
2634                 $LFS getstripe $tf
2635                 echo "lose overstriping setting"
2636         }
2637         sc=$($LFS getstripe -I2 --stripe-count $tf)
2638         (( $sc == 100 )) || {
2639                 $LFS getstripe $tf
2640                 echo "lose overstriping setting"
2641         }
2642
2643         stack_trap "rm -f $tf"
2644         dd if=/dev/zero of=$tf bs=1M count=10 || error "write $tf"
2645         sc=$($LFS getstripe -I2 --stripe-count $tf)
2646         (( $sc == 100 )) || {
2647                 $LFS getstripe $tf
2648                 echo "lose overstriping setting after instantiation"
2649         }
2650 }
2651 run_test 27Ci "add an overstriping component"
2652
2653 test_27Cj() {
2654         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2655                 skip "server does not support overstriping"
2656         (( $MDS1_VERSION >= $(version_code 2.15.61.76) )) ||
2657                 skip "need MDS >= 2.15.61.76"
2658
2659         stack_trap "rm -f $DIR/$tfile"
2660
2661         #check that beyond -32 it fails
2662         echo "setstripe -C -33 should fail"
2663         $LFS setstripe -C -33 $DIR/$tfile && error "setstripe should fail"
2664
2665         # start_full_debug_logging
2666         # number of stripes created will be 32*ost count
2667         $LFS setstripe  -C -32 $DIR/$tfile || error "create $tfile failed"
2668         local count=$($LFS getstripe -c $DIR/$tfile)
2669         local stripe_cnt=$(($OSTCOUNT * 32))
2670         (( $count == $stripe_cnt )) ||
2671                 error "$DIR/$tfile stripe count $count != $stripe_cnt"
2672 }
2673 run_test 27Cj "overstriping with -C for max values in multiple of targets"
2674
2675 test_27D() {
2676         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
2677         remote_mds_nodsh && skip "remote MDS with nodsh"
2678
2679         local POOL=${POOL:-testpool}
2680         local first_ost=0
2681         local last_ost=$(($OSTCOUNT - 1))
2682         local ost_step=1
2683         local ost_list=$(seq $first_ost $ost_step $last_ost)
2684         local ost_range="$first_ost $last_ost $ost_step"
2685
2686         test_mkdir $DIR/$tdir
2687         pool_add $POOL || error "pool_add failed"
2688         pool_add_targets $POOL $ost_range || error "pool_add_targets failed"
2689
2690         (( $MDS1_VERSION >= $(version_code 2.8.55) )) ||
2691                 SKIP27D+=" -s 29"
2692         (( $MDS1_VERSION >= $(version_code 2.9.55) &&
2693            $CLIENT_VERSION >= $(version_code 2.9.55) )) ||
2694                 SKIP27D+=" -s 30,31"
2695         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] &&
2696         (( $OSTCOUNT < $LOV_MAX_STRIPE_COUNT / 2)) ||
2697                 SKIP27D+=" -s 32,33"
2698         (( $MDS1_VERSION >= $(version_code $SEL_VER) )) ||
2699                 SKIP27D+=" -s 34"
2700         llapi_layout_test -d$DIR/$tdir -p$POOL -o$OSTCOUNT $SKIP27D ||
2701                 error "llapi_layout_test failed"
2702
2703         destroy_test_pools || error "destroy test pools failed"
2704 }
2705 run_test 27D "validate llapi_layout API"
2706
2707 # Verify that default_easize is increased from its initial value after
2708 # accessing a widely striped file.
2709 test_27E() {
2710         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
2711         [ $CLIENT_VERSION -lt $(version_code 2.5.57) ] &&
2712                 skip "client does not have LU-3338 fix"
2713
2714         # 72 bytes is the minimum space required to store striping
2715         # information for a file striped across one OST:
2716         # (sizeof(struct lov_user_md_v3) +
2717         #  sizeof(struct lov_user_ost_data_v1))
2718         local min_easize=72
2719         $LCTL set_param -n llite.*.default_easize $min_easize ||
2720                 error "lctl set_param failed"
2721         local easize=$($LCTL get_param -n llite.*.default_easize)
2722
2723         [ $easize -eq $min_easize ] ||
2724                 error "failed to set default_easize"
2725
2726         $LFS setstripe -c $OSTCOUNT $DIR/$tfile ||
2727                 error "setstripe failed"
2728         # In order to ensure stat() call actually talks to MDS we need to
2729         # do something drastic to this file to shake off all lock, e.g.
2730         # rename it (kills lookup lock forcing cache cleaning)
2731         mv $DIR/$tfile $DIR/${tfile}-1
2732         ls -l $DIR/${tfile}-1
2733         rm $DIR/${tfile}-1
2734
2735         easize=$($LCTL get_param -n llite.*.default_easize)
2736
2737         [ $easize -gt $min_easize ] ||
2738                 error "default_easize not updated"
2739 }
2740 run_test 27E "check that default extended attribute size properly increases"
2741
2742 test_27F() { # LU-5346/LU-7975
2743         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2744         [[ $OSTCOUNT -lt 2 ]] && skip "needs >= 2 OSTs"
2745         [[ $MDS1_VERSION -lt $(version_code 2.8.51) ]] &&
2746                 skip "Need MDS version at least 2.8.51"
2747         remote_ost_nodsh && skip "remote OST with nodsh"
2748
2749         test_mkdir $DIR/$tdir
2750         rm -f $DIR/$tdir/f0
2751         $LFS setstripe -c 2 $DIR/$tdir
2752
2753         # stop all OSTs to reproduce situation for LU-7975 ticket
2754         for num in $(seq $OSTCOUNT); do
2755                 stop ost$num
2756         done
2757
2758         # open/create f0 with O_LOV_DELAY_CREATE
2759         # truncate f0 to a non-0 size
2760         # close
2761         multiop $DIR/$tdir/f0 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:T1050000c
2762
2763         $CHECKSTAT -s 1050000 $DIR/$tdir/f0 || error "checkstat failed"
2764         # open/write it again to force delayed layout creation
2765         cat /etc/hosts > $DIR/$tdir/f0 &
2766         catpid=$!
2767
2768         # restart OSTs
2769         for num in $(seq $OSTCOUNT); do
2770                 start ost$num $(ostdevname $num) $OST_MOUNT_OPTS ||
2771                         error "ost$num failed to start"
2772         done
2773
2774         wait $catpid || error "cat failed"
2775
2776         cmp /etc/hosts $DIR/$tdir/f0 || error "cmp failed"
2777         [[ $($LFS getstripe -c $DIR/$tdir/f0) == 2 ]] ||
2778                 error "wrong stripecount"
2779
2780 }
2781 run_test 27F "Client resend delayed layout creation with non-zero size"
2782
2783 test_27G() { #LU-10629
2784         (( $MDS1_VERSION < $(version_code 2.11.51) )) &&
2785                 skip "Need MDS version at least 2.11.51"
2786         remote_mds_nodsh && skip "remote MDS with nodsh"
2787         local POOL=${POOL:-testpool}
2788         local ostrange="0 0 1"
2789
2790         test_mkdir $DIR/$tdir
2791         touch $DIR/$tdir/$tfile.nopool
2792         pool_add $POOL || error "pool_add failed"
2793         pool_add_targets $POOL $ostrange || error "pool_add_targets failed"
2794         $LFS setstripe -p $POOL $DIR/$tdir
2795
2796         local pool=$($LFS getstripe -p $DIR/$tdir)
2797
2798         [ "$pool" = "$POOL" ] || error "Striping failed got '$pool' not '$POOL'"
2799         touch $DIR/$tdir/$tfile.default
2800         $LFS setstripe -E 1M --pool $POOL -c 1 -E eof -c 1 $DIR/$tdir/$tfile.pfl
2801         $LFS find $DIR/$tdir -type f --pool $POOL
2802         local found=$($LFS find $DIR/$tdir -type f --pool $POOL | wc -l)
2803         [[ "$found" == "2" ]] ||
2804                 error "found $found != 2 files in '$DIR/$tdir' in '$POOL'"
2805
2806         $LFS setstripe -d $DIR/$tdir
2807
2808         pool=$($LFS getstripe -p -d $DIR/$tdir)
2809
2810         [[ "$pool" != "$POOL" ]] || error "$DIR/$tdir is still '$pool'"
2811 }
2812 run_test 27G "Clear OST pool from stripe"
2813
2814 test_27H() {
2815         [[ $MDS1_VERSION -le $(version_code 2.11.54) ]] &&
2816                 skip "Need MDS version newer than 2.11.54"
2817         [[ $OSTCOUNT -lt 3 ]] && skip_env "needs >= 3 OSTs"
2818         test_mkdir $DIR/$tdir
2819         $LFS setstripe -o 0 -o 2 $DIR/$tdir || error "setstripe failed"
2820         touch $DIR/$tdir/$tfile
2821         $LFS getstripe -c $DIR/$tdir/$tfile
2822         [ $($LFS getstripe -c $DIR/$tdir/$tfile) -eq 2 ] ||
2823                 error "two-stripe file doesn't have two stripes"
2824
2825         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
2826         $LFS getstripe -y $DIR/$tdir/$tfile
2827         (( $($LFS getstripe -y $DIR/$tdir/$tfile |
2828              egrep -c "l_ost_idx: [02]$") == "2" )) ||
2829                 error "expected l_ost_idx: [02]$ not matched"
2830
2831         # make sure ost list has been cleared
2832         local stripesize=$($LFS getstripe -S $DIR/$tdir)
2833         $LFS setstripe -S $((stripesize * 4)) -i 1 \
2834                 -c $((OSTCOUNT - 1)) $DIR/$tdir || error "setstripe"
2835         touch $DIR/$tdir/f3
2836         $LVERIFY $DIR/$tdir $DIR/$tdir/f3 || error "lverify failed"
2837 }
2838 run_test 27H "Set specific OSTs stripe"
2839
2840 test_27I() {
2841         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2842         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2843         [[ $MDS1_VERSION -gt $(version_code 2.12.52) ]] ||
2844                 skip "Need MDS version newer than 2.12.52"
2845         local pool=$TESTNAME
2846         local ostrange="1 1 1"
2847
2848         save_layout_restore_at_exit $MOUNT
2849         $LFS setstripe -c 2 -i 0 $MOUNT
2850         pool_add $pool || error "pool_add failed"
2851         pool_add_targets $pool $ostrange ||
2852                 error "pool_add_targets failed"
2853         test_mkdir $DIR/$tdir
2854         $LFS setstripe -p $pool $DIR/$tdir
2855         $MULTIOP $DIR/$tdir/$tfile Oc || error "multiop failed"
2856         $LFS getstripe $DIR/$tdir/$tfile
2857 }
2858 run_test 27I "check that root dir striping does not break parent dir one"
2859
2860 test_27Ia() {
2861         (( $MDS1_VERSION >= $(version_code 2.15.61.225) )) ||
2862                 skip "need MDS >= 2.15.61.255 for pool inheritance fix"
2863
2864         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
2865
2866         save_layout_restore_at_exit $MOUNT
2867         pool_add $TESTNAME || error "pool_add failed"
2868         pool_add_targets $TESTNAME 1 || error "pool_add_targets failed"
2869
2870         $LFS setstripe -p $TESTNAME $MOUNT
2871
2872         test_mkdir $DIR/$tdir
2873         $LFS setstripe -i0 $DIR/$tdir
2874         $MULTIOP $DIR/$tdir/$tfile.1 Oc || error_noexit "multiop failed"
2875         $LFS getstripe $DIR/$tdir/$tfile.1
2876
2877         $LFS setstripe -d $DIR/$tdir
2878         $LFS setstripe -o 0,1 $DIR/$tdir
2879         $MULTIOP $DIR/$tdir/$tfile.2 Oc || error_noexit "multiop failed"
2880         $LFS getstripe $DIR/$tdir/$tfile.2
2881
2882         test_mkdir $DIR/$tdir/d1
2883         $MULTIOP $DIR/$tdir/d1/$tfile.3 Oc || error_noexit "multiop failed"
2884         $LFS getstripe $DIR/$tdir/d1/$tfile.3
2885
2886         $LFS setstripe -d $DIR/$tdir
2887         $LFS setstripe -E 128G -o 0,1 -E-1 $DIR/$tdir
2888         test_mkdir $DIR/$tdir/d2
2889         $MULTIOP $DIR/$tdir/d2/$tfile.4 Oc || error_noexit "multiop failed"
2890         $LFS getstripe $DIR/$tdir/d2/$tfile.4
2891 }
2892 run_test 27Ia "check that root dir pool is dropped with conflict parent dir settings"
2893
2894 test_27J() {
2895         (( $MDS1_VERSION > $(version_code 2.12.51) )) ||
2896                 skip "Need MDS version newer than 2.12.51"
2897
2898
2899         test_mkdir $DIR/$tdir
2900         local uuid1=$(cat /proc/sys/kernel/random/uuid)
2901         local uuid2=$(cat /proc/sys/kernel/random/uuid)
2902
2903         # create foreign file (raw way)
2904         ! $LFS setstripe --flags 0xda08 $DIR/$tdir/$tfile ||
2905                 error "creating $tfile w/ hex flags w/o --foreign should fail"
2906
2907         ! $LFS setstripe --foreign --flags foo \
2908                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tfile ||
2909                         error "creating $tfile with '--flags foo' should fail"
2910
2911         ! $LFS setstripe --foreign --flags 0xffffffff \
2912                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tfile ||
2913                         error "creating $tfile w/ 0xffffffff flags should fail"
2914
2915         create_foreign_file -f $DIR/$tdir/$tfile -x "${uuid1}@${uuid2}" \
2916                 -t 1 -F 0xda08 || error "create_foreign_file failed"
2917
2918         # verify foreign file (raw way)
2919         parse_foreign_file -f $DIR/$tdir/$tfile |
2920                 grep "lov_foreign_magic: 0x0BD70BD0" ||
2921                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign magic"
2922         parse_foreign_file -f $DIR/$tdir/$tfile | grep "lov_xattr_size: 89" ||
2923                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign size"
2924         parse_foreign_file -f $DIR/$tdir/$tfile |
2925                 grep "lov_foreign_size: 73" ||
2926                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign size"
2927         parse_foreign_file -f $DIR/$tdir/$tfile |
2928                 grep "lov_foreign_type: 1" ||
2929                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign type"
2930         parse_foreign_file -f $DIR/$tdir/$tfile |
2931                 grep "lov_foreign_flags: 0x0000DA08" ||
2932                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign flags"
2933         local lov=$(parse_foreign_file -f $DIR/$tdir/$tfile |
2934                 grep "lov_foreign_value: 0x" |
2935                 sed -e 's/lov_foreign_value: 0x//')
2936         local lov2=$(echo -n "${uuid1}@${uuid2}" | od -A n -t x1 -w160)
2937         [[ $lov = ${lov2// /} ]] ||
2938                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign value"
2939
2940         # create foreign file (lfs + API)
2941         $LFS setstripe --foreign=none --flags 0xda08 \
2942                 -x "${uuid1}@${uuid2}" $DIR/$tdir/${tfile}2 ||
2943                 error "$DIR/$tdir/${tfile}2: create failed"
2944
2945         $LFS getstripe -v $DIR/$tdir/${tfile}2 |
2946                 grep "lfm_magic:.*0x0BD70BD0" ||
2947                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign magic"
2948         # lfm_length is LOV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
2949         $LFS getstripe -v $DIR/$tdir/${tfile}2 | grep "lfm_length:.*73" ||
2950                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign size"
2951         $LFS getstripe -v $DIR/$tdir/${tfile}2 | grep "lfm_type:.*none" ||
2952                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign type"
2953         $LFS getstripe -v $DIR/$tdir/${tfile}2 |
2954                 grep "lfm_flags:.*0x0000DA08" ||
2955                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign flags"
2956         $LFS getstripe $DIR/$tdir/${tfile}2 |
2957                 grep "lfm_value:.*${uuid1}@${uuid2}" ||
2958                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign value"
2959
2960         # modify striping should fail
2961         $LFS setstripe -c 2 $DIR/$tdir/$tfile &&
2962                 error "$DIR/$tdir/$tfile: setstripe should fail"
2963         $LFS setstripe -c 2 $DIR/$tdir/${tfile}2 &&
2964                 error "$DIR/$tdir/${tfile}2: setstripe should fail"
2965
2966         # skip basic ops on file with foreign LOV tests on >5.12 kernels
2967         (( $LINUX_VERSION_CODE < $(version_code 5.12.0) )) && {
2968                 # kernel >= 5.12.0 would skip filemap_read() with 0 sized file
2969                 # R/W should fail
2970                 cat $DIR/$tdir/$tfile &&
2971                         error "$DIR/$tdir/$tfile: read should fail"
2972                 cat $DIR/$tdir/${tfile}2 &&
2973                         error "$DIR/$tdir/${tfile}2: read should fail"
2974                 cat /etc/passwd > $DIR/$tdir/$tfile &&
2975                         error "$DIR/$tdir/$tfile: write should fail"
2976                 cat /etc/passwd > $DIR/$tdir/${tfile}2 &&
2977                         error "$DIR/$tdir/${tfile}2: write should fail"
2978         }
2979
2980         # chmod should work
2981         chmod 222 $DIR/$tdir/$tfile ||
2982                 error "$DIR/$tdir/$tfile: chmod failed"
2983         chmod 222 $DIR/$tdir/${tfile}2 ||
2984                 error "$DIR/$tdir/${tfile}2: chmod failed"
2985
2986         # chown should work
2987         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/$tfile ||
2988                 error "$DIR/$tdir/$tfile: chown failed"
2989         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tfile}2 ||
2990                 error "$DIR/$tdir/${tfile}2: chown failed"
2991
2992         # rename should work
2993         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}.new ||
2994                 error "$DIR/$tdir/$tfile: rename of foreign file has failed"
2995         mv $DIR/$tdir/${tfile}2 $DIR/$tdir/${tfile}2.new ||
2996                 error "$DIR/$tdir/${tfile}2: rename of foreign file has failed"
2997
2998         #remove foreign file
2999         rm $DIR/$tdir/${tfile}.new ||
3000                 error "$DIR/$tdir/${tfile}.new: remove of foreign file has failed"
3001         rm $DIR/$tdir/${tfile}2.new ||
3002                 error "$DIR/$tdir/${tfile}2.new: remove of foreign file has failed"
3003 }
3004 run_test 27J "basic ops on file with foreign LOV"
3005
3006 test_27K() {
3007         [[ $MDS1_VERSION -le $(version_code 2.12.49) ]] &&
3008                 skip "Need MDS version newer than 2.12.49"
3009
3010         test_mkdir $DIR/$tdir
3011         local uuid1=$(cat /proc/sys/kernel/random/uuid)
3012         local uuid2=$(cat /proc/sys/kernel/random/uuid)
3013
3014         # create foreign dir (raw way)
3015         ! $LFS setdirstripe --flags 0xda08 $DIR/$tdir/$tdir ||
3016                 error "creating $tdir w/ hex flags w/o --foreign should fail"
3017
3018         ! $LFS setdirstripe --foreign --flags foo \
3019                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tdir ||
3020                         error "creating $tdir with '--flags foo' should fail"
3021
3022         ! $LFS setdirstripe --foreign --flags 0xffffffff \
3023                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tdir ||
3024                         error "creating $tdir w/ 0xffffffff flags should fail"
3025
3026         create_foreign_dir -d $DIR/$tdir/$tdir -x "${uuid1}@${uuid2}" -t 1 ||
3027                 error "create_foreign_dir FAILED"
3028
3029         # verify foreign dir (raw way)
3030         parse_foreign_dir -d $DIR/$tdir/$tdir |
3031                 grep "lmv_foreign_magic:.*0xcd50cd0" ||
3032                 error "$DIR/$tdir/$tfile: invalid LMV EA magic"
3033         parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_xattr_size:.*89$" ||
3034                 error "$DIR/$tdir/$tdir: invalid LMV EA size"
3035         parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_foreign_type: 1$" ||
3036                 error "$DIR/$tdir/$tdir: invalid LMV EA type"
3037         parse_foreign_dir -d $DIR/$tdir/$tdir |
3038                 grep "lmv_foreign_flags: 55813$" ||
3039                 error "$DIR/$tdir/$tdir: invalid LMV EA flags"
3040         local lmv=$(parse_foreign_dir -d $DIR/$tdir/$tdir |
3041                 grep "lmv_foreign_value: 0x" |
3042                 sed 's/lmv_foreign_value: 0x//')
3043         local lmv2=$(echo -n "${uuid1}@${uuid2}" | od -A n -t x1 -w160 |
3044                 sed 's/ //g')
3045         [[ $lmv == $lmv2 ]] || error "$DIR/$tdir/$tdir: invalid LMV EA value"
3046
3047         # create foreign dir (lfs + API)
3048         $LFS mkdir --foreign=none --xattr="${uuid1}@${uuid2}" --flags=0xda05 \
3049                 $DIR/$tdir/${tdir}2 ||
3050                 error "$DIR/$tdir/${tdir}2: create failed"
3051
3052         $LFS getdirstripe -v $DIR/$tdir/${tdir}2
3053
3054         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
3055                 grep "lfm_magic:.*0x0CD50CD0" ||
3056                 error "$DIR/$tdir/${tdir}2: invalid LMV EA magic"
3057         # lfm_length is LMV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
3058         # - sizeof(lfm_type) - sizeof(lfm_flags)
3059         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_length:.*73" ||
3060                 error "$DIR/$tdir/${tdir}2: invalid LMV EA size"
3061         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_type:.*none" ||
3062                 error "$DIR/$tdir/${tdir}2: invalid LMV EA type"
3063         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
3064                 grep "lfm_flags:.*0x0000DA05" ||
3065                 error "$DIR/$tdir/${tdir}2: invalid LMV EA flags"
3066         $LFS getdirstripe $DIR/$tdir/${tdir}2 |
3067                 grep "lfm_value.*${uuid1}@${uuid2}" ||
3068                 error "$DIR/$tdir/${tdir}2: invalid LMV EA value"
3069
3070         # file create in dir should fail
3071         touch $DIR/$tdir/$tdir/$tfile && error "$DIR/$tdir: file create should fail"
3072         touch $DIR/$tdir/${tdir}2/$tfile &&
3073                 error "$DIR/${tdir}2: file create should fail"
3074
3075         # chmod should work
3076         chmod 777 $DIR/$tdir/$tdir ||
3077                 error "$DIR/$tdir: chmod failed"
3078         chmod 777 $DIR/$tdir/${tdir}2 ||
3079                 error "$DIR/${tdir}2: chmod failed"
3080
3081         # chown should work
3082         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/$tdir ||
3083                 error "$DIR/$tdir: chown failed"
3084         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}2 ||
3085                 error "$DIR/${tdir}2: chown failed"
3086
3087         # rename should work
3088         mv $DIR/$tdir/$tdir $DIR/$tdir/${tdir}.new ||
3089                 error "$DIR/$tdir/$tdir: rename of foreign dir has failed"
3090         mv $DIR/$tdir/${tdir}2 $DIR/$tdir/${tdir}2.new ||
3091                 error "$DIR/$tdir/${tdir}2: rename of foreign dir has failed"
3092
3093         #remove foreign dir
3094         rmdir $DIR/$tdir/${tdir}.new ||
3095                 error "$DIR/$tdir/${tdir}.new: remove of foreign dir has failed"
3096         rmdir $DIR/$tdir/${tdir}2.new ||
3097                 error "$DIR/$tdir/${tdir}2.new: remove of foreign dir has failed"
3098 }
3099 run_test 27K "basic ops on dir with foreign LMV"
3100
3101 test_27L() {
3102         remote_mds_nodsh && skip "remote MDS with nodsh"
3103
3104         local POOL=${POOL:-$TESTNAME}
3105
3106         pool_add $POOL || error "pool_add failed"
3107
3108         lfs pool_list $MOUNT | grep -Fx "${FSNAME}.${POOL}" ||
3109                  error "pool_list does not contain ${FSNAME}.${POOL}:" \
3110                        "$(lfs pool_list $MOUNT | grep -F "${POOL}")"
3111 }
3112 run_test 27L "lfs pool_list gives correct pool name"
3113
3114 test_27M() {
3115         (( $MDS1_VERSION >= $(version_code 2.12.57) )) ||
3116                 skip "Need MDS version >= than 2.12.57"
3117         remote_mds_nodsh && skip "remote MDS with nodsh"
3118         (( $OSTCOUNT > 1 )) || skip "need > 1 OST"
3119
3120         # Set default striping on directory
3121         local setcount=4
3122         local stripe_opt
3123         local mdts=$(comma_list $(mdts_nodes))
3124
3125         # if we run against a 2.12 server which lacks overstring support
3126         # then the connect_flag will not report overstriping, even if client
3127         # is 2.14+
3128         if [[ $($LCTL get_param mdc.*.connect_flags) =~ overstriping ]]; then
3129                 stripe_opt="-C $setcount"
3130         elif (( $OSTCOUNT >= $setcount )); then
3131                 stripe_opt="-c $setcount"
3132         else
3133                 skip "server does not support overstriping"
3134         fi
3135
3136         test_mkdir $DIR/$tdir
3137
3138         # Validate existing append_* params and ensure restore
3139         local pool=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_pool)
3140         [[ "$pool" == "" ]] || error "expected append_pool == '', got '$pool'"
3141         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_pool=none"
3142
3143         # Validate append_pool name length
3144         (( $MDS1_VERSION >= $(version_code 2.15.61) )) &&
3145                 do_nodes $mdts $LCTL \
3146                         set_param mdd.*.append_pool="LOV_MAXPOOLNAME*" &&
3147                         error "Wrong pool name length should report error"
3148
3149         local orig_count=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_stripe_count)
3150         ((orig_count == 1)) || error "expected append_stripe_count == 1, got $orig_count"
3151         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=1"
3152
3153         $LFS setstripe $stripe_opt $DIR/$tdir
3154
3155         echo 1 > $DIR/$tdir/${tfile}.1
3156         local count=$($LFS getstripe -c $DIR/$tdir/${tfile}.1)
3157         (( $count == $setcount )) ||
3158                 error "(1) stripe count $count, should be $setcount"
3159
3160         local appendcount=$orig_count
3161         echo 1 >> $DIR/$tdir/${tfile}.2_append
3162         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.2_append)
3163         (( $count == $appendcount )) ||
3164                 error "(2)stripe count $count, should be $appendcount for append"
3165
3166         # Disable O_APPEND striping, verify it works
3167         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=0
3168
3169         # Should now get the default striping, which is 4
3170         setcount=4
3171         echo 1 >> $DIR/$tdir/${tfile}.3_append
3172         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.3_append)
3173         (( $count == $setcount )) ||
3174                 error "(3) stripe count $count, should be $setcount"
3175
3176         # Try changing the stripe count for append files
3177         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=2
3178
3179         # Append striping is now 2 (directory default is still 4)
3180         appendcount=2
3181         echo 1 >> $DIR/$tdir/${tfile}.4_append
3182         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.4_append)
3183         (( $count == $appendcount )) ||
3184                 error "(4) stripe count $count, should be $appendcount for append"
3185
3186         # Test append stripe count of -1
3187         # Exercise LU-16872 patch with specific striping, only if MDS has fix
3188         (( $MDS1_VERSION > $(version_code 2.15.56.46) )) &&
3189                 $LFS setstripe -o 0,$((OSTCOUNT - 1)) $DIR/$tdir &&
3190                 touch $DIR/$tdir/$tfile.specific.{1..128}
3191         stack_trap "rm -f $DIR/$tdir/$tfile.*"
3192
3193         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=-1
3194         appendcount=$OSTCOUNT
3195         echo 1 >> $DIR/$tdir/${tfile}.5
3196         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.5)
3197         (( $count == $appendcount )) ||
3198                 error "(5) stripe count $count, should be $appendcount for append"
3199
3200         # Set append striping back to default of 1
3201         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=1
3202
3203         # Try a new default striping, PFL + DOM
3204         $LFS setstripe -L mdt -E 1M -E -1 -c 2 $DIR/$tdir
3205
3206         # Create normal DOM file, DOM returns stripe count == 0
3207         setcount=0
3208         touch $DIR/$tdir/${tfile}.6
3209         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.6)
3210         (( $count == $setcount )) ||
3211                 error "(6) stripe count $count, should be $setcount"
3212
3213         # Show
3214         appendcount=1
3215         echo 1 >> $DIR/$tdir/${tfile}.7_append
3216         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.7_append)
3217         (( $count == $appendcount )) ||
3218                 error "(7) stripe count $count, should be $appendcount for append"
3219
3220         # Clean up DOM layout
3221         $LFS setstripe -d $DIR/$tdir
3222
3223         # rest of tests don't work with FILESET
3224         [ -n "$FILESET" ] && exit
3225
3226         save_layout_restore_at_exit $MOUNT
3227         # Now test that append striping works when layout is from root
3228         $LFS setstripe -c 2 $MOUNT
3229         # Make a special directory for this
3230         mkdir $DIR/${tdir}/${tdir}.2
3231
3232         # Verify for normal file
3233         setcount=2
3234         echo 1 > $DIR/${tdir}/${tdir}.2/${tfile}.8
3235         count=$($LFS getstripe -c $DIR/$tdir/${tdir}.2/${tfile}.8)
3236         (( $count == $setcount )) ||
3237                 error "(8) stripe count $count, should be $setcount"
3238
3239         appendcount=1
3240         echo 1 >> $DIR/${tdir}/${tdir}.2/${tfile}.9_append
3241         count=$($LFS getstripe -c $DIR/${tdir}/${tdir}.2/${tfile}.9_append)
3242         (( $count == $appendcount )) ||
3243                 error "(9) stripe count $count, should be $appendcount for append"
3244
3245         # Now test O_APPEND striping with pools
3246         pool_add $TESTNAME || error "pool creation failed"
3247         pool_add_targets $TESTNAME 0 1 || error "Pool add targets failed"
3248         do_nodes $mdts $LCTL set_param mdd.*.append_pool="$TESTNAME"
3249
3250         echo 1 >> $DIR/$tdir/${tfile}.10_append
3251
3252         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.10_append)
3253         [[ "$pool" == "$TESTNAME" ]] || error "(10) incorrect pool: $pool"
3254
3255         # Check that count is still correct
3256         appendcount=1
3257         echo 1 >> $DIR/$tdir/${tfile}.11_append
3258         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.11_append)
3259         (( $count == $appendcount )) ||
3260                 error "(11) stripe count $count, should be $appendcount for append"
3261
3262         # Disable O_APPEND stripe count, verify pool works separately
3263         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=0
3264
3265         echo 1 >> $DIR/$tdir/${tfile}.12_append
3266
3267         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.12_append)
3268         [[ "$pool" == "$TESTNAME" ]] || error "(12) incorrect pool: $pool"
3269
3270         # Remove pool setting, verify it's not applied
3271         do_nodes $mdts $LCTL set_param mdd.*.append_pool='none'
3272
3273         echo 1 >> $DIR/$tdir/${tfile}.13_append
3274
3275         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.13_append)
3276         [[ -z "$pool" ]] || error "(13) pool found: $pool"
3277 }
3278 run_test 27M "test O_APPEND striping"
3279
3280 test_27N() {
3281         combined_mgs_mds && skip "needs separate MGS/MDT"
3282
3283         pool_add $TESTNAME || error "pool_add failed"
3284         do_facet mgs "$LCTL pool_list $FSNAME" |
3285                 grep -Fx "${FSNAME}.${TESTNAME}" ||
3286                 error "lctl pool_list on MGS failed"
3287 }
3288 run_test 27N "lctl pool_list on separate MGS gives correct pool name"
3289
3290 clean_foreign_symlink() {
3291         trap 0
3292         lctl set_param llite/$FSNAME-*/foreign_symlink_enable=0
3293         for i in $DIR/$tdir/* ; do
3294                 $LFS unlink_foreign $i || true
3295         done
3296 }
3297
3298 test_27O() {
3299         [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.51) ]] &&
3300                 skip "Need MDS version newer than 2.12.51"
3301
3302         test_mkdir $DIR/$tdir
3303         local uuid1=$(cat /proc/sys/kernel/random/uuid)
3304         local uuid2=$(cat /proc/sys/kernel/random/uuid)
3305
3306         trap clean_foreign_symlink EXIT
3307
3308         # enable foreign_symlink behaviour
3309         $LCTL set_param llite/$FSNAME-*/foreign_symlink_enable=1
3310
3311         # foreign symlink LOV format is a partial path by default
3312
3313         # create foreign file (lfs + API)
3314         $LFS setstripe --foreign=symlink --flags 0xda05 \
3315                 -x "${uuid1}/${uuid2}" --mode 0600 $DIR/$tdir/${tfile} ||
3316                 error "$DIR/$tdir/${tfile}: create failed"
3317
3318         $LFS getstripe -v $DIR/$tdir/${tfile} |
3319                 grep "lfm_magic:.*0x0BD70BD0" ||
3320                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign magic"
3321         $LFS getstripe -v $DIR/$tdir/${tfile} | grep "lfm_type:.*symlink" ||
3322                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign type"
3323         $LFS getstripe -v $DIR/$tdir/${tfile} |
3324                 grep "lfm_flags:.*0x0000DA05" ||
3325                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign flags"
3326         $LFS getstripe $DIR/$tdir/${tfile} |
3327                 grep "lfm_value:.*${uuid1}/${uuid2}" ||
3328                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign value"
3329
3330         # modify striping should fail
3331         $LFS setstripe -c 2 $DIR/$tdir/$tfile &&
3332                 error "$DIR/$tdir/$tfile: setstripe should fail"
3333
3334         # R/W should fail ("/{foreign_symlink_prefix}/${uuid1}/" missing)
3335         cat $DIR/$tdir/$tfile && error "$DIR/$tdir/$tfile: read should fail"
3336         cat /etc/passwd > $DIR/$tdir/$tfile &&
3337                 error "$DIR/$tdir/$tfile: write should fail"
3338
3339         # rename should succeed
3340         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}.new ||
3341                 error "$DIR/$tdir/$tfile: rename has failed"
3342
3343         #remove foreign_symlink file should fail
3344         rm $DIR/$tdir/${tfile}.new &&
3345                 error "$DIR/$tdir/${tfile}.new: remove of foreign_symlink file should fail"
3346
3347         #test fake symlink
3348         mkdir /tmp/${uuid1} ||
3349                 error "/tmp/${uuid1}: mkdir has failed"
3350         echo FOOFOO > /tmp/${uuid1}/${uuid2} ||
3351                 error "/tmp/${uuid1}/${uuid2}: echo has failed"
3352         $LCTL set_param llite/$FSNAME-*/foreign_symlink_prefix=/tmp/
3353         $CHECKSTAT -t link -l /tmp/${uuid1}/${uuid2} $DIR/$tdir/${tfile}.new ||
3354                 error "$DIR/$tdir/${tfile}.new: not seen as a symlink"
3355         #read should succeed now
3356         cat $DIR/$tdir/${tfile}.new | grep FOOFOO ||
3357                 error "$DIR/$tdir/${tfile}.new: symlink resolution has failed"
3358         #write should succeed now
3359         cat /etc/passwd > $DIR/$tdir/${tfile}.new ||
3360                 error "$DIR/$tdir/${tfile}.new: write should succeed"
3361         diff /etc/passwd $DIR/$tdir/${tfile}.new ||
3362                 error "$DIR/$tdir/${tfile}.new: diff has failed"
3363         diff /etc/passwd /tmp/${uuid1}/${uuid2} ||
3364                 error "/tmp/${uuid1}/${uuid2}: diff has failed"
3365
3366         #check that getstripe still works
3367         $LFS getstripe $DIR/$tdir/${tfile}.new ||
3368                 error "$DIR/$tdir/${tfile}.new: getstripe should still work with foreign_symlink enabled"
3369
3370         # chmod should still succeed
3371         chmod 644 $DIR/$tdir/${tfile}.new ||
3372                 error "$DIR/$tdir/${tfile}.new: chmod has failed"
3373
3374         # chown should still succeed
3375         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tfile}.new ||
3376                 error "$DIR/$tdir/${tfile}.new: chown has failed"
3377
3378         # rename should still succeed
3379         mv $DIR/$tdir/${tfile}.new $DIR/$tdir/${tfile} ||
3380                 error "$DIR/$tdir/${tfile}.new: rename has failed"
3381
3382         #remove foreign_symlink file should still fail
3383         rm $DIR/$tdir/${tfile} &&
3384                 error "$DIR/$tdir/${tfile}: remove of foreign_symlink file should fail"
3385
3386         #use special ioctl() to unlink foreign_symlink file
3387         $LFS unlink_foreign $DIR/$tdir/${tfile} ||
3388                 error "$DIR/$tdir/$tfile: unlink/ioctl failed"
3389
3390 }
3391 run_test 27O "basic ops on foreign file of symlink type"
3392
3393 test_27P() {
3394         [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.49) ]] &&
3395                 skip "Need MDS version newer than 2.12.49"
3396
3397         test_mkdir $DIR/$tdir
3398         local uuid1=$(cat /proc/sys/kernel/random/uuid)
3399         local uuid2=$(cat /proc/sys/kernel/random/uuid)
3400
3401         trap clean_foreign_symlink EXIT
3402
3403         # enable foreign_symlink behaviour
3404         $LCTL set_param llite/$FSNAME-*/foreign_symlink_enable=1
3405
3406         # foreign symlink LMV format is a partial path by default
3407
3408         # create foreign dir (lfs + API)
3409         $LFS mkdir --foreign=symlink --xattr="${uuid1}/${uuid2}" \
3410                 --flags=0xda05 --mode 0750 $DIR/$tdir/${tdir} ||
3411                 error "$DIR/$tdir/${tdir}: create failed"
3412
3413         $LFS getdirstripe -v $DIR/$tdir/${tdir}
3414
3415         $LFS getdirstripe -v $DIR/$tdir/${tdir} |
3416                 grep "lfm_magic:.*0x0CD50CD0" ||
3417                 error "$DIR/$tdir/${tdir}: invalid LMV EA magic"
3418         $LFS getdirstripe -v $DIR/$tdir/${tdir} | grep "lfm_type:.*symlink" ||
3419                 error "$DIR/$tdir/${tdir}: invalid LMV EA type"
3420         $LFS getdirstripe -v $DIR/$tdir/${tdir} |
3421                 grep "lfm_flags:.*0x0000DA05" ||
3422                 error "$DIR/$tdir/${tdir}: invalid LMV EA flags"
3423         $LFS getdirstripe $DIR/$tdir/${tdir} |
3424                 grep "lfm_value.*${uuid1}/${uuid2}" ||
3425                 error "$DIR/$tdir/${tdir}: invalid LMV EA value"
3426
3427         # file create in dir should fail
3428         # ("/{foreign_symlink_prefix}/${uuid1}/${uuid2}/" missing)
3429         touch $DIR/$tdir/$tdir/$tfile && error "$DIR/$tdir: file create should fail"
3430
3431         # rename should succeed
3432         mv $DIR/$tdir/$tdir $DIR/$tdir/${tdir}.new ||
3433                 error "$DIR/$tdir/$tdir: rename of foreign_symlink dir has failed"
3434
3435         #remove foreign_symlink dir should fail
3436         rmdir $DIR/$tdir/${tdir}.new &&
3437                 error "$DIR/$tdir/${tdir}.new: remove of foreign_symlink dir should fail"
3438
3439         #test fake symlink
3440         mkdir -p /tmp/${uuid1}/${uuid2} ||
3441                 error "/tmp/${uuid1}/${uuid2}: mkdir has failed"
3442         echo FOOFOO > /tmp/${uuid1}/${uuid2}/foo ||
3443                 error "/tmp/${uuid1}/${uuid2}/foo: echo has failed"
3444         $LCTL set_param llite/$FSNAME-*/foreign_symlink_prefix=/tmp/
3445         $CHECKSTAT -t link -l /tmp/${uuid1}/${uuid2} $DIR/$tdir/${tdir}.new ||
3446                 error "$DIR/$tdir/${tdir}.new: not seen as a symlink"
3447         cat $DIR/$tdir/${tdir}.new/foo | grep FOOFOO ||
3448                 error "$DIR/$tdir/${tdir}.new: symlink resolution has failed"
3449
3450         #check that getstripe fails now that foreign_symlink enabled
3451         $LFS getdirstripe $DIR/$tdir/${tdir}.new ||
3452                 error "$DIR/$tdir/${tdir}.new: getdirstripe should still work with foreign_symlink enabled"
3453
3454         # file create in dir should work now
3455         cp /etc/passwd $DIR/$tdir/${tdir}.new/$tfile ||
3456                 error "$DIR/$tdir/${tdir}.new/$tfile: file create should fail"
3457         diff /etc/passwd $DIR/$tdir/${tdir}.new/$tfile ||
3458                 error "$DIR/$tdir/${tdir}.new/$tfile: diff has failed"
3459         diff /etc/passwd /tmp/${uuid1}/${uuid2}/$tfile ||
3460                 error "/tmp/${uuid1}/${uuid2}/$tfile: diff has failed"
3461
3462         # chmod should still succeed
3463         chmod 755 $DIR/$tdir/${tdir}.new ||
3464                 error "$DIR/$tdir/${tdir}.new: chmod has failed"
3465
3466         # chown should still succeed
3467         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}.new ||
3468                 error "$DIR/$tdir/${tdir}.new: chown has failed"
3469
3470         # rename should still succeed
3471         mv $DIR/$tdir/${tdir}.new $DIR/$tdir/${tdir} ||
3472                 error "$DIR/$tdir/${tdir}.new: rename of foreign_symlink dir has failed"
3473
3474         #remove foreign_symlink dir should still fail
3475         rmdir $DIR/$tdir/${tdir} &&
3476                 error "$DIR/$tdir/${tdir}: remove of foreign_symlink dir should fail"
3477
3478         #use special ioctl() to unlink foreign_symlink file
3479         $LFS unlink_foreign $DIR/$tdir/${tdir} ||
3480                 error "$DIR/$tdir/$tdir: unlink/ioctl failed"
3481
3482         #created file should still exist
3483         [[ -f /tmp/${uuid1}/${uuid2}/$tfile ]] ||
3484                 error "/tmp/${uuid1}/${uuid2}/$tfile has been removed"
3485         diff /etc/passwd /tmp/${uuid1}/${uuid2}/$tfile ||
3486                 error "/tmp/${uuid1}/${uuid2}/$tfile: diff has failed"
3487 }
3488 run_test 27P "basic ops on foreign dir of foreign_symlink type"
3489
3490 test_27Q() {
3491         rm -f $TMP/$tfile $TMP/$tfile.loop $TMP/$tfile.none $TMP/$tfile.broken
3492         stack_trap "rm -f $TMP/$tfile*"
3493
3494         test_mkdir $DIR/$tdir-1
3495         test_mkdir $DIR/$tdir-2
3496
3497         echo 'It is what it is' > $DIR/$tdir-1/$tfile
3498         lov_getstripe_old $DIR/$tdir-1/$tfile || error "$DIR/$tdir-1/$tfile: rc = $?"
3499
3500         ln -s $DIR/$tdir-1/$tfile $DIR/$tdir-2/$tfile
3501         lov_getstripe_old $DIR/$tdir-2/$tfile || error "$DIR/$tdir-2/$tfile: rc = $?"
3502
3503         ln -s $DIR/$tdir-1/$tfile $TMP/$tfile
3504         lov_getstripe_old $TMP/$tfile || error "$TMP/$tfile: rc = $?"
3505
3506         # Create some bad symlinks and ensure that we don't loop
3507         # forever or something. These should return ELOOP (40) and
3508         # ENOENT (2) but I don't want to test for that because there's
3509         # always some weirdo architecture that needs to ruin
3510         # everything by defining these error numbers differently.
3511
3512         ln -s $TMP/$tfile.loop $TMP/$tfile.loop
3513         lov_getstripe_old $TMP/$tfile.loop && error "$TMP/$tfile.loop: rc = $?"
3514
3515         ln -s $TMP/$tfile.none $TMP/$tfile.broken
3516         lov_getstripe_old $TMP/$tfile.broken && error "$TMP/$tfile.broken: rc = $?"
3517
3518         return 0
3519 }
3520 run_test 27Q "llapi_file_get_stripe() works on symlinks"
3521
3522 test_27R() {
3523         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
3524                 skip "need MDS 2.14.55 or later"
3525         (( $OSTCOUNT >= 2 )) || skip_env "needs at least 2 OSTs"
3526
3527         local testdir="$DIR/$tdir"
3528         test_mkdir -p $testdir
3529         stack_trap "rm -rf $testdir"
3530         $LFS setstripe -c -1 $testdir || error "setstripe failed"
3531
3532         local f1="$testdir/f1"
3533         touch $f1 || error "failed to touch $f1"
3534         local count=$($LFS getstripe -c $f1)
3535         (( $count == $OSTCOUNT )) || error "wrong stripe count"
3536
3537         do_facet $SINGLEMDS $LCTL set_param lod.*.max_stripecount=-1
3538         (( $? == 34 )) || error "setting max_stripecount to -1 should fail and return ERANGE"
3539
3540         local maxcount=$(($OSTCOUNT - 1))
3541         local mdts=$(comma_list $(mdts_nodes))
3542         do_nodes $mdts $LCTL set_param lod.*.max_stripecount=$maxcount
3543         stack_trap "do_nodes $mdts $LCTL set_param lod.*.max_stripecount=0"
3544
3545         local f2="$testdir/f2"
3546         touch $f2 || error "failed to touch $f2"
3547         local count=$($LFS getstripe -c $f2)
3548         (( $count == $maxcount )) || error "wrong stripe count"
3549 }
3550 run_test 27R "test max_stripecount limitation when stripe count is set to -1"
3551
3552 test_27T() {
3553         (( $OST1_VERSION >= $(version_code 2.15.65.18) )) ||
3554                 skip "need ost1 >= v2_15_65-18-g8a865c65c691 for ENOSPC fix"
3555         [ $(facet_host client) == $(facet_host ost1) ] &&
3556                 skip "need ost1 and client on different nodes"
3557
3558         # CFS_FAIL_ONCE is needed to get cfs_fail_count reset
3559         #define OBD_FAIL_OSC_NO_GRANT            0x411
3560         #define CFS_FAIL_SKIP                    0x20000000
3561         #define CFS_FAIL_ONCE                    0x80000000
3562         $LCTL set_param fail_loc=0xa0000411 fail_val=1
3563         #define OBD_FAIL_OST_ENOSPC_VALID        0x255
3564         do_facet ost1 "$LCTL set_param fail_loc=0x80000255"
3565         $LFS setstripe -i 0 -c 1 $DIR/$tfile
3566         # DIO does not support partial writes to a single stripe - a write to
3567         # each stripe will fail or succeed entirely.  So we disable hybrid IO
3568         # so we can see the partial write behavior of buffered IO
3569         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
3570         $LCTL set_param llite.*.hybrid_io=0
3571         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
3572
3573         local pagesz=$(getconf PAGESIZE)
3574         local pagenr=$($LCTL get_param -n osc.*-OST0000-*.max_pages_per_rpc)
3575
3576         $MULTIOP $DIR/$tfile oO_WRONLY:P$(((pagenr + 10) * pagesz))c ||
3577                 error "multiop failed"
3578         (( $(stat -c '%s' $DIR/$tfile) == pagenr * pagesz )) ||
3579                 error "wrong size"
3580
3581         # this is to reset cfs_fail_count and to clear ar_force_sync flags
3582         $MULTIOP $DIR/$tfile oO_WRONLY:w${pagesz}c
3583 }
3584 run_test 27T "no eio on close on partial write due to enosp"
3585
3586 test_27U() {
3587         local dir=$DIR/$tdir
3588         local file=$dir/$tfile
3589         local append_pool=${TESTNAME}-append
3590         local normal_pool=${TESTNAME}-normal
3591         local pool
3592         local stripe_count
3593         local stripe_count2
3594         local mdts=$(comma_list $(mdts_nodes))
3595
3596         (( $MDS1_VERSION >= $(version_code 2.15.51) )) ||
3597                 skip "Need MDS version at least 2.15.51 for append pool feature"
3598
3599         # Validate existing append_* params and ensure restore
3600         pool=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_pool)
3601         [[ "$pool" == "" ]] || error "expected append_pool == '', got '$pool'"
3602         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_pool=none"
3603
3604         stripe_count=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_stripe_count)
3605         ((stripe_count == 1)) || error "expected append_stripe_count != 0, got $stripe_count"
3606         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=$stripe_count"
3607
3608         pool_add $append_pool || error "pool creation failed"
3609         pool_add_targets $append_pool 0 1 || error "Pool add targets failed"
3610
3611         pool_add $normal_pool || error "pool creation failed"
3612         pool_add_targets $normal_pool 0 1 || error "Pool add targets failed"
3613
3614         test_mkdir $dir
3615         $LFS setstripe -E 1M -c 1 -p $normal_pool -E 2M -c 2 -p $normal_pool -E eof -c -1 $dir
3616
3617         echo XXX >> $file.1
3618         $LFS getstripe $file.1
3619
3620         pool=$($LFS getstripe -p $file.1)
3621         [[ "$pool" == "$normal_pool" ]] || error "got pool '$pool', expected '$normal_pool'"
3622
3623         stripe_count2=$($LFS getstripe -c $file.1)
3624         ((stripe_count2 == stripe_count)) ||
3625                 error "got stripe_count '$stripe_count2', expected '$stripe_count'"
3626
3627         do_nodes $mdts $LCTL set_param mdd.*.append_pool=$append_pool
3628
3629         echo XXX >> $file.2
3630         $LFS getstripe $file.2
3631
3632         pool=$($LFS getstripe -p $file.2)
3633         [[ "$pool" == "$append_pool" ]] || error "got pool '$pool', expected '$append_pool'"
3634
3635         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=2
3636
3637         echo XXX >> $file.3
3638         $LFS getstripe $file.3
3639
3640         stripe_count2=$($LFS getstripe -c $file.3)
3641         ((stripe_count2 == 2)) || error "got stripe_count '$stripe_count2', expected 2"
3642 }
3643 run_test 27U "append pool and stripe count work with composite default layout"
3644
3645 test_27V() {
3646         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3647         (( $OSTCOUNT >= 4 )) || skip_env "needs >= 4 OSTs"
3648
3649         local dir=$DIR/$tdir
3650         local osp_param=osp.$FSNAME-OST0000-osc-MDT0000.max_create_count
3651         local lod_param=lod.$FSNAME-MDT0000-mdtlov.qos_threshold_rr
3652         local saved_max=$(do_facet mds1 $LCTL get_param -n $osp_param)
3653         local saved_qos=$(do_facet mds1 $LCTL get_param -n $lod_param)
3654         local pid
3655
3656         stack_trap "do_facet mds1 $LCTL set_param $osp_param=$saved_max"
3657
3658         do_facet mds1 $LCTL set_param $lod_param=0
3659         stack_trap "do_facet mds1 $LCTL set_param $lod_param=$saved_qos"
3660
3661         $LFS setdirstripe --mdt-count=1 --mdt-index=0 $dir
3662         stack_trap "rm -rf $dir"
3663
3664         # exercise race in LU-16981 with deactivating OST while creating a file
3665         (
3666                 while true; do
3667                         do_facet mds1 $LCTL set_param $osp_param=0 > /dev/null
3668                         sleep 0.1
3669                         do_facet mds1 \
3670                                 $LCTL set_param $osp_param=$saved_max > /dev/null
3671                 done
3672         ) &
3673
3674         pid=$!
3675         stack_trap "kill -9 $pid"
3676
3677         # errors here are OK so ignore them (just don't want to crash)
3678         $LFS setstripe -c -1 $dir/f.{1..200} 2> /dev/null
3679
3680         return 0
3681 }
3682 run_test 27V "creating widely striped file races with deactivating OST"
3683
3684 test_27W() {
3685         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
3686                 skip "server does not support overstriping"
3687         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3688         local stripe_count
3689         local defcount=4
3690
3691         # Set back to unrestricted
3692         stack_trap "$LCTL set_param llite.$FSNAME-*.enable_setstripe_gid=-1"
3693
3694         mkdir $DIR/$tdir
3695         # Set a default layout
3696         $LFS setstripe -C $defcount $DIR/$tdir || error "(0) root failed to set default layout"
3697
3698         chmod a+rw $DIR
3699         chmod a+rw $DIR/$tdir
3700         # Verify this works normally
3701         $RUNAS $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "(1) failed to setstripe"
3702         rm -f $DIR/$tdir/$tfile
3703
3704         # Limit to CAP_SYS_RESOURCE
3705         $LCTL set_param llite.$FSNAME-*.enable_setstripe_gid=0
3706         # Prints a messsage, but will use the default layout for the directory
3707         # This is so scripts which use setstripe and don't check error will not fail
3708         $RUNAS $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "(2) setstripe failed"
3709         # Verify default layout was used on file:
3710         stripe_count=$($LFS getstripe -c $DIR/$tdir/$tfile)
3711         ((stripe_count == defcount)) ||
3712                 error "(3) got stripe_count '$stripe_count', expected $defcount"
3713         rm -f $DIR/$tdir/$tfile
3714
3715         # Allow for RUNAS group
3716         $LCTL set_param llite.$FSNAME-*.enable_setstripe_gid=$RUNAS_GID
3717         $RUNAS $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "(4) failed to setstripe"
3718         # Confirm we did not use the default layout
3719         stripe_count=$($LFS getstripe -c $DIR/$tdir/$tfile)
3720         ((stripe_count == 1)) || error "(5) got stripe_count '$stripe_count', expected 1"
3721         rm -f $DIR/$tdir/$tfile
3722
3723         # Set to some other GID
3724         $LCTL set_param llite.$FSNAME-*.enable_setstripe_gid=1
3725         # Should give warning and succeed
3726         $RUNAS $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "(6) setstripe failed"
3727         # Confirm we used default layout
3728         stripe_count=$($LFS getstripe -c $DIR/$tdir/$tfile)
3729         ((stripe_count == defcount)) ||
3730                 error "(7) got stripe_count '$stripe_count', expected $defcount"
3731 }
3732 run_test 27W "test enable_setstripe_gid"
3733
3734 test_27X() {
3735         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
3736                 skip "server does not support overstriping"
3737
3738         local file=$DIR/$tfile
3739         local count
3740         local overstripe_count=$((OSTCOUNT * 2))
3741
3742         # Create a small file
3743         dd if=/dev/zero of=$file bs=1K count=1 || error "dd failed"
3744
3745         # Migrate with --overstripe-count=2*OSTCOUNT
3746         $LFS migrate --overstripe-count=$overstripe_count $file ||
3747                 error "migrate failed"
3748
3749         # Check that the stripe count is 2*OSTCOUNT
3750         count=$($LFS getstripe -c $file)
3751         [ $count -eq $overstripe_count ] ||
3752                 error "stripe count is $count, expected $overstripe_count"
3753
3754         # Check that the file has the overstriping flag set
3755         $LFS getstripe $file | grep -q "overstriped" ||
3756                 error "overstriping flag not set"
3757
3758         # Clean up
3759         rm -f $file
3760 }
3761 run_test 27X "lfs migrate honors --overstripe-count option"
3762
3763 # createtest also checks that device nodes are created and
3764 # then visible correctly (#2091)
3765 test_28() { # bug 2091
3766         test_mkdir $DIR/d28
3767         $CREATETEST $DIR/d28/ct || error "createtest failed"
3768 }
3769 run_test 28 "create/mknod/mkdir with bad file types ============"
3770
3771 test_29() {
3772         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3773
3774         [ $MDS1_VERSION -ge $(version_code 2.14.51) ] && {
3775                 disable_opencache
3776                 stack_trap "restore_opencache"
3777         }
3778
3779         sync; sleep 1; sync # flush out any dirty pages from previous tests
3780         cancel_lru_locks
3781         test_mkdir $DIR/d29
3782         touch $DIR/d29/foo
3783         log 'first d29'
3784         ls -l $DIR/d29
3785
3786         local locks_orig=$(total_used_locks mdc)
3787         (( $locks_orig != 0 )) || error "No mdc lock count"
3788
3789         local locks_unused_orig=$(total_unused_locks mdc)
3790
3791         log 'second d29'
3792         ls -l $DIR/d29
3793         log 'done'
3794
3795         local locks_current=$(total_used_locks mdc)
3796
3797         local locks_unused_current=$(total_unused_locks mdc)
3798
3799         if (( $locks_current > $locks_orig )); then
3800                 $LCTL set_param -n ldlm.dump_namespaces ""
3801                 error "CURRENT: $locks_current > $locks_orig"
3802         fi
3803         if (( $locks_unused_current > $locks_unused_orig )); then
3804                 error "UNUSED: $locks_unused_current > $locks_unused_orig"
3805         fi
3806 }
3807 run_test 29 "IT_GETATTR regression  ============================"
3808
3809 test_30a() { # was test_30
3810         cp $(which ls) $DIR || cp /bin/ls $DIR
3811         $DIR/ls / || error "Can't execute binary from lustre"
3812         rm $DIR/ls
3813 }
3814 run_test 30a "execute binary from Lustre (execve) =============="
3815
3816 test_30b() {
3817         cp `which ls` $DIR || cp /bin/ls $DIR
3818         chmod go+rx $DIR/ls
3819         $RUNAS $DIR/ls / || error "Can't execute binary from lustre as non-root"
3820         rm $DIR/ls
3821 }
3822 run_test 30b "execute binary from Lustre as non-root ==========="
3823
3824 test_30c() { # b=22376
3825         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3826
3827         cp $(which ls) $DIR || cp /bin/ls $DIR
3828         chmod a-rw $DIR/ls
3829         cancel_lru_locks mdc
3830         cancel_lru_locks osc
3831         $RUNAS $DIR/ls / || error "Can't execute binary from lustre"
3832         rm -f $DIR/ls
3833 }
3834 run_test 30c "execute binary from Lustre without read perms ===="
3835
3836 test_30d() {
3837         cp $(which dd) $DIR || error "failed to copy dd to $DIR/dd"
3838
3839         for i in {1..10}; do
3840                 $DIR/dd bs=1M count=128 if=/dev/zero of=$DIR/$tfile &
3841                 local PID=$!
3842                 sleep 1
3843                 $LCTL set_param ldlm.namespaces.*MDT*.lru_size=clear
3844                 wait $PID || error "executing dd from Lustre failed"
3845                 rm -f $DIR/$tfile
3846         done
3847
3848         rm -f $DIR/dd
3849 }
3850 run_test 30d "execute binary from Lustre while clear locks"
3851
3852 test_31a() {
3853         $OPENUNLINK $DIR/f31 $DIR/f31 || error "openunlink failed"
3854         $CHECKSTAT -a $DIR/f31 || error "$DIR/f31 exists"
3855 }
3856 run_test 31a "open-unlink file =================================="
3857
3858 test_31b() {
3859         touch $DIR/f31 || error "touch $DIR/f31 failed"
3860         ln $DIR/f31 $DIR/f31b || error "ln failed"
3861         $MULTIOP $DIR/f31b Ouc || error "multiop failed"
3862         $CHECKSTAT -t file $DIR/f31 || error "$DIR/f31 not file type"
3863 }
3864 run_test 31b "unlink file with multiple links while open ======="
3865
3866 test_31c() {
3867         touch $DIR/f31 || error "touch $DIR/f31 failed"
3868         ln $DIR/f31 $DIR/f31c || error "ln failed"
3869         multiop_bg_pause $DIR/f31 O_uc ||
3870                 error "multiop_bg_pause for $DIR/f31 failed"
3871         MULTIPID=$!
3872         $MULTIOP $DIR/f31c Ouc
3873         kill -USR1 $MULTIPID
3874         wait $MULTIPID
3875 }
3876 run_test 31c "open-unlink file with multiple links ============="
3877
3878 test_31d() {
3879         opendirunlink $DIR/d31d $DIR/d31d || error "opendirunlink failed"
3880         $CHECKSTAT -a $DIR/d31d || error "$DIR/d31d exists"
3881 }
3882 run_test 31d "remove of open directory ========================="
3883
3884 test_31e() { # bug 2904
3885         openfilleddirunlink $DIR/d31e || error "openfilleddirunlink failed"
3886 }
3887 run_test 31e "remove of open non-empty directory ==============="
3888
3889 test_31f() { # bug 4554
3890         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3891
3892         set -vx
3893         test_mkdir $DIR/d31f
3894         $LFS setstripe -S 1048576 -c 1 $DIR/d31f
3895         cp /etc/hosts $DIR/d31f
3896         ls -l $DIR/d31f
3897         $LFS getstripe $DIR/d31f/hosts
3898         multiop_bg_pause $DIR/d31f D_c || return 1
3899         MULTIPID=$!
3900
3901         rm -rv $DIR/d31f || error "first of $DIR/d31f"
3902         test_mkdir $DIR/d31f
3903         $LFS setstripe -S 1048576 -c 1 $DIR/d31f
3904         cp /etc/hosts $DIR/d31f
3905         ls -l $DIR/d31f
3906         $LFS getstripe $DIR/d31f/hosts
3907         multiop_bg_pause $DIR/d31f D_c || return 1
3908         MULTIPID2=$!
3909
3910         kill -USR1 $MULTIPID || error "first opendir $MULTIPID not running"
3911         wait $MULTIPID || error "first opendir $MULTIPID failed"
3912
3913         sleep 6
3914
3915         kill -USR1 $MULTIPID2 || error "second opendir $MULTIPID not running"
3916         wait $MULTIPID2 || error "second opendir $MULTIPID2 failed"
3917         set +vx
3918 }
3919 run_test 31f "remove of open directory with open-unlink file ==="
3920
3921 test_31g() {
3922         echo "-- cross directory link --"
3923         test_mkdir -c1 $DIR/${tdir}ga
3924         test_mkdir -c1 $DIR/${tdir}gb
3925         touch $DIR/${tdir}ga/f
3926         ln $DIR/${tdir}ga/f $DIR/${tdir}gb/g
3927         $CHECKSTAT -t file $DIR/${tdir}ga/f || error "source"
3928         [ `stat -c%h $DIR/${tdir}ga/f` == '2' ] || error "source nlink"
3929         $CHECKSTAT -t file $DIR/${tdir}gb/g || error "target"
3930         [ `stat -c%h $DIR/${tdir}gb/g` == '2' ] || error "target nlink"
3931 }
3932 run_test 31g "cross directory link==============="
3933
3934 test_31h() {
3935         echo "-- cross directory link --"
3936         test_mkdir -c1 $DIR/${tdir}
3937         test_mkdir -c1 $DIR/${tdir}/dir
3938         touch $DIR/${tdir}/f
3939         ln $DIR/${tdir}/f $DIR/${tdir}/dir/g
3940         $CHECKSTAT -t file $DIR/${tdir}/f || error "source"
3941         [ `stat -c%h $DIR/${tdir}/f` == '2' ] || error "source nlink"
3942         $CHECKSTAT -t file $DIR/${tdir}/dir/g || error "target"
3943         [ `stat -c%h $DIR/${tdir}/dir/g` == '2' ] || error "target nlink"
3944 }
3945 run_test 31h "cross directory link under child==============="
3946
3947 test_31i() {
3948         echo "-- cross directory link --"
3949         test_mkdir -c1 $DIR/$tdir
3950         test_mkdir -c1 $DIR/$tdir/dir
3951         touch $DIR/$tdir/dir/f
3952         ln $DIR/$tdir/dir/f $DIR/$tdir/g
3953         $CHECKSTAT -t file $DIR/$tdir/dir/f || error "source"
3954         [ `stat -c%h $DIR/$tdir/dir/f` == '2' ] || error "source nlink"
3955         $CHECKSTAT -t file $DIR/$tdir/g || error "target"
3956         [ `stat -c%h $DIR/$tdir/g` == '2' ] || error "target nlink"
3957 }
3958 run_test 31i "cross directory link under parent==============="
3959
3960 test_31j() {
3961         test_mkdir -c1 -p $DIR/$tdir
3962         test_mkdir -c1 -p $DIR/$tdir/dir1
3963         ln $DIR/$tdir/dir1 $DIR/$tdir/dir2 && error "ln for dir"
3964         link $DIR/$tdir/dir1 $DIR/$tdir/dir3 && error "link for dir"
3965         link $DIR/$tdir/dir1 $DIR/$tdir/dir1 && error "link to the same dir"
3966         return 0
3967 }
3968 run_test 31j "link for directory"
3969
3970 test_31k() {
3971         test_mkdir -c1 -p $DIR/$tdir
3972         touch $DIR/$tdir/s
3973         touch $DIR/$tdir/exist
3974         link $DIR/$tdir/s $DIR/$tdir/t || error "link"
3975         link $DIR/$tdir/s $DIR/$tdir/exist && error "link to exist file"
3976         link $DIR/$tdir/s $DIR/$tdir/s && error "link to the same file"
3977         link $DIR/$tdir/s $DIR/$tdir && error "link to parent dir"
3978         link $DIR/$tdir $DIR/$tdir/s && error "link parent dir to target"
3979         link $DIR/$tdir/not-exist $DIR/$tdir/foo && error "link non-existing to new"
3980         link $DIR/$tdir/not-exist $DIR/$tdir/s && error "link non-existing to exist"
3981         return 0
3982 }
3983 run_test 31k "link to file: the same, non-existing, dir"
3984
3985 test_31l() {
3986         local ln_ver=$(ln --version | awk '/coreutils/ { print $4 }')
3987
3988         (( $(version_code $ln_ver) < $(version_code 8.31) )) ||
3989         (( $(version_code $(uname -r)) >= $(version_code 5.18) )) ||
3990                 skip "need coreutils < 8.31 or kernel >= 5.18 for ln"
3991
3992         touch $DIR/$tfile || error "create failed"
3993         mkdir $DIR/$tdir || error "mkdir failed"
3994         ln $DIR/$tfile $DIR/$tdir/ || error "ln to '$tdir/' failed"
3995 }
3996 run_test 31l "link to file: target dir has trailing slash"
3997
3998 test_31m() {
3999         mkdir $DIR/d31m
4000         touch $DIR/d31m/s
4001         mkdir $DIR/d31m2
4002         touch $DIR/d31m2/exist
4003         link $DIR/d31m/s $DIR/d31m2/t || error "link"
4004         link $DIR/d31m/s $DIR/d31m2/exist && error "link to exist file"
4005         link $DIR/d31m/s $DIR/d31m2 && error "link to parent dir"
4006         link $DIR/d31m2 $DIR/d31m/s && error "link parent dir to target"
4007         link $DIR/d31m/not-exist $DIR/d31m2/foo && error "link non-existing to new"
4008         link $DIR/d31m/not-exist $DIR/d31m2/s && error "link non-existing to exist"
4009         return 0
4010 }
4011 run_test 31m "link to file: the same, non-existing, dir"
4012
4013 test_31n() {
4014         touch $DIR/$tfile || error "cannot create '$DIR/$tfile'"
4015         nlink=$(stat --format=%h $DIR/$tfile)
4016         [ ${nlink:--1} -eq 1 ] || error "nlink is $nlink, expected 1"
4017         local fd=$(free_fd)
4018         local cmd="exec $fd<$DIR/$tfile"
4019         eval $cmd
4020         cmd="exec $fd<&-"
4021         trap "eval $cmd" EXIT
4022         nlink=$(stat --dereference --format=%h /proc/self/fd/$fd)
4023         [ ${nlink:--1} -eq 1 ] || error "nlink is $nlink, expected 1"
4024         rm $DIR/$tfile || error "cannot remove '$DIR/$tfile'"
4025         nlink=$(stat --dereference --format=%h /proc/self/fd/$fd)
4026         [ ${nlink:--1} -eq 0 ] || error "nlink is $nlink, expected 0"
4027         eval $cmd
4028 }
4029 run_test 31n "check link count of unlinked file"
4030
4031 link_one() {
4032         local tempfile=$(mktemp $1_XXXXXX)
4033         link $tempfile $1 2> /dev/null &&
4034                 echo "$BASHPID: link $tempfile to $1 succeeded"
4035         unlink $tempfile
4036 }
4037
4038 test_31o() { # LU-2901
4039         test_mkdir $DIR/$tdir
4040         for LOOP in $(seq 100); do
4041                 rm -f $DIR/$tdir/$tfile*
4042                 for THREAD in $(seq 8); do
4043                         link_one $DIR/$tdir/$tfile.$LOOP &
4044                 done
4045                 wait
4046                 local LINKS=$(ls -1 $DIR/$tdir | grep -c $tfile.$LOOP)
4047                 [[ $LINKS -gt 1 ]] && ls $DIR/$tdir &&
4048                         error "$LINKS duplicate links to $tfile.$LOOP" &&
4049                         break || true
4050         done
4051 }
4052 run_test 31o "duplicate hard links with same filename"
4053
4054 test_31p() {
4055         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4056
4057         test_mkdir $DIR/$tdir
4058         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4059         $LFS setdirstripe -D -c2 -H all_char $DIR/$tdir/striped_dir
4060
4061         opendirunlink $DIR/$tdir/striped_dir/test1 ||
4062                 error "open unlink test1 failed"
4063         opendirunlink $DIR/$tdir/striped_dir/test2 ||
4064                 error "open unlink test2 failed"
4065
4066         $CHECKSTAT -a $DIR/$tdir/striped_dir/test1 ||
4067                 error "test1 still exists"
4068         $CHECKSTAT -a $DIR/$tdir/striped_dir/test2 ||
4069                 error "test2 still exists"
4070 }
4071 run_test 31p "remove of open striped directory"
4072
4073 test_31q() {
4074         [ $MDSCOUNT -lt 3 ] && skip_env "needs >= 3 MDTs"
4075
4076         $LFS mkdir -i 3,1 $DIR/$tdir || error "mkdir failed"
4077         index=$($LFS getdirstripe -i $DIR/$tdir)
4078         [ $index -eq 3 ] || error "first stripe index $index != 3"
4079         index=$($LFS getdirstripe $DIR/$tdir | tail -1 | awk '{print $1}')
4080         [ $index -eq 1 ] || error "second stripe index $index != 1"
4081
4082         # when "-c <stripe_count>" is set, the number of MDTs specified after
4083         # "-i" should equal to the stripe count
4084         $LFS mkdir -i 3,1 -c 3 $DIR/$tdir.2 && error "mkdir should fail" || true
4085 }
4086 run_test 31q "create striped directory on specific MDTs"
4087
4088 #LU-14949
4089 test_31r() {
4090         touch $DIR/$tfile.target
4091         touch $DIR/$tfile.source
4092
4093         #OBD_FAIL_LLITE_OPEN_DELAY 0x1419
4094         $LCTL set_param fail_loc=0x1419 fail_val=3
4095         cat $DIR/$tfile.target &
4096         CATPID=$!
4097
4098         # Guarantee open is waiting before we get here
4099         sleep 1
4100         mv $DIR/$tfile.source $DIR/$tfile.target
4101
4102         wait $CATPID
4103         RC=$?
4104         if [[ $RC -ne 0 ]]; then
4105                 error "open with cat failed, rc=$RC"
4106         fi
4107 }
4108 run_test 31r "open-rename(replace) race"
4109
4110 cleanup_test32_mount() {
4111         local rc=0
4112         trap 0
4113         local loopdev=$(losetup -a | grep $EXT2_DEV | sed -ne 's/:.*$//p')
4114         $UMOUNT $DIR/$tdir/ext2-mountpoint || rc=$?
4115         losetup -d $loopdev || true
4116         rm -rf $DIR/$tdir
4117         return $rc
4118 }
4119
4120 test_32a() {
4121         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4122
4123         echo "== more mountpoints and symlinks ================="
4124         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4125         trap cleanup_test32_mount EXIT
4126         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4127         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4128                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4129         $CHECKSTAT -t dir $DIR/$tdir/ext2-mountpoint/.. ||
4130                 error "$DIR/$tdir/ext2-mountpoint/.. not dir type"
4131         cleanup_test32_mount
4132 }
4133 run_test 32a "stat d32a/ext2-mountpoint/.. ====================="
4134
4135 test_32b() {
4136         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4137
4138         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4139         trap cleanup_test32_mount EXIT
4140         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4141         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4142                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4143         ls -al $DIR/$tdir/ext2-mountpoint/.. ||
4144                 error "Can't list $DIR/$tdir/ext2-mountpoint/.."
4145         cleanup_test32_mount
4146 }
4147 run_test 32b "open d32b/ext2-mountpoint/.. ====================="
4148
4149 test_32c() {
4150         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4151
4152         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4153         trap cleanup_test32_mount EXIT
4154         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4155         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4156                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4157         test_mkdir -p $DIR/$tdir/d2/test_dir
4158         $CHECKSTAT -t dir $DIR/$tdir/ext2-mountpoint/../d2/test_dir ||
4159                 error "$DIR/$tdir/ext2-mountpoint/../d2/test_dir not dir type"
4160         cleanup_test32_mount
4161 }
4162 run_test 32c "stat d32c/ext2-mountpoint/../d2/test_dir ========="
4163
4164 test_32d() {
4165         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4166
4167         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4168         trap cleanup_test32_mount EXIT
4169         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4170         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4171                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4172         test_mkdir -p $DIR/$tdir/d2/test_dir
4173         ls -al $DIR/$tdir/ext2-mountpoint/../d2/test_dir ||
4174                 error "Can't list $DIR/$tdir/ext2-mountpoint/../d2/test_dir"
4175         cleanup_test32_mount
4176 }
4177 run_test 32d "open d32d/ext2-mountpoint/../d2/test_dir"
4178
4179 test_32e() {
4180         rm -fr $DIR/$tdir
4181         test_mkdir -p $DIR/$tdir/tmp
4182         local tmp_dir=$DIR/$tdir/tmp
4183         ln -s $DIR/$tdir $tmp_dir/symlink11
4184         ln -s $tmp_dir/symlink11 $tmp_dir/../symlink01
4185         $CHECKSTAT -t link $DIR/$tdir/tmp/symlink11 || error "symlink11 bad"
4186         $CHECKSTAT -t link $DIR/$tdir/symlink01 || error "symlink01 bad"
4187 }
4188 run_test 32e "stat d32e/symlink->tmp/symlink->lustre-subdir"
4189
4190 test_32f() {
4191         rm -fr $DIR/$tdir
4192         test_mkdir -p $DIR/$tdir/tmp
4193         local tmp_dir=$DIR/$tdir/tmp
4194         ln -s $DIR/$tdir $tmp_dir/symlink11
4195         ln -s $tmp_dir/symlink11 $tmp_dir/../symlink01
4196         ls $DIR/$tdir/tmp/symlink11  || error "symlink11 bad"
4197         ls $DIR/$tdir/symlink01 || error "symlink01 bad"
4198 }
4199 run_test 32f "open d32f/symlink->tmp/symlink->lustre-subdir"
4200
4201 test_32g() {
4202         local tmp_dir=$DIR/$tdir/tmp
4203         test_mkdir -p $tmp_dir
4204         test_mkdir $DIR/${tdir}2
4205         ln -s $DIR/${tdir}2 $tmp_dir/symlink12
4206         ln -s $tmp_dir/symlink12 $tmp_dir/../symlink02
4207         $CHECKSTAT -t link $tmp_dir/symlink12 || error "symlink12 not a link"
4208         $CHECKSTAT -t link $DIR/$tdir/symlink02 || error "symlink02 not a link"
4209         $CHECKSTAT -t dir -f $tmp_dir/symlink12 || error "symlink12 not a dir"
4210         $CHECKSTAT -t dir -f $DIR/$tdir/symlink02 || error "symlink12 not a dir"
4211 }
4212 run_test 32g "stat d32g/symlink->tmp/symlink->lustre-subdir/${tdir}2"
4213
4214 test_32h() {
4215         rm -fr $DIR/$tdir $DIR/${tdir}2
4216         tmp_dir=$DIR/$tdir/tmp
4217         test_mkdir -p $tmp_dir
4218         test_mkdir $DIR/${tdir}2
4219         ln -s $DIR/${tdir}2 $tmp_dir/symlink12
4220         ln -s $tmp_dir/symlink12 $tmp_dir/../symlink02
4221         ls $tmp_dir/symlink12 || error "listing symlink12"
4222         ls $DIR/$tdir/symlink02  || error "listing symlink02"
4223 }
4224 run_test 32h "open d32h/symlink->tmp/symlink->lustre-subdir/${tdir}2"
4225
4226 test_32i() {
4227         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4228
4229         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4230         trap cleanup_test32_mount EXIT
4231         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4232         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4233                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4234         touch $DIR/$tdir/test_file
4235         $CHECKSTAT -t file $DIR/$tdir/ext2-mountpoint/../test_file ||
4236                 error "$DIR/$tdir/ext2-mountpoint/../test_file not file type"
4237         cleanup_test32_mount
4238 }
4239 run_test 32i "stat d32i/ext2-mountpoint/../test_file ==========="
4240
4241 test_32j() {
4242         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4243
4244         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4245         trap cleanup_test32_mount EXIT
4246         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4247         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4248                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4249         touch $DIR/$tdir/test_file
4250         cat $DIR/$tdir/ext2-mountpoint/../test_file ||
4251                 error "Can't open $DIR/$tdir/ext2-mountpoint/../test_file"
4252         cleanup_test32_mount
4253 }
4254 run_test 32j "open d32j/ext2-mountpoint/../test_file ==========="
4255
4256 test_32k() {
4257         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4258
4259         rm -fr $DIR/$tdir
4260         trap cleanup_test32_mount EXIT
4261         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4262         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4263                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4264         test_mkdir -p $DIR/$tdir/d2
4265         touch $DIR/$tdir/d2/test_file || error "touch failed"
4266         $CHECKSTAT -t file $DIR/$tdir/ext2-mountpoint/../d2/test_file ||
4267                 error "$DIR/$tdir/ext2-mountpoint/../d2/test_file not file type"
4268         cleanup_test32_mount
4269 }
4270 run_test 32k "stat d32k/ext2-mountpoint/../d2/test_file ========"
4271
4272 test_32l() {
4273         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4274
4275         rm -fr $DIR/$tdir
4276         trap cleanup_test32_mount EXIT
4277         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4278         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4279                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4280         test_mkdir -p $DIR/$tdir/d2
4281         touch $DIR/$tdir/d2/test_file || error "touch failed"
4282         cat  $DIR/$tdir/ext2-mountpoint/../d2/test_file ||
4283                 error "Can't open $DIR/$tdir/ext2-mountpoint/../d2/test_file"
4284         cleanup_test32_mount
4285 }
4286 run_test 32l "open d32l/ext2-mountpoint/../d2/test_file ========"
4287
4288 test_32m() {
4289         rm -fr $DIR/d32m
4290         test_mkdir -p $DIR/d32m/tmp
4291         TMP_DIR=$DIR/d32m/tmp
4292         ln -s $DIR $TMP_DIR/symlink11
4293         ln -s $TMP_DIR/symlink11 $TMP_DIR/../symlink01
4294         $CHECKSTAT -t link $DIR/d32m/tmp/symlink11 ||
4295                 error "symlink11 not a link"
4296         $CHECKSTAT -t link $DIR/d32m/symlink01 ||
4297                 error "symlink01 not a link"
4298 }
4299 run_test 32m "stat d32m/symlink->tmp/symlink->lustre-root ======"
4300
4301 test_32n() {
4302         rm -fr $DIR/d32n
4303         test_mkdir -p $DIR/d32n/tmp
4304         TMP_DIR=$DIR/d32n/tmp
4305         ln -s $DIR $TMP_DIR/symlink11
4306         ln -s $TMP_DIR/symlink11 $TMP_DIR/../symlink01
4307         ls -l $DIR/d32n/tmp/symlink11  || error "listing symlink11"
4308         ls -l $DIR/d32n/symlink01 || error "listing symlink01"
4309 }
4310 run_test 32n "open d32n/symlink->tmp/symlink->lustre-root ======"
4311
4312 test_32o() {
4313         touch $DIR/$tfile
4314         test_mkdir -p $DIR/d32o/tmp
4315         TMP_DIR=$DIR/d32o/tmp
4316         ln -s $DIR/$tfile $TMP_DIR/symlink12
4317         ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02
4318         $CHECKSTAT -t link $DIR/d32o/tmp/symlink12 ||
4319                 error "symlink12 not a link"
4320         $CHECKSTAT -t link $DIR/d32o/symlink02 || error "symlink02 not a link"
4321         $CHECKSTAT -t file -f $DIR/d32o/tmp/symlink12 ||
4322                 error "$DIR/d32o/tmp/symlink12 not file type"
4323         $CHECKSTAT -t file -f $DIR/d32o/symlink02 ||
4324                 error "$DIR/d32o/symlink02 not file type"
4325 }
4326 run_test 32o "stat d32o/symlink->tmp/symlink->lustre-root/$tfile"
4327
4328 test_32p() {
4329         log 32p_1
4330         rm -fr $DIR/d32p
4331         log 32p_2
4332         rm -f $DIR/$tfile
4333         log 32p_3
4334         touch $DIR/$tfile
4335         log 32p_4
4336         test_mkdir -p $DIR/d32p/tmp
4337         log 32p_5
4338         TMP_DIR=$DIR/d32p/tmp
4339         log 32p_6
4340         ln -s $DIR/$tfile $TMP_DIR/symlink12
4341         log 32p_7
4342         ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02
4343         log 32p_8
4344         cat $DIR/d32p/tmp/symlink12 ||
4345                 error "Can't open $DIR/d32p/tmp/symlink12"
4346         log 32p_9
4347         cat $DIR/d32p/symlink02 || error "Can't open $DIR/d32p/symlink02"
4348         log 32p_10
4349 }
4350 run_test 32p "open d32p/symlink->tmp/symlink->lustre-root/$tfile"
4351
4352 test_32q() {
4353         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4354
4355         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4356         trap cleanup_test32_mount EXIT
4357         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4358         touch $DIR/$tdir/ext2-mountpoint/under_the_mount || error "touch failed"
4359         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4360                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4361         ls $DIR/$tdir/ext2-mountpoint | grep "\<under_the_mount\>" && error
4362         cleanup_test32_mount
4363 }
4364 run_test 32q "stat follows mountpoints in Lustre (should return error)"
4365
4366 test_32r() {
4367         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4368
4369         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4370         trap cleanup_test32_mount EXIT
4371         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4372         touch $DIR/$tdir/ext2-mountpoint/under_the_mount || error "touch failed"
4373         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4374                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4375         ls $DIR/$tdir/ext2-mountpoint | grep -q under_the_mount && error || true
4376         cleanup_test32_mount
4377 }
4378 run_test 32r "opendir follows mountpoints in Lustre (should return error)"
4379
4380 test_33aa() {
4381         rm -f $DIR/$tfile
4382         touch $DIR/$tfile
4383         chmod 444 $DIR/$tfile
4384         chown $RUNAS_ID $DIR/$tfile
4385         log 33_1
4386         $RUNAS $OPENFILE -f O_RDWR $DIR/$tfile && error || true
4387         log 33_2
4388 }
4389 run_test 33aa "write file with mode 444 (should return error)"
4390
4391 test_33a() {
4392         rm -fr $DIR/$tdir
4393         test_mkdir $DIR/$tdir
4394         chown $RUNAS_ID $DIR/$tdir
4395         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $DIR/$tdir/$tfile ||
4396                 error "$RUNAS create $tdir/$tfile failed"
4397         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $DIR/$tdir/$tfile &&
4398                 error "open RDWR" || true
4399 }
4400 run_test 33a "test open file(mode=0444) with O_RDWR (should return error)"
4401
4402 test_33b() {
4403         rm -fr $DIR/$tdir
4404         test_mkdir $DIR/$tdir
4405         chown $RUNAS_ID $DIR/$tdir
4406         $RUNAS $OPENFILE -f 1286739555 $DIR/$tdir/$tfile || true
4407 }
4408 run_test 33b "test open file with malformed flags (No panic)"
4409
4410 test_33c() {
4411         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4412         remote_ost_nodsh && skip "remote OST with nodsh"
4413
4414         local ostnum
4415         local ostname
4416         local write_bytes
4417         local all_zeros
4418
4419         all_zeros=true
4420         test_mkdir $DIR/$tdir
4421         # Read: 0, Write: 4, create/destroy: 2/0, stat: 1, punch: 0
4422
4423         sync
4424         for ostnum in $(seq $OSTCOUNT); do
4425                 # test-framework's OST numbering is one-based, while Lustre's
4426                 # is zero-based
4427                 ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4428                 # check if at least some write_bytes stats are counted
4429                 write_bytes=$(do_facet ost$ostnum lctl get_param -n \
4430                               obdfilter.$ostname.stats |
4431                               awk '/^write_bytes/ {print $7}' )
4432                 echo "baseline_write_bytes@ost$ostnum/$ostname=$write_bytes"
4433                 if (( ${write_bytes:-0} > 0 )); then
4434                         all_zeros=false
4435                         break
4436                 fi
4437         done
4438
4439         $all_zeros || return 0
4440
4441         # Write four bytes
4442         echo foo > $DIR/$tdir/bar
4443         # Really write them
4444         sync
4445
4446         # Total up write_bytes after writing.  We'd better find non-zeros.
4447         for ostnum in $(seq $OSTCOUNT); do
4448                 ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4449                 write_bytes=$(do_facet ost$ostnum lctl get_param -n \
4450                               obdfilter/$ostname/stats |
4451                               awk '/^write_bytes/ {print $7}' )
4452                 echo "write_bytes@ost$ostnum/$ostname=$write_bytes"
4453                 if (( ${write_bytes:-0} > 0 )); then
4454                         all_zeros=false
4455                         break
4456                 fi
4457         done
4458
4459         if $all_zeros; then
4460                 for ostnum in $(seq $OSTCOUNT); do
4461                         ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4462                         echo "Check write_bytes is in obdfilter.*.stats:"
4463                         do_facet ost$ostnum lctl get_param -n \
4464                                 obdfilter.$ostname.stats
4465                 done
4466                 error "OST not keeping write_bytes stats (b=22312)"
4467         fi
4468 }
4469 run_test 33c "test write_bytes stats"
4470
4471 test_33d() {
4472         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
4473         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4474
4475         local MDTIDX=1
4476         local remote_dir=$DIR/$tdir/remote_dir
4477
4478         test_mkdir $DIR/$tdir
4479         $LFS mkdir -i $MDTIDX $remote_dir ||
4480                 error "create remote directory failed"
4481
4482         touch $remote_dir/$tfile
4483         chmod 444 $remote_dir/$tfile
4484         chown $RUNAS_ID $remote_dir/$tfile
4485
4486         $RUNAS $OPENFILE -f O_RDWR $DIR/$tfile && error || true
4487
4488         chown $RUNAS_ID $remote_dir
4489         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $remote_dir/f33 ||
4490                                         error "create" || true
4491         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $remote_dir/f33 &&
4492                                     error "open RDWR" || true
4493         $RUNAS $OPENFILE -f 1286739555 $remote_dir/f33 || true
4494 }
4495 run_test 33d "openfile with 444 modes and malformed flags under remote dir"
4496
4497 test_33e() {
4498         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4499
4500         mkdir $DIR/$tdir
4501
4502         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4503         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4504         mkdir $DIR/$tdir/local_dir
4505
4506         local s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4507         local s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4508         local l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4509
4510         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4511                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode"
4512
4513         rmdir $DIR/$tdir/* || error "rmdir failed"
4514
4515         umask 777
4516         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4517         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4518         mkdir $DIR/$tdir/local_dir
4519
4520         s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4521         s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4522         l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4523
4524         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4525                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode 777"
4526
4527         rmdir $DIR/$tdir/* || error "rmdir(umask 777) failed"
4528
4529         umask 000
4530         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4531         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4532         mkdir $DIR/$tdir/local_dir
4533
4534         s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4535         s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4536         l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4537
4538         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4539                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode 0"
4540 }
4541 run_test 33e "mkdir and striped directory should have same mode"
4542
4543 cleanup_33f() {
4544         trap 0
4545         do_facet $SINGLEMDS $LCTL set_param mdt.*.enable_remote_dir_gid=0
4546 }
4547
4548 test_33f() {
4549         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4550         remote_mds_nodsh && skip "remote MDS with nodsh"
4551
4552         mkdir $DIR/$tdir
4553         chmod go+rwx $DIR/$tdir
4554         do_facet $SINGLEMDS $LCTL set_param mdt.*.enable_remote_dir_gid=-1
4555         trap cleanup_33f EXIT
4556
4557         $RUNAS lfs mkdir -i 0 -c$MDSCOUNT $DIR/$tdir/striped_dir ||
4558                 error "cannot create striped directory"
4559
4560         $RUNAS touch $DIR/$tdir/striped_dir/{0..16} ||
4561                 error "cannot create files in striped directory"
4562
4563         $RUNAS rm $DIR/$tdir/striped_dir/{0..16} ||
4564                 error "cannot remove files in striped directory"
4565
4566         $RUNAS rmdir $DIR/$tdir/striped_dir ||
4567                 error "cannot remove striped directory"
4568
4569         cleanup_33f
4570 }
4571 run_test 33f "nonroot user can create, access, and remove a striped directory"
4572
4573 test_33g() {
4574         mkdir -p $DIR/$tdir/dir2
4575
4576         local err=$($RUNAS mkdir $DIR/$tdir/dir2 2>&1)
4577         echo $err
4578         [[ $err =~ "exists" ]] || error "Not exists error"
4579 }
4580 run_test 33g "nonroot user create already existing root created file"
4581
4582 sub_33h() {
4583         local hash_type=$1
4584         local count=250
4585
4586         test_mkdir -c $MDSCOUNT -H $hash_type $DIR/$tdir ||
4587                 error "lfs mkdir -H $hash_type $tdir failed"
4588         touch $DIR/$tdir/$tfile || error "touch $tfile failed"
4589
4590         local index=$($LFS getstripe -m $DIR/$tdir/$tfile)
4591         local index2
4592         local fname
4593
4594         for fname in $DIR/$tdir/$tfile.bak \
4595                      $DIR/$tdir/$tfile.SAV \
4596                      $DIR/$tdir/$tfile.orig \
4597                      $DIR/$tdir/$tfile~; do
4598                 touch $fname || error "touch $fname failed"
4599                 index2=$($LFS getstripe -m $fname)
4600                 (( $index == $index2 )) ||
4601                         error "$fname MDT index mismatch $index != $index2"
4602         done
4603
4604         local failed=0
4605         local patterns=(".$tfile.XXXXXX" "$tfile.XXXXXXXX")
4606         local pattern
4607         local stat
4608
4609         for pattern in ${patterns[*]}; do
4610                 echo "pattern $pattern"
4611                 fname=$DIR/$tdir/$pattern
4612                 for (( i = 0; i < $count; i++ )); do
4613                         fname=$(mktemp $DIR/$tdir/$pattern) ||
4614                                 error "mktemp $DIR/$tdir/$pattern failed"
4615                         index2=$($LFS getstripe -m $fname)
4616                         (( $index == $index2 )) && continue
4617
4618                         failed=$((failed + 1))
4619                         echo "$fname MDT index mismatch $index != $index2"
4620                 done
4621         done
4622
4623         echo "$failed/$count MDT index mismatches, expect ~2-4"
4624         (( failed < 10 )) || error "MDT index mismatch $failed/$count times"
4625
4626         local same=0
4627         local expect
4628
4629         # verify that "crush" is still broken with all files on same MDT,
4630         # crush2 should have about 1/MDSCOUNT files on each MDT, with margin
4631         [[ "$hash_type" == "crush" ]] && expect=$count ||
4632                 expect=$((count / MDSCOUNT))
4633
4634         local tries=3
4635
4636         for (( try = tries - 1; try >= 0; try-- )); do
4637                 # crush2 doesn't put all-numeric suffixes on the same MDT,
4638                 # filename like $tfile.12345678 should *not* be considered temp
4639                 for pattern in ${patterns[*]}; do
4640                         local base=${pattern%%X*}
4641                         local suff=${pattern#$base}
4642
4643                         echo "pattern $pattern"
4644                         for (( i = 0; i < $count; i++ )); do
4645                                 fname=$DIR/$tdir/$base$((${suff//X/1} + i))
4646                                 touch $fname || error "touch $fname failed"
4647                                 index2=$($LFS getstripe -m $fname)
4648                                 (( $index != $index2 )) && continue
4649
4650                                 same=$((same + 1))
4651                         done
4652                 done
4653
4654                 stat="$((same/${#patterns[*]}))/$count"
4655                 # the number of "bad" hashes is random, as it depends on the
4656                 # random filenames generated by "mktemp". Allow some margin in
4657                 # the results.
4658                 echo "$stat matches, expect ~$expect for $1"
4659                 (( same / ${#patterns[*]} <= expect * 9 / 7 &&
4660                    same / ${#patterns[*]} > expect * 5 / 7 )) && same=0 && break
4661                 log "MDT index match $stat times, $try tries left"
4662
4663                 (( try > 0 )) ||
4664                 error "MDT index match $stat times, after $tries tries"
4665                 same=0
4666         done
4667
4668         for (( try = tries - 1; try >= 0; try-- )); do
4669                 # crush2 doesn't put suffixes with special chars on the same MDT
4670                 # filenames like $tfile.txt.1234 should *not* be considered temp
4671                 for pattern in ${patterns[*]}; do
4672                         local base=${pattern%%X*}
4673                         local suff=${pattern#$base}
4674
4675                         pattern=$base...${suff/XXX}
4676                         echo "pattern=$pattern"
4677                         for (( i = 0; i < $count; i++ )); do
4678                                 fname=$(mktemp $DIR/$tdir/$pattern) ||
4679                                         error "touch $fname failed"
4680                                 index2=$($LFS getstripe -m $fname)
4681                                 (( $index != $index2 )) && continue
4682
4683                                 same=$((same + 1))
4684                         done
4685                 done
4686
4687                 stat="$((same/${#patterns[*]}))/$count"
4688                 # the number of "bad" hashes is random, as it depends on the
4689                 # filenames generated by "mktemp".  Allow some margin in results
4690                 echo "$stat matches, expect ~$expect for $1"
4691                 (( same / ${#patterns[*]} <= expect * 9 / 7 &&
4692                    same / ${#patterns[*]} > expect * 5 / 7 )) && break
4693                 log "MDT index match $stat times, $try tries left"
4694
4695                 (( try > 0 )) ||
4696                 error "MDT index match $stat times, after $tries tries"
4697                 same=0
4698         done
4699 }
4700
4701 test_33h() {
4702         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4703         (( $MDS1_VERSION >= $(version_code 2.13.50) )) ||
4704                 skip "Need MDS version at least 2.13.50"
4705
4706         sub_33h crush
4707 }
4708 run_test 33h "temp file is located on the same MDT as target (crush)"
4709
4710 test_33hh() {
4711         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4712         echo "MDS1_VERSION=$MDS1_VERSION version_code=$(version_code 2.15.0)"
4713         (( $MDS1_VERSION > $(version_code 2.15.0) )) ||
4714                 skip "Need MDS version at least 2.15.0 for crush2"
4715
4716         sub_33h crush2
4717 }
4718 run_test 33hh "temp file is located on the same MDT as target (crush2)"
4719
4720 test_33i()
4721 {
4722         (( MDSCOUNT < 2 )) && skip "needs >= 2 MDTs"
4723
4724         local FNAME=$(str_repeat 'f' 250)
4725
4726         test_mkdir -i 0 -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
4727         createmany -o $DIR/$tdir/$FNAME 1000 || error "createmany failed"
4728
4729         local count
4730         local total
4731
4732         count=$($LFS getstripe -m $DIR/$tdir/* | grep -cw 1)
4733
4734         local MDC=$(lctl dl | awk '/MDT0001-mdc-[^M]/ { print $4 }')
4735
4736         lctl --device %$MDC deactivate
4737         stack_trap "lctl --device %$MDC activate"
4738         ls $DIR/$tdir > /dev/null && error "ls should return an error"
4739         total=$(\ls -l $DIR/$tdir | wc -l)
4740         # "ls -l" will list total in the first line
4741         total=$((total - 1))
4742         (( total + count == 1000 )) ||
4743                 error "ls list $total files, $count files on MDT1"
4744 }
4745 run_test 33i "striped directory can be accessed when one MDT is down"
4746
4747 test_33j() {
4748         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4749
4750         mkdir -p $DIR/$tdir/
4751
4752         $LFS setdirstripe -D -i0,1 $DIR/$tdir/striped_dir_a &&
4753                 error "setdirstripe -D -i0,1 incorrectly succeeded"
4754
4755         $LFS setdirstripe -D -i0,1 -c1 $DIR/$tdir/striped_dir_b &&
4756                 error "setdirstripe -D -i0,1 -c1 incorrectly succeeded"
4757
4758         $LFS setdirstripe -D -i0,1 -c3 $DIR/$tdir/striped_dir_c &&
4759                 error "setdirstripe -D -i0,1 -c3 incorrectly succeeded"
4760
4761         $LFS setdirstripe -i0,1 $DIR/$tdir/striped_dir_e ||
4762                 error "-D was not specified, but still failed"
4763 }
4764 run_test 33j "lfs setdirstripe -D -i x,y,x should fail"
4765
4766 TEST_34_SIZE=${TEST_34_SIZE:-2000000000000}
4767 test_34a() {
4768         rm -f $DIR/f34
4769         $MCREATE $DIR/f34 || error "mcreate failed"
4770         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4771                 error "getstripe failed"
4772         $TRUNCATE $DIR/f34 $TEST_34_SIZE || error "truncate failed"
4773         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4774                 error "getstripe failed"
4775         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4776                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4777 }
4778 run_test 34a "truncate file that has not been opened ==========="
4779
4780 test_34b() {
4781         [ ! -f $DIR/f34 ] && test_34a
4782         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4783                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4784         $OPENFILE -f O_RDONLY $DIR/f34
4785         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4786                 error "getstripe failed"
4787         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4788                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4789 }
4790 run_test 34b "O_RDONLY opening file doesn't create objects ====="
4791
4792 test_34c() {
4793         [ ! -f $DIR/f34 ] && test_34a
4794         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4795                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4796         $OPENFILE -f O_RDWR $DIR/f34
4797         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" &&
4798                 error "$LFS getstripe failed"
4799         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4800                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4801 }
4802 run_test 34c "O_RDWR opening file-with-size works =============="
4803
4804 test_34d() {
4805         [ ! -f $DIR/f34 ] && test_34a
4806         dd if=/dev/zero of=$DIR/f34 conv=notrunc bs=4k count=1 ||
4807                 error "dd failed"
4808         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4809                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4810         rm $DIR/f34
4811 }
4812 run_test 34d "write to sparse file ============================="
4813
4814 test_34e() {
4815         rm -f $DIR/f34e
4816         $MCREATE $DIR/f34e || error "mcreate failed"
4817         $TRUNCATE $DIR/f34e 1000 || error "truncate failed"
4818         $CHECKSTAT -s 1000 $DIR/f34e ||
4819                 error "Size of $DIR/f34e not equal to 1000 bytes"
4820         $OPENFILE -f O_RDWR $DIR/f34e
4821         $CHECKSTAT -s 1000 $DIR/f34e ||
4822                 error "Size of $DIR/f34e not equal to 1000 bytes"
4823 }
4824 run_test 34e "create objects, some with size and some without =="
4825
4826 test_34f() { # bug 6242, 6243
4827         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4828
4829         SIZE34F=48000
4830         rm -f $DIR/f34f
4831         $MCREATE $DIR/f34f || error "mcreate failed"
4832         $TRUNCATE $DIR/f34f $SIZE34F || error "truncating $DIR/f3f to $SIZE34F"
4833         dd if=$DIR/f34f of=$TMP/f34f
4834         $CHECKSTAT -s $SIZE34F $TMP/f34f || error "$TMP/f34f not $SIZE34F bytes"
4835         dd if=/dev/zero of=$TMP/f34fzero bs=$SIZE34F count=1
4836         cmp $DIR/f34f $TMP/f34fzero || error "$DIR/f34f not all zero"
4837         cmp $TMP/f34f $TMP/f34fzero || error "$TMP/f34f not all zero"
4838         rm $TMP/f34f $TMP/f34fzero $DIR/f34f
4839 }
4840 run_test 34f "read from a file with no objects until EOF ======="
4841
4842 test_34g() {
4843         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4844
4845         dd if=/dev/zero of=$DIR/$tfile bs=1 count=100 seek=$TEST_34_SIZE ||
4846                 error "dd failed"
4847         $TRUNCATE $DIR/$tfile $((TEST_34_SIZE / 2))|| error "truncate failed"
4848         $CHECKSTAT -s $((TEST_34_SIZE / 2)) $DIR/$tfile ||
4849                 error "Size of $DIR/$tfile not equal to $((TEST_34_SIZE / 2))"
4850         cancel_lru_locks osc
4851         $CHECKSTAT -s $((TEST_34_SIZE / 2)) $DIR/$tfile ||
4852                 error "wrong size after lock cancel"
4853
4854         $TRUNCATE $DIR/$tfile $TEST_34_SIZE || error "truncate failed"
4855         $CHECKSTAT -s $TEST_34_SIZE $DIR/$tfile ||
4856                 error "expanding truncate failed"
4857         cancel_lru_locks osc
4858         $CHECKSTAT -s $TEST_34_SIZE $DIR/$tfile ||
4859                 error "wrong expanded size after lock cancel"
4860 }
4861 run_test 34g "truncate long file ==============================="
4862
4863 test_34h() {
4864         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4865
4866         local gid=10
4867         local sz=1000
4868
4869         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 || error "dd failed"
4870         sync # Flush the cache so that multiop below does not block on cache
4871              # flush when getting the group lock
4872         $MULTIOP $DIR/$tfile OG${gid}T${sz}g${gid}c &
4873         MULTIPID=$!
4874
4875         # Since just timed wait is not good enough, let's do a sync write
4876         # that way we are sure enough time for a roundtrip + processing
4877         # passed + 2 seconds of extra margin.
4878         dd if=/dev/zero of=$DIR/${tfile}-1 bs=$PAGE_SIZE oflag=direct count=1
4879         rm $DIR/${tfile}-1
4880         sleep 2
4881
4882         if [[ `ps h -o comm -p $MULTIPID` == "multiop" ]]; then
4883                 error "Multiop blocked on ftruncate, pid=$MULTIPID"
4884                 kill -9 $MULTIPID
4885         fi
4886         wait $MULTIPID
4887         local nsz=`stat -c %s $DIR/$tfile`
4888         [[ $nsz == $sz ]] || error "New size wrong $nsz != $sz"
4889 }
4890 run_test 34h "ftruncate file under grouplock should not block"
4891
4892 test_35a() {
4893         cp /bin/sh $DIR/f35a
4894         chmod 444 $DIR/f35a
4895         chown $RUNAS_ID $DIR/f35a
4896         $RUNAS $DIR/f35a && error || true
4897         rm $DIR/f35a
4898 }
4899 run_test 35a "exec file with mode 444 (should return and not leak)"
4900
4901 test_36a() {
4902         rm -f $DIR/f36
4903         utime $DIR/f36 || error "utime failed for MDS"
4904 }
4905 run_test 36a "MDS utime check (mknod, utime)"
4906
4907 test_36b() {
4908         echo "" > $DIR/f36
4909         utime $DIR/f36 || error "utime failed for OST"
4910 }
4911 run_test 36b "OST utime check (open, utime)"
4912
4913 test_36c() {
4914         rm -f $DIR/d36/f36
4915         test_mkdir $DIR/d36
4916         chown $RUNAS_ID $DIR/d36
4917         $RUNAS utime $DIR/d36/f36 || error "utime failed for MDS as non-root"
4918 }
4919 run_test 36c "non-root MDS utime check (mknod, utime)"
4920
4921 test_36d() {
4922         [ ! -d $DIR/d36 ] && test_36c
4923         echo "" > $DIR/d36/f36
4924         $RUNAS utime $DIR/d36/f36 || error "utime failed for OST as non-root"
4925 }
4926 run_test 36d "non-root OST utime check (open, utime)"
4927
4928 test_36e() {
4929         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID -- skipping"
4930
4931         test_mkdir $DIR/$tdir
4932         touch $DIR/$tdir/$tfile
4933         $RUNAS utime $DIR/$tdir/$tfile &&
4934                 error "utime worked, expected failure" || true
4935 }
4936 run_test 36e "utime on non-owned file (should return error)"
4937
4938 subr_36fh() {
4939         local fl="$1"
4940         local LANG_SAVE=$LANG
4941         local LC_LANG_SAVE=$LC_LANG
4942         export LANG=C LC_LANG=C # for date language
4943
4944         DATESTR="Dec 20  2000"
4945         test_mkdir $DIR/$tdir
4946         lctl set_param fail_loc=$fl
4947         date; date +%s
4948         cp /etc/hosts $DIR/$tdir/$tfile
4949         sync & # write RPC generated with "current" inode timestamp, but delayed
4950         sleep 1
4951         touch --date="$DATESTR" $DIR/$tdir/$tfile # setattr timestamp in past
4952         LS_BEFORE="`ls -l $DIR/$tdir/$tfile`" # old timestamp from client cache
4953         cancel_lru_locks $OSC
4954         LS_AFTER="`ls -l $DIR/$tdir/$tfile`"  # timestamp from OST object
4955         date; date +%s
4956         [ "$LS_BEFORE" != "$LS_AFTER" ] && \
4957                 echo "BEFORE: $LS_BEFORE" && \
4958                 echo "AFTER : $LS_AFTER" && \
4959                 echo "WANT  : $DATESTR" && \
4960                 error "$DIR/$tdir/$tfile timestamps changed" || true
4961
4962         export LANG=$LANG_SAVE LC_LANG=$LC_LANG_SAVE
4963 }
4964
4965 test_36f() {
4966         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4967
4968         #define OBD_FAIL_OST_BRW_PAUSE_BULK 0x214
4969         subr_36fh "0x80000214"
4970 }
4971 run_test 36f "utime on file racing with OST BRW write =========="
4972
4973 test_36g() {
4974         remote_ost_nodsh && skip "remote OST with nodsh"
4975         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4976         [ $MDS1_VERSION -lt $(version_code 2.12.51) ] &&
4977                 skip "Need MDS version at least 2.12.51"
4978
4979         local fmd_max_age
4980         local fmd
4981         local facet="ost1"
4982         local tgt="obdfilter"
4983
4984         [[ $OSC == "mdc" ]] && tgt="mdt" && facet="mds1"
4985
4986         test_mkdir $DIR/$tdir
4987         fmd_max_age=$(do_facet $facet \
4988                 "lctl get_param -n $tgt.*.tgt_fmd_seconds 2> /dev/null | \
4989                 head -n 1")
4990
4991         echo "FMD max age: ${fmd_max_age}s"
4992         touch $DIR/$tdir/$tfile
4993         fmd=$(do_facet $facet "lctl get_param -n $tgt.*.exports.*.fmd_count" |
4994                 gawk '{cnt=cnt+$1}  END{print cnt}')
4995         echo "FMD before: $fmd"
4996         [[ $fmd == 0 ]] &&
4997                 error "FMD wasn't create by touch"
4998         sleep $((fmd_max_age + 12))
4999         fmd=$(do_facet $facet "lctl get_param -n $tgt.*.exports.*.fmd_count" |
5000                 gawk '{cnt=cnt+$1}  END{print cnt}')
5001         echo "FMD after: $fmd"
5002         [[ $fmd == 0 ]] ||
5003                 error "FMD wasn't expired by ping"
5004 }
5005 run_test 36g "FMD cache expiry ====================="
5006
5007 test_36h() {
5008         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5009
5010         #define OBD_FAIL_OST_BRW_PAUSE_BULK2 0x227
5011         subr_36fh "0x80000227"
5012 }
5013 run_test 36h "utime on file racing with OST BRW write =========="
5014
5015 test_36i() {
5016         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
5017
5018         test_mkdir $DIR/$tdir
5019         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir
5020
5021         local mtime=$(stat -c%Y $DIR/$tdir/striped_dir)
5022         local new_mtime=$((mtime + 200))
5023
5024         #change Modify time of striped dir
5025         touch -m -d @$new_mtime $DIR/$tdir/striped_dir ||
5026                         error "change mtime failed"
5027
5028         local got=$(stat -c%Y $DIR/$tdir/striped_dir)
5029
5030         [ "$new_mtime" = "$got" ] || error "expect $new_mtime got $got"
5031 }
5032 run_test 36i "change mtime on striped directory"
5033
5034 # test_37 - duplicate with tests 32q 32r
5035
5036 test_38() {
5037         local file=$DIR/$tfile
5038         touch $file
5039         openfile -f O_DIRECTORY $file
5040         local RC=$?
5041         local ENOTDIR=20
5042         [ $RC -eq 0 ] && error "opened file $file with O_DIRECTORY" || true
5043         [ $RC -eq $ENOTDIR ] || error "error $RC should be ENOTDIR ($ENOTDIR)"
5044 }
5045 run_test 38 "open a regular file with O_DIRECTORY should return -ENOTDIR ==="
5046
5047 test_39a() { # was test_39
5048         touch $DIR/$tfile
5049         touch $DIR/${tfile}2
5050 #       ls -l  $DIR/$tfile $DIR/${tfile}2
5051 #       ls -lu  $DIR/$tfile $DIR/${tfile}2
5052 #       ls -lc  $DIR/$tfile $DIR/${tfile}2
5053         sleep 2
5054         $OPENFILE -f O_CREAT:O_TRUNC:O_WRONLY $DIR/${tfile}2
5055         if [ ! $DIR/${tfile}2 -nt $DIR/$tfile ]; then
5056                 echo "mtime"
5057                 ls -l --full-time $DIR/$tfile $DIR/${tfile}2
5058                 echo "atime"
5059                 ls -lu --full-time $DIR/$tfile $DIR/${tfile}2
5060                 echo "ctime"
5061                 ls -lc --full-time $DIR/$tfile $DIR/${tfile}2
5062                 error "O_TRUNC didn't change timestamps"
5063         fi
5064 }
5065 run_test 39a "mtime changed on create"
5066
5067 test_39b() {
5068         test_mkdir -c1 $DIR/$tdir
5069         cp -p /etc/passwd $DIR/$tdir/fopen
5070         cp -p /etc/passwd $DIR/$tdir/flink
5071         cp -p /etc/passwd $DIR/$tdir/funlink
5072         cp -p /etc/passwd $DIR/$tdir/frename
5073         ln $DIR/$tdir/funlink $DIR/$tdir/funlink2
5074
5075         sleep 1
5076         echo "aaaaaa" >> $DIR/$tdir/fopen
5077         echo "aaaaaa" >> $DIR/$tdir/flink
5078         echo "aaaaaa" >> $DIR/$tdir/funlink
5079         echo "aaaaaa" >> $DIR/$tdir/frename
5080
5081         local open_new=`stat -c %Y $DIR/$tdir/fopen`
5082         local link_new=`stat -c %Y $DIR/$tdir/flink`
5083         local unlink_new=`stat -c %Y $DIR/$tdir/funlink`
5084         local rename_new=`stat -c %Y $DIR/$tdir/frename`
5085
5086         cat $DIR/$tdir/fopen > /dev/null
5087         ln $DIR/$tdir/flink $DIR/$tdir/flink2
5088         rm -f $DIR/$tdir/funlink2
5089         mv -f $DIR/$tdir/frename $DIR/$tdir/frename2
5090
5091         for (( i=0; i < 2; i++ )) ; do
5092                 local open_new2=`stat -c %Y $DIR/$tdir/fopen`
5093                 local link_new2=`stat -c %Y $DIR/$tdir/flink`
5094                 local unlink_new2=`stat -c %Y $DIR/$tdir/funlink`
5095                 local rename_new2=`stat -c %Y $DIR/$tdir/frename2`
5096
5097                 [ $open_new2 -eq $open_new ] || error "open file reverses mtime"
5098                 [ $link_new2 -eq $link_new ] || error "link file reverses mtime"
5099                 [ $unlink_new2 -eq $unlink_new ] || error "unlink file reverses mtime"
5100                 [ $rename_new2 -eq $rename_new ] || error "rename file reverses mtime"
5101
5102                 cancel_lru_locks $OSC
5103                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5104         done
5105 }
5106 run_test 39b "mtime change on open, link, unlink, rename  ======"
5107
5108 # this should be set to past
5109 TEST_39_MTIME=`date -d "1 year ago" +%s`
5110
5111 # bug 11063
5112 test_39c() {
5113         touch $DIR1/$tfile
5114         sleep 2
5115         local mtime0=`stat -c %Y $DIR1/$tfile`
5116
5117         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5118         local mtime1=`stat -c %Y $DIR1/$tfile`
5119         [ "$mtime1" = $TEST_39_MTIME ] || \
5120                 error "mtime is not set to past: $mtime1, should be $TEST_39_MTIME"
5121
5122         local d1=`date +%s`
5123         echo hello >> $DIR1/$tfile
5124         local d2=`date +%s`
5125         local mtime2=`stat -c %Y $DIR1/$tfile`
5126         [ "$mtime2" -ge "$d1" ] && [ "$mtime2" -le "$d2" ] || \
5127                 error "mtime is not updated on write: $d1 <= $mtime2 <= $d2"
5128
5129         mv $DIR1/$tfile $DIR1/$tfile-1
5130
5131         for (( i=0; i < 2; i++ )) ; do
5132                 local mtime3=`stat -c %Y $DIR1/$tfile-1`
5133                 [ "$mtime2" = "$mtime3" ] || \
5134                         error "mtime ($mtime2) changed (to $mtime3) on rename"
5135
5136                 cancel_lru_locks $OSC
5137                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5138         done
5139 }
5140 run_test 39c "mtime change on rename ==========================="
5141
5142 # bug 21114
5143 test_39d() {
5144         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5145
5146         touch $DIR1/$tfile
5147         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5148
5149         for (( i=0; i < 2; i++ )) ; do
5150                 local mtime=`stat -c %Y $DIR1/$tfile`
5151                 [ $mtime = $TEST_39_MTIME ] || \
5152                         error "mtime($mtime) is not set to $TEST_39_MTIME"
5153
5154                 cancel_lru_locks $OSC
5155                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5156         done
5157 }
5158 run_test 39d "create, utime, stat =============================="
5159
5160 # bug 21114
5161 test_39e() {
5162         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5163
5164         touch $DIR1/$tfile
5165         local mtime1=`stat -c %Y $DIR1/$tfile`
5166
5167         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5168
5169         for (( i=0; i < 2; i++ )) ; do
5170                 local mtime2=`stat -c %Y $DIR1/$tfile`
5171                 [ $mtime2 = $TEST_39_MTIME ] || \
5172                         error "mtime($mtime2) is not set to $TEST_39_MTIME"
5173
5174                 cancel_lru_locks $OSC
5175                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5176         done
5177 }
5178 run_test 39e "create, stat, utime, stat ========================"
5179
5180 # bug 21114
5181 test_39f() {
5182         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5183
5184         touch $DIR1/$tfile
5185         mtime1=`stat -c %Y $DIR1/$tfile`
5186
5187         sleep 2
5188         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5189
5190         for (( i=0; i < 2; i++ )) ; do
5191                 local mtime2=`stat -c %Y $DIR1/$tfile`
5192                 [ $mtime2 = $TEST_39_MTIME ] || \
5193                         error "mtime($mtime2) is not set to $TEST_39_MTIME"
5194
5195                 cancel_lru_locks $OSC
5196                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5197         done
5198 }
5199 run_test 39f "create, stat, sleep, utime, stat ================="
5200
5201 # bug 11063
5202 test_39g() {
5203         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5204
5205         echo hello >> $DIR1/$tfile
5206         local mtime1=`stat -c %Y $DIR1/$tfile`
5207
5208         sleep 2
5209         chmod o+r $DIR1/$tfile
5210
5211         for (( i=0; i < 2; i++ )) ; do
5212                 local mtime2=`stat -c %Y $DIR1/$tfile`
5213                 [ "$mtime1" = "$mtime2" ] || \
5214                         error "lost mtime: $mtime2, should be $mtime1"
5215
5216                 cancel_lru_locks $OSC
5217                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5218         done
5219 }
5220 run_test 39g "write, chmod, stat ==============================="
5221
5222 # bug 11063
5223 test_39h() {
5224         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5225
5226         touch $DIR1/$tfile
5227         sleep 1
5228
5229         local d1=`date`
5230         echo hello >> $DIR1/$tfile
5231         local mtime1=`stat -c %Y $DIR1/$tfile`
5232
5233         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5234         local d2=`date`
5235         if [ "$d1" != "$d2" ]; then
5236                 echo "write and touch not within one second"
5237         else
5238                 for (( i=0; i < 2; i++ )) ; do
5239                         local mtime2=`stat -c %Y $DIR1/$tfile`
5240                         [ "$mtime2" = $TEST_39_MTIME ] || \
5241                                 error "lost mtime: $mtime2, should be $TEST_39_MTIME"
5242
5243                         cancel_lru_locks $OSC
5244                         if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5245                 done
5246         fi
5247 }
5248 run_test 39h "write, utime within one second, stat ============="
5249
5250 test_39i() {
5251         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5252
5253         touch $DIR1/$tfile
5254         sleep 1
5255
5256         echo hello >> $DIR1/$tfile
5257         local mtime1=`stat -c %Y $DIR1/$tfile`
5258
5259         mv $DIR1/$tfile $DIR1/$tfile-1
5260
5261         for (( i=0; i < 2; i++ )) ; do
5262                 local mtime2=`stat -c %Y $DIR1/$tfile-1`
5263
5264                 [ "$mtime1" = "$mtime2" ] || \
5265                         error "lost mtime: $mtime2, should be $mtime1"
5266
5267                 cancel_lru_locks $OSC
5268                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5269         done
5270 }
5271 run_test 39i "write, rename, stat =============================="
5272
5273 test_39j() {
5274         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5275
5276         start_full_debug_logging
5277         touch $DIR1/$tfile
5278         sleep 1
5279         stack_trap "rm -f $DIR1/$tfile"
5280
5281         #define OBD_FAIL_OSC_DELAY_SETTIME       0x412
5282         lctl set_param fail_loc=0x80000412
5283         multiop_bg_pause $DIR1/$tfile oO_RDWR:w2097152_c ||
5284                 error "multiop failed"
5285         local multipid=$!
5286         local mtime1=`stat -c %Y $DIR1/$tfile`
5287
5288         mv $DIR1/$tfile $DIR1/$tfile-1
5289
5290         kill -USR1 $multipid
5291         wait $multipid || error "multiop close failed"
5292
5293         for (( i=0; i < 2; i++ )) ; do
5294                 local mtime2=`stat -c %Y $DIR1/$tfile-1`
5295                 [ "$mtime1" = "$mtime2" ] ||
5296                         error "mtime is lost on close: $mtime2, " \
5297                               "should be $mtime1"
5298
5299                 cancel_lru_locks
5300                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5301         done
5302         lctl set_param fail_loc=0
5303         stop_full_debug_logging
5304 }
5305 run_test 39j "write, rename, close, stat ======================="
5306
5307 test_39k() {
5308         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5309
5310         touch $DIR1/$tfile
5311         sleep 1
5312         stack_trap "rm -f $DIR1/$tfile"
5313
5314         multiop_bg_pause $DIR1/$tfile oO_RDWR:w2097152_c || error "multiop failed"
5315         local multipid=$!
5316         local mtime1=`stat -c %Y $DIR1/$tfile`
5317
5318         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5319
5320         kill -USR1 $multipid
5321         wait $multipid || error "multiop close failed"
5322
5323         for (( i=0; i < 2; i++ )) ; do
5324                 local mtime2=`stat -c %Y $DIR1/$tfile`
5325
5326                 [ "$mtime2" = $TEST_39_MTIME ] || \
5327                         error "mtime is lost on close: $mtime2, should be $TEST_39_MTIME"
5328
5329                 cancel_lru_locks
5330                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5331         done
5332 }
5333 run_test 39k "write, utime, close, stat ========================"
5334
5335 # this should be set to future
5336 TEST_39_ATIME=`date -d "1 year" +%s`
5337
5338 test_39l() {
5339         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5340         remote_mds_nodsh && skip "remote MDS with nodsh"
5341
5342         local atime_diff=$(do_facet $SINGLEMDS \
5343                                 lctl get_param -n mdd.*MDT0000*.atime_diff)
5344         rm -rf $DIR/$tdir
5345         mkdir_on_mdt0 $DIR/$tdir
5346
5347         # test setting directory atime to future
5348         touch -a -d @$TEST_39_ATIME $DIR/$tdir
5349         local atime=$(stat -c %X $DIR/$tdir)
5350         [ "$atime" = $TEST_39_ATIME ] ||
5351                 error "atime is not set to future: $atime, $TEST_39_ATIME"
5352
5353         # test setting directory atime from future to now
5354         local now=$(date +%s)
5355         touch -a -d @$now $DIR/$tdir
5356
5357         atime=$(stat -c %X $DIR/$tdir)
5358         [ "$atime" -eq "$now"  ] ||
5359                 error "atime is not updated from future: $atime, $now"
5360
5361         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=2
5362         sleep 3
5363
5364         # test setting directory atime when now > dir atime + atime_diff
5365         local d1=$(date +%s)
5366         ls $DIR/$tdir
5367         local d2=$(date +%s)
5368         cancel_lru_locks mdc
5369         atime=$(stat -c %X $DIR/$tdir)
5370         [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
5371                 error "atime is not updated  : $atime, should be $d2"
5372
5373         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=60
5374         sleep 3
5375
5376         # test not setting directory atime when now < dir atime + atime_diff
5377         ls $DIR/$tdir
5378         cancel_lru_locks mdc
5379         atime=$(stat -c %X $DIR/$tdir)
5380         [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
5381                 error "atime is updated to $atime, should remain $d1<atime<$d2"
5382
5383         do_facet $SINGLEMDS \
5384                 lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff
5385 }
5386 run_test 39l "directory atime update ==========================="
5387
5388 test_39m() {
5389         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5390
5391         touch $DIR1/$tfile
5392         sleep 2
5393         local far_past_mtime=$(date -d "May 29 1953" +%s)
5394         local far_past_atime=$(date -d "Dec 17 1903" +%s)
5395
5396         touch -m -d @$far_past_mtime $DIR1/$tfile
5397         touch -a -d @$far_past_atime $DIR1/$tfile
5398
5399         for (( i=0; i < 2; i++ )) ; do
5400                 local timestamps=$(stat -c "%X %Y" $DIR1/$tfile)
5401                 [ "$timestamps" = "$far_past_atime $far_past_mtime" ] || \
5402                         error "atime or mtime set incorrectly"
5403
5404                 cancel_lru_locks $OSC
5405                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5406         done
5407 }
5408 run_test 39m "test atime and mtime before 1970"
5409
5410 test_39n() { # LU-3832
5411         remote_mds_nodsh && skip "remote MDS with nodsh"
5412
5413         local atime_diff=$(do_facet $SINGLEMDS \
5414                 lctl get_param -n mdd.*MDT0000*.atime_diff)
5415         local atime0
5416         local atime1
5417         local atime2
5418
5419         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=1
5420
5421         rm -rf $DIR/$tfile
5422         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer
5423         atime0=$(stat -c %X $DIR/$tfile)
5424
5425         sleep 5
5426         $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
5427         atime1=$(stat -c %X $DIR/$tfile)
5428
5429         sleep 5
5430         cancel_lru_locks mdc
5431         cancel_lru_locks osc
5432         $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
5433         atime2=$(stat -c %X $DIR/$tfile)
5434
5435         do_facet $SINGLEMDS \
5436                 lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff
5437
5438         [ "$atime0" -eq "$atime1" ] || error "atime0 $atime0 != atime1 $atime1"
5439         [ "$atime1" -eq "$atime2" ] || error "atime0 $atime0 != atime1 $atime1"
5440 }
5441 run_test 39n "check that O_NOATIME is honored"
5442
5443 test_39o() {
5444         TESTDIR=$DIR/$tdir/$tfile
5445         [ -e $TESTDIR ] && rm -rf $TESTDIR
5446         mkdir -p $TESTDIR
5447         cd $TESTDIR
5448         links1=2
5449         ls
5450         mkdir a b
5451         ls
5452         links2=$(stat -c %h .)
5453         [ $(($links1 + 2)) != $links2 ] &&
5454                 error "wrong links count $(($links1 + 2)) != $links2"
5455         rmdir b
5456         links3=$(stat -c %h .)
5457         [ $(($links1 + 1)) != $links3 ] &&
5458                 error "wrong links count $links1 != $links3"
5459         return 0
5460 }
5461 run_test 39o "directory cached attributes updated after create"
5462
5463 test_39p() {
5464         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
5465
5466         local MDTIDX=1
5467         TESTDIR=$DIR/$tdir/$tdir
5468         [ -e $TESTDIR ] && rm -rf $TESTDIR
5469         test_mkdir -p $TESTDIR
5470         cd $TESTDIR
5471         links1=2
5472         ls
5473         test_mkdir -i $MDTIDX $TESTDIR/remote_dir1
5474         test_mkdir -i $MDTIDX $TESTDIR/remote_dir2
5475         ls
5476         links2=$(stat -c %h .)
5477         [ $(($links1 + 2)) != $links2 ] &&
5478                 error "wrong links count $(($links1 + 2)) != $links2"
5479         rmdir remote_dir2
5480         links3=$(stat -c %h .)
5481         [ $(($links1 + 1)) != $links3 ] &&
5482                 error "wrong links count $links1 != $links3"
5483         return 0
5484 }
5485 run_test 39p "remote directory cached attributes updated after create ========"
5486
5487 test_39r() {
5488         [ $OST1_VERSION -ge $(version_code 2.13.52) ] ||
5489                 skip "no atime update on old OST"
5490         if [ "$ost1_FSTYPE" != ldiskfs ]; then
5491                 skip_env "ldiskfs only test"
5492         fi
5493
5494         local saved_adiff
5495         local ahost=$(facet_active_host ost1)
5496         saved_adiff=$(do_facet ost1 \
5497                 lctl get_param -n obdfilter.*OST0000.atime_diff)
5498         stack_trap "do_facet ost1 \
5499                 lctl set_param obdfilter.*.atime_diff=$saved_adiff"
5500
5501         do_facet ost1 "lctl set_param obdfilter.*.atime_diff=5"
5502
5503         $LFS setstripe -i 0 $DIR/$tfile
5504         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 ||
5505                 error "can't write initial file"
5506         cancel_lru_locks osc
5507
5508         # exceed atime_diff and access file
5509         sleep 10
5510         dd if=$DIR/$tfile of=/dev/null bs=4k count=1 ||
5511                 error "can't udpate atime"
5512
5513         # atime_cli value is in decimal
5514         local atime_cli=$(stat -c %X $DIR/$tfile)
5515         echo "client atime: $atime_cli"
5516
5517         local ostdev=$(ostdevname 1)
5518         local fids=($($LFS getstripe $DIR/$tfile | grep 0x))
5519         local fid="${fids[3]}:${fids[2]}:0"
5520         local objpath=$(ost_fid2_objpath ost1 $fid)
5521         local cmd="debugfs -c -R \\\"stat $objpath\\\" $ostdev"
5522
5523         # allow atime update to be written to device
5524         do_facet ost1 "$LCTL set_param -n osd*.*OST*.force_sync=1"
5525         echo "OST atime: $(do_facet ost1 "$cmd" |& grep atime)"
5526
5527         # Give enough time for server to get updated. Until then
5528         # the value read is defaulted to "0x00000000:00000000"
5529         # Wait until atime read via debugfs is not equal to zero.
5530         # Max limit to wait is 30 seconds.
5531         wait_update_cond $ahost                                         \
5532                 "$cmd |& awk -F'[: ]' '/atime:/ { print \\\$4 }'"       \
5533                 "-gt" "0" 30 || error "atime on ost is still 0 after 30 seconds"
5534         # atime_ost value is in hex
5535         local atime_ost=$(do_facet ost1 "$cmd" |&
5536                           awk -F'[: ]' '/atime:/ { print $4 }')
5537         # debugfs returns atime in 0xNNNNNNNN:00000000 format
5538         # convert Hex to decimal before comparing
5539         local atime_ost_dec=$((atime_ost))
5540
5541         # The test pass criteria is that the client time and server should
5542         # be same (2s gap accepted). This gap could arise due to VFS updating
5543         # the atime after the read(dd), stat and the updated time from the
5544         # inode
5545         (( $((atime_cli - atime_ost_dec)) <= 2 )) ||
5546                 error "atime on client $atime_cli != ost $atime_ost_dec"
5547 }
5548 run_test 39r "lazy atime update on OST"
5549
5550 test_39q() { # LU-8041
5551         local testdir=$DIR/$tdir
5552         mkdir -p $testdir
5553         multiop_bg_pause $testdir D_c || error "multiop failed"
5554         local multipid=$!
5555         cancel_lru_locks mdc
5556         kill -USR1 $multipid
5557         local atime=$(stat -c %X $testdir)
5558         [ "$atime" -ne 0 ] || error "atime is zero"
5559 }
5560 run_test 39q "close won't zero out atime"
5561
5562 test_39s() {
5563         local atime0
5564         local atime1
5565         local atime2
5566         local atime3
5567         local atime4
5568
5569         umount_client $MOUNT
5570         mount_client $MOUNT relatime
5571
5572         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer conv=fsync
5573         atime0=$(stat -c %X $DIR/$tfile)
5574
5575         # First read updates atime
5576         sleep 1
5577         cat $DIR/$tfile >/dev/null
5578         atime1=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
5579
5580         # Next reads do not update atime
5581         sleep 1
5582         cat $DIR/$tfile >/dev/null
5583         atime2=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
5584
5585         # If mtime is greater than atime, atime is updated
5586         sleep 1
5587         touch -m $DIR/$tfile # (mtime = now)
5588         sleep 1
5589         cat $DIR/$tfile >/dev/null # (atime is updated because atime < mtime)
5590         atime3=$(stat -c %X $DIR/$tfile) # (atime = mtime = atime0 + 3)
5591
5592         # Next reads do not update atime
5593         sleep 1
5594         cat $DIR/$tfile >/dev/null
5595         atime4=$(stat -c %X $DIR/$tfile)
5596
5597         # Remount the client to clear 'relatime' option
5598         remount_client $MOUNT
5599
5600         (( atime0 < atime1 )) ||
5601                 error "atime $atime0 should be smaller than $atime1"
5602         (( atime1 == atime2 )) ||
5603                 error "atime $atime1 was updated to $atime2"
5604         (( atime1 < atime3 )) || error "atime1 $atime1 != atime3 $atime3"
5605         (( atime3 == atime4 )) || error "atime3 $atime3 != atime4 $atime4"
5606 }
5607 run_test 39s "relatime is supported"
5608
5609 test_39u() {
5610         touch $DIR/$tfile
5611         stack_trap "rm -f $DIR/$tfile"
5612         sleep 2
5613         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 conv=notrunc ||
5614                 error "dd failed"
5615
5616         #define OBD_FAIL_LLITE_STAT_RACE1                       0x1434
5617         $LCTL set_param fail_loc=0x80001434
5618
5619         local mtimes=($(stat -c "%Y" $DIR/$tfile &
5620                         sleep 1; stat -c "%Y" $DIR/$tfile; wait))
5621
5622         (( ${mtimes[0]} == ${mtimes[1]} )) ||
5623                 error "mtime mismatch ${mtimes[0]} != ${mtimes[1]}"
5624 }
5625 run_test 39u "stat race"
5626
5627 test_40() {
5628         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
5629         $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&
5630                 error "openfile O_WRONLY:O_TRUNC $tfile failed"
5631         $CHECKSTAT -t file -s 4096 $DIR/$tfile ||
5632                 error "$tfile is not 4096 bytes in size"
5633 }
5634 run_test 40 "failed open(O_TRUNC) doesn't truncate ============="
5635
5636 test_41() {
5637         # bug 1553
5638         small_write $DIR/f41 18
5639 }
5640 run_test 41 "test small file write + fstat ====================="
5641
5642 count_ost_writes() {
5643         lctl get_param -n ${OSC}.*.stats |
5644                 awk -vwrites=0 '/ost_write/ { writes += $2 } \
5645                         END { printf("%0.0f", writes) }'
5646 }
5647
5648 # decent default
5649 WRITEBACK_SAVE=500
5650 DIRTY_RATIO_SAVE=40
5651 MAX_DIRTY_RATIO=50
5652 BG_DIRTY_RATIO_SAVE=10
5653 MAX_BG_DIRTY_RATIO=25
5654
5655 start_writeback() {
5656         trap 0
5657         # in 2.6, restore /proc/sys/vm/dirty_writeback_centisecs,
5658         # dirty_ratio, dirty_background_ratio
5659         if [ -f /proc/sys/vm/dirty_writeback_centisecs ]; then
5660                 sysctl -w vm.dirty_writeback_centisecs=$WRITEBACK_SAVE
5661                 sysctl -w vm.dirty_background_ratio=$BG_DIRTY_RATIO_SAVE
5662                 sysctl -w vm.dirty_ratio=$DIRTY_RATIO_SAVE
5663         else
5664                 # if file not here, we are a 2.4 kernel
5665                 kill -CONT `pidof kupdated`
5666         fi
5667 }
5668
5669 stop_writeback() {
5670         # setup the trap first, so someone cannot exit the test at the
5671         # exact wrong time and mess up a machine
5672         trap start_writeback EXIT
5673         # in 2.6, save and 0 /proc/sys/vm/dirty_writeback_centisecs
5674         if [ -f /proc/sys/vm/dirty_writeback_centisecs ]; then
5675                 WRITEBACK_SAVE=`sysctl -n vm.dirty_writeback_centisecs`
5676                 sysctl -w vm.dirty_writeback_centisecs=0
5677                 sysctl -w vm.dirty_writeback_centisecs=0
5678                 # save and increase /proc/sys/vm/dirty_ratio
5679                 DIRTY_RATIO_SAVE=`sysctl -n vm.dirty_ratio`
5680                 sysctl -w vm.dirty_ratio=$MAX_DIRTY_RATIO
5681                 # save and increase /proc/sys/vm/dirty_background_ratio
5682                 BG_DIRTY_RATIO_SAVE=`sysctl -n vm.dirty_background_ratio`
5683                 sysctl -w vm.dirty_background_ratio=$MAX_BG_DIRTY_RATIO
5684         else
5685                 # if file not here, we are a 2.4 kernel
5686                 kill -STOP `pidof kupdated`
5687         fi
5688 }
5689
5690 # ensure that all stripes have some grant before we test client-side cache
5691 setup_test42() {
5692         for i in `seq -f $DIR/f42-%g 1 $OSTCOUNT`; do
5693                 dd if=/dev/zero of=$i bs=4k count=1
5694                 rm $i
5695         done
5696 }
5697
5698 # Tests 42* verify that our behaviour is correct WRT caching, file closure,
5699 # file truncation, and file removal.
5700 test_42a() {
5701         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5702
5703         setup_test42
5704         cancel_lru_locks $OSC
5705         stop_writeback
5706         sync; sleep 1; sync # just to be safe
5707         BEFOREWRITES=`count_ost_writes`
5708         lctl get_param -n osc.*[oO][sS][cC][_-]*.cur_grant_bytes | grep "[0-9]"
5709         dd if=/dev/zero of=$DIR/f42a bs=1024 count=100
5710         AFTERWRITES=`count_ost_writes`
5711         [ $BEFOREWRITES -eq $AFTERWRITES ] || \
5712                 error "$BEFOREWRITES < $AFTERWRITES"
5713         start_writeback
5714 }
5715 run_test 42a "ensure that we don't flush on close"
5716
5717 test_42b() {
5718         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5719
5720         setup_test42
5721         cancel_lru_locks $OSC
5722         stop_writeback
5723         sync
5724         dd if=/dev/zero of=$DIR/f42b bs=1024 count=100
5725         BEFOREWRITES=$(count_ost_writes)
5726         unlink $DIR/f42b || error "unlink $DIR/f42b: $?"
5727         AFTERWRITES=$(count_ost_writes)
5728         if [[ $BEFOREWRITES -lt $AFTERWRITES ]]; then
5729                 error "$BEFOREWRITES < $AFTERWRITES on unlink"
5730         fi
5731         BEFOREWRITES=$(count_ost_writes)
5732         sync || error "sync: $?"
5733         AFTERWRITES=$(count_ost_writes)
5734         if [[ $BEFOREWRITES -lt $AFTERWRITES ]]; then
5735                 error "$BEFOREWRITES < $AFTERWRITES on sync"
5736         fi
5737         dmesg | grep 'error from obd_brw_async' && error 'error writing back'
5738         start_writeback
5739         return 0
5740 }
5741 run_test 42b "test destroy of file with cached dirty data ======"
5742
5743 # if these tests just want to test the effect of truncation,
5744 # they have to be very careful.  consider:
5745 # - the first open gets a {0,EOF}PR lock
5746 # - the first write conflicts and gets a {0, count-1}PW
5747 # - the rest of the writes are under {count,EOF}PW
5748 # - the open for truncate tries to match a {0,EOF}PR
5749 #   for the filesize and cancels the PWs.
5750 # any number of fixes (don't get {0,EOF} on open, match
5751 # composite locks, do smarter file size management) fix
5752 # this, but for now we want these tests to verify that
5753 # the cancellation with truncate intent works, so we
5754 # start the file with a full-file pw lock to match against
5755 # until the truncate.
5756 trunc_test() {
5757         test=$1
5758         file=$DIR/$test
5759         offset=$2
5760         cancel_lru_locks $OSC
5761         stop_writeback
5762         # prime the file with 0,EOF PW to match
5763         touch $file
5764         $TRUNCATE $file 0
5765         sync; sync
5766         # now the real test..
5767         dd if=/dev/zero of=$file bs=1024 count=100
5768         BEFOREWRITES=`count_ost_writes`
5769         $TRUNCATE $file $offset
5770         cancel_lru_locks $OSC
5771         AFTERWRITES=`count_ost_writes`
5772         start_writeback
5773 }
5774
5775 test_42c() {
5776         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5777
5778         trunc_test 42c 1024
5779         [ $BEFOREWRITES -eq $AFTERWRITES ] &&
5780                 error "beforewrites $BEFOREWRITES == afterwrites $AFTERWRITES on truncate"
5781         rm $file
5782 }
5783 run_test 42c "test partial truncate of file with cached dirty data"
5784
5785 test_42d() {
5786         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5787
5788         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
5789         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
5790         $LCTL set_param debug=+cache
5791
5792         trunc_test 42d 0
5793         [ $BEFOREWRITES -eq $AFTERWRITES ] ||
5794                 error "beforewrites $BEFOREWRITES != afterwrites $AFTERWRITES on truncate"
5795         rm $file
5796 }
5797 run_test 42d "test complete truncate of file with cached dirty data"
5798
5799 test_42e() { # bug22074
5800         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5801
5802         local TDIR=$DIR/${tdir}e
5803         local pages=16 # hardcoded 16 pages, don't change it.
5804         local files=$((OSTCOUNT * 500)) # hopefully 500 files on each OST
5805         local proc_osc0="osc.${FSNAME}-OST0000-osc-[^MDT]*"
5806         local max_dirty_mb
5807         local warmup_files
5808
5809         test_mkdir $DIR/${tdir}e
5810         $LFS setstripe -c 1 $TDIR
5811         createmany -o $TDIR/f $files
5812
5813         max_dirty_mb=$($LCTL get_param -n $proc_osc0/max_dirty_mb)
5814
5815         # we assume that with $OSTCOUNT files, at least one of them will
5816         # be allocated on OST0.
5817         warmup_files=$((OSTCOUNT * max_dirty_mb))
5818         createmany -o $TDIR/w $warmup_files
5819
5820         # write a large amount of data into one file and sync, to get good
5821         # avail_grant number from OST.
5822         for ((i=0; i<$warmup_files; i++)); do
5823                 idx=$($LFS getstripe -i $TDIR/w$i)
5824                 [ $idx -ne 0 ] && continue
5825                 dd if=/dev/zero of=$TDIR/w$i bs="$max_dirty_mb"M count=1
5826                 break
5827         done
5828         [[ $i -gt $warmup_files ]] && error "OST0 is still cold"
5829         sync
5830         $LCTL get_param $proc_osc0/cur_dirty_bytes
5831         $LCTL get_param $proc_osc0/cur_grant_bytes
5832
5833         # create as much dirty pages as we can while not to trigger the actual
5834         # RPCs directly. but depends on the env, VFS may trigger flush during this
5835         # period, hopefully we are good.
5836         for ((i=0; i<$warmup_files; i++)); do
5837                 idx=$($LFS getstripe -i $TDIR/w$i)
5838                 [ $idx -ne 0 ] && continue
5839                 dd if=/dev/zero of=$TDIR/w$i bs=1M count=1 2>/dev/null
5840         done
5841         $LCTL get_param $proc_osc0/cur_dirty_bytes
5842         $LCTL get_param $proc_osc0/cur_grant_bytes
5843
5844         # perform the real test
5845         $LCTL set_param $proc_osc0/rpc_stats 0
5846         for ((;i<$files; i++)); do
5847                 [ $($LFS getstripe -i $TDIR/f$i) -eq 0 ] || continue
5848                 dd if=/dev/zero of=$TDIR/f$i bs=$PAGE_SIZE count=$pages 2>/dev/null
5849         done
5850         sync
5851         $LCTL get_param $proc_osc0/rpc_stats
5852
5853         local percent=0
5854         local have_ppr=false
5855         $LCTL get_param $proc_osc0/rpc_stats |
5856                 while read PPR RRPC RPCT RCUM BAR WRPC WPCT WCUM; do
5857                         # skip lines until we are at the RPC histogram data
5858                         [ "$PPR" == "pages" ] && have_ppr=true && continue
5859                         $have_ppr || continue
5860
5861                         # we only want the percent stat for < 16 pages
5862                         [[ $(echo $PPR | tr -d ':') -ge $pages ]] && break
5863
5864                         percent=$((percent + WPCT))
5865                         if [[ $percent -gt 15 ]]; then
5866                                 error "less than 16-pages write RPCs" \
5867                                       "$percent% > 15%"
5868                                 break
5869                         fi
5870                 done
5871         rm -rf $TDIR
5872 }
5873 run_test 42e "verify sub-RPC writes are not done synchronously"
5874
5875 test_43A() { # was test_43
5876         test_mkdir $DIR/$tdir
5877         cp -p /bin/ls $DIR/$tdir/$tfile
5878         $MULTIOP $DIR/$tdir/$tfile Ow_c &
5879         pid=$!
5880         # give multiop a chance to open
5881         sleep 1
5882
5883         $DIR/$tdir/$tfile && error "execute $DIR/$tdir/$tfile succeeded" || true
5884         kill -USR1 $pid
5885         # Wait for multiop to exit
5886         wait $pid
5887 }
5888 run_test 43A "execution of file opened for write should return -ETXTBSY"
5889
5890 test_43a() {
5891         test_mkdir $DIR/$tdir
5892         cp -p $(which sleep) $DIR/$tdir/sleep || error "can't copy"
5893         $DIR/$tdir/sleep 60 &
5894         SLEEP_PID=$!
5895         # Make sure exec of $tdir/sleep wins race with truncate
5896         sleep 1
5897         $MULTIOP $DIR/$tdir/sleep Oc && error "expected error, got success"
5898         kill $SLEEP_PID
5899 }
5900 run_test 43a "open(RDWR) of file being executed should return -ETXTBSY"
5901
5902 test_43b() {
5903         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5904
5905         test_mkdir $DIR/$tdir
5906         cp -p $(which sleep) $DIR/$tdir/sleep || error "can't copy"
5907         $DIR/$tdir/sleep 60 &
5908         SLEEP_PID=$!
5909         # Make sure exec of $tdir/sleep wins race with truncate
5910         sleep 1
5911         $TRUNCATE $DIR/$tdir/sleep 0 && error "expected error, got success"
5912         kill $SLEEP_PID
5913 }
5914 run_test 43b "truncate of file being executed should return -ETXTBSY"
5915
5916 test_43c() {
5917         local testdir="$DIR/$tdir"
5918         test_mkdir $testdir
5919         cp $SHELL $testdir/
5920         ( cd $(dirname $SHELL) && md5sum $(basename $SHELL) ) |
5921                 ( cd $testdir && md5sum -c )
5922 }
5923 run_test 43c "md5sum of copy into lustre"
5924
5925 test_44A() { # was test_44
5926         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
5927
5928         dd if=/dev/zero of=$DIR/f1 bs=4k count=1 seek=1023
5929         dd if=$DIR/f1 bs=4k count=1 > /dev/null
5930 }
5931 run_test 44A "zero length read from a sparse stripe"
5932
5933 test_44a() {
5934         local nstripe=$($LFS getstripe -c -d $DIR)
5935         [ -z "$nstripe" ] && skip "can't get stripe info"
5936         [[ $nstripe -gt $OSTCOUNT ]] &&
5937                 skip "Wrong default stripe_count: $nstripe OSTCOUNT: $OSTCOUNT"
5938
5939         local stride=$($LFS getstripe -S -d $DIR)
5940         if [[ $nstripe -eq 0 || $nstripe -eq -1 ]]; then
5941                 nstripe=$($LFS df $DIR | grep OST: | wc -l)
5942         fi
5943
5944         OFFSETS="0 $((stride/2)) $((stride-1))"
5945         for offset in $OFFSETS; do
5946                 for i in $(seq 0 $((nstripe-1))); do
5947                         local GLOBALOFFSETS=""
5948                         # size in Bytes
5949                         local size=$((((i + 2 * $nstripe )*$stride + $offset)))
5950                         local myfn=$DIR/d44a-$size
5951                         echo "--------writing $myfn at $size"
5952                         ll_sparseness_write $myfn $size ||
5953                                 error "ll_sparseness_write"
5954                         GLOBALOFFSETS="$GLOBALOFFSETS $size"
5955                         ll_sparseness_verify $myfn $GLOBALOFFSETS ||
5956                                 error "ll_sparseness_verify $GLOBALOFFSETS"
5957
5958                         for j in $(seq 0 $((nstripe-1))); do
5959                                 # size in Bytes
5960                                 size=$((((j + $nstripe )*$stride + $offset)))
5961                                 ll_sparseness_write $myfn $size ||
5962                                         error "ll_sparseness_write"
5963                                 GLOBALOFFSETS="$GLOBALOFFSETS $size"
5964                         done
5965                         ll_sparseness_verify $myfn $GLOBALOFFSETS ||
5966                                 error "ll_sparseness_verify $GLOBALOFFSETS"
5967                         rm -f $myfn
5968                 done
5969         done
5970 }
5971 run_test 44a "test sparse pwrite ==============================="
5972
5973 test_44b() {
5974         (( $OST1_VERSION >= $(version_code 2.15.61.137) )) ||
5975                 skip "Need OST >= 2.15.61.137 for large object handling"
5976
5977         $LFS setstripe -c 1 $DIR/$tfile || error "setstripe failed"
5978         local off=$((2**32*4096-8192))
5979         dd if=/dev/zero of=$DIR/$tfile bs=1 count=1 seek=$off conv=notrunc ||
5980                 error "dd failed"
5981         cancel_lru_locks osc
5982         $CHECKSTAT -s $((2**32*4096-8192+1)) $DIR/$tfile || error "wrong size"
5983 }
5984 run_test 44b "write one byte at offset 0xfffffffe000"
5985
5986 test_44c() {
5987         (( $OST1_VERSION >= $(version_code 2.15.61.137) )) ||
5988                 skip "Need OST >= 2.15.61.137 for large object handling"
5989
5990         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
5991         local max_object_bytes=$(import_param $osc_tgt max_object_bytes)
5992
5993         $LFS setstripe -c 1 $DIR/$tfile || error "setstripe failed"
5994
5995         dd if=/dev/zero of=$DIR/$tfile conv=notrunc bs=1 count=1 \
5996                 seek=$((max_object_bytes - 1)) || error "dd failed"
5997         cancel_lru_locks osc
5998         $CHECKSTAT -s $max_object_bytes $DIR/$tfile || error "wrong size"
5999 }
6000 run_test 44c "write 1 byte at max_object_bytes - 1 offset"
6001
6002 test_44d() {
6003         (( $OST1_VERSION >= $(version_code 2.15.61.137) )) ||
6004                 skip "Need OST >= 2.15.61.137 for large object handling"
6005
6006         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
6007         local max_object_bytes=$(import_param $osc_tgt max_object_bytes)
6008
6009         $LFS setstripe -c 2 $DIR/$tfile || error "setstripe failed"
6010
6011         local stripe_size=$($LFS getstripe -S $DIR/$tfile)
6012         local off=$((max_object_bytes & ~(stripe_size - 1)))
6013
6014         $TRUNCATE $DIR/$tfile $off
6015         dd if=/dev/zero of=$DIR/$tfile bs=1 count=1 seek=$off
6016         local rc1=$?
6017         dd if=/dev/zero of=$DIR/$tfile oflag=append conv=notrunc bs=1 count=1 \
6018                 seek=$off
6019         local rc2=$?
6020         [[ $rc1 -eq 0 && $rc2 -eq 0 ]] || error "one of dd commands failed"
6021 }
6022 run_test 44d "if write at position fails (EFBIG), so should do append"
6023
6024 # write file until maximal size is reached
6025 max_file_size() {
6026         local file=$1
6027
6028         off=1
6029         minoff=1
6030         while true; do
6031                 echo a | dd of=$1 bs=1 count=1 conv=notrunc seek=$off status=progress \
6032                         2>/dev/null
6033                 [[ $? -ne 0 ]] && break
6034                 minoff=$off
6035                 off=$(echo "$off * 2" | bc)
6036         done
6037         maxoff=$off
6038         minoff_1=$(echo $off + 1 | bc)
6039         while [[ maxoff -ne minoff_1 ]]; do
6040                 off=$(echo "($maxoff + $minoff) / 2" | bc)
6041                 echo a | dd of=$1 bs=1 count=1 conv=notrunc seek=$off status=progress \
6042                         2>/dev/null
6043                 [[ $? -eq 0 ]] && minoff=$off || maxoff=$off
6044                 minoff_1=$(echo $off + 1 | bc)
6045         done
6046         stat -c %s $file
6047 }
6048
6049 test_44e_write_read()
6050 {
6051         local ifile=$1
6052         local ofile=$2
6053         local stripe_count=$3
6054         local stripe_size=$($LFS getstripe -S $ofile)
6055         local file_size=$(max_file_size $ofile)
6056         local write_count=$((stripe_count * stripe_size))
6057         local offset=$((file_size - write_count))
6058
6059         dd if=/dev/urandom of=$ifile bs=$write_count count=1 ||
6060                 error "failed to write random data"
6061
6062         dd if=$ifile of=$ofile bs=$write_count count=1 oflag=seek_bytes \
6063                 seek=$offset conv=notrunc || error "dd failed"
6064         cancel_lru_locks osc
6065         cmp $ifile $ofile -i 0:$offset -n $write_count || error "cmp failed"
6066 }
6067
6068 test_44e() {
6069         (( $OST1_VERSION >= $(version_code 2.15.61.137) )) ||
6070                     skip "Need OST >= 2.15.61.137 for large object handling"
6071
6072         local TF="$(mktemp --tmpdir -u $tfile.XXXXXX)"
6073
6074         $LFS setstripe -S 1M -c $OSTCOUNT $DIR/$tfile ||
6075                 error "lfs setstripe -S 1M -c $OSTCOUNT failed"
6076         test_44e_write_read $TF $DIR/$tfile $OSTCOUNT
6077         rm -f $DIR/$tfile
6078         rm -f $TF
6079
6080         $LFS setstripe -S 1M -c $OSTCOUNT -C $((OSTCOUNT * 2)) $DIR/$tfile ||
6081                 error "lfs setstripe -S 1M -c $OSTCOUNT -C [* 2] failed"
6082         test_44e_write_read $TF $DIR/$tfile $((OSTCOUNT * 2))
6083
6084         rm -f $DIR/$tfile
6085         rm -f $TF
6086 }
6087 run_test 44e "write and read maximal stripes"
6088
6089 test_44f() {
6090         [ "$FSTYPE" != "zfs" ] ||
6091                 skip "ORI-366/LU-1941: FIEMAP unimplemented on ZFS"
6092
6093         stack_trap "rm -f $DIR/$tfile-*"
6094         local i
6095         # required space: NUMFILES_44f * 20Mb
6096         local NUMFILES_44f=${NUMFILES_44f:-50}
6097
6098         for (( i=0; i<NUMFILES_44f; i++ )); do
6099                 multiop $DIR/$tfile-$i \
6100                         Ow10485760Z10485760w10485760Ic ||
6101                         error "multiop failed"
6102         done
6103 }
6104 run_test 44f "Check fiemap for sparse files"
6105
6106 test_44g() {
6107         # max stripe size is 4G - 64K
6108         $LFS setstripe -C 4 -S 4194240k $DIR/$tfile
6109         dd if=/dev/zero of=$DIR/$tfile conv=notrunc bs=64k count=1 \
6110            seek=$((65535 * 3 + 65533))
6111
6112         $LFS setstripe -c 2 -S 2g $DIR/$tfile-2
6113         dd if=/dev/zero of=$DIR/$tfile-2 conv=notrunc bs=64k count=1 \
6114            seek=65535
6115
6116         cancel_lru_locks osc
6117
6118         $CHECKSTAT -s $(((65535 * 3 + 65534) * 65536)) $DIR/$tfile ||
6119             error "wrong $DIR/$tfile size"
6120         $CHECKSTAT -s 4294967296 $DIR/$tfile-2 ||
6121             error "wrong $DIR/$tfile-2 size"
6122 }
6123 run_test 44g "test overflow in lov_stripe_size"
6124
6125 dirty_osc_total() {
6126         tot=0
6127         for d in `lctl get_param -n ${OSC}.*.cur_dirty_bytes`; do
6128                 tot=$(($tot + $d))
6129         done
6130         echo $tot
6131 }
6132 do_dirty_record() {
6133         before=`dirty_osc_total`
6134         echo executing "\"$*\""
6135         eval $*
6136         after=`dirty_osc_total`
6137         echo before $before, after $after
6138 }
6139 test_45() {
6140         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6141
6142         f="$DIR/f45"
6143         # Obtain grants from OST if it supports it
6144         echo blah > ${f}_grant
6145         stop_writeback
6146         sync
6147
6148         # cur_dirty_bytes is related and modified by the OSC cache granting
6149         # code. It is possible for the grants to be freed during async IO
6150         # completion resulting in 0 vs 0 comparisons for truncates and sync.
6151         # Since it can't be reliably proven that the operation did lower the
6152         # count, the comparisons are changed to >= (ge) rather than > (gt).
6153         #
6154         # N.B. This whole test seems flawed as the process doesn't hold file
6155         # descriptors, syscalls are not explicit, and dirty data is subject to
6156         # async changes outside of the MM subsystem. Some consideration should
6157         # be given to removing/rewriting this test.
6158         do_dirty_record "echo blah > $f"
6159         (( before == after )) && error "write wasn't cached"
6160         do_dirty_record "> $f"
6161         (( before >= after )) || error "truncate didn't lower dirty count"
6162         do_dirty_record "echo blah > $f"
6163         (( before == after )) && error "write wasn't cached"
6164         do_dirty_record "sync"
6165         (( after == 0 )) || error "writeback didn't zero dirty count"
6166         do_dirty_record "echo blah > $f"
6167         (( before == after )) && error "write wasn't cached"
6168         do_dirty_record "cancel_lru_locks osc"
6169         (( before >= after )) ||
6170                 error "lock cancellation didn't lower dirty count"
6171         start_writeback
6172 }
6173 run_test 45 "osc io page accounting"
6174
6175 # in a 2 stripe file (lov.sh), page 1023 maps to page 511 in its object.  this
6176 # test tickles a bug where re-dirtying a page was failing to be mapped to the
6177 # objects offset and an assert hit when an rpc was built with 1023's mapped
6178 # offset 511 and 511's raw 511 offset. it also found general redirtying bugs.
6179 test_46() {
6180         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6181
6182         f="$DIR/f46"
6183         stop_writeback
6184         sync
6185         dd if=/dev/zero of=$f bs=$PAGE_SIZE seek=511 count=1
6186         sync
6187         dd conv=notrunc if=/dev/zero of=$f bs=$PAGE_SIZE seek=1023 count=1
6188         dd conv=notrunc if=/dev/zero of=$f bs=$PAGE_SIZE seek=511 count=1
6189         sync
6190         start_writeback
6191 }
6192 run_test 46 "dirtying a previously written page ================"
6193
6194 # test_47 is removed "Device nodes check" is moved to test_28
6195
6196 test_48a() { # bug 2399
6197         [ "$mds1_FSTYPE" = "zfs" ] &&
6198         [ $MDS1_VERSION -lt $(version_code 2.3.63) ] &&
6199                 skip "MDS prior to 2.3.63 handle ZFS dir .. incorrectly"
6200
6201         test_mkdir $DIR/$tdir
6202         cd $DIR/$tdir
6203         mv $DIR/$tdir $DIR/$tdir.new || error "move directory failed"
6204         test_mkdir $DIR/$tdir
6205         touch foo || error "'touch foo' failed after recreating cwd"
6206         test_mkdir bar
6207         touch .foo || error "'touch .foo' failed after recreating cwd"
6208         test_mkdir .bar
6209         ls . > /dev/null || error "'ls .' failed after recreating cwd"
6210         ls .. > /dev/null || error "'ls ..' failed after removing cwd"
6211         cd . || error "'cd .' failed after recreating cwd"
6212         mkdir . && error "'mkdir .' worked after recreating cwd"
6213         rmdir . && error "'rmdir .' worked after recreating cwd"
6214         ln -s . baz || error "'ln -s .' failed after recreating cwd"
6215         cd .. || error "'cd ..' failed after recreating cwd"
6216 }
6217 run_test 48a "Access renamed working dir (should return errors)="
6218
6219 test_48b() { # bug 2399
6220         rm -rf $DIR/$tdir
6221         test_mkdir $DIR/$tdir
6222         cd $DIR/$tdir
6223         rmdir $DIR/$tdir || error "remove cwd $DIR/$tdir failed"
6224         touch foo && error "'touch foo' worked after removing cwd"
6225         mkdir foo && error "'mkdir foo' worked after removing cwd"
6226         touch .foo && error "'touch .foo' worked after removing cwd"
6227         mkdir .foo && error "'mkdir .foo' worked after removing cwd"
6228         ls . > /dev/null && error "'ls .' worked after removing cwd"
6229         ls .. > /dev/null || error "'ls ..' failed after removing cwd"
6230         mkdir . && error "'mkdir .' worked after removing cwd"
6231         rmdir . && error "'rmdir .' worked after removing cwd"
6232         ln -s . foo && error "'ln -s .' worked after removing cwd"
6233         cd .. || echo "'cd ..' failed after removing cwd `pwd`"  #bug 3517
6234 }
6235 run_test 48b "Access removed working dir (should return errors)="
6236
6237 test_48c() { # bug 2350
6238         #lctl set_param debug=-1
6239         #set -vx
6240         rm -rf $DIR/$tdir
6241         test_mkdir -p $DIR/$tdir/dir
6242         cd $DIR/$tdir/dir
6243         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
6244         $TRACE touch foo && error "touch foo worked after removing cwd"
6245         $TRACE mkdir foo && error "'mkdir foo' worked after removing cwd"
6246         touch .foo && error "touch .foo worked after removing cwd"
6247         mkdir .foo && error "mkdir .foo worked after removing cwd"
6248         $TRACE ls . && error "'ls .' worked after removing cwd"
6249         $TRACE ls .. || error "'ls ..' failed after removing cwd"
6250         $TRACE mkdir . && error "'mkdir .' worked after removing cwd"
6251         $TRACE rmdir . && error "'rmdir .' worked after removing cwd"
6252         $TRACE ln -s . foo && error "'ln -s .' worked after removing cwd"
6253         $TRACE cd .. || echo "'cd ..' failed after removing cwd `pwd`" #bug 3415
6254 }
6255 run_test 48c "Access removed working subdir (should return errors)"
6256
6257 test_48d() { # bug 2350
6258         #lctl set_param debug=-1
6259         #set -vx
6260         rm -rf $DIR/$tdir
6261         test_mkdir -p $DIR/$tdir/dir
6262         cd $DIR/$tdir/dir
6263         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
6264         $TRACE rmdir $DIR/$tdir || error "remove parent $DIR/$tdir failed"
6265         $TRACE touch foo && error "'touch foo' worked after removing parent"
6266         $TRACE mkdir foo && error "mkdir foo worked after removing parent"
6267         touch .foo && error "'touch .foo' worked after removing parent"
6268         mkdir .foo && error "mkdir .foo worked after removing parent"
6269         $TRACE ls . && error "'ls .' worked after removing parent"
6270         $TRACE ls .. && error "'ls ..' worked after removing parent"
6271         $TRACE mkdir . && error "'mkdir .' worked after removing parent"
6272         $TRACE rmdir . && error "'rmdir .' worked after removing parent"
6273         $TRACE ln -s . foo && error "'ln -s .' worked after removing parent"
6274         true
6275 }
6276 run_test 48d "Access removed parent subdir (should return errors)"
6277
6278 test_48e() { # bug 4134
6279         #lctl set_param debug=-1
6280         #set -vx
6281         rm -rf $DIR/$tdir
6282         test_mkdir -p $DIR/$tdir/dir
6283         cd $DIR/$tdir/dir
6284         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
6285         $TRACE rmdir $DIR/$tdir || error "remove parent $DIR/$tdir failed"
6286         $TRACE touch $DIR/$tdir || error "'touch $DIR/$tdir' failed"
6287         $TRACE chmod +x $DIR/$tdir || error "'chmod +x $DIR/$tdir' failed"
6288         # On a buggy kernel addition of "touch foo" after cd .. will
6289         # produce kernel oops in lookup_hash_it
6290         touch ../foo && error "'cd ..' worked after recreate parent"
6291         cd $DIR
6292         $TRACE rm $DIR/$tdir || error "rm '$DIR/$tdir' failed"
6293 }
6294 run_test 48e "Access to recreated parent subdir (should return errors)"
6295
6296 test_48f() {
6297         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
6298                 skip "need MDS >= 2.13.55"
6299         [[ $MDSCOUNT -ge 2 ]] || skip "needs >= 2 MDTs"
6300         [[ "$(facet_host mds1)" != "$(facet_host mds2)" ]] ||
6301                 skip "needs different host for mdt1 mdt2"
6302         [[ $(facet_fstype mds1) == ldiskfs ]] || skip "ldiskfs only"
6303
6304         $LFS mkdir -i0 $DIR/$tdir
6305         $LFS mkdir -i 1 $DIR/$tdir/sub1 $DIR/$tdir/sub2 $DIR/$tdir/sub3
6306
6307         for d in sub1 sub2 sub3; do
6308                 #define OBD_FAIL_OSD_REF_DEL    0x19c
6309                 do_facet mds1 $LCTL set_param fail_loc=0x8000019c
6310                 rm -rf $DIR/$tdir/$d && error "rm $d should fail"
6311         done
6312
6313         rm -d --interactive=never $DIR/$tdir || error "rm $tdir fail"
6314 }
6315 run_test 48f "non-zero nlink dir unlink won't LBUG()"
6316
6317 test_49() { # LU-1030
6318         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6319         remote_ost_nodsh && skip "remote OST with nodsh"
6320
6321         # get ost1 size - $FSNAME-OST0000
6322         ost1_size=$(do_facet ost1 $LFS df | grep ${ost1_svc} |
6323                 awk '{ print $4 }')
6324         # write 800M at maximum
6325         [[ $ost1_size -lt 2 ]] && ost1_size=2
6326         [[ $ost1_size -gt 819200 ]] && ost1_size=819200
6327
6328         $LFS setstripe -c 1 -i 0 $DIR/$tfile
6329         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((ost1_size >> 2)) &
6330         local dd_pid=$!
6331
6332         # change max_pages_per_rpc while writing the file
6333         local osc1_mppc=osc.$(get_osc_import_name client ost1).max_pages_per_rpc
6334         local orig_mppc=$($LCTL get_param -n $osc1_mppc)
6335         # loop until dd process exits
6336         while ps ax -opid | grep -wq $dd_pid; do
6337                 $LCTL set_param $osc1_mppc=$((RANDOM % 256 + 1))
6338                 sleep $((RANDOM % 5 + 1))
6339         done
6340         # restore original max_pages_per_rpc
6341         $LCTL set_param $osc1_mppc=$orig_mppc
6342         rm $DIR/$tfile || error "rm $DIR/$tfile failed"
6343 }
6344 run_test 49 "Change max_pages_per_rpc won't break osc extent"
6345
6346 test_50() {
6347         # bug 1485
6348         test_mkdir $DIR/$tdir
6349         cd $DIR/$tdir
6350         ls /proc/$$/cwd || error "ls /proc/$$/cwd failed"
6351 }
6352 run_test 50 "special situations: /proc symlinks  ==============="
6353
6354 test_51a() {    # was test_51
6355         # bug 1516 - create an empty entry right after ".." then split dir
6356         test_mkdir -c1 $DIR/$tdir
6357         touch $DIR/$tdir/foo
6358         $MCREATE $DIR/$tdir/bar
6359         rm $DIR/$tdir/foo
6360         createmany -m $DIR/$tdir/longfile 201
6361         FNUM=202
6362         while [[ $(ls -sd $DIR/$tdir | awk '{ print $1 }') -eq 4 ]]; do
6363                 $MCREATE $DIR/$tdir/longfile$FNUM
6364                 FNUM=$(($FNUM + 1))
6365                 echo -n "+"
6366         done
6367         echo
6368         ls -l $DIR/$tdir > /dev/null || error "ls -l $DIR/$tdir failed"
6369 }
6370 run_test 51a "special situations: split htree with empty entry =="
6371
6372 cleanup_print_lfs_df () {
6373         trap 0
6374         $LFS df
6375         $LFS df -i
6376 }
6377
6378 test_51b() {
6379         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6380
6381         local dir=$DIR/$tdir
6382         local nrdirs=$((65536 + 100))
6383
6384         # cleanup the directory
6385         rm -fr $dir
6386
6387         mkdir_on_mdt -i $((RANDOM % MDSCOUNT)) $dir
6388
6389         $LFS df
6390         $LFS df -i
6391         local mdtidx=$(printf "%04x" $($LFS getstripe -m $dir))
6392         local numfree=$(lctl get_param -n mdc.$FSNAME-MDT$mdtidx*.filesfree)
6393         [[ $numfree -lt $nrdirs ]] &&
6394                 skip "not enough free inodes ($numfree) on MDT$mdtidx"
6395
6396         # need to check free space for the directories as well
6397         local blkfree=$(lctl get_param -n mdc.$FSNAME-MDT$mdtidx*.kbytesavail)
6398         numfree=$(( blkfree / $(fs_inode_ksize) ))
6399         [[ $numfree -lt $nrdirs ]] && skip "not enough blocks ($numfree)"
6400
6401         trap cleanup_print_lfs_df EXIT
6402
6403         # create files
6404         createmany -d $dir/d $nrdirs || {
6405                 unlinkmany -d $dir/d $nrdirs
6406                 error "failed to create $nrdirs subdirs in MDT$mdtidx:$dir"
6407         }
6408
6409         # really created :
6410         nrdirs=$(ls -U $dir | wc -l)
6411
6412         # unlink all but 100 subdirectories, then check it still works
6413         local left=100
6414         local delete=$((nrdirs - left))
6415
6416         $LFS df
6417         $LFS df -i
6418
6419         # for ldiskfs the nlink count should be 1, but this is OSD specific
6420         # and so this is listed for informational purposes only
6421         echo "nlink before: $(stat -c %h $dir), created before: $nrdirs"
6422         unlinkmany -d $dir/d $delete ||
6423                 error "unlink of first $delete subdirs failed"
6424
6425         echo "nlink between: $(stat -c %h $dir)"
6426         local found=$(ls -U $dir | wc -l)
6427         [ $found -ne $left ] &&
6428                 error "can't find subdirs: found only $found, expected $left"
6429
6430         unlinkmany -d $dir/d $delete $left ||
6431                 error "unlink of second $left subdirs failed"
6432         # regardless of whether the backing filesystem tracks nlink accurately
6433         # or not, the nlink count shouldn't be more than "." and ".." here
6434         local after=$(stat -c %h $dir)
6435         [[ $after -gt 2 ]] && error "nlink after: $after > 2" ||
6436                 echo "nlink after: $after"
6437
6438         cleanup_print_lfs_df
6439 }
6440 run_test 51b "exceed 64k subdirectory nlink limit on create, verify unlink"
6441
6442 test_51c() {
6443         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
6444         local dir=$DIR/$tdir-c2
6445         local nrdirs=$((65536 * 2 + 2000))
6446         local mdtidx
6447
6448         trap cleanup_print_lfs_df EXIT
6449
6450         $LFS mkdir -c 2 -H fnv_1a_64 $dir
6451         while read mtdidx rest; do
6452                 local mdtname=$FSNAME-MDT$(printf "%04x" $mdtidx)
6453                 local numfree=$(lctl get_param -n mdc.$mdtname*.filesfree)
6454                 local blkfree=$(lctl get_param -n mdc.$mdtname*.kbytesavail)
6455
6456                 (( numfree < nrdirs / 2 || blkfree / $(fs_inode_ksize) < nrdirs / 2 )) &&
6457                         skip "not enough inodes or blocks for mdt$mdtidx"
6458         done < <( $LFS getdirstripe $dir | awk '{ if ($2 ~ /\[0x.*:0x.*:0x.*\]/) {  print $1; } }' )
6459
6460         createmany -d $dir/d $nrdirs ||
6461                 error "failed to create $nrdirs subdirs in $dir"
6462         # nlink for the striped dir should be either 1
6463         # (ldiskfs, nlink is overflowed at least in one stripe)
6464         # or $ndirs + 2
6465         local nlinks=$(stat -c %h $dir)
6466         (( nlinks == 1 || nlinks == nrdirs + 2 )) ||
6467                 error "Wrong nlink count of $nlinks"
6468
6469         unlinkmany -d $dir/d $nrdirs || error "Removal of the subdirs failed"
6470         rmdir $dir || error "rmdir failed"
6471         cleanup_print_lfs_df
6472 }
6473 run_test 51c "exceed 64k subdirectory count per dir stripe, verify nlink count"
6474
6475 test_51d_sub() {
6476         local stripecount=$1
6477         local nfiles=$2
6478
6479         log "create files with stripecount=$stripecount"
6480         $LFS setstripe -C $stripecount $DIR/$tdir
6481         createmany -o $DIR/$tdir/t- $nfiles
6482         $LFS getstripe $DIR/$tdir > $TMP/$tfile
6483         for ((n = 0; n < $OSTCOUNT; n++)); do
6484                 objs[$n]=$(awk -vobjs=0 '($1 == '$n') { objs += 1 } \
6485                            END { printf("%0.0f", objs) }' $TMP/$tfile)
6486                 objs0[$n]=$(grep -A 1 idx $TMP/$tfile | awk -vobjs=0 \
6487                             '($1 == '$n') { objs += 1 } \
6488                             END { printf("%0.0f", objs) }')
6489                 log "OST$n has ${objs[$n]} objects, ${objs0[$n]} are index 0"
6490         done
6491         unlinkmany $DIR/$tdir/t- $nfiles
6492         rm  -f $TMP/$tfile
6493
6494         local nlast
6495         local min=4
6496         local max=6 # allow variance of (1 - $min/$max) = 33% by default
6497
6498         # For some combinations of stripecount and OSTCOUNT current code
6499         # is not ideal, and allocates 50% fewer *first* objects to some OSTs
6500         # than others. Rather than skipping this test entirely, check that
6501         # and keep testing to ensure imbalance does not get worse. LU-15282
6502         (( (OSTCOUNT == 6 && stripecount == 4) ||
6503            (OSTCOUNT == 10 && (stripecount == 4 || stripecount == 8)) ||
6504            (OSTCOUNT == 12 && (stripecount == 8 || stripecount == 9)))) && max=9
6505         for ((nlast=0, n = 1; n < $OSTCOUNT; nlast=n,n++)); do
6506                 (( ${objs[$n]} > ${objs[$nlast]} * 4 / 5 )) ||
6507                         { $LFS df && $LFS df -i &&
6508                         error "stripecount=$stripecount: " \
6509                               "OST $n has fewer objects vs. OST $nlast " \
6510                               "(${objs[$n]} < ${objs[$nlast]} x 4/5)"; }
6511                 (( ${objs[$n]} < ${objs[$nlast]} * 5 / 4 )) ||
6512                         { $LFS df && $LFS df -i &&
6513                         error "stripecount=$stripecount: " \
6514                               "OST $n has more objects vs. OST $nlast " \
6515                               "(${objs[$n]} > ${objs[$nlast]} x 5/4)"; }
6516
6517                 (( ${objs0[$n]} > ${objs0[$nlast]} * $min / $max )) ||
6518                         { $LFS df && $LFS df -i &&
6519                         error "stripecount=$stripecount: " \
6520                               "OST $n has fewer #0 objects vs. OST $nlast " \
6521                               "(${objs0[$n]} < ${objs0[$nlast]} x $min/$max)"; }
6522                 (( ${objs0[$n]} < ${objs0[$nlast]} * $max / $min )) ||
6523                         { $LFS df && $LFS df -i &&
6524                         error "stripecount=$stripecount: " \
6525                               "OST $n has more #0 objects vs. OST $nlast " \
6526                               "(${objs0[$n]} > ${objs0[$nlast]} x $max/$min)"; }
6527         done
6528 }
6529
6530 test_51d() {
6531         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6532         [[ $OSTCOUNT -lt 3 ]] && skip_env "needs >= 3 OSTs"
6533
6534         local stripecount
6535         local per_ost=100
6536         local nfiles=$((per_ost * OSTCOUNT))
6537         local mdts=$(comma_list $(mdts_nodes))
6538         local param="osp.*.create_count"
6539         local qos_old=$(do_facet mds1 \
6540                 "$LCTL get_param -n lod.$FSNAME-*.qos_threshold_rr" | head -n 1)
6541
6542         do_nodes $mdts \
6543                 "$LCTL set_param lod.$FSNAME-*.qos_threshold_rr=100"
6544         stack_trap "do_nodes $mdts \
6545                 '$LCTL set_param lod.$FSNAME-*.qos_threshold_rr=${qos_old%%%}'"
6546
6547         test_mkdir $DIR/$tdir
6548         local dirstripes=$(lfs getdirstripe -c $DIR/$tdir)
6549         (( dirstripes > 0 )) || dirstripes=1
6550
6551         # Ensure enough OST objects precreated for tests to pass without
6552         # running out of objects.  This is an LOV r-r OST algorithm test,
6553         # not an OST object precreation test.
6554         local old=$(do_facet mds1 "$LCTL get_param -n $param" | head -n 1)
6555         (( old >= nfiles )) ||
6556         {
6557                 local create_count=$((nfiles * OSTCOUNT / dirstripes))
6558
6559                 do_nodes $mdts "$LCTL set_param $param=$create_count"
6560                 stack_trap "do_nodes $mdts $LCTL set_param $param=$old"
6561
6562                 # trigger precreation from all MDTs for all OSTs
6563                 for ((i = 0; i < $MDSCOUNT * 2; i++ )); do
6564                         $LFS setstripe -c -1 $DIR/$tdir/wide.$i
6565                 done
6566         }
6567
6568         for ((stripecount = 3; stripecount <= $OSTCOUNT; stripecount++)); do
6569                 sleep 8  # allow object precreation to catch up
6570                 test_51d_sub $stripecount $nfiles
6571         done
6572 }
6573 run_test 51d "check LOV round-robin OST object distribution"
6574
6575 test_51e() {
6576         if [ "$mds1_FSTYPE" != ldiskfs ]; then
6577                 skip_env "ldiskfs only test"
6578         fi
6579
6580         test_mkdir -c1 $DIR/$tdir
6581         test_mkdir -c1 $DIR/$tdir/d0
6582
6583         touch $DIR/$tdir/d0/foo
6584         createmany -l $DIR/$tdir/d0/foo $DIR/$tdir/d0/f- 65001 &&
6585                 error "file exceed 65000 nlink limit!"
6586         unlinkmany $DIR/$tdir/d0/f- 65001
6587         return 0
6588 }
6589 run_test 51e "check file nlink limit"
6590
6591 test_51f() {
6592         test_mkdir $DIR/$tdir
6593
6594         local max=100000
6595         local ulimit_old=$(ulimit -n)
6596         local spare=20 # number of spare fd's for scripts/libraries, etc.
6597         local mdt=$($LFS getstripe -m $DIR/$tdir)
6598         local numfree=$($LFS df -i $DIR/$tdir | awk '/MDT:'$mdt'/ { print $4 }')
6599
6600         echo "MDT$mdt numfree=$numfree, max=$max"
6601         [[ $numfree -gt $max ]] && numfree=$max || numfree=$((numfree * 7 / 8))
6602         if [ $((numfree + spare)) -gt $ulimit_old ]; then
6603                 while ! ulimit -n $((numfree + spare)); do
6604                         numfree=$((numfree * 3 / 4))
6605                 done
6606                 echo "changed ulimit from $ulimit_old to $((numfree + spare))"
6607         else
6608                 echo "left ulimit at $ulimit_old"
6609         fi
6610
6611         createmany -o -k -t 120 $DIR/$tdir/f $numfree || {
6612                 unlinkmany $DIR/$tdir/f $numfree
6613                 error "create+open $numfree files in $DIR/$tdir failed"
6614         }
6615         ulimit -n $ulimit_old
6616
6617         # if createmany exits at 120s there will be fewer than $numfree files
6618         unlinkmany $DIR/$tdir/f $numfree || true
6619 }
6620 run_test 51f "check many open files limit"
6621
6622 test_52a() {
6623         [ -f $DIR/$tdir/foo ] && chattr -a $DIR/$tdir/foo
6624         test_mkdir $DIR/$tdir
6625         touch $DIR/$tdir/foo
6626         chattr +a $DIR/$tdir/foo || error "chattr +a failed"
6627         echo bar >> $DIR/$tdir/foo || error "append bar failed"
6628         cp /etc/hosts $DIR/$tdir/foo && error "cp worked"
6629         rm -f $DIR/$tdir/foo 2>/dev/null && error "rm worked"
6630         link $DIR/$tdir/foo $DIR/$tdir/foo_link 2>/dev/null &&
6631                                         error "link worked"
6632         echo foo >> $DIR/$tdir/foo || error "append foo failed"
6633         mrename $DIR/$tdir/foo $DIR/$tdir/foo_ren && error "rename worked"
6634         lsattr $DIR/$tdir/foo | egrep -q "^-+a[-e]+ $DIR/$tdir/foo" ||
6635                                                      error "lsattr"
6636         chattr -a $DIR/$tdir/foo || error "chattr -a failed"
6637         cp -r $DIR/$tdir $TMP/
6638         rm -fr $DIR/$tdir $TMP/$tdir || error "cleanup rm failed"
6639 }
6640 run_test 52a "append-only flag test (should return errors)"
6641
6642 test_52b() {
6643         [ -f $DIR/$tdir/foo ] && chattr -i $DIR/$tdir/foo
6644         test_mkdir $DIR/$tdir
6645         touch $DIR/$tdir/foo
6646         chattr +i $DIR/$tdir/foo || error "chattr +i failed"
6647         cat test > $DIR/$tdir/foo && error "cat test worked"
6648         cp /etc/hosts $DIR/$tdir/foo && error "cp worked"
6649         rm -f $DIR/$tdir/foo 2>/dev/null && error "rm worked"
6650         link $DIR/$tdir/foo $DIR/$tdir/foo_link 2>/dev/null &&
6651                                         error "link worked"
6652         echo foo >> $DIR/$tdir/foo && error "echo worked"
6653         mrename $DIR/$tdir/foo $DIR/$tdir/foo_ren && error "rename worked"
6654         [ -f $DIR/$tdir/foo ] || error "$tdir/foo is not a file"
6655         [ -f $DIR/$tdir/foo_ren ] && error "$tdir/foo_ren is not a file"
6656         lsattr $DIR/$tdir/foo | egrep -q "^-+i[-e]+ $DIR/$tdir/foo" ||
6657                                                         error "lsattr"
6658         chattr -i $DIR/$tdir/foo || error "chattr failed"
6659
6660         rm -fr $DIR/$tdir || error "unable to remove $DIR/$tdir"
6661 }
6662 run_test 52b "immutable flag test (should return errors) ======="
6663
6664 test_53() {
6665         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6666         remote_mds_nodsh && skip "remote MDS with nodsh"
6667         remote_ost_nodsh && skip "remote OST with nodsh"
6668
6669         local param
6670         local param_seq
6671         local ostname
6672         local mds_last
6673         local mds_last_seq
6674         local ost_last
6675         local ost_last_seq
6676         local ost_last_id
6677         local ostnum
6678         local node
6679         local found=false
6680         local support_last_seq=true
6681
6682         [[ $MDS1_VERSION -ge $(version_code 2.3.60) ]] ||
6683                 support_last_seq=false
6684
6685         # only test MDT0000
6686         local mdtosc=$(get_mdtosc_proc_path $SINGLEMDS)
6687         local value
6688         for value in $(do_facet $SINGLEMDS \
6689                        $LCTL get_param osp.$mdtosc.prealloc_last_id) ; do
6690                 param=$(echo ${value[0]} | cut -d "=" -f1)
6691                 ostname=$(echo $param | cut -d "." -f2 | cut -d - -f 1-2)
6692
6693                 if $support_last_seq; then
6694                         param_seq=$(echo $param |
6695                                 sed -e s/prealloc_last_id/prealloc_last_seq/g)
6696                         mds_last_seq=$(do_facet $SINGLEMDS \
6697                                        $LCTL get_param -n $param_seq)
6698                 fi
6699                 mds_last=$(do_facet $SINGLEMDS $LCTL get_param -n $param)
6700
6701                 ostnum=$(index_from_ostuuid ${ostname}_UUID)
6702                 node=$(facet_active_host ost$((ostnum+1)))
6703                 param="obdfilter.$ostname.last_id"
6704                 for ost_last in $(do_node $node $LCTL get_param -n $param) ; do
6705                         echo "$ostname.last_id=$ost_last; MDS.last_id=$mds_last"
6706                         ost_last_id=$ost_last
6707
6708                         if $support_last_seq; then
6709                                 ost_last_id=$(echo $ost_last |
6710                                               awk -F':' '{print $2}' |
6711                                               sed -e "s/^0x//g")
6712                                 ost_last_seq=$(echo $ost_last |
6713                                                awk -F':' '{print $1}')
6714                                 [[ $ost_last_seq = $mds_last_seq ]] || continue
6715                         fi
6716
6717                         if [[ $ost_last_id != $mds_last ]]; then
6718                                 error "$ost_last_id != $mds_last"
6719                         else
6720                                 found=true
6721                                 break
6722                         fi
6723                 done
6724         done
6725         $found || error "can not match last_seq/last_id for $mdtosc"
6726         return 0
6727 }
6728 run_test 53 "verify that MDS and OSTs agree on pre-creation ===="
6729
6730 test_54a() {
6731         $SOCKETSERVER $DIR/socket ||
6732                 error "$SOCKETSERVER $DIR/socket failed: $?"
6733         $SOCKETCLIENT $DIR/socket ||
6734                 error "$SOCKETCLIENT $DIR/socket failed: $?"
6735         unlink $DIR/socket || error "unlink $DIR/socket failed: $?"
6736 }
6737 run_test 54a "unix domain socket test"
6738
6739 test_54b() {
6740         f="$DIR/f54b"
6741         mknod $f c 1 3
6742         chmod 0666 $f
6743         dd if=/dev/zero of=$f bs=$PAGE_SIZE count=1
6744 }
6745 run_test 54b "char device works in lustre ======================"
6746
6747 find_loop_dev() {
6748         [ -b /dev/loop/0 ] && LOOPBASE=/dev/loop/
6749         [ -b /dev/loop0 ] && LOOPBASE=/dev/loop
6750         [ -z "$LOOPBASE" ] && echo "/dev/loop/0 and /dev/loop0 gone?" && return
6751
6752         for i in $(seq 3 7); do
6753                 losetup $LOOPBASE$i > /dev/null 2>&1 && continue
6754                 LOOPDEV=$LOOPBASE$i
6755                 LOOPNUM=$i
6756                 break
6757         done
6758 }
6759
6760 cleanup_54c() {
6761         local rc=0
6762         loopdev="$DIR/loop54c"
6763
6764         trap 0
6765         $UMOUNT $DIR/$tdir || rc=$?
6766         losetup -d $loopdev || true
6767         losetup -d $LOOPDEV || true
6768         rm -rf $loopdev $DIR/$tfile $DIR/$tdir
6769         return $rc
6770 }
6771
6772 test_54c() {
6773         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6774
6775         loopdev="$DIR/loop54c"
6776
6777         find_loop_dev
6778         [ -z "$LOOPNUM" ] && skip_env "couldn't find empty loop device"
6779         trap cleanup_54c EXIT
6780         mknod $loopdev b 7 $LOOPNUM
6781         echo "make a loop file system with $DIR/$tfile on $loopdev ($LOOPNUM)."
6782         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE seek=1024 count=1 > /dev/null
6783         losetup $loopdev $DIR/$tfile ||
6784                 error "can't set up $loopdev for $DIR/$tfile"
6785         mkfs.ext2 $loopdev || error "mke2fs on $loopdev"
6786         test_mkdir $DIR/$tdir
6787         mount -t ext2 $loopdev $DIR/$tdir ||
6788                 error "error mounting $loopdev on $DIR/$tdir"
6789         dd if=/dev/zero of=$DIR/$tdir/tmp bs=$PAGE_SIZE count=30 ||
6790                 error "dd write"
6791         df $DIR/$tdir
6792         dd if=$DIR/$tdir/tmp of=/dev/zero bs=$PAGE_SIZE count=30 ||
6793                 error "dd read"
6794         cleanup_54c
6795 }
6796 run_test 54c "block device works in lustre ====================="
6797
6798 test_54d() {
6799         local pipe="$DIR/$tfile.pipe"
6800         local string="aaaaaa"
6801
6802         mknod $pipe p
6803         echo -n "$string" > $pipe &
6804         local result=$(cat $pipe)
6805         [[ "$result" == "$string" ]] || error "$result != $string"
6806 }
6807 run_test 54d "fifo device works in lustre ======================"
6808
6809 test_54e() {
6810         f="$DIR/f54e"
6811         string="aaaaaa"
6812         cp -aL /dev/console $f
6813         echo $string > $f || error "echo $string to $f failed"
6814 }
6815 run_test 54e "console/tty device works in lustre ======================"
6816
6817 test_55a() {
6818         local dev_path="/sys/kernel/debug/lustre/devices"
6819
6820         load_module kunit/obd_test verbose=2 || error "load_module failed"
6821
6822         # This must be run in iteractive mode, since attach and setup
6823         # are stateful
6824         eval "$LCTL <<-EOF || error 'OBD device creation failed'
6825                 attach obd_test obd_name obd_uuid
6826                 setup obd_test
6827         EOF"
6828
6829         echo "Devices:"
6830         cat "$dev_path" | tail -n 10
6831
6832         $LCTL --device "obd_name" cleanup
6833         $LCTL --device "obd_name" detach
6834
6835         dmesg | tail -n 25 | grep "Lustre: OBD:.*FAIL" &&
6836                 error "OBD unit test failed"
6837
6838         rmmod -v obd_test ||
6839                 error "rmmod failed (may trigger a failure in a later test)"
6840 }
6841 run_test 55a "OBD device life cycle unit tests"
6842
6843 test_55b() {
6844         local dev_path="/sys/kernel/debug/lustre/devices"
6845         local dev_count="$(wc -l $dev_path | awk '{print $1}')"
6846
6847         # Set up a large number of devices, using the number
6848         # that can be set up in about a minute (based on prior
6849         # testing). We don't want to run this test forever.
6850         local num_dev_to_create="$(( 24000 - $dev_count))"
6851
6852         load_module kunit/obd_test || error "load_module failed"
6853
6854         local start=$SECONDS
6855
6856         # This must be run in iteractive mode, since attach and setup
6857         # are stateful
6858         for ((i = 1; i <= num_dev_to_create; i++)); do
6859                 echo "attach obd_test obd_name_$i obd_uuid_$i"
6860                 echo "setup obd_test_$i"
6861         done | $LCTL || error "OBD device creation failed"
6862
6863         echo "Load time: $((SECONDS - start))"
6864         echo "Devices:"
6865         cat "$dev_path" | tail -n 10
6866
6867         for ((i = 1; i <= num_dev_to_create; i++)); do
6868                 echo "--device obd_name_$i cleanup"
6869                 echo "--device obd_name_$i detach"
6870         done | $LCTL || error "OBD device cleanup failed"
6871
6872         echo "Unload time: $((SECONDS - start))"
6873
6874         rmmod -v obd_test ||
6875                 error "rmmod failed (may trigger a failure in a later test)"
6876 }
6877 run_test 55b "Load and unload max OBD devices"
6878
6879 test_55c()
6880 {
6881         load_module kunit/obd_mod_rpcs_test ||
6882                 error "load_module obd_mod_rpcs_test failed"
6883         dmesg | tail -n 25 | grep "obd_mod_rpcs_test"
6884         if [ $(dmesg | tail -n 25 | grep "Force grant RPC"| wc -l) -gt 1 ]; then
6885                 error "Force granted more than once, failing."
6886         else
6887                 echo "Force granted exactly once. Passed."
6888         fi
6889         rmmod -v obd_mod_rpcs_test ||
6890                 error "rmmod failed (may trigger a failure in a later test)"
6891 }
6892 run_test 55c "obd_mod_rpcs_test"
6893
6894 test_56a() {
6895         local numfiles=3
6896         local numdirs=2
6897         local dir=$DIR/$tdir
6898
6899         rm -rf $dir
6900         test_mkdir -p $dir/dir
6901         for i in $(seq $numfiles); do
6902                 touch $dir/file$i
6903                 touch $dir/dir/file$i
6904         done
6905
6906         local numcomp=$($LFS getstripe --component-count $dir)
6907
6908         [[ $numcomp == 0 ]] && numcomp=1
6909
6910         # test lfs getstripe with --recursive
6911         local filenum=$($LFS getstripe -r $dir | egrep -c "obdidx|l_ost_idx")
6912
6913         [[ $filenum -eq $((numfiles * 2)) ]] ||
6914                 error "$LFS getstripe -r: found $filenum != $((numfiles * 2))"
6915         filenum=$($LFS getstripe $dir | egrep -c "obdidx|l_ost_idx")
6916         [[ $filenum -eq $numfiles ]] ||
6917                 error "$LFS getstripe $dir: found $filenum, not $numfiles"
6918         echo "$LFS getstripe showed obdidx or l_ost_idx"
6919
6920         # test lfs getstripe with file instead of dir
6921         filenum=$($LFS getstripe $dir/file1 | egrep -c "obdidx|l_ost_idx")
6922         [[ $filenum -eq 1 ]] ||
6923                 error "$LFS getstripe $dir/file1: found $filenum, not 1"
6924         echo "$LFS getstripe file1 passed"
6925
6926         #test lfs getstripe with --verbose
6927         filenum=$($LFS getstripe --verbose $dir | grep -c lmm_magic)
6928         [[ $filenum -eq $((numfiles * numcomp)) ]] ||
6929                 error "$LFS getstripe --verbose $dir: "\
6930                       "got $filenum want $((numfiles * numcomp)) lmm_magic"
6931         [[ $($LFS getstripe $dir | grep -c lmm_magic) -eq 0 ]] ||
6932                 error "$LFS getstripe $dir: showed lmm_magic"
6933
6934         #test lfs getstripe with -v prints lmm_fid
6935         filenum=$($LFS getstripe -v $dir | grep -c lmm_fid)
6936         local countfids=$(((numdirs + numfiles) * numcomp))
6937         [[ $filenum -eq $countfids ]] ||
6938                 error "$LFS getstripe -v $dir: "\
6939                       "got $filenum want $countfids lmm_fid"
6940         [[ $($LFS getstripe $dir | grep -c lmm_fid) -eq 0 ]] ||
6941                 error "$LFS getstripe $dir: showed lmm_fid by default"
6942         echo "$LFS getstripe --verbose passed"
6943
6944         #check for FID information
6945         local fid1=$($LFS getstripe --fid $dir/file1)
6946         local fid2=$($LFS getstripe --verbose $dir/file1 |
6947                      awk '/lmm_fid: / { print $2; exit; }')
6948         local fid3=$($LFS path2fid $dir/file1)
6949
6950         [ "$fid1" != "$fid2" ] &&
6951                 error "getstripe --fid '$fid1' != getstripe --verbose '$fid2'"
6952         [ "$fid1" != "$fid3" ] &&
6953                 error "getstripe --fid '$fid1' != lfs path2fid '$fid3'"
6954         echo "$LFS getstripe --fid passed"
6955
6956         #test lfs getstripe with --obd
6957         $LFS getstripe --obd wrong_uuid $dir 2>&1 | grep -q "unknown obduuid" ||
6958                 error "$LFS getstripe --obd wrong_uuid: should return error"
6959
6960         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
6961
6962         local ostidx=1
6963         local obduuid=$(ostuuid_from_index $ostidx)
6964         local found=$($LFS getstripe -r --obd $obduuid $dir |
6965                 grep 'lmm_stripe_offset:' | grep -c " $ostidx\$")
6966
6967         filenum=$($LFS getstripe -ir $dir | grep -c "^$ostidx\$")
6968         [[ $($LFS getstripe -id $dir) -ne $ostidx ]] ||
6969                 ((filenum--))
6970         [[ $($LFS getstripe -id $dir/dir) -ne $ostidx ]] ||
6971                 ((filenum--))
6972
6973         [[ $found -eq $filenum ]] ||
6974                 error "$LFS getstripe --obd: found $found expect $filenum"
6975         [[ $($LFS getstripe -r -v --obd $obduuid $dir |
6976                 sed '/^[         ]*'${ostidx}'[  ]/d' |
6977                 sed -n '/^[      ]*[0-9][0-9]*[  ]/p' | wc -l) -eq 0 ]] ||
6978                 error "$LFS getstripe --obd: should not show file on other obd"
6979         echo "$LFS getstripe --obd passed"
6980 }
6981 run_test 56a "check $LFS getstripe"
6982
6983 test_56b() {
6984         local dir=$DIR/$tdir
6985         local numdirs=3
6986
6987         test_mkdir $dir
6988         for i in $(seq $numdirs); do
6989                 test_mkdir $dir/dir$i
6990         done
6991
6992         # test lfs getdirstripe default mode is non-recursion, which is
6993         # different from lfs getstripe
6994         local dircnt=$($LFS getdirstripe $dir | grep -c lmv_stripe_count)
6995
6996         [[ $dircnt -eq 1 ]] ||
6997                 error "$LFS getdirstripe: found $dircnt, not 1"
6998         dircnt=$($LFS getdirstripe --recursive $dir |
6999                 grep -c lmv_stripe_count)
7000         [[ $dircnt -eq $((numdirs + 1)) ]] ||
7001                 error "$LFS getdirstripe -r: $dircnt, != $((numdirs + 1))"
7002 }
7003 run_test 56b "check $LFS getdirstripe"
7004
7005 test_56bb() {
7006         verify_yaml_available || skip_env "YAML verification not installed"
7007         local output_file=$DIR/$tfile.out
7008
7009         $LFS getdirstripe -v -D -y $DIR 1> $output_file
7010
7011         cat $output_file
7012         verify_yaml <<<$output_file ||
7013                 error "default layout is not valid YAML"
7014
7015 # check non-default 1 stripe case
7016         test_mkdir -c 1 $DIR/$tdir
7017         $LFS getdirstripe -v -y $DIR 1> $output_file
7018         cat $output_file
7019         verify_yaml <<<$output_file || error "dir layout not valid YAML"
7020 }
7021 run_test 56bb "check $LFS getdirstripe layout is YAML"
7022
7023 test_56bc() {
7024         (( $MDSCOUNT >= 2 )) || skip "need >= 2 MDTs"
7025         verify_yaml_available || skip_env "YAML verification not installed"
7026
7027         local src_dir=$DIR/$tdir.src
7028         local yaml_file=$DIR/$tfile.yaml
7029
7030         $LFS setdirstripe -c 4 $src_dir ||
7031                 error "failed to setstripe"
7032         $LFS getdirstripe --yaml -v $src_dir > $yaml_file ||
7033                 error "failed to getdirstripe --yaml -v"
7034
7035         cat $yaml_file
7036         verify_yaml <<<$yaml_file ||
7037                 error "striped dir layout is not valid YAML"
7038
7039         local orig=$(get_dir_layout_param $src_dir)
7040         local rest=$(cat $yaml_file | parse_layout_param)
7041         [[ "$orig" == "$rest" ]] ||
7042                 error "failed to parse YAML layout"
7043 }
7044 run_test 56bc "check '$LFS getdirstripe --yaml' params are valid"
7045
7046 test_56c() {
7047         remote_ost_nodsh && skip "remote OST with nodsh"
7048
7049         local ost_idx=0
7050         local ost_name=$(ostname_from_index $ost_idx)
7051         local old_status=$(ost_dev_status $ost_idx $MOUNT -v)
7052         local inst=$(lfs getname -i $DIR)
7053         local state="osc.$ost_name-osc-$inst.statfs_state"
7054         local old_state=$($LCTL get_param -n $state)
7055         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
7056
7057         [[ "$old_status" == "$old_state" ]] ||
7058                 error "old status '$old_status' != state '$old_state'"
7059
7060         [[ -z "$old_status" || "$old_status" == "f" ]] ||
7061                 skip_env "OST $ost_name is in $old_status status"
7062
7063         local degraded="obdfilter.$ost_name.degraded"
7064         save_lustre_params ost1 $degraded > $p
7065         do_facet ost1 $LCTL set_param -n $degraded=1
7066         stack_trap "restore_lustre_params < $p; rm -f $p"
7067
7068         if (( $OST1_VERSION >= $(version_code 2.12.55) )); then
7069                 local no_precreate="obdfilter.$ost_name.no_precreate"
7070
7071                 save_lustre_params ost1 $no_precreate >> $p
7072                 do_facet ost1 $LCTL set_param -n $no_precreate=1
7073         fi
7074         if (( $OST1_VERSION >= $(version_code 2.12.57) )) &&
7075            [[ ! "$old_status" =~ "f" ]]; then
7076                 local nonrotational="osd-*.$ost_name.nonrotational"
7077
7078                 save_lustre_params ost1 $nonrotational >> $p
7079                 do_facet ost1 $LCTL set_param -n $nonrotational=1
7080         fi
7081
7082         [[ ! $($LFS df -v $MOUNT 2>&1) =~ "inactive device" ]] ||
7083                 error "$LFS df -v showing inactive devices"
7084         sleep_maxage
7085
7086         $LFS df -v $MOUNT
7087         $LCTL get_param *.*.statfs_state
7088
7089         local new_status=$(ost_dev_status $ost_idx $MOUNT -v)
7090
7091         [[ "$new_status" =~ "D" ]] ||
7092                 error "$ost_name status is '$new_status', missing 'D'"
7093         if (( $OST1_VERSION >= $(version_code 2.12.55) )) &&
7094            [[ ! "$new_status" =~ "N" ]]; then
7095                 error "$ost_name status is '$new_status', missing 'N'"
7096         fi
7097         if (( $OST1_VERSION >= $(version_code 2.12.57) )) &&
7098            [[ ! "$new_status" =~ "f" ]]; then
7099                 error "$ost_name status is '$new_status', missing 'f'"
7100         fi
7101
7102         wait_update_facet client "$LCTL get_param -n $state" "$new_status" ||
7103                 error "new state != new_status '$new_status'"
7104
7105         restore_lustre_params < $p
7106
7107         wait_update_facet client \
7108                 "$LFS df -v | awk '/$ost_name/ { print \\\$7 }'" "$old_status" ||
7109         {
7110                 new_status=$(ost_dev_status $ost_idx)
7111
7112                 error "new_status '$new_status' != old_status '$old_status'"
7113         }
7114
7115         wait_update_facet client "$LCTL get_param -n $state" "$old_state" ||
7116         {
7117                 local new_state=$($LCTL get_param -n $state)
7118
7119                 error "restored state '$new_state' != old_state '$old_state'"
7120         }
7121 }
7122 run_test 56c "check 'lfs df' showing device status"
7123
7124 test_56ca() {
7125         remote_ost_nodsh && skip "remote OST with nodsh"
7126         (( $OST1_VERSION >= $(version_code 2.16.53) )) ||
7127                 skip "Need OST1 >= 2.16.53 for this test"
7128
7129         local o_idx=0 # Target OST which will be set to readonly
7130         local ost_name=$(ostname_from_index $o_idx)
7131
7132         # Force set OST0 as readonly
7133         do_facet ost${o_idx} $LCTL set_param -n obdfilter.$ost_name.readonly=1
7134
7135         sleep_maxage # Give time for sync
7136
7137         local new_status=$(ost_dev_status $o_idx $MOUNT -v) # Get new stats
7138
7139         # revert to the normal state and wait for propagation
7140         do_facet ost${o_idx} $LCTL set_param -n obdfilter.$ost_name.readonly=0
7141         sleep_maxage
7142
7143         [[ "$new_status" =~ "R" ]] ||
7144                 error "$ost_name status is '$new_status', missing 'R'"
7145 }
7146 run_test 56ca "'lfs df -v' correctly reports 'R' flag when OST set as Readonly"
7147
7148 test_56d() {
7149         local mdts=$($LFS df -v $MOUNT | grep -c MDT)
7150         local osts=$($LFS df -v $MOUNT | grep -c OST)
7151
7152         $LFS df $MOUNT
7153
7154         (( mdts == MDSCOUNT )) ||
7155                 error "lfs df -v showed $mdts MDTs, not $MDSCOUNT"
7156         (( osts == OSTCOUNT )) ||
7157                 error "lfs df -v showed $osts OSTs, not $OSTCOUNT"
7158 }
7159 run_test 56d "'lfs df -v' prints only configured devices"
7160
7161 test_56e() {
7162         err_enoent=2 # No such file or directory
7163         err_eopnotsupp=95 # Operation not supported
7164
7165         enoent_mnt=/pmt1 # Invalid dentry. Path not present
7166         notsup_mnt=/tmp  # Valid dentry, but Not a lustreFS
7167
7168         # Check for handling of path not exists
7169         output=$($LFS df $enoent_mnt 2>&1)
7170         ret=$?
7171
7172         fs=$(echo $output | awk -F: '{print $2}' | awk '{print $3}' | tr -d \')
7173         [[ $fs = $enoent_mnt && $ret -eq $err_enoent ]] ||
7174                 error "expect failure $err_enoent, not $ret"
7175
7176         # Check for handling of non-Lustre FS
7177         output=$($LFS df $notsup_mnt)
7178         ret=$?
7179
7180         fs=$(echo $output | awk '{print $1}' | awk -F: '{print $2}')
7181         [[ $fs = $notsup_mnt && $ret -eq $err_eopnotsupp ]] ||
7182                 error "expect success $err_eopnotsupp, not $ret"
7183
7184         # Check for multiple LustreFS argument
7185         output=$($LFS df $MOUNT $MOUNT $MOUNT | grep -c "filesystem_summary:")
7186         ret=$?
7187
7188         [[ $output -eq 3 && $ret -eq 0 ]] ||
7189                 error "expect success 3, not $output, rc = $ret"
7190
7191         # Check for correct non-Lustre FS handling among multiple
7192         # LustreFS argument
7193         output=$($LFS df $MOUNT $notsup_mnt $MOUNT |
7194                 grep -c "filesystem_summary:"; exit ${PIPESTATUS[0]})
7195         ret=$?
7196
7197         [[ $output -eq 2 && $ret -eq $err_eopnotsupp ]] ||
7198                 error "expect success 2, not $output, rc = $ret"
7199 }
7200 run_test 56e "'lfs df' Handle non LustreFS & multiple LustreFS"
7201
7202 NUMFILES=3
7203 NUMDIRS=3
7204 setup_56() {
7205         local local_tdir="$1"
7206         local local_numfiles="$2"
7207         local local_numdirs="$3"
7208         local dir_params="$4"
7209         local dir_stripe_params="$5"
7210
7211         if [ ! -d "$local_tdir" ] ; then
7212                 test_mkdir -p $dir_stripe_params $local_tdir
7213                 [ "$dir_params" ] && $LFS setstripe $dir_params $local_tdir
7214                 for i in $(seq $local_numfiles) ; do
7215                         touch $local_tdir/file$i
7216                 done
7217                 for i in $(seq $local_numdirs) ; do
7218                         test_mkdir $dir_stripe_params $local_tdir/dir$i
7219                         for j in $(seq $local_numfiles) ; do
7220                                 touch $local_tdir/dir$i/file$j
7221                         done
7222                 done
7223         fi
7224 }
7225
7226 setup_56_special() {
7227         local local_tdir=$1
7228         local local_numfiles=$2
7229         local local_numdirs=$3
7230
7231         setup_56 $local_tdir $local_numfiles $local_numdirs
7232
7233         if [ ! -e "$local_tdir/loop${local_numfiles}b" ] ; then
7234                 for i in $(seq $local_numfiles) ; do
7235                         mknod $local_tdir/loop${i}b b 7 $i
7236                         mknod $local_tdir/null${i}c c 1 3
7237                         ln -s $local_tdir/file1 $local_tdir/link${i}
7238                 done
7239                 for i in $(seq $local_numdirs) ; do
7240                         mknod $local_tdir/dir$i/loop${i}b b 7 $i
7241                         mknod $local_tdir/dir$i/null${i}c c 1 3
7242                         ln -s $local_tdir/dir$i/file1 $local_tdir/dir$i/link${i}
7243                 done
7244         fi
7245 }
7246
7247 test_56g() {
7248         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7249         local expected=$(($NUMDIRS + 2))
7250
7251         setup_56 $dir $NUMFILES $NUMDIRS
7252
7253         # test lfs find with -name
7254         for i in $(seq $NUMFILES) ; do
7255                 local nums=$($LFS find -name "*$i" $dir | wc -l)
7256
7257                 [ $nums -eq $expected ] ||
7258                         error "lfs find -name '*$i' $dir wrong: "\
7259                               "found $nums, expected $expected"
7260         done
7261 }
7262 run_test 56g "check lfs find -name"
7263
7264 test_56h() {
7265         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7266         local expected=$(((NUMDIRS + 1) * (NUMFILES - 1) + NUMFILES))
7267
7268         setup_56 $dir $NUMFILES $NUMDIRS
7269
7270         # test lfs find with ! -name
7271         for i in $(seq $NUMFILES) ; do
7272                 local nums=$($LFS find ! -name "*$i" $dir | wc -l)
7273
7274                 [ $nums -eq $expected ] ||
7275                         error "lfs find ! -name '*$i' $dir wrong: "\
7276                               "found $nums, expected $expected"
7277         done
7278 }
7279 run_test 56h "check lfs find ! -name"
7280
7281 test_56i() {
7282         local dir=$DIR/$tdir
7283
7284         test_mkdir $dir
7285
7286         local cmd="$LFS find -ost $(ostuuid_from_index 0 $dir) $dir"
7287         local out=$($cmd)
7288
7289         [ -z "$out" ] || error "'$cmd' returned directory '$out'"
7290 }
7291 run_test 56i "check 'lfs find -ost UUID' skips directories"
7292
7293 test_56ib() {
7294         local dir=$DIR/$tdir
7295         local file=$dir/$tfile
7296         local idx=$((RANDOM % $OSTCOUNT))
7297         local find_file
7298         local cmd
7299
7300         test_mkdir $dir
7301         echo "create file $file on OST $idx"
7302         $LFS setstripe $file -o $idx||
7303                 error "failed to create test file $file"
7304
7305         cmd="$LFS find --ost 0,1-$idx,$idx $dir"
7306         echo "Command: $cmd"
7307         find_file=$($cmd)
7308         echo "lfs find result: $find_file"
7309         [[ "$find_file" == "$file" ]] ||
7310                 error "file $file is NOT found"
7311
7312         cmd="$LFS find ! --ost $idx-$((OSTCOUNT-1)),$idx $dir"
7313         echo "Command: $cmd"
7314         find_file=$($cmd)
7315         [[ -z "$find_file" ]]  ||
7316                 error "should NOT find any file, but find $find_file"
7317 }
7318 run_test 56ib "check 'lfs find -ost INDEX_RANGE' command"
7319
7320 test_56j() {
7321         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7322
7323         setup_56_special $dir $NUMFILES $NUMDIRS
7324
7325         local expected=$((NUMDIRS + 1))
7326         local cmd="$LFS find -type d $dir"
7327         local nums=$($cmd | wc -l)
7328
7329         [ $nums -eq $expected ] ||
7330                 error "'$cmd' wrong: found $nums, expected $expected"
7331 }
7332 run_test 56j "check lfs find -type d"
7333
7334 test_56k() {
7335         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7336
7337         setup_56_special $dir $NUMFILES $NUMDIRS
7338
7339         local expected=$(((NUMDIRS + 1) * NUMFILES))
7340         local cmd="$LFS find -type f $dir"
7341         local nums=$($cmd | wc -l)
7342
7343         [ $nums -eq $expected ] ||
7344                 error "'$cmd' wrong: found $nums, expected $expected"
7345 }
7346 run_test 56k "check lfs find -type f"
7347
7348 test_56l() {
7349         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7350
7351         setup_56_special $dir $NUMFILES $NUMDIRS
7352
7353         local expected=$((NUMDIRS + NUMFILES))
7354         local cmd="$LFS find -type b $dir"
7355         local nums=$($cmd | wc -l)
7356
7357         [ $nums -eq $expected ] ||
7358                 error "'$cmd' wrong: found $nums, expected $expected"
7359 }
7360 run_test 56l "check lfs find -type b"
7361
7362 test_56m() {
7363         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7364
7365         setup_56_special $dir $NUMFILES $NUMDIRS
7366
7367         local expected=$((NUMDIRS + NUMFILES))
7368         local cmd="$LFS find -type c $dir"
7369         local nums=$($cmd | wc -l)
7370         [ $nums -eq $expected ] ||
7371                 error "'$cmd' wrong: found $nums, expected $expected"
7372 }
7373 run_test 56m "check lfs find -type c"
7374
7375 test_56n() {
7376         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
7377         setup_56_special $dir $NUMFILES $NUMDIRS
7378
7379         local expected=$((NUMDIRS + NUMFILES))
7380         local cmd="$LFS find -type l $dir"
7381         local nums=$($cmd | wc -l)
7382
7383         [ $nums -eq $expected ] ||
7384                 error "'$cmd' wrong: found $nums, expected $expected"
7385 }
7386 run_test 56n "check lfs find -type l"
7387
7388 test_56o() {
7389         local dir=$DIR/$tdir
7390
7391         setup_56 $dir $NUMFILES $NUMDIRS
7392         utime $dir/file1 > /dev/null || error "utime (1)"
7393         utime $dir/file2 > /dev/null || error "utime (2)"
7394         utime $dir/dir1 > /dev/null || error "utime (3)"
7395         utime $dir/dir2 > /dev/null || error "utime (4)"
7396         utime $dir/dir1/file1 > /dev/null || error "utime (5)"
7397         dd if=/dev/zero count=1 >> $dir/dir1/file1 && sync
7398
7399         local expected=4
7400         local nums=$($LFS find -mtime +0 $dir | wc -l)
7401
7402         [ $nums -eq $expected ] ||
7403                 error "lfs find -mtime +0 $dir: found $nums expect $expected"
7404
7405         expected=12
7406         cmd="$LFS find -mtime 0 $dir"
7407         nums=$($cmd | wc -l)
7408         [ $nums -eq $expected ] ||
7409                 error "'$cmd' wrong: found $nums, expected $expected"
7410 }
7411 run_test 56o "check lfs find -mtime for old files"
7412
7413 test_56ob() {
7414         local dir=$DIR/$tdir
7415         local expected=1
7416         local count=0
7417
7418         # just to make sure there is something that won't be found
7419         test_mkdir $dir
7420         touch $dir/$tfile.now
7421
7422         for age in year week day hour min; do
7423                 count=$((count + 1))
7424
7425                 touch $dir/$tfile-a.$age $dir/$tfile-m.$age
7426                 touch --date="$count $age ago" -a $dir/$tfile-a.$age
7427                 touch --date="$count $age ago" -m $dir/$tfile-m.$age
7428
7429                 local cmd="$LFS find $dir -mtime $count${age:0:1}"
7430                 local nums=$($cmd | wc -l)
7431                 [ $nums -eq $expected ] ||
7432                         error "'$cmd' wrong: found $nums, expected $expected"
7433
7434                 cmd="$LFS find $dir -atime $count${age:0:1}"
7435                 nums=$($cmd | wc -l)
7436                 [ $nums -eq $expected ] ||
7437                         error "'$cmd' wrong: found $nums, expected $expected"
7438         done
7439
7440         sleep 2
7441         cmd="$LFS find $dir -ctime +1s -type f"
7442         nums=$($cmd | wc -l)
7443         (( $nums == $count * 2 + 1)) ||
7444                 error "'$cmd' wrong: found $nums, expected $((count * 2 + 1))"
7445 }
7446 run_test 56ob "check lfs find -atime -mtime -ctime with units"
7447
7448 test_newerXY_base() {
7449         local x=$1
7450         local y=$2
7451         local dir=$DIR/$tdir
7452         local ref
7453         local negref
7454
7455         stack_trap "rm -rf $DIR/$tdir $DIR/$tfile*" RETURN EXIT
7456
7457         if [ $y == "t" ]; then
7458                 if [ $x == "b" ]; then
7459                         ref=\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\"
7460                 else
7461                         ref=\"$(date +"%Y-%m-%d %H:%M:%S")\"
7462                 fi
7463         else
7464                 ref=$DIR/$tfile.newer.$x$y
7465                 touch $ref || error "touch $ref failed"
7466         fi
7467
7468         echo "before = $ref"
7469         sleep 2
7470         setup_56 $dir $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
7471         sleep 2
7472         if [ $y == "t" ]; then
7473                 if [ $x == "b" ]; then
7474                         negref=\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\"
7475                 else
7476                         negref=\"$(date +"%Y-%m-%d %H:%M:%S")\"
7477                 fi
7478         else
7479                 negref=$DIR/$tfile.negnewer.$x$y
7480                 touch $negref || error "touch $negref failed"
7481         fi
7482
7483         echo "after = $negref"
7484         local cmd="$LFS find $dir -newer$x$y $ref"
7485         local nums=$(eval $cmd | wc -l)
7486         local expected=$(((NUMFILES + 2) * NUMDIRS + 1))
7487
7488         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
7489                 error "'$cmd' wrong: found $nums newer, expected $expected"  ; }
7490
7491         cmd="$LFS find $dir ! -newer$x$y $negref"
7492         nums=$(eval $cmd | wc -l)
7493         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
7494                 error "'$cmd' wrong: found $nums older, expected $expected"  ; }
7495
7496         cmd="$LFS find $dir -newer$x$y $ref ! -newer$x$y $negref"
7497         nums=$(eval $cmd | wc -l)
7498         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
7499                 error "'$cmd' wrong: found $nums between, expected $expected"; }
7500 }
7501
7502 test_56oc() {
7503         test_newerXY_base "a" "a"
7504         test_newerXY_base "a" "m"
7505         test_newerXY_base "a" "c"
7506         test_newerXY_base "m" "a"
7507         test_newerXY_base "m" "m"
7508         test_newerXY_base "m" "c"
7509         test_newerXY_base "c" "a"
7510         test_newerXY_base "c" "m"
7511         test_newerXY_base "c" "c"
7512
7513         test_newerXY_base "a" "t"
7514         test_newerXY_base "m" "t"
7515         test_newerXY_base "c" "t"
7516
7517         (( $MDS1_VERSION >= $(version_code v2_13_53-145-g186b97e68a) &&
7518            $CLIENT_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7519                 { echo "btime needs v2_13_53-145-g186b97e68a"; return 0; }
7520
7521         test_newerXY_base "b" "b"
7522         test_newerXY_base "b" "t"
7523 }
7524 run_test 56oc "check lfs find -newerXY work"
7525
7526 test_56od() {
7527         (( $MDS1_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7528                 skip "btime unsupported on MDS < v2_13_53-145-g186b97e68a"
7529
7530         (( $CLIENT_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7531                 skip "btime unsupported on clients < v2_13_53-145-g186b97e68a"
7532
7533         local dir=$DIR/$tdir
7534         local ref=$DIR/$tfile.ref
7535         local negref=$DIR/$tfile.negref
7536
7537         mkdir $dir || error "mkdir $dir failed"
7538         touch $dir/$tfile.n1 || error "touch $dir/$tfile.n1 failed"
7539         touch $dir/$tfile.n2 || error "touch $dir/$tfile.n2 failed"
7540         mkdir $dir/$tdir.n1 || error "mkdir $dir/$tdir.n1 failed"
7541         mkdir $dir/$tdir.n2 || error "mkdir $dir/$tdir.n2 failed"
7542         touch $ref || error "touch $ref failed"
7543         # sleep 3 seconds at least
7544         sleep 3
7545
7546         local before=$(do_facet mds1 date +%s)
7547         local skew=$(($(date +%s) - before + 1))
7548
7549         if (( skew < 0 && skew > -5 )); then
7550                 sleep $((0 - skew + 1))
7551                 skew=0
7552         fi
7553
7554         # Set the dir stripe params to limit files all on MDT0,
7555         # otherwise we need to calc the max clock skew between
7556         # the client and MDTs.
7557         setup_56 $dir/d.btime $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
7558         sleep 2
7559         touch $negref || error "touch $negref failed"
7560
7561         local cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type f"
7562         local nums=$($cmd | wc -l)
7563         local expected=$(((NUMFILES + 1) * NUMDIRS))
7564
7565         [ $nums -eq $expected ] ||
7566                 error "'$cmd' wrong: found $nums, expected $expected"
7567
7568         cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type d"
7569         nums=$($cmd | wc -l)
7570         expected=$((NUMFILES + 1))
7571         [ $nums -eq $expected ] ||
7572                 error "'$cmd' wrong: found $nums, expected $expected"
7573
7574         [ $skew -lt 0 ] && return
7575
7576         local after=$(do_facet mds1 date +%s)
7577         local age=$((after - before + 1 + skew))
7578
7579         cmd="$LFS find $dir -btime -${age}s -type f"
7580         nums=$($cmd | wc -l)
7581         expected=$(((NUMFILES + 1) * NUMDIRS))
7582
7583         echo "Clock skew between client and server: $skew, age:$age"
7584         [ $nums -eq $expected ] ||
7585                 error "'$cmd' wrong: found $nums, expected $expected"
7586
7587         expected=$(($NUMDIRS + 1))
7588         cmd="$LFS find $dir -btime -${age}s -type d"
7589         nums=$($cmd | wc -l)
7590         [ $nums -eq $expected ] ||
7591                 error "'$cmd' wrong: found $nums, expected $expected"
7592         rm -f $ref $negref || error "Failed to remove $ref $negref"
7593 }
7594 run_test 56od "check lfs find -btime with units"
7595
7596 test_56oe() {
7597         local dir=$DIR/$tdir
7598         local expected=5
7599         local unit=hour
7600
7601         # just to make sure there is something that won't be found
7602         test_mkdir $dir
7603         touch $dir/$tfile.now
7604
7605         for ((val = 1; val <= 10; val++)); do
7606                 touch $dir/$tfile-a.$val $dir/$tfile-m.$val
7607                 touch $dir/$tfile-c.$val
7608                 echo -n "$tfile-c.$val  @ctime (Epoch):"
7609                 stat -c "%Z" $dir/$tfile-c.$val
7610                 touch --date="$val $unit ago" -a $dir/$tfile-a.$val
7611                 touch --date="$val $unit ago" -m $dir/$tfile-m.$val
7612                 (( val % 5 != 2 )) || sleep 10
7613         done
7614
7615         local now=$(date +%s)
7616         local lower_bound=$(( now - $(stat -c "%Z" $dir/$tfile-c.8) + 2 ))
7617         local upper_bound=$(( now - $(stat -c "%Z" $dir/$tfile-c.2) - 2 ))
7618
7619         (( now == $(date +%s))) ||
7620                 skip "System is too slow for accurate results"
7621
7622         cmd="$LFS find $dir -ctime -${upper_bound}s -ctime +${lower_bound}s"
7623         nums=$($cmd | grep -c c.*)
7624
7625         (( nums == expected )) ||
7626                 error "'$cmd' wrong: found $nums, expected $expected"
7627
7628         local cmd="$LFS find $dir -atime +7h30m -atime -2h30m"
7629         local nums=$($cmd | wc -l)
7630
7631         (( $($cmd | grep -c a.7) == 1 )) ||
7632                 error "'$cmd' didn't capture file accessed 7 hours ago"
7633         (( $($cmd | grep -c a.3) == 1 )) ||
7634                 error "'$cmd' didn't capture file accessed 3 hours ago"
7635         (( nums == expected )) ||
7636                 error "'$cmd' wrong: found $nums, expected $expected"
7637
7638         cmd="$LFS find $dir -mtime -7h30m -mtime +2h30m"
7639         nums=$($cmd | wc -l)
7640
7641         (( $($cmd | grep -c m.7) == 1 )) ||
7642                 error "'$cmd' didn't capture file modified 7 hours ago"
7643         (( $($cmd | grep -c m.3) == 1 )) ||
7644                 error "'$cmd' didn't capture file modified 3 hours ago"
7645         (( nums == expected )) ||
7646                 error "'$cmd' wrong: found $nums, expected $expected"
7647 }
7648 run_test 56oe "check lfs find with time range"
7649
7650 test_56p() {
7651         [ $RUNAS_ID -eq $UID ] &&
7652                 skip_env "RUNAS_ID = UID = $UID -- skipping"
7653
7654         local dir=$DIR/$tdir
7655
7656         setup_56 $dir $NUMFILES $NUMDIRS
7657         chown $RUNAS_ID $dir/file* || error "chown $DIR/${tdir}g/file$i failed"
7658
7659         local expected=$NUMFILES
7660         local cmd="$LFS find -uid $RUNAS_ID $dir"
7661         local nums=$($cmd | wc -l)
7662
7663         [ $nums -eq $expected ] ||
7664                 error "'$cmd' wrong: found $nums, expected $expected"
7665
7666         expected=$(((NUMFILES + 1) * NUMDIRS + 1))
7667         cmd="$LFS find ! -uid $RUNAS_ID $dir"
7668         nums=$($cmd | wc -l)
7669         [ $nums -eq $expected ] ||
7670                 error "'$cmd' wrong: found $nums, expected $expected"
7671 }
7672 run_test 56p "check lfs find -uid and ! -uid"
7673
7674 test_56q() {
7675         [ $RUNAS_ID -eq $UID ] &&
7676                 skip_env "RUNAS_ID = UID = $UID -- skipping"
7677
7678         local dir=$DIR/$tdir
7679
7680         setup_56 $dir $NUMFILES $NUMDIRS
7681         chgrp $RUNAS_GID $dir/file* || error "chown $dir/file$i failed"
7682
7683         local expected=$NUMFILES
7684         local cmd="$LFS find -gid $RUNAS_GID $dir"
7685         local nums=$($cmd | wc -l)
7686
7687         [ $nums -eq $expected ] ||
7688                 error "'$cmd' wrong: found $nums, expected $expected"
7689
7690         expected=$(( ($NUMFILES+1) * $NUMDIRS + 1))
7691         cmd="$LFS find ! -gid $RUNAS_GID $dir"
7692         nums=$($cmd | wc -l)
7693         [ $nums -eq $expected ] ||
7694                 error "'$cmd' wrong: found $nums, expected $expected"
7695 }
7696 run_test 56q "check lfs find -gid and ! -gid"
7697
7698 test_56r() {
7699         local dir=$DIR/$tdir
7700
7701         setup_56 $dir $NUMFILES $NUMDIRS
7702
7703         local expected=12
7704         local cmd="$LFS find -size 0 -type f -lazy $dir"
7705         local nums=$($cmd | wc -l)
7706
7707         [ $nums -eq $expected ] ||
7708                 error "'$cmd' wrong: found $nums, expected $expected"
7709         cmd="$LFS find -size 0 -type f $dir"
7710         nums=$($cmd | wc -l)
7711         [ $nums -eq $expected ] ||
7712                 error "'$cmd' wrong: found $nums, expected $expected"
7713
7714         expected=0
7715         cmd="$LFS find ! -size 0 -type f -lazy $dir"
7716         nums=$($cmd | wc -l)
7717         [ $nums -eq $expected ] ||
7718                 error "'$cmd' wrong: found $nums, expected $expected"
7719         cmd="$LFS find ! -size 0 -type f $dir"
7720         nums=$($cmd | wc -l)
7721         [ $nums -eq $expected ] ||
7722                 error "'$cmd' wrong: found $nums, expected $expected"
7723
7724         echo "test" > $dir/$tfile
7725         echo "test2" > $dir/$tfile.2 && sync
7726         expected=1
7727         cmd="$LFS find -size 5c -type f -lazy $dir"
7728         nums=$($cmd | wc -l)
7729         [ $nums -eq $expected ] ||
7730                 error "'$cmd' wrong: found $nums, expected $expected"
7731         cmd="$LFS find -size 5c -type f $dir"
7732         nums=$($cmd | wc -l)
7733         [ $nums -eq $expected ] ||
7734                 error "'$cmd' wrong: found $nums, expected $expected"
7735
7736         expected=1
7737         cmd="$LFS find -size +5c -type f -lazy $dir"
7738         nums=$($cmd | wc -l)
7739         [ $nums -eq $expected ] ||
7740                 error "'$cmd' wrong: found $nums, expected $expected"
7741         cmd="$LFS find -size +5c -type f $dir"
7742         nums=$($cmd | wc -l)
7743         [ $nums -eq $expected ] ||
7744                 error "'$cmd' wrong: found $nums, expected $expected"
7745
7746         expected=2
7747         cmd="$LFS find -size +0 -type f -lazy $dir"
7748         nums=$($cmd | wc -l)
7749         [ $nums -eq $expected ] ||
7750                 error "'$cmd' wrong: found $nums, expected $expected"
7751         cmd="$LFS find -size +0 -type f $dir"
7752         nums=$($cmd | wc -l)
7753         [ $nums -eq $expected ] ||
7754                 error "'$cmd' wrong: found $nums, expected $expected"
7755
7756         expected=2
7757         cmd="$LFS find ! -size -5c -type f -lazy $dir"
7758         nums=$($cmd | wc -l)
7759         [ $nums -eq $expected ] ||
7760                 error "'$cmd' wrong: found $nums, expected $expected"
7761         cmd="$LFS find ! -size -5c -type f $dir"
7762         nums=$($cmd | wc -l)
7763         [ $nums -eq $expected ] ||
7764                 error "'$cmd' wrong: found $nums, expected $expected"
7765
7766         expected=12
7767         cmd="$LFS find -size -5c -type f -lazy $dir"
7768         nums=$($cmd | wc -l)
7769         [ $nums -eq $expected ] ||
7770                 error "'$cmd' wrong: found $nums, expected $expected"
7771         cmd="$LFS find -size -5c -type f $dir"
7772         nums=$($cmd | wc -l)
7773         [ $nums -eq $expected ] ||
7774                 error "'$cmd' wrong: found $nums, expected $expected"
7775 }
7776 run_test 56r "check lfs find -size works"
7777
7778 test_56ra_sub() {
7779         local expected=$1
7780         local glimpses=$2
7781         local cmd="$3"
7782
7783         cancel_lru_locks $OSC
7784
7785         local rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
7786         local nums=$($cmd | wc -l)
7787
7788         [ $nums -eq $expected ] ||
7789                 error "'$cmd' wrong: found $nums, expected $expected"
7790
7791         local rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
7792
7793         if (( rpcs_before + glimpses != rpcs_after )); then
7794                 echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
7795                 $LCTL get_param osc.*.stats | grep ldlm_glimpse_enqueue
7796
7797                 if [[ $glimpses == 0 ]]; then
7798                         error "'$cmd' should not send glimpse RPCs to OST"
7799                 else
7800                         error "'$cmd' should send $glimpses glimpse RPCs to OST"
7801                 fi
7802         fi
7803 }
7804
7805 test_56ra() {
7806         [[ $MDS1_VERSION -gt $(version_code 2.12.58) ]] ||
7807                 skip "MDS < 2.12.58 doesn't return LSOM data"
7808         local dir=$DIR/$tdir
7809         local old_agl=$($LCTL get_param -n llite.*.statahead_agl)
7810
7811         [[ $OSC == "mdc" ]] && skip "statahead not needed for DoM files"
7812
7813         # statahead_agl may cause extra glimpse which confuses results. LU-13017
7814         $LCTL set_param -n llite.*.statahead_agl=0
7815         stack_trap "$LCTL set_param -n llite.*.statahead_agl=$old_agl"
7816
7817         setup_56 $dir $NUMFILES $NUMDIRS "-c 1"
7818         # open and close all files to ensure LSOM is updated
7819         cancel_lru_locks $OSC
7820         find $dir -type f | xargs cat > /dev/null
7821
7822         #   expect_found  glimpse_rpcs  command_to_run
7823         test_56ra_sub 12  0 "$LFS find -size 0 -type f -lazy $dir"
7824         test_56ra_sub 12 12 "$LFS find -size 0 -type f $dir"
7825         test_56ra_sub  0  0 "$LFS find ! -size 0 -type f -lazy $dir"
7826         test_56ra_sub  0 12 "$LFS find ! -size 0 -type f $dir"
7827
7828         echo "test" > $dir/$tfile
7829         echo "test2" > $dir/$tfile.2 && sync
7830         cancel_lru_locks $OSC
7831         cat $dir/$tfile $dir/$tfile.2 > /dev/null
7832
7833         test_56ra_sub  1  0 "$LFS find -size 5c -type f -lazy $dir"
7834         test_56ra_sub  1 14 "$LFS find -size 5c -type f $dir"
7835         test_56ra_sub  1  0 "$LFS find -size +5c -type f -lazy $dir"
7836         test_56ra_sub  1 14 "$LFS find -size +5c -type f $dir"
7837
7838         test_56ra_sub  2  0 "$LFS find -size +0 -type f -lazy $dir"
7839         test_56ra_sub  2 14 "$LFS find -size +0 -type f $dir"
7840         test_56ra_sub  2  0 "$LFS find ! -size -5c -type f -lazy $dir"
7841         test_56ra_sub  2 14 "$LFS find ! -size -5c -type f $dir"
7842         test_56ra_sub 12  0 "$LFS find -size -5c -type f -lazy $dir"
7843         test_56ra_sub 12 14 "$LFS find -size -5c -type f $dir"
7844 }
7845 run_test 56ra "check lfs find -size -lazy works for data on OSTs"
7846
7847 test_56rb() {
7848         local dir=$DIR/$tdir
7849         local tmp=$TMP/$tfile.log
7850         local mdt_idx;
7851
7852         test_mkdir -p $dir || error "failed to mkdir $dir"
7853         $LFS setstripe -c 1 -i 0 $dir/$tfile ||
7854                 error "failed to setstripe $dir/$tfile"
7855         mdt_idx=$($LFS getdirstripe -i $dir)
7856         dd if=/dev/zero of=$dir/$tfile bs=1M count=1
7857
7858         stack_trap "rm -f $tmp $dir/$tfile" EXIT
7859         $LFS find --size +100K --ost 0 $dir |& tee $tmp
7860         ! grep -q obd_uuid $tmp ||
7861                 error "failed to find --size +100K --ost 0 $dir"
7862         $LFS find --size +100K --mdt $mdt_idx $dir |& tee $tmp
7863         ! grep -q obd_uuid $tmp ||
7864                 error "failed to find --size +100K --mdt $mdt_idx $dir"
7865 }
7866 run_test 56rb "check lfs find --size --ost/--mdt works"
7867
7868 test_56rc() {
7869         (( MDSCOUNT >= 2 )) || skip "needs at least 2 MDTs"
7870         local dir=$DIR/$tdir
7871         local found
7872
7873         test_mkdir -c 2 -H all_char $dir || error "failed to mkdir $dir"
7874         $LFS mkdir -c 2 --mdt-hash all_char $dir/$tdir-all{1..10}
7875         (( $MDSCOUNT > 2 )) &&
7876                 $LFS mkdir -c 3 --mdt-hash fnv_1a_64 $dir/$tdir-fnv{1..10}
7877         mkdir $dir/$tdir-{1..10}
7878         touch $dir/$tfile-{1..10}
7879
7880         found=$($LFS find $dir --mdt-count 2 | wc -l)
7881         expect=11
7882         (( $found == $expect )) || error "found $found 2-stripe, expect $expect"
7883
7884         found=$($LFS find $dir -T +1 | wc -l)
7885         (( $MDSCOUNT > 2 )) && expect=$((expect + 10))
7886         (( $found == $expect )) || error "found $found 2+stripe, expect $expect"
7887
7888         found=$($LFS find $dir --mdt-hash all_char | wc -l)
7889         expect=11
7890         (( $found == $expect )) || error "found $found all_char, expect $expect"
7891
7892         found=$($LFS find $dir --mdt-hash fnv_1a_64 | wc -l)
7893         (( $MDSCOUNT > 2 )) && expect=10 || expect=0
7894         (( $found == $expect )) || error "found $found all_char, expect $expect"
7895 }
7896 run_test 56rc "check lfs find --mdt-count/--mdt-hash works"
7897
7898 test_56rd() {
7899         local dir=$DIR/$tdir
7900
7901         test_mkdir $dir
7902         rm -f $dir/*
7903
7904         mkfifo $dir/fifo || error "failed to create fifo file"
7905         $LFS find $dir -t p --printf "%p %y %LP\n" ||
7906                 error "should not fail when getting projid from pipe file"
7907         found=$($LFS find $dir -t p --printf "%y")
7908         [[ "p" == $found ]] || error "found $found, expect p"
7909
7910         mknod $dir/chardev c 1 5 ||
7911                 error "failed to create character device file"
7912         $LFS find $dir -t c --printf "%p %y %LP\n" ||
7913                 error "should not fail when getting projid from chardev file"
7914         found=$($LFS find $dir -t c --printf "%y")
7915         [[ "c" == $found ]] || error "found $found, expect c"
7916
7917         found=$($LFS find $dir ! -type d --printf "%p %y %LP\n" | wc -l)
7918         (( found == 2 )) || error "unable to list all files"
7919 }
7920 run_test 56rd "check lfs find --printf special files"
7921
7922 test_56re()
7923 {
7924         local dir=$DIR/$tdir
7925         local file=$dir/a
7926         local test_cases=(
7927                 "|%5s|" "|%05s|" "|%0s|" "|%-5s|" "|%-0s|"
7928                 "|%5G|" "|%05G|" "|%0G|" "|%-5G|" "|%-0G|"
7929                 "|%25i|" "|%025i|" "|%0i|" "|%-25i|" "|%-0i|"
7930                 "|%5k|" "|%05k|" "|%0k|" "|%-5k|" "|%-0k|"
7931                 "|%5y|" "|%05y|" "|%0y|" "|%-5y|" "|%-0y|"
7932                 "|%5m|" "|%05m|" "|%0m|" "|%-5m|" "|%-0m|" "|%-05m|"
7933                 "|%----5s|" "|%----00005s|" "|%00005s|"
7934                 "|%020|" "|%20|" "|%-20|" "|%-020|" "|%---020|" "|%---20|"
7935         )
7936
7937         test_mkdir "$dir"
7938         touch "$file"
7939         truncate -s 37 "$file"
7940
7941         for format in ${test_cases[@]}; do
7942                 local expected=$(find "$dir" -type f -printf "$format\n")
7943                 local output=$($LFS find "$dir" -type f -printf "$format\n")
7944
7945                 [[ $output == $expected ]] ||
7946                         error "Unexpected output to \"$format\", expected '$expected' got '$output'"
7947         done
7948 }
7949 run_test 56re "check lfs find -printf width format specifiers are consistant with regular find"
7950
7951 test_56rf()
7952 {
7953         local dir=$DIR/$tdir
7954         local file=$dir/a
7955         local test_cases
7956         local poolname=testpool56rf
7957         local stripe_count
7958         local fid
7959
7960         test_mkdir "$dir"
7961         pool_add $poolname || error "Could not create pool '$poolname'"
7962
7963         lfs setstripe -c 2 -S 4M -p $poolname "$file"
7964         stripe_count=$(lfs getstripe -c "$file")
7965         fid=$($LFS path2fid "$file" | sed 's/\[\(.*\)\]/\1/')
7966         len=$((${#fid} + 5))
7967
7968         test_cases=(
7969                 "|%${len}LF|" "|     $fid|"
7970                 "|%0${len}LF|" "|     $fid|"
7971                 "|%0LF|" "|$fid|"
7972                 "|%-${len}LF|" "|$fid     |"
7973                 "|%-0LF|" "|$fid|"
7974
7975                 "|%14Lp|" "|  $poolname|"
7976                 "|%014Lp|" "|  $poolname|"
7977                 "|%0Lp|" "|$poolname|"
7978                 "|%-14Lp|" "|$poolname  |"
7979                 "|%-0Lp|" "|$poolname|"
7980                 "|%07Lp|" "|$poolname|"
7981                 "|%-7Lp|" "|$poolname|"
7982
7983                 "|%4Lc|" "|   $stripe_count|"
7984                 "|%04Lc|" "|   $stripe_count|"
7985                 "|%0Lc|" "|$stripe_count|"
7986                 "|%-4Lc|" "|$stripe_count   |"
7987                 "|%-0Lc|" "|$stripe_count|"
7988
7989                 "|%10LS|" "|   4194304|"
7990                 "|%010LS|" "|   4194304|"
7991                 "|%0LS|" "|4194304|"
7992                 "|%-10LS|" "|4194304   |"
7993                 "|%-0LS|" "|4194304|"
7994         )
7995
7996         for (( i = 0; i < ${#test_cases[@]}; i += 2 )); do
7997                 local format=${test_cases[i]}
7998                 local expected=${test_cases[i + 1]}
7999                 local output=$($LFS find "$dir" -type f -printf "$format\n")
8000
8001                 [[ $output == $expected ]] ||
8002                         error "Unexpected output to \"$format\", expected '$expected' got '$output'"
8003         done
8004 }
8005 run_test 56rf "check lfs find -printf width format specifiers for lustre specific formats"
8006
8007 test_56s() { # LU-611 #LU-9369
8008         [[ $OSTCOUNT -lt 2 ]] && skip_env "need at least 2 OSTs"
8009
8010         local dir=$DIR/$tdir
8011         local onestripe=$(((NUMDIRS + 1) * NUMFILES))
8012
8013         setup_56 $dir $NUMFILES $NUMDIRS "-c 1"
8014         for i in $(seq $NUMDIRS); do
8015                 $LFS setstripe -c $((OSTCOUNT + 1)) $dir/dir$i/$tfile
8016         done
8017
8018         local expected=$NUMDIRS
8019         local cmd="$LFS find -c $OSTCOUNT $dir"
8020         local nums=$($cmd | wc -l)
8021
8022         [ $nums -eq $expected ] || {
8023                 $LFS getstripe -R $dir
8024                 error "'$cmd' wrong: found $nums, expected $expected"
8025         }
8026
8027         expected=$((NUMDIRS + onestripe))
8028         cmd="$LFS find -stripe-count +0 -type f $dir"
8029         nums=$($cmd | wc -l)
8030         [ $nums -eq $expected ] || {
8031                 $LFS getstripe -R $dir
8032                 error "'$cmd' wrong: found $nums, expected $expected"
8033         }
8034
8035         expected=$onestripe
8036         cmd="$LFS find -stripe-count 1 -type f $dir"
8037         nums=$($cmd | wc -l)
8038         [ $nums -eq $expected ] || {
8039                 $LFS getstripe -R $dir
8040                 error "'$cmd' wrong: found $nums, expected $expected"
8041         }
8042
8043         cmd="$LFS find -stripe-count -2 -type f $dir"
8044         nums=$($cmd | wc -l)
8045         [ $nums -eq $expected ] || {
8046                 $LFS getstripe -R $dir
8047                 error "'$cmd' wrong: found $nums, expected $expected"
8048         }
8049
8050         expected=0
8051         cmd="$LFS find -stripe-count $((OSTCOUNT + 1)) -type f $dir"
8052         nums=$($cmd | wc -l)
8053         [ $nums -eq $expected ] || {
8054                 $LFS getstripe -R $dir
8055                 error "'$cmd' wrong: found $nums, expected $expected"
8056         }
8057 }
8058 run_test 56s "check lfs find -stripe-count works"
8059
8060 test_56t() { # LU-611 #LU-9369
8061         local dir=$DIR/$tdir
8062
8063         setup_56 $dir 0 $NUMDIRS
8064         for i in $(seq $NUMDIRS); do
8065                 $LFS setstripe -S 8M $dir/dir$i/$tfile
8066         done
8067
8068         local expected=$NUMDIRS
8069         local cmd="$LFS find -S 8M $dir"
8070         local nums=$($cmd | wc -l)
8071
8072         [ $nums -eq $expected ] || {
8073                 $LFS getstripe -R $dir
8074                 error "'$cmd' wrong: found $nums, expected $expected"
8075         }
8076         rm -rf $dir
8077
8078         setup_56 $dir $NUMFILES $NUMDIRS "--stripe-size 512k"
8079
8080         $LFS setstripe -S 256k $dir/$tfile.{0,1,2,3}
8081
8082         expected=$(((NUMDIRS + 1) * NUMFILES))
8083         cmd="$LFS find -stripe-size 512k -type f $dir"
8084         nums=$($cmd | wc -l)
8085         [ $nums -eq $expected ] ||
8086                 error "'$cmd' wrong: found $nums, expected $expected"
8087
8088         cmd="$LFS find -stripe-size +320k -type f $dir"
8089         nums=$($cmd | wc -l)
8090         [ $nums -eq $expected ] ||
8091                 error "'$cmd' wrong: found $nums, expected $expected"
8092
8093         expected=$(((NUMDIRS + 1) * NUMFILES + 4))
8094         cmd="$LFS find -stripe-size +200k -type f $dir"
8095         nums=$($cmd | wc -l)
8096         [ $nums -eq $expected ] ||
8097                 error "'$cmd' wrong: found $nums, expected $expected"
8098
8099         cmd="$LFS find -stripe-size -640k -type f $dir"
8100         nums=$($cmd | wc -l)
8101         [ $nums -eq $expected ] ||
8102                 error "'$cmd' wrong: found $nums, expected $expected"
8103
8104         expected=4
8105         cmd="$LFS find -stripe-size 256k -type f $dir"
8106         nums=$($cmd | wc -l)
8107         [ $nums -eq $expected ] ||
8108                 error "'$cmd' wrong: found $nums, expected $expected"
8109
8110         cmd="$LFS find -stripe-size -320k -type f $dir"
8111         nums=$($cmd | wc -l)
8112         [ $nums -eq $expected ] ||
8113                 error "'$cmd' wrong: found $nums, expected $expected"
8114
8115         expected=0
8116         cmd="$LFS find -stripe-size 1024k -type f $dir"
8117         nums=$($cmd | wc -l)
8118         [ $nums -eq $expected ] ||
8119                 error "'$cmd' wrong: found $nums, expected $expected"
8120 }
8121 run_test 56t "check lfs find -stripe-size works"
8122
8123 test_56u() { # LU-611
8124         local dir=$DIR/$tdir
8125
8126         setup_56 $dir $NUMFILES $NUMDIRS "-i 0 -c 1"
8127
8128         if [[ $OSTCOUNT -gt 1 ]]; then
8129                 $LFS setstripe -i 1 -c 1 $dir/$tfile.{0,1,2,3}
8130                 onestripe=4
8131         else
8132                 onestripe=0
8133         fi
8134
8135         local expected=$(((NUMDIRS + 1) * NUMFILES))
8136         local cmd="$LFS find -stripe-index 0 -type f $dir"
8137         local nums=$($cmd | wc -l)
8138
8139         [ $nums -eq $expected ] ||
8140                 error "'$cmd' wrong: found $nums, expected $expected"
8141
8142         expected=$onestripe
8143         cmd="$LFS find -stripe-index 1 -type f $dir"
8144         nums=$($cmd | wc -l)
8145         [ $nums -eq $expected ] ||
8146                 error "'$cmd' wrong: found $nums, expected $expected"
8147
8148         cmd="$LFS find ! -stripe-index 0 -type f $dir"
8149         nums=$($cmd | wc -l)
8150         [ $nums -eq $expected ] ||
8151                 error "'$cmd' wrong: found $nums, expected $expected"
8152
8153         expected=0
8154         # This should produce an error and not return any files
8155         cmd="$LFS find -stripe-index $OSTCOUNT -type f $dir"
8156         nums=$($cmd 2>/dev/null | wc -l)
8157         [ $nums -eq $expected ] ||
8158                 error "'$cmd' wrong: found $nums, expected $expected"
8159
8160         if [[ $OSTCOUNT -gt 1 ]]; then
8161                 expected=$(((NUMDIRS + 1) * NUMFILES + onestripe))
8162                 cmd="$LFS find -stripe-index 0,1 -type f $dir"
8163                 nums=$($cmd | wc -l)
8164                 [ $nums -eq $expected ] ||
8165                         error "'$cmd' wrong: found $nums, expected $expected"
8166         fi
8167 }
8168 run_test 56u "check lfs find -stripe-index works"
8169
8170 test_56v() {
8171         local mdt_idx=0
8172         local dir=$DIR/$tdir
8173
8174         setup_56 $dir $NUMFILES $NUMDIRS
8175
8176         UUID=$(mdtuuid_from_index $mdt_idx $dir)
8177         [ -z "$UUID" ] && error "mdtuuid_from_index cannot find MDT $mdt_idx"
8178
8179         for file in $($LFS find -m $UUID $dir); do
8180                 file_midx=$($LFS getstripe -m $file)
8181                 [ $file_midx -eq $mdt_idx ] ||
8182                         error "lfs find -m $UUID != getstripe -m $file_midx"
8183         done
8184 }
8185 run_test 56v "check 'lfs find -m match with lfs getstripe -m'"
8186
8187 test_56wa() {
8188         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8189         [ $PARALLEL == "yes" ] && skip "skip parallel run"
8190
8191         local dir=$DIR/$tdir
8192
8193         setup_56 $dir $NUMFILES $NUMDIRS "-c $OSTCOUNT" "-c1"
8194         stack_trap "rm -rf $dir"
8195
8196         local stripe_size=$($LFS getstripe -S -d $dir) ||
8197                 error "$LFS getstripe -S -d $dir failed"
8198         stripe_size=${stripe_size%% *}
8199
8200         local file_size=$((stripe_size * OSTCOUNT))
8201         local file_num=$((NUMDIRS * NUMFILES + NUMFILES))
8202         local required_space=$((file_num * file_size))
8203         local free_space=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
8204                            head -n1)
8205         (( free_space >= required_space / 1024 )) ||
8206                 skip_env "need $required_space, have $free_space kbytes"
8207
8208         local dd_bs=65536
8209         local dd_count=$((file_size / dd_bs))
8210
8211         # write data into the files
8212         local i
8213         local j
8214         local file
8215
8216         for ((i = 1; i <= NUMFILES; i++ )); do
8217                 file=$dir/file$i
8218                 yes | dd bs=$dd_bs count=$dd_count of=$file &>/dev/null ||
8219                         error "write data into $file failed"
8220         done
8221         for ((i = 1; i <= NUMDIRS; i++ )); do
8222                 for ((j = 1; j <= NUMFILES; j++ )); do
8223                         file=$dir/dir$i/file$j
8224                         yes|dd bs=$dd_bs count=$dd_count of=$file &>/dev/null ||
8225                                 error "write data into $file failed"
8226                 done
8227         done
8228
8229         # $LFS_MIGRATE will fail if hard link migration is unsupported
8230         if (( MDS1_VERSION > $(version_code 2.5.55) )); then
8231                 createmany -l$dir/dir1/file1 $dir/dir1/link 200 ||
8232                         error "creating links to $dir/dir1/file1 failed"
8233         fi
8234
8235         local expected=-1
8236
8237         (( OSTCOUNT <= 1 )) || expected=$((OSTCOUNT - 1))
8238
8239         # lfs_migrate file
8240         local cmd="$LFS_MIGRATE -y -v -c $expected $dir/file1"
8241
8242         echo "$cmd"
8243         eval $cmd || error "$cmd failed"
8244
8245         check_stripe_count $dir/file1 $expected
8246
8247         if (( $MDS1_VERSION >= $(version_code 2.6.90) )); then
8248                 # lfs_migrate file onto OST 0 if it is on OST 1, or onto
8249                 # OST 1 if it is on OST 0. This file is small enough to
8250                 # be on only one stripe.
8251                 file=$dir/migr_1_ost
8252                 dd bs=$dd_bs count=1 if=/dev/urandom of=$file >/dev/null 2>&1 ||
8253                         error "write data into $file failed"
8254                 local obdidx=$($LFS getstripe -i $file)
8255                 local oldmd5=$(md5sum $file)
8256                 local newobdidx=0
8257
8258                 (( obdidx != 0 )) || newobdidx=1
8259                 cmd="$LFS migrate -i $newobdidx $file"
8260                 echo $cmd
8261                 eval $cmd || error "$cmd failed"
8262
8263                 local realobdix=$($LFS getstripe -i $file)
8264                 local newmd5=$(md5sum $file)
8265
8266                 (( $newobdidx == $realobdix )) ||
8267                         error "new OST is different (was=$obdidx, wanted=$newobdidx, got=$realobdix)"
8268                 [[ "$oldmd5" == "$newmd5" ]] ||
8269                         error "md5sum differ: $oldmd5, $newmd5"
8270         fi
8271
8272         # lfs_migrate dir
8273         cmd="$LFS_MIGRATE -y -v -c $expected $dir/dir1"
8274         echo "$cmd"
8275         eval $cmd || error "$cmd failed"
8276
8277         for (( j = 1; j <= NUMFILES; j++ )); do
8278                 check_stripe_count $dir/dir1/file$j $expected
8279         done
8280
8281         # lfs_migrate works with lfs find
8282         cmd="$LFS find -stripe_count $OSTCOUNT -type f $dir |
8283              $LFS_MIGRATE -y -v -c $expected"
8284         echo "$cmd"
8285         eval $cmd || error "$cmd failed"
8286
8287         for (( i = 2; i <= NUMFILES; i++ )); do
8288                 check_stripe_count $dir/file$i $expected
8289         done
8290         for (( i = 2; i <= NUMDIRS; i++ )); do
8291                 for (( j = 1; j <= NUMFILES; j++ )); do
8292                         check_stripe_count $dir/dir$i/file$j $expected
8293                 done
8294         done
8295 }
8296 run_test 56wa "check lfs_migrate -c stripe_count works"
8297
8298 test_56wb() {
8299         local file1=$DIR/$tdir/file1
8300         local create_pool=false
8301         local initial_pool=$($LFS getstripe -p $DIR)
8302         local pool_list=()
8303         local pool=""
8304
8305         echo -n "Creating test dir..."
8306         test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
8307         echo "done."
8308
8309         echo -n "Creating test file..."
8310         touch $file1 || error "cannot create file"
8311         echo "done."
8312
8313         echo -n "Detecting existing pools..."
8314         pool_list=($($LFS pool_list $FSNAME | grep "$FSNAME\." | cut -d. -f2))
8315
8316         if [ ${#pool_list[@]} -gt 0 ]; then
8317                 echo "${pool_list[@]}"
8318                 for thispool in "${pool_list[@]}"; do
8319                         if [[ -z "$initial_pool" ||
8320                               "$initial_pool" != "$thispool" ]]; then
8321                                 pool="$thispool"
8322                                 echo "Using existing pool '$pool'"
8323                                 break
8324                         fi
8325                 done
8326         else
8327                 echo "none detected."
8328         fi
8329         if [ -z "$pool" ]; then
8330                 pool=${POOL:-testpool}
8331                 [ "$initial_pool" = "$pool" ] && pool="testpool2"
8332                 echo -n "Creating pool '$pool'..."
8333                 create_pool=true
8334                 pool_add $pool &> /dev/null ||
8335                         error "pool_add failed"
8336                 echo "done."
8337
8338                 echo -n "Adding target to pool..."
8339                 pool_add_targets $pool 0 0 1 &> /dev/null ||
8340                         error "pool_add_targets failed"
8341                 echo "done."
8342         fi
8343
8344         echo -n "Setting pool using -p option..."
8345         $LFS_MIGRATE -y -q --no-rsync -p $pool $file1 &> /dev/null ||
8346                 error "migrate failed rc = $?"
8347         echo "done."
8348
8349         echo -n "Verifying test file is in pool after migrating..."
8350         [ "$($LFS getstripe -p $file1)" = $pool ] ||
8351                 error "file was not migrated to pool $pool"
8352         echo "done."
8353
8354         echo -n "Removing test file from pool '$pool'..."
8355         # "lfs migrate $file" won't remove the file from the pool
8356         # until some striping information is changed.
8357         $LFS migrate -c 1 $file1 &> /dev/null ||
8358                 error "cannot remove from pool"
8359         [ "$($LFS getstripe -p $file1)" ] &&
8360                 error "pool still set"
8361         echo "done."
8362
8363         echo -n "Setting pool using --pool option..."
8364         $LFS_MIGRATE -y -q --no-rsync --pool $pool $file1 &> /dev/null ||
8365                 error "migrate failed rc = $?"
8366         echo "done."
8367
8368         # Clean up
8369         rm -f $file1
8370         if $create_pool; then
8371                 destroy_test_pools 2> /dev/null ||
8372                         error "destroy test pools failed"
8373         fi
8374 }
8375 run_test 56wb "check lfs_migrate pool support"
8376
8377 test_56wc() {
8378         local file1="$DIR/$tdir/$tfile"
8379         local md5
8380         local parent_ssize
8381         local parent_scount
8382         local cur_ssize
8383         local cur_scount
8384         local orig_ssize
8385         local new_scount
8386         local cur_comp
8387
8388         echo -n "Creating test dir..."
8389         test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
8390         $LFS setstripe -S 1M -c 1 "$DIR/$tdir" &> /dev/null ||
8391                 error "cannot set stripe by '-S 1M -c 1'"
8392         echo "done"
8393
8394         echo -n "Setting initial stripe for test file..."
8395         $LFS setstripe -S 512K -c 1 "$file1" &> /dev/null ||
8396                 error "cannot set stripe"
8397         cur_ssize=$($LFS getstripe -S "$file1")
8398         (( cur_ssize == 524288 )) || error "setstripe -S $cur_ssize != 524288"
8399         echo "done."
8400
8401         dd if=/dev/urandom of=$file1 bs=1M count=12 || error "dd $file1 failed"
8402         stack_trap "rm -f $file1"
8403         md5="$(md5sum $file1)"
8404
8405         # File currently set to -S 512K -c 1
8406
8407         # Ensure -c and -S options are rejected when -R is set
8408         echo -n "Verifying incompatible options are detected..."
8409         $LFS_MIGRATE -R -c 1 "$file1" &&
8410                 error "incompatible -R and -c options not detected"
8411         $LFS_MIGRATE -R -S 1M "$file1" &&
8412                 error "incompatible -R and -S options not detected"
8413         $LFS_MIGRATE -R -p pool "$file1" &&
8414                 error "incompatible -R and -p options not detected"
8415         $LFS_MIGRATE -R -E eof -c 1 "$file1" &&
8416                 error "incompatible -R and -E options not detected"
8417         $LFS_MIGRATE -R -A "$file1" &&
8418                 error "incompatible -R and -A options not detected"
8419         $LFS_MIGRATE -A -c 1 "$file1" &&
8420                 error "incompatible -A and -c options not detected"
8421         $LFS_MIGRATE -A -S 1M "$file1" &&
8422                 error "incompatible -A and -S options not detected"
8423         $LFS_MIGRATE -A -p pool "$file1" &&
8424                 error "incompatible -A and -p options not detected"
8425         $LFS_MIGRATE -A -E eof -c 1 "$file1" &&
8426                 error "incompatible -A and -E options not detected"
8427         echo "done."
8428
8429         # Ensure unrecognized options are passed through to 'lfs migrate'
8430         echo -n "Verifying -S option is passed through to lfs migrate..."
8431         $LFS_MIGRATE -y -S 1M "$file1" || error "migration failed"
8432         cur_ssize=$($LFS getstripe -S "$file1")
8433         (( cur_ssize == 1048576 )) || error "migrate -S $cur_ssize != 1048576"
8434         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (1)"
8435         echo "done."
8436
8437         # File currently set to -S 1M -c 1
8438
8439         # Ensure long options are supported
8440         echo -n "Verifying long options supported..."
8441         $LFS_MIGRATE --non-block "$file1" ||
8442                 error "long option without argument not supported"
8443         $LFS_MIGRATE --stripe-size 512K "$file1" ||
8444                 error "long option with argument not supported"
8445         cur_ssize=$($LFS getstripe -S "$file1")
8446         (( cur_ssize == 524288 )) ||
8447                 error "migrate --stripe-size $cur_ssize != 524288"
8448         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (2)"
8449         echo "done."
8450
8451         # File currently set to -S 512K -c 1
8452
8453         if (( OSTCOUNT > 1 )); then
8454                 echo -n "Verifying explicit stripe count can be set..."
8455                 $LFS_MIGRATE -c 2 "$file1" || error "migrate failed"
8456                 cur_scount=$($LFS getstripe -c "$file1")
8457                 (( cur_scount == 2 )) || error "migrate -c $cur_scount != 2"
8458                 [[ "$(md5sum $file1)" == "$md5" ]] ||
8459                         error "file data has changed (3)"
8460                 echo "done."
8461         fi
8462
8463         # File currently set to -S 512K -c 1 or -S 512K -c 2
8464
8465         # Ensure parent striping is used if -R is set, and no stripe
8466         # count or size is specified
8467         echo -n "Setting stripe for parent directory..."
8468         $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
8469                 error "cannot set stripe '-S 2M -c 1'"
8470         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (4)"
8471         echo "done."
8472
8473         echo -n "Verifying restripe option uses parent stripe settings..."
8474         parent_ssize=$($LFS getstripe -S $DIR/$tdir 2>/dev/null)
8475         parent_scount=$($LFS getstripe -c $DIR/$tdir 2>/dev/null)
8476         $LFS_MIGRATE -R "$file1" || error "migrate failed"
8477         cur_ssize=$($LFS getstripe -S "$file1")
8478         (( cur_ssize == parent_ssize )) ||
8479                 error "migrate -R stripe_size $cur_ssize != $parent_ssize"
8480         cur_scount=$($LFS getstripe -c "$file1")
8481         (( cur_scount == parent_scount )) ||
8482                 error "migrate -R stripe_count $cur_scount != $parent_scount"
8483         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (5)"
8484         echo "done."
8485
8486         # File currently set to -S 1M -c 1
8487
8488         # Ensure striping is preserved if -R is not set, and no stripe
8489         # count or size is specified
8490         echo -n "Verifying striping size preserved when not specified..."
8491         orig_ssize=$($LFS getstripe -S "$file1" 2>/dev/null)
8492         $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
8493                 error "cannot set stripe on parent directory"
8494         $LFS_MIGRATE "$file1" || error "migrate failed"
8495         cur_ssize=$($LFS getstripe -S "$file1")
8496         (( cur_ssize == orig_ssize )) ||
8497                 error "migrate by default $cur_ssize != $orig_ssize"
8498         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (6)"
8499         echo "done."
8500
8501         # Ensure file name properly detected when final option has no argument
8502         echo -n "Verifying file name properly detected..."
8503         $LFS_MIGRATE "$file1" ||
8504                 error "file name interpreted as option argument"
8505         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (7)"
8506         echo "done."
8507
8508         # Ensure PFL arguments are passed through properly
8509         echo -n "Verifying PFL options passed through..."
8510         new_scount=$(((OSTCOUNT + 1) / 2))
8511         $LFS_MIGRATE -E 1M -c 1 -E 16M -c $new_scount -E eof -c -1 "$file1" ||
8512                 error "migrate PFL arguments failed"
8513         cur_comp=$($LFS getstripe --comp-count $file1)
8514         (( cur_comp == 3 )) || error "component count '$cur_comp' != 3"
8515         cur_scount=$($LFS getstripe --stripe-count $file1)
8516         (( cur_scount == new_scount)) ||
8517                 error "PFL stripe count $cur_scount != $new_scount"
8518         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (8)"
8519         echo "done."
8520 }
8521 run_test 56wc "check unrecognized options for lfs_migrate are passed through"
8522
8523 test_56wd() {
8524         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8525
8526         local file1=$DIR/$tdir/$tfile
8527
8528         echo -n "Creating test dir..."
8529         test_mkdir $DIR/$tdir || error "cannot create dir"
8530         echo "done."
8531
8532         echo -n "Creating test file..."
8533         echo "$tfile" > $file1
8534         echo "done."
8535
8536         # Ensure 'lfs migrate' will fail by using a non-existent option,
8537         # and make sure rsync is not called to recover
8538         echo -n "Make sure --no-rsync option works..."
8539         $LFS_MIGRATE -y --no-rsync --invalid-opt $file1 2>&1 |
8540                 grep -q 'refusing to fall back to rsync' ||
8541                 error "rsync was called with --no-rsync set"
8542         echo "done."
8543
8544         # Ensure rsync is called without trying 'lfs migrate' first
8545         echo -n "Make sure --rsync option works..."
8546         $LFS_MIGRATE -y --rsync --invalid-opt $file1 2>&1 |
8547                 grep -q 'falling back to rsync' &&
8548                 error "lfs migrate was called with --rsync set"
8549         echo "done."
8550 }
8551 run_test 56wd "check lfs_migrate --rsync and --no-rsync work"
8552
8553 test_56we() {
8554         local td=$DIR/$tdir
8555         local tf=$td/$tfile
8556
8557         test_mkdir $td || error "cannot create $td"
8558         touch $tf || error "cannot touch $tf"
8559
8560         echo -n "Make sure --non-direct|-D works..."
8561         $LFS_MIGRATE -y --non-direct -v $tf 2>&1 |
8562                 grep -q "lfs migrate --non-direct" ||
8563                 error "--non-direct option cannot work correctly"
8564         $LFS_MIGRATE -y -D -v $tf 2>&1 |
8565                 grep -q "lfs migrate -D" ||
8566                 error "-D option cannot work correctly"
8567         echo "done."
8568 }
8569 run_test 56we "check lfs_migrate --non-direct|-D support"
8570
8571 test_56x() {
8572         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8573         check_swap_layouts_support
8574
8575         local dir=$DIR/$tdir
8576         local ref1=/etc/passwd
8577         local file1=$dir/file1
8578
8579         test_mkdir $dir || error "creating dir $dir"
8580         $LFS setstripe -c 2 $file1
8581         cp $ref1 $file1
8582         $LFS migrate -c 1 $file1 || error "migrate failed rc = $?"
8583         stripe=$($LFS getstripe -c $file1)
8584         [[ $stripe == 1 ]] || error "stripe of $file1 is $stripe != 1"
8585         cmp $file1 $ref1 || error "content mismatch $file1 differs from $ref1"
8586
8587         # clean up
8588         rm -f $file1
8589 }
8590 run_test 56x "lfs migration support"
8591
8592 test_56xB() {
8593         local td=$DIR/$tdir
8594         local tf1=$td/${tfile}_1
8595         local tf2=$td/${tfile}_2
8596         local tf3=$td/${tfile}_3
8597         local flist=/tmp/flist.$$
8598
8599         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8600
8601         test_mkdir $td
8602         dd if=/dev/urandom of=$tf1 bs=1K count=1 || error "failed to create $tf1"
8603         dd if=/dev/urandom of=$tf2 bs=1K count=1 || error "failed to create $tf2"
8604         dd if=/dev/urandom of=$tf3 bs=1K count=1 || error "failed to create $tf3"
8605
8606         stack_trap "rm -f $flist"
8607
8608         $LFS find $td -type f > $flist || error "failed to generate list file"
8609         $LFS migrate -o 0 --files-from=$flist ||
8610                 error "failed to run lfs migrate with --files-from"
8611
8612         $LFS find $td -type f -print0 | $LFS migrate -o 1 --null ||
8613                 error "failed to run lfs migrate from pipe"
8614
8615         $LFS find $td -type f -print0 > $flist ||
8616                 error "failed to generate 0-ending list file"
8617         $LFS migrate -o 0 -0 --files-from=$flist ||
8618                 error "failed to run lfs migrate with -0 --files-from"
8619 }
8620 run_test 56xB "lfs migrate with -0, --null, --files-from arguments"
8621
8622 test_56xa() {
8623         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
8624         check_swap_layouts_support
8625
8626         local dir=$DIR/$tdir/$testnum
8627
8628         test_mkdir -p $dir
8629
8630         local ref1=/etc/passwd
8631         local file1=$dir/file1
8632
8633         $LFS setstripe -c 2 $file1
8634         cp $ref1 $file1
8635         $LFS migrate --block -c 1 $file1 || error "migrate failed rc = $?"
8636
8637         local stripe=$($LFS getstripe -c $file1)
8638
8639         [[ $stripe == 1 ]] || error "stripe of $file1 is $stripe != 1"
8640         cmp $file1 $ref1 || error "content mismatch $file1 differs from $ref1"
8641
8642         # clean up
8643         rm -f $file1
8644 }
8645 run_test 56xa "lfs migration --block support"
8646
8647 test_56xab() {
8648         local pid
8649         local dir=$DIR/$tdir/$testnum
8650         local file1=$dir/$tfile
8651
8652         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
8653         check_swap_layouts_support
8654
8655         test_mkdir -p $dir
8656         $LFS setstripe -c 2 $file1
8657
8658         dd if=/dev/urandom of=$file1 bs=1 oflag=sync & pid=$!
8659         kill -0 $pid ||
8660                 error "failed to start dd to write to $file1 continously"
8661         stack_trap "kill $pid"
8662         sleep 1
8663
8664         $LFS migrate --block -c 1 $file1 || error "migrate failed rc = $?"
8665
8666         ls -l $file1
8667         $LFS getstripe $file1
8668 }
8669 run_test 56xab "lfs migration --block on changing file"
8670
8671 check_migrate_links() {
8672         [[ "$1" == "--rsync" ]] && local opts="--rsync -y" && shift
8673         local dir="$1"
8674         local file1="$dir/file1"
8675         local begin="$2"
8676         local count="$3"
8677         local runas="$4"
8678         local total_count=$(($begin + $count - 1))
8679         local symlink_count=10
8680         local uniq_count=10
8681
8682         if [ ! -f "$file1" ]; then
8683                 echo -n "creating initial file..."
8684                 $LFS setstripe -c 1 -S "512k" "$file1" ||
8685                         error "cannot setstripe initial file"
8686                 echo "done"
8687
8688                 echo -n "creating symlinks..."
8689                 for s in $(seq 1 $symlink_count); do
8690                         ln -s "$file1" "$dir/slink$s" ||
8691                                 error "cannot create symlinks"
8692                 done
8693                 echo "done"
8694
8695                 echo -n "creating nonlinked files..."
8696                 createmany -o "$dir/uniq" 1 10 &> /dev/null ||
8697                         error "cannot create nonlinked files"
8698                 echo "done"
8699         fi
8700
8701         # create hard links
8702         if [ ! -f "$dir/file$total_count" ]; then
8703                 echo -n "creating hard links $begin:$total_count..."
8704                 createmany -l"$file1" "$dir/file" "$begin" "$count" &>  \
8705                         /dev/null || error "cannot create hard links"
8706                 echo "done"
8707         fi
8708
8709         echo -n "checking number of hard links listed in xattrs..."
8710         local fid=$($LFS getstripe -F "$file1")
8711         local paths=($($LFS fid2path "$MOUNT" "$fid" 2> /dev/null))
8712
8713         echo "${#paths[*]}"
8714         if [ ${#paths[*]} -lt $total_count -a "$begin" -eq 2  ]; then
8715                         skip "hard link list has unexpected size, skipping test"
8716         fi
8717         if [ ${#paths[*]} -ge $total_count -a "$begin" -ne 2  ]; then
8718                         error "link names should exceed xattrs size"
8719         fi
8720
8721         echo -n "migrating files..."
8722         local migrate_out=$($runas $LFS_MIGRATE $opts -S '1m' $dir)
8723         local rc=$?
8724         [ $rc -eq 0 ] || error "migrate failed rc = $rc"
8725         echo "done"
8726
8727         # make sure all links have been properly migrated
8728         echo -n "verifying files..."
8729         fid=$($LFS getstripe -F "$file1") ||
8730                 error "cannot get fid for file $file1"
8731         for i in $(seq 2 $total_count); do
8732                 local fid2=$($LFS getstripe -F $dir/file$i)
8733
8734                 [ "$fid2" == "$fid" ] ||
8735                         error "migrated hard link has mismatched FID"
8736         done
8737
8738         # make sure hard links were properly detected, and migration was
8739         # performed only once for the entire link set; nonlinked files should
8740         # also be migrated
8741         local actual=$(grep -c 'done' <<< "$migrate_out")
8742         local expected=$(($uniq_count + 1))
8743
8744         [ "$actual" -eq  "$expected" ] ||
8745                 error "hard links individually migrated ($actual != $expected)"
8746
8747         # make sure the correct number of hard links are present
8748         local hardlinks=$(stat -c '%h' "$file1")
8749
8750         [ $hardlinks -eq $total_count ] ||
8751                 error "num hard links $hardlinks != $total_count"
8752         echo "done"
8753
8754         return 0
8755 }
8756
8757 test_56xb() {
8758         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
8759                 skip "Need MDS version at least 2.10.55"
8760
8761         local dir="$DIR/$tdir"
8762
8763         test_mkdir "$dir" || error "cannot create dir $dir"
8764
8765         echo "testing lfs migrate mode when all links fit within xattrs"
8766         check_migrate_links "$dir" 2 99
8767
8768         echo "testing rsync mode when all links fit within xattrs"
8769         check_migrate_links --rsync "$dir" 2 99
8770
8771         echo "testing lfs migrate mode when all links do not fit within xattrs"
8772         check_migrate_links "$dir" 101 100
8773
8774         echo "testing rsync mode when all links do not fit within xattrs"
8775         check_migrate_links --rsync "$dir" 101 100
8776
8777         chown -R $RUNAS_ID $dir
8778         echo "testing non-root lfs migrate mode when not all links are in xattr"
8779         check_migrate_links "$dir" 101 100 "$RUNAS -G0"
8780
8781         # clean up
8782         rm -rf $dir
8783 }
8784 run_test 56xb "lfs migration hard link support"
8785
8786 test_56xc() {
8787         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8788
8789         local dir="$DIR/$tdir"
8790
8791         test_mkdir "$dir" || error "cannot create dir $dir"
8792
8793         # Test 1: ensure file < 1 GB is always migrated with 1 stripe
8794         echo -n "Setting initial stripe for 20MB test file..."
8795         $LFS setstripe -c 2 -i 0 "$dir/20mb" ||
8796                 error "cannot setstripe 20MB file"
8797         echo "done"
8798         echo -n "Sizing 20MB test file..."
8799         $TRUNCATE "$dir/20mb" 20971520 || error "cannot create 20MB test file"
8800         echo "done"
8801         echo -n "Verifying small file autostripe count is 1..."
8802         $LFS_MIGRATE -y -A -C 1 "$dir/20mb" ||
8803                 error "cannot migrate 20MB file"
8804         local stripe_count=$($LFS getstripe -c "$dir/20mb") ||
8805                 error "cannot get stripe for $dir/20mb"
8806         [ $stripe_count -eq 1 ] ||
8807                 error "unexpected stripe count $stripe_count for 20MB file"
8808         rm -f "$dir/20mb"
8809         echo "done"
8810
8811         # Test 2: File is small enough to fit within the available space on
8812         # sqrt(size_in_gb) + 1 OSTs but is larger than 1GB.  The file must
8813         # have at least an additional 1KB for each desired stripe for test 3
8814         echo -n "Setting stripe for 1GB test file..."
8815         $LFS setstripe -c 1 -i 0 "$dir/1gb" || error "cannot setstripe 1GB file"
8816         echo "done"
8817         echo -n "Sizing 1GB test file..."
8818         # File size is 1GB + 3KB
8819         $TRUNCATE "$dir/1gb" 1073744896 || error "cannot create 1GB test file"
8820         echo "done"
8821
8822         # need at least 512MB per OST for 1GB file to fit in 2 stripes
8823         local avail=$($LCTL get_param -n llite.$FSNAME*.kbytesavail)
8824         if (( avail > 524288 * OSTCOUNT )); then
8825                 echo -n "Migrating 1GB file..."
8826                 $LFS_MIGRATE -y -A -C 1 "$dir/1gb" ||
8827                         error "cannot migrate 1GB file"
8828                 echo "done"
8829                 echo -n "Verifying autostripe count is sqrt(n) + 1..."
8830                 stripe_count=$($LFS getstripe -c "$dir/1gb") ||
8831                         error "cannot getstripe for 1GB file"
8832                 [ $stripe_count -eq 2 ] ||
8833                         error "unexpected stripe count $stripe_count != 2"
8834                 echo "done"
8835         fi
8836
8837         # Test 3: File is too large to fit within the available space on
8838         # sqrt(n) + 1 OSTs.  Simulate limited available space with -X
8839         if [ $OSTCOUNT -ge 3 ]; then
8840                 # The required available space is calculated as
8841                 # file size (1GB + 3KB) / OST count (3).
8842                 local kb_per_ost=349526
8843
8844                 echo -n "Migrating 1GB file with limit..."
8845                 $LFS_MIGRATE -y -A -C 1 -X $kb_per_ost "$dir/1gb" ||
8846                         error "cannot migrate 1GB file with limit"
8847                 echo "done"
8848
8849                 stripe_count=$($LFS getstripe -c "$dir/1gb")
8850                 echo -n "Verifying 1GB autostripe count with limited space..."
8851                 [ "$stripe_count" -a $stripe_count -ge 3 ] ||
8852                         error "unexpected stripe count $stripe_count (min 3)"
8853                 echo "done"
8854         fi
8855
8856         # clean up
8857         rm -rf $dir
8858 }
8859 run_test 56xc "lfs migration autostripe"
8860
8861 test_56xd() {
8862         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8863
8864         local dir=$DIR/$tdir
8865         local f_mgrt=$dir/$tfile.mgrt
8866         local f_yaml=$dir/$tfile.yaml
8867         local f_copy=$dir/$tfile.copy
8868         local layout_yaml="-E 1M -S 512K -c 1 -E -1 -S 1M -c 2 -i 0"
8869         local layout_copy="-c 2 -S 2M -i 1"
8870         local yamlfile=$dir/yamlfile
8871         local layout_before;
8872         local layout_after;
8873
8874         test_mkdir "$dir" || error "cannot create dir $dir"
8875         stack_trap "rm -rf $dir"
8876         $LFS setstripe $layout_yaml $f_yaml ||
8877                 error "cannot setstripe $f_yaml with layout $layout_yaml"
8878         $LFS getstripe --yaml $f_yaml > $yamlfile
8879         $LFS setstripe $layout_copy $f_copy ||
8880                 error "cannot setstripe $f_copy with layout $layout_copy"
8881         touch $f_mgrt
8882         dd if=/dev/zero of=$f_mgrt bs=1M count=4
8883
8884         # 1. test option --yaml
8885         $LFS_MIGRATE -y --yaml $yamlfile $f_mgrt ||
8886                 error "cannot migrate $f_mgrt with --yaml $yamlfile"
8887         layout_before=$(get_layout_param $f_yaml)
8888         layout_after=$(get_layout_param $f_mgrt)
8889         [ "$layout_after" == "$layout_before" ] ||
8890                 error "lfs_migrate --yaml: $layout_after != $layout_before"
8891
8892         # 2. test option --copy
8893         $LFS_MIGRATE -y --copy $f_copy $f_mgrt ||
8894                 error "cannot migrate $f_mgrt with --copy $f_copy"
8895         layout_before=$(SKIP_INDEX=yes get_layout_param $f_copy)
8896         layout_after=$(SKIP_INDEX=yes get_layout_param $f_mgrt)
8897         [ "$layout_after" == "$layout_before" ] ||
8898                 error "lfs_migrate --copy: $layout_after != $layout_before"
8899 }
8900 run_test 56xd "check lfs_migrate --yaml and --copy support"
8901
8902 test_56xe() {
8903         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8904
8905         local dir=$DIR/$tdir
8906         local f_comp=$dir/$tfile
8907         local layout="-E 1M -S 512K -E 2M -c 2 -E 3M -c 2 -E eof -c $OSTCOUNT"
8908         local layout_before=""
8909         local layout_after=""
8910
8911         test_mkdir "$dir" || error "cannot create dir $dir"
8912         stack_trap "rm -rf $dir"
8913         $LFS setstripe $layout $f_comp ||
8914                 error "cannot setstripe $f_comp with layout $layout"
8915         layout_before=$(SKIP_INDEX=yes get_layout_param $f_comp)
8916         dd if=/dev/zero of=$f_comp bs=1M count=4
8917
8918         # 1. migrate a comp layout file by lfs_migrate
8919         $LFS_MIGRATE -y $f_comp || error "cannot migrate $f_comp by lfs_migrate"
8920         layout_after=$(SKIP_INDEX=yes get_layout_param $f_comp)
8921         idx_before=$($LFS getstripe $f_comp | awk '$2 == "0:" { print $5 }' |
8922                      tr '\n' ' ')
8923         [ "$layout_before" == "$layout_after" ] ||
8924                 error "lfs_migrate: $layout_before != $layout_after"
8925
8926         # 2. migrate a comp layout file by lfs migrate
8927         $LFS migrate $f_comp || error "cannot migrate $f_comp by lfs migrate"
8928         layout_after=$(SKIP_INDEX=yes get_layout_param $f_comp)
8929         idx_after=$($LFS getstripe $f_comp | awk '$2 == "0:" { print $5 }' |
8930                      tr '\n' ' ')
8931         [ "$layout_before" == "$layout_after" ] ||
8932                 error "lfs migrate: $layout_before != $layout_after"
8933
8934         # this may not fail every time with a broken lfs migrate, but will fail
8935         # often enough to notice, and will not have false positives very often
8936         [ "$idx_before" != "$idx_after" ] ||
8937                 error "lfs migrate: $idx_before == $idx_after"
8938 }
8939 run_test 56xe "migrate a composite layout file"
8940
8941 test_56xf() {
8942         [[ $OSTCOUNT -ge 2 ]] || skip_env "needs >= 2 OSTs"
8943
8944         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
8945                 skip "Need server version at least 2.13.53"
8946
8947         local dir=$DIR/$tdir
8948         local f_comp=$dir/$tfile
8949         local layout="-E 1M -c1 -E -1 -c2"
8950         local fid_before=""
8951         local fid_after=""
8952
8953         test_mkdir "$dir" || error "cannot create dir $dir"
8954         stack_trap "rm -rf $dir"
8955         $LFS setstripe $layout $f_comp ||
8956                 error "cannot setstripe $f_comp with layout $layout"
8957         fid_before=$($LFS getstripe --fid $f_comp)
8958         dd if=/dev/zero of=$f_comp bs=1M count=4
8959
8960         # 1. migrate a comp layout file to a comp layout
8961         $LFS migrate $f_comp || error "cannot migrate $f_comp by lfs migrate"
8962         fid_after=$($LFS getstripe --fid $f_comp)
8963         [ "$fid_before" == "$fid_after" ] ||
8964                 error "comp-to-comp migrate: $fid_before != $fid_after"
8965
8966         # 2. migrate a comp layout file to a plain layout
8967         $LFS migrate -c2 $f_comp ||
8968                 error "cannot migrate $f_comp by lfs migrate"
8969         fid_after=$($LFS getstripe --fid $f_comp)
8970         [ "$fid_before" == "$fid_after" ] ||
8971                 error "comp-to-plain migrate: $fid_before != $fid_after"
8972
8973         # 3. migrate a plain layout file to a comp layout
8974         $LFS migrate $layout $f_comp ||
8975                 error "cannot migrate $f_comp by lfs migrate"
8976         fid_after=$($LFS getstripe --fid $f_comp)
8977         [ "$fid_before" == "$fid_after" ] ||
8978                 error "plain-to-comp migrate: $fid_before != $fid_after"
8979 }
8980 run_test 56xf "FID is not lost during migration of a composite layout file"
8981
8982 check_file_ost_range() {
8983         local file="$1"
8984         shift
8985         local range="$*"
8986         local -a file_range
8987         local idx
8988
8989         file_range=($($LFS getstripe -y "$file" |
8990                 awk '/l_ost_idx:/ { print $NF }'))
8991
8992         if [[ "${#file_range[@]}" = 0 ]]; then
8993                 echo "No osts found for $file"
8994                 return 1
8995         fi
8996
8997         for idx in "${file_range[@]}"; do
8998                 [[ " $range " =~ " $idx " ]] ||
8999                         return 1
9000         done
9001
9002         return 0
9003 }
9004
9005 sub_test_56xg() {
9006         local stripe_opt="$1"
9007         local pool="$2"
9008         shift 2
9009         local pool_ostidx="$(seq $* | tr '\n' ' ')"
9010
9011         $LFS migrate $stripe_opt -p $pool $DIR/$tfile ||
9012                 error "Fail to migrate $tfile on $pool"
9013         [[ "$($LFS getstripe -p $DIR/$tfile)" = "$pool" ]] ||
9014                 error "$tfile is not in pool $pool"
9015         check_file_ost_range "$DIR/$tfile" $pool_ostidx ||
9016                 error "$tfile osts mismatch with pool $pool (osts $pool_ostidx)"
9017 }
9018
9019 test_56xg() {
9020         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
9021         [[ $OSTCOUNT -ge 2 ]] || skip "needs >= 2 OSTs"
9022         [[ $MDS1_VERSION -gt $(version_code 2.14.52) ]] ||
9023                 skip "Need MDS version newer than 2.14.52"
9024
9025         local -a pool_names=("${TESTNAME}_0" "${TESTNAME}_1" "${TESTNAME}_2")
9026         local -a pool_ranges=("0 0" "1 1" "0 1")
9027
9028         # init pools
9029         for i in "${!pool_names[@]}"; do
9030                 pool_add ${pool_names[$i]} ||
9031                         error "pool_add failed (pool: ${pool_names[$i]})"
9032                 pool_add_targets ${pool_names[$i]} ${pool_ranges[$i]} ||
9033                         error "pool_add_targets failed (pool: ${pool_names[$i]})"
9034         done
9035
9036         # init the file to migrate
9037         $LFS setstripe -c1 -i1 $DIR/$tfile ||
9038                 error "Unable to create $tfile on OST1"
9039         stack_trap "rm -f $DIR/$tfile"
9040         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=4 status=none ||
9041                 error "Unable to write on $tfile"
9042
9043         echo "1. migrate $tfile on pool ${pool_names[0]}"
9044         sub_test_56xg "-c-1" "${pool_names[0]}" ${pool_ranges[0]}
9045
9046         echo "2. migrate $tfile on pool ${pool_names[2]}"
9047         sub_test_56xg "-c-1 -S2M" "${pool_names[2]}" ${pool_ranges[2]}
9048
9049         echo "3. migrate $tfile on pool ${pool_names[1]}"
9050         sub_test_56xg "-n -c-1" "${pool_names[1]}" ${pool_ranges[1]}
9051
9052         echo "4. migrate $tfile on pool ${pool_names[2]} with default stripe parameters"
9053         sub_test_56xg "" "${pool_names[2]}" ${pool_ranges[2]}
9054         echo
9055
9056         # Clean pools
9057         destroy_test_pools ||
9058                 error "pool_destroy failed"
9059 }
9060 run_test 56xg "lfs migrate pool support"
9061
9062 test_56xh() {
9063         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
9064
9065         local size_mb=25
9066         local file1=$DIR/$tfile
9067         local tmp1=$TMP/$tfile.tmp
9068
9069         $LFS setstripe -c 2 $file1
9070
9071         stack_trap "rm -f $file1 $tmp1"
9072         dd if=/dev/urandom of=$tmp1 bs=1M count=$size_mb ||
9073                         error "error creating $tmp1"
9074         ls -lsh $tmp1
9075         cp $tmp1 $file1
9076
9077         local start=$SECONDS
9078
9079         $LFS migrate --stats --stats-interval=1 -W 1M -c 1 $file1 ||
9080                 error "migrate failed rc = $?"
9081
9082         local elapsed=$((SECONDS - start))
9083
9084         # with 1MB/s, elapsed should equal size_mb
9085         (( elapsed >= size_mb * 95 / 100 )) ||
9086                 error "'lfs migrate -W' too fast ($elapsed < 0.95 * $size_mb)?"
9087
9088         (( elapsed <= size_mb * 120 / 100 )) ||
9089                 error_not_in_vm "'lfs migrate -W' slow ($elapsed > 1.2 * $size_mb)"
9090
9091         (( elapsed <= size_mb * 350 / 100 )) ||
9092                 error "'lfs migrate -W' too slow in VM ($elapsed > 3.5 * $size_mb)"
9093
9094         stripe=$($LFS getstripe -c $file1)
9095         (( $stripe == 1 )) || error "stripe of $file1 is $stripe != 1"
9096         cmp $file1 $tmp1 || error "content mismatch $file1 differs from $tmp1"
9097
9098         # Clean up file (since it is multiple MB)
9099         rm -f $file1 $tmp1
9100 }
9101 run_test 56xh "lfs migrate bandwidth limitation support"
9102
9103 test_56xi() {
9104         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
9105         verify_yaml_available || skip_env "YAML verification not installed"
9106
9107         local size_mb=5
9108         local file1=$DIR/$tfile.1
9109         local file2=$DIR/$tfile.2
9110         local file3=$DIR/$tfile.3
9111         local output_file=$DIR/$tfile.out
9112         local tmp1=$TMP/$tfile.tmp
9113
9114         $LFS setstripe -c 2 $file1
9115         $LFS setstripe -c 2 $file2
9116         $LFS setstripe -c 2 $file3
9117
9118         stack_trap "rm -f $file1 $file2 $file3 $tmp1 $output_file"
9119         dd if=/dev/urandom of=$tmp1 bs=1M count=$size_mb ||
9120                         error "error creating $tmp1"
9121         ls -lsh $tmp1
9122         cp $tmp1 $file1
9123         cp $tmp1 $file2
9124         cp $tmp1 $file3
9125
9126         $LFS migrate --stats --stats-interval=1 \
9127                 -c 1 $file1 $file2 $file3 1> $output_file ||
9128                 error "migrate failed rc = $?"
9129
9130         cat $output_file
9131         cat $output_file | verify_yaml || error "rename_stats is not valid YAML"
9132
9133         # Clean up file (since it is multiple MB)
9134         rm -f $file1 $file2 $file3 $tmp1 $output_file
9135 }
9136 run_test 56xi "lfs migrate stats support"
9137
9138 test_56xj() { # LU-16571 "lfs migrate -b" can cause thread starvation on OSS
9139         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
9140
9141         local file=$DIR/$tfile
9142         local linkdir=$DIR/$tdir
9143
9144         test_mkdir $linkdir || error "fail to create $linkdir"
9145         $LFS setstripe -i 0 -c 1 -S1M $file
9146         stack_trap "rm -rf $file $linkdir"
9147         dd if=/dev/urandom of=$file bs=1M count=10 ||
9148                 error "fail to create $file"
9149
9150         # Create file links
9151         local cpts
9152         local threads_max
9153         local nlinks
9154
9155         thread_max=$(do_facet ost1 "$LCTL get_param -n ost.OSS.ost.threads_max")
9156         cpts=$(do_facet ost1 "$LCTL get_param -n cpu_partition_table | wc -l")
9157         (( nlinks = thread_max * 3 / 2 / cpts))
9158
9159         echo "create $nlinks hard links of $file"
9160         createmany -l $file $linkdir/link $nlinks
9161
9162         # Parallel migrates (should not block)
9163         local i
9164         for ((i = 0; i < nlinks; i++)); do
9165                 echo $linkdir/link$i
9166         done | xargs -n1 -P $nlinks $LFS migrate -c2
9167
9168         local stripe_count
9169         stripe_count=$($LFS getstripe -c $file) ||
9170                 error "fail to get stripe count on $file"
9171
9172         ((stripe_count == 2)) ||
9173                 error "fail to migrate $file (stripe_count = $stripe_count)"
9174 }
9175 run_test 56xj "lfs migrate -b should not cause starvation of threads on OSS"
9176
9177 test_56xk() {
9178         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
9179
9180         local size_mb=5
9181         local file1=$DIR/$tfile
9182
9183         stack_trap "rm -f $file1"
9184         $LFS setstripe -c 1 $file1
9185         dd if=/dev/zero of=$file1 bs=1M count=$size_mb ||
9186                 error "error creating $file1"
9187         $LFS mirror extend -N $file1 || error "can't mirror"
9188         dd if=/dev/zero of=$file1 bs=4k count=1 conv=notrunc ||
9189                 error "can't dd"
9190         $LFS getstripe $file1 | grep stale ||
9191                 error "one component must be stale"
9192
9193         local start=$SECONDS
9194         $LFS mirror resync --stats --stats-interval=1 -W 1M $file1 ||
9195                 error "migrate failed rc = $?"
9196         local elapsed=$((SECONDS - start))
9197         $LFS getstripe $file1 | grep stale &&
9198                 error "all components must be sync"
9199
9200         # with 1MB/s, elapsed should equal size_mb
9201         (( elapsed >= size_mb * 95 / 100 )) ||
9202                 error "'lfs mirror resync -W' too fast ($elapsed < 0.95 * $size_mb)?"
9203
9204         (( elapsed <= size_mb * 120 / 100 )) ||
9205                 error_not_in_vm "'lfs mirror resync -W' slow ($elapsed > 1.2 * $size_mb)"
9206
9207         (( elapsed <= size_mb * 350 / 100 )) ||
9208                 error "'lfs mirror resync -W' too slow in VM ($elapsed > 3.5 * $size_mb)"
9209 }
9210 run_test 56xk "lfs mirror resync bandwidth limitation support"
9211
9212 test_56xl() {
9213         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
9214         verify_yaml_available || skip_env "YAML verification not installed"
9215
9216         local size_mb=5
9217         local file1=$DIR/$tfile.1
9218         local output_file=$DIR/$tfile.out
9219
9220         stack_trap "rm -f $file1"
9221         $LFS setstripe -c 1 $file1
9222         dd if=/dev/zero of=$file1 bs=1M count=$size_mb ||
9223                 error "error creating $file1"
9224         $LFS mirror extend -N $file1 || error "can't mirror"
9225         dd if=/dev/zero of=$file1 bs=4k count=1 conv=notrunc ||
9226                 error "can't dd"
9227         $LFS getstripe $file1 | grep stale ||
9228                 error "one component must be stale"
9229         $LFS getstripe $file1
9230
9231         $LFS mirror resync --stats --stats-interval=1 $file1 >$output_file ||
9232                 error "resync failed rc = $?"
9233         $LFS getstripe $file1 | grep stale &&
9234                 error "all components must be sync"
9235
9236         cat $output_file
9237         cat $output_file | verify_yaml || error "stats is not valid YAML"
9238 }
9239 run_test 56xl "lfs mirror resync stats support"
9240
9241 test_56y() {
9242         [ $MDS1_VERSION -lt $(version_code 2.4.53) ] &&
9243                 skip "No HSM $(lustre_build_version $SINGLEMDS) MDS < 2.4.53"
9244
9245         local res=""
9246         local dir=$DIR/$tdir
9247         local f1=$dir/file1
9248         local f2=$dir/file2
9249
9250         test_mkdir -p $dir || error "creating dir $dir"
9251         touch $f1 || error "creating std file $f1"
9252         $MULTIOP $f2 H2c || error "creating released file $f2"
9253
9254         # a directory can be raid0, so ask only for files
9255         res=$($LFS find $dir -L raid0 -type f | wc -l)
9256         [[ $res == 2 ]] || error "search raid0: found $res files != 2"
9257
9258         res=$($LFS find $dir \! -L raid0 -type f | wc -l)
9259         [[ $res == 0 ]] || error "search !raid0: found $res files != 0"
9260
9261         # only files can be released, so no need to force file search
9262         res=$($LFS find $dir -L released)
9263         [[ $res == $f2 ]] || error "search released: found $res != $f2"
9264
9265         res=$($LFS find $dir -type f \! -L released)
9266         [[ $res == $f1 ]] || error "search !released: found $res != $f1"
9267 }
9268 run_test 56y "lfs find -L raid0|released"
9269
9270 test_56z() { # LU-4824
9271         # This checks to make sure 'lfs find' continues after errors
9272         # There are two classes of errors that should be caught:
9273         # - If multiple paths are provided, all should be searched even if one
9274         #   errors out
9275         # - If errors are encountered during the search, it should not terminate
9276         #   early
9277         local dir=$DIR/$tdir
9278         local i
9279
9280         test_mkdir $dir
9281         for i in d{0..9}; do
9282                 test_mkdir $dir/$i
9283                 touch $dir/$i/$tfile
9284         done
9285         $LFS find $DIR/non_existent_dir $dir &&
9286                 error "$LFS find did not return an error"
9287         # Make a directory unsearchable. This should NOT be the last entry in
9288         # directory order.  Arbitrarily pick the 6th entry
9289         chmod 700 $($LFS find $dir -type d | sed '6!d')
9290
9291         $RUNAS $LFS find $DIR/non_existent $dir
9292         local count=$($RUNAS $LFS find $DIR/non_existent $dir | wc -l)
9293
9294         # The user should be able to see 10 directories and 9 files
9295         (( count == 19 )) ||
9296                 error "$LFS find found $count != 19 entries after error"
9297 }
9298 run_test 56z "lfs find should continue after an error"
9299
9300 test_56aa() { # LU-5937
9301         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
9302
9303         local dir=$DIR/$tdir
9304
9305         mkdir $dir
9306         $LFS setdirstripe -c$MDSCOUNT $dir/striped_dir
9307
9308         createmany -o $dir/striped_dir/${tfile}- 1024
9309         local dirs=$($LFS find --size +8k $dir/)
9310
9311         [ -n "$dirs" ] || error "lfs find --size wrong under striped dir"
9312 }
9313 run_test 56aa "lfs find --size under striped dir"
9314
9315 test_56ab() { # LU-10705
9316         test_mkdir $DIR/$tdir
9317         dd if=/dev/urandom of=$DIR/$tdir/$tfile.1 bs=8k count=1 seek=2k
9318         dd if=/dev/urandom of=$DIR/$tdir/$tfile.2 bs=4k count=1 seek=4k
9319         dd if=/dev/urandom of=$DIR/$tdir/$tfile.3 bs=1M count=2 seek=16
9320         # Flush writes to ensure valid blocks.  Need to be more thorough for
9321         # ZFS, since blocks are not allocated/returned to client immediately.
9322         sync_all_data
9323         wait_zfs_commit ost1 2
9324         cancel_lru_locks osc
9325         ls -ls $DIR/$tdir
9326
9327         local files=$($LFS find --size +16M $DIR/$tdir | wc -l)
9328
9329         [[ $files == 3 ]] || error ">16M size files $files isn't 3 as expected"
9330
9331         files=$($LFS find --blocks +1M $DIR/$tdir | wc -l)
9332         [[ $files == 1 ]] || error ">1M blocks files $files isn't 1 as expected"
9333
9334         rm -f $DIR/$tdir/$tfile.[123]
9335 }
9336 run_test 56ab "lfs find --blocks"
9337
9338 # LU-11188
9339 test_56aca() {
9340         local dir="$DIR/$tdir"
9341         local perms=(001 002 003 004 005 006 007
9342                      010 020 030 040 050 060 070
9343                      100 200 300 400 500 600 700
9344                      111 222 333 444 555 666 777)
9345         local perm_minus=(8 8 4 8 4 4 2
9346                           8 8 4 8 4 4 2
9347                           8 8 4 8 4 4 2
9348                           4 4 2 4 2 2 1)
9349         local perm_slash=(8  8 12  8 12 12 14
9350                           8  8 12  8 12 12 14
9351                           8  8 12  8 12 12 14
9352                          16 16 24 16 24 24 28)
9353
9354         test_mkdir "$dir"
9355         for perm in ${perms[*]}; do
9356                 touch "$dir/$tfile.$perm"
9357                 chmod $perm "$dir/$tfile.$perm"
9358         done
9359
9360         for ((i = 0; i < ${#perms[*]}; i++)); do
9361                 local num=$($LFS find $dir -perm ${perms[i]} | wc -l)
9362                 (( $num == 1 )) ||
9363                         error "lfs find -perm ${perms[i]}:"\
9364                               "$num != 1"
9365
9366                 num=$($LFS find $dir -perm -${perms[i]} -type f| wc -l)
9367                 (( $num == ${perm_minus[i]} )) ||
9368                         error "lfs find -perm -${perms[i]}:"\
9369                               "$num != ${perm_minus[i]}"
9370
9371                 num=$($LFS find $dir -perm /${perms[i]} -type f| wc -l)
9372                 (( $num == ${perm_slash[i]} )) ||
9373                         error "lfs find -perm /${perms[i]}:"\
9374                               "$num != ${perm_slash[i]}"
9375         done
9376 }
9377 run_test 56aca "check lfs find -perm with octal representation"
9378
9379 test_56acb() {
9380         local dir=$DIR/$tdir
9381         # p is the permission of write and execute for user, group and other
9382         # without the umask. It is used to test +wx.
9383         local p=$(printf "%o" "$((0333 & ~$(umask)))")
9384         local perms=(1000 000 2000 4000 $p 644 111 110 100 004)
9385         local symbolic=(+t  a+t u+t g+t o+t
9386                         g+s u+s o+s +s o+sr
9387                         o=r,ug+o,u+w
9388                         u+ g+ o+ a+ ugo+
9389                         u- g- o- a- ugo-
9390                         u= g= o= a= ugo=
9391                         o=r,ug+o,u+w u=r,a+u,u+w
9392                         g=r,ugo=g,u+w u+x,+X +X
9393                         u+x,u+X u+X u+x,g+X o+r,+X
9394                         u+x,go+X +wx +rwx)
9395
9396         test_mkdir $dir
9397         for perm in ${perms[*]}; do
9398                 touch "$dir/$tfile.$perm"
9399                 chmod $perm "$dir/$tfile.$perm"
9400         done
9401
9402         for (( i = 0; i < ${#symbolic[*]}; i++ )); do
9403                 local num=$($LFS find $dir -perm ${symbolic[i]} | wc -l)
9404
9405                 (( $num == 1 )) ||
9406                         error "lfs find $dir -perm ${symbolic[i]}: $num != 1"
9407         done
9408 }
9409 run_test 56acb "check lfs find -perm with symbolic representation"
9410
9411 test_56acc() {
9412         local dir=$DIR/$tdir
9413         local tests="17777 787 789 abcd
9414                 ug=uu ug=a ug=gu uo=ou urw
9415                 u+xg+x a=r,u+x,"
9416
9417         test_mkdir $dir
9418         for err in $tests; do
9419                 if $LFS find $dir -perm $err 2>/dev/null; then
9420                         error "lfs find -perm $err: parsing should have failed"
9421                 fi
9422         done
9423 }
9424 run_test 56acc "check parsing error for lfs find -perm"
9425
9426 test_56ba() {
9427         [ $MDS1_VERSION -lt $(version_code 2.10.50) ] &&
9428                 skip "Need MDS version at least 2.10.50"
9429
9430         # Create composite files with one component
9431         local dir=$DIR/$tdir
9432
9433         setup_56 $dir/1Mfiles 5 1 "-S 1M --component-end 1M"
9434         # Create composite files with three components
9435         setup_56 $dir/2Mfiles 5 2 "-E 2M -S 1M -E 4M -E 6M"
9436         # LU-16904 Create plain layout files
9437         lfs setstripe -c 1 $dir/$tfile-{1..10}
9438
9439         local nfiles=$($LFS find --component-end 1M --type f $dir | wc -l)
9440
9441         [[ $nfiles == 10 ]] ||
9442                 error "lfs find -E 1M found $nfiles != 10 files"
9443
9444         nfiles=$($LFS find ! -E 1M --type f $dir | wc -l)
9445         [[ $nfiles == 25 ]] ||
9446                 error "lfs find ! -E 1M found $nfiles != 25 files"
9447
9448         # All files have a component that starts at 0
9449         nfiles=$($LFS find --component-start 0 --type f $dir | wc -l)
9450         [[ $nfiles == 35 ]] ||
9451                 error "lfs find --component-start 0 - $nfiles != 35 files"
9452
9453         nfiles=$($LFS find --component-start 2M --type f $dir | wc -l)
9454         [[ $nfiles == 15 ]] ||
9455                 error "lfs find --component-start 2M - $nfiles != 15 files"
9456
9457         # All files created here have a componenet that does not starts at 2M
9458         nfiles=$($LFS find ! --component-start 2M --type f $dir | wc -l)
9459         [[ $nfiles == 35 ]] ||
9460                 error "lfs find ! --component-start 2M - $nfiles != 35 files"
9461
9462         # Find files with a specified number of components
9463         local nfiles=$($LFS find --component-count 3 --type f $dir | wc -l)
9464         [[ $nfiles == 15 ]] ||
9465                 error "lfs find --component-count 3 - $nfiles != 15 files"
9466
9467         # Remember non-composite files have a component count of zero
9468         local nfiles=$($LFS find --component-count 0 --type f $dir | wc -l)
9469         [[ $nfiles == 10 ]] ||
9470                 error "lfs find --component-count 0 - $nfiles != 10 files"
9471
9472         nfiles=$($LFS find ! --component-count 3 --type f $dir | wc -l)
9473         [[ $nfiles == 20 ]] ||
9474                 error "lfs find ! --component-count 3 - $nfiles != 20 files"
9475
9476         # All files have a flag called "init"
9477         local nfiles=$($LFS find --component-flags init --type f $dir | wc -l)
9478         [[ $nfiles == 35 ]] ||
9479                 error "lfs find --component-flags init - $nfiles != 35 files"
9480
9481         # Multi-component files will have a component not initialized
9482         local nfiles=$($LFS find ! --component-flags init --type f $dir | wc -l)
9483         [[ $nfiles == 15 ]] ||
9484                 error "lfs find !--component-flags init - $nfiles != 15 files"
9485
9486         rm -rf $dir
9487
9488 }
9489 run_test 56ba "test lfs find --component-end, -start, -count, and -flags"
9490
9491 test_56ca() {
9492         [[ $MDS1_VERSION -ge $(version_code 2.10.57) ]] ||
9493                 skip "Need MDS version at least 2.10.57"
9494
9495         local td=$DIR/$tdir
9496         local tf=$td/$tfile
9497         local dir
9498         local nfiles
9499         local cmd
9500         local i
9501         local j
9502
9503         # create mirrored directories and mirrored files
9504         mkdir $td || error "mkdir $td failed"
9505         $LFS mirror create -N3 $td || error "create mirrored dir $td failed"
9506         createmany -o $tf- 10 || error "create $tf- failed"
9507
9508         for i in $(seq 2); do
9509                 dir=$td/dir$i
9510                 mkdir $dir || error "mkdir $dir failed"
9511                 $LFS mirror create -N$((3 + i)) $dir ||
9512                         error "create mirrored dir $dir failed"
9513                 createmany -o $dir/$tfile- 10 ||
9514                         error "create $dir/$tfile- failed"
9515         done
9516
9517         # change the states of some mirrored files
9518         echo foo > $tf-6
9519         for i in $(seq 2); do
9520                 dir=$td/dir$i
9521                 for j in $(seq 4 9); do
9522                         echo foo > $dir/$tfile-$j
9523                 done
9524         done
9525
9526         # find mirrored files with specific mirror count
9527         cmd="$LFS find --mirror-count 3 --type f $td"
9528         nfiles=$($cmd | wc -l)
9529         [[ $nfiles = 10 ]] || error "$cmd: $nfiles != 10 files"
9530
9531         cmd="$LFS find ! --mirror-count 3 --type f $td"
9532         nfiles=$($cmd | wc -l)
9533         [[ $nfiles = 20 ]] || error "$cmd: $nfiles != 20 files"
9534
9535         cmd="$LFS find --mirror-count +2 --type f $td"
9536         nfiles=$($cmd | wc -l)
9537         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
9538
9539         cmd="$LFS find --mirror-count -6 --type f $td"
9540         nfiles=$($cmd | wc -l)
9541         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
9542
9543         # find mirrored files with specific file state
9544         cmd="$LFS find --maxdepth 1 --mirror-state=^ro --type f $td"
9545         [[ $($cmd) = $tf-6 ]] || error "$cmd: didn't return $tf-6"
9546
9547         cmd="$LFS find --mirror-state=ro --type f $td"
9548         nfiles=$($cmd | wc -l)
9549         [[ $nfiles = 17 ]] || error "$cmd: $nfiles != 17 files"
9550
9551         cmd="$LFS find ! --mirror-state=ro --type f $td"
9552         nfiles=$($cmd | wc -l)
9553         [[ $nfiles = 13 ]] || error "$cmd: $nfiles != 13 files"
9554
9555         cmd="$LFS find --mirror-state=wp --type f $td"
9556         nfiles=$($cmd | wc -l)
9557         [[ $nfiles = 13 ]] || error "$cmd: $nfiles != 13 files"
9558
9559         cmd="$LFS find ! --mirror-state=sp --type f $td"
9560         nfiles=$($cmd | wc -l)
9561         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
9562 }
9563 run_test 56ca "check lfs find --mirror-count|-N and --mirror-state"
9564
9565 test_56da() { # LU-14179
9566         local path=$DIR/$tdir
9567
9568         test_mkdir $path
9569         cd $path
9570
9571         local longdir=$(str_repeat 'a' 255)
9572
9573         for i in {1..15}; do
9574                 path=$path/$longdir
9575                 test_mkdir $longdir
9576                 cd $longdir
9577         done
9578
9579         local len=${#path}
9580         local lastdir=$(str_repeat 'a' $((4096 - 1 - $len - 1)))
9581
9582         test_mkdir $lastdir
9583         cd $lastdir
9584         # PATH_MAX-1
9585         (( ${#PWD} == 4095 )) || error "bad PWD length ${#PWD}, expect 4095"
9586
9587         # NAME_MAX
9588         touch $(str_repeat 'f' 255)
9589
9590         $LFS find $DIR/$tdir --type d |& grep "lfs find: error" &&
9591                 error "lfs find reported an error"
9592
9593         rm -rf $DIR/$tdir
9594 }
9595 run_test 56da "test lfs find with long paths"
9596
9597 test_56db() {
9598         local mdts=$($LFS df -m | grep -c MDT)
9599         local osts=$($LFS df -m | grep -c OST)
9600
9601         $LFS df
9602
9603         (( mdts == MDSCOUNT )) ||
9604                 error "lfs df -m showed $mdts MDTs, not $MDSCOUNT"
9605         (( osts == 0 )) ||
9606                 error "lfs df -m showed $osts OSTs, not 0"
9607 }
9608 run_test 56db "test 'lfs df -m' only shows MDT devices"
9609
9610 test_56dc() {
9611         local mdts=$($LFS df -o | grep -c MDT)
9612         local osts=$($LFS df -o | grep -c OST)
9613
9614         $LFS df
9615
9616         (( osts == OSTCOUNT )) ||
9617                 error "lfs df -o showed $osts OSTs, not $OSTCOUNT"
9618         (( mdts == 0 )) ||
9619                 error "lfs df -o showed $mdts MDTs, not 0"
9620 }
9621 run_test 56dc "test 'lfs df -o' only shows OST devices"
9622
9623 test_56dd() {
9624         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
9625
9626         setup_56 $dir $NUMFILES $NUMDIRS
9627
9628         local lfscount=($($LFS find $dir -mindepth 1 -maxdepth 2 | sort))
9629         local findcount=($(find $dir -mindepth 1 -maxdepth 2 | sort))
9630
9631         if [[ ${#lfscount[@]} != ${#findcount[@]} ]]; then
9632                 error "lfs find returned ${#lfscount[@]} files, find returned ${#findcount[@]} files"
9633         fi
9634
9635         for ((i = 0; i < ${#lfscount[@]}; i++)); do
9636                 [[ "${lfscount[$i]}" == "${findcount[$i]}" ]] &&
9637                         echo "${lfscount[$i]}" ||
9638                         error "${#lfscount[@]} != ${#findcount[@]}"
9639         done
9640 }
9641 run_test 56dd "test lfs find with mindepth argument"
9642
9643 test_56ea() { #LU-10378
9644         local path=$DIR/$tdir
9645         local pool=$TESTNAME
9646
9647         # Create ost pool
9648         pool_add $pool || error "pool_add $pool failed"
9649         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
9650                 error "adding targets to $pool failed"
9651
9652         # Set default pool on directory before creating file
9653         mkdir $path || error "mkdir $path failed"
9654         $LFS setstripe -p $pool $path ||
9655                 error "set OST pool on $pool failed"
9656         touch $path/$tfile || error "touch $path/$tfile failed"
9657
9658         # Compare basic file attributes from -printf and stat
9659         local attr_printf=$($LFS find $path/$tfile -printf "%A@ %T@ %C@ %U %G %n")
9660         local attr_stat=$(stat -c "%X %Y %Z %u %g %h" $path/$tfile)
9661
9662         [[ "${attr_printf}" == "${attr_stat}" ]] ||
9663                 error "Attrs from lfs find and stat don't match"
9664
9665         # Compare Lustre attributes from lfs find and lfs getstripe
9666         local lattr_printf=$($LFS find $path/$tfile -printf "%Lc %LS %Li %Lp")
9667         local str_cnt=$($LFS getstripe --stripe-count $path/$tfile)
9668         local str_size=$($LFS getstripe --stripe-size $path/$tfile)
9669         local str_idx=$($LFS getstripe --stripe-index $path/$tfile)
9670         local fpool=$($LFS getstripe --pool $path/$tfile)
9671         local lattr_getstr="${str_cnt} ${str_size} ${str_idx} ${fpool}"
9672
9673         [[ "${lattr_printf}" == "${lattr_getstr}" ]] ||
9674                 error "Attrs from lfs find and lfs getstripe don't match"
9675
9676         # Verify behavior for unknown escape/format sequences
9677         local esc_printf=$($LFS find $path/$tfile -printf '\\ %% \Q %Q')
9678
9679         [[ "${esc_printf}" == '\ % \Q %Q' ]] ||
9680                 error "Escape/format codes don't match"
9681 }
9682 run_test 56ea "test lfs find -printf option"
9683
9684 test_56eaa() {
9685         local lfs_find=($($LFS find $DIR -printf "%i %u %g %M %p\n" | sort -n))
9686         local normal_find=($(find $DIR -printf "%i %u %g %M %p\n" | sort -n))
9687
9688         echo "comparing ${#normal_find[@]} elements starting with:"
9689         echo "lfs: ${lfs_find[0]} ${lfs_find[1]} ${lfs_find[2]} ${lfs_find[3]} ${lfs_find[4]}"
9690         echo "find: ${normal_find[0]} ${normal_find[1]} ${normal_find[2]} ${normal_find[3]} ${normal_find[4]}"
9691
9692         for ((i = 0; i < ${#normal_find[@]}; i++)); do
9693                 if [[ "${lfs_find[i]}" != "${normal_find[i]}" ]]; then
9694                         error "expected '${normal_find[i]}' but got '${lfs_find[i]}' from file ${lfs_find[$((i - (i % 5) + 4))]}"
9695                 fi
9696         done
9697 }
9698 run_test 56eaa "test lfs find -printf added functions"
9699
9700 test_56eab() {
9701         touch $DIR/$tfile
9702         local lfs_ls=($($LFS find $DIR -name $tfile -ls))
9703         local find_ls=($(find $DIR -name $tfile -ls))
9704
9705 # "-1" is last field, since dates are not printed exactly the same.
9706         for ((i = -1; i < 7; i++)); do
9707                 [[ "${lfs_ls[i]}" == "${find_ls[i]}" ]] ||
9708                         error "expected '${lfs_ls[i]}' but got '${find_ls[i]}'"
9709         done
9710 }
9711 run_test 56eab "test lfs find -ls function"
9712
9713 test_56eb() {
9714         local dir=$DIR/$tdir
9715         local subdir_1=$dir/subdir_1
9716
9717         test_mkdir -p $subdir_1
9718         ln -s subdir_1 $dir/link_1
9719
9720         $LFS getstripe $dir | grep "^$dir/link_1$" -A1 ||
9721                 error "symlink is not followed"
9722
9723         $LFS getstripe --no-follow $dir |
9724                 grep "^$dir/link_1 has no stripe info$" ||
9725                 error "symlink should not have stripe info"
9726
9727         touch $dir/testfile
9728         ln -s testfile $dir/file_link_2
9729
9730         $LFS getstripe $dir | grep "^$dir/file_link_2$" -A1 ||
9731                 error "symlink is not followed"
9732
9733         $LFS getstripe --no-follow $dir |
9734                 grep "^$dir/file_link_2 has no stripe info$" ||
9735                 error "symlink should not have stripe info"
9736 }
9737 run_test 56eb "check lfs getstripe on symlink"
9738
9739 test_56ebb() {
9740
9741         mkdir $DIR/$tdir
9742         mkfifo $DIR/$tdir/$tfile-fifo
9743         $LFS getdirstripe -r $DIR/$tdir || error "$LFS getdirstripe -r: $DIR"
9744 }
9745 run_test 56ebb "check $LFS getdirstripe for FIFO file"
9746
9747 test_56ec() {
9748         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
9749         local dir=$DIR/$tdir
9750         local srcfile=$dir/srcfile
9751         local srcyaml=$dir/srcyaml
9752         local destfile=$dir/destfile
9753
9754         test_mkdir -p $dir
9755
9756         $LFS setstripe -i 1 $srcfile
9757         $LFS getstripe --hex-idx --yaml $srcfile > $srcyaml
9758         # if the setstripe yaml parsing fails for any reason, the command can
9759         # randomly assign the correct OST index, leading to an erroneous
9760         # success. but the chance of false success is low enough that a
9761         # regression should still be quickly caught.
9762         $LFS setstripe --yaml=$srcyaml $destfile
9763
9764         local srcindex=$($LFS getstripe -i $srcfile)
9765         local destindex=$($LFS getstripe -i $destfile)
9766
9767         if [[ ! $srcindex -eq $destindex ]]; then
9768                 error "setstripe did not set OST index correctly"
9769         fi
9770 }
9771 run_test 56ec "check lfs getstripe,setstripe --hex --yaml"
9772
9773 # LU-15565
9774 test_56ed() {
9775         local new=$DIR/$tdir/$tfile-layout-new
9776         local old=$DIR/$tdir/$tfile-layout-old
9777
9778         test_mkdir $DIR/$tdir
9779
9780         cat << PFL_LAYOUT_NEW > $new
9781 lcm_layout_gen:    3
9782 lcm_mirror_count:  1
9783 lcm_entry_count:   3
9784 components:
9785   - lcme_id:             1
9786     lcme_mirror_id:      0
9787     lcme_flags:          init
9788     lcme_extent.e_start: 0
9789     lcme_extent.e_end:   1073741824
9790     sub_layout:
9791       lmm_stripe_count:  1
9792       lmm_stripe_size:   4194304
9793       lmm_pattern:       raid0
9794       lmm_layout_gen:    0
9795       lmm_stripe_offset: 0
9796       lmm_objects:
9797       - l_ost_idx: 0
9798         l_fid:     0x280000400:0x2:0x0
9799   - lcme_id:             2
9800     lcme_mirror_id:      0
9801     lcme_flags:          0
9802     lcme_extent.e_start: 1073741824
9803     lcme_extent.e_end:   4294967296
9804     sub_layout:
9805       lmm_stripe_count:  4
9806       lmm_stripe_size:   4194304
9807       lmm_pattern:       raid0
9808       lmm_layout_gen:    0
9809       lmm_stripe_offset: -1
9810   - lcme_id:             3
9811     lcme_mirror_id:      0
9812     lcme_flags:          0
9813     lcme_extent.e_start: 4294967296
9814     lcme_extent.e_end:   EOF
9815     sub_layout:
9816       lmm_stripe_count:  4
9817       lmm_stripe_size:   4194304
9818       lmm_pattern:       raid0
9819       lmm_layout_gen:    0
9820       lmm_stripe_offset: -1
9821 PFL_LAYOUT_NEW
9822
9823 # Layout changed in 2.16.0
9824         cat << PFL_LAYOUT_OLD > $old
9825   lcm_layout_gen:    3
9826   lcm_mirror_count:  1
9827   lcm_entry_count:   3
9828   component0:
9829     lcme_id:             1
9830     lcme_mirror_id:      0
9831     lcme_flags:          init
9832     lcme_extent.e_start: 0
9833     lcme_extent.e_end:   1073741824
9834     sub_layout:
9835       lmm_stripe_count:  1
9836       lmm_stripe_size:   4194304
9837       lmm_pattern:       raid0
9838       lmm_layout_gen:    0
9839       lmm_stripe_offset: 0
9840       lmm_objects:
9841       - l_ost_idx: 0
9842         l_fid:     0x280000400:0x2:0x0
9843   component1:
9844     lcme_id:             2
9845     lcme_mirror_id:      0
9846     lcme_flags:          0
9847     lcme_extent.e_start: 1073741824
9848     lcme_extent.e_end:   4294967296
9849     sub_layout:
9850       lmm_stripe_count:  4
9851       lmm_stripe_size:   4194304
9852       lmm_pattern:       raid0
9853       lmm_layout_gen:    0
9854       lmm_stripe_offset: -1
9855   component2:
9856     lcme_id:             3
9857     lcme_mirror_id:      0
9858     lcme_flags:          0
9859     lcme_extent.e_start: 4294967296
9860     lcme_extent.e_end:   EOF
9861     sub_layout:
9862       lmm_stripe_count:  4
9863       lmm_stripe_size:   4194304
9864       lmm_pattern:       raid0
9865       lmm_layout_gen:    0
9866       lmm_stripe_offset: -1
9867 PFL_LAYOUT_OLD
9868
9869         local yaml_file=$DIR/$tdir/layout.yaml
9870         local dir=$DIR/$tdir
9871         local test=$dir/$tfile.test
9872
9873         $LFS setstripe -E 4M -c 2 -E EOF -c 4 $test ||
9874                 error "failed to setstripe"
9875         $LFS getstripe --yaml $test > $yaml_file ||
9876                 error "failed to getstripe --yaml"
9877
9878         $LFS setstripe --yaml $old $dir/$tfile.new ||
9879                 error "failed to setstripe from new YAML format"
9880         # test that the old format can still be used
9881         $LFS setstripe --yaml $old $dir/$tfile.old ||
9882                 error "failed to setstripe from old YAML format"
9883
9884         local orig=$(get_layout_param $test)
9885         local rest=$(cat $yaml_file | parse_layout_param)
9886         [[ "$orig" == "$rest" ]] ||
9887                 error "failed to parse current YAML layout"
9888
9889         orig=$(get_layout_param $dir/$tfile.old)
9890         rest=$(cat $old | parse_layout_param)
9891         [[ "$orig" == "$rest" ]] ||
9892                 error "failed to parse old YAML layout"
9893
9894         orig=$(get_layout_param $dir/$tfile.new)
9895         rest=$(cat $new | parse_layout_param)
9896         [[ "$orig" == "$rest" ]] ||
9897                 error "failed to parse new YAML layout"
9898
9899 }
9900 run_test 56ed "verify new YAML format is valid and back-compatible"
9901
9902 test_56eda() {
9903         local dir=$DIR/$tdir
9904         local subdir=$dir/subdir
9905         local file1=$dir/$tfile
9906         local file2=$dir/$tfile\2
9907         local link=$dir/$tfile-link
9908         local nfiles
9909
9910         test_mkdir -p $dir
9911         $LFS setdirstripe -c1 $subdir
9912         touch $file1
9913         touch $file2
9914         ln $file2 $link
9915
9916         nfiles=$($LFS find --links 1 $dir | wc -l)
9917         (( $nfiles == 1 )) ||
9918                 error "lfs find --links expected 1 file, got $nfiles"
9919
9920         nfiles=$($LFS find --type f --links 2 $dir | wc -l)
9921         (( $nfiles == 2 )) ||
9922                 error "lfs find --links expected 2 files, got $nfiles"
9923
9924         nfiles=$($LFS find --type d --links 2 $dir | wc -l)
9925         (( $nfiles == 1 )) ||
9926                 error "lfs find --links expected 1 directory, got $nfiles"
9927 }
9928 run_test 56eda "check lfs find --links"
9929
9930 test_56edb() {
9931         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
9932
9933         local dir=$DIR/$tdir
9934         local stripedir=$dir/stripedir
9935         local nfiles
9936
9937         test_mkdir -p $dir
9938
9939         $LFS setdirstripe -c2 $stripedir
9940
9941         $LFS getdirstripe $stripedir
9942
9943         nfiles=$($LFS find --type d --links 2 $stripedir | wc -l)
9944         (( $nfiles == 1 )) ||
9945                 error "lfs find --links expected 1 directory, got $nfiles"
9946 }
9947 run_test 56edb "check lfs find --links for directory striped on multiple MDTs"
9948
9949 test_56ef() {
9950         local dir=$DIR/$tdir
9951         local dir1=$dir/d1
9952         local dir2=$dir/d2
9953         local nfiles
9954         local err_msg
9955
9956         test_mkdir -p $dir
9957
9958         mkdir $dir1
9959         mkdir $dir2
9960
9961         touch $dir1/f
9962         touch $dir2/f
9963
9964         nfiles=$($LFS find $dir1 $dir2 ! -type d | wc -l)
9965         (( $nfiles == 2 )) ||
9966                 error "(1) lfs find expected 2 files, got $nfiles"
9967
9968         nfiles=$($LFS find $dir1 $dir2 -type f | wc -l)
9969         (( $nfiles == 2 )) ||
9970                 error "(2) lfs find expected 2 files, got $nfiles"
9971
9972         nfiles=$($LFS find -type f $dir1 $dir2 | wc -l)
9973         (( $nfiles == 2 )) ||
9974                 error "(3) lfs find expected 2 files, got $nfiles"
9975
9976         err_msg=$($LFS find $dir1/typo $dir1/f 2>&1 > /dev/null)
9977         [[ $err_msg =~ "No such file or directory" ]] ||
9978                 error "expected standard error message, got: '$err_msg'"
9979 }
9980 run_test 56ef "lfs find with multiple paths"
9981
9982 test_56eg() {
9983         local dir=$DIR/$tdir
9984         local found
9985
9986         which setfattr > /dev/null 2>&1 || skip_env "no setfattr command"
9987
9988         test_mkdir -p $dir
9989
9990         touch $dir/$tfile
9991         ln -s $dir/$tfile $dir/$tfile.symlink
9992         setfattr -n "trusted.test" -v "test_target" $dir/$tfile
9993         setfattr --no-dereference -n "trusted.test" -v "test_link" \
9994                 $dir/$tfile.symlink
9995         setfattr --no-dereference -n "trusted.common" \
9996                 $dir/{$tfile,$tfile.symlink}
9997
9998         found=$($LFS find -xattr "trusted.*=test_target" \
9999                 -xattr "trusted.common" $dir)
10000         [[ "$found" == "$dir/$tfile" ]] || {
10001                 getfattr -d -m trusted.* $dir/$tfile
10002                 error "should have found '$tfile' with xattr 'trusted.test=test_target', got '$found'"
10003         }
10004
10005         found=$($LFS find -xattr "trusted.*=test_link" \
10006                 -xattr "trusted.common" $dir)
10007         [[ "$found" == "$dir/$tfile.symlink" ]] || {
10008                 getfattr --no-dereference -d -m trusted.* $dir/$tfile.symlink
10009                 error "should have found '$tfile.symlink' with xattr 'trusted.test=test_link', got '$found'"
10010         }
10011
10012         rm -f $dir/*
10013
10014         touch $dir/$tfile.1
10015         touch $dir/$tfile.2
10016         setfattr -n "user.test" -v "1" $dir/$tfile.1
10017         setfattr -n "user.test" -v "2" $dir/$tfile.2
10018         setfattr -n "user.test2" -v "common" $dir/$tfile.{1,2}
10019
10020         found=$($LFS find -xattr "user.*=common" -xattr "user.test=1" $dir)
10021         [[ "$found" == "$dir/$tfile.1" ]] || {
10022                 getfattr -d $dir/$tfile.1
10023                 error "should have found '$tfile.1' with xattr user.test=1', got '$found'"
10024         }
10025
10026         found=$($LFS find -xattr "user.*=common" ! -xattr "user.test=1" $dir)
10027         [[ "$found" == "$dir/$tfile.2" ]] || {
10028                 getfattr -d $dir/$tfile.2
10029                 error "should have found '$tfile.2' without xattr 'user.test=1', got '$found'"
10030         }
10031
10032         setfattr -n "user.empty" $dir/$tfile.1
10033         found=$($LFS find -xattr "user.empty" $dir)
10034         [[ "$found" == "$dir/$tfile.1" ]] || {
10035                 getfattr -d $dir/$tfile.1
10036                 error "should have found '$tfile.1' with xattr 'user.empty=', got '$found'"
10037         }
10038
10039         # setfattr command normally does not store terminating null byte
10040         # when writing a string as an xattr value.
10041         #
10042         # In order to test matching a value string that includes a terminating
10043         # null, explicitly encode the string "test\0" with the null terminator.
10044         setfattr -n "user.test" -v "0x7465737400" $dir/$tfile.1
10045         found=$($LFS find -xattr "user.test=test" $dir)
10046         [[ "$found" == "$dir/$tfile.1" ]] || {
10047                 getfattr -d --encoding=hex $dir/$tfile.1
10048                 error "should have found '$tfile.1' with xattr 'user.test=0x7465737400', got '$found'"
10049         }
10050 }
10051 run_test 56eg "lfs find -xattr"
10052
10053 test_56eh() {
10054         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
10055
10056         setup_56_special $dir $NUMFILES $NUMDIRS
10057
10058         local cmd="$LFS find $dir"
10059         local total=$($cmd | wc -l)
10060         local n=1
10061
10062         local nums
10063
10064         echo "Running tests on $dir, with $total total results."
10065
10066         while (( $n < 100 )); do
10067                 nums=$($LFS find --skip=$((100 - $n)) $dir | wc -l)
10068                 (( $nums <= $(($total * ($n + 5) / 100)) &&
10069                    $nums >= $(($total * ($n - 5) / 100)) )) ||
10070                         error "--skip=$((100 - $n)): expected $(($total * $n / 100)) results with 5% error margin, got $nums"
10071                 (( n++ ))
10072         done
10073 }
10074 run_test 56eh "check lfs find --skip"
10075
10076 test_56ei() {
10077         (( $MDS1_VERSION >= $(version_code 2.15.64.110) )) ||
10078                 skip "need MDS >= v2_15_64-110-g501e5b2c8a for special projid"
10079         local path=$DIR/$tdir
10080         local projid=1234
10081         local expected_count=3
10082
10083         # Create test dir containing:
10084         # - regular file, with default projid
10085         # - regular file, with unique projid
10086         # - symbolic link, with unique projid
10087         # - special char dev file, with unique projid
10088         test_mkdir $path || error "mkdir $path failed"
10089         touch $path/file0 $path/file$projid || error "touch failed"
10090         ln -s $path/file$projid $path/link$projid
10091         mknod $path/char$projid c 1 3
10092         $LFS project -p $projid -s $path/file$projid
10093         $LFS project -p $projid -s $path/link$projid
10094         $LFS project -p $projid -s $path/char$projid
10095         stack_trap "rm -rf $path" EXIT
10096
10097         $LFS project -r $path/
10098         echo -e "Actual output:\n$($LFS find $path --printf '%LP %p\n')"
10099
10100         # Find all files and print their projids along with their path; count
10101         found_count=$($LFS find $path --printf "%LP %p\n" |
10102                 grep -E "$projid $path/(link|char|file)$projid" | wc -l)
10103         echo -e "found_count: $found_count"
10104         [[ $found_count == $expected_count ]] ||
10105                 error "Did not find any entries with expected projid $projid"
10106 }
10107 run_test 56ei "test lfs find --printf prints correct projid for special files"
10108
10109 test_56ej() {
10110         test_mkdir $DIR/$tdir.src ||
10111                 error "mkdir failed on $DIR/$tdir.src"
10112         test_mkdir $DIR/$tdir.dest ||
10113                 error "mkdir failed on $DIR/$tdir.dest"
10114         local f_mgrt=$DIR/$tdir.dest/$tfile.mgrt
10115
10116         $LFS setstripe -o 1 $DIR/$tdir.src
10117         $LFS setstripe -o 0 $DIR/$tdir.dest
10118         dd if=/dev/random of=$f_mgrt bs=1M count=1
10119
10120         $LFS migrate  --non-block --copy $DIR/$tdir.src $f_mgrt ||
10121                 error "migrate remote dir error $DIR/$tdir.src $f_mgrt"
10122 }
10123 run_test 56ej "lfs migration --non-block copy"
10124
10125 test_57a() {
10126         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10127         # note test will not do anything if MDS is not local
10128         if [ "$mds1_FSTYPE" != ldiskfs ]; then
10129                 skip_env "ldiskfs only test"
10130         fi
10131         remote_mds_nodsh && skip "remote MDS with nodsh"
10132
10133         local MNTDEV="osd*.*MDT*.mntdev"
10134         DEV=$(do_facet $SINGLEMDS lctl get_param -n $MNTDEV)
10135         [ -z "$DEV" ] && error "can't access $MNTDEV"
10136         for DEV in $(do_facet $SINGLEMDS lctl get_param -n $MNTDEV); do
10137                 do_facet $SINGLEMDS $DUMPE2FS -h $DEV > $TMP/t57a.dump ||
10138                         error "can't access $DEV"
10139                 DEVISIZE=$(awk '/Inode size:/ { print $3 }' $TMP/t57a.dump)
10140                 [[ $DEVISIZE -gt 128 ]] || error "inode size $DEVISIZE"
10141                 rm $TMP/t57a.dump
10142         done
10143 }
10144 run_test 57a "verify MDS filesystem created with large inodes =="
10145
10146 test_57b() {
10147         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10148         if [ "$mds1_FSTYPE" != ldiskfs ]; then
10149                 skip_env "ldiskfs only test"
10150         fi
10151         remote_mds_nodsh && skip "remote MDS with nodsh"
10152
10153         local dir=$DIR/$tdir
10154         local filecount=100
10155         local file1=$dir/f1
10156         local fileN=$dir/f$filecount
10157
10158         rm -rf $dir || error "removing $dir"
10159         test_mkdir -c1 $dir
10160         local mdtidx=$($LFS getstripe -m $dir)
10161         local mdtname=MDT$(printf %04x $mdtidx)
10162         local facet=mds$((mdtidx + 1))
10163
10164         echo "mcreating $filecount files"
10165         createmany -m $dir/f 1 $filecount || error "creating files in $dir"
10166
10167         # verify that files do not have EAs yet
10168         $LFS getstripe $file1 2>&1 | grep -q "no stripe" ||
10169                 error "$file1 has an EA"
10170         $LFS getstripe $fileN 2>&1 | grep -q "no stripe" ||
10171                 error "$fileN has an EA"
10172
10173         sync
10174         sleep 1
10175         df $dir  #make sure we get new statfs data
10176         local mdsfree=$(do_facet $facet \
10177                         lctl get_param -n osd*.*$mdtname.kbytesfree)
10178         local mdcfree=$(lctl get_param -n mdc.*$mdtname-mdc-*.kbytesfree)
10179         local file
10180
10181         echo "opening files to create objects/EAs"
10182         for file in $(seq -f $dir/f%g 1 $filecount); do
10183                 $OPENFILE -f O_RDWR $file > /dev/null 2>&1 ||
10184                         error "opening $file"
10185         done
10186
10187         # verify that files have EAs now
10188         $LFS getstripe -y $file1 | grep -q "l_ost_idx" ||
10189                 error "$file1 missing EA"
10190         $LFS getstripe -y $fileN | grep -q "l_ost_idx" ||
10191                 error "$fileN missing EA"
10192
10193         sleep 1  #make sure we get new statfs data
10194         df $dir
10195         local mdsfree2=$(do_facet $facet \
10196                          lctl get_param -n osd*.*$mdtname.kbytesfree)
10197         local mdcfree2=$(lctl get_param -n mdc.*$mdtname-mdc-*.kbytesfree)
10198
10199         if [[ $mdcfree2 -lt $((mdcfree - 16)) ]]; then
10200                 if [ "$mdsfree" != "$mdsfree2" ]; then
10201                         error "MDC before $mdcfree != after $mdcfree2"
10202                 else
10203                         echo "MDC before $mdcfree != after $mdcfree2"
10204                         echo "unable to confirm if MDS has large inodes"
10205                 fi
10206         fi
10207         rm -rf $dir
10208 }
10209 run_test 57b "default LOV EAs are stored inside large inodes ==="
10210
10211 test_58() {
10212         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10213         [ -z "$(which wiretest 2>/dev/null)" ] &&
10214                         skip_env "could not find wiretest"
10215
10216         wiretest
10217 }
10218 run_test 58 "verify cross-platform wire constants =============="
10219
10220 test_59() {
10221         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10222
10223         echo "touch 130 files"
10224         createmany -o $DIR/f59- 130
10225         echo "rm 130 files"
10226         unlinkmany $DIR/f59- 130
10227         sync
10228         # wait for commitment of removal
10229         wait_delete_completed
10230 }
10231 run_test 59 "verify cancellation of llog records async ========="
10232
10233 TEST60_HEAD="test_60 run $RANDOM"
10234 test_60a() {
10235         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10236         remote_mgs_nodsh && skip "remote MGS with nodsh"
10237         do_facet mgs "! which run-llog.sh &> /dev/null" &&
10238                 do_facet mgs "! ls run-llog.sh &> /dev/null" &&
10239                         skip_env "missing subtest run-llog.sh"
10240
10241         log "$TEST60_HEAD - from kernel mode"
10242         do_facet mgs "$LCTL dk > /dev/null"
10243         do_facet mgs "bash run-llog.sh" || error "run-llog.sh failed"
10244         do_facet mgs $LCTL dk > $TMP/$tfile
10245
10246         # LU-6388: test llog_reader
10247         local llog_reader=$(do_facet mgs "which llog_reader 2> /dev/null")
10248         llog_reader=${llog_reader:-$LUSTRE/utils/llog_reader}
10249         [ -z $(do_facet mgs ls -d $llog_reader 2> /dev/null) ] &&
10250                         skip_env "missing llog_reader"
10251         local fstype=$(facet_fstype mgs)
10252         [ $fstype != ldiskfs -a $fstype != zfs ] &&
10253                 skip_env "Only for ldiskfs or zfs type mgs"
10254
10255         local mntpt=$(facet_mntpt mgs)
10256         local mgsdev=$(mgsdevname 1)
10257         local fid_list
10258         local fid
10259         local rec_list
10260         local rec
10261         local rec_type
10262         local obj_file
10263         local path
10264         local seq
10265         local oid
10266         local pass=true
10267
10268         #get fid and record list
10269         fid_list=($(awk '/9_sub.*record/ { print $NF }' $TMP/$tfile |
10270                 tail -n 4))
10271         rec_list=($(awk '/9_sub.*record/ { print $((NF-3)) }' $TMP/$tfile |
10272                 tail -n 4))
10273         #remount mgs as ldiskfs or zfs type
10274         stop mgs || error "stop mgs failed"
10275         mount_fstype mgs || error "remount mgs failed"
10276         for ((i = 0; i < ${#fid_list[@]}; i++)); do
10277                 fid=${fid_list[i]}
10278                 rec=${rec_list[i]}
10279                 seq=$(echo $fid | awk -F ':' '{ print $1 }' | sed -e "s/^0x//g")
10280                 oid=$(echo $fid | awk -F ':' '{ print $2 }' | sed -e "s/^0x//g")
10281                 oid=$((16#$oid))
10282
10283                 case $fstype in
10284                         ldiskfs )
10285                                 obj_file=$mntpt/$(ost_fid2_objpath mgs $fid) ;;
10286                         zfs )
10287                                 obj_file=$mntpt/oi.$(($((16#$seq))&127))/$fid ;;
10288                 esac
10289                 echo "obj_file is $obj_file"
10290                 do_facet mgs $llog_reader $obj_file
10291
10292                 rec_type=$(do_facet mgs $llog_reader $obj_file | grep "type=" |
10293                         awk '{ print $3 }' | sed -e "s/^type=//g")
10294                 if [ $rec_type != $rec ]; then
10295                         echo "FAILED test_60a wrong record type $rec_type," \
10296                               "should be $rec"
10297                         pass=false
10298                         break
10299                 fi
10300
10301                 #check obj path if record type is LLOG_LOGID_MAGIC
10302                 if [ "$rec" == "1064553b" ]; then
10303                         path=$(do_facet mgs $llog_reader $obj_file |
10304                                 grep "path=" | awk '{ print $NF }' |
10305                                 sed -e "s/^path=//g")
10306                         if [ $obj_file != $mntpt/$path ]; then
10307                                 echo "FAILED test_60a wrong obj path" \
10308                                       "$montpt/$path, should be $obj_file"
10309                                 pass=false
10310                                 break
10311                         fi
10312                 fi
10313         done
10314         rm -f $TMP/$tfile
10315         #restart mgs before "error", otherwise it will block the next test
10316         stop mgs || error "stop mgs failed"
10317         start mgs $(mgsdevname) $MGS_MOUNT_OPTS || error "start mgs failed"
10318         $pass || error "test failed, see FAILED test_60a messages for specifics"
10319 }
10320 run_test 60a "llog_test run from kernel module and test llog_reader"
10321
10322 test_60b() { # bug 6411
10323         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10324
10325         dmesg > $DIR/$tfile
10326         LLOG_COUNT=$(do_facet mgs dmesg |
10327                      awk "/$TEST60_HEAD/ { marker = 1; from_marker = 0; }
10328                           /llog_[a-z]*.c:[0-9]/ {
10329                                 if (marker)
10330                                         from_marker++
10331                                 from_begin++
10332                           }
10333                           END {
10334                                 if (marker)
10335                                         print from_marker
10336                                 else
10337                                         print from_begin
10338                           }")
10339
10340         [[ $LLOG_COUNT -gt 120 ]] &&
10341                 error "CDEBUG_LIMIT not limiting messages ($LLOG_COUNT)" || true
10342 }
10343 run_test 60b "limit repeated messages from CERROR/CWARN"
10344
10345 test_60c() {
10346         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10347
10348         echo "create 5000 files"
10349         createmany -o $DIR/f60c- 5000
10350 #define OBD_FAIL_MDS_LLOG_CREATE_FAILED  0x137
10351         lctl set_param fail_loc=0x80000137
10352         unlinkmany $DIR/f60c- 5000
10353         lctl set_param fail_loc=0
10354 }
10355 run_test 60c "unlink file when mds full"
10356
10357 test_60d() {
10358         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10359
10360         SAVEPRINTK=$(lctl get_param -n printk)
10361         # verify "lctl mark" is even working"
10362         MESSAGE="test message ID $RANDOM $$"
10363         $LCTL mark "$MESSAGE" || error "$LCTL mark failed"
10364         dmesg | grep -q "$MESSAGE" || error "didn't find debug marker in log"
10365
10366         lctl set_param printk=0 || error "set lnet.printk failed"
10367         lctl get_param -n printk | grep emerg || error "lnet.printk dropped emerg"
10368         MESSAGE="new test message ID $RANDOM $$"
10369         # Assume here that libcfs_debug_mark_buffer() uses D_WARNING
10370         $LCTL mark "$MESSAGE" || error "$LCTL mark failed"
10371         dmesg | grep -q "$MESSAGE" && error "D_WARNING wasn't masked" || true
10372
10373         lctl set_param -n printk="$SAVEPRINTK"
10374 }
10375 run_test 60d "test printk console message masking"
10376
10377 test_60e() {
10378         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10379         remote_mds_nodsh && skip "remote MDS with nodsh"
10380
10381         touch $DIR/$tfile
10382 #define OBD_FAIL_MDS_LLOG_CREATE_FAILED2  0x15b
10383         do_facet mds1 lctl set_param fail_loc=0x15b
10384         rm $DIR/$tfile
10385 }
10386 run_test 60e "no space while new llog is being created"
10387
10388 test_60f() {
10389         local old_path=$($LCTL get_param -n debug_path)
10390
10391         stack_trap "$LCTL set_param debug_path=$old_path"
10392         stack_trap "rm -f $TMP/$tfile*"
10393         rm -f $TMP/$tfile* 2> /dev/null
10394         #define OBD_FAIL_PTLRPC_DUMP_LOG         0x50e
10395         $LCTL set_param debug_path=$TMP/$tfile fail_loc=0x8000050e
10396         test_mkdir $DIR/$tdir
10397         # retry in case the open is cached and not released
10398         for (( i = 0; i < 100 && $(ls $TMP/$tfile* | wc -l) == 0; i++ )); do
10399                 echo $i > $DIR/$tdir/$tfile.$i && cat $DIR/$tdir/$tfile.$i
10400                 sleep 0.1
10401         done
10402         ls $TMP/$tfile*
10403         (( $(ls $TMP/$tfile* | wc -l) > 0 )) || error "$TMP/$tfile not dumped"
10404 }
10405 run_test 60f "change debug_path works"
10406
10407 test_60g() {
10408         (( $MDS1_VERSION >= $(version_code v2_12_57-61-g02b5a407081c) )) ||
10409                 skip "Need MDS >= v2_12_57-61-g02b5a407081c for statahead fix"
10410
10411         local pid
10412         local i
10413
10414         test_mkdir -c $MDSCOUNT $DIR/$tdir
10415
10416         (
10417                 local index=0
10418                 while true; do
10419                         $LFS setdirstripe -i $(($index % $MDSCOUNT)) \
10420                                 -c $MDSCOUNT $DIR/$tdir/subdir$index \
10421                                 2>/dev/null
10422                         mkdir $DIR/$tdir/subdir$index 2>/dev/null
10423                         rmdir $DIR/$tdir/subdir$index 2>/dev/null
10424                         index=$((index + 1))
10425                 done
10426         ) &
10427
10428         pid=$!
10429
10430         for i in {0..100}; do
10431                 # define OBD_FAIL_OSD_TXN_START    0x19a
10432                 local index=$((i % MDSCOUNT + 1))
10433
10434                 do_facet mds$index $LCTL set_param fail_loc=0x8000019a \
10435                         > /dev/null
10436                 sleep 0.01
10437         done
10438
10439         kill -9 $pid
10440
10441         for i in $(seq $MDSCOUNT); do
10442                 do_facet mds$i $LCTL set_param fail_loc=0 > /dev/null
10443         done
10444
10445         mkdir $DIR/$tdir/new || error "mkdir failed"
10446         rmdir $DIR/$tdir/new || error "rmdir failed"
10447
10448         do_facet mds1 $LCTL lfsck_start -M $(facet_svc mds1) -A -C \
10449                 -t namespace
10450         for i in $(seq $MDSCOUNT); do
10451                 wait_update_facet mds$i "$LCTL get_param -n \
10452                         mdd.$(facet_svc mds$i).lfsck_namespace |
10453                         awk '/^status/ { print \\\$2 }'" "completed"
10454         done
10455
10456         ls -R $DIR/$tdir
10457         rm -rf $DIR/$tdir || error "rmdir failed"
10458 }
10459 run_test 60g "transaction abort won't cause MDT hung"
10460
10461 test_60h() {
10462         [ $MDS1_VERSION -le $(version_code 2.12.52) ] &&
10463                 skip "Need MDS version at least 2.12.52"
10464         [ $MDSCOUNT -lt 2 ] && skip "Need at least 2 MDTs"
10465
10466         local f
10467
10468         #define OBD_FAIL_MDS_STRIPE_CREATE       0x188
10469         #define OBD_FAIL_MDS_STRIPE_FID          0x189
10470         for fail_loc in 0x80000188 0x80000189; do
10471                 do_facet mds1 "$LCTL set_param fail_loc=$fail_loc"
10472                 $LFS mkdir -c $MDSCOUNT -i 0 $DIR/$tdir-$fail_loc ||
10473                         error "mkdir $dir-$fail_loc failed"
10474                 for i in {0..10}; do
10475                         # create may fail on missing stripe
10476                         echo $i > $DIR/$tdir-$fail_loc/$i
10477                 done
10478                 $LFS getdirstripe $DIR/$tdir-$fail_loc ||
10479                         error "getdirstripe $tdir-$fail_loc failed"
10480                 $LFS migrate -m 1 $DIR/$tdir-$fail_loc ||
10481                         error "migrate $tdir-$fail_loc failed"
10482                 $LFS getdirstripe $DIR/$tdir-$fail_loc ||
10483                         error "getdirstripe $tdir-$fail_loc failed"
10484                 pushd $DIR/$tdir-$fail_loc
10485                 for f in *; do
10486                         echo $f | cmp $f - || error "$f data mismatch"
10487                 done
10488                 popd
10489                 rm -rf $DIR/$tdir-$fail_loc
10490         done
10491 }
10492 run_test 60h "striped directory with missing stripes can be accessed"
10493
10494 function t60i_load() {
10495         mkdir $DIR/$tdir
10496         #define OBD_FAIL_LLOG_PAUSE_AFTER_PAD               0x131c
10497         $LCTL set_param fail_loc=0x131c fail_val=1
10498         for ((i=0; i<5000; i++)); do
10499                 touch $DIR/$tdir/f$i
10500         done
10501 }
10502
10503 test_60i() {
10504         changelog_register || error "changelog_register failed"
10505         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
10506         changelog_users $SINGLEMDS | grep -q $cl_user ||
10507                 error "User $cl_user not found in changelog_users"
10508         changelog_chmask "ALL"
10509         t60i_load &
10510         local PID=$!
10511         for((i=0; i<100; i++)); do
10512                 changelog_dump >/dev/null ||
10513                         error "can't read changelog"
10514         done
10515         kill $PID
10516         wait $PID
10517         changelog_deregister || error "changelog_deregister failed"
10518         $LCTL set_param fail_loc=0
10519 }
10520 run_test 60i "llog: new record vs reader race"
10521
10522 test_60j() {
10523         (( $MDS1_VERSION >= $(version_code 2.15.50) )) ||
10524                 skip "need MDS version at least 2.15.50"
10525         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
10526         remote_mds_nodsh && skip "remote MDS with nodsh"
10527         [[ "$mds1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
10528
10529         changelog_users $SINGLEMDS | grep "^cl" &&
10530                 skip "active changelog user"
10531
10532         local llog_reader=$(do_facet $SINGLEMDS "which llog_reader 2> /dev/null")
10533
10534         [[ -z $(do_facet $SINGLEMDS ls -d $llog_reader 2> /dev/null) ]] &&
10535                 skip_env "missing llog_reader"
10536
10537         mkdir_on_mdt0 $DIR/$tdir
10538
10539         local f=$DIR/$tdir/$tfile
10540         local mdt_dev
10541         local tmpfile
10542         local plain
10543
10544         changelog_register || error "cannot register changelog user"
10545
10546         # set changelog_mask to ALL
10547         changelog_chmask "ALL"
10548         changelog_clear
10549
10550         createmany -o ${f}- 100 || error "createmany failed as $RUNAS_ID"
10551         unlinkmany ${f}- 100 || error "unlinkmany failed"
10552
10553         tmpfile="$(mktemp --tmpdir -u $tfile.XXXXXX)"
10554         mdt_dev=$(facet_device $SINGLEMDS)
10555
10556         do_facet $SINGLEMDS sync
10557         plain=$(do_facet $SINGLEMDS "$DEBUGFS -c -R 'dump changelog_catalog \
10558                 $tmpfile' $mdt_dev; $llog_reader $tmpfile" |
10559                 awk '{match($0,"path=([^ ]+)",a)}END{print a[1]}')
10560
10561         stack_trap "do_facet $SINGLEMDS rm -f $tmpfile"
10562
10563         # if $tmpfile is not on EXT3 filesystem for some reason
10564         [[ ${plain:0:1} == 'O' ]] ||
10565                 skip "path $plain is not in 'O/1/d<n>/<n>' format"
10566
10567         size=$(do_facet $SINGLEMDS "$DEBUGFS -c -R 'dump $plain $tmpfile' \
10568                 $mdt_dev; stat -c %s $tmpfile")
10569         echo "Truncate llog from $size to $((size - size % 8192))"
10570         size=$((size - size % 8192))
10571         do_facet $SINGLEMDS $TRUNCATE $tmpfile $size
10572         errs=$(do_facet $SINGLEMDS "$llog_reader $tmpfile" |
10573                 grep -c 'in bitmap only')
10574         (( $errs > 0 )) || error "llog_reader didn't find lost records"
10575
10576         size=$((size - 9000))
10577         echo "Corrupt llog in the middle at $size"
10578         do_facet $SINGLEMDS dd if=/dev/urandom of=$tmpfile bs=1 seek=$size \
10579                 count=333 conv=notrunc
10580         errs=$(do_facet $SINGLEMDS "$llog_reader $tmpfile" |
10581                 grep -c 'next chunk')
10582         (( $errs > 0 )) || error "llog_reader didn't skip bad chunk"
10583 }
10584 run_test 60j "llog_reader reports corruptions"
10585
10586 test_61a() {
10587         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10588
10589         f="$DIR/f61"
10590         dd if=/dev/zero of=$f bs=$PAGE_SIZE count=1 || error "dd $f failed"
10591         cancel_lru_locks osc
10592         $MULTIOP $f OSMWUc || error "$MULTIOP $f failed"
10593         sync
10594 }
10595 run_test 61a "mmap() writes don't make sync hang ================"
10596
10597 test_61b() {
10598         mmap_mknod_test $DIR/$tfile || error "mmap_mknod_test failed"
10599 }
10600 run_test 61b "mmap() of unstriped file is successful"
10601
10602 # bug 2319 - oig_wait() interrupted causes crash because of invalid waitq.
10603 # Though this test is irrelevant anymore, it helped to reveal some
10604 # other grant bugs (LU-4482), let's keep it.
10605 test_63a() {   # was test_63
10606         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10607
10608         MAX_DIRTY_MB=$(lctl get_param -n osc.*.max_dirty_mb | head -n 1)
10609
10610         for i in `seq 10` ; do
10611                 dd if=/dev/zero of=$DIR/f63 bs=8k &
10612                 sleep 5
10613                 kill $!
10614                 sleep 1
10615         done
10616
10617         rm -f $DIR/f63 || true
10618 }
10619 run_test 63a "Verify oig_wait interruption does not crash ======="
10620
10621 # bug 2248 - async write errors didn't return to application on sync
10622 # bug 3677 - async write errors left page locked
10623 test_63b() {
10624         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10625
10626         debugsave
10627         lctl set_param debug=-1
10628
10629         # ensure we have a grant to do async writes
10630         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1
10631         rm $DIR/$tfile
10632
10633         sync    # sync lest earlier test intercept the fail_loc
10634
10635         #define OBD_FAIL_OSC_BRW_PREP_REQ        0x406
10636         lctl set_param fail_loc=0x80000406
10637         $MULTIOP $DIR/$tfile Owy && \
10638                 error "sync didn't return ENOMEM"
10639         sync; sleep 2; sync     # do a real sync this time to flush page
10640         lctl get_param -n llite.*.dump_page_cache | grep locked && \
10641                 error "locked page left in cache after async error" || true
10642         debugrestore
10643 }
10644 run_test 63b "async write errors should be returned to fsync ==="
10645
10646 test_64a () {
10647         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10648
10649         lfs df $DIR
10650         lctl get_param osc.*[oO][sS][cC][_-]*.cur* | grep "=[1-9]"
10651 }
10652 run_test 64a "verify filter grant calculations (in kernel) ====="
10653
10654 test_64b () {
10655         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10656
10657         bash oos.sh $MOUNT || error "oos.sh failed: $?"
10658 }
10659 run_test 64b "check out-of-space detection on client"
10660
10661 test_64c() {
10662         $LCTL set_param osc.*OST0000-osc-[^mM]*.cur_grant_bytes=0
10663 }
10664 run_test 64c "verify grant shrink"
10665
10666 # this does exactly what osc_request.c:osc_announce_cached() does in
10667 # order to calculate max amount of grants to ask from server
10668 want_grant() {
10669         local tgt=$1
10670
10671         local nrpages=$($LCTL get_param -n osc.$tgt.max_pages_per_rpc)
10672         local rpc_in_flight=$($LCTL get_param -n osc.$tgt.max_rpcs_in_flight)
10673
10674         ((rpc_in_flight++));
10675         nrpages=$((nrpages * rpc_in_flight))
10676
10677         local dirty_max_pages=$($LCTL get_param -n osc.$tgt.max_dirty_mb)
10678
10679         dirty_max_pages=$((dirty_max_pages * 1024 * 1024 / PAGE_SIZE))
10680
10681         [[ $dirty_max_pages -gt $nrpages ]] && nrpages=$dirty_max_pages
10682         local undirty=$((nrpages * PAGE_SIZE))
10683
10684         local max_extent_pages
10685         max_extent_pages=$(import_param $tgt grant_max_extent_size)
10686         max_extent_pages=$((max_extent_pages / PAGE_SIZE))
10687         local nrextents=$(((nrpages + max_extent_pages - 1) / max_extent_pages))
10688         local grant_extent_tax
10689         grant_extent_tax=$(import_param $tgt grant_extent_tax)
10690
10691         undirty=$((undirty + nrextents * grant_extent_tax))
10692
10693         echo $undirty
10694 }
10695
10696 # this is size of unit for grant allocation. It should be equal to
10697 # what tgt_grant.c:tgt_grant_chunk() calculates
10698 grant_chunk() {
10699         local tgt=$1
10700         local max_brw_size
10701         local grant_extent_tax
10702
10703         max_brw_size=$(import_param $tgt max_brw_size)
10704
10705         grant_extent_tax=$(import_param $tgt grant_extent_tax)
10706
10707         echo $(((max_brw_size + grant_extent_tax) * 2))
10708 }
10709
10710 test_64d() {
10711         [ $OST1_VERSION -ge $(version_code 2.10.56) ] ||
10712                 skip "OST < 2.10.55 doesn't limit grants enough"
10713
10714         local tgt=$($LCTL dl | awk '/OST0000-osc-[^mM]/ { print $4 }')
10715
10716         [[ "$($LCTL get_param osc.${tgt}.import)" =~ "grant_param" ]] ||
10717                 skip "no grant_param connect flag"
10718
10719         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
10720
10721         $LCTL set_param -n -n debug="$OLDDEBUG" || true
10722         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
10723
10724
10725         local max_cur_granted=$(($(want_grant $tgt) + $(grant_chunk $tgt)))
10726         stack_trap "rm -f $DIR/$tfile && wait_delete_completed" EXIT
10727
10728         $LFS setstripe $DIR/$tfile -i 0 -c 1
10729         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1000 &
10730         ddpid=$!
10731
10732         while kill -0 $ddpid; do
10733                 local cur_grant=$($LCTL get_param -n osc.$tgt.cur_grant_bytes)
10734
10735                 if [[ $cur_grant -gt $max_cur_granted ]]; then
10736                         kill $ddpid
10737                         error "cur_grant $cur_grant > $max_cur_granted"
10738                 fi
10739
10740                 sleep 1
10741         done
10742 }
10743 run_test 64d "check grant limit exceed"
10744
10745 check_grants() {
10746         local tgt=$1
10747         local expected=$2
10748         local msg=$3
10749         local cur_grants=$($LCTL get_param -n osc.$tgt.cur_grant_bytes)
10750
10751         ((cur_grants == expected)) ||
10752                 error "$msg: grants mismatch: $cur_grants, expected $expected"
10753 }
10754
10755 round_up_p2() {
10756         echo $((($1 + $2 - 1) & ~($2 - 1)))
10757 }
10758
10759 test_64e() {
10760         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10761         [ $OST1_VERSION -ge $(version_code 2.11.56) ] ||
10762                 skip "Need OSS version at least 2.11.56"
10763
10764         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
10765         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
10766         $LCTL set_param debug=+cache
10767
10768         # Remount client to reset grant
10769         remount_client $MOUNT || error "failed to remount client"
10770         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
10771
10772         local init_grants=$(import_param $osc_tgt initial_grant)
10773
10774         check_grants $osc_tgt $init_grants "init grants"
10775
10776         local extent_tax=$(import_param $osc_tgt grant_extent_tax)
10777         local max_brw_size=$(import_param $osc_tgt max_brw_size)
10778         local gbs=$(import_param $osc_tgt grant_block_size)
10779
10780         # write random number of bytes from max_brw_size / 4 to max_brw_size
10781         local write_bytes=$(shuf -i $((max_brw_size / 4))-$max_brw_size -n 1)
10782         # align for direct io
10783         write_bytes=$(round_up_p2 $write_bytes PAGE_SIZE)
10784         # round to grant consumption unit
10785         local wb_round_up=$(round_up_p2 $write_bytes gbs)
10786
10787         local grants=$((wb_round_up + extent_tax))
10788
10789         $LFS setstripe -c 1 -i 0 $DIR/$tfile  || error "lfs setstripe failed"
10790         stack_trap "rm -f $DIR/$tfile"
10791
10792         # define OBD_FAIL_TGT_NO_GRANT 0x725
10793         # make the server not grant more back
10794         do_facet ost1 $LCTL set_param fail_loc=0x725
10795         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 oflag=direct
10796
10797         do_facet ost1 $LCTL set_param fail_loc=0
10798
10799         check_grants $osc_tgt $((init_grants - grants)) "dio w/o grant alloc"
10800
10801         rm -f $DIR/$tfile || error "rm failed"
10802
10803         # Remount client to reset grant
10804         remount_client $MOUNT || error "failed to remount client"
10805         osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
10806
10807         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
10808
10809         # define OBD_FAIL_TGT_NO_GRANT 0x725
10810         # make the server not grant more back
10811         do_facet ost1 $LCTL set_param fail_loc=0x725
10812         $MULTIOP $DIR/$tfile "oO_WRONLY:w${write_bytes}yc"
10813         do_facet ost1 $LCTL set_param fail_loc=0
10814
10815         check_grants $osc_tgt $((init_grants - grants)) "buf io w/o grant alloc"
10816 }
10817 run_test 64e "check grant consumption (no grant allocation)"
10818
10819 test_64f() {
10820         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10821
10822         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
10823         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
10824         $LCTL set_param debug=+cache
10825
10826         # Remount client to reset grant
10827         remount_client $MOUNT || error "failed to remount client"
10828         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
10829
10830         local init_grants=$(import_param $osc_tgt initial_grant)
10831         local extent_tax=$(import_param $osc_tgt grant_extent_tax)
10832         local max_brw_size=$(import_param $osc_tgt max_brw_size)
10833         local gbs=$(import_param $osc_tgt grant_block_size)
10834         local chunk=$(grant_chunk $osc_tgt)
10835
10836         # write random number of bytes from max_brw_size / 4 to max_brw_size
10837         local write_bytes=$(shuf -i $((max_brw_size / 4))-$max_brw_size -n 1)
10838         # align for direct io
10839         write_bytes=$(round_up_p2 $write_bytes PAGE_SIZE)
10840         # round to grant consumption unit
10841         local wb_round_up=$(round_up_p2 $write_bytes gbs)
10842
10843         local grants=$((wb_round_up + extent_tax))
10844
10845         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
10846         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 oflag=direct ||
10847                 error "error writing to $DIR/$tfile"
10848         stack_trap "rm -f $DIR/$tfile"
10849
10850         check_grants $osc_tgt $((init_grants - grants + chunk)) \
10851                 "direct io with grant allocation"
10852
10853         rm -f $DIR/$tfile || error "rm failed"
10854
10855         # Remount client to reset grant
10856         remount_client $MOUNT || error "failed to remount client"
10857         osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
10858
10859         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
10860
10861         # Hybrid means this won't really be buffered IO, so we disable it for
10862         # this part of the test
10863         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
10864         $LCTL set_param llite.*.hybrid_io=0
10865         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
10866         # Testing that buffered IO consumes grant on the client
10867
10868         # Delay the RPC on the server so it's guaranteed to not complete even
10869         # if the RPC is sent from the client
10870         #define OBD_FAIL_PTLRPC_PAUSE_REQ        0x50a
10871         $LCTL set_param fail_loc=0x50a fail_val=3
10872         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 conv=notrunc ||
10873                 error "error writing to $DIR/$tfile with buffered IO"
10874
10875         check_grants $osc_tgt $((init_grants - grants)) \
10876                 "buffered io, not write rpc"
10877
10878         # Clear the fail loc and do a sync on the client
10879         $LCTL set_param fail_loc=0 fail_val=0
10880         sync
10881
10882         # RPC is now known to have sent
10883         check_grants $osc_tgt $((init_grants - grants + chunk)) \
10884                 "buffered io, one RPC"
10885 }
10886 run_test 64f "check grant consumption (with grant allocation)"
10887
10888 test_64g() {
10889         (( $MDS1_VERSION >= $(version_code 2.14.56) )) ||
10890                 skip "Need MDS version at least 2.14.56"
10891
10892         local mdts=$(comma_list $(mdts_nodes))
10893
10894         local old=$($LCTL get_param mdc.$FSNAME-*.grant_shrink_interval |
10895                         tr '\n' ' ')
10896         stack_trap "$LCTL set_param $old"
10897
10898         # generate dirty pages and increase dirty granted on MDT
10899         stack_trap "rm -f $DIR/$tfile-*"
10900         for (( i = 0; i < 10; i++)); do
10901                 $LFS setstripe -E 1M -L mdt $DIR/$tfile-$i ||
10902                         error "can't set stripe"
10903                 dd if=/dev/zero of=$DIR/$tfile-$i bs=128k count=1 ||
10904                         error "can't dd"
10905                 $LFS getstripe $DIR/$tfile-$i | grep -q pattern.*mdt || {
10906                         $LFS getstripe $DIR/$tfile-$i
10907                         error "not DoM file"
10908                 }
10909         done
10910
10911         # flush dirty pages
10912         sync
10913
10914         # wait until grant shrink reset grant dirty on MDTs
10915         for ((i = 0; i < 120; i++)); do
10916                 grant_dirty=$(do_nodes $mdts $LCTL get_param -n  mdt.*.tot_dirty |
10917                         awk '{sum=sum+$1} END {print sum}')
10918                 vm_dirty=$(awk '/Dirty:/{print $2}' /proc/meminfo)
10919                 echo "$grant_dirty grants, $vm_dirty pages"
10920                 (( grant_dirty + vm_dirty == 0 )) && break
10921                 (( i == 3 )) && sync &&
10922                         $LCTL set_param mdc.$FSNAME-*.grant_shrink_interval=5
10923                 sleep 1
10924         done
10925
10926         grant_dirty=$(do_nodes $mdts $LCTL get_param -n  mdt.*.tot_dirty |
10927                 awk '{sum=sum+$1} END {print sum}')
10928         (( grant_dirty == 0 )) || error "$grant_dirty on MDT"
10929 }
10930 run_test 64g "grant shrink on MDT"
10931
10932 test_64h() {
10933         (( $OST1_VERSION >= $(version_code 2.14.56) )) ||
10934                 skip "need OST at least 2.14.56 to avoid grant shrink on read"
10935
10936         local instance=$($LFS getname -i $DIR)
10937         local osc_tgt="$FSNAME-OST0000-osc-$instance"
10938         local num_exps=$(do_facet ost1 \
10939             $LCTL get_param -n obdfilter.*OST0000*.num_exports)
10940         local max_brw_size=$(import_param $osc_tgt max_brw_size)
10941         local avail=$($LCTL get_param -n osc.*OST0000-osc-$instance.kbytesavail)
10942         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
10943
10944         # 10MiB is for file to be written, max_brw_size * 16 *
10945         # num_exps is space reserve so that tgt_grant_shrink() decided
10946         # to not shrink
10947         local expect=$((max_brw_size * 16 * num_exps + 10 * 1048576))
10948         (( avail * 1024 < expect )) &&
10949                 skip "need $expect bytes on ost1, have $(( avail * 1024 )) only"
10950
10951         save_lustre_params client "osc.*OST0000*.grant_shrink" > $p
10952         save_lustre_params client "osc.*OST0000*.grant_shrink_interval" >> $p
10953         stack_trap "restore_lustre_params < $p; rm -f $p" EXIT
10954         $LCTL set_param osc.*OST0000*.grant_shrink=1
10955         $LCTL set_param osc.*OST0000*.grant_shrink_interval=10
10956
10957         $LFS setstripe -c 1 -i 0 $DIR/$tfile
10958         stack_trap "rm -f $DIR/$tfile"
10959         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 oflag=sync
10960
10961         # drop cache so that coming read would do rpc
10962         cancel_lru_locks osc
10963
10964         # shrink interval is set to 10, pause for 7 seconds so that
10965         # grant thread did not wake up yet but coming read entered
10966         # shrink mode for rpc (osc_should_shrink_grant())
10967         sleep 7
10968
10969         declare -a cur_grant_bytes
10970         declare -a tot_granted
10971         cur_grant_bytes[0]=$($LCTL get_param -n osc.*OST0000*.cur_grant_bytes)
10972         tot_granted[0]=$(do_facet ost1 \
10973             $LCTL get_param -n obdfilter.*OST0000*.tot_granted)
10974
10975         dd if=$DIR/$tfile bs=4K count=1 of=/dev/null
10976
10977         cur_grant_bytes[1]=$($LCTL get_param -n osc.*OST0000*.cur_grant_bytes)
10978         tot_granted[1]=$(do_facet ost1 \
10979             $LCTL get_param -n obdfilter.*OST0000*.tot_granted)
10980
10981         # grant change should be equal on both sides
10982         (( cur_grant_bytes[0] - cur_grant_bytes[1] ==
10983                 tot_granted[0] - tot_granted[1])) ||
10984                 error "grant change mismatch, "                                \
10985                         "server: ${tot_granted[0]} to ${tot_granted[1]}, "     \
10986                         "client: ${cur_grant_bytes[0]} to ${cur_grant_bytes[1]}"
10987 }
10988 run_test 64h "grant shrink on read"
10989
10990 test_64i() {
10991         (( $OST1_VERSION >= $(version_code 2.14.56) )) ||
10992                 skip "need OST at least 2.14.56 to avoid grant shrink on replay"
10993
10994         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10995         remote_ost_nodsh && skip "remote OSTs with nodsh"
10996
10997         $LFS setstripe -c 1 -i 0 $DIR/$tfile
10998         stack_trap "rm -f $DIR/$tfile"
10999
11000         dd if=/dev/zero of=$DIR/$tfile bs=1M count=64
11001
11002         # lustre-ffff9fc75e850800 /mnt/lustre -> ffff9fc75e850800
11003         local instance=$($LFS getname -i $DIR)
11004
11005         local osc_tgt="$FSNAME-OST0000-osc-$instance"
11006         local cgb=$($LCTL get_param -n osc.$osc_tgt.cur_grant_bytes)
11007
11008         # shrink grants and simulate rpc loss
11009         #define OBD_FAIL_PTLRPC_DROP_REQ_OPC     0x513
11010         do_facet ost1 "$LCTL set_param fail_loc=0x80000513 fail_val=17"
11011         $LCTL set_param osc.$osc_tgt.cur_grant_bytes=$((cgb/2))B
11012
11013         fail ost1
11014
11015         dd if=/dev/zero of=$DIR/$tfile oflag=append bs=1M count=8 conv=notrunc
11016
11017         local testid=$(echo $TESTNAME | tr '_' ' ')
11018
11019         do_facet ost1 dmesg | tac | sed "/$testid/,$ d" |
11020                 grep "GRANT, real grant" &&
11021                 error "client has more grants then it owns" || true
11022 }
11023 run_test 64i "shrink on reconnect"
11024
11025 test_64j() {
11026         $LFS setstripe -c 1 -i 0 $DIR/$tfile
11027
11028         # get rid of lost grants which could be formed on previous test
11029         $MULTIOP $DIR/$tfile oO_RDWR:O_SYNC:w4096c
11030 #define OBD_FAIL_OST_GRANT_PREPARE      0x256
11031         do_facet ost1 "$LCTL set_param fail_loc=0x80000256"
11032
11033         $MULTIOP $DIR/$tfile oO_RDWR:O_DIRECT:w4096c
11034 }
11035 run_test 64j "check grants on re-done rpc"
11036
11037 # bug 1414 - set/get directories' stripe info
11038 test_65a() {
11039         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11040
11041         # LU-16904 check if the root is set as PFL layout
11042         local numcomp=$($LFS getstripe --component-count $MOUNT)
11043         [ $numcomp -eq 0 ] || skip "Skip test_65a for PFL layout"
11044
11045         test_mkdir $DIR/$tdir
11046         touch $DIR/$tdir/f1
11047         $LVERIFY $DIR/$tdir $DIR/$tdir/f1 || error "lverify failed"
11048 }
11049 run_test 65a "directory with no stripe info"
11050
11051 test_65b() {
11052         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11053
11054         test_mkdir $DIR/$tdir
11055         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
11056
11057         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
11058                                                 error "setstripe"
11059         touch $DIR/$tdir/f2
11060         $LVERIFY $DIR/$tdir $DIR/$tdir/f2 || error "lverify failed"
11061 }
11062 run_test 65b "directory setstripe -S stripe_size*2 -i 0 -c 1"
11063
11064 test_65c() {
11065         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11066         [ $OSTCOUNT -lt 2 ] && skip_env "need at least 2 OSTs"
11067
11068         test_mkdir $DIR/$tdir
11069         local stripesize=$($LFS getstripe -S $DIR/$tdir)
11070
11071         $LFS setstripe -S $((stripesize * 4)) -i 1 \
11072                 -c $((OSTCOUNT - 1)) $DIR/$tdir || error "setstripe"
11073         touch $DIR/$tdir/f3
11074         $LVERIFY $DIR/$tdir $DIR/$tdir/f3 || error "lverify failed"
11075 }
11076 run_test 65c "directory setstripe -S stripe_size*4 -i 1 -c $((OSTCOUNT-1))"
11077
11078 test_65d() {
11079         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11080
11081         test_mkdir $DIR/$tdir
11082         local STRIPECOUNT=$($LFS getstripe -c $DIR/$tdir)
11083         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
11084
11085         if [[ $STRIPECOUNT -le 0 ]]; then
11086                 sc=1
11087         elif [[ $STRIPECOUNT -gt $LOV_MAX_STRIPE_COUNT ]]; then
11088                 [[ $OSTCOUNT -gt $LOV_MAX_STRIPE_COUNT ]] &&
11089                         sc=$LOV_MAX_STRIPE_COUNT || sc=$(($OSTCOUNT - 1))
11090         else
11091                 sc=$(($STRIPECOUNT - 1))
11092         fi
11093         $LFS setstripe -S $STRIPESIZE -c $sc $DIR/$tdir || error "setstripe"
11094         touch $DIR/$tdir/f4 $DIR/$tdir/f5
11095         $LVERIFY $DIR/$tdir $DIR/$tdir/f4 $DIR/$tdir/f5 ||
11096                 error "lverify failed"
11097 }
11098 run_test 65d "directory setstripe -S stripe_size -c stripe_count"
11099
11100 test_65e() {
11101         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11102
11103         # LU-16904 delete layout when root is set as PFL layout
11104         save_layout_restore_at_exit $MOUNT
11105         $LFS setstripe -d $MOUNT || error "setstripe failed"
11106
11107         test_mkdir $DIR/$tdir
11108
11109         $LFS setstripe $DIR/$tdir || error "setstripe"
11110         $LFS getstripe -v $DIR/$tdir | grep "Default" ||
11111                                         error "no stripe info failed"
11112         touch $DIR/$tdir/f6
11113         $LVERIFY $DIR/$tdir $DIR/$tdir/f6 || error "lverify failed"
11114 }
11115 run_test 65e "directory setstripe defaults"
11116
11117 test_65f() {
11118         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11119
11120         test_mkdir $DIR/${tdir}f
11121         $RUNAS $LFS setstripe $DIR/${tdir}f &&
11122                 error "setstripe succeeded" || true
11123 }
11124 run_test 65f "dir setstripe permission (should return error) ==="
11125
11126 test_65g() {
11127         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11128
11129         # LU-16904 delete layout when root is set as PFL layout
11130         save_layout_restore_at_exit $MOUNT
11131         $LFS setstripe -d $MOUNT || error "setstripe failed"
11132
11133         test_mkdir $DIR/$tdir
11134         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
11135
11136         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
11137                 error "setstripe -S failed"
11138         $LFS setstripe -d $DIR/$tdir || error "setstripe -d failed"
11139         $LFS getstripe -v $DIR/$tdir | grep "Default" ||
11140                 error "delete default stripe failed"
11141 }
11142 run_test 65g "directory setstripe -d"
11143
11144 test_65h() {
11145         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11146
11147         test_mkdir $DIR/$tdir
11148         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
11149
11150         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
11151                 error "setstripe -S failed"
11152         test_mkdir $DIR/$tdir/dd1
11153         [ $($LFS getstripe -c $DIR/$tdir) = $($LFS getstripe -c $DIR/$tdir/dd1) ] ||
11154                 error "stripe info inherit failed"
11155 }
11156 run_test 65h "directory stripe info inherit ===================="
11157
11158 test_65i() {
11159         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11160
11161         save_layout_restore_at_exit $MOUNT
11162
11163         # bug6367: set non-default striping on root directory
11164         $LFS setstripe -S 65536 -c -1 $MOUNT || error "error setting stripe"
11165
11166         # bug12836: getstripe on -1 default directory striping
11167         $LFS getstripe $MOUNT || error "getstripe $MOUNT failed"
11168
11169         # bug12836: getstripe -v on -1 default directory striping
11170         $LFS getstripe -v $MOUNT || error "getstripe -v $MOUNT failed"
11171
11172         # bug12836: new find on -1 default directory striping
11173         $LFS find -mtime -1 $MOUNT > /dev/null || error "find $MOUNT failed"
11174 }
11175 run_test 65i "various tests to set root directory striping"
11176
11177 test_65j() { # bug6367
11178         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11179
11180         sync; sleep 1
11181
11182         # if we aren't already remounting for each test, do so for this test
11183         if [ "$I_MOUNTED" = "yes" ]; then
11184                 cleanup || error "failed to unmount"
11185                 setup
11186         fi
11187
11188         save_layout_restore_at_exit $MOUNT
11189
11190         $LFS setstripe -d $MOUNT || error "setstripe failed"
11191 }
11192 run_test 65j "set default striping on root directory (bug 6367)="
11193
11194 cleanup_65k() {
11195         rm -rf $DIR/$tdir
11196         wait_delete_completed
11197         do_facet $SINGLEMDS "lctl set_param -n \
11198                 osp.$ost*MDT0000.max_create_count=$max_count"
11199         do_facet $SINGLEMDS "lctl set_param -n \
11200                 osp.$ost*MDT0000.create_count=$count"
11201         do_facet $SINGLEMDS lctl --device  %$INACTIVE_OSC activate
11202         echo $INACTIVE_OSC "is Activate"
11203
11204         wait_osc_import_state mds ost$(( ostnum + 1 )) FULL
11205 }
11206
11207 test_65k() { # bug11679
11208         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11209         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
11210         remote_mds_nodsh && skip "remote MDS with nodsh"
11211
11212         local disable_precreate=true
11213         [ $MDS1_VERSION -le $(version_code 2.8.54) ] &&
11214                 disable_precreate=false
11215
11216         echo "Check OST status: "
11217         local MDS_OSCS=$(do_facet $SINGLEMDS lctl dl |
11218                 awk '/[oO][sS][cC].*md[ts]/ { print $4 }')
11219
11220         for OSC in $MDS_OSCS; do
11221                 echo $OSC "is active"
11222                 do_facet $SINGLEMDS lctl --device %$OSC activate
11223         done
11224
11225         for INACTIVE_OSC in $MDS_OSCS; do
11226                 local ost=$(osc_to_ost $INACTIVE_OSC)
11227                 local ostnum=$(do_facet $SINGLEMDS lctl get_param -n \
11228                                lov.*md*.target_obd |
11229                                awk -F: /$ost/'{ print $1 }' | head -n 1)
11230
11231                 mkdir -p $DIR/$tdir
11232                 $LFS setstripe -i $ostnum -c 1 $DIR/$tdir
11233                 createmany -o $DIR/$tdir/$tfile.$ostnum. 1000
11234
11235                 echo "Deactivate: " $INACTIVE_OSC
11236                 do_facet $SINGLEMDS lctl --device %$INACTIVE_OSC deactivate
11237
11238                 local count=$(do_facet $SINGLEMDS "lctl get_param -n \
11239                               osp.$ost*MDT0000.create_count")
11240                 local max_count=$(do_facet $SINGLEMDS "lctl get_param -n \
11241                                   osp.$ost*MDT0000.max_create_count")
11242                 $disable_precreate &&
11243                         do_facet $SINGLEMDS "lctl set_param -n \
11244                                 osp.$ost*MDT0000.max_create_count=0"
11245
11246                 for idx in $(seq 0 $((OSTCOUNT - 1))); do
11247                         [ -f $DIR/$tdir/$idx ] && continue
11248                         echo "$LFS setstripe -i $idx -c 1 $DIR/$tdir/$idx"
11249                         $LFS setstripe -i $idx -c 1 $DIR/$tdir/$idx ||
11250                                 { cleanup_65k;
11251                                   error "setstripe $idx should succeed"; }
11252                         rm -f $DIR/$tdir/$idx || error "rm $idx failed"
11253                 done
11254                 unlinkmany $DIR/$tdir/$tfile.$ostnum. 1000
11255                 rmdir $DIR/$tdir
11256
11257                 do_facet $SINGLEMDS "lctl set_param -n \
11258                         osp.$ost*MDT0000.max_create_count=$max_count"
11259                 do_facet $SINGLEMDS "lctl set_param -n \
11260                         osp.$ost*MDT0000.create_count=$count"
11261                 do_facet $SINGLEMDS lctl --device  %$INACTIVE_OSC activate
11262                 echo $INACTIVE_OSC "is Activate"
11263
11264                 wait_osc_import_state mds ost$(( ostnum + 1 )) FULL
11265         done
11266 }
11267 run_test 65k "validate manual striping works properly with deactivated OSCs"
11268
11269 test_65l() { # bug 12836
11270         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11271
11272         test_mkdir -p $DIR/$tdir/test_dir
11273         $LFS setstripe -c -1 $DIR/$tdir/test_dir
11274         $LFS find -mtime -1 $DIR/$tdir >/dev/null
11275 }
11276 run_test 65l "lfs find on -1 stripe dir ========================"
11277
11278 test_65m() {
11279         local layout=$(save_layout $MOUNT)
11280         $RUNAS $LFS setstripe -c 2 $MOUNT && {
11281                 restore_layout $MOUNT $layout
11282                 error "setstripe should fail by non-root users"
11283         }
11284         true
11285 }
11286 run_test 65m "normal user can't set filesystem default stripe"
11287
11288 test_65n() {
11289         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
11290         [[ $MDS1_VERSION -ge $(version_code 2.12.50) ]] ||
11291                 skip "Need MDS version at least 2.12.50"
11292         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
11293
11294         [[ $OSTCOUNT -ge 2 ]] || skip_env "needs >= 2 OSTs"
11295         which getfattr > /dev/null 2>&1 || skip_env "no getfattr command"
11296         which setfattr > /dev/null 2>&1 || skip_env "no setfattr command"
11297
11298         save_layout_restore_at_exit $MOUNT
11299
11300         # new subdirectory under root directory should not inherit
11301         # the default layout from root
11302         # LU-16904 check if the root is set as PFL layout
11303         local numcomp=$($LFS getstripe --component-count $MOUNT)
11304
11305         if [[ $numcomp -eq 0 ]]; then
11306                 local dir1=$MOUNT/$tdir-1
11307                 mkdir $dir1 || error "mkdir $dir1 failed"
11308                 ! getfattr -n trusted.lov $dir1 &> /dev/null ||
11309                         error "$dir1 shouldn't have LOV EA"
11310         fi
11311
11312         # delete the default layout on root directory
11313         $LFS setstripe -d $MOUNT || error "delete root default layout failed"
11314
11315         local dir2=$MOUNT/$tdir-2
11316         mkdir $dir2 || error "mkdir $dir2 failed"
11317         ! getfattr -n trusted.lov $dir2 &> /dev/null ||
11318                 error "$dir2 shouldn't have LOV EA"
11319
11320         # set a new striping pattern on root directory
11321         local def_stripe_size=$($LFS getstripe -S $MOUNT)
11322         local new_def_stripe_size=$((def_stripe_size * 2))
11323         $LFS setstripe -S $new_def_stripe_size $MOUNT ||
11324                 error "set stripe size on $MOUNT failed"
11325
11326         # new file created in $dir2 should inherit the new stripe size from
11327         # the filesystem default
11328         local file2=$dir2/$tfile-2
11329         touch $file2 || error "touch $file2 failed"
11330
11331         local file2_stripe_size=$($LFS getstripe -S $file2)
11332         [[ $file2_stripe_size -eq $new_def_stripe_size ]] ||
11333         {
11334                 echo "file2_stripe_size: '$file2_stripe_size'"
11335                 echo "new_def_stripe_size: '$new_def_stripe_size'"
11336                 error "$file2 didn't inherit stripe size $new_def_stripe_size"
11337         }
11338
11339         local dir3=$MOUNT/$tdir-3
11340         mkdir $dir3 || error "mkdir $dir3 failed"
11341         # $dir3 shouldn't have LOV EA, but "lfs getstripe -d $dir3" should show
11342         # the root layout, which is the actual default layout that will be used
11343         # when new files are created in $dir3.
11344         local dir3_layout=$(get_layout_param $dir3)
11345         local root_dir_layout=$(get_layout_param $MOUNT)
11346         [[ "$dir3_layout" = "$root_dir_layout" ]] ||
11347         {
11348                 echo "dir3_layout: '$dir3_layout'"
11349                 echo "root_dir_layout: '$root_dir_layout'"
11350                 error "$dir3 should show the default layout from $MOUNT"
11351         }
11352
11353         # set OST pool on root directory
11354         local pool=$TESTNAME
11355         pool_add $pool || error "add $pool failed"
11356         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
11357                 error "add targets to $pool failed"
11358
11359         $LFS setstripe -p $pool $MOUNT ||
11360                 error "set OST pool on $MOUNT failed"
11361
11362         # new file created in $dir3 should inherit the pool from
11363         # the filesystem default
11364         local file3=$dir3/$tfile-3
11365         touch $file3 || error "touch $file3 failed"
11366
11367         local file3_pool=$($LFS getstripe -p $file3)
11368         [[ "$file3_pool" = "$pool" ]] ||
11369                 error "$file3 ('$file3_pool') didn't inherit OST pool '$pool'"
11370
11371         local dir4=$MOUNT/$tdir-4
11372         mkdir $dir4 || error "mkdir $dir4 failed"
11373         local dir4_layout=$(get_layout_param $dir4)
11374         root_dir_layout=$(get_layout_param $MOUNT)
11375         echo "$LFS getstripe -d $dir4"
11376         $LFS getstripe -d $dir4
11377         echo "$LFS getstripe -d $MOUNT"
11378         $LFS getstripe -d $MOUNT
11379         [[ "$dir4_layout" = "$root_dir_layout" ]] ||
11380         {
11381                 echo "dir4_layout: '$dir4_layout'"
11382                 echo "root_dir_layout: '$root_dir_layout'"
11383                 error "$dir4 should show the default layout from $MOUNT"
11384         }
11385
11386         # new file created in $dir4 should inherit the pool from
11387         # the filesystem default
11388         local file4=$dir4/$tfile-4
11389         touch $file4 || error "touch $file4 failed"
11390
11391         local file4_pool=$($LFS getstripe -p $file4)
11392         [[ "$file4_pool" = "$pool" ]] ||
11393                 error "$file4 ('$file4_pool') didn't inherit OST pool $pool"
11394
11395         # new subdirectory under non-root directory should inherit
11396         # the default layout from its parent directory
11397         $LFS setstripe -S $new_def_stripe_size -p $pool $dir4 ||
11398                 error "set directory layout on $dir4 failed"
11399
11400         local dir5=$dir4/$tdir-5
11401         mkdir $dir5 || error "mkdir $dir5 failed"
11402
11403         dir4_layout=$(get_layout_param $dir4)
11404         local dir5_layout=$(get_layout_param $dir5)
11405         [[ "$dir4_layout" = "$dir5_layout" ]] ||
11406         {
11407                 echo "dir4_layout: '$dir4_layout'"
11408                 echo "dir5_layout: '$dir5_layout'"
11409                 error "$dir5 should inherit the default layout from $dir4"
11410         }
11411
11412         # though subdir under ROOT doesn't inherit default layout, but
11413         # its sub dir/file should be created with default layout.
11414         [[ $MDSCOUNT -ge 2 ]] || skip_env "needs >= 2 MDTs"
11415         [[ $MDS1_VERSION -ge $(version_code 2.12.59) ]] ||
11416                 skip "Need MDS version at least 2.12.59"
11417
11418         local default_lmv_count=$($LFS getdirstripe -D -c $MOUNT)
11419         local default_lmv_index=$($LFS getdirstripe -D -i $MOUNT)
11420         local default_lmv_hash=$($LFS getdirstripe -D -H $MOUNT)
11421
11422         if [ $default_lmv_hash == "none" ]; then
11423                 stack_trap "$LFS setdirstripe -D -d $MOUNT" EXIT
11424         else
11425                 stack_trap "$LFS setdirstripe -D -i $default_lmv_index \
11426                         -c $default_lmv_count -H $default_lmv_hash $MOUNT" EXIT
11427         fi
11428
11429         $LFS setdirstripe -D -c 2 $MOUNT ||
11430                 error "setdirstripe -D -c 2 failed"
11431         mkdir $MOUNT/$tdir-6 || error "mkdir $tdir-6 failed"
11432         local lmv_count=$($LFS getdirstripe -c $MOUNT/$tdir-6)
11433         [ $lmv_count -eq 2 ] || error "$tdir-6 stripe count $lmv_count"
11434
11435         (( $MDS1_VERSION >= $(version_code v2_14_57-22-g6e59408f1a) )) ||
11436                 skip "Need MDS >= 2.14.57.22 for proper pool inheritance"
11437         # $dir4 layout includes pool
11438         $LFS setstripe -S $((new_def_stripe_size * 2)) $dir4
11439         [[ "$pool" = $($LFS getstripe -p -d $dir4) ]] ||
11440                 error "pool lost on setstripe"
11441         $LFS setstripe -E -1 -S $new_def_stripe_size $dir4
11442         [[ "$pool" = $($LFS getstripe -p -d $dir4) ]] ||
11443                 error "pool lost on compound layout setstripe"
11444 }
11445 run_test 65n "don't inherit default layout from root for new subdirectories"
11446
11447 test_65o() {
11448         (( $MDS1_VERSION >= $(version_code 2.14.57) )) ||
11449                 skip "need MDS version at least 2.14.57"
11450
11451         # set OST pool on root directory
11452         local pool=$TESTNAME
11453
11454         pool_add $pool || error "add $pool failed"
11455         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
11456                 error "add targets to $pool failed"
11457
11458         local dir1=$MOUNT/$tdir
11459
11460         mkdir $dir1 || error "mkdir $dir1 failed"
11461
11462         # set a new striping pattern on root directory
11463         local def_stripe_size=$($LFS getstripe -S $MOUNT)
11464
11465         $LFS setstripe -p $pool $dir1 ||
11466                 error "set directory layout on $dir1 failed"
11467
11468         # $dir1 layout includes pool
11469         $LFS setstripe -S $((def_stripe_size * 2)) $dir1
11470         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
11471                 error "pool lost on setstripe"
11472         $LFS setstripe -E 1M -L mdt -E -1 -c 1 $dir1
11473         $LFS getstripe $dir1
11474         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
11475                 error "pool lost on compound layout setstripe"
11476
11477         $LFS setdirstripe -i 0 -c 2 $dir1/dir2 ||
11478                 error "setdirstripe failed on sub-dir with inherited pool"
11479         $LFS getstripe $dir1/dir2
11480         [[ "$pool" = $($LFS getstripe -p -d $dir1/dir2) ]] ||
11481                 error "pool lost on compound layout setdirstripe"
11482
11483         $LFS setstripe -E -1 -c 1 $dir1
11484         $LFS getstripe -d $dir1
11485         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
11486                 error "pool lost on setstripe"
11487 }
11488 run_test 65o "pool inheritance for mdt component"
11489
11490 test_65p () { # LU-16152
11491         local src_dir=$DIR/$tdir/src_dir
11492         local dst_dir=$DIR/$tdir/dst_dir
11493         local yaml_file=$DIR/$tdir/layout.yaml
11494         local border
11495
11496         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) ||
11497                 skip "Need at least version 2.15.51"
11498
11499         test_mkdir -p $src_dir
11500         $LFS setstripe -E 2048M -c 4 -E EOF -c 8 $src_dir ||
11501                 error "failed to setstripe"
11502         $LFS getstripe --yaml -d $src_dir > $yaml_file ||
11503                 error "failed to getstripe"
11504
11505         test_mkdir -p $dst_dir
11506         $LFS setstripe --yaml $yaml_file $dst_dir ||
11507                 error "failed to setstripe with yaml file"
11508         border=$($LFS getstripe -d $dst_dir |
11509                 awk '/lcme_extent.e_end:/ { print $2; exit; }') ||
11510                 error "failed to getstripe"
11511
11512         # 2048M is 0x80000000, or 2147483648
11513         (( $border == 2147483648 )) ||
11514                 error "failed to handle huge number in yaml layout"
11515 }
11516 run_test 65p "setstripe with yaml file and huge number"
11517
11518 test_65q () { # LU-16194
11519         local src_dir=$DIR/$tdir/src_dir
11520
11521         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) &&
11522         (( $MDS1_VERSION >= $(version_code 2.15.51) )) ||
11523                 skip "Need at least version 2.15.51"
11524
11525         test_mkdir -p $src_dir
11526         # 8E is 0x8000 0000 0000 0000, which is negative as s64
11527         $LFS setstripe -E 8E -c 4 -E EOF -c 8 $src_dir &&
11528                 error "should fail if extent start/end >=8E"
11529
11530         # EOF should work as before
11531         $LFS setstripe -E 8M -c 4 -E EOF -c 8 $src_dir ||
11532                 error "failed to setstripe normally"
11533 }
11534 run_test 65q "setstripe with >=8E offset should fail"
11535
11536 65r_check_offsets() {
11537         local offsets
11538         local all_zeroes=1
11539         local pfl=$1
11540
11541         offsets=$($LFS getstripe -y $pfl | awk '/stripe_offset:/ { print $2 }')
11542         for off in ${offsets[@]}; do
11543                 ((off == 0)) || all_zeroes=0
11544         done
11545         echo $all_zeroes
11546 }
11547
11548 test_65r() { #LU-13062
11549         (( OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
11550
11551         local dir=$DIR/$tdir
11552         local pfl=$DIR/$tdir/$tfile
11553
11554         test_mkdir -p $DIR/$tdir
11555         # lfs setstripe can set all 0 offsets directly
11556         $LFS setstripe -E1m -c1 -i0 -E2m -c2 -i0 -E4m -c4 -i0 -E -1 -i0 $pfl ||
11557                 error "Create file $pfl failed"
11558         (( $(65r_check_offsets $pfl) == 1 )) ||
11559                 error "lfs setstripe directions are ignored"
11560
11561         # lfs setstripe --copy should reset specified offsets to default
11562         lfs setstripe --copy=$pfl ${pfl}.copy ||
11563                 error "lfs setstripe --copy failed"
11564         (( $(65r_check_offsets ${pfl}.copy) == 0 )) ||
11565                 error "lfs setstripe --copy keeps specific offsets"
11566
11567         # directory layout copy should drop specific offsets
11568         $LFS setstripe -E1m -c1 -i0 -E2m -c2 -i0 -E4m -c4 -i0 -E -1 -i0 $dir ||
11569                 error "Failed to set default layout for $dir"
11570         lfs setstripe --copy=$dir ${pfl}.dircopy ||
11571                 error "lfs setstripe --copy from directory failed"
11572         (( $(65r_check_offsets ${pfl}.dircopy) == 0 )) ||
11573                 error "lfs setstripe --copy for directory keeps offsets"
11574 }
11575 run_test 65r "prevent all-zero offsets"
11576
11577 # bug 2543 - update blocks count on client
11578 test_66() {
11579         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11580
11581         local COUNT=${COUNT:-8}
11582         dd if=/dev/urandom of=$DIR/f66 bs=1k count=$COUNT
11583         sync; sync_all_data; sync; sync_all_data
11584         cancel_lru_locks osc
11585         local BLOCKS=$(ls -s --block-size=1k $DIR/f66 | awk '{ print $1 }')
11586         (( BLOCKS >= COUNT )) || error "$DIR/f66 blocks $BLOCKS < $COUNT"
11587 }
11588 run_test 66 "update inode blocks count on client ==============="
11589
11590 meminfo() {
11591         awk '($1 == "'$1':") { print $2 }' /proc/meminfo
11592 }
11593
11594 swap_used() {
11595         swapon -s | awk '($1 == "'$1'") { print $4 }'
11596 }
11597
11598 # bug5265, obdfilter oa2dentry return -ENOENT
11599 # #define OBD_FAIL_SRV_ENOENT 0x217
11600 test_69() {
11601         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11602         remote_ost_nodsh && skip "remote OST with nodsh"
11603
11604         f="$DIR/$tfile"
11605         $LFS setstripe -c 1 -i 0 $f
11606         stack_trap "rm -f $f ${f}.2"
11607
11608         $DIRECTIO write ${f}.2 0 1 || error "directio write error"
11609
11610         do_facet ost1 lctl set_param fail_loc=0x217
11611         $TRUNCATE $f 1 # vmtruncate() will ignore truncate() error.
11612         $DIRECTIO write $f 0 2 && error "write succeeded, expect -ENOENT"
11613
11614         do_facet ost1 lctl set_param fail_loc=0
11615         $DIRECTIO write $f 0 2 || error "write error"
11616
11617         cancel_lru_locks osc
11618         $DIRECTIO read $f 0 1 || error "read error"
11619
11620         do_facet ost1 lctl set_param fail_loc=0x217
11621         $DIRECTIO read $f 1 1 && error "read succeeded, expect -ENOENT"
11622
11623         do_facet ost1 lctl set_param fail_loc=0
11624 }
11625 run_test 69 "verify oa2dentry return -ENOENT doesn't LBUG ======"
11626
11627 test_70a() {
11628         # Perform a really simple test of health write and health check
11629         (( $OST1_VERSION >= $(version_code 2.15.59) )) ||
11630                 skip "OSTs < 2.15.59 doesn't have enable_health_write"
11631
11632         local orig_value="$(do_facet ost1 $LCTL get_param -n enable_health_write)"
11633
11634         stack_trap "do_facet ost1 $LCTL set_param enable_health_write $orig_value"
11635
11636         # Test with health write off
11637         do_facet ost1 $LCTL set_param enable_health_write off ||
11638                 error "can't set enable_health_write off"
11639         do_facet ost1 $LCTL get_param enable_health_write ||
11640                 error "can't get enable_health_write"
11641
11642         [[ "$(do_facet ost1 $LCTL get_param health_check)" =~ "healthy" ]] ||
11643                 error "not healthy (1)"
11644
11645         # Test with health write on
11646         do_facet ost1 $LCTL set_param enable_health_write on ||
11647                 error "can't set enable_health_write on"
11648         do_facet ost1 $LCTL get_param enable_health_write ||
11649                 error "can't get enable_health_write"
11650
11651         [[ "$(do_facet ost1 $LCTL get_param health_check)" =~ "healthy" ]] ||
11652                 error "not healthy (2)"
11653 }
11654 run_test 70a "verify health_check, health_write don't explode (on OST)"
11655
11656 test_71() {
11657         test_mkdir $DIR/$tdir
11658         $LFS setdirstripe -D -c$MDSCOUNT $DIR/$tdir
11659         bash rundbench -C -D $DIR/$tdir 2 || error "dbench failed!"
11660 }
11661 run_test 71 "Running dbench on lustre (don't segment fault) ===="
11662
11663 test_72a() { # bug 5695 - Test that on 2.6 remove_suid works properly
11664         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11665         [ "$RUNAS_ID" = "$UID" ] &&
11666                 skip_env "RUNAS_ID = UID = $UID -- skipping"
11667         # Check that testing environment is properly set up. Skip if not
11668         FAIL_ON_ERROR=false check_runas_id_ret $RUNAS_ID $RUNAS_GID $RUNAS ||
11669                 skip_env "User $RUNAS_ID does not exist - skipping"
11670
11671         touch $DIR/$tfile
11672         chmod 777 $DIR/$tfile
11673         chmod ug+s $DIR/$tfile
11674         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=512 count=1 ||
11675                 error "$RUNAS dd $DIR/$tfile failed"
11676         # See if we are still setuid/sgid
11677         [ -u $DIR/$tfile ] || [ -g $DIR/$tfile ] &&
11678                 error "S/gid is not dropped on write"
11679         # Now test that MDS is updated too
11680         cancel_lru_locks mdc
11681         [ -u $DIR/$tfile ] || [ -g $DIR/$tfile ] &&
11682                 error "S/gid is not dropped on MDS"
11683         rm -f $DIR/$tfile
11684 }
11685 run_test 72a "Test that remove suid works properly (bug5695) ===="
11686
11687 test_72b() { # bug 24226 -- keep mode setting when size is not changing
11688         local perm
11689
11690         [ "$RUNAS_ID" = "$UID" ] &&
11691                 skip_env "RUNAS_ID = UID = $UID -- skipping"
11692         [ "$RUNAS_ID" -eq 0 ] &&
11693                 skip_env "RUNAS_ID = 0 -- skipping"
11694         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11695         # Check that testing environment is properly set up. Skip if not
11696         FAIL_ON_ERROR=false check_runas_id_ret $RUNAS_ID $RUNAS_ID $RUNAS ||
11697                 skip_env "User $RUNAS_ID does not exist - skipping"
11698
11699         touch $DIR/${tfile}-f{g,u}
11700         test_mkdir $DIR/${tfile}-dg
11701         test_mkdir $DIR/${tfile}-du
11702         chmod 770 $DIR/${tfile}-{f,d}{g,u}
11703         chmod g+s $DIR/${tfile}-{f,d}g
11704         chmod u+s $DIR/${tfile}-{f,d}u
11705         for perm in 777 2777 4777; do
11706                 $RUNAS chmod $perm $DIR/${tfile}-fg && error "S/gid file allowed improper chmod to $perm"
11707                 $RUNAS chmod $perm $DIR/${tfile}-fu && error "S/uid file allowed improper chmod to $perm"
11708                 $RUNAS chmod $perm $DIR/${tfile}-dg && error "S/gid dir allowed improper chmod to $perm"
11709                 $RUNAS chmod $perm $DIR/${tfile}-du && error "S/uid dir allowed improper chmod to $perm"
11710         done
11711         true
11712 }
11713 run_test 72b "Test that we keep mode setting if without file data changed (bug 24226)"
11714
11715 # bug 3462 - multiple simultaneous MDC requests
11716 test_73() {
11717         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11718
11719         test_mkdir $DIR/d73-1
11720         test_mkdir $DIR/d73-2
11721         multiop_bg_pause $DIR/d73-1/f73-1 O_c || return 1
11722         pid1=$!
11723
11724         lctl set_param fail_loc=0x80000129
11725         $MULTIOP $DIR/d73-1/f73-2 Oc &
11726         sleep 1
11727         lctl set_param fail_loc=0
11728
11729         $MULTIOP $DIR/d73-2/f73-3 Oc &
11730         pid3=$!
11731
11732         kill -USR1 $pid1
11733         wait $pid1 || return 1
11734
11735         sleep 25
11736
11737         $CHECKSTAT -t file $DIR/d73-1/f73-1 || return 4
11738         $CHECKSTAT -t file $DIR/d73-1/f73-2 || return 5
11739         $CHECKSTAT -t file $DIR/d73-2/f73-3 || return 6
11740
11741         rm -rf $DIR/d73-*
11742 }
11743 run_test 73 "multiple MDC requests (should not deadlock)"
11744
11745 test_74a() { # bug 6149, 6184
11746         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11747
11748         touch $DIR/f74a
11749         #define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
11750         #
11751         # very important to OR with CFS_FAIL_ONCE (0x80000000) -- otherwise it
11752         # will spin in a tight reconnection loop
11753         $LCTL set_param fail_loc=0x8000030e
11754         # get any lock that won't be difficult - lookup works.
11755         ls $DIR/f74a
11756         $LCTL set_param fail_loc=0
11757         rm -f $DIR/f74a
11758         true
11759 }
11760 run_test 74a "ldlm_enqueue freed-export error path, ls (shouldn't LBUG)"
11761
11762 test_74b() { # bug 13310
11763         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11764
11765         #define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
11766         #
11767         # very important to OR with CFS_FAIL_ONCE (0x80000000) -- otherwise it
11768         # will spin in a tight reconnection loop
11769         $LCTL set_param fail_loc=0x8000030e
11770         # get a "difficult" lock
11771         touch $DIR/f74b
11772         $LCTL set_param fail_loc=0
11773         rm -f $DIR/f74b
11774         true
11775 }
11776 run_test 74b "ldlm_enqueue freed-export error path, touch (shouldn't LBUG)"
11777
11778 test_74c() {
11779         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11780
11781         #define OBD_FAIL_LDLM_NEW_LOCK
11782         $LCTL set_param fail_loc=0x319
11783         touch $DIR/$tfile && error "touch successful"
11784         $LCTL set_param fail_loc=0
11785         true
11786 }
11787 run_test 74c "ldlm_lock_create error path, (shouldn't LBUG)"
11788
11789 slab_lic=/sys/kernel/slab/lustre_inode_cache
11790 num_objects() {
11791         [ -f $slab_lic/shrink ] && echo 1 > $slab_lic/shrink
11792         [ -f $slab_lic/objects ] && awk '{ print $1 }' $slab_lic/objects ||
11793                 awk '/lustre_inode_cache/ { print $2; exit }' /proc/slabinfo
11794 }
11795
11796 test_76a() { # Now for b=20433, added originally in b=1443
11797         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11798
11799         cancel_lru_locks osc
11800         # there may be some slab objects cached per core
11801         local cpus=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
11802         local before=$(num_objects)
11803         local count=$((512 * cpus))
11804         [ "$SLOW" = "no" ] && count=$((128 * cpus))
11805         local margin=$((count / 10))
11806         if [[ -f $slab_lic/aliases ]]; then
11807                 local aliases=$(cat $slab_lic/aliases)
11808                 (( aliases > 0 )) && margin=$((margin * aliases))
11809         fi
11810
11811         echo "before slab objects: $before"
11812         for i in $(seq $count); do
11813                 touch $DIR/$tfile
11814                 rm -f $DIR/$tfile
11815         done
11816         cancel_lru_locks osc
11817         local after=$(num_objects)
11818         echo "created: $count, after slab objects: $after"
11819         # shared slab counts are not very accurate, allow significant margin
11820         # the main goal is that the cache growth is not permanently > $count
11821         while (( after > before + margin )); do
11822                 sleep 1
11823                 after=$(num_objects)
11824                 wait=$((wait + 1))
11825                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
11826                 if (( wait > 60 )); then
11827                         error "inode slab grew from $before+$margin to $after"
11828                 fi
11829         done
11830 }
11831 run_test 76a "confirm clients recycle inodes properly ===="
11832
11833 test_76b() {
11834         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11835         [ $CLIENT_VERSION -ge $(version_code 2.13.55) ] || skip "not supported"
11836
11837         local count=512
11838         local before=$(num_objects)
11839
11840         for i in $(seq $count); do
11841                 mkdir $DIR/$tdir
11842                 rmdir $DIR/$tdir
11843         done
11844
11845         local after=$(num_objects)
11846         local wait=0
11847
11848         while (( after > before )); do
11849                 sleep 1
11850                 after=$(num_objects)
11851                 wait=$((wait + 1))
11852                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
11853                 if (( wait > 60 )); then
11854                         error "inode slab grew from $before to $after"
11855                 fi
11856         done
11857
11858         echo "slab objects before: $before, after: $after"
11859 }
11860 run_test 76b "confirm clients recycle directory inodes properly ===="
11861
11862 export ORIG_CSUM=""
11863 set_checksums()
11864 {
11865         # Note: in sptlrpc modes which enable its own bulk checksum, the
11866         # original crc32_le bulk checksum will be automatically disabled,
11867         # and the OBD_FAIL_OSC_CHECKSUM_SEND/OBD_FAIL_OSC_CHECKSUM_RECEIVE
11868         # will be checked by sptlrpc code against sptlrpc bulk checksum.
11869         # In this case set_checksums() will not be no-op, because sptlrpc
11870         # bulk checksum will be enabled all through the test.
11871
11872         [ "$ORIG_CSUM" ] || ORIG_CSUM=`lctl get_param -n osc.*.checksums | head -n1`
11873         lctl set_param -n osc.*.checksums $1
11874         return 0
11875 }
11876
11877 export ORIG_CSUM_TYPE="`lctl get_param -n osc.*osc-[^mM]*.checksum_type |
11878                         sed 's/.*\[\(.*\)\].*/\1/g' | head -n1`"
11879 CKSUM_TYPES=${CKSUM_TYPES:-$(lctl get_param -n osc.*osc-[^mM]*.checksum_type |
11880                              tr -d [] | head -n1)}
11881 set_checksum_type()
11882 {
11883         lctl set_param -n osc.*osc-[^mM]*.checksum_type $1
11884         rc=$?
11885         log "set checksum type to $1, rc = $rc"
11886         return $rc
11887 }
11888
11889 get_osc_checksum_type()
11890 {
11891         # arugment 1: OST name, like OST0000
11892         ost=$1
11893         checksum_type=$(lctl get_param -n osc.*${ost}-osc-[^mM]*.checksum_type |
11894                         sed 's/.*\[\(.*\)\].*/\1/g')
11895         rc=$?
11896         [ $rc -ne 0 ] && error "failed to get checksum type of $ost, rc = $rc, output = $checksum_type"
11897         echo $checksum_type
11898 }
11899
11900 F77_TMP=$TMP/f77-temp
11901 F77SZ=8
11902 setup_f77() {
11903         dd if=/dev/urandom of=$F77_TMP bs=1M count=$F77SZ || \
11904                 error "error writing to $F77_TMP"
11905 }
11906
11907 test_77a() { # bug 10889
11908         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11909         $GSS && skip_env "could not run with gss"
11910
11911         [ ! -f $F77_TMP ] && setup_f77
11912         set_checksums 1
11913         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ || error "dd error"
11914         set_checksums 0
11915         rm -f $DIR/$tfile
11916 }
11917 run_test 77a "normal checksum read/write operation"
11918
11919 test_77b() { # bug 10889
11920         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11921         $GSS && skip_env "could not run with gss"
11922
11923         [ ! -f $F77_TMP ] && setup_f77
11924         #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
11925         $LCTL set_param fail_loc=0x80000409
11926         set_checksums 1
11927
11928         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ conv=sync ||
11929                 error "dd error: $?"
11930         $LCTL set_param fail_loc=0
11931
11932         for algo in $CKSUM_TYPES; do
11933                 cancel_lru_locks osc
11934                 set_checksum_type $algo
11935                 #define OBD_FAIL_OSC_CHECKSUM_RECEIVE    0x408
11936                 $LCTL set_param fail_loc=0x80000408
11937                 cmp $F77_TMP $DIR/$tfile || error "file compare failed"
11938                 $LCTL set_param fail_loc=0
11939         done
11940         set_checksums 0
11941         set_checksum_type $ORIG_CSUM_TYPE
11942         rm -f $DIR/$tfile
11943 }
11944 run_test 77b "checksum error on client write, read"
11945
11946 cleanup_77c() {
11947         trap 0
11948         set_checksums 0
11949         $LCTL set_param osc.*osc-[^mM]*.checksum_dump=0
11950         $check_ost &&
11951                 do_facet ost1 $LCTL set_param obdfilter.*-OST*.checksum_dump=0
11952         [ -n "$osc_file_prefix" ] && rm -f ${osc_file_prefix}*
11953         $check_ost && [ -n "$ost_file_prefix" ] &&
11954                 do_facet ost1 rm -f ${ost_file_prefix}\*
11955 }
11956
11957 test_77c() {
11958         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11959         $GSS && skip_env "could not run with gss"
11960         remote_ost_nodsh && skip "remote OST with nodsh"
11961
11962         local bad1
11963         local osc_file_prefix
11964         local osc_file
11965         local check_ost=false
11966         local ost_file_prefix="$TMP/lustre-log"
11967         local ost_file
11968         local orig_cksum
11969         local dump_cksum
11970         local fid
11971         local old_ost_path=$(do_facet ost1 $LCTL get_param -n debug_path)
11972
11973         stack_trap "do_facet ost1 $LCTL set_param debug_path=$old_ost_path"
11974         do_facet ost1 $LCTL set_param debug_path=${ost_file_prefix}
11975
11976         # ensure corruption will occur on first OSS/OST
11977         $LFS setstripe -i 0 $DIR/$tfile
11978
11979         [ ! -f $F77_TMP ] && setup_f77
11980         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ conv=sync ||
11981                 error "dd write error: $?"
11982         fid=$($LFS path2fid $DIR/$tfile)
11983
11984         if [ $OST1_VERSION -ge $(version_code 2.9.57) ]
11985         then
11986                 check_ost=true
11987                 ost_file_prefix=${ost_file_prefix}-checksum_dump-ost-\\${fid}
11988         else
11989                 echo "OSS do not support bulk pages dump upon error"
11990         fi
11991
11992         osc_file_prefix=$($LCTL get_param -n debug_path)
11993         osc_file_prefix=${osc_file_prefix}-checksum_dump-osc-\\${fid}
11994
11995         trap cleanup_77c EXIT
11996
11997         set_checksums 1
11998         # enable bulk pages dump upon error on Client
11999         $LCTL set_param osc.*osc-[^mM]*.checksum_dump=1
12000         # enable bulk pages dump upon error on OSS
12001         $check_ost &&
12002                 do_facet ost1 $LCTL set_param obdfilter.*-OST*.checksum_dump=1
12003
12004         # flush Client cache to allow next read to reach OSS
12005         cancel_lru_locks osc
12006
12007         #define OBD_FAIL_OSC_CHECKSUM_RECEIVE       0x408
12008         $LCTL set_param fail_loc=0x80000408
12009         dd if=$DIR/$tfile of=/dev/null bs=1M || error "dd read error: $?"
12010         $LCTL set_param fail_loc=0
12011
12012         rm -f $DIR/$tfile
12013
12014         # check cksum dump on Client
12015         osc_file=$(ls ${osc_file_prefix}*)
12016         [ -n "$osc_file" ] || error "no checksum dump file on Client"
12017         # OBD_FAIL_OSC_CHECKSUM_RECEIVE corrupts with "bad1" at start of file
12018         bad1=$(dd if=$osc_file bs=1 count=4 2>/dev/null) || error "dd error: $?"
12019         [ $bad1 == "bad1" ] || error "unexpected corrupt pattern"
12020         orig_cksum=$(dd if=$F77_TMP bs=1 skip=4 count=1048572 2>/dev/null |
12021                      cksum)
12022         dump_cksum=$(dd if=$osc_file bs=1 skip=4 2>/dev/null | cksum)
12023         [[ "$orig_cksum" == "$dump_cksum" ]] ||
12024                 error "dump content does not match on Client"
12025
12026         $check_ost || skip "No need to check cksum dump on OSS"
12027
12028         # check cksum dump on OSS
12029         ost_file=$(do_facet ost1 ls ${ost_file_prefix}\*)
12030         [ -n "$ost_file" ] || error "no checksum dump file on OSS"
12031         orig_cksum=$(dd if=$F77_TMP bs=1048576 count=1 2>/dev/null | cksum)
12032         dump_cksum=$(do_facet ost1 dd if=$ost_file 2>/dev/null \| cksum)
12033         [[ "$orig_cksum" == "$dump_cksum" ]] ||
12034                 error "dump content does not match on OSS"
12035
12036         cleanup_77c
12037 }
12038 run_test 77c "checksum error on client read with debug"
12039
12040 test_77d() { # bug 10889
12041         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12042         $GSS && skip_env "could not run with gss"
12043
12044         stack_trap "rm -f $DIR/$tfile"
12045         #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
12046         $LCTL set_param fail_loc=0x80000409
12047         set_checksums 1
12048         $DIRECTIO write $DIR/$tfile 0 $F77SZ $((1024 * 1024)) ||
12049                 error "direct write: rc=$?"
12050         $LCTL set_param fail_loc=0
12051         set_checksums 0
12052
12053         #define OBD_FAIL_OSC_CHECKSUM_RECEIVE    0x408
12054         $LCTL set_param fail_loc=0x80000408
12055         set_checksums 1
12056         cancel_lru_locks osc
12057         $DIRECTIO read $DIR/$tfile 0 $F77SZ $((1024 * 1024)) ||
12058                 error "direct read: rc=$?"
12059         $LCTL set_param fail_loc=0
12060         set_checksums 0
12061 }
12062 run_test 77d "checksum error on OST direct write, read"
12063
12064 test_77f() { # bug 10889
12065         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12066         $GSS && skip_env "could not run with gss"
12067
12068         set_checksums 1
12069         stack_trap "rm -f $DIR/$tfile"
12070         for algo in $CKSUM_TYPES; do
12071                 cancel_lru_locks osc
12072                 set_checksum_type $algo
12073                 #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
12074                 $LCTL set_param fail_loc=0x409
12075                 $DIRECTIO write $DIR/$tfile 0 $F77SZ $((1024 * 1024)) &&
12076                         error "direct write succeeded"
12077                 $LCTL set_param fail_loc=0
12078         done
12079         set_checksum_type $ORIG_CSUM_TYPE
12080         set_checksums 0
12081 }
12082 run_test 77f "repeat checksum error on write (expect error)"
12083
12084 test_77g() { # bug 10889
12085         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12086         $GSS && skip_env "could not run with gss"
12087         remote_ost_nodsh && skip "remote OST with nodsh"
12088
12089         [ ! -f $F77_TMP ] && setup_f77
12090
12091         local file=$DIR/$tfile
12092         stack_trap "rm -f $file" EXIT
12093
12094         $LFS setstripe -c 1 -i 0 $file
12095         #define OBD_FAIL_OST_CHECKSUM_RECEIVE       0x21a
12096         do_facet ost1 lctl set_param fail_loc=0x8000021a
12097         set_checksums 1
12098         dd if=$F77_TMP of=$file bs=1M count=$F77SZ ||
12099                 error "write error: rc=$?"
12100         do_facet ost1 lctl set_param fail_loc=0
12101         set_checksums 0
12102
12103         cancel_lru_locks osc
12104         #define OBD_FAIL_OST_CHECKSUM_SEND          0x21b
12105         do_facet ost1 lctl set_param fail_loc=0x8000021b
12106         set_checksums 1
12107         cmp $F77_TMP $file || error "file compare failed"
12108         do_facet ost1 lctl set_param fail_loc=0
12109         set_checksums 0
12110 }
12111 run_test 77g "checksum error on OST write, read"
12112
12113 test_77k() { # LU-10906
12114         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12115         $GSS && skip_env "could not run with gss"
12116
12117         local cksum_param="osc.$FSNAME*.checksums"
12118         local get_checksum="$LCTL get_param -n $cksum_param | head -n1"
12119         local checksum
12120         local i
12121
12122         [ "$ORIG_CSUM" ] || ORIG_CSUM=$(eval $get_checksum)
12123         stack_trap "wait_update $HOSTNAME '$get_checksum' $ORIG_CSUM || true"
12124         stack_trap "do_facet mgs $LCTL set_param -P $cksum_param=$ORIG_CSUM"
12125
12126         for i in 0 1; do
12127                 do_facet mgs $LCTL set_param -P $cksum_param=$i ||
12128                         error "failed to set checksum=$i on MGS"
12129                 wait_update $HOSTNAME "$get_checksum" $i
12130                 #remount
12131                 echo "remount client, checksum should be $i"
12132                 remount_client $MOUNT || error "failed to remount client"
12133                 checksum=$(eval $get_checksum)
12134                 [ $checksum -eq $i ] || error "checksum($checksum) != $i"
12135         done
12136         # remove persistent param to avoid races with checksum mountopt below
12137         do_facet mgs $LCTL set_param -P -d $cksum_param ||
12138                 error "failed to delete checksum on MGS"
12139
12140         for opt in "checksum" "nochecksum"; do
12141                 #remount with mount option
12142                 echo "remount client with option $opt, checksum should be $i"
12143                 umount_client $MOUNT || error "failed to umount client"
12144                 mount_client $MOUNT "$MOUNT_OPTS,$opt" ||
12145                         error "failed to mount client with option '$opt'"
12146                 checksum=$(eval $get_checksum)
12147                 [ $checksum -eq $i ] || error "checksum($checksum) != $i"
12148                 i=$((i - 1))
12149         done
12150
12151         remount_client $MOUNT || error "failed to remount client"
12152 }
12153 run_test 77k "enable/disable checksum correctly"
12154
12155 test_77l() {
12156         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12157         $GSS && skip_env "could not run with gss"
12158
12159         set_checksums 1
12160         stack_trap "set_checksums $ORIG_CSUM" EXIT
12161         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
12162         local old
12163
12164         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
12165         $LCTL set_param osc.*.idle_timeout=10
12166         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
12167
12168         set_checksum_type invalid && error "unexpected success of invalid checksum type"
12169
12170         $LFS setstripe -c 1 -i 0 $DIR/$tfile
12171         for algo in $CKSUM_TYPES; do
12172                 set_checksum_type $algo || error "fail to set checksum type $algo"
12173                 osc_algo=$(get_osc_checksum_type OST0000)
12174                 [ "$osc_algo" != "$algo" ] && error "checksum type is $osc_algo after setting it to $algo"
12175
12176                 # no locks, no reqs to let the connection idle
12177                 cancel_lru_locks osc
12178                 lru_resize_disable osc
12179                 wait_osc_import_state client ost1 IDLE
12180
12181                 # ensure ost1 is connected
12182                 stat $DIR/$tfile >/dev/null || error "can't stat"
12183                 wait_osc_import_state client ost1 FULL
12184
12185                 osc_algo=$(get_osc_checksum_type OST0000)
12186                 [ "$osc_algo" != "$algo" ] && error "checksum type changed from $algo to $osc_algo after reconnection"
12187         done
12188         return 0
12189 }
12190 run_test 77l "preferred checksum type is remembered after reconnected"
12191
12192 [ "$ORIG_CSUM" ] && set_checksums $ORIG_CSUM || true
12193 rm -f $F77_TMP
12194 unset F77_TMP
12195
12196 test_77m() {
12197         (( $CLIENT_VERSION >= $(version_code 2.14.52) )) ||
12198                 skip "Need at least version 2.14.52"
12199         local param=checksum_speed
12200
12201         $LCTL get_param $param || error "reading $param failed"
12202
12203         csum_speeds=$($LCTL get_param -n $param)
12204
12205         [[ "$csum_speeds" =~ "adler32" && "$csum_speeds" =~ "crc32" ]] ||
12206                 error "known checksum types are missing"
12207 }
12208 run_test 77m "Verify checksum_speed is correctly read"
12209
12210 check_filefrag_77n() {
12211         local nr_ext=0
12212         local starts=()
12213         local ends=()
12214
12215         while read extidx a b start end rest; do
12216                 if [[ "${extidx}" =~ ^[0-9]+: ]]; then
12217                         nr_ext=$(( $nr_ext + 1 ))
12218                         starts+=( ${start%..} )
12219                         ends+=( ${end%:} )
12220                 fi
12221         done < <( filefrag -sv $1 )
12222
12223         [[ $nr_ext -eq 2 ]] && [[ "${starts[-1]}" == $(( ${ends[0]} + 1 )) ]] && return 0
12224         return 1
12225 }
12226
12227 test_77n() {
12228         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
12229         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
12230         [[ "$CKSUM_TYPES" =~ t10 ]] || skip "no T10 checksum support on osc"
12231
12232         touch $DIR/$tfile
12233         $TRUNCATE $DIR/$tfile 0
12234         dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=0
12235         dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=2
12236         check_filefrag_77n $DIR/$tfile ||
12237                 skip "$tfile blocks not contiguous around hole"
12238
12239         set_checksums 1
12240         stack_trap "set_checksums $ORIG_CSUM" EXIT
12241         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
12242         stack_trap "rm -f $DIR/$tfile"
12243
12244         for algo in $CKSUM_TYPES; do
12245                 if [[ "$algo" =~ ^t10 ]]; then
12246                         set_checksum_type $algo ||
12247                                 error "fail to set checksum type $algo"
12248                         dd if=$DIR/$tfile of=/dev/null bs=12k count=1 iflag=direct ||
12249                                 error "fail to read $tfile with $algo"
12250                 fi
12251         done
12252         rm -f $DIR/$tfile
12253         return 0
12254 }
12255 run_test 77n "Verify read from a hole inside contiguous blocks with T10PI"
12256
12257 test_77o() {
12258         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
12259                 skip "Need MDS version at least 2.14.55"
12260         (( $OST1_VERSION >= $(version_code 2.14.55) )) ||
12261                 skip "Need OST version at least 2.14.55"
12262         local ofd=obdfilter
12263         local mdt=mdt
12264
12265         # print OST checksum_type
12266         echo "$ofd.$FSNAME-*.checksum_type:"
12267         do_nodes $(osts_nodes) "$LCTL get_param -n $ofd.$FSNAME-*.checksum_type"
12268
12269         # print MDT checksum_type
12270         echo "$mdt.$FSNAME-*.checksum_type:"
12271         do_nodes $(comma_list $(mdts_nodes)) \
12272                 $LCTL get_param -n $mdt.$FSNAME-*.checksum_type
12273
12274         local o_count=$(do_nodes $(osts_nodes) \
12275                    $LCTL get_param -n $ofd.$FSNAME-*.checksum_type | wc -l)
12276
12277         (( $o_count == $OSTCOUNT )) ||
12278                 error "found $o_count checksums, not \$OSTCOUNT=$OSTCOUNT"
12279
12280         local m_count=$(do_nodes $(comma_list $(mdts_nodes)) \
12281                    $LCTL get_param -n $mdt.$FSNAME-*.checksum_type | wc -l)
12282
12283         (( $m_count == $MDSCOUNT )) ||
12284                 error "found $m_count checksums, not \$MDSCOUNT=$MDSCOUNT"
12285 }
12286 run_test 77o "Verify checksum_type for server (mdt and ofd(obdfilter))"
12287
12288 cleanup_test_78() {
12289         trap 0
12290         rm -f $DIR/$tfile
12291 }
12292
12293 test_78() { # bug 10901
12294         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12295         remote_ost || skip_env "local OST"
12296
12297         NSEQ=5
12298         F78SIZE=$(($(awk '/MemFree:/ { print $2 }' /proc/meminfo) / 1024))
12299         echo "MemFree: $F78SIZE, Max file size: $MAXFREE"
12300         MEMTOTAL=$(($(awk '/MemTotal:/ { print $2 }' /proc/meminfo) / 1024))
12301         echo "MemTotal: $MEMTOTAL"
12302
12303         # reserve 256MB of memory for the kernel and other running processes,
12304         # and then take 1/2 of the remaining memory for the read/write buffers.
12305         if [ $MEMTOTAL -gt 512 ] ;then
12306                 MEMTOTAL=$(((MEMTOTAL - 256 ) / 2))
12307         else
12308                 # for those poor memory-starved high-end clusters...
12309                 MEMTOTAL=$((MEMTOTAL / 2))
12310         fi
12311         echo "Mem to use for directio: $MEMTOTAL"
12312
12313         [[ $F78SIZE -gt $MEMTOTAL ]] && F78SIZE=$MEMTOTAL
12314         [[ $F78SIZE -gt 512 ]] && F78SIZE=512
12315         [[ $F78SIZE -gt $((MAXFREE / 1024)) ]] && F78SIZE=$((MAXFREE / 1024))
12316         SMALLESTOST=$($LFS df $DIR | grep OST | awk '{ print $4 }' | sort -n |
12317                 head -n1)
12318         echo "Smallest OST: $SMALLESTOST"
12319         [[ $SMALLESTOST -lt 10240 ]] &&
12320                 skip "too small OSTSIZE, useless to run large O_DIRECT test"
12321
12322         trap cleanup_test_78 EXIT
12323
12324         [[ $F78SIZE -gt $((SMALLESTOST * $OSTCOUNT / 1024 - 80)) ]] &&
12325                 F78SIZE=$((SMALLESTOST * $OSTCOUNT / 1024 - 80))
12326
12327         [ "$SLOW" = "no" ] && NSEQ=1 && [ $F78SIZE -gt 32 ] && F78SIZE=32
12328         echo "File size: $F78SIZE"
12329         $LFS setstripe -c $OSTCOUNT $DIR/$tfile || error "setstripe failed"
12330         for i in $(seq 1 $NSEQ); do
12331                 FSIZE=$(($F78SIZE / ($NSEQ - $i + 1)))
12332                 echo directIO rdwr round $i of $NSEQ
12333                 $DIRECTIO rdwr $DIR/$tfile 0 $FSIZE 1048576||error "rdwr failed"
12334         done
12335
12336         cleanup_test_78
12337 }
12338 run_test 78 "handle large O_DIRECT writes correctly ============"
12339
12340 test_79() { # bug 12743
12341         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
12342
12343         wait_delete_completed
12344
12345         local bktotal=$(calc_osc_kbytes kbytestotal)
12346         local bkfree=$(calc_osc_kbytes kbytesfree)
12347         local bkavail=$(calc_osc_kbytes kbytesavail)
12348         local string=($(df -P $MOUNT | tail -n 1))
12349         local dftotal=${string[1]}
12350         local dfused=${string[2]}
12351         local dfavail=${string[3]}
12352         local dffree=$(($dftotal - $dfused))
12353         local allowance=$((64 * $OSTCOUNT))
12354
12355         $LFS df $MOUNT
12356         echo ${string[*]}
12357
12358         (( dftotal >= bktotal - allowance && dftotal <= bktotal + allowance)) ||
12359                 error "df total($dftotal) mismatch OST total($bktotal)"
12360         (( dffree >= bkfree - allowance && dffree <= bkfree + allowance )) ||
12361                 error "df free($dffree) mismatch OST free($bkfree)"
12362         (( dfavail >= bkavail - allowance && dfavail <= bkavail + allowance)) ||
12363                 error "df avail($dfavail) mismatch OST avail($bkavail)"
12364
12365         $LCTL get_param *.$FSNAME-*.{maxbytes,namelen_max}
12366         (( $MDS1_VERSION < $(version_code 2.16.52-70) )) ||
12367                 do_nodes $(mdts_nodes) \
12368                         $LCTL get_param *.$FSNAME-*.{maxbytes,namelen_max}
12369         (( $OST1_VERSION < $(version_code 2.16.52-70) )) ||
12370                 do_nodes $(osts_nodes) \
12371                         $LCTL get_param *.$FSNAME-*.{maxbytes,namelen_max}
12372         local dfnamelen=$(stat -f -c %l $MOUNT)
12373         local lnamelen=($($LCTL get_param -n llite.$FSNAME-*.namelen_max))
12374
12375         (( $dfnamelen == $lnamelen )) ||
12376                 error "df namelen($dfnamelen) != llite namelen($lnamelen)"
12377 }
12378 run_test 79 "df report consistency check"
12379
12380 test_80() { # bug 10718
12381         remote_ost_nodsh && skip "remote OST with nodsh"
12382         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12383
12384         # relax strong synchronous semantics for slow backends like ZFS
12385         if [ "$ost1_FSTYPE" != "ldiskfs" ]; then
12386                 local soc="obdfilter.*.sync_lock_cancel"
12387                 local save=$(do_facet ost1 $LCTL get_param -n $soc | head -n1)
12388
12389                 # "sync_on_lock_cancel" was broken by v2_11_55_0-26-g7059644e9a
12390                 # Fixed in 2.13.51~79, so we'll keep it for interop with 2.12.x
12391                 if [ -z "$save" ]; then
12392                         soc="obdfilter.*.sync_on_lock_cancel"
12393                         save=$(do_facet ost1 $LCTL get_param -n $soc | head -n1)
12394                 fi
12395
12396                 if [ "$save" != "never" ]; then
12397                         local osts=$(osts_nodes)
12398
12399                         do_nodes $osts $LCTL set_param $soc=never
12400                         stack_trap "do_nodes $osts $LCTL set_param $soc=$save"
12401                 fi
12402         fi
12403
12404         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=1M
12405         sync; sleep 1; sync
12406         local before=$(date +%s)
12407         cancel_lru_locks osc
12408         local after=$(date +%s)
12409         local diff=$((after - before))
12410         [ $diff -le 1 ] || error "elapsed for 1M@1T = $diff"
12411
12412         rm -f $DIR/$tfile
12413 }
12414 run_test 80 "Page eviction is equally fast at high offsets too"
12415
12416 test_81a() { # LU-456
12417         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12418         remote_ost_nodsh && skip "remote OST with nodsh"
12419
12420         # define OBD_FAIL_OST_MAPBLK_ENOSPC    0x228
12421         # MUST OR with the CFS_FAIL_ONCE (0x80000000)
12422         do_facet ost1 lctl set_param fail_loc=0x80000228
12423
12424         # write should trigger a retry and success
12425         $LFS setstripe -i 0 -c 1 $DIR/$tfile
12426         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
12427         RC=$?
12428         if [ $RC -ne 0 ] ; then
12429                 error "write should success, but failed for $RC"
12430         fi
12431 }
12432 run_test 81a "OST should retry write when get -ENOSPC ==============="
12433
12434 test_81b() { # LU-456
12435         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12436         remote_ost_nodsh && skip "remote OST with nodsh"
12437
12438         # define OBD_FAIL_OST_MAPBLK_ENOSPC    0x228
12439         # Don't OR with the CFS_FAIL_ONCE (0x80000000)
12440         do_facet ost1 lctl set_param fail_loc=0x228
12441
12442         # write should retry several times and return -ENOSPC finally
12443         $LFS setstripe -i 0 -c 1 $DIR/$tfile
12444         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
12445         RC=$?
12446         ENOSPC=28
12447         if [ $RC -ne $ENOSPC ] ; then
12448                 error "dd should fail for -ENOSPC, but succeed."
12449         fi
12450 }
12451 run_test 81b "OST should return -ENOSPC when retry still fails ======="
12452
12453 test_99() {
12454         [ -z "$(which cvs 2>/dev/null)" ] && skip_env "could not find cvs"
12455
12456         test_mkdir $DIR/$tdir.cvsroot
12457         chown $RUNAS_ID $DIR/$tdir.cvsroot
12458
12459         cd $TMP
12460         $RUNAS cvs -d $DIR/$tdir.cvsroot init || error "cvs init failed"
12461
12462         cd /etc/init.d
12463         # some versions of cvs import exit(1) when asked to import links or
12464         # files they can't read.  ignore those files.
12465         local toignore=$(find . -type l -printf '-I %f\n' -o \
12466                          ! -perm /4 -printf '-I %f\n')
12467         $RUNAS cvs -d $DIR/$tdir.cvsroot import -m "nomesg" $toignore \
12468                 $tdir.reposname vtag rtag
12469
12470         cd $DIR
12471         test_mkdir $DIR/$tdir.reposname
12472         chown $RUNAS_ID $DIR/$tdir.reposname
12473         $RUNAS cvs -d $DIR/$tdir.cvsroot co $tdir.reposname
12474
12475         cd $DIR/$tdir.reposname
12476         $RUNAS touch foo99
12477         $RUNAS cvs add -m 'addmsg' foo99
12478         $RUNAS cvs update
12479         $RUNAS cvs commit -m 'nomsg' foo99
12480         rm -fr $DIR/$tdir.cvsroot
12481 }
12482 run_test 99 "cvs strange file/directory operations"
12483
12484 test_100() {
12485         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12486         [[ "$NETTYPE" =~ tcp ]] ||
12487                 skip_env "TCP secure port test, not useful for NETTYPE=$NETTYPE"
12488         [[ -n "$(type -p ss)" ]] || skip_env "ss not available"
12489         remote_ost_nodsh && skip "remote OST with nodsh"
12490         remote_mds_nodsh && skip "remote MDS with nodsh"
12491         remote_servers || skip "useless for local single node setup"
12492
12493         ss -tna | ( rc=1; while read STATE SND RCV LOCAL REMOTE STAT; do
12494                 [[ "${REMOTE/*:/}" == "$ACCEPTOR_PORT" ]] || continue
12495
12496                 rc=0
12497                 if (( ${LOCAL/*:/} >= 1024 )); then
12498                         echo "bad: $PROT $SND $RCV $LOCAL $REMOTE $STAT"
12499                         ss -tna
12500                         error "local: ${LOCAL/*:/} > 1024 remote: ${REMOTE/*:/}"
12501                 fi
12502         done
12503         (( $rc == 0 )) || error "privileged port not found" )
12504 }
12505 run_test 100 "check local port using privileged port"
12506
12507 function get_named_value()
12508 {
12509     local tag=$1
12510
12511     grep -w "$tag" | sed "s/^$tag  *\([0-9]*\)  *.*/\1/"
12512 }
12513
12514 test_101a() {
12515         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
12516
12517         local s
12518         local discard
12519         local nreads=10000
12520         local cache_limit=32
12521
12522         $LCTL set_param -n osc.*-osc*.rpc_stats=0
12523         $LCTL set_param -n llite.*.read_ahead_stats=0
12524         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
12525                               awk '/^max_cached_mb/ { print $2 }')
12526         stack_trap "$LCTL set_param -n llite.*.max_cached_mb=$max_cached_mb"
12527         $LCTL set_param -n llite.*.max_cached_mb=$cache_limit
12528
12529         #
12530         # randomly read 10000 of 64K chunks from file 3x 32MB in size
12531         #
12532         echo "nreads: $nreads file size: $((cache_limit * 3))MB"
12533         $READS -f $DIR/$tfile -s$((cache_limit * 3192 * 1024)) -b65536 -C -n$nreads -t 180
12534
12535         discard=0
12536         for s in $($LCTL get_param -n llite.*.read_ahead_stats |
12537                    get_named_value 'read.but.discarded'); do
12538                         discard=$(($discard + $s))
12539         done
12540
12541         $LCTL get_param osc.*-osc*.rpc_stats
12542         $LCTL get_param llite.*.read_ahead_stats
12543
12544         # Discard is generally zero, but sometimes a few random reads line up
12545         # and trigger larger readahead, which is wasted & leads to discards.
12546         if (( $discard > $nreads )); then
12547                 error "too many discarded pages ($discard > $nreads)"
12548         fi
12549         rm -f $DIR/$tfile || true
12550 }
12551 run_test 101a "check read-ahead for random reads"
12552
12553 setup_test101bc() {
12554         test_mkdir $DIR/$tdir
12555         local ssize=$1
12556         local FILE_LENGTH=$2
12557         STRIPE_OFFSET=0
12558
12559         local FILE_SIZE_MB=$((FILE_LENGTH / ssize))
12560
12561         local osts=$(osts_nodes)
12562         set_osd_param $osts '' read_cache_enable 0
12563         set_osd_param $osts '' writethrough_cache_enable 0
12564
12565         trap cleanup_test101bc EXIT
12566         # prepare the read-ahead file
12567         $LFS setstripe -S $ssize -i $STRIPE_OFFSET -c $OSTCOUNT $DIR/$tfile
12568
12569         dd if=/dev/zero of=$DIR/$tfile bs=$ssize \
12570                                 count=$FILE_SIZE_MB 2> /dev/null
12571
12572 }
12573
12574 cleanup_test101bc() {
12575         trap 0
12576         rm -rf $DIR/$tdir
12577         rm -f $DIR/$tfile
12578
12579         local osts=$(osts_nodes)
12580         set_osd_param $osts '' read_cache_enable 1
12581         set_osd_param $osts '' writethrough_cache_enable 1
12582 }
12583
12584 ra_check_101() {
12585         local read_size=$1
12586         local stripe_size=$2
12587         local stride_length=$((stripe_size / read_size))
12588         local stride_width=$((stride_length * OSTCOUNT))
12589         local discard_limit=$(( ((stride_length - 1) * 3 / stride_width) *
12590                                 (stride_width - stride_length) ))
12591         local discard=$($LCTL get_param -n llite.*.read_ahead_stats |
12592                   get_named_value 'read.but.discarded' | calc_sum)
12593
12594         if [[ $discard -gt $discard_limit ]]; then
12595                 $LCTL get_param llite.*.read_ahead_stats
12596                 error "($discard limit ${discard_limit}) discarded pages with size (${read_size})"
12597         else
12598                 echo "Read-ahead success for size ${read_size}"
12599         fi
12600 }
12601
12602 test_101b() {
12603         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12604         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12605
12606         local STRIPE_SIZE=1048576
12607         local STRIDE_SIZE=$((STRIPE_SIZE*OSTCOUNT))
12608
12609         if [ $SLOW == "yes" ]; then
12610                 local FILE_LENGTH=$((STRIDE_SIZE * 64))
12611         else
12612                 local FILE_LENGTH=$((STRIDE_SIZE * 8))
12613         fi
12614
12615         local ITERATION=$((FILE_LENGTH / STRIDE_SIZE))
12616
12617         # prepare the read-ahead file
12618         setup_test101bc $STRIPE_SIZE $FILE_LENGTH
12619         cancel_lru_locks osc
12620         for BIDX in 2 4 8 16 32 64 128 256
12621         do
12622                 local BSIZE=$((BIDX*4096))
12623                 local READ_COUNT=$((STRIPE_SIZE/BSIZE))
12624                 local STRIDE_LENGTH=$((STRIDE_SIZE/BSIZE))
12625                 local OFFSET=$((STRIPE_SIZE/BSIZE*(OSTCOUNT - 1)))
12626                 $LCTL set_param -n llite.*.read_ahead_stats=0
12627                 $READS -f $DIR/$tfile  -l $STRIDE_LENGTH -o $OFFSET \
12628                               -s $FILE_LENGTH -b $STRIPE_SIZE -a $READ_COUNT -n $ITERATION
12629                 cancel_lru_locks osc
12630                 ra_check_101 $BSIZE $STRIPE_SIZE $FILE_LENGTH
12631         done
12632         cleanup_test101bc
12633         true
12634 }
12635 run_test 101b "check stride-io mode read-ahead ================="
12636
12637 test_101c() {
12638         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12639
12640         local STRIPE_SIZE=1048576
12641         local FILE_LENGTH=$((STRIPE_SIZE*100))
12642         local nreads=10000
12643         local rsize=65536
12644         local osc_rpc_stats
12645
12646         setup_test101bc $STRIPE_SIZE $FILE_LENGTH
12647
12648         cancel_lru_locks osc
12649         $LCTL set_param osc.*.rpc_stats=0
12650         $READS -f $DIR/$tfile -s$FILE_LENGTH -b$rsize -n$nreads -t 180
12651         $LCTL get_param osc.*.rpc_stats
12652         for osc_rpc_stats in $($LCTL get_param -N osc.*.rpc_stats); do
12653                 local stats=$($LCTL get_param -n $osc_rpc_stats)
12654                 local lines=$(echo "$stats" | awk 'END {print NR;}')
12655                 local size
12656
12657                 if [ $lines -le 20 ]; then
12658                         echo "continue debug"
12659                         continue
12660                 fi
12661                 for size in 1 2 4 8; do
12662                         local rpc=$(echo "$stats" |
12663                                     awk '($1 == "'$size':") {print $2; exit; }')
12664                         [ $rpc != 0 ] && ((size * PAGE_SIZE < rsize)) &&
12665                                 error "Small $((size*PAGE_SIZE)) read IO $rpc!"
12666                 done
12667                 echo "$osc_rpc_stats check passed!"
12668         done
12669         cleanup_test101bc
12670         true
12671 }
12672 run_test 101c "check stripe_size aligned read-ahead"
12673
12674 test_101d() {
12675         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12676
12677         local file=$DIR/$tfile
12678         local sz_MB=${FILESIZE_101d:-80}
12679         local ra_MB=${READAHEAD_MB:-40}
12680
12681         local free_MB=$(($(df -P $DIR | tail -n 1 | awk '{ print $4 }') / 1024))
12682         [ $free_MB -lt $sz_MB ] &&
12683                 skip "Need free space ${sz_MB}M, have ${free_MB}M"
12684
12685         echo "Create test file $file size ${sz_MB}M, ${free_MB}M free"
12686         $LFS setstripe -c -1 $file || error "setstripe failed"
12687
12688         dd if=/dev/zero of=$file bs=1M count=$sz_MB || error "dd failed"
12689         echo Cancel LRU locks on lustre client to flush the client cache
12690         cancel_lru_locks osc
12691
12692         echo Disable read-ahead
12693         local old_RA=$($LCTL get_param -n llite.*.max_read_ahead_mb | head -n 1)
12694         $LCTL set_param -n llite.*.max_read_ahead_mb=0
12695         stack_trap "$LCTL set_param -n llite.*.max_read_ahead_mb=$old_RA" EXIT
12696         $LCTL get_param -n llite.*.max_read_ahead_mb
12697
12698         echo "Reading the test file $file with read-ahead disabled"
12699         local sz_KB=$((sz_MB * 1024 / 4))
12700         # 10485760 bytes transferred in 0.000938 secs (11179579337 bytes/sec)
12701         # 104857600 bytes (105 MB) copied, 0.00876352 s, 12.0 GB/s
12702         # 83886080 bytes (84 MB, 80 MiB) copied, 16 s, 5.2 MB/s
12703         local raOFF=$(LANG=C dd if=$file of=/dev/null bs=4k count=$sz_KB |&
12704                       sed -e '/records/d' -e 's/.* \([0-9][0-9\.]*\) *s.*/\1/')
12705
12706         echo "Cancel LRU locks on lustre client to flush the client cache"
12707         cancel_lru_locks osc
12708         echo Enable read-ahead with ${ra_MB}MB
12709         $LCTL set_param -n llite.*.max_read_ahead_mb=$ra_MB
12710
12711         echo "Reading the test file $file with read-ahead enabled"
12712         local raON=$(LANG=C dd if=$file of=/dev/null bs=4k count=$sz_KB |&
12713                       sed -e '/records/d' -e 's/.* \([0-9][0-9\.]*\) *s.*/\1/')
12714
12715         echo "read-ahead disabled time read '$raOFF'"
12716         echo "read-ahead enabled time read '$raON'"
12717
12718         rm -f $file
12719         wait_delete_completed
12720
12721         # use awk for this check instead of bash because it handles decimals
12722         awk "{ exit !($raOFF < 0.5 || $raOFF > $raON) }" <<<"ignore_me" ||
12723                 error "readahead ${raON}s > no-readahead ${raOFF}s (${sz_MB}M)"
12724 }
12725 run_test 101d "file read with and without read-ahead enabled"
12726
12727 test_101e() {
12728         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12729
12730         local file=$DIR/$tfile
12731         local size_KB=500  #KB
12732         local count=100
12733         local bsize=1024
12734
12735         local free_KB=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
12736         local need_KB=$((count * size_KB))
12737         [[ $free_KB -le $need_KB ]] &&
12738                 skip_env "Need free space $need_KB, have $free_KB"
12739
12740         echo "Creating $count ${size_KB}K test files"
12741         for ((i = 0; i < $count; i++)); do
12742                 dd if=/dev/zero of=$file.$i bs=$bsize count=$size_KB 2>/dev/null
12743         done
12744
12745         echo "Cancel LRU locks on lustre client to flush the client cache"
12746         cancel_lru_locks $OSC
12747
12748         echo "Reset readahead stats"
12749         $LCTL set_param -n llite.*.read_ahead_stats=0
12750
12751         for ((i = 0; i < $count; i++)); do
12752                 dd if=$file.$i of=/dev/null bs=$bsize count=$size_KB 2>/dev/null
12753         done
12754
12755         $LCTL get_param llite.*.max_cached_mb
12756         $LCTL get_param llite.*.read_ahead_stats
12757         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
12758                      get_named_value 'misses' | calc_sum)
12759
12760         for ((i = 0; i < $count; i++)); do
12761                 rm -rf $file.$i 2>/dev/null
12762         done
12763
12764         #10000 means 20% reads are missing in readahead
12765         [[ $miss -lt 10000 ]] ||  error "misses too much for small reads"
12766 }
12767 run_test 101e "check read-ahead for small read(1k) for small files(500k)"
12768
12769 test_101f() {
12770         which iozone || skip_env "no iozone installed"
12771
12772         local old_debug=$($LCTL get_param debug)
12773         old_debug=${old_debug#*=}
12774         $LCTL set_param debug="reada mmap"
12775
12776         # create a test file
12777         iozone -i 0 -+n -r 1m -s 128m -w -f $DIR/$tfile > /dev/null 2>&1
12778
12779         echo Cancel LRU locks on lustre client to flush the client cache
12780         cancel_lru_locks osc
12781
12782         echo Reset readahead stats
12783         $LCTL set_param -n llite.*.read_ahead_stats=0
12784
12785         echo mmap read the file with small block size
12786         iozone -i 1 -u 1 -l 1 -+n -r 32k -s 128m -B -f $DIR/$tfile \
12787                 > /dev/null 2>&1
12788
12789         echo checking missing pages
12790         $LCTL get_param llite.*.read_ahead_stats
12791         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
12792                         get_named_value 'misses' | calc_sum)
12793
12794         $LCTL set_param debug="$old_debug"
12795         [ $miss -lt 3 ] || error "misses too much pages ('$miss')!"
12796         rm -f $DIR/$tfile
12797 }
12798 run_test 101f "check mmap read performance"
12799
12800 test_101g_brw_size_test() {
12801         local mb=$1
12802         local pages=$((mb * 1048576 / PAGE_SIZE))
12803         local file=$DIR/$tfile
12804
12805         $LCTL set_param osc.*.max_pages_per_rpc=${mb}M ||
12806                 { error "unable to set max_pages_per_rpc=${mb}M"; return 1; }
12807         for mp in $($LCTL get_param -n osc.*.max_pages_per_rpc); do
12808                 [ $mp -ne $pages ] && error "max_pages_per_rpc $mp != $pages" &&
12809                         return 2
12810         done
12811
12812         stack_trap "rm -f $file; wait_delete_completed" EXIT
12813         $LCTL set_param -n osc.*.rpc_stats=0
12814
12815         # 10 RPCs should be enough for the test
12816         local count=10
12817         dd if=/dev/zero of=$file bs=${mb}M count=$count ||
12818                 { error "dd write ${mb} MB blocks failed"; return 3; }
12819         cancel_lru_locks osc
12820         dd of=/dev/null if=$file bs=${mb}M count=$count ||
12821                 { error "dd write ${mb} MB blocks failed"; return 4; }
12822
12823         # calculate number of full-sized read and write RPCs
12824         rpcs=($($LCTL get_param -n 'osc.*.rpc_stats' |
12825                 sed -n '/pages per rpc/,/^$/p' |
12826                 awk '/'$pages':/ { reads += $2; writes += $6 }; \
12827                 END { print reads,writes }'))
12828         # allow one extra full-sized read RPC for async readahead
12829         [[ ${rpcs[0]} == $count || ${rpcs[0]} == $((count + 1)) ]] ||
12830                 { error "${rpcs[0]} != $count read RPCs"; return 5; }
12831         [[ ${rpcs[1]} == $count ]] ||
12832                 { error "${rpcs[1]} != $count write RPCs"; return 6; }
12833 }
12834
12835 test_101g() {
12836         remote_ost_nodsh && skip "remote OST with nodsh"
12837
12838         local rpcs
12839         local facets=$(get_facets OST)
12840         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
12841         local brw_size="obdfilter.*.brw_size"
12842
12843         $LFS setstripe -i 0 -c 1 $DIR/$tfile
12844
12845         local orig_mb=$(do_facet ost1 $LCTL get_param -n $brw_size | head -n 1)
12846
12847         if (( $OST1_VERSION >= $(version_code 2.8.52) )); then
12848                 local osts=$(osts_nodes)
12849
12850                 (( $OST1_VERSION < $(version_code 2.9.52) )) || suffix="M"
12851
12852                 if (( $orig_mb < 16 )); then
12853                         save_lustre_params $facets "$brw_size" > $p
12854                         stack_trap "rm -f $p"
12855                         do_nodes $osts $LCTL set_param -n $brw_size=16$suffix ||
12856                                 error "set 16MB RPC size failed"
12857
12858                         echo "remount client to enable new RPC size"
12859                         remount_client $MOUNT || error "remount_client failed"
12860                 fi
12861
12862                 test_101g_brw_size_test 16 || error "16MB RPC test failed"
12863                 # should be able to set brw_size=12, but no rpc_stats for that
12864                 test_101g_brw_size_test 8 || error "8MB RPC test failed"
12865         fi
12866
12867         test_101g_brw_size_test 4 || error "4MB RPC test failed"
12868
12869         if (( $orig_mb < 16 )); then
12870                 restore_lustre_params < $p
12871                 remount_client $MOUNT || error "remount_client restore failed"
12872         fi
12873 }
12874 run_test 101g "Big bulk(4/16 MiB) readahead"
12875
12876 test_101h() {
12877         $LFS setstripe -i 0 -c 1 $DIR/$tfile
12878         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
12879         $LCTL set_param llite.*.hybrid_io=0
12880         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
12881
12882         dd if=/dev/zero of=$DIR/$tfile bs=1M count=70 ||
12883                 error "dd 70M file failed"
12884         echo Cancel LRU locks on lustre client to flush the client cache
12885         cancel_lru_locks osc
12886
12887         echo "Reset readahead stats"
12888         $LCTL set_param -n llite.*.read_ahead_stats 0
12889
12890         echo "Read 10M of data but cross 64M bundary"
12891         dd if=$DIR/$tfile of=/dev/null bs=10M skip=6 count=1
12892         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
12893                      get_named_value 'misses' | calc_sum)
12894         [ $miss -eq 1 ] || error "expected miss 1 but got $miss"
12895         rm -f $p $DIR/$tfile
12896 }
12897 run_test 101h "Readahead should cover current read window"
12898
12899 test_101i() {
12900         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 ||
12901                 error "dd 10M file failed"
12902
12903         local max_per_file_mb=$($LCTL get_param -n \
12904                 llite.*.max_read_ahead_per_file_mb 2>/dev/null)
12905         cancel_lru_locks osc
12906         stack_trap "$LCTL set_param llite.*.max_read_ahead_per_file_mb=$max_per_file_mb"
12907         $LCTL set_param llite.*.max_read_ahead_per_file_mb=1 ||
12908                 error "set max_read_ahead_per_file_mb to 1 failed"
12909
12910         echo "Reset readahead stats"
12911         $LCTL set_param llite.*.read_ahead_stats=0
12912
12913         dd if=$DIR/$tfile of=/dev/null bs=2M
12914
12915         $LCTL get_param llite.*.read_ahead_stats
12916         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
12917                      awk '/misses/ { print $2 }')
12918         [ $miss -eq 5 ] || error "expected misses 5 but got $miss"
12919         rm -f $DIR/$tfile
12920 }
12921 run_test 101i "allow current readahead to exceed reservation"
12922
12923 test_101j() {
12924         $LFS setstripe -i 0 -c 1 $DIR/$tfile ||
12925                 error "setstripe $DIR/$tfile failed"
12926         local file_size=$((1048576 * 16))
12927         local old_ra=$($LCTL get_param -n llite.*.max_read_ahead_mb | head -n 1)
12928         stack_trap "$LCTL set_param -n llite.*.max_read_ahead_mb $old_ra" EXIT
12929         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
12930         $LCTL set_param llite.*.hybrid_io=0
12931         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
12932
12933         echo Disable read-ahead
12934         $LCTL set_param -n llite.*.max_read_ahead_mb=0
12935
12936         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$(($file_size / 1048576))
12937         for blk in $PAGE_SIZE 1048576 $file_size; do
12938                 cancel_lru_locks osc
12939                 echo "Reset readahead stats"
12940                 $LCTL set_param -n llite.*.read_ahead_stats=0
12941                 local count=$(($file_size / $blk))
12942                 dd if=$DIR/$tfile bs=$blk count=$count of=/dev/null
12943                 local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
12944                              get_named_value 'failed.to.fast.read' | calc_sum)
12945                 $LCTL get_param -n llite.*.read_ahead_stats
12946                 [ $miss -eq $count ] || error "expected $count got $miss"
12947         done
12948
12949         rm -f $p $DIR/$tfile
12950 }
12951 run_test 101j "A complete read block should be submitted when no RA"
12952
12953 test_readahead_base() {
12954         local file=$DIR/$tfile
12955         local size=$1
12956         local iosz
12957         local ramax
12958         local ranum
12959
12960         $LCTL set_param -n llite.*.read_ahead_stats=0
12961         # The first page is not accounted into readahead
12962         ramax=$(((size + PAGE_SIZE - 1) / PAGE_SIZE - 1))
12963         iosz=$(((size + 1048575) / 1048576 * 1048576))
12964         echo "Test readahead: size=$size ramax=$ramx iosz=$iosz"
12965
12966         $LCTL mark  "Test readahead: size=$size ramax=$ramx iosz=$iosz"
12967         fallocate -l $size $file || error "failed to fallocate $file"
12968         cancel_lru_locks osc
12969         $MULTIOP $file or${iosz}c || error "failed to read $file"
12970         $LCTL get_param -n llite.*.read_ahead_stats
12971         ranum=$($LCTL get_param -n llite.*.read_ahead_stats |
12972                 awk '/readahead.pages/ { print $7 }' | calc_sum)
12973         (( $ranum <= $ramax )) ||
12974                 error "read-ahead pages is $ranum more than $ramax"
12975         rm -rf $file || error "failed to remove $file"
12976 }
12977
12978 test_101m()
12979 {
12980         local file=$DIR/$tfile
12981         local ramax
12982         local ranum
12983         local size
12984         local iosz
12985
12986         check_set_fallocate_or_skip
12987         stack_trap "rm -f $file" EXIT
12988
12989         test_readahead_base 4096
12990
12991         # file size: 16K = 16384
12992         test_readahead_base 16384
12993         test_readahead_base 16385
12994         test_readahead_base 16383
12995
12996         # file size: 1M + 1 = 1048576 + 1
12997         test_readahead_base 1048577
12998         # file size: 1M + 16K
12999         test_readahead_base $((1048576 + 16384))
13000
13001         # file size: stripe_size * (stripe_count - 1) + 16K
13002         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
13003         test_readahead_base $((1048576 * (OSTCOUNT - 1) + 16384))
13004         # file size: stripe_size * stripe_count + 16K
13005         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
13006         test_readahead_base $((1048576 * OSTCOUNT + 16384))
13007         # file size: 2 * stripe_size * stripe_count + 16K
13008         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
13009         test_readahead_base $((2 * 1048576 * OSTCOUNT + 16384))
13010 }
13011 run_test 101m "read ahead for small file and last stripe of the file"
13012
13013 setup_test102() {
13014         test_mkdir $DIR/$tdir
13015         chown $RUNAS_ID $DIR/$tdir
13016         STRIPE_SIZE=65536
13017         STRIPE_OFFSET=1
13018         STRIPE_COUNT=$OSTCOUNT
13019         [[ $OSTCOUNT -gt 4 ]] && STRIPE_COUNT=4
13020
13021         trap cleanup_test102 EXIT
13022         cd $DIR
13023         $1 $LFS setstripe -S $STRIPE_SIZE -i $STRIPE_OFFSET -c $STRIPE_COUNT $tdir
13024         cd $DIR/$tdir
13025         for num in 1 2 3 4; do
13026                 for count in $(seq 1 $STRIPE_COUNT); do
13027                         for idx in $(seq 0 $[$STRIPE_COUNT - 1]); do
13028                                 local size=`expr $STRIPE_SIZE \* $num`
13029                                 local file=file"$num-$idx-$count"
13030                                 $1 $LFS setstripe -S $size -i $idx -c $count $file
13031                         done
13032                 done
13033         done
13034
13035         cd $DIR
13036         $1 tar cf $TMP/f102.tar $tdir --xattrs
13037 }
13038
13039 cleanup_test102() {
13040         trap 0
13041         rm -f $TMP/f102.tar
13042         rm -rf $DIR/d0.sanity/d102
13043 }
13044
13045 test_102a() {
13046         [ "$UID" != 0 ] && skip "must run as root"
13047         [ -z "$(lctl get_param -n mdc.*-mdc-*.connect_flags | grep xattr)" ] &&
13048                 skip_env "must have user_xattr"
13049
13050         [ -z "$(which setfattr 2>/dev/null)" ] &&
13051                 skip_env "could not find setfattr"
13052
13053         local testfile=$DIR/$tfile
13054
13055         touch $testfile
13056         echo "set/get xattr..."
13057         setfattr -n trusted.name1 -v value1 $testfile ||
13058                 error "setfattr -n trusted.name1=value1 $testfile failed"
13059         getfattr -n trusted.name1 $testfile 2> /dev/null |
13060           grep "trusted.name1=.value1" ||
13061                 error "$testfile missing trusted.name1=value1"
13062
13063         setfattr -n user.author1 -v author1 $testfile ||
13064                 error "setfattr -n user.author1=author1 $testfile failed"
13065         getfattr -n user.author1 $testfile 2> /dev/null |
13066           grep "user.author1=.author1" ||
13067                 error "$testfile missing trusted.author1=author1"
13068
13069         echo "listxattr..."
13070         setfattr -n trusted.name2 -v value2 $testfile ||
13071                 error "$testfile unable to set trusted.name2"
13072         setfattr -n trusted.name3 -v value3 $testfile ||
13073                 error "$testfile unable to set trusted.name3"
13074         [ $(getfattr -d -m "^trusted" $testfile 2> /dev/null |
13075             grep "trusted.name" | wc -l) -eq 3 ] ||
13076                 error "$testfile missing 3 trusted.name xattrs"
13077
13078         setfattr -n user.author2 -v author2 $testfile ||
13079                 error "$testfile unable to set user.author2"
13080         setfattr -n user.author3 -v author3 $testfile ||
13081                 error "$testfile unable to set user.author3"
13082         [ $(getfattr -d -m "^user" $testfile 2> /dev/null |
13083             grep "user.author" | wc -l) -eq 3 ] ||
13084                 error "$testfile missing 3 user.author xattrs"
13085
13086         echo "remove xattr..."
13087         setfattr -x trusted.name1 $testfile ||
13088                 error "$testfile error deleting trusted.name1"
13089         getfattr -d -m trusted $testfile 2> /dev/null | grep "trusted.name1" &&
13090                 error "$testfile did not delete trusted.name1 xattr"
13091
13092         setfattr -x user.author1 $testfile ||
13093                 error "$testfile error deleting user.author1"
13094         echo "set lustre special xattr ..."
13095         $LFS setstripe -c1 $testfile
13096         local lovea=$(getfattr -n "trusted.lov" -e hex $testfile |
13097                 awk -F "=" '/trusted.lov/ { print $2 }' )
13098         setfattr -n "trusted.lov" -v $lovea $testfile ||
13099                 error "$testfile doesn't ignore setting trusted.lov again"
13100         setfattr -n "trusted.lov" -v "invalid_value" $testfile &&
13101                 error "$testfile allow setting invalid trusted.lov"
13102         rm -f $testfile
13103 }
13104 run_test 102a "user xattr test =================================="
13105
13106 check_102b_layout() {
13107         local layout="$*"
13108         local testfile=$DIR/$tfile
13109
13110         echo "test layout '$layout'"
13111         $LFS setstripe $layout $testfile || error "setstripe failed"
13112         $LFS getstripe -y $testfile
13113
13114         echo "get/set/list trusted.lov xattr ..." # b=10930
13115         local value=$(getfattr -n trusted.lov -e hex $testfile | grep trusted)
13116         [[ "$value" =~ "trusted.lov" ]] ||
13117                 error "can't get trusted.lov from $testfile"
13118         local stripe_count_orig=$($LFS getstripe -c $testfile) ||
13119                 error "getstripe failed"
13120
13121         $MCREATE $testfile.2 || error "mcreate $testfile.2 failed"
13122
13123         value=$(cut -d= -f2 <<<$value)
13124         # LU-13168: truncated xattr should fail if short lov_user_md header
13125         [ $CLIENT_VERSION -lt $(version_code 2.13.53) ] &&
13126                 lens="${#value}" || lens="$(seq 4 2 ${#value})"
13127         for len in $lens; do
13128                 echo "setfattr $len $testfile.2"
13129                 setfattr -n trusted.lov -v ${value:0:$len} $testfile.2 &&
13130                         [ $len -lt 66 ] && error "short xattr len=$len worked"
13131         done
13132         local stripe_size=$($LFS getstripe -S $testfile.2)
13133         local stripe_count=$($LFS getstripe -c $testfile.2)
13134         [[ $stripe_size -eq 65536 ]] ||
13135                 error "stripe size $stripe_size != 65536"
13136         [[ $stripe_count -eq $stripe_count_orig ]] ||
13137                 error "stripe count $stripe_count != $stripe_count_orig"
13138         rm $testfile $testfile.2
13139 }
13140
13141 test_102b() {
13142         [ -z "$(which setfattr 2>/dev/null)" ] &&
13143                 skip_env "could not find setfattr"
13144         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13145
13146         # check plain layout
13147         check_102b_layout -S 65536 -i 1 -c $OSTCOUNT
13148
13149         # and also check composite layout
13150         check_102b_layout -E 1M -S 65536 -i 1 -c $OSTCOUNT -Eeof -S4M
13151
13152 }
13153 run_test 102b "getfattr/setfattr for trusted.lov EAs"
13154
13155 test_102c() {
13156         [ -z "$(which setfattr 2>/dev/null)" ] &&
13157                 skip_env "could not find setfattr"
13158         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13159
13160         # b10930: get/set/list lustre.lov xattr
13161         echo "get/set/list lustre.lov xattr ..."
13162         test_mkdir $DIR/$tdir
13163         chown $RUNAS_ID $DIR/$tdir
13164         local testfile=$DIR/$tdir/$tfile
13165         $RUNAS $LFS setstripe -S 65536 -i 1 -c $OSTCOUNT $testfile ||
13166                 error "setstripe failed"
13167         local STRIPECOUNT=$($RUNAS $LFS getstripe -c $testfile) ||
13168                 error "getstripe failed"
13169         $RUNAS getfattr -d -m "^lustre" $testfile 2> /dev/null | \
13170         grep "lustre.lov" || error "can't get lustre.lov from $testfile"
13171
13172         local testfile2=${testfile}2
13173         local value=`getfattr -n lustre.lov $testfile 2> /dev/null | \
13174                      grep "lustre.lov" |sed -e 's/[^=]\+=//'  `
13175
13176         $RUNAS $MCREATE $testfile2
13177         $RUNAS setfattr -n lustre.lov -v $value $testfile2
13178         local stripe_size=$($RUNAS $LFS getstripe -S $testfile2)
13179         local stripe_count=$($RUNAS $LFS getstripe -c $testfile2)
13180         [ $stripe_size -eq 65536 ] || error "stripe size $stripe_size != 65536"
13181         [ $stripe_count -eq $STRIPECOUNT ] ||
13182                 error "stripe count $stripe_count != $STRIPECOUNT"
13183 }
13184 run_test 102c "non-root getfattr/setfattr for lustre.lov EAs ==========="
13185
13186 compare_stripe_info1() {
13187         local stripe_index_all_zero=true
13188
13189         for num in 1 2 3 4; do
13190                 for count in $(seq 1 $STRIPE_COUNT); do
13191                         for offset in $(seq 0 $[$STRIPE_COUNT - 1]); do
13192                                 local size=$((STRIPE_SIZE * num))
13193                                 local file=file"$num-$offset-$count"
13194                                 stripe_size=$($LFS getstripe -S $PWD/$file)
13195                                 [[ $stripe_size -ne $size ]] &&
13196                                     error "$file: size $stripe_size != $size"
13197                                 stripe_count=$($LFS getstripe -c $PWD/$file)
13198                                 # allow fewer stripes to be created, ORI-601
13199                                 [[ $stripe_count -lt $(((3 * count + 3) / 4)) ]] &&
13200                                     error "$file: count $stripe_count != $count"
13201                                 stripe_index=$($LFS getstripe -i $PWD/$file)
13202                                 [[ $stripe_index -ne 0 ]] &&
13203                                         stripe_index_all_zero=false
13204                         done
13205                 done
13206         done
13207         $stripe_index_all_zero &&
13208                 error "all files are being extracted starting from OST index 0"
13209         return 0
13210 }
13211
13212 have_xattrs_include() {
13213         tar --help | grep -q xattrs-include &&
13214                 echo --xattrs-include="lustre.*"
13215 }
13216
13217 test_102d() {
13218         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13219         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13220
13221         XINC=$(have_xattrs_include)
13222         setup_test102
13223         tar xf $TMP/f102.tar -C $DIR/$tdir --xattrs $XINC
13224         cd $DIR/$tdir/$tdir
13225         compare_stripe_info1
13226 }
13227 run_test 102d "tar restore stripe info from tarfile,not keep osts"
13228
13229 test_102f() {
13230         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13231         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13232
13233         XINC=$(have_xattrs_include)
13234         setup_test102
13235         test_mkdir $DIR/$tdir.restore
13236         cd $DIR
13237         tar cf - --xattrs $tdir | tar xf - \
13238                 -C $DIR/$tdir.restore --xattrs $XINC
13239         cd $DIR/$tdir.restore/$tdir
13240         compare_stripe_info1
13241 }
13242 run_test 102f "tar copy files, not keep osts"
13243
13244 grow_xattr() {
13245         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep xattr)" ] &&
13246                 skip "must have user_xattr"
13247         [ -z "$(which setfattr 2>/dev/null)" ] &&
13248                 skip_env "could not find setfattr"
13249         [ -z "$(which getfattr 2>/dev/null)" ] &&
13250                 skip_env "could not find getfattr"
13251
13252         local xsize=${1:-1024}  # in bytes
13253         local file=$DIR/$tfile
13254         local value="$(generate_string $xsize)"
13255         local xbig=trusted.big
13256         local toobig=$2
13257
13258         touch $file
13259         log "save $xbig on $file"
13260         if [ -z "$toobig" ]
13261         then
13262                 setfattr -n $xbig -v $value $file ||
13263                         error "saving $xbig on $file failed"
13264         else
13265                 setfattr -n $xbig -v $value $file &&
13266                         error "saving $xbig on $file succeeded"
13267                 return 0
13268         fi
13269
13270         local orig=$(get_xattr_value $xbig $file)
13271         [[ "$orig" != "$value" ]] && error "$xbig different after saving $xbig"
13272
13273         local xsml=trusted.sml
13274         log "save $xsml on $file"
13275         setfattr -n $xsml -v val $file || error "saving $xsml on $file failed"
13276
13277         local new=$(get_xattr_value $xbig $file)
13278         [[ "$new" != "$orig" ]] && error "$xbig different after saving $xsml"
13279
13280         log "grow $xsml on $file"
13281         setfattr -n $xsml -v "$value" $file ||
13282                 error "growing $xsml on $file failed"
13283
13284         new=$(get_xattr_value $xbig $file)
13285         [[ "$new" != "$orig" ]] && error "$xbig different after growing $xsml"
13286         log "$xbig still valid after growing $xsml"
13287
13288         rm -f $file
13289 }
13290
13291 test_102h() { # bug 15777
13292         grow_xattr 1024
13293 }
13294 run_test 102h "grow xattr from inside inode to external block"
13295
13296 test_102ha() {
13297         large_xattr_enabled || skip_env "ea_inode feature disabled"
13298
13299         echo "setting xattr of max xattr size: $(max_xattr_size)"
13300         grow_xattr $(max_xattr_size)
13301
13302         echo "setting xattr of > max xattr size: $(max_xattr_size) + 10"
13303         echo "This should fail:"
13304         grow_xattr $(($(max_xattr_size) + 10)) 1
13305 }
13306 run_test 102ha "grow xattr from inside inode to external inode"
13307
13308 test_102i() { # bug 17038
13309         [ -z "$(which getfattr 2>/dev/null)" ] &&
13310                 skip "could not find getfattr"
13311
13312         touch $DIR/$tfile
13313         ln -s $DIR/$tfile $DIR/${tfile}link
13314         getfattr -n trusted.lov $DIR/$tfile ||
13315                 error "lgetxattr on $DIR/$tfile failed"
13316         getfattr -h -n trusted.lov $DIR/${tfile}link 2>&1 |
13317                 grep -i "no such attr" ||
13318                 error "error for lgetxattr on $DIR/${tfile}link is not ENODATA"
13319         rm -f $DIR/$tfile $DIR/${tfile}link
13320 }
13321 run_test 102i "lgetxattr test on symbolic link ============"
13322
13323 test_102j() {
13324         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13325         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13326
13327         XINC=$(have_xattrs_include)
13328         setup_test102 "$RUNAS"
13329         chown $RUNAS_ID $DIR/$tdir
13330         $RUNAS tar xf $TMP/f102.tar -C $DIR/$tdir --xattrs $XINC
13331         cd $DIR/$tdir/$tdir
13332         compare_stripe_info1 "$RUNAS"
13333 }
13334 run_test 102j "non-root tar restore stripe info from tarfile, not keep osts ==="
13335
13336 test_102k() {
13337         [ -z "$(which setfattr 2>/dev/null)" ] &&
13338                 skip "could not find setfattr"
13339
13340         touch $DIR/$tfile
13341         # b22187 just check that does not crash for regular file.
13342         setfattr -n trusted.lov $DIR/$tfile
13343         # b22187 'setfattr -n trusted.lov' should remove LOV EA for directories
13344         local test_kdir=$DIR/$tdir
13345         test_mkdir $test_kdir
13346         local default_size=$($LFS getstripe -S $test_kdir)
13347         local default_count=$($LFS getstripe -c $test_kdir)
13348         local default_offset=$($LFS getstripe -i $test_kdir)
13349         $LFS setstripe -S 65536 -i 0 -c $OSTCOUNT $test_kdir ||
13350                 error 'dir setstripe failed'
13351         setfattr -n trusted.lov $test_kdir
13352         local stripe_size=$($LFS getstripe -S $test_kdir)
13353         local stripe_count=$($LFS getstripe -c $test_kdir)
13354         local stripe_offset=$($LFS getstripe -i $test_kdir)
13355         [ $stripe_size -eq $default_size ] ||
13356                 error "stripe size $stripe_size != $default_size"
13357         [ $stripe_count -eq $default_count ] ||
13358                 error "stripe count $stripe_count != $default_count"
13359         [ $stripe_offset -eq $default_offset ] ||
13360                 error "stripe offset $stripe_offset != $default_offset"
13361         rm -rf $DIR/$tfile $test_kdir
13362 }
13363 run_test 102k "setfattr without parameter of value shouldn't cause a crash"
13364
13365 test_102l() {
13366         [ -z "$(which getfattr 2>/dev/null)" ] &&
13367                 skip "could not find getfattr"
13368
13369         # LU-532 trusted. xattr is invisible to non-root
13370         local testfile=$DIR/$tfile
13371
13372         touch $testfile
13373
13374         echo "listxattr as user..."
13375         chown $RUNAS_ID $testfile
13376         $RUNAS getfattr -d -m '.*' $testfile 2>&1 |
13377             grep -q "trusted" &&
13378                 error "$testfile trusted xattrs are user visible"
13379
13380         return 0;
13381 }
13382 run_test 102l "listxattr size test =================================="
13383
13384 test_102m() { # LU-3403 llite: error of listxattr when buffer is small
13385         local path=$DIR/$tfile
13386         touch $path
13387
13388         listxattr_size_check $path || error "listattr_size_check $path failed"
13389 }
13390 run_test 102m "Ensure listxattr fails on small bufffer ========"
13391
13392 cleanup_test102
13393
13394 getxattr() { # getxattr path name
13395         # Return the base64 encoding of the value of xattr name on path.
13396         local path=$1
13397         local name=$2
13398
13399         # # getfattr --absolute-names --encoding=base64 --name=trusted.lov $path
13400         # file: $path
13401         # trusted.lov=0s0AvRCwEAAAAGAAAAAAAAAAAEAAACAAAAAAAQAAEAA...AAAAAAAAA=
13402         #
13403         # We print just 0s0AvRCwEAAAAGAAAAAAAAAAAEAAACAAAAAAAQAAEAA...AAAAAAAAA=
13404
13405         getfattr --absolute-names --encoding=base64 --name=$name $path |
13406                 awk -F= -v name=$name '$1 == name {
13407                         print substr($0, index($0, "=") + 1);
13408         }'
13409 }
13410
13411 test_102n() { # LU-4101 mdt: protect internal xattrs
13412         [ -z "$(which setfattr 2>/dev/null)" ] &&
13413                 skip "could not find setfattr"
13414         if [ $MDS1_VERSION -lt $(version_code 2.5.50) ]
13415         then
13416                 skip "MDT < 2.5.50 allows setxattr on internal trusted xattrs"
13417         fi
13418
13419         local file0=$DIR/$tfile.0
13420         local file1=$DIR/$tfile.1
13421         local xattr0=$TMP/$tfile.0
13422         local xattr1=$TMP/$tfile.1
13423         local namelist="lov lma lmv link fid version som hsm"
13424         local name
13425         local value
13426
13427         rm -rf $file0 $file1 $xattr0 $xattr1
13428         touch $file0 $file1
13429
13430         # Get 'before' xattrs of $file1.
13431         getfattr --absolute-names --dump --match=- $file1 > $xattr0
13432
13433         [ $MDS1_VERSION -lt $(version_code 2.8.53) ] &&
13434                 namelist+=" lfsck_namespace"
13435         for name in $namelist; do
13436                 # Try to copy xattr from $file0 to $file1.
13437                 value=$(getxattr $file0 trusted.$name 2> /dev/null)
13438
13439                 setfattr --name=trusted.$name --value="$value" $file1 ||
13440                         error "setxattr 'trusted.$name' failed"
13441
13442                 # Try to set a garbage xattr.
13443                 value=0sVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIGl0c2VsZi4=
13444
13445                 if [[ x$name == "xlov" ]]; then
13446                         setfattr --name=trusted.lov --value="$value" $file1 &&
13447                         error "setxattr invalid 'trusted.lov' success"
13448                 else
13449                         setfattr --name=trusted.$name --value="$value" $file1 ||
13450                                 error "setxattr invalid 'trusted.$name' failed"
13451                 fi
13452
13453                 # Try to remove the xattr from $file1. We don't care if this
13454                 # appears to succeed or fail, we just don't want there to be
13455                 # any changes or crashes.
13456                 setfattr --remove=$trusted.$name $file1 2> /dev/null
13457         done
13458
13459         if [ $MDS1_VERSION -gt $(version_code 2.6.50) ]
13460         then
13461                 name="lfsck_ns"
13462                 # Try to copy xattr from $file0 to $file1.
13463                 value=$(getxattr $file0 trusted.$name 2> /dev/null)
13464
13465                 setfattr --name=trusted.$name --value="$value" $file1 ||
13466                         error "setxattr 'trusted.$name' failed"
13467
13468                 # Try to set a garbage xattr.
13469                 value=0sVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIGl0c2VsZi4=
13470
13471                 setfattr --name=trusted.$name --value="$value" $file1 ||
13472                         error "setxattr 'trusted.$name' failed"
13473
13474                 # Try to remove the xattr from $file1. We don't care if this
13475                 # appears to succeed or fail, we just don't want there to be
13476                 # any changes or crashes.
13477                 setfattr --remove=$trusted.$name $file1 2> /dev/null
13478         fi
13479
13480         # Get 'after' xattrs of file1.
13481         getfattr --absolute-names --dump --match=- $file1 > $xattr1
13482
13483         if ! diff $xattr0 $xattr1; then
13484                 error "before and after xattrs of '$file1' differ"
13485         fi
13486
13487         rm -rf $file0 $file1 $xattr0 $xattr1
13488
13489         return 0
13490 }
13491 run_test 102n "silently ignore setxattr on internal trusted xattrs"
13492
13493 test_102p() { # LU-4703 setxattr did not check ownership
13494         [ $MDS1_VERSION -lt $(version_code 2.5.56) ] &&
13495                 skip "MDS needs to be at least 2.5.56"
13496
13497         local testfile=$DIR/$tfile
13498
13499         touch $testfile
13500
13501         echo "setfacl as user..."
13502         $RUNAS setfacl -m "u:$RUNAS_ID:rwx" $testfile
13503         [ $? -ne 0 ] || error "setfacl by $RUNAS_ID was allowed on $testfile"
13504
13505         echo "setfattr as user..."
13506         setfacl -m "u:$RUNAS_ID:---" $testfile
13507         $RUNAS setfattr -x system.posix_acl_access $testfile
13508         [ $? -ne 0 ] || error "setfattr by $RUNAS_ID was allowed on $testfile"
13509 }
13510 run_test 102p "check setxattr(2) correctly fails without permission"
13511
13512 test_102q() {
13513         [ $MDS1_VERSION -lt $(version_code 2.6.92) ] &&
13514                 skip "MDS needs to be at least 2.6.92"
13515
13516         orphan_linkea_check $DIR/$tfile || error "orphan_linkea_check"
13517 }
13518 run_test 102q "flistxattr should not return trusted.link EAs for orphans"
13519
13520 test_102r() {
13521         [ $MDS1_VERSION -lt $(version_code 2.6.93) ] &&
13522                 skip "MDS needs to be at least 2.6.93"
13523
13524         touch $DIR/$tfile || error "touch"
13525         setfattr -n user.$(basename $tfile) $DIR/$tfile || error "setfattr"
13526         getfattr -n user.$(basename $tfile) $DIR/$tfile || error "getfattr"
13527         rm $DIR/$tfile || error "rm"
13528
13529         #normal directory
13530         mkdir -p $DIR/$tdir || error "mkdir"
13531         setfattr -n user.$(basename $tdir) $DIR/$tdir || error "setfattr dir"
13532         getfattr -n user.$(basename $tdir) $DIR/$tdir || error "getfattr dir"
13533         setfattr -x user.$(basename $tdir) $DIR/$tdir ||
13534                 error "$testfile error deleting user.author1"
13535         getfattr -d -m user.$(basename $tdir) 2> /dev/null |
13536                 grep "user.$(basename $tdir)" &&
13537                 error "$tdir did not delete user.$(basename $tdir)"
13538         rmdir $DIR/$tdir || error "rmdir"
13539
13540         #striped directory
13541         test_mkdir $DIR/$tdir
13542         setfattr -n user.$(basename $tdir) $DIR/$tdir || error "setfattr dir"
13543         getfattr -n user.$(basename $tdir) $DIR/$tdir || error "getfattr dir"
13544         setfattr -x user.$(basename $tdir) $DIR/$tdir ||
13545                 error "$testfile error deleting user.author1"
13546         getfattr -d -m user.$(basename $tdir) 2> /dev/null |
13547                 grep "user.$(basename $tdir)" &&
13548                 error "$tdir did not delete user.$(basename $tdir)"
13549         rmdir $DIR/$tdir || error "rm striped dir"
13550 }
13551 run_test 102r "set EAs with empty values"
13552
13553 test_102s() {
13554         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
13555                 skip "MDS needs to be at least 2.11.52"
13556
13557         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
13558
13559         save_lustre_params client "llite.*.xattr_cache" > $save
13560
13561         for cache in 0 1; do
13562                 lctl set_param llite.*.xattr_cache=$cache
13563
13564                 rm -f $DIR/$tfile
13565                 touch $DIR/$tfile || error "touch"
13566                 for prefix in lustre security system trusted user; do
13567                         # Note getxattr() may fail with 'Operation not
13568                         # supported' or 'No such attribute' depending
13569                         # on prefix and cache.
13570                         getfattr -n $prefix.n102s $DIR/$tfile &&
13571                                 error "getxattr '$prefix.n102s' should fail (cache = $cache)"
13572                 done
13573         done
13574
13575         restore_lustre_params < $save
13576 }
13577 run_test 102s "getting nonexistent xattrs should fail"
13578
13579 test_102t() {
13580         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
13581                 skip "MDS needs to be at least 2.11.52"
13582
13583         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
13584
13585         save_lustre_params client "llite.*.xattr_cache" > $save
13586
13587         for cache in 0 1; do
13588                 lctl set_param llite.*.xattr_cache=$cache
13589
13590                 for buf_size in 0 256; do
13591                         rm -f $DIR/$tfile
13592                         touch $DIR/$tfile || error "touch"
13593                         setfattr -n user.multiop $DIR/$tfile
13594                         $MULTIOP $DIR/$tfile oa$buf_size ||
13595                                 error "cannot get zero length xattr value (buf_size = $buf_size)"
13596                 done
13597         done
13598
13599         restore_lustre_params < $save
13600 }
13601 run_test 102t "zero length xattr values handled correctly"
13602
13603 run_acl_subtest()
13604 {
13605         local test=$LUSTRE/tests/acl/$1.test
13606         local tmp=$(mktemp -t $1-XXXXXX).test
13607         local bin=$2
13608         local dmn=$3
13609         local grp=$4
13610         local nbd=$5
13611         export LANG=C
13612
13613
13614         local sedusers="-e s/bin/$bin/g -e s/daemon/$dmn/g"
13615         local sedgroups="-e s/:users/:$grp/g"
13616         [[ -z "$nbd" ]] || sedusers+=" -e s/nobody/$nbd/g"
13617
13618         sed $sedusers $sedgroups < $test > $tmp
13619         stack_trap "rm -f $tmp"
13620         [[ -s $tmp ]] || error "sed failed to create test script"
13621
13622         echo "performing $1 with bin='$bin' daemon='$dmn' users='$grp'..."
13623         $LUSTRE/tests/acl/run $tmp || error "run_acl_subtest '$1' failed"
13624 }
13625
13626 test_103a() {
13627         [ "$UID" != 0 ] && skip "must run as root"
13628         $GSS && skip_env "could not run under gss"
13629         [[ "$(lctl get_param -n mdc.*-mdc-*.connect_flags)" =~ "acl" ]] ||
13630                 skip_env "must have acl enabled"
13631         which setfacl || skip_env "could not find setfacl"
13632         remote_mds_nodsh && skip "remote MDS with nodsh"
13633
13634         local mdts=$(comma_list $(mdts_nodes))
13635         local saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
13636
13637         [[ -z "$saved" ]] || do_nodes $mdts $LCTL set_param mdt.*.job_xattr=NONE
13638         stack_trap "[[ -z \"$saved\" ]] || \
13639                     do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$saved" EXIT
13640
13641         ACLBIN=${ACLBIN:-"bin"}
13642         ACLDMN=${ACLDMN:-"daemon"}
13643         ACLGRP=${ACLGRP:-"users"}
13644         ACLNBD=${ACLNBD:-"nobody"}
13645
13646         if ! id $ACLBIN ||
13647            [[ "$(id -u $ACLBIN)" != "$(do_facet mds1 id -u $ACLBIN)" ]]; then
13648                 echo "bad 'bin' user '$ACLBIN', using '$USER0'"
13649                 ACLBIN=$USER0
13650                 if ! id $ACLBIN ; then
13651                         cat /etc/passwd
13652                         skip_env "can't find suitable ACL 'bin' $ACLBIN"
13653                 fi
13654         fi
13655         if ! id $ACLDMN || (( $(id -u $ACLDMN) < $(id -u $ACLBIN) )) ||
13656            [[ "$(id -u $ACLDMN)" != "$(do_facet mds1 id -u $ACLDMN)" ]]; then
13657                 echo "bad 'daemon' user '$ACLDMN', using '$USER1'"
13658                 ACLDMN=$USER1
13659                 if ! id $ACLDMN ; then
13660                         cat /etc/passwd
13661                         skip_env "can't find suitable ACL 'daemon' $ACLDMN"
13662                 fi
13663         fi
13664         if ! getent group $ACLGRP; then
13665                 echo "missing 'users' group '$ACLGRP', using '$TSTUSR'"
13666                 ACLGRP="$TSTUSR"
13667                 if ! getent group $ACLGRP; then
13668                         echo "cannot find group '$ACLGRP', adding it"
13669                         cat /etc/group
13670                         add_group 60000 $ACLGRP
13671                 fi
13672         fi
13673
13674         local bingid=$(getent group $ACLBIN | cut -d: -f 3)
13675         local dmngid=$(getent group $ACLDMN | cut -d: -f 3)
13676         local grpgid=$(getent group $ACLGRP | cut -d: -f 3)
13677
13678         if (( $bingid > $grpgid || $dmngid > $grpgid )); then
13679                 echo "group '$ACLGRP' has low gid=$grpgid, use '$TSTUSR'"
13680                 ACLGRP="$TSTUSR"
13681                 if ! getent group $ACLGRP; then
13682                         echo "cannot find group '$ACLGRP', adding it"
13683                         cat /etc/group
13684                         add_group 60000 $ACLGRP
13685                 fi
13686                 grpgid=$(getent group $ACLGRP | cut -d: -f 3)
13687                 if (( $bingid > $grpgid || $dmngid > $grpgid )); then
13688                         cat /etc/group
13689                         skip_env "$ACLGRP gid=$grpgid less than $bingid|$dmngid"
13690                 fi
13691         fi
13692
13693         gpasswd -a $ACLDMN $ACLBIN ||
13694                 error "setting client group failed"             # LU-5641
13695         do_facet mds1 gpasswd -a $ACLDMN $ACLBIN ||
13696                 error "setting MDS group failed"                # LU-5641
13697
13698         declare -a identity_old
13699
13700         for ((num = 1; num <= $MDSCOUNT; num++)); do
13701                 switch_identity $num true || identity_old[$num]=$?
13702         done
13703
13704         SAVE_UMASK=$(umask)
13705         umask 0022
13706         $LFS mkdir -c1 -i0 $DIR/$tdir
13707         cd $DIR/$tdir
13708
13709         run_acl_subtest cp $ACLBIN $ACLDMN $ACLGRP
13710         run_acl_subtest getfacl-noacl $ACLBIN $ACLDMN $ACLGRP
13711         run_acl_subtest misc $ACLBIN $ACLDMN $ACLGRP
13712         run_acl_subtest permissions $ACLBIN $ACLDMN $ACLGRP
13713         # LU-1482 mdd: Setting xattr are properly checked with and without ACLs
13714         # CentOS7- uses nobody=99, while newer distros use nobody=65534
13715         if ! id -u $ACLNBD ||
13716            (( $(id -u nobody) != $(do_facet mds1 id -u nobody) )); then
13717                 ACLNBD="nfsnobody"
13718                 if ! id -u $ACLNBD; then
13719                         ACLNBD=""
13720                 fi
13721         fi
13722         if [[ -n "$ACLNBD" ]] && ! getent group $ACLNBD; then
13723                 add_group $(id -u $ACLNBD) $ACLNBD
13724                 if ! getent group $ACLNBD; then
13725                         ACLNBD=""
13726                 fi
13727         fi
13728         if (( $MDS1_VERSION > $(version_code 2.8.55) )) &&
13729            [[ -n "$ACLNBD" ]] && which setfattr; then
13730                 run_acl_subtest permissions_xattr \
13731                         $ACLBIN $ACLDMN $ACLGRP $ACLNBD
13732         elif [[ -z "$ACLNBD" ]]; then
13733                 echo "skip 'permission_xattr' test - missing 'nobody' user/grp"
13734         else
13735                 echo "skip 'permission_xattr' test - missing setfattr command"
13736         fi
13737         run_acl_subtest setfacl $ACLBIN $ACLDMN $ACLGRP
13738
13739         # inheritance test got from HP
13740         cp $LUSTRE/tests/acl/make-tree . || error "cannot copy make-tree"
13741         chmod +x make-tree || error "chmod +x failed"
13742         run_acl_subtest inheritance $ACLBIN $ACLDMN $ACLGRP
13743         rm -f make-tree
13744
13745         echo "LU-974 ignore umask when acl is enabled..."
13746         run_acl_subtest 974 $ACLBIN $ACLDMN $ACLGRP
13747         if [ $MDSCOUNT -ge 2 ]; then
13748                 run_acl_subtest 974_remote $ACLBIN $ACLDMN $ACLGRP
13749         fi
13750
13751         echo "LU-2561 newly created file is same size as directory..."
13752         if [ "$mds1_FSTYPE" != "zfs" ]; then
13753                 run_acl_subtest 2561 $ACLBIN $ACLDMN $ACLGRP
13754         else
13755                 run_acl_subtest 2561_zfs $ACLBIN $ACLDMN $ACLGRP
13756         fi
13757
13758         run_acl_subtest 4924 $ACLBIN $ACLDMN $ACLGRP
13759
13760         cd $SAVE_PWD
13761         umask $SAVE_UMASK
13762
13763         for ((num = 1; num <= $MDSCOUNT; num++)); do
13764                 if [[ "${identity_old[$num]}" == 1 ]]; then
13765                         switch_identity $num false || identity_old[$num]=$?
13766                 fi
13767         done
13768 }
13769 run_test 103a "acl test"
13770
13771 test_103b() {
13772         declare -a pids
13773         local U
13774
13775         stack_trap "rm -f $DIR/$tfile.*"
13776         for U in {0..511}; do
13777                 {
13778                 local O=$(printf "%04o" $U)
13779
13780                 umask $(printf "%04o" $((511 ^ $O)))
13781                 $LFS setstripe -c 1 $DIR/$tfile.s$O
13782                 local S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.s$O))
13783
13784                 (( $S == ($O & 0666) )) ||
13785                         error "lfs setstripe $DIR/$tfile.s$O '$S' != '$O'"
13786
13787                 $LFS setstripe -E16M -c 1 -E1G -S4M $DIR/$tfile.p$O
13788                 S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.p$O))
13789                 (( $S == ($O & 0666) )) ||
13790                         error "lfs setstripe -E $DIR/$tfile.p$O '$S' != '$O'"
13791
13792                 $LFS setstripe -N2 -c 1 $DIR/$tfile.m$O
13793                 S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.m$O))
13794                 (( $S == ($O & 0666) )) ||
13795                         error "lfs setstripe -N2 $DIR/$tfile.m$O '$S' != '$O'"
13796                 rm -f $DIR/$tfile.[smp]$0
13797                 } &
13798                 local pid=$!
13799
13800                 # limit the concurrently running threads to 64. LU-11878
13801                 local idx=$((U % 64))
13802                 [ -z "${pids[idx]}" ] || wait ${pids[idx]}
13803                 pids[idx]=$pid
13804         done
13805         wait
13806 }
13807 run_test 103b "umask lfs setstripe"
13808
13809 test_103c() {
13810         mkdir -p $DIR/$tdir
13811         cp -rp $DIR/$tdir $DIR/$tdir.bak
13812
13813         [ -n "$(getfattr -d -m. $DIR/$tdir | grep posix_acl_default)" ] &&
13814                 error "$DIR/$tdir shouldn't contain default ACL"
13815         [ -n "$(getfattr -d -m. $DIR/$tdir.bak | grep posix_acl_default)" ] &&
13816                 error "$DIR/$tdir.bak shouldn't contain default ACL"
13817         true
13818 }
13819 run_test 103c "'cp -rp' won't set empty acl"
13820
13821 test_103e() {
13822         local numacl
13823         local fileacl
13824         local saved_debug=$($LCTL get_param -n debug)
13825
13826         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
13827                 skip "MDS needs to be at least 2.14.52"
13828
13829         large_xattr_enabled || skip_env "ea_inode feature disabled"
13830
13831         mkdir -p $DIR/$tdir
13832         # add big LOV EA to cause reply buffer overflow earlier
13833         $LFS setstripe -C 1000 $DIR/$tdir
13834         lctl set_param mdc.*-mdc*.stats=clear
13835
13836         $LCTL set_param debug=0
13837         stack_trap "$LCTL set_param debug=\"$saved_debug\"" EXIT
13838         stack_trap "$LCTL get_param mdc.*-mdc*.stats" EXIT
13839
13840         # add a large number of default ACLs (expect 8000+ for 2.13+)
13841         for U in {2..7000}; do
13842                 setfacl -d -m user:$U:rwx $DIR/$tdir ||
13843                         error "Able to add just $U default ACLs"
13844         done
13845         numacl=$(getfacl $DIR/$tdir |& grep -c "default:user")
13846         echo "$numacl default ACLs created"
13847
13848         stat $DIR/$tdir || error "Cannot stat directory"
13849         # check file creation
13850         touch $DIR/$tdir/$tfile ||
13851                 error "failed to create $tfile with $numacl default ACLs"
13852         stat $DIR/$tdir/$tfile  || error "Cannot stat file"
13853         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
13854         echo "$fileacl ACLs were inherited"
13855         (( $fileacl == $numacl )) ||
13856                 error "Not all default ACLs were inherited: $numacl != $fileacl"
13857         # check that new ACLs creation adds new ACLs to inherited ACLs
13858         setfacl -m user:19000:rwx $DIR/$tdir/$tfile ||
13859                 error "Cannot set new ACL"
13860         numacl=$((numacl + 1))
13861         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
13862         (( $fileacl == $numacl )) ||
13863                 error "failed to add new ACL: $fileacl != $numacl as expected"
13864         # adds more ACLs to a file to reach their maximum at 8000+
13865         numacl=0
13866         for U in {20000..25000}; do
13867                 setfacl -m user:$U:rwx $DIR/$tdir/$tfile || break
13868                 numacl=$((numacl + 1))
13869         done
13870         echo "Added $numacl more ACLs to the file"
13871         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
13872         echo "Total $fileacl ACLs in file"
13873         stat $DIR/$tdir/$tfile > /dev/null || error "Cannot stat file"
13874         rm -f $DIR/$tdir/$tfile || error "Cannot remove file"
13875         rmdir $DIR/$tdir || error "Cannot remove directory"
13876 }
13877 run_test 103e "inheritance of big amount of default ACLs"
13878
13879 test_103f() {
13880         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
13881                 skip "MDS needs to be at least 2.14.51"
13882
13883         large_xattr_enabled || skip_env "ea_inode feature disabled"
13884
13885         # enable changelog to consume more internal MDD buffers
13886         changelog_register
13887
13888         mkdir -p $DIR/$tdir
13889         # add big LOV EA
13890         $LFS setstripe -C 1000 $DIR/$tdir
13891         setfacl -d -m user:$U:rwx $DIR/$tdir || error "Cannot add default ACLs"
13892         mkdir $DIR/$tdir/inherited || error "failed to create subdirectory"
13893         rmdir $DIR/$tdir/inherited || error "Cannot remove subdirectory"
13894         rmdir $DIR/$tdir || error "Cannot remove directory"
13895 }
13896 run_test 103f "changelog doesn't interfere with default ACLs buffers"
13897
13898 test_104a() {
13899         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13900
13901         touch $DIR/$tfile
13902         lfs df || error "lfs df failed"
13903         lfs df -ih || error "lfs df -ih failed"
13904         lfs df -h $DIR || error "lfs df -h $DIR failed"
13905         lfs df -i $DIR || error "lfs df -i $DIR failed"
13906         lfs df $DIR/$tfile || error "lfs df $DIR/$tfile failed"
13907         lfs df -ih $DIR/$tfile || error "lfs df -ih $DIR/$tfile failed"
13908
13909         local OSC=$(lctl dl | grep OST0000-osc-[^M] | awk '{ print $4 }')
13910         lctl --device %$OSC deactivate
13911         lfs df || error "lfs df with deactivated OSC failed"
13912         lctl --device %$OSC activate
13913         # wait the osc back to normal
13914         wait_osc_import_ready client ost
13915
13916         lfs df || error "lfs df with reactivated OSC failed"
13917         rm -f $DIR/$tfile
13918 }
13919 run_test 104a "lfs df [-ih] [path] test ========================="
13920
13921 test_104b() {
13922         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13923         [ $RUNAS_ID -eq $UID ] &&
13924                 skip_env "RUNAS_ID = UID = $UID -- skipping"
13925
13926         denied_cnt=$(($($RUNAS $LFS check servers 2>&1 |
13927                         grep "Permission denied" | wc -l)))
13928         if [ $denied_cnt -ne 0 ]; then
13929                 error "lfs check servers test failed"
13930         fi
13931 }
13932 run_test 104b "$RUNAS lfs check servers test ===================="
13933
13934 #
13935 # Verify $1 is within range of $2.
13936 # Success when $1 is within range. That is, when $1 is >= 2% of $2 and
13937 # $1 is <= 2% of $2. Else Fail.
13938 #
13939 value_in_range() {
13940         # Strip all units (M, G, T)
13941         actual=$(echo $1 | tr -d A-Z)
13942         expect=$(echo $2 | tr -d A-Z)
13943
13944         expect_lo=$(($expect * 98 / 100)) # 2% below
13945         expect_hi=$(($expect * 102 / 100)) # 2% above
13946
13947         # permit 2% drift above and below
13948         (( $actual >= $expect_lo && $actual <= $expect_hi ))
13949 }
13950
13951 test_104c() {
13952         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13953         [ "$ost1_FSTYPE" == "zfs" ] || skip "zfs only test"
13954
13955         local ost_param="osd-zfs.$FSNAME-OST0000."
13956         local mdt_param="osd-zfs.$FSNAME-MDT0000."
13957         local ofacets=$(get_facets OST)
13958         local mfacets=$(get_facets MDS)
13959         local saved_ost_blocks=
13960         local saved_mdt_blocks=
13961
13962         echo "Before recordsize change"
13963         lfs_df=($($LFS df -h | grep "filesystem_summary:"))
13964         df=($(df -h | grep "$MOUNT"$))
13965
13966         # For checking.
13967         echo "lfs output : ${lfs_df[*]}"
13968         echo "df  output : ${df[*]}"
13969
13970         for facet in ${ofacets//,/ }; do
13971                 if [ -z $saved_ost_blocks ]; then
13972                         saved_ost_blocks=$(do_facet $facet \
13973                                 lctl get_param -n $ost_param.blocksize)
13974                         echo "OST Blocksize: $saved_ost_blocks"
13975                 fi
13976                 ost=$(do_facet $facet lctl get_param -n $ost_param.mntdev)
13977                 do_facet $facet zfs set recordsize=32768 $ost
13978         done
13979
13980         # BS too small. Sufficient for functional testing.
13981         for facet in ${mfacets//,/ }; do
13982                 if [ -z $saved_mdt_blocks ]; then
13983                         saved_mdt_blocks=$(do_facet $facet \
13984                                 lctl get_param -n $mdt_param.blocksize)
13985                         echo "MDT Blocksize: $saved_mdt_blocks"
13986                 fi
13987                 mdt=$(do_facet $facet lctl get_param -n $mdt_param.mntdev)
13988                 do_facet $facet zfs set recordsize=32768 $mdt
13989         done
13990
13991         # Give new values chance to reflect change
13992         sleep 2
13993
13994         echo "After recordsize change"
13995         lfs_df_after=($($LFS df -h | grep "filesystem_summary:"))
13996         df_after=($(df -h | grep "$MOUNT"$))
13997
13998         # For checking.
13999         echo "lfs output : ${lfs_df_after[*]}"
14000         echo "df  output : ${df_after[*]}"
14001
14002         # Verify lfs df
14003         value_in_range ${lfs_df_after[1]%.*} ${lfs_df[1]%.*} ||
14004                 error "lfs_df bytes: ${lfs_df_after[1]%.*} != ${lfs_df[1]%.*}"
14005         value_in_range ${lfs_df_after[2]%.*} ${lfs_df[2]%.*} ||
14006                 error "lfs_df used: ${lfs_df_after[2]%.*} != ${lfs_df[2]%.*}"
14007         value_in_range ${lfs_df_after[3]%.*} ${lfs_df[3]%.*} ||
14008                 error "lfs_df avail: ${lfs_df_after[3]%.*} != ${lfs_df[3]%.*}"
14009
14010         # Verify df
14011         value_in_range ${df_after[1]%.*} ${df[1]%.*} ||
14012                 error "df bytes: ${df_after[1]%.*} != ${df[1]%.*}"
14013         value_in_range ${df_after[2]%.*} ${df[2]%.*} ||
14014                 error "df used: ${df_after[2]%.*} != ${df[2]%.*}"
14015         value_in_range ${df_after[3]%.*} ${df[3]%.*} ||
14016                 error "df avail: ${df_after[3]%.*} != ${df[3]%.*}"
14017
14018         # Restore MDT recordize back to original
14019         for facet in ${mfacets//,/ }; do
14020                 mdt=$(do_facet $facet lctl get_param -n $mdt_param.mntdev)
14021                 do_facet $facet zfs set recordsize=$saved_mdt_blocks $mdt
14022         done
14023
14024         # Restore OST recordize back to original
14025         for facet in ${ofacets//,/ }; do
14026                 ost=$(do_facet $facet lctl get_param -n $ost_param.mntdev)
14027                 do_facet $facet zfs set recordsize=$saved_ost_blocks $ost
14028         done
14029
14030         return 0
14031 }
14032 run_test 104c "Verify df vs lfs_df stays same after recordsize change"
14033
14034 test_104d() {
14035         (( $RUNAS_ID != $UID )) ||
14036                 skip_env "RUNAS_ID = UID = $UID -- skipping"
14037
14038         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) ||
14039                 skip "lustre version doesn't support lctl dl with non-root"
14040
14041         # debugfs only allows root users to access files, so the
14042         # previous move of the "devices" file to debugfs broke
14043         # "lctl dl" for non-root users. The LU-9680 Netlink
14044         # interface again allows non-root users to list devices.
14045         [ "$($RUNAS $LCTL dl | wc -l)" -ge 3 ] ||
14046                 error "lctl dl doesn't work for non root"
14047
14048         ost_count="$($RUNAS $LCTL dl | grep $FSNAME-OST* | wc -l)"
14049         [ "$ost_count" -eq $OSTCOUNT ]  ||
14050                 error "lctl dl reports wrong number of OST devices"
14051
14052         mdt_count="$($RUNAS $LCTL dl | grep $FSNAME-MDT* | wc -l)"
14053         [ "$mdt_count" -eq $MDSCOUNT ]  ||
14054                 error "lctl dl reports wrong number of MDT devices"
14055 }
14056 run_test 104d "$RUNAS lctl dl test"
14057
14058 test_105a() {
14059         # doesn't work on 2.4 kernels
14060         touch $DIR/$tfile
14061         if $(flock_is_enabled); then
14062                 flocks_test 1 on -f $DIR/$tfile || error "fail flock on"
14063         else
14064                 flocks_test 1 off -f $DIR/$tfile || error "fail flock off"
14065         fi
14066         rm -f $DIR/$tfile
14067 }
14068 run_test 105a "flock when mounted without -o flock test ========"
14069
14070 test_105b() {
14071         touch $DIR/$tfile
14072         if $(flock_is_enabled); then
14073                 flocks_test 1 on -c $DIR/$tfile || error "fail flock on"
14074         else
14075                 flocks_test 1 off -c $DIR/$tfile || error "fail flock off"
14076         fi
14077         rm -f $DIR/$tfile
14078 }
14079 run_test 105b "fcntl when mounted without -o flock test ========"
14080
14081 test_105c() {
14082         touch $DIR/$tfile
14083         if $(flock_is_enabled); then
14084                 flocks_test 1 on -l $DIR/$tfile || error "fail flock on"
14085         else
14086                 flocks_test 1 off -l $DIR/$tfile || error "fail flock off"
14087         fi
14088         rm -f $DIR/$tfile
14089 }
14090 run_test 105c "lockf when mounted without -o flock test"
14091
14092 test_105d() { # bug 15924
14093         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14094
14095         test_mkdir $DIR/$tdir
14096         flock_is_enabled || skip_env "mount w/o flock enabled"
14097         #define OBD_FAIL_LDLM_CP_CB_WAIT  0x315
14098         $LCTL set_param fail_loc=0x80000315
14099         flocks_test 2 $DIR/$tdir
14100 }
14101 run_test 105d "flock race (should not freeze) ========"
14102
14103 test_105e() { # bug 22660 && 22040
14104         flock_is_enabled || skip_env "mount w/o flock enabled"
14105
14106         touch $DIR/$tfile
14107         flocks_test 3 $DIR/$tfile
14108 }
14109 run_test 105e "Two conflicting flocks from same process"
14110
14111 wait_end() {
14112         echo $*
14113         while :; do
14114                 [ -f $TMP/${tfile}_sTOP ] && return
14115                 sleep 1
14116         done
14117 }
14118
14119 test_105f() {
14120         flock_is_enabled || skip_env "mount w/o flock enabled"
14121
14122         local pmax=$(ulimit -u)
14123         local i=0
14124         touch $DIR/$tfile
14125         [ $pmax -gt 20 ] && pmax=20
14126         for((i=0; i <= $pmax; i++)) {
14127                 wait_end "R4000, 5000" | flocks_test 6 $DIR/$tfile &
14128         }
14129         for((i=0; i <= 10; i++)) {
14130                 local locks=$(do_facet $SINGLEMDS $LCTL get_param -n \
14131                         ldlm.namespaces.mdt-${FSNAME}-MDT0000*.lock_count)
14132                 [ $locks -ge $pmax ] && break
14133                 [ $i -eq 10 ] && error "The locks cannot be added after 10 secs"
14134                 sleep 1
14135         }
14136         touch $TMP/${tfile}_sTOP
14137         wait
14138         rm -r $DIR/$tfile $TMP/${tfile}_sTOP
14139 }
14140 run_test 105f "Enqueue same range flocks"
14141
14142 test_105g() {
14143         (( $CLIENT_VERSION >= $(version_code 2.15.64.117) )) ||
14144                 skip "Need Client >= 2.15.63.127 for ldlm dump stack"
14145
14146         flock_is_enabled || skip_env "mount w/o flock enabled"
14147         mkdir $DIR/$tdir
14148         #define OBD_FAIL_LDLM_LOCK_STACK  0x32f
14149         do_facet client $LCTL set_param -n \
14150                 ldlm.namespaces.*.dump_stack_on_error=1
14151         stack_trap "do_facet client $LCTL set_param -n \
14152                 ldlm.namespaces.*.dump_stack_on_error=0"
14153         $LCTL set_param fail_loc=0x8000032f
14154         flocks_test 2 $DIR/$tdir
14155         dmesg | tac | sed "/$(echo $TESTNAME | tr '_' ' ')/,$ d" |
14156                 grep -q "dump_stack" || error "didn't find dump_stack"
14157 }
14158 run_test 105g "ldlm_lock_debug stack test"
14159
14160 test_105h() {
14161         local info
14162         touch $DIR/$tfile
14163
14164         stack_trap "rm $DIR/$tfile" EXIT
14165         # enqueue 2 non-overlap locks
14166         info=$(echo -e "W20,40\nR100,200\nT0" | flocks_test 6 $DIR/$tfile)
14167         [ x$info == 'xW20,40;R100,200.' ] || error "flock error1-$info"
14168         # enqueue overlap locks
14169         info=$(echo -e "W20,400\nR100,2000\nR10,1000\nW500,1000\nT0" | flocks_test 6 $DIR/$tfile)
14170         [ x$info == 'xR10,490;W500,1000;R1500,600.' ] || error "flock error2-$info"
14171         # split a lock
14172         info=$(echo -e "W2000,1000\nR2200, 200\nT0" |flocks_test 6 $DIR/$tfile)
14173         [ x$info == 'xW2000,200;R2200,200;W2400,600.' ] || error "flock error3-$info"
14174         # merge 2 locks
14175         info=$(echo -e "R200,1000\nR9000,200\nW100,10000\nT0" | flocks_test 6 $DIR/$tfile)
14176         [ x$info == 'xW100,10000.' ] || error "flock error4-$info"
14177         # adjoining locks
14178         info=$(echo -e "R200,100\nR300, 200\nR500,100\nT0" | flocks_test 6 $DIR/$tfile)
14179         [ x$info == 'xR200,400.' ] || error "flock error5-$info"
14180         # adjoining locks with diff mode
14181         info=$(echo -e "R200,100\nW300, 200\nR500,100\nT0" | flocks_test 6 $DIR/$tfile)
14182         [ x$info == 'xR200,100;W300,200;R500,100.' ] || error "flock error6-$info"
14183         # split & merge
14184         info=$(echo -e "R200,1000\nW300, 200\nR100,200\nR300,200\nT0" | flocks_test 6 $DIR/$tfile)
14185         [ x$info == 'xR100,1100.' ] || error "flock error7-$info"
14186 }
14187 run_test 105h "Flock functional verify"
14188
14189 test_105i() {
14190         local tmpfile=$TMP/tmpf.$$
14191         touch $DIR/$tfile
14192
14193         stack_trap "rm $tmpfile $DIR/$tfile" EXIT
14194         # enqueue 2 non-overlap locks
14195         >$tmpfile
14196         echo -e "R20,200\nP5\nW10,1000" | flocks_test 6 $DIR/$tfile 2>>$tmpfile &
14197         echo -e "R20,200\nP5\nW10,1000" | flocks_test 6 $DIR/$tfile 2>>$tmpfile &
14198         wait
14199         # Check for EDEADLK
14200         grep 'cannot set lock(35)' $tmpfile
14201 }
14202 run_test 105i "Flock deadlock verify"
14203
14204 test_106() { #bug 10921
14205         test_mkdir $DIR/$tdir
14206         $DIR/$tdir && error "exec $DIR/$tdir succeeded"
14207         chmod 777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
14208 }
14209 run_test 106 "attempt exec of dir followed by chown of that dir"
14210
14211 test_107() {
14212         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14213
14214         CDIR=`pwd`
14215         local file=core
14216
14217         cd $DIR
14218         rm -f $file
14219
14220         local save_pattern=$(sysctl -n kernel.core_pattern)
14221         local save_uses_pid=$(sysctl -n kernel.core_uses_pid)
14222         sysctl -w kernel.core_pattern=$file
14223         sysctl -w kernel.core_uses_pid=0
14224
14225         ulimit -c unlimited
14226         sleep 60 &
14227         SLEEPPID=$!
14228
14229         sleep 1
14230
14231         kill -s 11 $SLEEPPID
14232         wait $SLEEPPID
14233         if [ -e $file ]; then
14234                 size=`stat -c%s $file`
14235                 [ $size -eq 0 ] && error "Fail to create core file $file"
14236         else
14237                 error "Fail to create core file $file"
14238         fi
14239         rm -f $file
14240         sysctl -w kernel.core_pattern=$save_pattern
14241         sysctl -w kernel.core_uses_pid=$save_uses_pid
14242         cd $CDIR
14243 }
14244 run_test 107 "Coredump on SIG"
14245
14246 test_110() {
14247         test_mkdir $DIR/$tdir
14248         test_mkdir $DIR/$tdir/$(str_repeat 'a' 255)
14249         $LFS mkdir -c $MDSCOUNT $DIR/$tdir/$(str_repeat 'b' 256) &&
14250                 error "mkdir with 256 char should fail, but did not"
14251         touch $DIR/$tdir/$(str_repeat 'x' 255) ||
14252                 error "create with 255 char failed"
14253         touch $DIR/$tdir/$(str_repeat 'y' 256) &&
14254                 error "create with 256 char should fail, but did not"
14255
14256         ls -l $DIR/$tdir
14257         rm -rf $DIR/$tdir
14258 }
14259 run_test 110 "filename length checking"
14260
14261 test_116a() { # was previously test_116()
14262         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14263         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
14264         remote_mds_nodsh && skip "remote MDS with nodsh"
14265
14266         echo -n "Free space priority "
14267         do_facet $SINGLEMDS lctl get_param -n lo[vd].*-mdtlov.qos_prio_free |
14268                 head -n1
14269         declare -a AVAIL
14270         free_min_max
14271
14272         [ $MINV -eq 0 ] && skip "no free space in OST$MINI, skip"
14273         [ $MINV -gt 10000000 ] && skip "too much free space in OST$MINI, skip"
14274         stack_trap simple_cleanup_common
14275
14276         # Check if we need to generate uneven OSTs
14277         test_mkdir -p $DIR/$tdir/OST${MINI}
14278         local FILL=$((MINV / 4))
14279         local DIFF=$((MAXV - MINV))
14280         local DIFF2=$((DIFF * 100 / MINV))
14281
14282         local threshold=$(do_facet $SINGLEMDS \
14283                 lctl get_param -n *.*MDT0000-mdtlov.qos_threshold_rr | head -n1)
14284         threshold=${threshold%%%}
14285         echo -n "Check for uneven OSTs: "
14286         echo -n "diff=${DIFF}KB (${DIFF2}%) must be > ${threshold}% ..."
14287
14288         if [[ $DIFF2 -gt $threshold ]]; then
14289                 echo "ok"
14290                 echo "Don't need to fill OST$MINI"
14291         else
14292                 # generate uneven OSTs. Write 2% over the QOS threshold value
14293                 echo "no"
14294                 DIFF=$((threshold - DIFF2 + 2))
14295                 DIFF2=$((MINV * DIFF / 100))
14296                 echo "Fill $DIFF% remaining space in OST$MINI with ${DIFF2}KB"
14297                 $LFS setstripe -i $MINI -c 1 $DIR/$tdir/OST${MINI} ||
14298                         error "setstripe failed"
14299                 DIFF=$((DIFF2 / 2048))
14300                 i=0
14301                 while [ $i -lt $DIFF ]; do
14302                         i=$((i + 1))
14303                         dd if=/dev/zero of=$DIR/$tdir/OST${MINI}/$tfile-$i \
14304                                 bs=2M count=1 2>/dev/null
14305                         echo -n .
14306                 done
14307                 echo .
14308                 sync
14309                 sleep_maxage
14310                 free_min_max
14311         fi
14312
14313         DIFF=$((MAXV - MINV))
14314         DIFF2=$((DIFF * 100 / MINV))
14315         echo -n "diff=$DIFF=$DIFF2% must be > $threshold% for QOS mode..."
14316         if [ $DIFF2 -gt $threshold ]; then
14317                 echo "ok"
14318         else
14319                 skip "QOS imbalance criteria not met"
14320         fi
14321
14322         MINI1=$MINI
14323         MINV1=$MINV
14324         MAXI1=$MAXI
14325         MAXV1=$MAXV
14326
14327         # now fill using QOS
14328         $LFS setstripe -c 1 $DIR/$tdir
14329         FILL=$((FILL / 200))
14330         if [ $FILL -gt 600 ]; then
14331                 FILL=600
14332         fi
14333         echo "writing $FILL files to QOS-assigned OSTs"
14334         i=0
14335         while [ $i -lt $FILL ]; do
14336                 i=$((i + 1))
14337                 dd if=/dev/zero of=$DIR/$tdir/$tfile-$i bs=200k \
14338                         count=1 2>/dev/null
14339                 echo -n .
14340         done
14341         echo "wrote $i 200k files"
14342         sync
14343         sleep_maxage
14344
14345         echo "Note: free space may not be updated, so measurements might be off"
14346         free_min_max
14347         DIFF2=$((MAXV - MINV))
14348         echo "free space delta: orig $DIFF final $DIFF2"
14349         [ $DIFF2 -gt $DIFF ] && echo "delta got worse!"
14350         DIFF=$((MINV1 - ${AVAIL[$MINI1]}))
14351         echo "Wrote ${DIFF}KB to smaller OST $MINI1"
14352         DIFF2=$((MAXV1 - ${AVAIL[$MAXI1]}))
14353         echo "Wrote ${DIFF2}KB to larger OST $MAXI1"
14354         if [[ $DIFF -gt 0 ]]; then
14355                 FILL=$((DIFF2 * 100 / DIFF - 100))
14356                 echo "Wrote ${FILL}% more data to larger OST $MAXI1"
14357         fi
14358
14359         # Figure out which files were written where
14360         UUID=$(lctl get_param -n lov.${FSNAME}-clilov-*.target_obd |
14361                awk '/'$MINI1': / {print $2; exit}')
14362         echo $UUID
14363         MINC=$($LFS getstripe --ost $UUID $DIR/$tdir | grep $DIR | wc -l)
14364         echo "$MINC files created on smaller OST $MINI1"
14365         UUID=$(lctl get_param -n lov.${FSNAME}-clilov-*.target_obd |
14366                awk '/'$MAXI1': / {print $2; exit}')
14367         echo $UUID
14368         MAXC=$($LFS getstripe --ost $UUID $DIR/$tdir | grep $DIR | wc -l)
14369         echo "$MAXC files created on larger OST $MAXI1"
14370         if [[ $MINC -gt 0 ]]; then
14371                 FILL=$((MAXC * 100 / MINC - 100))
14372                 echo "Wrote ${FILL}% more files to larger OST $MAXI1"
14373         fi
14374         [[ $MAXC -gt $MINC ]] ||
14375                 error_ignore LU-9 "stripe QOS didn't balance free space"
14376 }
14377 run_test 116a "stripe QOS: free space balance ==================="
14378
14379 test_116b() { # LU-2093
14380         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14381         remote_mds_nodsh && skip "remote MDS with nodsh"
14382
14383 #define OBD_FAIL_MDS_OSC_CREATE_FAIL     0x147
14384         local old_rr=$(do_facet $SINGLEMDS lctl get_param -n \
14385                        lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr | head -1)
14386         [ -z "$old_rr" ] && skip "no QOS"
14387         do_facet $SINGLEMDS lctl set_param \
14388                 lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr=0
14389         mkdir -p $DIR/$tdir
14390         do_facet $SINGLEMDS lctl set_param fail_loc=0x147
14391         createmany -o $DIR/$tdir/f- 20 || error "can't create"
14392         do_facet $SINGLEMDS lctl set_param fail_loc=0
14393         rm -rf $DIR/$tdir
14394         do_facet $SINGLEMDS lctl set_param \
14395                 lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr=$old_rr
14396 }
14397 run_test 116b "QoS shouldn't LBUG if not enough OSTs found on the 2nd pass"
14398
14399 test_117() # bug 10891
14400 {
14401         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14402
14403         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
14404         #define OBD_FAIL_OST_SETATTR_CREDITS 0x21e
14405         lctl set_param fail_loc=0x21e
14406         > $DIR/$tfile || error "truncate failed"
14407         lctl set_param fail_loc=0
14408         echo "Truncate succeeded."
14409         rm -f $DIR/$tfile
14410 }
14411 run_test 117 "verify osd extend =========="
14412
14413 NO_SLOW_RESENDCOUNT=4
14414 export OLD_RESENDCOUNT=""
14415 set_resend_count () {
14416         local PROC_RESENDCOUNT="osc.${FSNAME}-OST*-osc-*.resend_count"
14417         OLD_RESENDCOUNT=$(lctl get_param -n $PROC_RESENDCOUNT | head -n1)
14418         lctl set_param -n $PROC_RESENDCOUNT $1
14419         echo resend_count is set to $(lctl get_param -n $PROC_RESENDCOUNT)
14420 }
14421
14422 # for reduce test_118* time (b=14842)
14423 [ "$SLOW" = "no" ] && set_resend_count $NO_SLOW_RESENDCOUNT
14424
14425 # Reset async IO behavior after error case
14426 reset_async() {
14427         FILE=$DIR/reset_async
14428
14429         # Ensure all OSCs are cleared
14430         $LFS setstripe -c -1 $FILE
14431         dd if=/dev/zero of=$FILE bs=64k count=$OSTCOUNT
14432         sync
14433         rm $FILE
14434 }
14435
14436 test_118a() #bug 11710
14437 {
14438         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14439
14440         reset_async
14441
14442         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14443         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14444         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
14445
14446         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14447                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14448                 return 1;
14449         fi
14450         rm -f $DIR/$tfile
14451 }
14452 run_test 118a "verify O_SYNC works =========="
14453
14454 test_118b()
14455 {
14456         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14457         remote_ost_nodsh && skip "remote OST with nodsh"
14458         local osts=$(osts_nodes)
14459
14460         reset_async
14461
14462         #define OBD_FAIL_SRV_ENOENT 0x217
14463         set_nodes_failloc $osts 0x217
14464         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14465         RC=$?
14466         set_nodes_failloc $osts 0
14467         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14468         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14469                     grep -c writeback)
14470
14471         if [[ $RC -eq 0 ]]; then
14472                 error "Must return error due to dropped pages, rc=$RC"
14473                 return 1;
14474         fi
14475
14476         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14477                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14478                 return 1;
14479         fi
14480
14481         echo "Dirty pages not leaked on ENOENT"
14482
14483         # Due to the above error the OSC will issue all RPCs syncronously
14484         # until a subsequent RPC completes successfully without error.
14485         $MULTIOP $DIR/$tfile Ow4096yc
14486         rm -f $DIR/$tfile
14487
14488         return 0
14489 }
14490 run_test 118b "Reclaim dirty pages on fatal error =========="
14491
14492 test_118c()
14493 {
14494         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14495
14496         # for 118c, restore the original resend count, LU-1940
14497         [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] &&
14498                                 set_resend_count $OLD_RESENDCOUNT
14499         remote_ost_nodsh && skip "remote OST with nodsh"
14500         local osts=$(osts_nodes)
14501
14502         reset_async
14503
14504         #define OBD_FAIL_OST_EROFS               0x216
14505         set_nodes_failloc $osts 0x216
14506
14507         # multiop should block due to fsync until pages are written
14508         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
14509         MULTIPID=$!
14510         sleep 1
14511
14512         if [[ `ps h -o comm -p $MULTIPID` != "multiop" ]]; then
14513                 error "Multiop failed to block on fsync, pid=$MULTIPID"
14514         fi
14515
14516         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14517                     grep -c writeback)
14518         if [[ $WRITEBACK -eq 0 ]]; then
14519                 error "No page in writeback, writeback=$WRITEBACK"
14520         fi
14521
14522         set_nodes_failloc $osts 0
14523         wait $MULTIPID
14524         RC=$?
14525         if [[ $RC -ne 0 ]]; then
14526                 error "Multiop fsync failed, rc=$RC"
14527         fi
14528
14529         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14530         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14531                     grep -c writeback)
14532         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14533                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14534         fi
14535
14536         rm -f $DIR/$tfile
14537         echo "Dirty pages flushed via fsync on EROFS"
14538         return 0
14539 }
14540 run_test 118c "Fsync blocks on EROFS until dirty pages are flushed =========="
14541
14542 # continue to use small resend count to reduce test_118* time (b=14842)
14543 [ "$SLOW" = "no" ] && set_resend_count $NO_SLOW_RESENDCOUNT
14544
14545 test_118d()
14546 {
14547         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14548         remote_ost_nodsh && skip "remote OST with nodsh"
14549         local osts=$(osts_nodes)
14550
14551         reset_async
14552
14553         #define OBD_FAIL_OST_BRW_PAUSE_BULK
14554         set_nodes_failloc $osts 0x214
14555         # multiop should block due to fsync until pages are written
14556         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
14557         MULTIPID=$!
14558         sleep 1
14559
14560         if [[ `ps h -o comm -p $MULTIPID` != "multiop" ]]; then
14561                 error "Multiop failed to block on fsync, pid=$MULTIPID"
14562         fi
14563
14564         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14565                     grep -c writeback)
14566         if [[ $WRITEBACK -eq 0 ]]; then
14567                 error "No page in writeback, writeback=$WRITEBACK"
14568         fi
14569
14570         wait $MULTIPID || error "Multiop fsync failed, rc=$?"
14571         set_nodes_failloc $osts 0
14572
14573         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14574         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14575                     grep -c writeback)
14576         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14577                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14578         fi
14579
14580         rm -f $DIR/$tfile
14581         echo "Dirty pages gaurenteed flushed via fsync"
14582         return 0
14583 }
14584 run_test 118d "Fsync validation inject a delay of the bulk =========="
14585
14586 test_118f() {
14587         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14588
14589         reset_async
14590
14591         #define OBD_FAIL_OSC_BRW_PREP_REQ2        0x40a
14592         lctl set_param fail_loc=0x8000040a
14593
14594         # Should simulate EINVAL error which is fatal
14595         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14596         RC=$?
14597         if [[ $RC -eq 0 ]]; then
14598                 error "Must return error due to dropped pages, rc=$RC"
14599         fi
14600
14601         lctl set_param fail_loc=0x0
14602
14603         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
14604         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14605         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14606                     grep -c writeback)
14607         if [[ $LOCKED -ne 0 ]]; then
14608                 error "Locked pages remain in cache, locked=$LOCKED"
14609         fi
14610
14611         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14612                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14613         fi
14614
14615         rm -f $DIR/$tfile
14616         echo "No pages locked after fsync"
14617
14618         reset_async
14619         return 0
14620 }
14621 run_test 118f "Simulate unrecoverable OSC side error =========="
14622
14623 test_118g() {
14624         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14625
14626         reset_async
14627
14628         #define OBD_FAIL_OSC_BRW_PREP_REQ        0x406
14629         lctl set_param fail_loc=0x406
14630
14631         # simulate local -ENOMEM
14632         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14633         RC=$?
14634
14635         lctl set_param fail_loc=0
14636         if [[ $RC -eq 0 ]]; then
14637                 error "Must return error due to dropped pages, rc=$RC"
14638         fi
14639
14640         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
14641         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14642         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14643                         grep -c writeback)
14644         if [[ $LOCKED -ne 0 ]]; then
14645                 error "Locked pages remain in cache, locked=$LOCKED"
14646         fi
14647
14648         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14649                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14650         fi
14651
14652         rm -f $DIR/$tfile
14653         echo "No pages locked after fsync"
14654
14655         reset_async
14656         return 0
14657 }
14658 run_test 118g "Don't stay in wait if we got local -ENOMEM  =========="
14659
14660 test_118h() {
14661         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14662         remote_ost_nodsh && skip "remote OST with nodsh"
14663         local osts=$(osts_nodes)
14664
14665         reset_async
14666
14667         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
14668         set_nodes_failloc $osts 0x20e
14669         # Should simulate ENOMEM error which is recoverable and should be handled by timeout
14670         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14671         RC=$?
14672
14673         set_nodes_failloc $osts 0
14674         if [[ $RC -eq 0 ]]; then
14675                 error "Must return error due to dropped pages, rc=$RC"
14676         fi
14677
14678         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
14679         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14680         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
14681                     grep -c writeback)
14682         if [[ $LOCKED -ne 0 ]]; then
14683                 error "Locked pages remain in cache, locked=$LOCKED"
14684         fi
14685
14686         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14687                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14688         fi
14689
14690         rm -f $DIR/$tfile
14691         echo "No pages locked after fsync"
14692
14693         return 0
14694 }
14695 run_test 118h "Verify timeout in handling recoverables errors  =========="
14696
14697 [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] && set_resend_count $OLD_RESENDCOUNT
14698
14699 test_118i() {
14700         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14701         remote_ost_nodsh && skip "remote OST with nodsh"
14702         local osts=$(osts_nodes)
14703
14704         reset_async
14705
14706         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
14707         set_nodes_failloc $osts 0x20e
14708
14709         # Should simulate ENOMEM error which is recoverable and should be handled by timeout
14710         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
14711         PID=$!
14712         sleep 5
14713         set_nodes_failloc $osts 0
14714
14715         wait $PID
14716         RC=$?
14717         if [[ $RC -ne 0 ]]; then
14718                 error "got error, but should be not, rc=$RC"
14719         fi
14720
14721         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
14722         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14723         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
14724         if [[ $LOCKED -ne 0 ]]; then
14725                 error "Locked pages remain in cache, locked=$LOCKED"
14726         fi
14727
14728         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14729                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14730         fi
14731
14732         rm -f $DIR/$tfile
14733         echo "No pages locked after fsync"
14734
14735         return 0
14736 }
14737 run_test 118i "Fix error before timeout in recoverable error  =========="
14738
14739 [ "$SLOW" = "no" ] && set_resend_count 4
14740
14741 test_118j() {
14742         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14743         remote_ost_nodsh && skip "remote OST with nodsh"
14744         local osts=$(osts_nodes)
14745
14746         reset_async
14747
14748         #define OBD_FAIL_OST_BRW_WRITE_BULK2     0x220
14749         set_nodes_failloc $osts 0x220
14750
14751         # return -EIO from OST
14752         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
14753         RC=$?
14754         set_nodes_failloc $osts 0x0
14755         if [[ $RC -eq 0 ]]; then
14756                 error "Must return error due to dropped pages, rc=$RC"
14757         fi
14758
14759         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
14760         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
14761         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
14762         if [[ $LOCKED -ne 0 ]]; then
14763                 error "Locked pages remain in cache, locked=$LOCKED"
14764         fi
14765
14766         # in recoverable error on OST we want resend and stay until it finished
14767         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
14768                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
14769         fi
14770
14771         rm -f $DIR/$tfile
14772         echo "No pages locked after fsync"
14773
14774         return 0
14775 }
14776 run_test 118j "Simulate unrecoverable OST side error =========="
14777
14778 test_118k()
14779 {
14780         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14781         remote_ost_nodsh && skip "remote OSTs with nodsh"
14782         local osts=$(osts_nodes)
14783
14784         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
14785         set_nodes_failloc $osts 0x20e
14786         test_mkdir $DIR/$tdir
14787
14788         for ((i=0;i<10;i++)); do
14789                 (dd if=/dev/zero of=$DIR/$tdir/$tfile-$i bs=1M count=10 || \
14790                         error "dd to $DIR/$tdir/$tfile-$i failed" )&
14791                 SLEEPPID=$!
14792                 sleep 0.500s
14793                 kill $SLEEPPID
14794                 wait $SLEEPPID
14795         done
14796
14797         set_nodes_failloc $osts 0
14798         rm -rf $DIR/$tdir
14799 }
14800 run_test 118k "bio alloc -ENOMEM and IO TERM handling ========="
14801
14802 test_118l() # LU-646
14803 {
14804         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14805
14806         test_mkdir $DIR/$tdir
14807         $MULTIOP $DIR/$tdir Dy || error "fsync dir failed"
14808         rm -rf $DIR/$tdir
14809 }
14810 run_test 118l "fsync dir"
14811
14812 test_118m() # LU-3066
14813 {
14814         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14815
14816         test_mkdir $DIR/$tdir
14817         $MULTIOP $DIR/$tdir DY || error "fdatasync dir failed"
14818         rm -rf $DIR/$tdir
14819 }
14820 run_test 118m "fdatasync dir ========="
14821
14822 [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] && set_resend_count $OLD_RESENDCOUNT
14823
14824 test_118n()
14825 {
14826         local begin
14827         local end
14828
14829         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14830         remote_ost_nodsh && skip "remote OSTs with nodsh"
14831         local osts=$(osts_nodes)
14832
14833         # Sleep to avoid a cached response.
14834         #define OBD_STATFS_CACHE_SECONDS 1
14835         sleep 2
14836
14837         # Inject a 10 second delay in the OST_STATFS handler.
14838         #define OBD_FAIL_OST_STATFS_DELAY 0x242
14839         set_nodes_failloc $osts 0x242
14840
14841         begin=$SECONDS
14842         stat --file-system $MOUNT > /dev/null
14843         end=$SECONDS
14844
14845         set_nodes_failloc $osts 0
14846
14847         if ((end - begin > 20)); then
14848                 error "statfs took $((end - begin)) seconds, expected 10"
14849         fi
14850 }
14851 run_test 118n "statfs() sends OST_STATFS requests in parallel"
14852
14853 # With unaligned_dio enabled there are no restrictions on dio.
14854 unaligned_dio() {
14855         local udio=0
14856
14857         $LCTL get_param osc.*.import | grep connect_flags: |
14858                 grep -q "unaligned_dio" || udio=1
14859
14860         return $udio
14861 }
14862
14863 # With unaligned_dio enabled there are no restrictions on dio.
14864 unaligned_dio_or_skip()
14865 {
14866         if ! unaligned_dio; then
14867                 skip "Need 'unaligned_dio' support"
14868         fi
14869 }
14870
14871 dio_readv_writev_support()
14872 {
14873         # Kernels after 3.16 work:
14874         (( $(version_code $(uname -r)) >= $(version_code 3.16) )) &&
14875                 return 0
14876         # Lustre with LU-17524 works:
14877         (( $OST1_VERSION > $(version_code 2.15.61.196) )) &&
14878                 return 0
14879
14880         skip "need readv/writev with O_DIRECT support"
14881 }
14882
14883 test_119a() # bug 11737
14884 {
14885         BSIZE=$((512 * 1024))
14886         directio write $DIR/$tfile 0 1 $BSIZE
14887         # We ask to read two blocks, which is more than a file size.
14888         # directio will indicate an error when requested and actual
14889         # sizes aren't equeal (a normal situation in this case) and
14890         # print actual read amount.
14891         NOB=`directio read $DIR/$tfile 0 2 $BSIZE | awk '/error/ {print $6}'`
14892         if [ "$NOB" != "$BSIZE" ]; then
14893                 error "read $NOB bytes instead of $BSIZE"
14894         fi
14895         rm -f $DIR/$tfile
14896 }
14897 run_test 119a "Short directIO read must return actual read amount"
14898
14899 test_119b() # bug 11737
14900 {
14901         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
14902
14903         $LFS setstripe -c 2 $DIR/$tfile || error "setstripe failed"
14904         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=1 || error "dd failed"
14905         sync
14906         $MULTIOP $DIR/$tfile oO_RDONLY:O_DIRECT:r$((2048 * 1024)) ||
14907                 error "direct read failed"
14908         rm -f $DIR/$tfile
14909 }
14910 run_test 119b "Sparse directIO read must return actual read amount"
14911
14912 test_119c() # bug 13099
14913 {
14914         BSIZE=1048576
14915         directio write $DIR/$tfile 3 1 $BSIZE || error "direct write failed"
14916         directio readhole $DIR/$tfile 0 2 $BSIZE || error "reading hole failed"
14917         rm -f $DIR/$tfile
14918 }
14919 run_test 119c "Testing for direct read hitting hole"
14920
14921 # Note: test 119d was removed, skipping 119d for new tests to avoid polluting
14922 # Maloo test history
14923
14924 test_119e()
14925 {
14926         unaligned_dio_or_skip
14927         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
14928
14929         local stripe_size=$((1024 * 1024)) #1 MiB
14930         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
14931         local file_size=$((25 * stripe_size))
14932         local bsizes
14933
14934         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
14935         stack_trap "rm -f $DIR/$tfile*"
14936
14937         # Just a bit bigger than the largest size in the test set below
14938         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
14939                 error "buffered i/o to create file failed"
14940
14941         # trivial test of unaligned DIO
14942         dd if=$DIR/$tfile.1 bs=4095 of=$DIR/$tfile.2 count=4 \
14943                 iflag=direct oflag=direct ||
14944                 error "trivial unaligned dio failed"
14945
14946         # Test of disabling unaligned DIO support
14947         $LCTL set_param llite.*.unaligned_dio=0
14948         stack_trap "$LCTL set_param llite.*.unaligned_dio=1"
14949         echo "testing disabling unaligned DIO - 'invalid argument' expected:"
14950         dd if=$DIR/$tfile.1 bs=1024 of=$DIR/$tfile.2 count=4 \
14951                 iflag=direct oflag=direct &&
14952                 error "unaligned dio succeeded when disabled"
14953         $LCTL set_param llite.*.unaligned_dio=1
14954
14955         # Clean up before next part of test
14956         rm -f $DIR/$tfile.2
14957
14958         if zfs_or_rotational; then
14959                 # DIO on ZFS can take up to 2 seconds per IO
14960                 # rotational is better, but still slow.
14961                 # Limit testing on those media to larger sizes
14962                 if unaligned_dio; then
14963                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
14964                                 $((stripe_size + 1024))"
14965                 else
14966                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
14967                                 $((stripe_size - 1))"
14968                 fi
14969         elif unaligned_dio; then
14970                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
14971                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
14972                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
14973                         $((stripe_size - 1)) $stripe_size \
14974                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
14975                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
14976         else
14977                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
14978                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
14979                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4))"
14980         fi
14981
14982         for bs in $bsizes; do
14983                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
14984                 echo "Read/write with DIO at size $bs"
14985                 # Read and write with DIO from source to dest
14986                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 \
14987                         iflag=direct oflag=direct ||
14988                         error "dio failed"
14989
14990                 ls -la $DIR/$tfile.1 $DIR/$tfile.2
14991                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
14992                         error "size incorrect, file copy read/write bsize: $bs"
14993                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
14994                         error "files differ, bsize $bs"
14995                 rm -f $DIR/$tfile.2
14996         done
14997 }
14998 run_test 119e "Basic tests of dio read and write at various sizes"
14999
15000 test_119f()
15001 {
15002         unaligned_dio_or_skip
15003         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15004
15005         local stripe_size=$((1024 * 1024)) #1 MiB
15006         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
15007         local file_size=$((25 * stripe_size))
15008         local bsizes
15009
15010         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
15011         stack_trap "rm -f $DIR/$tfile*"
15012
15013         # Just a bit bigger than the largest size in the test set below
15014         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
15015                 error "buffered i/o to create file failed"
15016
15017         if zfs_or_rotational; then
15018                 # DIO on ZFS can take up to 2 seconds per IO
15019                 # rotational is better, but still slow.
15020                 # Limit testing on those media to larger sizes
15021                 if unaligned_dio; then
15022                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15023                                 $((stripe_size + 1024))"
15024                 else
15025                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15026                                 $((stripe_size - 1))"
15027                 fi
15028         elif unaligned_dio; then
15029                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15030                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15031                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
15032                         $((stripe_size - 1)) $stripe_size \
15033                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
15034                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
15035         else
15036                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15037                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15038                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4))"
15039         fi
15040
15041         for bs in $bsizes; do
15042                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
15043                 # Read and write with DIO from source to dest in two
15044                 # threads - should give correct copy of file
15045
15046                 echo "bs: $bs"
15047                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 iflag=direct \
15048                         oflag=direct conv=notrunc &
15049                 pid_dio1=$!
15050                 # Note block size is different here for a more interesting race
15051                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
15052                         iflag=direct oflag=direct conv=notrunc &
15053                 pid_dio2=$!
15054                 wait $pid_dio1
15055                 rc1=$?
15056                 wait $pid_dio2
15057                 rc2=$?
15058                 if (( rc1 != 0 )); then
15059                         error "dio copy 1 w/bsize $bs failed: $rc1"
15060                 fi
15061                 if (( rc2 != 0 )); then
15062                         error "dio copy 2 w/bsize $bs failed: $rc2"
15063                 fi
15064
15065
15066                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
15067                         error "size incorrect, file copy read/write bsize: $bs"
15068                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
15069                         error "files differ, bsize $bs"
15070                 rm -f $DIR/$tfile.2
15071         done
15072 }
15073 run_test 119f "dio vs dio race"
15074
15075 test_119g()
15076 {
15077         unaligned_dio_or_skip
15078         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15079
15080         local stripe_size=$((1024 * 1024)) #1 MiB
15081         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
15082         local file_size=$((25 * stripe_size))
15083         local bsizes
15084
15085         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
15086         stack_trap "rm -f $DIR/$tfile*"
15087
15088         # Just a bit bigger than the largest size in the test set below
15089         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
15090                 error "buffered i/o to create file failed"
15091
15092         if zfs_or_rotational; then
15093                 # DIO on ZFS can take up to 2 seconds per IO
15094                 # rotational is better, but still slow.
15095                 # Limit testing on those media to larger sizes
15096                 if unaligned_dio; then
15097                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15098                                 $((stripe_size + 1024))"
15099                 else
15100                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15101                                 $((stripe_size - 1))"
15102                 fi
15103         elif unaligned_dio; then
15104                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15105                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15106                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
15107                         $((stripe_size - 1)) $stripe_size \
15108                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
15109                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
15110         else
15111                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15112                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15113                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4))"
15114         fi
15115
15116         for bs in $bsizes; do
15117                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
15118                 echo "bs: $bs"
15119                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 iflag=direct \
15120                         oflag=direct conv=notrunc &
15121                 pid_dio1=$!
15122                 # Buffered I/O with similar but not the same block size
15123                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 &
15124                 pid_bio2=$!
15125                 wait $pid_dio1
15126                 rc1=$?
15127                 wait $pid_bio2
15128                 rc2=$?
15129                 if (( rc1 != 0 )); then
15130                         error "dio copy 1 w/bsize $bs failed: $rc1"
15131                 fi
15132                 if (( rc2 != 0 )); then
15133                         error "buffered copy 2 w/bsize $bs failed: $rc2"
15134                 fi
15135
15136                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
15137                         error "size incorrect"
15138                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
15139                         error "files differ, bsize $bs"
15140                 rm -f $DIR/$tfile.2
15141         done
15142 }
15143 run_test 119g "dio vs buffered I/O race"
15144
15145 test_119h()
15146 {
15147         unaligned_dio_or_skip
15148         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15149
15150         local stripe_size=$((1024 * 1024)) #1 MiB
15151         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
15152         local file_size=$((25 * stripe_size))
15153         local bsizes
15154
15155         stack_trap "rm -f $DIR/$tfile.*"
15156
15157         if zfs_or_rotational; then
15158                 # DIO on ZFS can take up to 2 seconds per IO
15159                 # rotational is better, but still slow.
15160                 # Limit testing on those media to larger sizes
15161                 if unaligned_dio; then
15162                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15163                                 $((stripe_size + 1024))"
15164                 else
15165                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15166                                 $((stripe_size - 1))"
15167                 fi
15168         elif unaligned_dio; then
15169                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15170                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15171                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
15172                         $((stripe_size - 1)) $stripe_size \
15173                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
15174                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
15175         else
15176                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15177                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15178                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4))"
15179         fi
15180
15181         for bs in $bsizes; do
15182                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
15183                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
15184                 echo "unaligned writes of blocksize: $bs"
15185                 # Write a file with unaligned DIO and regular DIO, and compare
15186                 # them
15187                 # with 'u', multiop randomly unaligns the io from the buffer
15188                 $MULTIOP $DIR/$tfile.1 \
15189                 oO_CREAT:O_RDWR:O_DIRECT:wu${bs}wu${bs}wu${bs}wu${bs}wu${bs} ||
15190                         error "multiop memory unaligned write failed, $bs"
15191                 $MULTIOP $DIR/$tfile.2 \
15192                 oO_CREAT:O_RDWR:O_DIRECT:w${bs}w${bs}w${bs}w${bs}w${bs} ||
15193                         error "multiop memory aligned write failed, $bs"
15194
15195                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
15196                         error "files differ, bsize $bs"
15197                 rm -f $DIR/$tfile.*
15198         done
15199
15200         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
15201         dd if=/dev/zero bs=$((stripe_size * 5)) of=$DIR/$tfile.1 count=5 ||
15202                 error "dd to create source file for read failed"
15203
15204         # Just a few quick tests to make sure unaligned DIO reads don't crash
15205         for bs in $bsizes; do
15206
15207                 echo "unaligned reads of blocksize: $bs"
15208                 # with 'u', multiop randomly unaligns the io from the buffer
15209                 $MULTIOP $DIR/$tfile.1 \
15210                 oO_CREAT:O_RDWR:O_DIRECT:ru${bs}ru${bs}ru${bs}ru${bs}ru${bs} ||
15211                         error "multiop memory unaligned read failed, $bs"
15212
15213         done
15214         rm -f $DIR/$tfile*
15215 }
15216 run_test 119h "basic tests of memory unaligned dio"
15217
15218 # Unaligned AIO is disabled and may not be reenabled
15219 # See LU-18032
15220 # aiocp with the '-a' option makes testing memory unaligned aio trivial
15221 test_119i()
15222 {
15223         unaligned_dio_or_skip
15224         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15225         which aiocp || skip_env "no aiocp installed"
15226         skip "LU-18032: Unaligned AIO is disabled and may not be re-enabled"
15227
15228         local stripe_size=$((1024 * 1024)) #1 MiB
15229         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
15230         local file_size=$((25 * stripe_size))
15231         local bsizes
15232
15233         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
15234         stack_trap "rm -f $DIR/$tfile.*"
15235
15236         # Just a bit bigger than the largest size in the test set below
15237         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
15238                 error "buffered i/o to create file failed"
15239
15240         if zfs_or_rotational; then
15241                 # DIO on ZFS can take up to 2 seconds per IO
15242                 # rotational is better, but still slow.
15243                 # Limit testing on those media to larger sizes
15244                 if unaligned_dio; then
15245                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15246                                 $((stripe_size + 1024))"
15247                 else
15248                         bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
15249                                 $((stripe_size - 1))"
15250                 fi
15251         elif unaligned_dio; then
15252                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15253                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15254                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
15255                         $((stripe_size - 1)) $stripe_size \
15256                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
15257                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
15258         else
15259                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
15260                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
15261                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4))"
15262         fi
15263
15264         # Do page aligned and NOT page aligned AIO
15265         for align in 8 512 $((PAGE_SIZE)); do
15266         # Deliberately includes a few aligned sizes
15267         for bs in $bsizes; do
15268                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
15269
15270                 echo "bs: $bs, align: $align, file_size $file_size"
15271                 aiocp -a $align -b $bs -s $file_size -f O_DIRECT \
15272                         $DIR/$tfile.1 $DIR/$tfile.2 ||
15273                         error "unaligned aio failed, bs: $bs, align: $align"
15274
15275                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
15276                         error "size incorrect"
15277                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
15278                         error "files differ"
15279                 rm -f $DIR/$tfile.2
15280         done
15281         done
15282 }
15283 run_test 119i "test unaligned aio at varying sizes"
15284
15285 test_119j()
15286 {
15287         unaligned_dio_or_skip
15288         (( $LINUX_VERSION_CODE > $(version_code 4.5.0) )) ||
15289                 skip "needs kernel > 4.5.0 for ki_flags support"
15290
15291         local rpcs
15292         dd if=/dev/urandom of=$DIR/$tfile bs=8 count=1 || error "(0) dd failed"
15293         sync
15294         $LCTL set_param -n osc.*.rpc_stats=0
15295         # Read from page cache, does not generate an rpc
15296         dd if=$DIR/$tfile of=/dev/null bs=8 count=1 || error "(1) dd failed"
15297         $LCTL get_param osc.*.rpc_stats
15298         rpcs=($($LCTL get_param -n 'osc.*.rpc_stats' |
15299                 sed -n '/pages per rpc/,/^$/p' |
15300                 awk '/'$pages':/ { reads += $2; writes += $6 }; \
15301                 END { print reads,writes }'))
15302         [[ ${rpcs[0]} == 0 ]] ||
15303                 error "(3) ${rpcs[0]} != 0 read RPCs"
15304
15305         # Test hybrid IO read
15306         # Force next BIO as DIO
15307         # This forces an RPC to the server
15308         #define OBD_FAIL_LLITE_FORCE_BIO_AS_DIO 0x1429
15309         $LCTL set_param fail_loc=0x1429
15310         dd if=$DIR/$tfile of=/dev/null bs=8 count=1 || error "(4) dd failed"
15311         $LCTL get_param osc.*.rpc_stats
15312         rpcs=($($LCTL get_param -n 'osc.*.rpc_stats' |
15313                 sed -n '/pages per rpc/,/^$/p' |
15314                 awk '/'$pages':/ { reads += $2; writes += $6 }; \
15315                 END { print reads,writes }'))
15316         [[ ${rpcs[0]} == 1 ]] ||
15317                 error "(5) ${rpcs[0]} != 1 read RPCs"
15318
15319         # Test hybrid IO write
15320         #define OBD_FAIL_LLITE_FORCE_BIO_AS_DIO 0x1429
15321         $LCTL set_param fail_loc=0x1429
15322         #NB: We do not check for 0 write RPCs in the BIO case because that
15323         # would make the test racey vs cache flushing
15324         # but the DIO case is guaranteed to generate 1 write RPC
15325         dd if=/dev/zero of=$DIR/$tfile bs=8 count=1 || error "(6) dd failed"
15326         $LCTL get_param osc.*.rpc_stats
15327         rpcs=($($LCTL get_param -n 'osc.*.rpc_stats' |
15328                 sed -n '/pages per rpc/,/^$/p' |
15329                 awk '/'$pages':/ { reads += $2; writes += $6 }; \
15330                 END { print reads,writes }'))
15331         [[ ${rpcs[1]} == 1 ]] ||
15332                 error "(7) ${rpcs[0]} != 1 read RPCs"
15333 }
15334 run_test 119j "basic tests of hybrid IO switching"
15335
15336 test_119m() {
15337         dio_readv_writev_support
15338
15339         timeout 90s rwv -f $DIR/$tfile -Dw -n 3 0x80000 0x100000 0x180000 ||
15340                 error "DIO aligned writev test failed"
15341         timeout 90s rwv -f $DIR/$tfile -Dr -v -n 2 0x180000 0x100000 ||
15342                 error "DIO aligned readv failed"
15343         rm -f $DIR/$tfile
15344 }
15345 run_test 119m "Test DIO readv/writev: exercise iter duplication"
15346
15347 test_119n()
15348 {
15349         # zfs server should fail without unaligned_dio connect flag
15350         # and report EINVAL when attempting unaligned dio.
15351         dio_readv_writev_support
15352
15353         [[ "${ost1_FSTYPE}" == "zfs" ]] ||
15354                 skip "need ZFS server without unaligned_dio support"
15355         $LCTL get_param osc.*.import | grep connect_flags: |
15356                 grep -q "unaligned_dio" &&
15357                         skip "zfs server without 'unaligned_dio' support"
15358
15359         error_string=$(rwv -f $DIR/$tfile -Dw -n2 1024 4096 2>&1) &&
15360                 error "Allowed unaligned dio with ZFS with unpatched server"
15361         grep -q "Invalid argument" <<< $error_string ||
15362                 error "Expected 'Invalid argument' failure: '$error_string'."
15363
15364         rwv -f $DIR/$tfile -Dw -n2 65536 4096 ||
15365                 error "DIO aligned writev test failed"
15366
15367         error_string=$(rwv -f $DIR/$tfile -Dr -v -n2 1024 4096 2>&1) &&
15368                 error "Allowed unaligned dio with ZFS with unpatched server"
15369         grep -q "Invalid argument" <<< $error_string ||
15370                 error "Expected 'Invalid argument' failure: '$error_string'."
15371
15372         rm -f $DIR/$tfile
15373 }
15374 run_test 119n "Test Unaligned DIO readv() and writev() with unpatched ZFS"
15375
15376 test_119o()
15377 {
15378         dio_readv_writev_support
15379
15380         [[ "${ost1_FSTYPE}" == "zfs" ]] ||
15381                 skip "need ldiskfs without unaligned_dio support."
15382         $LCTL get_param osc.*.import | grep connect_flags: |
15383                 grep -q "unaligned_dio" &&
15384                         skip "need ldiskfs without 'unaligned_dio' support"
15385
15386         error_string=$(timeout 200s \
15387         rwv -f $DIR/$tfile -Dw -n 3 0x7ffff 0x100001 0x180000 2>&1) &&
15388                 error "Allowed 64k unaligned dio writev"
15389         grep -q -E 'Invalid argument|Write error:' <<< $error_string ||
15390                 error "Expected 'Invalid argument' failure: '$error_string'."
15391         rwv -f $DIR/$tfile -Dw -n 3 0x80000 0x100000 0x180000 ||
15392                 error "DIO aligned writev test failed"
15393         error_string=$(timeout 200s \
15394         rwv -f $DIR/$tfile -Dr -v -n 3 0x7ffff 0x100001 0x180000 2>&1) &&
15395                 error "Allowed 64k unaligned dio readv"
15396         grep -q -E 'Invalid argument|Read error:' <<< $error_string ||
15397                 error "Expected 'Invalid argument' failure: '$error_string'."
15398
15399         rm -f $DIR/$tfile
15400 }
15401 run_test 119o "Test Unaligned DIO readv() and writev() with unpatched servers"
15402
15403 test_119p()
15404 {
15405         # Patched servers, unaligned dio that needs interop page alignment
15406         dio_readv_writev_support
15407
15408         $LCTL get_param osc.*.import | grep connect_flags: |
15409                 grep -q "unaligned_dio" ||
15410                         skip "need unaligned_dio support."
15411         rwv -f $DIR/$tfile -Dw -n 3 0x7ffff 0x100001 0x180000 ||
15412                 error "DIO unaligned writev test failed"
15413         rwv -f $DIR/$tfile -Dr -v -n 3 0x7ffff 0x100001 0x180000 ||
15414                 error "DIO unaligned readv failed"
15415         rm -f $DIR/$tfile
15416 }
15417 run_test 119p "Test Unaligned DIO readv() and writev() with patched servers"
15418
15419 test_119q()
15420 {
15421         dio_readv_writev_support
15422         $LCTL get_param osc.*.import | grep connect_flags: |
15423                 grep -q "unaligned_dio" ||
15424                         skip "need unaligned_dio support."
15425
15426         local page_size
15427         local off0
15428         local off1
15429         local off2
15430
15431         #  4k:   0x1000,  8k:   0x2000,  32k:   0x8000   64k:  0x10000
15432         for page_size in 0x1000 0x2000 0x8000 0x10000; do
15433                 echo "RWV interop with 64k + $page_size +/- 1"
15434                 # short by 1 byte
15435                 off0=$((page_size + 0xffff))
15436                 echo "writev: $off0 0x100001 0x100000"
15437                 timeout 90s rwv -f $DIR/$tfile -Dw -n 3 $off0 0x100001 0x100000 ||
15438                         error "DIO unaligned writev test failed: $off0"
15439                 echo "readv: 0x100001 $off0 0x100000"
15440                 timeout 90s rwv -f $DIR/$tfile -Dr -v -n 3 0x100001 $off0 0x100000 ||
15441                         error "DIO unaligned readv failed: $off0"
15442                 rm -f $DIR/$tfile
15443                 # page offset exactly
15444                 off1=$((page_size + 0x10000))
15445                 echo "writev: $off1 0x100001 0x100000"
15446                 timeout 90s rwv -f $DIR/$tfile -Dw -n 3 $off1 0x100001 0x100000 ||
15447                         error "DIO unaligned writev test failed: $off1"
15448                 echo "readv: 0x100001 $off1 0x100000"
15449                 timeout 90s rwv -f $DIR/$tfile -Dr -v -n 3 0x100001 $off1 0x100000 ||
15450                         error "DIO unaligned readv failed: $off1"
15451                 rm -f $DIR/$tfile
15452                 # page offset over by 1 byte
15453                 off2=$((page_size + 0x10001))
15454                 echo "writev: $off2 0x100001 0x100000"
15455                 timeout 90s rwv -f $DIR/$tfile -Dw -n 3 $off2 0x100001 0x100000 ||
15456                         error "DIO unaligned writev test failed: $off2"
15457                 echo "readv: 3 0x100001 $off2 0x100000"
15458                 timeout 90s rwv -f $DIR/$tfile -Dr -v -n 3 0x100001 $off2 0x100000 ||
15459                         error "DIO unaligned readv failed: $off2"
15460                 rm -f $DIR/$tfile
15461         done
15462 }
15463 run_test 119q "Test patchded Unaligned DIO readv() and writev()"
15464
15465 test_120a() {
15466         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15467         remote_mds_nodsh && skip "remote MDS with nodsh"
15468         test_mkdir -i0 -c1 $DIR/$tdir
15469         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15470                 skip_env "no early lock cancel on server"
15471
15472         lru_resize_disable mdc
15473         lru_resize_disable osc
15474         cancel_lru_locks mdc
15475         # asynchronous object destroy at MDT could cause bl ast to client
15476         cancel_lru_locks osc
15477
15478         local old=$($LCTL get_param -n llite.*.dir_read_on_open)
15479
15480         # statahead_agl may cause extra glimpse which confuses results. LU-13017
15481         $LCTL set_param -n llite.*.dir_read_on_open=0
15482         stack_trap "$LCTL set_param -n llite.*.dir_read_on_open=$old" EXIT
15483
15484         stat $DIR/$tdir > /dev/null
15485         can1=$(do_facet mds1 \
15486                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15487                awk '/ldlm_cancel/ {print $2}')
15488         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15489                awk '/ldlm_bl_callback/ {print $2}')
15490         test_mkdir -i0 -c1 $DIR/$tdir/d1
15491         can2=$(do_facet mds1 \
15492                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15493                awk '/ldlm_cancel/ {print $2}')
15494         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15495                awk '/ldlm_bl_callback/ {print $2}')
15496         (( $can1 == $can2 )) || error "$((can2-can1)) cancel RPC occured."
15497         (( $blk1 == $blk2 )) || error "$((blk2-blk1)) blocking RPC occured."
15498 }
15499 run_test 120a "Early Lock Cancel: mkdir test"
15500
15501 test_120b() {
15502         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15503         remote_mds_nodsh && skip "remote MDS with nodsh"
15504         test_mkdir $DIR/$tdir
15505         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15506                 skip_env "no early lock cancel on server"
15507
15508         lru_resize_disable mdc
15509         lru_resize_disable osc
15510         cancel_lru_locks mdc
15511         stat $DIR/$tdir > /dev/null
15512         can1=$(do_facet $SINGLEMDS \
15513                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15514                awk '/ldlm_cancel/ {print $2}')
15515         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15516                awk '/ldlm_bl_callback/ {print $2}')
15517         touch $DIR/$tdir/f1
15518         can2=$(do_facet $SINGLEMDS \
15519                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15520                awk '/ldlm_cancel/ {print $2}')
15521         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15522                awk '/ldlm_bl_callback/ {print $2}')
15523         (( $can1 == $can2 )) || error "$((can2-can1)) cancel RPC occured."
15524         (( $blk1 == $blk2 )) || error "$((blk2-blk1)) blocking RPC occured."
15525 }
15526 run_test 120b "Early Lock Cancel: create test"
15527
15528 test_120c() {
15529         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15530         remote_mds_nodsh && skip "remote MDS with nodsh"
15531         test_mkdir -i0 -c1 $DIR/$tdir
15532         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15533                 skip "no early lock cancel on server"
15534
15535         lru_resize_disable mdc
15536         lru_resize_disable osc
15537         test_mkdir -i0 -c1 $DIR/$tdir/d1
15538         test_mkdir -i0 -c1 $DIR/$tdir/d2
15539         touch $DIR/$tdir/d1/f1
15540         cancel_lru_locks mdc
15541         stat $DIR/$tdir/d1 $DIR/$tdir/d2 $DIR/$tdir/d1/f1 > /dev/null
15542         can1=$(do_facet mds1 \
15543                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15544                awk '/ldlm_cancel/ {print $2}')
15545         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15546                awk '/ldlm_bl_callback/ {print $2}')
15547         ln $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2
15548         can2=$(do_facet mds1 \
15549                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15550                awk '/ldlm_cancel/ {print $2}')
15551         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15552                awk '/ldlm_bl_callback/ {print $2}')
15553         (( $can1 == $can2 )) || error "$((can2-can1)) cancel RPC occured."
15554         (( $blk1 == $blk2 )) || error "$((blk2-blk1)) blocking RPC occured."
15555 }
15556 run_test 120c "Early Lock Cancel: link test"
15557
15558 test_120d() {
15559         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15560         remote_mds_nodsh && skip "remote MDS with nodsh"
15561         test_mkdir -i0 -c1 $DIR/$tdir
15562         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15563                 skip_env "no early lock cancel on server"
15564
15565         lru_resize_disable mdc
15566         lru_resize_disable osc
15567         touch $DIR/$tdir
15568         cancel_lru_locks mdc
15569         stat $DIR/$tdir > /dev/null
15570         can1=$(do_facet mds1 \
15571                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15572                awk '/ldlm_cancel/ {print $2}')
15573         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15574                awk '/ldlm_bl_callback/ {print $2}')
15575         chmod a+x $DIR/$tdir
15576         can2=$(do_facet mds1 \
15577                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15578                awk '/ldlm_cancel/ {print $2}')
15579         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15580                awk '/ldlm_bl_callback/ {print $2}')
15581         (( $can1 == $can2 )) || error "$((can2-can1)) cancel RPC occured."
15582         (( $blk1 == $blk2 )) || error "$((blk2-blk1)) blocking RPC occured."
15583 }
15584 run_test 120d "Early Lock Cancel: setattr test"
15585
15586 test_120e() {
15587         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15588         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15589                 skip_env "no early lock cancel on server"
15590         remote_mds_nodsh && skip "remote MDS with nodsh"
15591
15592         local dlmtrace_set=false
15593
15594         test_mkdir -i0 -c1 $DIR/$tdir
15595         lru_resize_disable mdc
15596         lru_resize_disable osc
15597         ! $LCTL get_param debug | grep -q dlmtrace &&
15598                 $LCTL set_param debug=+dlmtrace &&
15599                 stack_trap "$LCTL set_param debug=-dlmtrace"
15600         dd if=/dev/zero of=$DIR/$tdir/f1 count=1
15601         cancel_lru_locks mdc
15602         cancel_lru_locks osc
15603         dd if=$DIR/$tdir/f1 of=/dev/null
15604         stat $DIR/$tdir $DIR/$tdir/f1 > /dev/null
15605         # XXX client can not do early lock cancel of OST lock
15606         # during unlink (LU-4206), so cancel osc lock now.
15607         sleep 2
15608         cancel_lru_locks osc
15609         can1=$(do_facet mds1 \
15610                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15611                awk '/ldlm_cancel/ {print $2}')
15612         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15613                awk '/ldlm_bl_callback/ {print $2}')
15614         unlink $DIR/$tdir/f1
15615         sleep 5
15616         can2=$(do_facet mds1 \
15617                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15618                awk '/ldlm_cancel/ {print $2}')
15619         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15620                awk '/ldlm_bl_callback/ {print $2}')
15621         (( $can1 == $can2 )) || error "$((can2 - can1)) cancel RPC occured"
15622         (( $blk1 == $blk2 )) || error "$((blk2 - blk1)) blocking RPC occured"
15623 }
15624 run_test 120e "Early Lock Cancel: unlink test"
15625
15626 test_120f() {
15627         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15628         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15629                 skip_env "no early lock cancel on server"
15630         remote_mds_nodsh && skip "remote MDS with nodsh"
15631
15632         test_mkdir -i0 -c1 $DIR/$tdir
15633         lru_resize_disable mdc
15634         lru_resize_disable osc
15635         test_mkdir -i0 -c1 $DIR/$tdir/d1
15636         test_mkdir -i0 -c1 $DIR/$tdir/d2
15637         dd if=/dev/zero of=$DIR/$tdir/d1/f1 count=1
15638         dd if=/dev/zero of=$DIR/$tdir/d2/f2 count=1
15639         cancel_lru_locks mdc
15640         cancel_lru_locks osc
15641         dd if=$DIR/$tdir/d1/f1 of=/dev/null
15642         dd if=$DIR/$tdir/d2/f2 of=/dev/null
15643         stat $DIR/$tdir/d1 $DIR/$tdir/d2 $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2 > /dev/null
15644         # XXX client can not do early lock cancel of OST lock
15645         # during rename (LU-4206), so cancel osc lock now.
15646         sleep 2
15647         cancel_lru_locks osc
15648         can1=$(do_facet mds1 \
15649                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15650                awk '/ldlm_cancel/ {print $2}')
15651         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15652                awk '/ldlm_bl_callback/ {print $2}')
15653         mrename $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2
15654         sleep 5
15655         can2=$(do_facet mds1 \
15656                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15657                awk '/ldlm_cancel/ {print $2}')
15658         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15659                awk '/ldlm_bl_callback/ {print $2}')
15660         (( $can1 == $can2 )) || error "$((can2-can1)) cancel RPC occured."
15661         (( $blk1 == $blk2 )) || error "$((blk2-blk1)) blocking RPC occured."
15662 }
15663 run_test 120f "Early Lock Cancel: rename test"
15664
15665 test_120g() {
15666         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15667         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
15668                 skip_env "no early lock cancel on server"
15669         remote_mds_nodsh && skip "remote MDS with nodsh"
15670
15671         lru_resize_disable mdc
15672         lru_resize_disable osc
15673         count=10000
15674         echo create $count files
15675         test_mkdir $DIR/$tdir
15676         cancel_lru_locks mdc
15677         cancel_lru_locks osc
15678         t0=$(date +%s)
15679
15680         can0=$(do_facet $SINGLEMDS \
15681                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15682                awk '/ldlm_cancel/ {print $2}')
15683         blk0=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15684                awk '/ldlm_bl_callback/ {print $2}')
15685         createmany -o $DIR/$tdir/f $count
15686         sync
15687         can1=$(do_facet $SINGLEMDS \
15688                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15689                awk '/ldlm_cancel/ {print $2}')
15690         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15691                awk '/ldlm_bl_callback/ {print $2}')
15692         t1=$(date +%s)
15693         echo "total: $((can1-can0)) cancels, $((blk1-blk0)) blockings"
15694         echo "rm $count files"
15695         rm -r $DIR/$tdir
15696         sync
15697         can2=$(do_facet $SINGLEMDS \
15698                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
15699                awk '/ldlm_cancel/ {print $2}')
15700         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
15701                awk '/ldlm_bl_callback/ {print $2}')
15702         t2=$(date +%s)
15703         echo "total: $count removes in $((t2-t1))"
15704         echo "total: $((can2-can1)) cancels, $((blk2-blk1)) blockings"
15705         wait_delete_completed
15706 }
15707 run_test 120g "Early Lock Cancel: performance test"
15708
15709 test_121() { #bug #10589
15710         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15711
15712         rm -rf $DIR/$tfile
15713         writes=$(LANG=C dd if=/dev/zero of=$DIR/$tfile count=1 2>&1 | awk -F '+' '/out$/ {print $1}')
15714 #define OBD_FAIL_LDLM_CANCEL_RACE        0x310
15715         lctl set_param fail_loc=0x310
15716         cancel_lru_locks osc > /dev/null
15717         reads=$(LANG=C dd if=$DIR/$tfile of=/dev/null 2>&1 | awk -F '+' '/in$/ {print $1}')
15718         lctl set_param fail_loc=0
15719         [[ $reads -eq $writes ]] ||
15720                 error "read $reads blocks, must be $writes blocks"
15721 }
15722 run_test 121 "read cancel race ========="
15723
15724 test_123a_base() { # was test 123, statahead(b=11401)
15725         local lsx="$1"
15726
15727         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
15728
15729         local slow_is=error
15730         if ! grep -q "processor.*: 1" /proc/cpuinfo; then
15731                 log "testing UP system. Performance may be lower than expected."
15732                 slow_is=log
15733         fi
15734         running_in_vm && slow_is=log
15735
15736         lru_resize_enable
15737         $LCTL set_param mdc.*.batch_stats=0
15738
15739         rm -rf $DIR/$tdir
15740         test_mkdir $DIR/$tdir
15741         local numfree=$(df -i -P $DIR | tail -n 1 | awk '{ print $4 }')
15742         (( $numfree > 100000 )) && numfree=100000 || numfree=$((numfree-1000))
15743         local mult=10
15744         for ((i=100, j=0; i<=$numfree; j=$i, i=$((i * mult)) )); do
15745                 createmany -o $DIR/$tdir/$tfile $j $((i - j))
15746
15747                 local max=($($LCTL get_param -n llite.*.statahead_max))
15748                 $LCTL set_param llite.*.statahead_max=0
15749                 cancel_lru_locks mdc
15750                 cancel_lru_locks osc
15751                 local stime=$SECONDS
15752                 time $lsx $DIR/$tdir | wc -l
15753                 local etime=$SECONDS
15754                 local delta=$((etime - stime))
15755                 log "$lsx $i files without statahead: $delta sec"
15756                 $LCTL set_param llite.*.statahead_max=$max
15757
15758                 local swrong=$($LCTL get_param -n llite.*.statahead_stats |
15759                                awk '/statahead.wrong:/ { print $NF }')
15760                 $LCTL get_param -n llite.*.statahead_max | grep '[0-9]'
15761                 cancel_lru_locks mdc
15762                 cancel_lru_locks osc
15763                 stime=$SECONDS
15764                 time $lsx $DIR/$tdir | wc -l
15765                 etime=$SECONDS
15766                 local delta_sa=$((etime - stime))
15767                 log "$lsx $i files with statahead: $delta_sa sec"
15768                 $LCTL get_param -n llite.*.statahead_stats
15769                 local ewrong=$($LCTL get_param -n llite.*.statahead_stats |
15770                                awk '/statahead.wrong:/ { print $NF }')
15771
15772                 [[ $swrong -lt $ewrong ]] &&
15773                         log "statahead was stopped, maybe too many locks held!"
15774                 [[ $delta -eq 0 || $delta_sa -eq 0 ]] && continue
15775
15776                 if (( $delta_sa*100 > $delta*105 && $delta_sa > $delta+2)); then
15777                         max=$($LCTL get_param -n llite.*.statahead_max |
15778                                 head -n 1)
15779                         $LCTL set_param llite.*.statahead_max 0
15780                         cancel_lru_locks mdc
15781                         cancel_lru_locks osc
15782                         stime=$SECONDS
15783                         time $lsx $DIR/$tdir | wc -l
15784                         etime=$SECONDS
15785                         delta=$((etime - stime))
15786                         log "$lsx $i files again without statahead: $delta sec"
15787                         $LCTL set_param llite.*.statahead_max=$max
15788                         if (( $delta_sa * 100 > $delta * 105 &&
15789                               $delta_sa > $delta + 2 )); then
15790                                 $slow_is "$lsx $i files slower with statahead!"
15791                                 break
15792                         fi
15793                 fi
15794
15795                 (( $delta <= 20 )) || break
15796                 (( $delta <= 8 )) || mult=$((50 / delta))
15797                 [[ "$SLOW" == "no" ]] || (( $delta <= 5 )) || break
15798         done
15799         log "$lsx done"
15800
15801         stime=$SECONDS
15802         rm -r $DIR/$tdir || error "failed to rm $DIR/$tdir"
15803         sync
15804         etime=$SECONDS
15805         delta=$((etime - stime))
15806         log "rm -r $DIR/$tdir: $delta seconds"
15807         $LCTL get_param llite.*.statahead_stats
15808         $LCTL get_param mdc.*.batch_stats
15809 }
15810
15811 test_123aa() {
15812         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15813
15814         test_123a_base "ls -l"
15815 }
15816 run_test 123aa "verify statahead work"
15817
15818 test_123ab() {
15819         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15820
15821         statx_supported || skip_env "Test must be statx() syscall supported"
15822
15823         test_123a_base "$STATX -l"
15824 }
15825 run_test 123ab "verify statahead work by using statx"
15826
15827 test_123ac() {
15828         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15829
15830         statx_supported || skip_env "Test must be statx() syscall supported"
15831
15832         local rpcs_before
15833         local rpcs_after
15834         local agl_before
15835         local agl_after
15836
15837         cancel_lru_locks $OSC
15838         rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
15839         agl_before=$($LCTL get_param -n llite.*.statahead_stats |
15840                      awk '/agl.total:/ { print $NF }')
15841         test_123a_base "$STATX -c \"%n %i %A %h %u %g %W %X %Z\" -D"
15842         test_123a_base "$STATX --cached=always -D"
15843         agl_after=$($LCTL get_param -n llite.*.statahead_stats |
15844                     awk '/agl.total:/ { print $NF }')
15845         [ $agl_before -eq $agl_after ] ||
15846                 error "Should not trigger AGL thread - $agl_before:$agl_after"
15847         rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
15848         [ $rpcs_after -eq $rpcs_before ] ||
15849                 error "$STATX should not send glimpse RPCs to $OSC"
15850 }
15851 run_test 123ac "verify statahead work by using statx without glimpse RPCs"
15852
15853 test_batch_statahead() {
15854         local max=$1
15855         local batch_max=$2
15856         local num=10000
15857         local batch_rpcs
15858         local unbatch_rpcs
15859         local hit_total
15860
15861         echo -e "\n\n\nbatch: statahead_max=$max statahead_batch_max=$batch_max"
15862         $LCTL set_param mdc.*.batch_stats=0
15863         $LCTL set_param llite.*.statahead_max=$max
15864         $LCTL set_param llite.*.statahead_batch_max=$batch_max
15865         # Verify that batched statahead is faster than one without statahead
15866         test_123a_base "ls -l"
15867
15868         stack_trap "rm -rf $DIR/$tdir" EXIT
15869         mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
15870         createmany -o $DIR/$tdir/$tfile $num || error "failed to create files"
15871
15872         # unbatched statahead
15873         $LCTL set_param llite.*.statahead_batch_max=0
15874         $LCTL set_param llite.*.statahead_stats=clear
15875         $LCTL set_param mdc.*.stats=clear
15876         cancel_lru_locks mdc
15877         cancel_lru_locks osc
15878         echo -n "ls -l files in $tdir: "
15879         time ls -l $DIR/$tdir | wc -l
15880         unbatch_rpcs=$(calc_stats mdc.*.stats ldlm_ibits_enqueue)
15881         wait_update_facet client "pgrep ll_sa" "" 35 ||
15882                 error "ll_sa thread is still running"
15883         hit_total=$($LCTL get_param -n llite.*.statahead_stats |
15884                     awk '/hit.total:/ { print $NF }')
15885         # hit ratio should be larger than 75% (7500).
15886         echo "unbatched statahead RPC=$unbatch_rpcs hit count=$hit_total"
15887         (( $hit_total > 7500 )) || {
15888                 $LCTL get_param llite.*.statahead_stats
15889                 error "unbatched statahead RPC=$unbatch_rpcs hit count=$hit_total too low"
15890         }
15891
15892         # batched statahead
15893         $LCTL set_param llite.*.statahead_batch_max=$batch_max
15894         $LCTL set_param llite.*.statahead_stats=clear
15895         $LCTL set_param mdc.*.batch_stats=clear
15896         $LCTL set_param mdc.*.stats=clear
15897         cancel_lru_locks mdc
15898         cancel_lru_locks osc
15899         echo -n "ls -l files in $tdir: "
15900         time ls -l $DIR/$tdir | wc -l
15901         batch_rpcs=$(calc_stats mdc.*.stats mds_batch)
15902         # wait for statahead thread to quit and update statahead stats
15903         wait_update_facet client "pgrep ll_sa" "" 35 ||
15904                 error "ll_sa thread is still running"
15905         hit_total=$($LCTL get_param -n llite.*.statahead_stats |
15906                     awk '/hit.total:/ { print $NF }')
15907         # hit ratio should be larger than 75% (7500).
15908         echo "batched statahead RPC=$batch_rpc hit count=$hit_total"
15909         (( $hit_total > 7500 )) || {
15910                 $LCTL get_param llite.*.statahead_stats
15911                 error "batched statahead RPC=$batch_rpc hit count=$hit_total too low"
15912         }
15913
15914         (( $unbatch_rpcs > $batch_rpcs )) ||
15915                 error "batched statahead does not reduce RPCs ($unbatch_rpcs < $batch_rpcs)"
15916         $LCTL get_param mdc.*.batch_stats
15917 }
15918
15919 test_123ad() {
15920         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15921
15922         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
15923                 skip "Need server version at least 2.15.53"
15924
15925         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
15926                 skip "Server does not support batch RPC"
15927
15928         local max
15929         local batch_max
15930
15931         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
15932         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
15933
15934         stack_trap "$LCTL set_param llite.*.statahead_max=$max" EXIT
15935         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max" EXIT
15936
15937         test_batch_statahead 32 32
15938         test_batch_statahead 2048 256
15939 }
15940 run_test 123ad "Verify batching statahead works correctly"
15941
15942 test_123b () { # statahead(bug 15027)
15943         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15944
15945         test_mkdir $DIR/$tdir
15946         createmany -o $DIR/$tdir/$tfile-%d 1000
15947
15948         cancel_lru_locks mdc
15949         cancel_lru_locks osc
15950
15951 #define OBD_FAIL_MDC_GETATTR_ENQUEUE     0x803
15952         lctl set_param fail_loc=0x80000803
15953         ls -lR $DIR/$tdir > /dev/null
15954         log "ls done"
15955         lctl set_param fail_loc=0x0
15956         lctl get_param -n llite.*.statahead_stats
15957         rm -r $DIR/$tdir
15958         sync
15959
15960 }
15961 run_test 123b "not panic with network error in statahead enqueue (bug 15027)"
15962
15963 test_123c() {
15964         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
15965
15966         test_mkdir -i 0 -c 1 $DIR/$tdir.0
15967         test_mkdir -i 1 -c 1 $DIR/$tdir.1
15968         touch $DIR/$tdir.1/{1..3}
15969         mv $DIR/$tdir.1/{1..3} $DIR/$tdir.0
15970
15971         remount_client $MOUNT
15972
15973         $MULTIOP $DIR/$tdir.0 Q
15974
15975         # let statahead to complete
15976         ls -l $DIR/$tdir.0 > /dev/null
15977
15978         testid=$(echo $TESTNAME | tr '_' ' ')
15979         dmesg | tac | sed "/$testid/,$ d" | grep "Can not initialize inode" &&
15980                 error "statahead warning" || true
15981 }
15982 run_test 123c "Can not initialize inode warning on DNE statahead"
15983
15984 test_123d() {
15985         local num=100
15986         local swrong
15987         local ewrong
15988
15989         test_mkdir -c -1 $DIR/$tdir || error "test_mkdir $DIR/$tdir failed"
15990         $LFS setdirstripe -D -c $MDSCOUNT $DIR/$tdir ||
15991                 error "setdirstripe $DIR/$tdir failed"
15992         createmany -d $DIR/$tdir/$tfile $num || error "createmany $num failed"
15993         stack_trap "unlinkmany -d $DIR/$tdir/$tfile $num"
15994         remount_client $MOUNT
15995         $LCTL get_param llite.*.statahead_max
15996         $LCTL set_param llite.*.statahead_stats=0 ||
15997                 error "clear statahead_stats failed"
15998         swrong=$(lctl get_param -n llite.*.statahead_stats |
15999                  awk '/statahead.wrong:/ { print $NF }')
16000         ls -l $DIR/$tdir || error "ls -l $DIR/$tdir failed"
16001         # wait for statahead thread finished to update hit/miss stats.
16002         sleep 1
16003         $LCTL get_param -n llite.*.statahead_stats
16004         ewrong=$(lctl get_param -n llite.*.statahead_stats |
16005                  awk '/statahead.wrong:/ { print $NF }')
16006         (( $swrong == $ewrong )) ||
16007                 log "statahead was stopped, maybe too many locks held!"
16008 }
16009 run_test 123d "Statahead on striped directories works correctly"
16010
16011 test_123e() {
16012         local max
16013         local batch_max
16014         local dir=$DIR/$tdir
16015
16016         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16017                 skip "Server does not support batch RPC"
16018
16019         mkdir $dir || error "mkdir $dir failed"
16020         $LFS setstripe -C 32 $dir || error "setstripe $dir failed"
16021         stack_trap "rm -rf $dir"
16022
16023         touch $dir/$tfile.{0..1000} || error "touch 1000 files failed"
16024
16025         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
16026         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
16027         stack_trap "$LCTL set_param llite.*.statahead_max=$max" EXIT
16028         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max" EXIT
16029
16030         $LCTL set_param llite.*.statahead_max=2048
16031         $LCTL set_param llite.*.statahead_batch_max=1024
16032
16033         ls -l $dir
16034         $LCTL get_param mdc.*.batch_stats
16035         $LCTL get_param llite.*.statahead_*
16036 }
16037 run_test 123e "statahead with large wide striping"
16038
16039 test_123f() {
16040         local max
16041         local batch_max
16042         local dir=$DIR/$tdir
16043
16044         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16045                 skip "Server does not support batch RPC"
16046
16047         mkdir $dir || error "mkdir $dir failed"
16048         $LFS setstripe -C 1000 $dir || error "setstripe $dir failed"
16049         stack_trap "rm -rf $dir"
16050
16051         touch $dir/$tfile.{0..200} || error "touch 200 files failed"
16052
16053         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
16054         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
16055
16056         $LCTL set_param llite.*.statahead_max=64
16057         $LCTL set_param llite.*.statahead_batch_max=64
16058
16059         ls -l $dir
16060         lctl get_param mdc.*.batch_stats
16061         lctl get_param llite.*.statahead_*
16062
16063         $LCTL set_param llite.*.statahead_max=$max
16064         $LCTL set_param llite.*.statahead_batch_max=$batch_max
16065 }
16066 run_test 123f "Retry mechanism with large wide striping files"
16067
16068 test_123g() {
16069         local dir=$DIR/$tdir
16070         local num=1000
16071
16072         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16073                 skip "Server does not support batch RPC"
16074
16075         mkdir $dir || error "failed to mkdir $dir"
16076         createmany -o $dir/$tfile $num || error "failed creatmany files"
16077         cancel_lru_locks mdc
16078         cancel_lru_locks osc
16079
16080         $LCTL set_param llite.*.statahead_stats=clear
16081         $LCTL set_param mdc.*.batch_stats=clear
16082         aheadmany -c stat -s 0 -e $num -b $tfile -d $dir ||
16083                 error "aheadmany $dir with $tfile failed"
16084         wait_update_facet client "pgrep ll_sa" "" 35 ||
16085                 error "ll_sa thread is still running"
16086         $LCTL get_param -n llite.*.statahead_stats
16087         $LCTL get_param -n mdc.*.batch_stats
16088
16089         local count
16090
16091         count=$($LCTL get_param -n llite.*.statahead_stats |
16092                 awk '/hit.total:/ {print $2}')
16093         echo "Hit total: $count"
16094         # Hit ratio should be >= 75%
16095         (( $count > num * 75 / 100 )) ||
16096                 error "hit total $count is be > 75% of $num"
16097 }
16098 run_test 123g "Test for stat-ahead advise"
16099
16100 test_123h_base() {
16101         local dir=$DIR/$tdir
16102         local cmd="touch $dir/$tfile.{$1}"
16103         local fcnt=$2
16104
16105         stack_trap "rm -rf $dir"
16106         mkdir -p $dir || error "failed to mkdir $dir"
16107         eval $cmd
16108
16109         cancel_lru_locks mdc
16110         $LCTL set_param llite.*.statahead_stats=clear
16111         $LCTL set_param mdc.*.batch_stats=0
16112         $LCTL set_param llite.*.statahead_max=1024
16113         $LCTL set_param llite.*.statahead_batch_max=1024
16114         lctl get_param -n llite.*.statahead_stats
16115         du -a $dir > /dev/null
16116         echo "Wait statahead thread (ll_sa_xxx) to exit..."
16117         wait_update_facet client "pgrep ll_sa" "" 35 ||
16118                 error "ll_sa statahead thread does not quit in 35s"
16119         $LCTL get_param -n llite.*.statahead_stats
16120         $LCTL get_param -n mdc.*.batch_stats
16121
16122         local count=$($LCTL get_param -n llite.*.statahead_stats |
16123                         awk '/fname.total:/ {print $2}')
16124
16125         [ $count == 1 ] || error "File name pattern statahead not trigger"
16126         count=$($LCTL get_param -n llite.*.statahead_stats |
16127                 awk '/hit.total:/ {print $2}')
16128         # Hit ratio should be >= 75%
16129         (( $count > fcnt * 75 / 100 )) ||
16130                 error "hit total is too low: $count"
16131         rm -rf $dir || error "rm -rf $dir failed"
16132 }
16133
16134 test_123h() {
16135         local max
16136         local batch_max
16137         local enabled
16138
16139         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16140                 skip "Server does not support batch RPC"
16141
16142         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
16143         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
16144         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
16145         stack_trap "$LCTL set_param llite.*.statahead_max=$max"
16146         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max"
16147         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
16148
16149         $LCTL set_param llite.*.enable_statahead_fname=1
16150
16151         echo "Scan a directory with number regularized fname"
16152         test_123h_base "0..10000" 10000
16153
16154         echo "Scan a directory with zeroed padding number regularized fname"
16155         test_123h_base "000000..010000" 10000
16156 }
16157 run_test 123h "Verify statahead work with the fname pattern via du"
16158
16159 test_123i_base() {
16160         local fmt=$1
16161         local iocmd=$2
16162         local dir=$DIR/$tdir
16163         local cmd="createmany -m $fmt"
16164
16165         echo "Command:"
16166         echo "- $cmd"
16167         echo "- $iocmd"
16168         stack_trap "unlinkmany $fmt"
16169         mkdir -p $dir || error "failed to mkdir $dir"
16170         eval $cmd
16171
16172         cancel_lru_locks mdc
16173         $LCTL set_param llite.*.statahead_stats=clear
16174         $LCTL set_param mdc.*.batch_stats=0
16175
16176         echo "statahead_stats (Pre):"
16177         $LCTL get_param -n llite.*.statahead_stats
16178         eval $iocmd || error "$iocmd failed"
16179         echo "statahead_stats (Post):"
16180         $LCTL get_param -n llite.*.statahead_stats
16181         $LCTL get_param -n mdc.*.batch_stats
16182
16183         echo "Wait the statahead thread (ll_sa_xxx) to exit ..."
16184         wait_update_facet client "pgrep ll_sa" "" 35 ||
16185                 error "ll_sa statahead thread does not quit in 35s"
16186         $LCTL get_param -n llite.*.statahead_stats
16187         $LCTL get_param -n mdc.*.batch_stats
16188
16189         local count=$($LCTL get_param -n llite.*.statahead_stats |
16190                         awk '/fname.total:/ {print $2}')
16191
16192         [ $count == 1 ] || error "File name pattern statahead not trigger"
16193         count=$($LCTL get_param -n llite.*.statahead_stats |
16194                 awk '/hit.total:/ {print $2}')
16195         # Hit ratio should be >= 75%
16196         (( $count > 750 )) || error "hit total is too low: $count"
16197 }
16198
16199 test_123i() {
16200         local dir=$DIR/$tdir
16201         local cnt=1000
16202         local max
16203         local batch_max
16204         local enabled
16205         local min
16206
16207         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16208                 skip "Server does not support batch RPC"
16209
16210         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
16211         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
16212         min=$($LCTL get_param -n llite.*.statahead_min | head -n 1)
16213         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
16214         stack_trap "$LCTL set_param llite.*.statahead_max=$max"
16215         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max"
16216         stack_trap "$LCTL set_param llite.*.statahead_min=$min"
16217         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
16218         $LCTL set_param llite.*.statahead_max=1024
16219         $LCTL set_param llite.*.statahead_batch_max=32
16220         $LCTL set_param llite.*.statahead_min=64
16221         $LCTL set_param llite.*.enable_statahead_fname=1
16222
16223         test_123i_base "$dir/$tfile.%06d $cnt" "ls $dir/* > /dev/null"
16224         test_123i_base "$dir/$tfile $cnt" \
16225                 "aheadmany -c stat -N -s 0 -e $cnt -b $tfile -d $dir"
16226 }
16227 run_test 123i "Verify statahead work with the fname indexing pattern"
16228
16229 test_123j() {
16230         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
16231
16232         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16233                 skip "Server does not support batch RPC"
16234
16235         local enabled
16236
16237         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
16238         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
16239         $LCTL set_param llite.*.enable_statahead_fname=1
16240
16241         stack_trap "rm -rf $DIR/${tdir}.{1..11}"
16242
16243         mkdir $DIR/${tdir}.{1..10} ||
16244                 error "failed to mkdir $DIR/${tdir}.{1..10}"
16245         cancel_lru_locks mdc
16246
16247         for i in $(seq 1 10); do
16248                 stat $DIR/${tdir}.$i || error "failed to stat $DIR/${tdir}.$i"
16249         done
16250
16251         stat $DIR/${tdir}.11
16252         $LFS mkdir -i $((MDSCOUNT - 1)) -c 2 -H all_char $DIR/${tdir}.11 ||
16253                 error "failed to mkdir $DIR/${tdir}.11"
16254         touch $DIR/${tdir}.11/$tfile ||
16255                 error "failed to create file $DIR/${tdir}.11/$tfile"
16256 }
16257 run_test 123j "-ENOENT error from batched statahead be handled correctly"
16258
16259 test_123k() {
16260         MDTEST=${MDTEST:=$(which mdtest 2> /dev/null || true)}
16261         [[ -n "$MDTEST" ]] || skip_env "mdtest not found"
16262
16263         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16264                 skip "Server does not support batch RPC"
16265
16266         local enabled
16267
16268         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
16269         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
16270         $LCTL set_param llite.*.enable_statahead_fname=1
16271
16272         local np=2
16273
16274         mpi_run -np $np $MDTEST -C -F -n 1000 -d $DIR/$tdir
16275         cancel_lru_locks mdc
16276         $LCTL set_param llite.*.statahead_stats=clear
16277         $LCTL set_param mdc.*.batch_stats=0
16278         mpi_run -np $np $MDTEST -T -F -n 1000 -d $DIR/$tdir
16279         #umount_client $MOUNT || error "failed to umount client"
16280         echo "Sleep to wait statahead thread (ll_sa_xxx) to exit ..."
16281         wait_update_facet client "pgrep ll_sa" "" 35 ||
16282                 error "ll_sa thread is still running"
16283
16284         $LCTL get_param -n llite.*.statahead_stats
16285         $LCTL get_param -n mdc.*.batch_stats
16286         ps -el | grep ll_sa
16287
16288         local count=$($LCTL get_param -n llite.*.statahead_stats |
16289                         awk '/fname.total:/ {print $2}')
16290
16291         [ $count == $np ] || error "File name pattern statahead not trigger"
16292         count=$($LCTL get_param -n llite.*.statahead_stats |
16293                 awk '/hit.total:/ {print $2}')
16294         # Hit ratio should be >= 75%
16295         [ $count -gt $((np * 1000 * 75 / 100)) ] ||
16296                 error "hit total is too low: $count"
16297 }
16298 run_test 123k "Verify statahead work with mdtest shared stat() mode"
16299
16300 test_123l() {
16301         local dir=$DIR/$tdir
16302         local cmd="touch $dir/$tfile.{000000..000100}"
16303
16304         $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc ||
16305                 skip "Server does not support batch RPC"
16306
16307         stack_trap "rm -rf $dir"
16308         mkdir -p $dir || error "failed to mkdir $dir"
16309         eval $cmd
16310
16311         cancel_lru_locks mdc
16312         $LCTL set_param llite.*.statahead_stats=clear
16313         $LCTL set_param mdc.*.batch_stats=0
16314
16315         local max
16316         local batch_max
16317         local enabled
16318
16319         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
16320         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
16321         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
16322         stack_trap "$LCTL set_param llite.*.statahead_max=$max"
16323         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max"
16324         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
16325         $LCTL set_param llite.*.enable_statahead_fname=1
16326         $LCTL set_param llite.*.statahead_max=1024
16327         $LCTL set_param llite.*.statahead_batch_max=32
16328         $LCTL get_param -n llite.*.statahead_stats
16329         #define OBD_FAIL_LLITE_STATAHEAD_PAUSE  0x1433
16330         $LCTL set_param fail_loc=0x80001433 fail_val=35
16331         ls $dir/* > /dev/null
16332         $LCTL get_param -n llite.*.statahead_stats
16333         $LCTL get_param -n mdc.*.batch_stats
16334
16335         echo "Sleep to wait the statahead thread (ll_sa_xxx) to exit ..."
16336         wait_update_facet client "pgrep ll_sa" "" 35 ||
16337                 error "ll_sa thread is still running"
16338         $LCTL get_param -n llite.*.statahead_stats
16339 }
16340 run_test 123l "Avoid panic when revalidate a local cached entry"
16341
16342 test_124a() {
16343         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16344         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
16345                 skip_env "no lru resize on server"
16346
16347         local NR=2000
16348
16349         test_mkdir $DIR/$tdir
16350
16351         log "create $NR files at $DIR/$tdir"
16352         createmany -o $DIR/$tdir/f $NR ||
16353                 error "failed to create $NR files in $DIR/$tdir"
16354
16355         cancel_lru_locks mdc
16356         ls -l $DIR/$tdir > /dev/null
16357
16358         local NSDIR=""
16359         local LRU_SIZE=0
16360         for VALUE in $($LCTL get_param ldlm.namespaces.*mdc-*.lru_size); do
16361                 local PARAM=$(echo ${VALUE[0]} | cut -d "=" -f1)
16362                 LRU_SIZE=$($LCTL get_param -n $PARAM)
16363                 if [[ $LRU_SIZE -gt $(default_lru_size) ]]; then
16364                         NSDIR=$(echo $PARAM | cut -d "." -f1-3)
16365                         log "NSDIR=$NSDIR"
16366                         log "NS=$(basename $NSDIR)"
16367                         break
16368                 fi
16369         done
16370
16371         if [[ -z "$NSDIR" || $LRU_SIZE -lt $(default_lru_size) ]]; then
16372                 skip "Not enough cached locks created!"
16373         fi
16374         log "LRU=$LRU_SIZE"
16375
16376         local SLEEP=30
16377
16378         # We know that lru resize allows one client to hold $LIMIT locks
16379         # for 10h. After that locks begin to be killed by client.
16380         local MAX_HRS=10
16381         local LIMIT=$($LCTL get_param -n $NSDIR.pool.limit)
16382         log "LIMIT=$LIMIT"
16383         if [ $LIMIT -lt $LRU_SIZE ]; then
16384                 skip "Limit is too small $LIMIT"
16385         fi
16386
16387         # Make LVF so higher that sleeping for $SLEEP is enough to _start_
16388         # killing locks. Some time was spent for creating locks. This means
16389         # that up to the moment of sleep finish we must have killed some of
16390         # them (10-100 locks). This depends on how fast ther were created.
16391         # Many of them were touched in almost the same moment and thus will
16392         # be killed in groups.
16393         local LVF=$(($MAX_HRS * 60 * 60 / $SLEEP * $LIMIT / $LRU_SIZE * 100))
16394
16395         # Use $LRU_SIZE_B here to take into account real number of locks
16396         # created in the case of CMD, LRU_SIZE_B != $NR in most of cases
16397         local LRU_SIZE_B=$LRU_SIZE
16398         log "LVF=$LVF"
16399         local OLD_LVF=$($LCTL get_param -n $NSDIR.pool.lock_volume_factor)
16400         log "OLD_LVF=$OLD_LVF"
16401         $LCTL set_param -n $NSDIR.pool.lock_volume_factor $LVF
16402
16403         # Let's make sure that we really have some margin. Client checks
16404         # cached locks every 10 sec.
16405         SLEEP=$((SLEEP+20))
16406         log "Sleep ${SLEEP} sec"
16407         local SEC=0
16408         while ((SEC<$SLEEP)); do
16409                 echo -n "..."
16410                 sleep 5
16411                 SEC=$((SEC+5))
16412                 LRU_SIZE=$($LCTL get_param -n $NSDIR/lru_size)
16413                 echo -n "$LRU_SIZE"
16414         done
16415         echo ""
16416         $LCTL set_param -n $NSDIR.pool.lock_volume_factor $OLD_LVF
16417         local LRU_SIZE_A=$($LCTL get_param -n $NSDIR.lru_size)
16418
16419         [[ $LRU_SIZE_B -gt $LRU_SIZE_A ]] || {
16420                 error "No locks dropped in ${SLEEP}s. LRU size: $LRU_SIZE_A"
16421                 unlinkmany $DIR/$tdir/f $NR
16422                 return
16423         }
16424
16425         log "Dropped "$((LRU_SIZE_B-LRU_SIZE_A))" locks in ${SLEEP}s"
16426         log "unlink $NR files at $DIR/$tdir"
16427         unlinkmany $DIR/$tdir/f $NR
16428 }
16429 run_test 124a "lru resize ======================================="
16430
16431 get_max_pool_limit()
16432 {
16433         local limit=$($LCTL get_param \
16434                       -n ldlm.namespaces.*-MDT0000-mdc-*.pool.limit)
16435         local max=0
16436         for l in $limit; do
16437                 if [[ $l -gt $max ]]; then
16438                         max=$l
16439                 fi
16440         done
16441         echo $max
16442 }
16443
16444 test_124b() {
16445         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16446         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
16447                 skip_env "no lru resize on server"
16448
16449         LIMIT=$(get_max_pool_limit)
16450
16451         NR=$(($(default_lru_size)*20))
16452         if [[ $NR -gt $LIMIT ]]; then
16453                 log "Limit lock number by $LIMIT locks"
16454                 NR=$LIMIT
16455         fi
16456
16457         IFree=$(mdsrate_inodes_available)
16458         if [ $IFree -lt $NR ]; then
16459                 log "Limit lock number by $IFree inodes"
16460                 NR=$IFree
16461         fi
16462
16463         lru_resize_disable mdc
16464         stack_trap "lru_resize_enable mdc" EXIT
16465         test_mkdir -p $DIR/$tdir/disable_lru_resize
16466
16467         createmany -o $DIR/$tdir/disable_lru_resize/f $NR
16468         log "doing ls -la $DIR/$tdir/disable_lru_resize 3 times"
16469         cancel_lru_locks mdc
16470         stime=$SECONDS
16471         PID=""
16472         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
16473         PID="$PID $!"
16474         sleep 2
16475         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
16476         PID="$PID $!"
16477         sleep 2
16478         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
16479         PID="$PID $!"
16480         wait $PID
16481         etime=$SECONDS
16482         nolruresize_delta=$((etime-stime))
16483         log "ls -la time: $nolruresize_delta seconds"
16484         log "lru_size = $(lctl get_param -n ldlm.namespaces.*mdc*.lru_size)"
16485         unlinkmany $DIR/$tdir/disable_lru_resize/f $NR
16486
16487         lru_resize_enable mdc
16488         test_mkdir -p $DIR/$tdir/enable_lru_resize
16489
16490         stack_trap "unlinkmany $DIR/$tdir/enable_lru_resize/f $NR"
16491         createmany -o $DIR/$tdir/enable_lru_resize/f $NR
16492         log "doing ls -la $DIR/$tdir/enable_lru_resize 3 times"
16493         cancel_lru_locks mdc
16494         stime=$SECONDS
16495         PID=""
16496         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
16497         PID="$PID $!"
16498         sleep 2
16499         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
16500         PID="$PID $!"
16501         sleep 2
16502         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
16503         PID="$PID $!"
16504         wait $PID
16505         etime=$SECONDS
16506         lruresize_delta=$((etime-stime))
16507         log "ls -la time: $lruresize_delta seconds"
16508         log "lru_size = $(lctl get_param -n ldlm.namespaces.*mdc*.lru_size)"
16509
16510         if [ $lruresize_delta -gt $nolruresize_delta ]; then
16511                 log "ls -la is $(((lruresize_delta - $nolruresize_delta) * 100 / $nolruresize_delta))% slower with lru resize enabled"
16512         elif [ $nolruresize_delta -gt $lruresize_delta ]; then
16513                 log "ls -la is $(((nolruresize_delta - $lruresize_delta) * 100 / $nolruresize_delta))% faster with lru resize enabled"
16514         else
16515                 log "lru resize performs the same with no lru resize"
16516         fi
16517 }
16518 run_test 124b "lru resize (performance test) ======================="
16519
16520 test_124c() {
16521         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16522         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
16523                 skip_env "no lru resize on server"
16524
16525         # cache ununsed locks on client
16526         local nr=100
16527         cancel_lru_locks mdc
16528         test_mkdir $DIR/$tdir
16529         createmany -o $DIR/$tdir/f $nr ||
16530                 error "failed to create $nr files in $DIR/$tdir"
16531         ls -l $DIR/$tdir > /dev/null
16532
16533         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
16534         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
16535         local max_age=$($LCTL get_param -n $nsdir.lru_max_age)
16536         local recalc_p=$($LCTL get_param -n $nsdir.pool.recalc_period)
16537         echo "unused=$unused, max_age=$max_age, recalc_p=$recalc_p"
16538
16539         # set lru_max_age to 1 sec
16540         $LCTL set_param $nsdir.lru_max_age=1000 # milliseconds
16541         echo "sleep $((recalc_p * 2)) seconds..."
16542         sleep $((recalc_p * 2))
16543
16544         local remaining=$($LCTL get_param -n $nsdir.lock_unused_count)
16545         # restore lru_max_age
16546         $LCTL set_param -n $nsdir.lru_max_age $max_age
16547         [ $remaining -eq 0 ] || error "$remaining locks are not canceled"
16548         unlinkmany $DIR/$tdir/f $nr
16549 }
16550 run_test 124c "LRUR cancel very aged locks"
16551
16552 test_124d() {
16553         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16554         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
16555                 skip_env "no lru resize on server"
16556
16557         # cache ununsed locks on client
16558         local nr=100
16559
16560         lru_resize_disable mdc
16561
16562         cancel_lru_locks mdc
16563
16564         # asynchronous object destroy at MDT could cause bl ast to client
16565         test_mkdir $DIR/$tdir
16566         createmany -o $DIR/$tdir/f $nr ||
16567                 error "failed to create $nr files in $DIR/$tdir"
16568         stack_trap "unlinkmany $DIR/$tdir/f $nr" EXIT
16569
16570         ls -l $DIR/$tdir > /dev/null
16571
16572         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
16573         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
16574         local max_age=$($LCTL get_param -n $nsdir.lru_max_age)
16575         local recalc_p=$($LCTL get_param -n $nsdir.pool.recalc_period)
16576
16577         echo "unused=$unused, max_age=$max_age, recalc_p=$recalc_p"
16578
16579         # set lru_max_age to 1 sec
16580         $LCTL set_param $nsdir.lru_max_age=1000 # milliseconds
16581         stack_trap "$LCTL set_param -n $nsdir.lru_max_age $max_age" EXIT
16582
16583         echo "sleep $((recalc_p * 2)) seconds..."
16584         sleep $((recalc_p * 2))
16585
16586         local remaining=$($LCTL get_param -n $nsdir.lock_unused_count)
16587
16588         [ $remaining -eq 0 ] || error "$remaining locks are not canceled"
16589 }
16590 run_test 124d "cancel very aged locks if lru-resize disabled"
16591
16592 test_125() { # 13358
16593         $LCTL get_param -n llite.*.client_type | grep -q local ||
16594                 skip "must run as local client"
16595         $LCTL get_param -n mdc.*-mdc-*.connect_flags | grep -q acl ||
16596                 skip_env "must have acl enabled"
16597         [ -z "$(which setfacl)" ] && skip_env "must have setfacl tool"
16598         id $USER0 || skip_env "missing user $USER0"
16599
16600         test_mkdir $DIR/$tdir
16601         $LFS setstripe -S 65536 -c -1 $DIR/$tdir || error "setstripe failed"
16602         setfacl -R -m u:$USER0:rwx $DIR/$tdir ||
16603                 error "setfacl $DIR/$tdir failed"
16604         ls -ld $DIR/$tdir || error "cannot access $DIR/$tdir"
16605 }
16606 run_test 125 "don't return EPROTO when a dir has a non-default striping and ACLs"
16607
16608 test_126() { # bug 12829/13455
16609         $GSS && skip_env "must run as gss disabled"
16610         $LCTL get_param -n llite.*.client_type | grep -q local ||
16611                 skip "must run as local client"
16612         [ "$UID" != 0 ] && skip "must run as root, not UID $UID"
16613
16614         $RUNAS -u 0 -g 1 touch $DIR/$tfile || error "touch failed"
16615         gid=`ls -n $DIR/$tfile | awk '{print $4}'`
16616         rm -f $DIR/$tfile
16617         [ $gid -eq "1" ] || error "gid is set to" $gid "instead of 1"
16618 }
16619 run_test 126 "check that the fsgid provided by the client is taken into account"
16620
16621 test_127a() { # bug 15521
16622         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16623         local name count samp unit min max sum sumsq
16624         local tmpfile=$TMP/$tfile.tmp
16625
16626         # enable stats header if it is disabled
16627         $LCTL set_param enable_stats_header=1
16628
16629         $LFS setstripe -i 0 -c 1 $DIR/$tfile || error "setstripe failed"
16630         echo "stats before reset"
16631         stack_trap "rm -f $DIR/$tfile $tmpfile"
16632         local now=$(date +%s)
16633
16634         $LCTL get_param osc.*.stats | tee $tmpfile
16635
16636         local snapshot_time=$(awk '/snapshot_time/ { print $2; exit }' $tmpfile)
16637         local start_time=$(awk '/start_time/ { print $2; exit }' $tmpfile)
16638         local elapsed=$(awk '/elapsed_time/ { print $2; exit }' $tmpfile)
16639         local uptime=$(awk '{ print $1 }' /proc/uptime)
16640
16641         # snapshot_time should match POSIX epoch time, allow some delta for VMs
16642         (( ${snapshot_time%\.*} >= $now - 5 &&
16643            ${snapshot_time%\.*} <= $now + 5 )) ||
16644                 error "snapshot_time=$snapshot_time != now=$now"
16645         # elapsed _should_ be from mount, but at least less than uptime
16646         (( ${elapsed%\.*} < ${uptime%\.*} )) ||
16647                 error "elapsed=$elapsed > uptime=$uptime"
16648         (( ${snapshot_time%\.*} - ${start_time%\.*} >= ${elapsed%\.*} - 2 &&
16649            ${snapshot_time%\.*} - ${start_time%\.*} <= ${elapsed%\.*} + 2 )) ||
16650                 error "elapsed=$elapsed != $snapshot_time - $start_time"
16651
16652         $LCTL set_param osc.*.stats=0
16653         local reset=$(date +%s)
16654         local fsize=$((2048 * 1024))
16655
16656         dd if=/dev/zero of=$DIR/$tfile bs=$fsize count=1
16657         cancel_lru_locks osc
16658         dd if=$DIR/$tfile of=/dev/null bs=$fsize
16659
16660         now=$(date +%s)
16661         $LCTL get_param osc.*0000-osc-*.stats > $tmpfile
16662         while read name count samp unit min max sum sumsq; do
16663                 [[ "$samp" == "samples" ]] || continue
16664
16665                 echo "got name=$name count=$count unit=$unit min=$min max=$max"
16666                 [ ! $min ] && error "Missing min value for $name proc entry"
16667                 eval $name=$count || error "Wrong proc format"
16668
16669                 case $name in
16670                 read_bytes|write_bytes)
16671                         [[ "$unit" =~ "bytes" ]] ||
16672                                 error "unit is not 'bytes': $unit"
16673                         (( $min >= 4096 )) || error "min is too small: $min"
16674                         (( $min <= $fsize )) || error "min is too big: $min"
16675                         (( $max >= 4096 )) || error "max is too small: $max"
16676                         (( $max <= $fsize )) || error "max is too big: $max"
16677                         (( $sum == $fsize )) || error "sum is wrong: $sum"
16678                         (( $sumsq >= ($fsize / 4096) * (4096 * 4096) )) ||
16679                                 error "sumsquare is too small: $sumsq"
16680                         (( $sumsq <= $fsize * $fsize )) ||
16681                                 error "sumsquare is too big: $sumsq"
16682                         ;;
16683                 ost_read|ost_write)
16684                         [[ "$unit" =~ "usec" ]] ||
16685                                 error "unit is not 'usec': $unit"
16686                         ;;
16687                 *)      ;;
16688                 esac
16689         done < $tmpfile
16690
16691         #check that we actually got some stats
16692         [ "$read_bytes" ] || error "Missing read_bytes stats"
16693         [ "$write_bytes" ] || error "Missing write_bytes stats"
16694         [ "$read_bytes" != 0 ] || error "no read done"
16695         [ "$write_bytes" != 0 ] || error "no write done"
16696
16697         snapshot_time=$(awk '/snapshot_time/ { print $2; exit }' $tmpfile)
16698         start_time=$(awk '/start_time/ { print $2; exit }' $tmpfile)
16699         elapsed=$(awk '/elapsed_time/ { print $2; exit }' $tmpfile)
16700
16701         # snapshot_time should match POSIX epoch time, allow some delta for VMs
16702         (( ${snapshot_time%\.*} >= $now - 5 &&
16703            ${snapshot_time%\.*} <= $now + 5 )) ||
16704                 error "reset snapshot_time=$snapshot_time != now=$now"
16705         # elapsed should be from time of stats reset
16706         (( ${elapsed%\.*} >= $now - $reset - 2 &&
16707            ${elapsed%\.*} <= $now - $reset + 2 )) ||
16708                 error "reset elapsed=$elapsed > $now - $reset"
16709         (( ${snapshot_time%\.*} - ${start_time%\.*} >= ${elapsed%\.*} - 2 &&
16710            ${snapshot_time%\.*} - ${start_time%\.*} <= ${elapsed%\.*} + 2 )) ||
16711                 error "reset elapsed=$elapsed != $snapshot_time - $start_time"
16712 }
16713 run_test 127a "verify the client stats are sane"
16714
16715 test_127b() { # bug LU-333
16716         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16717         local name count samp unit min max sum sumsq
16718
16719         echo "stats before reset"
16720         $LCTL get_param llite.*.stats
16721         $LCTL set_param llite.*.stats=0
16722
16723         # perform 2 reads and writes so MAX is different from SUM.
16724         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1
16725         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1
16726         cancel_lru_locks osc
16727         dd if=$DIR/$tfile of=/dev/null bs=$PAGE_SIZE count=1
16728         dd if=$DIR/$tfile of=/dev/null bs=$PAGE_SIZE count=1
16729
16730         $LCTL get_param llite.*.stats | grep samples > $TMP/$tfile.tmp
16731         stack_trap "rm -f $TMP/$tfile.tmp"
16732         while read name count samp unit min max sum sumsq; do
16733                 echo "got name=$name count=$count unit=$unit min=$min max=$max"
16734                 eval $name=$count || error "Wrong proc format"
16735
16736                 case $name in
16737                 read_bytes|write_bytes)
16738                         [[ "$unit" =~ "bytes" ]] ||
16739                                 error "unit is not 'bytes': $unit"
16740                         (( $count == 2 )) || error "count is not 2: $count"
16741                         (( $min == $PAGE_SIZE )) ||
16742                                 error "min is not $PAGE_SIZE: $min"
16743                         (( $max == $PAGE_SIZE )) ||
16744                                 error "max is not $PAGE_SIZE: $max"
16745                         (( $sum == $PAGE_SIZE * 2 )) ||
16746                                 error "sum is not $((PAGE_SIZE * 2)): $sum"
16747                         ;;
16748                 read|write)
16749                         [[ "$unit" =~ "usec" ]] ||
16750                                 error "unit is not 'usec': $unit"
16751                         ;;
16752                 *)      ;;
16753                 esac
16754         done < $TMP/$tfile.tmp
16755
16756         #check that we actually got some stats
16757         [ "$read_bytes" ] || error "Missing read_bytes stats"
16758         [ "$write_bytes" ] || error "Missing write_bytes stats"
16759         [ "$read_bytes" != 0 ] || error "no read done"
16760         [ "$write_bytes" != 0 ] || error "no write done"
16761 }
16762 run_test 127b "verify the llite client stats are sane"
16763
16764 test_127c() { # LU-12394
16765         [ "$OSTCOUNT" -lt "2" ] && skip_env "needs >= 2 OSTs"
16766         local size
16767         local bsize
16768         local reads
16769         local writes
16770         local count
16771
16772         $LCTL set_param llite.*.extents_stats=1
16773         stack_trap "$LCTL set_param llite.*.extents_stats=0" EXIT
16774
16775         # Use two stripes so there is enough space in default config
16776         $LFS setstripe -c 2 $DIR/$tfile
16777
16778         # Extent stats start at 0-4K and go in power of two buckets
16779         # LL_HIST_START = 12 --> 2^12 = 4K
16780         # We do 3K*2^i, so 3K, 6K, 12K, 24K... hitting each bucket.
16781         # We do not do buckets larger than 64 MiB to avoid ENOSPC issues on
16782         # small configs
16783         for size in 3K 6K 12K 24K 48K 96K 192K 384K 768K 1536K 3M 6M 12M 24M 48M;
16784                 do
16785                 # Write and read, 2x each, second time at a non-zero offset
16786                 dd if=/dev/zero of=$DIR/$tfile bs=$size count=1
16787                 dd if=/dev/zero of=$DIR/$tfile bs=$size count=1 seek=10
16788                 dd if=$DIR/$tfile of=/dev/null bs=$size count=1
16789                 dd if=$DIR/$tfile of=/dev/null bs=$size count=1 seek=10
16790                 rm -f $DIR/$tfile
16791         done
16792
16793         $LCTL get_param llite.*.extents_stats
16794
16795         count=2
16796         for bsize in 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M;
16797                 do
16798                 local bucket=$($LCTL get_param -n llite.*.extents_stats |
16799                                 grep -m 1 $bsize)
16800                 reads=$(echo $bucket | awk '{print $5}')
16801                 writes=$(echo $bucket | awk '{print $9}')
16802                 [ "$reads" -eq $count ] ||
16803                         error "$reads reads in < $bsize bucket, expect $count"
16804                 [ "$writes" -eq $count ] ||
16805                         error "$writes writes in < $bsize bucket, expect $count"
16806         done
16807
16808         # Test mmap write and read
16809         $LCTL set_param llite.*.extents_stats=c
16810         size=512
16811         dd if=/dev/zero of=$DIR/$tfile bs=${size}K count=1
16812         $MULTIOP $DIR/$tfile OSMRUc || error "$MULTIOP $DIR/$tfile failed"
16813         $MULTIOP $DIR/$tfile OSMWUc || error "$MULTIOP $DIR/$tfile failed"
16814
16815         $LCTL get_param llite.*.extents_stats
16816
16817         count=$(((size*1024) / PAGE_SIZE))
16818
16819         bsize=$((2 * PAGE_SIZE / 1024))K
16820
16821         bucket=$($LCTL get_param -n llite.*.extents_stats |
16822                         grep -m 1 $bsize)
16823         reads=$(echo $bucket | awk '{print $5}')
16824         writes=$(echo $bucket | awk '{print $9}')
16825         # mmap writes fault in the page first, creating an additonal read
16826         [ "$reads" -eq $((2 * count)) ] ||
16827                 error "$reads reads in < $bsize bucket, expect $count"
16828         [ "$writes" -eq $count ] ||
16829                 error "$writes writes in < $bsize bucket, expect $count"
16830 }
16831 run_test 127c "test llite extent stats with regular & mmap i/o"
16832
16833 test_128() { # bug 15212
16834         touch $DIR/$tfile
16835         $LFS 2>&1 <<-EOF | tee $TMP/$tfile.log
16836                 find $DIR/$tfile
16837                 find $DIR/$tfile
16838         EOF
16839
16840         result=$(grep error $TMP/$tfile.log)
16841         rm -f $DIR/$tfile $TMP/$tfile.log
16842         [ -z "$result" ] ||
16843                 error "consecutive find's under interactive lfs failed"
16844 }
16845 run_test 128 "interactive lfs for 2 consecutive find's"
16846
16847 set_dir_limits () {
16848         local mntdev
16849         local canondev
16850         local node
16851
16852         local ldproc=/proc/fs/ldiskfs
16853         local facets=$(get_facets MDS)
16854
16855         for facet in ${facets//,/ }; do
16856                 canondev=$(ldiskfs_canon \
16857                            *.$(convert_facet2label $facet).mntdev $facet)
16858                 do_facet $facet "test -e $ldproc/$canondev/max_dir_size" ||
16859                         ldproc=/sys/fs/ldiskfs
16860                 do_facet $facet "echo $1 >$ldproc/$canondev/max_dir_size"
16861                 do_facet $facet "echo $2 >$ldproc/$canondev/warning_dir_size"
16862         done
16863 }
16864
16865 check_mds_dmesg() {
16866         local facets=$(get_facets MDS)
16867         for facet in ${facets//,/ }; do
16868                 do_facet $facet "dmesg | tail -3 | grep $1" && return 0
16869         done
16870         return 1
16871 }
16872
16873 test_129() {
16874         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16875         [[ $MDS1_VERSION -ge $(version_code 2.5.56) ]] ||
16876                 skip "Need MDS version with at least 2.5.56"
16877         if [ "$mds1_FSTYPE" != ldiskfs ]; then
16878                 skip_env "ldiskfs only test"
16879         fi
16880         remote_mds_nodsh && skip "remote MDS with nodsh"
16881
16882         local ENOSPC=28
16883         local has_warning=false
16884
16885         rm -rf $DIR/$tdir
16886         mkdir -p $DIR/$tdir
16887
16888         # block size of mds1
16889         local maxsize=$(($($LCTL get_param -n mdc.*MDT0000*.blocksize) * 8))
16890         set_dir_limits $maxsize $((maxsize * 6 / 8))
16891         stack_trap "set_dir_limits 0 0"
16892         stack_trap "unlinkmany $DIR/$tdir/file_base_ 2000 || true"
16893         local dirsize=$(stat -c%s "$DIR/$tdir")
16894         local nfiles=0
16895         while (( $dirsize <= $maxsize )); do
16896                 $MCREATE $DIR/$tdir/file_base_$nfiles
16897                 rc=$?
16898                 # check two errors:
16899                 # ENOSPC for ext4 max_dir_size, which has been used since
16900                 # kernel v3.6-rc1-8-gdf981d03ee, lustre v2_4_50_0-79-gaed82035c0
16901                 if (( rc == ENOSPC )); then
16902                         set_dir_limits 0 0
16903                         echo "rc=$rc returned as expected after $nfiles files"
16904
16905                         createmany -o $DIR/$tdir/file_extra_$nfiles. 5 ||
16906                                 error "create failed w/o dir size limit"
16907
16908                         # messages may be rate limited if test is run repeatedly
16909                         check_mds_dmesg '"is approaching max"' ||
16910                                 echo "warning message should be output"
16911                         check_mds_dmesg '"has reached max"' ||
16912                                 echo "reached message should be output"
16913
16914                         dirsize=$(stat -c%s "$DIR/$tdir")
16915
16916                         [[ $dirsize -ge $maxsize ]] && return 0
16917                         error "dirsize $dirsize < $maxsize after $nfiles files"
16918                 elif (( rc != 0 )); then
16919                         break
16920                 fi
16921                 nfiles=$((nfiles + 1))
16922                 dirsize=$(stat -c%s "$DIR/$tdir")
16923         done
16924
16925         error "rc=$rc, size=$dirsize/$maxsize, mdt=$MDSCOUNT, nfiles=$nfiles"
16926 }
16927 run_test 129 "test directory size limit ========================"
16928
16929 OLDIFS="$IFS"
16930 test_130a() {
16931         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
16932         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
16933
16934         local fm_file=$DIR/$tfile
16935
16936         $LFS setstripe -S 65536 -c 1 $fm_file || error "setstripe on $fm_file"
16937         stack_trap "rm -f $fm_file"
16938         dd if=/dev/zero of=$fm_file bs=65536 count=1 ||
16939                 error "dd failed for $fm_file"
16940
16941         # LU-1795: test filefrag/FIEMAP once, even if unsupported on ZFS
16942         filefrag -ves $fm_file
16943         local rc=$?
16944         [[ "$ost1_FSTYPE" != "zfs" ]] ||
16945                 skip "LU-1941: FIEMAP unimplemented on ZFS"
16946         (( $rc == 0 )) || error "filefrag $fm_file failed"
16947
16948         filefrag_op=$(filefrag -ve -k $fm_file |
16949                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
16950         local lun=$($LFS getstripe -i $fm_file)
16951         local start_blk=$(echo $filefrag_op | cut -d: -f2 | cut -d. -f1)
16952         local tot_len=0
16953
16954         while read line; do
16955                 local frag_lun=$(echo $line | cut -d: -f5)
16956                 local ext_len=$(echo $line | cut -d: -f4)
16957
16958                 (( $frag_lun == $lun )) ||
16959                         error "OST$lun was reported on OST$frag_lun"
16960                 (( tot_len += ext_len ))
16961         done <<< "$filefrag_op"
16962
16963         (( start_blk == 0 )) ||
16964                 error "OST$last_lun start_blk $start_blk != 0"
16965         (( tot_len == 64 )) ||
16966                 error "OST$last_lun $tot_len != 64"
16967
16968         echo "FIEMAP on single striped file succeeded"
16969 }
16970 run_test 130a "FIEMAP (1-stripe file)"
16971
16972 test_130b() {
16973         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
16974
16975         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
16976         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
16977         [[ "$ost1_FSTYPE" != "zfs" ]] ||
16978                 skip "LU-1941: FIEMAP unimplemented on ZFS"
16979
16980         local fm_file=$DIR/$tfile
16981         $LFS setstripe -S 65536 -c $OSTCOUNT $fm_file ||
16982                 error "setstripe on $fm_file"
16983         stack_trap "rm -f $fm_file"
16984
16985         local actual_stripe_count=$($LFS getstripe -c $fm_file)
16986         dd if=/dev/zero of=$fm_file bs=1M count=$actual_stripe_count ||
16987                 error "dd failed on $fm_file"
16988
16989         filefrag -ves $fm_file || error "filefrag $fm_file failed"
16990         filefrag_op=$(filefrag -ve -k $fm_file |
16991                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
16992
16993         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
16994                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
16995         local tot_len=0
16996         local num_luns=1
16997
16998         while read line; do
16999                 local frag_lun=$(echo $line | cut -d: -f5 |
17000                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
17001                 local ext_len=$(echo $line | cut -d: -f4)
17002                 if (( $frag_lun != $last_lun )); then
17003                         (( tot_len == 1024 )) ||
17004                                 error "OST$last_lun $tot_len != 1024"
17005                         (( num_luns += 1 ))
17006                         tot_len=0
17007                 fi
17008                 (( tot_len += ext_len ))
17009                 last_lun=$frag_lun
17010         done <<< "$filefrag_op"
17011
17012         (( num_luns == $actual_stripe_count )) ||
17013                 error "OST$last_lun $num_luns != $actual_stripe_count"
17014         (( tot_len == 1024 )) ||
17015                 error "OST$last_lun $tot_len != 1024"
17016
17017         echo "FIEMAP on $OSTCOUNT-stripe file succeeded"
17018 }
17019 run_test 130b "FIEMAP ($OSTCOUNT-stripe file)"
17020
17021 test_130c() {
17022         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
17023
17024         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17025         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
17026         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17027                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17028
17029         local fm_file=$DIR/$tfile
17030         $LFS setstripe -S 65536 -c 2 $fm_file || error "setstripe on $fm_file"
17031         stack_trap "rm -f $fm_file"
17032
17033         dd if=/dev/zero of=$fm_file seek=1 bs=1M count=1 ||
17034                 error "dd failed on $fm_file"
17035
17036         filefrag -ves $fm_file || error "filefrag $fm_file failed"
17037         filefrag_op=$(filefrag -ve -k $fm_file |
17038                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
17039
17040         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
17041                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
17042         local tot_len=0
17043         local num_luns=1
17044
17045         while read line; do
17046                 local frag_lun=$(echo $line | cut -d: -f5 |
17047                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
17048                 local ext_len=$(echo $line | cut -d: -f4)
17049                 if (( $frag_lun != $last_lun )); then
17050                         local logical=$(echo $line | cut -d: -f2 | cut -d. -f1)
17051                         (( logical == 512 )) ||
17052                                 error "OST$last_lun logical start $logical != 512"
17053                         (( tot_len == 512 )) ||
17054                                 error "OST$last_lun $tot_len != 512"
17055                         (( num_luns += 1 ))
17056                         tot_len=0
17057                 fi
17058                 (( tot_len += ext_len ))
17059                 last_lun=$frag_lun
17060         done <<< "$filefrag_op"
17061         (( num_luns == 2 )) ||
17062                 error "OST$last_lun $num_luns != 2"
17063         (( tot_len == 512 )) ||
17064                 error "OST$last_lun $tot_len != 512"
17065
17066         echo "FIEMAP on 2-stripe file with hole succeeded"
17067 }
17068 run_test 130c "FIEMAP (2-stripe file with hole)"
17069
17070 test_130d() {
17071         (( $OSTCOUNT >= 3 )) || skip "needs >= 3 OSTs"
17072
17073         filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17074         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
17075         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17076                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17077
17078         local fm_file=$DIR/$tfile
17079         $LFS setstripe -S 65536 -c $OSTCOUNT $fm_file ||
17080                         error "setstripe on $fm_file"
17081         stack_trap "rm -f $fm_file"
17082
17083         local actual_stripe_count=$($LFS getstripe -c $fm_file)
17084         dd if=/dev/zero of=$fm_file bs=1M count=$actual_stripe_count ||
17085                 error "dd failed on $fm_file"
17086
17087         filefrag -ves $fm_file || error "filefrag $fm_file failed"
17088         filefrag_op=$(filefrag -ve -k $fm_file |
17089                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
17090
17091         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
17092                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
17093         local tot_len=0
17094         local num_luns=1
17095
17096         while read line; do
17097                 local frag_lun=$(echo $line | cut -d: -f5 |
17098                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
17099                 local ext_len=$(echo $line | cut -d: -f4)
17100                 if (( $frag_lun != $last_lun )); then
17101                         (( tot_len == 1024 )) ||
17102                                 error "OST$last_lun $tot_len != 1024"
17103                         (( num_luns += 1 ))
17104                         tot_len=0
17105                 fi
17106                 (( tot_len += ext_len ))
17107                 last_lun=$frag_lun
17108         done <<< "$filefrag_op"
17109
17110         (( num_luns == actual_stripe_count )) ||
17111                 error "OST$last_lun $num_luns != $actual_stripe_count"
17112         (( tot_len == 1024 )) ||
17113                 error "OST$last_lun $tot_len != 1024"
17114
17115         echo "FIEMAP on N-stripe file succeeded"
17116 }
17117 run_test 130d "FIEMAP (N-stripe file)"
17118
17119 test_130e() {
17120         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
17121
17122         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17123         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
17124         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17125                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17126
17127         local fm_file=$DIR/$tfile
17128         $LFS setstripe -S 131072 -c 2 $fm_file || error "setstripe on $fm_file"
17129         stack_trap "rm -f $fm_file"
17130
17131         local num_blks=512
17132         local expected_len=$(( (num_blks / 2) * 64 ))
17133         for ((i = 0; i < $num_blks; i++)); do
17134                 dd if=/dev/zero of=$fm_file count=1 bs=64k seek=$((2*$i)) \
17135                         conv=notrunc > /dev/null 2>&1
17136         done
17137
17138         filefrag -ves $fm_file || error "filefrag $fm_file failed"
17139         filefrag_op=$(filefrag -ve -k $fm_file |
17140                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
17141
17142         local last_lun=$(echo $filefrag_op | cut -d: -f5)
17143         local tot_len=0
17144         local num_luns=1
17145
17146         while read line; do
17147                 local frag_lun=$(echo $line | cut -d: -f5)
17148                 local ext_len=$(echo $line | cut -d: -f4)
17149                 if (( $frag_lun != $last_lun )); then
17150                         (( tot_len == $expected_len )) ||
17151                                 error "OST$last_lun $tot_len != $expected_len"
17152                         (( num_luns += 1 ))
17153                         tot_len=0
17154                 fi
17155                 (( tot_len += ext_len ))
17156                 last_lun=$frag_lun
17157         done <<< "$filefrag_op"
17158         (( num_luns == 2 )) ||
17159                 error "OST$last_lun $num_luns != 2"
17160         (( tot_len == $expected_len )) ||
17161                 error "OST$last_lun $tot_len != $expected_len"
17162
17163         echo "FIEMAP with continuation calls succeeded"
17164 }
17165 run_test 130e "FIEMAP (test continuation FIEMAP calls)"
17166
17167 test_130f() {
17168         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17169         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
17170         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17171                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17172
17173         local fm_file=$DIR/$tfile
17174         $MULTIOP $fm_file oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:T33554432c ||
17175                 error "multiop create with lov_delay_create on $fm_file"
17176
17177         filefrag -ves $fm_file || error "filefrag $fm_file failed"
17178         filefrag_extents=$(filefrag -vek $fm_file |
17179                            awk '/extents? found/ { print $2 }')
17180         if (( $filefrag_extents != 0 )); then
17181                 error "$fm_file: filefrag_extents=$filefrag_extents != 0"
17182         fi
17183
17184         rm -f $fm_file
17185 }
17186 run_test 130f "FIEMAP (unstriped file)"
17187
17188 test_130g() {
17189         (( $MDS1_VERSION >= $(version_code 2.12.53) )) ||
17190                 skip "Need MDS version with at least 2.12.53 for overstriping"
17191         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17192         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
17193         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17194                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17195
17196         local file=$DIR/$tfile
17197         local nr=$((OSTCOUNT * 100))
17198
17199         $LFS setstripe -C $nr -S1M $file ||
17200                 error "failed to setstripe -C $nr $file"
17201
17202         stack_trap "rm -f $file"
17203         dd if=/dev/zero of=$file count=$nr bs=1M
17204         sync
17205         nr=$($LFS getstripe -c $file)
17206
17207         local extents=$(filefrag -v $file |
17208                         sed -n '/ext:/,/found/{/ext:/d; /found/d; p}' | wc -l)
17209
17210         echo "filefrag list $extents extents in file with stripecount $nr"
17211         if (( extents < nr )); then
17212                 $LFS getstripe $file
17213                 filefrag -v $file
17214                 error "filefrag printed $extents < $nr extents"
17215         fi
17216 }
17217 run_test 130g "FIEMAP (overstripe file)"
17218
17219 test_130h() {
17220         (( OSTCOUNT < 2 )) && skip_env "need 2 OSTs"
17221
17222         $LFS setstripe -o 0,1 -S 1M $DIR/$tfile
17223         $LFS getstripe $DIR/$tfile
17224         dd if=/dev/zero of=$DIR/$tfile bs=1M count=2
17225         stack_trap "rm -f $DIR/$tfile"
17226         $LCTL set_param ldlm.namespaces.*-OST0000-osc-*.lru_size=clear
17227         sleep 1
17228         local before=$(date +%s)
17229         ##define OBD_FAIL_OSC_FIEMAP              0x418
17230         $LCTL set_param fail_loc=0x80000418 fail_val=5
17231         checkfiemap $DIR/$tfile $((2 * 1024 * 1024)) &
17232         sleep 1
17233         dd if=/dev/zero of=$DIR/$tfile bs=1M count=3
17234         wait
17235         $LCTL set_param fail_loc=0 fail_val=0
17236         # check for client eviction
17237         local evict=$($LCTL get_param osc.$FSNAME-OST0001-osc-f*.state |
17238           awk -F"[ [,]" '/EVICTED ]$/ { if (mx<$5) {mx=$5;} } END { print mx }')
17239         [ -z "$evict" ] || [[ $evict -le $before ]] || error "eviction happened"
17240 }
17241 run_test 130h "FIEMAP deadlock"
17242
17243 test_130i() {
17244         (( $MDS1_VERSION >= $(version_code 2.15.63.195) )) ||
17245                 skip "Need MDS version at least 2.15.63.195 for DoM support"
17246         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
17247         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing Lustre support"
17248         [[ "$ost1_FSTYPE" != "zfs" ]] ||
17249                 skip "LU-1941: FIEMAP unimplemented on ZFS"
17250
17251         local dom_file=$DIR/$tfile
17252
17253         stack_trap "rm -f $dom_file"
17254
17255         $LFS setstripe -E 1M -L mdt -E -1 -c2 -S 131072 -o1,0 $dom_file ||
17256                 error "setstripe on $dom_file"
17257
17258         local blks=$((128 * 3))
17259         local expected=$(((blks / 3) * 4))
17260
17261         for ((i = 0; i < $blks; i++)); do
17262                 dd if=/dev/zero of=$dom_file count=1 bs=4k seek=$((2 * i)) \
17263                         conv=notrunc > /dev/null 2>&1 ||
17264                         error "dd failed to $dom_file"
17265         done
17266
17267         filefrag -ves $dom_file | (head -7; echo ; tail -5)
17268         (( ! ${PIPESTATUS[0]} )) || error "filefrag $dom_file failed"
17269
17270         filefrag_op=$(filefrag -ve -k $dom_file |
17271                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
17272
17273         local last_lun=$(echo $filefrag_op | cut -d: -f5)
17274         local lun_len=0
17275         local num_luns=1
17276
17277         while IFS=$'\n' read line; do
17278                 local frag_lun=$(echo $line | cut -d: -f5)
17279                 local ext_len=$(echo $line | cut -d: -f4)
17280
17281                 if (( $frag_lun != $last_lun )); then
17282                         if (( lun_len != expected )); then
17283                                 error "dev #$last_lun: $lun_len != $expected"
17284                         else
17285                                 (( num_luns += 1 ))
17286                                 lun_len=0
17287                         fi
17288                 fi
17289                 (( lun_len += ext_len ))
17290                 last_lun=$frag_lun
17291         done <<< "$filefrag_op"
17292
17293         if (( num_luns != 3 )); then
17294                 error "num devices: $num_luns, but 3 expected"
17295         fi
17296         if (( lun_len != expected )); then
17297                 error "dev #$last_lun: $lun_len != $expected"
17298         fi
17299         echo "FIEMAP on DoM file succeeded"
17300 }
17301 run_test 130i "FIEMAP (DoM file)"
17302
17303 # Test for writev/readv
17304 test_131a() {
17305         rwv -f $DIR/$tfile -w -n 3 524288 1048576 1572864 ||
17306                 error "writev test failed"
17307         rwv -f $DIR/$tfile -r -v -n 2 1572864 1048576 ||
17308                 error "readv failed"
17309         rm -f $DIR/$tfile
17310 }
17311 run_test 131a "test iov's crossing stripe boundary for writev/readv"
17312
17313 test_131b() {
17314         local fsize=$((524288 + 1048576 + 1572864))
17315         rwv -f $DIR/$tfile -w -a -n 3 524288 1048576 1572864 &&
17316                 $CHECKSTAT -t file $DIR/$tfile -s $fsize ||
17317                         error "append writev test failed"
17318
17319         ((fsize += 1572864 + 1048576))
17320         rwv -f $DIR/$tfile -w -a -n 2 1572864 1048576 &&
17321                 $CHECKSTAT -t file $DIR/$tfile -s $fsize ||
17322                         error "append writev test failed"
17323         rm -f $DIR/$tfile
17324 }
17325 run_test 131b "test append writev"
17326
17327 test_131c() {
17328         rwv -f $DIR/$tfile -w -d -n 1 1048576 || return 0
17329         error "NOT PASS"
17330 }
17331 run_test 131c "test read/write on file w/o objects"
17332
17333 test_131d() {
17334         rwv -f $DIR/$tfile -w -n 1 1572864
17335         NOB=`rwv -f $DIR/$tfile -r -n 3 524288 524288 1048576 | awk '/error/ {print $6}'`
17336         if [ "$NOB" != 1572864 ]; then
17337                 error "Short read filed: read $NOB bytes instead of 1572864"
17338         fi
17339         rm -f $DIR/$tfile
17340 }
17341 run_test 131d "test short read"
17342
17343 test_131e() {
17344         rwv -f $DIR/$tfile -w -s 1048576 -n 1 1048576
17345         rwv -f $DIR/$tfile -r -z -s 0 -n 1 524288 || \
17346         error "read hitting hole failed"
17347         rm -f $DIR/$tfile
17348 }
17349 run_test 131e "test read hitting hole"
17350
17351 check_stats() {
17352         local facet=$1
17353         local op=$2
17354         local want=${3:-0}
17355         local res
17356
17357         # open             11 samples [usecs] 468 4793 13658 35791898
17358         case $facet in
17359         mds*) res=($(do_facet $facet \
17360                    $LCTL get_param mdt.$FSNAME-MDT0000.md_stats | grep "$op"))
17361                  ;;
17362         ost*) res=($(do_facet $facet \
17363                   $LCTL get_param obdfilter.$FSNAME-OST0000.stats | grep "$op"))
17364                  ;;
17365         *) error "Wrong facet '$facet'" ;;
17366         esac
17367         [[ -n "$res" ]] || error "counter for $op on $facet not incremented"
17368         # if $want is zero, it means any stat increment is ok.
17369         if (( $want > 0 )); then
17370                 local count=${res[1]}
17371
17372                 if (( $count != $want )); then
17373                         if [[ $facet =~ "mds" ]]; then
17374                                 do_nodes $(comma_list $(mdts_nodes)) \
17375                                         $LCTL get_param mdt.*.md_stats
17376                         else
17377                                 do_nodes $(osts_nodes) \
17378                                         $LCTL get_param obdfilter.*.stats
17379                         fi
17380                         error "The $op counter on $facet is $count, not $want"
17381                 fi
17382         fi
17383 }
17384
17385 test_133a() {
17386         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17387         remote_ost_nodsh && skip "remote OST with nodsh"
17388         remote_mds_nodsh && skip "remote MDS with nodsh"
17389         do_facet $SINGLEMDS $LCTL list_param mdt.*.rename_stats ||
17390                 skip_env "MDS doesn't support rename stats"
17391
17392         local testdir=$DIR/${tdir}/stats_testdir
17393
17394         mkdir_on_mdt0 $DIR/${tdir}
17395
17396         # clear stats.
17397         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17398         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
17399
17400         # verify mdt stats first.
17401         mkdir_on_mdt0 ${testdir} || error "mkdir_on_mdt0 failed"
17402         check_stats $SINGLEMDS "mkdir" 1
17403
17404         # clear "open" from "lfs mkdir" above
17405         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17406         touch ${testdir}/${tfile} || error "touch failed"
17407         check_stats $SINGLEMDS "open" 1
17408         check_stats $SINGLEMDS "close" 1
17409         (( $MDS1_VERSION >= $(version_code 2.15.62) )) && {
17410                 # open should match close
17411                 ls -lR ${testdir}
17412                 check_stats $SINGLEMDS "open" 2
17413                 check_stats $SINGLEMDS "close" 2
17414         }
17415         [ $MDS1_VERSION -ge $(version_code 2.8.54) ] && {
17416                 mknod ${testdir}/${tfile}-pipe p || error "mknod failed"
17417                 check_stats $SINGLEMDS "mknod" 2
17418         }
17419         rm -f ${testdir}/${tfile}-pipe || error "pipe remove failed"
17420         check_stats $SINGLEMDS "unlink" 1
17421         rm -f ${testdir}/${tfile} || error "file remove failed"
17422         check_stats $SINGLEMDS "unlink" 2
17423
17424         # remove working dir and check mdt stats again.
17425         rmdir ${testdir} || error "rmdir failed"
17426         check_stats $SINGLEMDS "rmdir" 1
17427
17428         local testdir1=$DIR/${tdir}/stats_testdir1
17429         mkdir_on_mdt0 ${testdir}
17430         mkdir_on_mdt0 ${testdir1}
17431         touch ${testdir1}/test1
17432         mv ${testdir1}/test1 ${testdir} || error "file crossdir rename"
17433         check_stats $SINGLEMDS "crossdir_rename" 1
17434
17435         mv ${testdir}/test1 ${testdir}/test0 || error "file samedir rename"
17436         check_stats $SINGLEMDS "samedir_rename" 1
17437
17438         rm -rf $DIR/${tdir}
17439 }
17440 run_test 133a "Verifying MDT stats ========================================"
17441
17442 test_133b() {
17443         local res
17444
17445         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17446         remote_ost_nodsh && skip "remote OST with nodsh"
17447         remote_mds_nodsh && skip "remote MDS with nodsh"
17448
17449         local testdir=$DIR/${tdir}/stats_testdir
17450
17451         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
17452         mkdir_on_mdt0 ${testdir} || error "mkdir_on_mdt0 failed"
17453         touch ${testdir}/${tfile} || error "touch failed"
17454         cancel_lru_locks mdc
17455
17456         # clear stats.
17457         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17458         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
17459
17460         # extra mdt stats verification.
17461         chmod 444 ${testdir}/${tfile} || error "chmod failed"
17462         check_stats $SINGLEMDS "setattr" 1
17463         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17464         if [ $MDS1_VERSION -ne $(version_code 2.2.0) ]
17465         then            # LU-1740
17466                 ls -l ${testdir}/${tfile} > /dev/null|| error "ls failed"
17467                 check_stats $SINGLEMDS "getattr" 1
17468         fi
17469         rm -rf $DIR/${tdir}
17470
17471         # when DNE is enabled, MDT uses STATFS RPC to ping other targets
17472         # so the check below is not reliable
17473         [ $MDSCOUNT -eq 1 ] || return 0
17474
17475         # Sleep to avoid a cached response.
17476         #define OBD_STATFS_CACHE_SECONDS 1
17477         sleep 2
17478         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17479         do_facet ost1 $LCTL set_param obdfilter.*.exports.*.stats=clear
17480         $LFS df || error "lfs failed"
17481         check_stats $SINGLEMDS "statfs" 1
17482
17483         # check aggregated statfs (LU-10018)
17484         [ $MDS1_VERSION -lt $(version_code 2.11.54) ] &&
17485                 return 0
17486         [ $CLIENT_VERSION -lt $(version_code 2.11.54) ] &&
17487                 return 0
17488         sleep 2
17489         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17490         do_facet ost1 $LCTL set_param obdfilter.*.exports.*.stats=clear
17491         df $DIR
17492         check_stats $SINGLEMDS "statfs" 1
17493
17494         # We want to check that the client didn't send OST_STATFS to
17495         # ost1 but the MDT also uses OST_STATFS for precreate. So some
17496         # extra care is needed here.
17497         if remote_mds; then
17498                 local nid=$($LCTL list_nids | head -1 | sed  "s/\./\\\./g")
17499                 local param="obdfilter.$FSNAME-OST0000.exports.'$nid'.stats"
17500
17501                 res=$(do_facet ost1 $LCTL get_param $param | grep statfs)
17502                 [ "$res" ] && error "OST got STATFS"
17503         fi
17504
17505         return 0
17506 }
17507 run_test 133b "Verifying extra MDT stats =================================="
17508
17509 test_133c() {
17510         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17511         remote_ost_nodsh && skip "remote OST with nodsh"
17512         remote_mds_nodsh && skip "remote MDS with nodsh"
17513
17514         local testdir=$DIR/$tdir/stats_testdir
17515
17516         test_mkdir -p $testdir
17517
17518         # verify obdfilter stats.
17519         $LFS setstripe -c 1 -i 0 $testdir/$tfile
17520         sync
17521         cancel_lru_locks osc
17522         wait_delete_completed
17523
17524         # clear stats.
17525         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
17526         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
17527
17528         dd if=/dev/zero of=$testdir/$tfile conv=notrunc bs=512k count=1 ||
17529                 error "dd failed"
17530         sync
17531         cancel_lru_locks osc
17532         check_stats ost1 "write" 1
17533
17534         dd if=$testdir/$tfile of=/dev/null bs=1k count=1 || error "dd failed"
17535         check_stats ost1 "read" 1
17536
17537         > $testdir/$tfile || error "truncate failed"
17538         check_stats ost1 "punch" 1
17539
17540         rm -f $testdir/$tfile || error "file remove failed"
17541         wait_delete_completed
17542         check_stats ost1 "destroy" 1
17543
17544         rm -rf $DIR/$tdir
17545 }
17546 run_test 133c "Verifying OST stats ========================================"
17547
17548 order_2() {
17549         local value=$1
17550         local orig=$value
17551         local order=1
17552
17553         while [ $value -ge 2 ]; do
17554                 order=$((order*2))
17555                 value=$((value/2))
17556         done
17557
17558         if [ $orig -gt $order ]; then
17559                 order=$((order*2))
17560         fi
17561         echo $order
17562 }
17563
17564 size_in_KMGT() {
17565     local value=$1
17566     local size=('K' 'M' 'G' 'T');
17567     local i=0
17568     local size_string=$value
17569
17570     while [ $value -ge 1024 ]; do
17571         if [ $i -gt 3 ]; then
17572             #T is the biggest unit we get here, if that is bigger,
17573             #just return XXXT
17574             size_string=${value}T
17575             break
17576         fi
17577         value=$((value >> 10))
17578         if [ $value -lt 1024 ]; then
17579             size_string=${value}${size[$i]}
17580             break
17581         fi
17582         i=$((i + 1))
17583     done
17584
17585     echo $size_string
17586 }
17587
17588 get_rename_size() {
17589         local size=$1
17590         local context=${2:-.}
17591         local sample=$(do_facet $SINGLEMDS $LCTL \
17592                 get_param mdt.$FSNAME-MDT0000.rename_stats |
17593                 grep -A1 $context |
17594                 awk '/ '${size}'/ {print $4}' | sed -e "s/,//g")
17595         echo $sample
17596 }
17597
17598 test_133d() {
17599         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17600         remote_ost_nodsh && skip "remote OST with nodsh"
17601         remote_mds_nodsh && skip "remote MDS with nodsh"
17602         do_facet $SINGLEMDS $LCTL list_param mdt.*.rename_stats ||
17603                 skip_env "MDS doesn't support rename stats"
17604
17605         local testdir1=$DIR/${tdir}/stats_testdir1
17606         local testdir2=$DIR/${tdir}/stats_testdir2
17607         mkdir -p $DIR/${tdir} || error "mkdir $tdir failed"
17608
17609         do_facet $SINGLEMDS $LCTL set_param mdt.*.rename_stats=clear
17610
17611         mkdir_on_mdt0 ${testdir1} || error "mkdir $testdir1 failed"
17612         mkdir_on_mdt0 ${testdir2} || error "mkdir $testdir2 failed"
17613
17614         createmany -o $testdir1/test 512 || error "createmany failed"
17615
17616         # check samedir rename size
17617         mv ${testdir1}/test0 ${testdir1}/test_0
17618
17619         local testdir1_size=$(ls -l $DIR/${tdir} |
17620                 awk '/stats_testdir1/ {print $5}')
17621         local testdir2_size=$(ls -l $DIR/${tdir} |
17622                 awk '/stats_testdir2/ {print $5}')
17623
17624         testdir1_size=$(order_2 $testdir1_size)
17625         testdir2_size=$(order_2 $testdir2_size)
17626
17627         testdir1_size=$(size_in_KMGT $testdir1_size)
17628         testdir2_size=$(size_in_KMGT $testdir2_size)
17629
17630         echo "source rename dir size: ${testdir1_size}"
17631         echo "target rename dir size: ${testdir2_size}"
17632
17633         local cmd="do_facet $SINGLEMDS $LCTL "
17634         cmd+="get_param mdt.$FSNAME-MDT0000.rename_stats"
17635
17636         eval $cmd || error "$cmd failed"
17637         local samedir=$($cmd | grep 'same_dir')
17638         local same_sample=$(get_rename_size $testdir1_size)
17639         [ -z "$samedir" ] && error "samedir_rename_size count error"
17640         [[ $same_sample -eq 1 ]] ||
17641                 error "samedir_rename_size error $same_sample"
17642         echo "Check same dir rename stats success"
17643
17644         do_facet $SINGLEMDS $LCTL set_param mdt.*.rename_stats=clear
17645
17646         # check crossdir rename size
17647         mv ${testdir1}/test_0 ${testdir2}/test_0
17648
17649         testdir1_size=$(ls -l $DIR/${tdir} |
17650                 awk '/stats_testdir1/ {print $5}')
17651         testdir2_size=$(ls -l $DIR/${tdir} |
17652                 awk '/stats_testdir2/ {print $5}')
17653
17654         testdir1_size=$(order_2 $testdir1_size)
17655         testdir2_size=$(order_2 $testdir2_size)
17656
17657         testdir1_size=$(size_in_KMGT $testdir1_size)
17658         testdir2_size=$(size_in_KMGT $testdir2_size)
17659
17660         echo "source rename dir size: ${testdir1_size}"
17661         echo "target rename dir size: ${testdir2_size}"
17662
17663         eval $cmd || error "$cmd failed"
17664         local crossdir=$($cmd | grep 'crossdir')
17665         local src_sample=$(get_rename_size $testdir1_size crossdir_src)
17666         local tgt_sample=$(get_rename_size $testdir2_size crossdir_tgt)
17667         [ -z "$crossdir" ] && error "crossdir_rename_size count error"
17668         [[ $src_sample -eq 1 ]] ||
17669                 error "crossdir_rename_size error $src_sample"
17670         [[ $tgt_sample -eq 1 ]] ||
17671                 error "crossdir_rename_size error $tgt_sample"
17672         echo "Check cross dir rename stats success"
17673         rm -rf $DIR/${tdir}
17674 }
17675 run_test 133d "Verifying rename_stats ========================================"
17676
17677 test_133e() {
17678         remote_mds_nodsh && skip "remote MDS with nodsh"
17679         remote_ost_nodsh && skip "remote OST with nodsh"
17680         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17681
17682         local testdir=$DIR/${tdir}/stats_testdir
17683         local ctr f0 f1 bs=32768 count=42 sum
17684
17685         mkdir -p ${testdir} || error "mkdir failed"
17686
17687         $LFS setstripe -c 1 -i 0 ${testdir}/${tfile}
17688
17689         for ctr in {write,read}_bytes; do
17690                 sync
17691                 cancel_lru_locks osc
17692
17693                 do_facet ost1 $LCTL set_param -n \
17694                         "obdfilter.*.exports.clear=clear"
17695
17696                 if [ $ctr = write_bytes ]; then
17697                         f0=/dev/zero
17698                         f1=${testdir}/${tfile}
17699                 else
17700                         f0=${testdir}/${tfile}
17701                         f1=/dev/null
17702                 fi
17703
17704                 dd if=$f0 of=$f1 conv=notrunc bs=$bs count=$count || \
17705                         error "dd failed"
17706                 sync
17707                 cancel_lru_locks osc
17708
17709                 sum=$(do_facet ost1 $LCTL get_param \
17710                         "obdfilter.*.exports.*.stats" |
17711                         awk -v ctr=$ctr 'BEGIN { sum = 0 }
17712                                 $1 == ctr { sum += $7 }
17713                                 END { printf("%0.0f", sum) }')
17714
17715                 if ((sum != bs * count)); then
17716                         error "Bad $ctr sum, expected $((bs * count)), got $sum"
17717                 fi
17718         done
17719
17720         rm -rf $DIR/${tdir}
17721 }
17722 run_test 133e "Verifying OST {read,write}_bytes nid stats ================="
17723
17724 test_133f() {
17725         [[ $(lustre_version_code $facet) -ge $(version_code 2.7.65) ]] ||
17726                 skip "too old lustre for get_param -R ($facet_ver)"
17727
17728         # verifying readability.
17729         $LCTL get_param -R '*' &> /dev/null
17730
17731         # Verifing writability with badarea_io.
17732         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
17733         local skipped_params='force_lbug|changelog_mask|daemon_file'
17734         $LCTL list_param -FR '*' | grep '=' | tr -d = |
17735                 egrep -v "$skipped_params" |
17736                 xargs -n 1 find $proc_dirs -name |
17737                 xargs -n 1 badarea_io ||
17738                 error "client badarea_io failed"
17739
17740         # remount the FS in case writes/reads /proc break the FS
17741         cleanup || error "failed to unmount"
17742         setup || error "failed to setup"
17743 }
17744 run_test 133f "Check reads/writes of client lustre proc files with bad area io"
17745
17746 test_133g() {
17747         remote_mds_nodsh && skip "remote MDS with nodsh"
17748         remote_ost_nodsh && skip "remote OST with nodsh"
17749
17750         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
17751         local proc_dirs_str=$(eval echo $proc_dirs)
17752         local skipped_params="'force_lbug|daemon_file'"
17753         local facet
17754         for facet in mds1 ost1; do
17755                 local facet_ver=$(lustre_version_code $facet)
17756                 if [ $facet_ver -ge $(version_code 2.7.65) ]; then
17757                         do_facet $facet "$LCTL get_param -R '*'" &> /dev/null
17758                 else
17759                         log "$facet: too old lustre for get_param -R"
17760                 fi
17761                 if [ $facet_ver -ge $(version_code 2.5.54) ]; then
17762                         do_facet $facet "$LCTL list_param -FR '*' | grep '=' |
17763                                 tr -d = | egrep -v $skipped_params |
17764                                 xargs -n 1 find $proc_dirs_str -name |
17765                                 xargs -n 1 badarea_io" ||
17766                                         error "$facet badarea_io failed"
17767                 else
17768                         skip_noexit "$facet: too old lustre for get_param -R"
17769                 fi
17770         done
17771
17772         # remount the FS in case writes/reads /proc break the FS
17773         cleanup || error "failed to unmount"
17774         setup || error "failed to setup"
17775 }
17776 run_test 133g "Check reads/writes of server lustre proc files with bad area io"
17777
17778 test_133h() {
17779         remote_mds_nodsh && skip "remote MDS with nodsh"
17780         remote_ost_nodsh && skip "remote OST with nodsh"
17781         [[ $MDS1_VERSION -lt $(version_code 2.9.54) ]] &&
17782                 skip "Need MDS version at least 2.9.54"
17783
17784         local facet
17785         for facet in client mds1 ost1; do
17786                 # Get the list of files that are missing the terminating newline
17787                 local plist=$(do_facet $facet
17788                         $LCTL list_param -FR '*' | grep '=' | tr -d =)
17789                 local ent
17790                 for ent in $plist; do
17791                         local missing=$(do_facet $facet $LCTL get_param $ent \|\
17792                                 awk -v FS='\v' -v RS='\v\v' \
17793                                 "'END { if(NR>0 && \\\$NF !~ /.*\\\n\$/) \
17794                                         print FILENAME}'" 2>/dev/null)
17795                         [ -z $missing ] || {
17796                                 do_facet $facet $LCTL get_param $ent | od -An -tx1
17797                                 error "file does not end with newline: $facet-$ent"
17798                         }
17799                 done
17800         done
17801 }
17802 run_test 133h "Proc files should end with newlines"
17803
17804 test_134a() {
17805         remote_mds_nodsh && skip "remote MDS with nodsh"
17806         [[ $MDS1_VERSION -lt $(version_code 2.7.54) ]] &&
17807                 skip "Need MDS version at least 2.7.54"
17808
17809         mkdir_on_mdt0 $DIR/$tdir || error "failed to create $DIR/$tdir"
17810         cancel_lru_locks mdc
17811
17812         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
17813         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
17814         [ $unused -eq 0 ] || error "$unused locks are not cleared"
17815
17816         local nr=1000
17817         createmany -o $DIR/$tdir/f $nr ||
17818                 error "failed to create $nr files in $DIR/$tdir"
17819         unused=$($LCTL get_param -n $nsdir.lock_unused_count)
17820
17821         #define OBD_FAIL_LDLM_WATERMARK_LOW     0x327
17822         do_facet mds1 $LCTL set_param fail_loc=0x327
17823         do_facet mds1 $LCTL set_param fail_val=500
17824         touch $DIR/$tdir/m
17825
17826         echo "sleep 10 seconds ..."
17827         sleep 10
17828         local lck_cnt=$($LCTL get_param -n $nsdir.lock_unused_count)
17829
17830         do_facet mds1 $LCTL set_param fail_loc=0
17831         do_facet mds1 $LCTL set_param fail_val=0
17832         [ $lck_cnt -lt $unused ] ||
17833                 error "No locks reclaimed, before:$unused, after:$lck_cnt"
17834
17835         rm $DIR/$tdir/m
17836         unlinkmany $DIR/$tdir/f $nr
17837 }
17838 run_test 134a "Server reclaims locks when reaching lock_reclaim_threshold"
17839
17840 test_134b() {
17841         remote_mds_nodsh && skip "remote MDS with nodsh"
17842         [[ $MDS1_VERSION -lt $(version_code 2.7.54) ]] &&
17843                 skip "Need MDS version at least 2.7.54"
17844
17845         mkdir_on_mdt0 $DIR/$tdir || error "failed to create $DIR/$tdir"
17846         cancel_lru_locks mdc
17847
17848         local low_wm=$(do_facet mds1 $LCTL get_param -n \
17849                         ldlm.lock_reclaim_threshold_mb)
17850         # disable reclaim temporarily
17851         do_facet mds1 $LCTL set_param ldlm.lock_reclaim_threshold_mb=0
17852
17853         #define OBD_FAIL_LDLM_WATERMARK_HIGH     0x328
17854         do_facet mds1 $LCTL set_param fail_loc=0x328
17855         do_facet mds1 $LCTL set_param fail_val=500
17856
17857         $LCTL set_param debug=+trace
17858
17859         local nr=600
17860         createmany -o $DIR/$tdir/f $nr &
17861         local create_pid=$!
17862
17863         echo "Sleep $TIMEOUT seconds ..."
17864         sleep $TIMEOUT
17865         if ! ps -p $create_pid  > /dev/null 2>&1; then
17866                 do_facet mds1 $LCTL set_param fail_loc=0
17867                 do_facet mds1 $LCTL set_param fail_val=0
17868                 do_facet mds1 $LCTL set_param \
17869                         ldlm.lock_reclaim_threshold_mb=${low_wm}m
17870                 error "createmany finished incorrectly!"
17871         fi
17872         do_facet mds1 $LCTL set_param fail_loc=0
17873         do_facet mds1 $LCTL set_param fail_val=0
17874         do_facet mds1 $LCTL set_param ldlm.lock_reclaim_threshold_mb=${low_wm}m
17875         wait $create_pid || return 1
17876
17877         unlinkmany $DIR/$tdir/f $nr
17878 }
17879 run_test 134b "Server rejects lock request when reaching lock_limit_mb"
17880
17881 test_135() {
17882         remote_mds_nodsh && skip "remote MDS with nodsh"
17883         [[ $MDS1_VERSION -lt $(version_code 2.13.50) ]] &&
17884                 skip "Need MDS version at least 2.13.50"
17885         local fname
17886
17887         mkdir -p $DIR/$tdir || error "failed to create $DIR/$tdir"
17888
17889 #define OBD_FAIL_PLAIN_RECORDS 0x1319
17890         #set only one record at plain llog
17891         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1319 fail_val=1
17892
17893         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
17894
17895         #fill already existed plain llog each 64767
17896         #wrapping whole catalog
17897         createmany -o -u $DIR/$tdir/$tfile- $((64767 * 1))
17898
17899         createmany -o $DIR/$tdir/$tfile_ 64700
17900         for (( i = 0; i < 64700; i = i + 2 ))
17901         do
17902                 rm $DIR/$tdir/$tfile_$i &
17903                 rm $DIR/$tdir/$tfile_$((i + 1)) &
17904                 local pid=$!
17905                 wait $pid
17906         done
17907
17908         #waiting osp synchronization
17909         wait_delete_completed
17910 }
17911 run_test 135 "Race catalog processing"
17912
17913 test_136() {
17914         remote_mds_nodsh && skip "remote MDS with nodsh"
17915         [[ $MDS1_VERSION -lt $(version_code 2.13.50) ]] &&
17916                 skip "Need MDS version at least 2.13.50"
17917         local fname
17918
17919         mkdir -p $DIR/$tdir || error "failed to create $DIR/$tdir"
17920         $LFS setstripe -c 1 -i 0 $DIR/$tdir || error "failed to set striping"
17921         #set only one record at plain llog
17922 #define OBD_FAIL_CATALOG_FULL_CHECK                0x131a
17923         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x131a fail_val=1
17924
17925         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
17926
17927         # fill already existed 2 plain llogs each 64767 wrapping whole catalog,
17928         # drop server memory periodically only on ZFS to avoid OOM during test
17929         local items=1000
17930         for ((created = 0; created < 64767 * 5 / 2; created += items)); do
17931                 echo "$(date +%s): create $created-$((created + items - 1))"
17932                 createmany -o -u $DIR/$tdir/$tfile- $created $items
17933                 if [[ "$mds1_FSTYPE" == "zfs" ]]; then
17934                         wait_delete_completed
17935                         do_facet mds1 "echo 1 > /proc/sys/vm/drop_caches"
17936                 fi
17937         done
17938         [[ "$FSTYPE" == "zfs" ]] || wait_delete_completed
17939
17940         createmany -o $DIR/$tdir/$tfile_ 10
17941         sleep 25
17942
17943         do_facet $SINGLEMDS $LCTL set_param fail_val=3
17944         for (( i = 0; i < 10; i = i + 3 )); do
17945                 rm $DIR/$tdir/$tfile_$i &
17946                 rm $DIR/$tdir/$tfile_$((i + 1)) &
17947                 local pid=$!
17948                 wait $pid
17949                 sleep 7
17950                 rm $DIR/$tdir/$tfile_$((i + 2)) &
17951         done
17952
17953         #waiting osp synchronization
17954         wait_delete_completed
17955 }
17956 run_test 136 "Race catalog processing 2"
17957
17958 test_140() { #bug-17379
17959         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17960
17961         test_mkdir $DIR/$tdir
17962         cd $DIR/$tdir || error "Changing to $DIR/$tdir"
17963         cp $(which stat) . || error "Copying stat to $DIR/$tdir"
17964
17965         # VFS limits max symlink depth to 5(4KSTACK) or 7(8KSTACK) or 8
17966         # For kernel > 3.5, bellow only tests consecutive symlink (MAX 40)
17967         local i=0
17968         while i=$((i + 1)); do
17969                 test_mkdir $i
17970                 cd $i || error "Changing to $i"
17971                 ln -s ../stat stat || error "Creating stat symlink"
17972                 # Read the symlink until ELOOP present,
17973                 # not LBUGing the system is considered success,
17974                 # we didn't overrun the stack.
17975                 $OPENFILE -f O_RDONLY stat >/dev/null 2>&1; ret=$?
17976                 if [ $ret -ne 0 ]; then
17977                         if [ $ret -eq 40 ]; then
17978                                 break  # -ELOOP
17979                         else
17980                                 error "Open stat symlink"
17981                                         return
17982                         fi
17983                 fi
17984         done
17985         i=$((i - 1))
17986         echo "The symlink depth = $i"
17987         [ $i -eq 5 ] || [ $i -eq 7 ] || [ $i -eq 8 ] || [ $i -eq 40 ] ||
17988                 error "Invalid symlink depth"
17989
17990         # Test recursive symlink
17991         ln -s symlink_self symlink_self
17992         $OPENFILE -f O_RDONLY symlink_self >/dev/null 2>&1; ret=$?
17993         echo "open symlink_self returns $ret"
17994         [ $ret -eq 40 ] || error "recursive symlink doesn't return -ELOOP"
17995 }
17996 run_test 140 "Check reasonable stack depth (shouldn't LBUG) ===="
17997
17998 test_150a() {
17999         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18000
18001         local TF="$TMP/$tfile"
18002
18003         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18004         dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
18005         cp $TF $DIR/$tfile
18006         cancel_lru_locks $OSC
18007         cmp $TF $DIR/$tfile || error "$TMP/$tfile $DIR/$tfile differ"
18008         remount_client $MOUNT
18009         df -P $MOUNT
18010         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (remount)"
18011
18012         $TRUNCATE $TF 6000
18013         $TRUNCATE $DIR/$tfile 6000
18014         cancel_lru_locks $OSC
18015         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (truncate1)"
18016
18017         echo "12345" >>$TF
18018         echo "12345" >>$DIR/$tfile
18019         cancel_lru_locks $OSC
18020         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append1)"
18021
18022         echo "12345" >>$TF
18023         echo "12345" >>$DIR/$tfile
18024         cancel_lru_locks $OSC
18025         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append2)"
18026 }
18027 run_test 150a "truncate/append tests"
18028
18029 test_150b() {
18030         check_set_fallocate_or_skip
18031         local out
18032
18033         touch $DIR/$tfile
18034         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18035         out=$(check_fallocate $DIR/$tfile 2>&1) ||
18036                 skip_eopnotsupp "$out|check_fallocate failed"
18037 }
18038 run_test 150b "Verify fallocate (prealloc) functionality"
18039
18040 test_150bb() {
18041         check_set_fallocate_or_skip
18042
18043         touch $DIR/$tfile
18044         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18045         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=20 || error "dd failed"
18046         > $DIR/$tfile
18047         fallocate -l $((1048576 * 20)) $DIR/$tfile || error "fallocate failed"
18048         # precomputed md5sum for 20MB of zeroes
18049         local expect="8f4e33f3dc3e414ff94e5fb6905cba8c"
18050         local sum=($(md5sum $DIR/$tfile))
18051
18052         [[ "${sum[0]}" == "$expect" ]] || error "fallocate unwritten is not zero"
18053
18054         check_set_fallocate 1
18055
18056         > $DIR/$tfile
18057         fallocate -l $((1048576 * 20)) $DIR/$tfile || error "fallocate failed"
18058         sum=($(md5sum $DIR/$tfile))
18059
18060         [[ "${sum[0]}" == "$expect" ]] || error "fallocate zero is not zero"
18061 }
18062 run_test 150bb "Verify fallocate modes both zero space"
18063
18064 test_150c() {
18065         check_set_fallocate_or_skip
18066         local striping="-c2"
18067
18068         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18069         $LFS setstripe -c $OSTCOUNT -S1M $DIR/$tfile || error "setstripe failed"
18070         fallocate -l ${OSTCOUNT}m $DIR/$tfile || error "fallocate failed"
18071         local bytes=$(($(stat -c '%b * %B' $DIR/$tfile)))
18072         local want=$((OSTCOUNT * 1048576))
18073
18074         # Must allocate all requested space, not more than 5% extra
18075         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
18076                 error "bytes $bytes is not $want"
18077
18078         rm -f $DIR/$tfile
18079
18080         echo "verify fallocate on PFL file"
18081
18082         [[ "x$DOM" == "xyes" ]] && striping="-L mdt"
18083
18084         $LFS setstripe -E1M $striping -E16M -c3 -Eeof -c 4 $DIR/$tfile ||
18085                 error "Create $DIR/$tfile failed"
18086         fallocate -l $((1048576 * 512)) $DIR/$tfile || error "fallocate failed"
18087         bytes=$(($(stat -c '%b * %B' $DIR/$tfile)))
18088         want=$((512 * 1048576))
18089
18090         # Must allocate all requested space, not more than 5% extra
18091         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
18092                 error "bytes $bytes is not $want"
18093 }
18094 run_test 150c "Verify fallocate Size and Blocks"
18095
18096 test_150d() {
18097         check_set_fallocate_or_skip
18098         local striping="-c2"
18099
18100         [[ "x$DOM" == "xyes" ]] && striping="-L mdt"
18101
18102         stack_trap "rm -f $DIR/$tdir; wait_delete_completed"
18103         $LFS setstripe -E1M $striping -E eof -c $OSTCOUNT -S1M $DIR/$tdir ||
18104                 error "setstripe failed"
18105         fallocate -o 1G -l ${OSTCOUNT}m $DIR/$tdir || error "fallocate failed"
18106         local bytes=$(($(stat -c '%b * %B' $DIR/$tdir)))
18107         local want=$((OSTCOUNT * 1048576))
18108
18109         # Must allocate all requested space, not more than 5% extra
18110         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
18111                 error "bytes $bytes is not $want"
18112 }
18113 run_test 150d "Verify fallocate Size and Blocks - Non zero start"
18114
18115 test_150e() {
18116         check_set_fallocate_or_skip
18117
18118         echo "df before:"
18119         $LFS df
18120         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18121         $LFS setstripe -c${OSTCOUNT} $DIR/$tfile ||
18122                 error "$LFS setstripe -c${OSTCOUNT} $DIR/$tfile failed"
18123
18124         # Find OST with Minimum Size
18125         min_size_ost=$($LFS df | awk "/$FSNAME-OST/ { print \$4 }" |
18126                        sort -un | head -1)
18127
18128         # Get 100MB per OST of the available space to reduce run time
18129         # else 60% of the available space if we are running SLOW tests
18130         if [ $SLOW == "no" ]; then
18131                 local space=$((1024 * 100 * OSTCOUNT))
18132         else
18133                 local space=$(((min_size_ost * 60)/100 * OSTCOUNT))
18134         fi
18135
18136         fallocate -l${space}k $DIR/$tfile ||
18137                 error "fallocate ${space}k $DIR/$tfile failed"
18138         echo "'fallocate -l ${space}k $DIR/$tfile' succeeded"
18139
18140         # get size immediately after fallocate. This should be correctly
18141         # updated
18142         local size=$(stat -c '%s' $DIR/$tfile)
18143         local used=$(( $(stat -c '%b * %B' $DIR/$tfile) / 1024))
18144
18145         # Sleep for a while for statfs to get updated. And not pull from cache.
18146         sleep 2
18147
18148         echo "df after fallocate:"
18149         $LFS df
18150
18151         (( size / 1024 == space )) || error "size $size != requested $space"
18152         [ "$ost1_FSTYPE" != ldiskfs ] || (( used >= space )) ||
18153                 error "used $used < space $space"
18154
18155         rm $DIR/$tfile || error "rm failed"
18156         sync
18157         wait_delete_completed
18158
18159         echo "df after unlink:"
18160         $LFS df
18161 }
18162 run_test 150e "Verify 60% of available OST space consumed by fallocate"
18163
18164 test_150f() {
18165         local size
18166         local blocks
18167         local want_size_before=20480 # in bytes
18168         local want_blocks_before=40 # 512 sized blocks
18169         local want_blocks_after=24  # 512 sized blocks
18170         local length=$(((want_blocks_before - want_blocks_after) * 512))
18171
18172         [[ $OST1_VERSION -ge $(version_code 2.14.0) ]] ||
18173                 skip "need at least 2.14.0 for fallocate punch"
18174
18175         if [ "$ost1_FSTYPE" = "zfs" ] || [ "$mds1_FSTYPE" = "zfs" ]; then
18176                 skip "LU-14160: punch mode is not implemented on OSD ZFS"
18177         fi
18178
18179         check_set_fallocate_or_skip
18180         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18181
18182         [[ "x$DOM" == "xyes" ]] &&
18183                 $LFS setstripe -E1M -L mdt -E eof $DIR/$tfile
18184
18185         echo "Verify fallocate punch: Range within the file range"
18186         yes 'A' | dd of=$DIR/$tfile bs=4096 count=5 ||
18187                 error "dd failed for bs 4096 and count 5"
18188
18189         # Call fallocate with punch range which is within the file range
18190         out=$(fallocate -p --offset 4096 -l $length $DIR/$tfile 2>&1) ||
18191                 skip_eopnotsupp "$out|fallocate: offset 4096 and length $length"
18192         # client must see changes immediately after fallocate
18193         size=$(stat -c '%s' $DIR/$tfile)
18194         blocks=$(stat -c '%b' $DIR/$tfile)
18195
18196         # Verify punch worked.
18197         (( blocks == want_blocks_after )) ||
18198                 error "punch failed: blocks $blocks != $want_blocks_after"
18199
18200         (( size == want_size_before )) ||
18201                 error "punch failed: size $size != $want_size_before"
18202
18203         # Verify there is hole in file
18204         local data_off=$(lseek_test -d 4096 $DIR/$tfile)
18205         # precomputed md5sum
18206         local expect="4a9a834a2db02452929c0a348273b4aa"
18207
18208         cksum=($(md5sum $DIR/$tfile))
18209         [[ "${cksum[0]}" == "$expect" ]] ||
18210                 error "unexpected MD5SUM after punch: ${cksum[0]}"
18211
18212         # Start second sub-case for fallocate punch.
18213         echo "Verify fallocate punch: Range overlapping and less than blocksize"
18214         yes 'A' | dd of=$DIR/$tfile bs=4096 count=5 ||
18215                 error "dd failed for bs 4096 and count 5"
18216
18217         # Punch range less than block size will have no change in block count
18218         want_blocks_after=40  # 512 sized blocks
18219
18220         # Punch overlaps two blocks and less than blocksize
18221         out=$(fallocate -p --offset 4000 -l 3000 $DIR/$tfile 2>&1) ||
18222                 skip_eopnotsupp "$out|fallocate: offset 4000 length 3000"
18223         size=$(stat -c '%s' $DIR/$tfile)
18224         blocks=$(stat -c '%b' $DIR/$tfile)
18225
18226         # Verify punch worked.
18227         (( blocks == want_blocks_after )) ||
18228                 error "punch failed: blocks $blocks != $want_blocks_after"
18229
18230         (( size == want_size_before )) ||
18231                 error "punch failed: size $size != $want_size_before"
18232
18233         # Verify if range is really zero'ed out. We expect Zeros.
18234         # precomputed md5sum
18235         expect="c57ec5d769c3dbe3426edc3f7d7e11d3"
18236         cksum=($(md5sum $DIR/$tfile))
18237         [[ "${cksum[0]}" == "$expect" ]] ||
18238                 error "unexpected MD5SUM after punch: ${cksum[0]}"
18239 }
18240 run_test 150f "Verify fallocate punch functionality"
18241
18242 test_150g() {
18243         local space
18244         local size
18245         local blocks
18246         local blocks_after
18247         local size_after
18248         local BS=4096 # Block size in bytes
18249
18250         [[ $OST1_VERSION -ge $(version_code 2.14.0) ]] ||
18251                 skip "need at least 2.14.0 for fallocate punch"
18252
18253         if [ "$ost1_FSTYPE" = "zfs" ] || [ "$mds1_FSTYPE" = "zfs" ]; then
18254                 skip "LU-14160: punch mode is not implemented on OSD ZFS"
18255         fi
18256
18257         check_set_fallocate_or_skip
18258         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18259
18260         if [[ "x$DOM" == "xyes" ]]; then
18261                 $LFS setstripe -E2M -L mdt -E eof -c${OSTCOUNT} $DIR/$tfile ||
18262                         error "$LFS setstripe DoM + ${OSTCOUNT} OST failed"
18263         else
18264                 $LFS setstripe -c${OSTCOUNT} $DIR/$tfile ||
18265                         error "$LFS setstripe -c${OSTCOUNT} $DIR/$tfile failed"
18266         fi
18267
18268         # Get 100MB per OST of the available space to reduce run time
18269         # else 60% of the available space if we are running SLOW tests
18270         if [ $SLOW == "no" ]; then
18271                 space=$((1024 * 100 * OSTCOUNT))
18272         else
18273                 # Find OST with Minimum Size
18274                 space=$($LFS df | awk "/$FSNAME-OST/ { print \$4 }" |
18275                         sort -un | head -1)
18276                 echo "min size OST: $space"
18277                 space=$(((space * 60)/100 * OSTCOUNT))
18278         fi
18279         # space in 1k units, round to 4k blocks
18280         local blkcount=$((space * 1024 / $BS))
18281
18282         echo "Verify fallocate punch: Very large Range"
18283         fallocate -l${space}k $DIR/$tfile ||
18284                 error "fallocate ${space}k $DIR/$tfile failed"
18285         # write 1M at the end, start and in the middle
18286         yes 'A' | dd of=$DIR/$tfile bs=$BS count=256 ||
18287                 error "dd failed: bs $BS count 256"
18288         yes 'A' | dd of=$DIR/$tfile bs=$BS seek=$((blkcount - 256)) count=256 ||
18289                 error "dd failed: bs $BS count 256 seek $((blkcount - 256))"
18290         yes 'A' | dd of=$DIR/$tfile bs=$BS seek=$((blkcount / 2)) count=1024 ||
18291                 error "dd failed: bs $BS count 256 seek $((blkcount / 2))"
18292
18293         # Gather stats.
18294         size=$(stat -c '%s' $DIR/$tfile)
18295
18296         # gather punch length.
18297         local punch_size=$((size - (BS * 2)))
18298
18299         echo "punch_size = $punch_size"
18300         echo "size - punch_size: $((size - punch_size))"
18301         echo "size - punch_size in blocks: $(((size - punch_size)/BS))"
18302
18303         # Call fallocate to punch all except 2 blocks. We leave the
18304         # first and the last block
18305         echo "fallocate -p --offset $BS -l $punch_size $DIR/$tfile"
18306         out=$(fallocate -p --offset $BS -l $punch_size $DIR/$tfile 2>&1) ||
18307                 skip_eopnotsupp "$out|fallocate: offset $BS length $punch_size"
18308
18309         size_after=$(stat -c '%s' $DIR/$tfile)
18310         blocks_after=$(stat -c '%b' $DIR/$tfile)
18311
18312         # Verify punch worked.
18313         # Size should be kept
18314         (( size == size_after )) ||
18315                 error "punch failed: size $size != $size_after"
18316
18317         # two 4k data blocks to remain plus possible 1 extra extent block
18318         (( blocks_after <= ((BS / 512) * 3) )) ||
18319                 error "too many blocks remains: $blocks_after"
18320
18321         # Verify that file has hole between the first and the last blocks
18322         local hole_start=$(lseek_test -l 0 $DIR/$tfile)
18323         local hole_end=$(lseek_test -d $BS $DIR/$tfile)
18324
18325         echo "Hole at [$hole_start, $hole_end)"
18326         (( hole_start == BS )) ||
18327                 error "no hole at offset $BS after punch"
18328
18329         (( hole_end == BS + punch_size )) ||
18330                 error "data at offset $hole_end < $((BS + punch_size))"
18331 }
18332 run_test 150g "Verify fallocate punch on large range"
18333
18334 test_150h() {
18335         local file=$DIR/$tfile
18336         local size
18337
18338         check_set_fallocate_or_skip
18339         statx_supported || skip_env "Test must be statx() syscall supported"
18340
18341         # fallocate() does not update the size information on the MDT
18342         fallocate -l 16K $file || error "failed to fallocate $file"
18343         cancel_lru_locks $OSC
18344         # STATX with cached-always mode will not send glimpse RPCs to OST,
18345         # it uses the caching attrs on the client side as much as possible.
18346         size=$($STATX --cached=always -c %s $file)
18347         [ $size == 16384 ] ||
18348                 error "size after fallocate() is $size, expected 16384"
18349 }
18350 run_test 150h "Verify extend fallocate updates the file size"
18351
18352 test_150ia() {
18353         (( $MDS1_VERSION >= $(version_code 2.16.50) )) ||
18354                 skip "need MDS1 version >= 2.16.50 for falloc zero-range"
18355
18356         if [[ "$ost1_FSTYPE" = "zfs" || "$mds1_FSTYPE" = "zfs" ]]; then
18357                 skip "zero-range mode is not implemented on OSD ZFS"
18358         fi
18359
18360         check_set_fallocate_or_skip
18361         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18362
18363         [[ "$DOM" == "yes" ]] &&
18364                 $LFS setstripe -E1M -L mdt -E eof $DIR/$tfile
18365
18366         echo "Verify fallocate(zero): range within the file"
18367         yes 'A' | dd of=$DIR/$tfile bs=$PAGE_SIZE count=8 ||
18368                 error "dd failed for bs $PAGE_SIZE and count 8"
18369
18370         # zero range page aligned
18371         local offset=$((2 * PAGE_SIZE))
18372         local length=$((4 * PAGE_SIZE))
18373         out=$(fallocate -z --offset $offset -l $length $DIR/$tfile 2>&1) ||
18374                 skip_eopnotsupp "$out|falloc(zero): off $offset, len $length"
18375
18376         # precomputed md5sum
18377         local expect="f6b2adb9a352ee2b9d1f54a629e7998c"
18378         cksum=($(md5sum $DIR/$tfile))
18379         [[ "${cksum[0]}" == "$expect" ]] ||
18380                 error "unexpected MD5SUM after zero: ${cksum[0]}"
18381
18382         # zero range partial page
18383         local offset=2000
18384         local length=1000
18385         out=$(fallocate -z --offset $offset -l $length $DIR/$tfile 2>&1) ||
18386                 skip_eopnotsupp "$out|falloc(zero): off $offset, len $length"
18387
18388         expect="19912462c2a304a225df656b80844ba5"
18389         cksum=($(md5sum $DIR/$tfile))
18390         [[ "${cksum[0]}" == "$expect" ]] ||
18391                 error "unexpected MD5SUM after zero(partial): ${cksum[0]}"
18392 }
18393 run_test 150ia "Verify fallocate zero-range ZERO functionality"
18394
18395 test_150ib() {
18396         (( $MDS1_VERSION >= $(version_code 2.16.50) )) ||
18397                 skip "need MDS1 version >= 2.16.50 for falloc zero-range"
18398
18399         if [[ "$ost1_FSTYPE" = "zfs" || "$mds1_FSTYPE" = "zfs" ]]; then
18400                 skip "zero-range mode is not implemented on OSD ZFS"
18401         fi
18402
18403         check_set_fallocate_or_skip
18404         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18405
18406         [[ "$DOM" == "yes" ]] &&
18407                 $LFS setstripe -E1M -L mdt -E eof $DIR/$tfile
18408
18409         local blocks_after_punch=$((4 * PAGE_SIZE / 512))
18410         local blocks_after_zero_fill=$((8 * PAGE_SIZE / 512))
18411         local blocks_after_extend_ext=$((16 * PAGE_SIZE / 512))
18412         local blocks_after_extend_ind=$((16 * PAGE_SIZE / 512 + 8))
18413         local expect_len=$((8 * PAGE_SIZE))
18414
18415         # file size [0, 32K)
18416         echo "Verify fallocate(zero): range within the file"
18417         yes 'A' | dd of=$DIR/$tfile bs=$PAGE_SIZE count=8 ||
18418                 error "dd failed for bs $PAGE_SIZE and count 8"
18419
18420         # punch across [8K,24K)
18421         local offset=$((2 * PAGE_SIZE))
18422         local length=$((4 * PAGE_SIZE))
18423         out=$(fallocate -p --offset $offset -l $length $DIR/$tfile 2>&1) ||
18424                 skip_eopnotsupp "$out|falloc(zero): off $offset, len $length"
18425
18426         # Verify punch worked as expected
18427         blocks=$(stat -c '%b' $DIR/$tfile)
18428         (( blocks == blocks_after_punch )) ||
18429                 error "punch failed:$blocks!=$blocks_after_punch"
18430
18431         # zero prealloc fill the hole just punched
18432         out=$(fallocate -z --offset $offset -l $length $DIR/$tfile 2>&1) ||
18433                 skip_eopnotsupp "$out|falloc(zero): off $offset, len $length"
18434
18435         # Verify zero prealloc worked.
18436         blocks=$(stat -c '%b' $DIR/$tfile)
18437         (( blocks == blocks_after_zero_fill )) ||
18438                 error "zero prealloc failed:$blocks!=$blocks_after_zero_fill"
18439
18440         # zero prealloc with KEEP_SIZE on
18441         offset=$((8 * PAGE_SIZE))
18442         length=$((8 * PAGE_SIZE))
18443         out=$(fallocate -z -n --offset $offset -l $length $DIR/$tfile 2>&1) ||
18444                 skip_eopnotsupp "$out|falloc(zero): off $offset, len $length"
18445         # block allocate, size remains
18446         blocks=$(stat -c '%b' $DIR/$tfile)
18447         if [[ "$DOM" == "yes" ]]; then
18448                 (( blocks == blocks_after_extend_ind )) ||
18449                         error "extend failed:$blocks!=$blocks_after_extend_ind"
18450         else
18451                 (( blocks == blocks_after_extend_ext )) ||
18452                         error "extend failed:$blocks!=$blocks_after_extend_ext"
18453         fi
18454         lsz=$(stat -c '%s' $DIR/$tfile)
18455         (( lsz == expect_len)) ||
18456                 error "zero extend failed(len):$lsz!=$expect_len"
18457 }
18458 run_test 150ib "Verify fallocate zero-range PREALLOC functionality"
18459
18460 test_150ic() {
18461         (( $MDS1_VERSION >= $(version_code 2.16.54) )) ||
18462                 skip "need MDS1 version >= 2.16.54 for falloc zero-range"
18463
18464         if [[ "$ost1_FSTYPE" = "zfs" || "$mds1_FSTYPE" = "zfs" ]]; then
18465                 skip "zero-range mode is not implemented on OSD ZFS"
18466         fi
18467
18468         [[ "$DOM" == "yes" ]] ||
18469                 skip "only check on DoM component"
18470         check_set_fallocate_or_skip
18471
18472         # set a larger dom-size for test
18473         local MB1=1048576
18474         local mdtname=${FSNAME}-MDT0000-mdtlov
18475         local dom_limit_saved=$(do_facet mds1 $LCTL get_param -n \
18476                                                 lod.$mdtname.dom_stripesize)
18477         local dom_limit=$((256 * MB1))
18478         do_facet mds1 $LCTL set_param -n \
18479                 lod.$mdtname.dom_stripesize=$dom_limit
18480         stack_trap "do_facet mds1 $LCTL set_param -n \
18481                 lod.$mdtname.dom_stripesize=$dom_limit_saved"
18482         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
18483
18484         echo "Verify fallocate zero-range: range extending the file"
18485         $LFS setstripe -E 256M -L mdt -E eof $DIR/$tfile ||
18486                 error "$LFS setstripe DoM failed"
18487         # now let's extend the range to [0, 128M), to trigger BRWs
18488         local offset=0
18489         local length=$((128 * MB1))
18490         # Given per block 4KB size, per index block could hold
18491         # 1024 block index. 128MB needs data block 32768,
18492         # index block 1(L2) + 32(L1)
18493         local want_blocks=$((128 * MB1 / 512 + 33 * 8))
18494
18495         touch $DIR/$tfile
18496         out=$(fallocate -z --offset $offset -l $length $DIR/$tfile 2>&1) ||
18497                 skip_eopnotsupp "$out|fallocate: offset $offset and len $length"
18498
18499         # Verify zero prealloc worked.
18500         local blocks=$(stat -c '%b' $DIR/$tfile)
18501         (( blocks == want_blocks )) ||
18502                 error "zero prealloc failed:$blocks!=$want_blocks"
18503
18504         local expect="fde9e0818281836e4fc0edfede2b8762"
18505         local cksum=($(md5sum $DIR/$tfile))
18506         [[ "${cksum[0]}" == "$expect" ]] ||
18507                 error "unexpected MD5SUM after fallo(large-zero): ${cksum[0]}"
18508 }
18509 run_test 150ic "Verify fallocate LARGE zero PREALLOC functionality"
18510
18511 #LU-2902 roc_hit was not able to read all values from lproc
18512 function roc_hit_init() {
18513         local osts=${1:-$(osts_nodes)}
18514         local dir=$DIR/$tdir-check
18515         local file=$dir/$tfile
18516         local BEFORE
18517         local AFTER
18518         local idx
18519
18520         test_mkdir $dir
18521         #use setstripe to do a write to every ost
18522         for ((i=0; i < OSTCOUNT; i++)); do
18523                 $LFS setstripe -c 1 -i $i $dir || error "$LFS setstripe $file failed"
18524                 dd if=/dev/urandom of=$file bs=4k count=4 2>&1 > /dev/null
18525                 idx=$(printf %04x $i)
18526                 BEFORE=$(get_osd_param $osts *OST$idx stats |
18527                         awk '$1 == "cache_access" {sum += $7}
18528                                 END { printf("%0.0f", sum) }')
18529
18530                 cancel_lru_locks osc
18531                 cat $file >/dev/null
18532
18533                 AFTER=$(get_osd_param $osts *OST$idx stats |
18534                         awk '$1 == "cache_access" {sum += $7}
18535                                 END { printf("%0.0f", sum) }')
18536
18537                 echo BEFORE:$BEFORE AFTER:$AFTER
18538                 if ! let "AFTER - BEFORE == 4"; then
18539                         rm -rf $dir
18540                         error "roc_hit is not safe to use"
18541                 fi
18542                 rm $file
18543         done
18544
18545         rm -rf $dir
18546 }
18547
18548 function roc_hit() {
18549         local osts=${1:-$(osts_nodes)}
18550
18551         echo $(get_osd_param $osts '' stats |
18552                 awk '$1 == "cache_hit" {sum += $7}
18553                         END { printf("%0.0f", sum) }')
18554 }
18555
18556 function set_cache() {
18557         local osts=$1
18558         local type=$2
18559         local param=$3
18560         local on=1
18561
18562         if [ "$param" == "off" ]; then
18563                 on=0;
18564         fi
18565         set_osd_param $osts '' ${type}_cache_enable $on
18566
18567         cancel_lru_locks osc
18568 }
18569
18570 test_151() {
18571         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18572         remote_ost_nodsh && skip "remote OST with nodsh"
18573         (( CLIENT_VERSION == OST1_VERSION )) ||
18574                 skip "LU-13081: no interop testing for OSS cache"
18575
18576         local CPAGES=3
18577         local osts=$(osts_nodes)
18578
18579         # check whether obdfilter is cache capable at all
18580         if ! get_osd_param $osts '' read_cache_enable >/dev/null; then
18581                 skip "not cache-capable obdfilter"
18582         fi
18583
18584         # check cache is enabled on all obdfilters
18585         if get_osd_param $osts '' read_cache_enable | grep 0; then
18586                 skip "oss cache is disabled"
18587         fi
18588
18589         set_osd_param $osts '' writethrough_cache_enable 1
18590
18591         # check write cache is enabled on all obdfilters
18592         if get_osd_param $osts '' writethrough_cache_enable | grep 0; then
18593                 skip "oss write cache is NOT enabled"
18594         fi
18595
18596         roc_hit_init $osts
18597
18598         #define OBD_FAIL_OBD_NO_LRU  0x609
18599         do_nodes $osts $LCTL set_param fail_loc=0x609
18600
18601         # pages should be in the case right after write
18602         dd if=/dev/urandom of=$DIR/$tfile bs=4k count=$CPAGES ||
18603                 error "dd failed"
18604
18605         local BEFORE=$(roc_hit $osts)
18606         cancel_lru_locks osc
18607         cat $DIR/$tfile >/dev/null
18608         local AFTER=$(roc_hit $osts)
18609
18610         do_nodes $osts $LCTL set_param fail_loc=0
18611
18612         if ! let "AFTER - BEFORE == CPAGES"; then
18613                 error "NOT IN CACHE: before: $BEFORE, after: $AFTER"
18614         fi
18615
18616         cancel_lru_locks osc
18617         # invalidates OST cache
18618         do_nodes $osts "echo 1 > /proc/sys/vm/drop_caches"
18619         set_osd_param $osts '' read_cache_enable 0
18620         cat $DIR/$tfile >/dev/null
18621
18622         # now data shouldn't be found in the cache
18623         BEFORE=$(roc_hit $osts)
18624         cancel_lru_locks osc
18625         cat $DIR/$tfile >/dev/null
18626         AFTER=$(roc_hit $osts)
18627         if let "AFTER - BEFORE != 0"; then
18628                 error "IN CACHE: before: $BEFORE, after: $AFTER"
18629         fi
18630
18631         set_osd_param $osts '' read_cache_enable 1
18632         rm -f $DIR/$tfile
18633 }
18634 run_test 151 "test cache on oss and controls ==============================="
18635
18636 test_152() {
18637         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18638
18639         local TF="$TMP/$tfile"
18640
18641         # simulate ENOMEM during write
18642 #define OBD_FAIL_OST_NOMEM      0x226
18643         lctl set_param fail_loc=0x80000226
18644         dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
18645         cp $TF $DIR/$tfile
18646         sync || error "sync failed"
18647         lctl set_param fail_loc=0
18648
18649         # discard client's cache
18650         cancel_lru_locks osc
18651
18652         # simulate ENOMEM during read
18653         lctl set_param fail_loc=0x80000226
18654         cmp $TF $DIR/$tfile || error "cmp failed"
18655         lctl set_param fail_loc=0
18656
18657         rm -f $TF
18658 }
18659 run_test 152 "test read/write with enomem ============================"
18660
18661 test_153() {
18662         $MULTIOP $DIR/$tfile Ow4096Ycu || error "multiop failed"
18663 }
18664 run_test 153 "test if fdatasync does not crash ======================="
18665
18666 dot_lustre_fid_permission_check() {
18667         local fid=$1
18668         local ffid=$MOUNT/.lustre/fid/$fid
18669         local test_dir=$2
18670
18671         echo "stat fid $fid"
18672         stat $ffid || error "stat $ffid failed."
18673         echo "touch fid $fid"
18674         touch $ffid || error "touch $ffid failed."
18675         echo "write to fid $fid"
18676         cat /etc/hosts > $ffid || error "write $ffid failed."
18677         echo "read fid $fid"
18678         diff /etc/hosts $ffid || error "read $ffid failed."
18679         echo "append write to fid $fid"
18680         cat /etc/hosts >> $ffid || error "append write $ffid failed."
18681         echo "rename fid $fid"
18682         mv $ffid $test_dir/$tfile.1 &&
18683                 error "rename $ffid to $tfile.1 should fail."
18684         touch $test_dir/$tfile.1
18685         mv $test_dir/$tfile.1 $ffid &&
18686                 error "rename $tfile.1 to $ffid should fail."
18687         rm -f $test_dir/$tfile.1
18688         echo "truncate fid $fid"
18689         $TRUNCATE $ffid 777 || error "truncate $ffid failed."
18690         echo "link fid $fid"
18691         ln -f $ffid $test_dir/tfile.lnk || error "link $ffid failed."
18692         if [[ $($LCTL get_param -n mdc.*-mdc-*.connect_flags) =~ acl ]]; then
18693                 id $USER0 || skip_env "missing user $USER0"
18694                 echo "setfacl fid $fid"
18695                 setfacl -R -m u:$USER0:rwx $ffid ||
18696                         error "setfacl $ffid failed"
18697                 echo "getfacl fid $fid"
18698                 getfacl $ffid || error "getfacl $ffid failed."
18699         fi
18700         echo "unlink fid $fid"
18701         unlink $MOUNT/.lustre/fid/$fid && error "unlink $ffid should fail."
18702         echo "mknod fid $fid"
18703         mknod $ffid c 1 3 && error "mknod $ffid should fail."
18704
18705         fid=[0xf00000400:0x1:0x0]
18706         ffid=$MOUNT/.lustre/fid/$fid
18707
18708         echo "stat non-exist fid $fid"
18709         stat $ffid > /dev/null && error "stat non-exist $ffid should fail."
18710         echo "write to non-exist fid $fid"
18711         cat /etc/hosts > $ffid && error "write non-exist $ffid should fail."
18712         echo "link new fid $fid"
18713         ln $test_dir/$tfile $ffid && error "link $ffid should fail."
18714
18715         mkdir -p $test_dir/$tdir
18716         touch $test_dir/$tdir/$tfile
18717         fid=$($LFS path2fid $test_dir/$tdir)
18718         rc=$?
18719         [ $rc -ne 0 ] &&
18720                 error "error: could not get fid for $test_dir/$dir/$tfile."
18721
18722         ffid=$MOUNT/.lustre/fid/$fid
18723
18724         echo "ls $fid"
18725         ls $ffid || error "ls $ffid failed."
18726         echo "touch $fid/$tfile.1"
18727         touch $ffid/$tfile.1 || error "touch $ffid/$tfile.1 failed."
18728
18729         echo "touch $MOUNT/.lustre/fid/$tfile"
18730         touch $MOUNT/.lustre/fid/$tfile && \
18731                 error "touch $MOUNT/.lustre/fid/$tfile should fail."
18732
18733         echo "setxattr to $MOUNT/.lustre/fid"
18734         setfattr -n trusted.name1 -v value1 $MOUNT/.lustre/fid
18735
18736         echo "listxattr for $MOUNT/.lustre/fid"
18737         getfattr -d -m "^trusted" $MOUNT/.lustre/fid
18738
18739         echo "delxattr from $MOUNT/.lustre/fid"
18740         setfattr -x trusted.name1 $MOUNT/.lustre/fid
18741
18742         echo "touch invalid fid: $MOUNT/.lustre/fid/[0x200000400:0x2:0x3]"
18743         touch $MOUNT/.lustre/fid/[0x200000400:0x2:0x3] &&
18744                 error "touch invalid fid should fail."
18745
18746         echo "touch non-normal fid: $MOUNT/.lustre/fid/[0x1:0x2:0x0]"
18747         touch $MOUNT/.lustre/fid/[0x1:0x2:0x0] &&
18748                 error "touch non-normal fid should fail."
18749
18750         echo "rename $tdir to $MOUNT/.lustre/fid"
18751         mrename $test_dir/$tdir $MOUNT/.lustre/fid &&
18752                 error "rename to $MOUNT/.lustre/fid should fail."
18753
18754         if [ $MDS1_VERSION -ge $(version_code 2.3.51) ]
18755         then            # LU-3547
18756                 local old_obf_mode=$(stat --format="%a" $DIR/.lustre/fid)
18757                 local new_obf_mode=777
18758
18759                 echo "change mode of $DIR/.lustre/fid to $new_obf_mode"
18760                 chmod $new_obf_mode $DIR/.lustre/fid ||
18761                         error "chmod $new_obf_mode $DIR/.lustre/fid failed"
18762
18763                 local obf_mode=$(stat --format=%a $DIR/.lustre/fid)
18764                 [ $obf_mode -eq $new_obf_mode ] ||
18765                         error "stat $DIR/.lustre/fid returned wrong mode $obf_mode"
18766
18767                 echo "restore mode of $DIR/.lustre/fid to $old_obf_mode"
18768                 chmod $old_obf_mode $DIR/.lustre/fid ||
18769                         error "chmod $old_obf_mode $DIR/.lustre/fid failed"
18770         fi
18771
18772         $OPENFILE -f O_LOV_DELAY_CREATE:O_CREAT $test_dir/$tfile-2
18773         fid=$($LFS path2fid $test_dir/$tfile-2)
18774
18775         if [ $MDS1_VERSION -ge $(version_code 2.6.50) ]
18776         then # LU-5424
18777                 echo "cp /etc/passwd $MOUNT/.lustre/fid/$fid"
18778                 cp /etc/passwd $MOUNT/.lustre/fid/$fid ||
18779                         error "create lov data thru .lustre failed"
18780         fi
18781         echo "cp /etc/passwd $test_dir/$tfile-2"
18782         cp /etc/passwd $test_dir/$tfile-2 ||
18783                 error "copy to $test_dir/$tfile-2 failed."
18784         echo "diff /etc/passwd $MOUNT/.lustre/fid/$fid"
18785         diff /etc/passwd $MOUNT/.lustre/fid/$fid ||
18786                 error "diff /etc/passwd $MOUNT/.lustre/fid/$fid failed."
18787
18788         rm -rf $test_dir/tfile.lnk
18789         rm -rf $test_dir/$tfile-2
18790 }
18791
18792 test_154A() {
18793         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
18794                 skip "Need MDS version at least 2.4.1"
18795
18796         local tf=$DIR/$tfile
18797         touch $tf
18798
18799         local fid=$($LFS path2fid $tf)
18800         [ -z "$fid" ] && error "path2fid unable to get $tf FID"
18801
18802         # check that we get the same pathname back
18803         local rootpath
18804         local found
18805         for rootpath in "$MOUNT" "$MOUNT///" "$MOUNT/$tfile"; do
18806                 echo "$rootpath $fid"
18807                 found=$($LFS fid2path $rootpath "$fid")
18808                 [ -z "$found" ] && error "fid2path unable to get '$fid' path"
18809                 [ "$found" == "$tf" ] || error "fid2path $found != $tf"
18810         done
18811
18812         # check wrong root path format
18813         rootpath=$MOUNT"_wrong"
18814         found=$($LFS fid2path $rootpath "$fid")
18815         [ -z "$found" ] || error "should fail ($rootpath != $MOUNT)"
18816 }
18817 run_test 154A "lfs path2fid and fid2path basic checks"
18818
18819 test_154B() {
18820         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
18821                 skip "Need MDS version at least 2.4.1"
18822
18823         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
18824         touch $DIR/$tdir/$tfile || error "touch $DIR/$tdir/$tfile failed"
18825         local linkea=$($LL_DECODE_LINKEA $DIR/$tdir/$tfile | grep 'pfid')
18826         [ -z "$linkea" ] && error "decode linkea $DIR/$tdir/$tfile failed"
18827
18828         local name=$(echo $linkea | awk '/pfid/ {print $5}' | sed -e "s/'//g")
18829         local PFID=$(echo $linkea | awk '/pfid/ {print $3}' | sed -e "s/,//g")
18830
18831         # check that we get the same pathname
18832         echo "PFID: $PFID, name: $name"
18833         local FOUND=$($LFS fid2path $MOUNT "$PFID")
18834         [ -z "$FOUND" ] && error "fid2path unable to get $PFID path"
18835         [ "$FOUND/$name" != "$DIR/$tdir/$tfile" ] &&
18836                 error "ll_decode_linkea has $FOUND/$name != $DIR/$tdir/$tfile"
18837
18838         rm -rf $DIR/$tdir || error "Can not delete directory $DIR/$tdir"
18839 }
18840 run_test 154B "verify the ll_decode_linkea tool"
18841
18842 test_154C() {
18843         (( $MDS1_VERSION >= $(version_code 2.16.54) )) ||
18844                 skip "need MDS1 version >= 2.16.54 for OST FID lookup"
18845         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
18846
18847         local tf=$DIR/$tfile
18848         $LFS setstripe -c2 -i0 -S1M $tf
18849         dd if=/dev/zero of=$tf bs=1M count=8
18850
18851         stack_trap "rm -rf $tf; wait_delete_completed"
18852
18853         local stripe_info=$($LFS getstripe $tf)
18854         # for each OST object, execute fid2path
18855         while read -r lfid ofid; do
18856                 # keep only valid lines to parse
18857                 [[ "$lfid" == "l_fid:" ]] || continue
18858
18859                 found=$($LFS fid2path "$MOUNT" "$ofid")
18860                 echo "ost_fid=$ofid with outpath=$found"
18861                 [[ -n "$found" ]] ||
18862                         error "fid2path failed on $ofid"
18863                 [[ "$found" == "$tf" ]] || error "fid2path $found != $tf"
18864         done < <($LFS getstripe -y $tf)
18865 }
18866 run_test 154C "lfs fid2path on OST FID"
18867
18868 test_154a() {
18869         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18870         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
18871         (( $MDS1_VERSION >= $(version_code 2.2.51) )) ||
18872                 skip "Need MDS version at least 2.2.51"
18873         [ -z "$(which setfacl)" ] && skip_env "must have setfacl tool"
18874
18875         cp /etc/hosts $DIR/$tfile
18876
18877         fid=$($LFS path2fid $DIR/$tfile)
18878         rc=$?
18879         [ $rc -ne 0 ] && error "error: could not get fid for $DIR/$tfile."
18880
18881         dot_lustre_fid_permission_check "$fid" $DIR ||
18882                 error "dot lustre permission check $fid failed"
18883
18884         ls -a $MOUNT | grep "\.lustre" && error ".lustre should not be listed"
18885
18886         rm -rf $MOUNT/.lustre && error ".lustre is not allowed to be unlinked"
18887
18888         touch $MOUNT/.lustre/file &&
18889                 error "creation is not allowed under .lustre"
18890
18891         mkdir $MOUNT/.lustre/dir &&
18892                 error "mkdir is not allowed under .lustre"
18893
18894         rm -rf $DIR/$tfile
18895 }
18896 run_test 154a "Open-by-FID"
18897
18898 test_154b() {
18899         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18900         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
18901         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
18902         [[ $MDS1_VERSION -ge $(version_code 2.2.51) ]] ||
18903                 skip "Need MDS version at least 2.2.51"
18904
18905         local remote_dir=$DIR/$tdir/remote_dir
18906         local MDTIDX=1
18907         local rc=0
18908
18909         mkdir -p $DIR/$tdir
18910         $LFS mkdir -i $MDTIDX $remote_dir ||
18911                 error "create remote directory failed"
18912
18913         cp /etc/hosts $remote_dir/$tfile
18914
18915         fid=$($LFS path2fid $remote_dir/$tfile)
18916         rc=$?
18917         [ $rc -ne 0 ] && error "error: could not get fid for $remote_dir/$tfile"
18918
18919         dot_lustre_fid_permission_check "$fid" $remote_dir ||
18920                 error "dot lustre permission check $fid failed"
18921         rm -rf $DIR/$tdir
18922 }
18923 run_test 154b "Open-by-FID for remote directory"
18924
18925 test_154c() {
18926         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
18927                 skip "Need MDS version at least 2.4.1"
18928
18929         touch $DIR/$tfile.1 $DIR/$tfile.2 $DIR/$tfile.3
18930         local FID1=$($LFS path2fid $DIR/$tfile.1)
18931         local FID2=$($LFS path2fid $DIR/$tfile.2)
18932         local FID3=$($LFS path2fid $DIR/$tfile.3)
18933
18934         local N=1
18935         $LFS path2fid $DIR/$tfile.[123] | while read PATHNAME FID; do
18936                 [ "$PATHNAME" = "$DIR/$tfile.$N:" ] ||
18937                         error "path2fid pathname $PATHNAME != $DIR/$tfile.$N:"
18938                 local want=FID$N
18939                 [ "$FID" = "${!want}" ] ||
18940                         error "path2fid $PATHNAME FID $FID != FID$N ${!want}"
18941                 N=$((N + 1))
18942         done
18943
18944         $LFS fid2path $MOUNT "$FID1" "$FID2" "$FID3" | while read PATHNAME;
18945         do
18946                 [ "$PATHNAME" = "$DIR/$tfile.$N" ] ||
18947                         error "fid2path pathname $PATHNAME != $DIR/$tfile.$N:"
18948                 N=$((N + 1))
18949         done
18950 }
18951 run_test 154c "lfs path2fid and fid2path multiple arguments"
18952
18953 test_154d() {
18954         remote_mds_nodsh && skip "remote MDS with nodsh"
18955         [[ $MDS1_VERSION -lt $(version_code 2.5.53) ]] &&
18956                 skip "Need MDS version at least 2.5.53"
18957
18958         if remote_mds; then
18959                 nid=$($LCTL list_nids | sed  "s/\./\\\./g")
18960         else
18961                 nid="0@lo"
18962         fi
18963         local proc_ofile="mdt.*.exports.'$nid'.open_files"
18964         local fd
18965         local cmd
18966
18967         rm -f $DIR/$tfile
18968         touch $DIR/$tfile
18969
18970         local fid=$($LFS path2fid $DIR/$tfile)
18971         # Open the file
18972         fd=$(free_fd)
18973         cmd="exec $fd<$DIR/$tfile"
18974         eval $cmd
18975         local fid_list=$(do_facet $SINGLEMDS $LCTL get_param $proc_ofile)
18976         echo "$fid_list" | grep "$fid"
18977         rc=$?
18978
18979         cmd="exec $fd>/dev/null"
18980         eval $cmd
18981         if [ $rc -ne 0 ]; then
18982                 error "FID $fid not found in open files list $fid_list"
18983         fi
18984 }
18985 run_test 154d "Verify open file fid"
18986
18987 test_154e()
18988 {
18989         [[ $MDS1_VERSION -lt $(version_code 2.6.50) ]] &&
18990                 skip "Need MDS version at least 2.6.50"
18991
18992         if ls -a $MOUNT | grep -q '^\.lustre$'; then
18993                 error ".lustre returned by readdir"
18994         fi
18995 }
18996 run_test 154e ".lustre is not returned by readdir"
18997
18998 test_154ea()
18999 {
19000         stack_trap "rm -rf $MOUNT/[abcdeg]*" EXIT
19001
19002         # long specially selected names are to displace .lustre out of
19003         # first directory block
19004         touch $MOUNT/$(printf "a%0100x" 6)
19005         for i in 11 15
19006         do
19007             touch $MOUNT/$(printf "a%0254x" $i)
19008         done
19009         touch $MOUNT/$(printf "b%0254x" $i)
19010         for i in 16 6 7
19011         do
19012             touch $MOUNT/$(printf "c%0254x" $i)
19013         done
19014         for i in 4 10 8
19015         do
19016             touch $MOUNT/$(printf "d%0254x" $i)
19017         done
19018         for i in 1 14
19019         do
19020             touch /mnt/lustre/$(printf "e%0254x" $i)
19021         done
19022         for i in 13 14
19023         do
19024             touch /mnt/lustre/$(printf "g%0254x" $i)
19025         done
19026         if ls -a $MOUNT | grep -q '^\.lustre$'; then
19027             error ".lustre returned by readdir"
19028         fi
19029 }
19030 run_test 154ea ".lustre is not returned by readdir (2)"
19031
19032 test_154f() {
19033         # create parent directory on a single MDT to avoid cross-MDT hardlinks
19034         mkdir_on_mdt0 $DIR/$tdir
19035         # test dirs inherit from its stripe
19036         mkdir -p $DIR/$tdir/foo1 || error "mkdir error"
19037         mkdir -p $DIR/$tdir/foo2 || error "mkdir error"
19038         cp /etc/hosts $DIR/$tdir/foo1/$tfile
19039         ln $DIR/$tdir/foo1/$tfile $DIR/$tdir/foo2/link
19040         touch $DIR/f
19041
19042         # get fid of parents
19043         local FID0=$($LFS path2fid $DIR/$tdir)
19044         local FID1=$($LFS path2fid $DIR/$tdir/foo1)
19045         local FID2=$($LFS path2fid $DIR/$tdir/foo2)
19046         local FID3=$($LFS path2fid $DIR)
19047
19048         # check that path2fid --parents returns expected <parent_fid>/name
19049         # 1) test for a directory (single parent)
19050         local parent=$($LFS path2fid --parents $DIR/$tdir/foo1)
19051         [ "$parent" == "$FID0/foo1" ] ||
19052                 error "expected parent: $FID0/foo1, got: $parent"
19053
19054         # 2) test for a file with nlink > 1 (multiple parents)
19055         parent=$($LFS path2fid --parents $DIR/$tdir/foo1/$tfile)
19056         echo "$parent" | grep -F "$FID1/$tfile" ||
19057                 error "$FID1/$tfile not returned in parent list"
19058         echo "$parent" | grep -F "$FID2/link" ||
19059                 error "$FID2/link not returned in parent list"
19060
19061         # 3) get parent by fid
19062         local file_fid=$($LFS path2fid $DIR/$tdir/foo1/$tfile)
19063         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
19064         echo "$parent" | grep -F "$FID1/$tfile" ||
19065                 error "$FID1/$tfile not returned in parent list (by fid)"
19066         echo "$parent" | grep -F "$FID2/link" ||
19067                 error "$FID2/link not returned in parent list (by fid)"
19068
19069         # 4) test for entry in root directory
19070         parent=$($LFS path2fid --parents $DIR/f)
19071         echo "$parent" | grep -F "$FID3/f" ||
19072                 error "$FID3/f not returned in parent list"
19073
19074         # 5) test it on root directory
19075         [ -z "$FILESET" ] && {
19076                 # LU_ROOT_FID is wrong for fileset
19077                 [ -z "$($LFS path2fid --parents $MOUNT 2>/dev/null)" ] ||
19078                         error "$MOUNT should not have parents"
19079         }
19080
19081         # enable xattr caching and check that linkea is correctly updated
19082         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
19083         save_lustre_params client "llite.*.xattr_cache" > $save
19084         lctl set_param llite.*.xattr_cache 1
19085
19086         # 6.1) linkea update on rename
19087         mv $DIR/$tdir/foo1/$tfile $DIR/$tdir/foo2/$tfile.moved
19088
19089         # get parents by fid
19090         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
19091         # foo1 should no longer be returned in parent list
19092         echo "$parent" | grep -F "$FID1" &&
19093                 error "$FID1 should no longer be in parent list"
19094         # the new path should appear
19095         echo "$parent" | grep -F "$FID2/$tfile.moved" ||
19096                 error "$FID2/$tfile.moved is not in parent list"
19097
19098         # 6.2) linkea update on unlink
19099         rm -f $DIR/$tdir/foo2/link
19100         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
19101         # foo2/link should no longer be returned in parent list
19102         echo "$parent" | grep -F "$FID2/link" &&
19103                 error "$FID2/link should no longer be in parent list"
19104         true
19105
19106         rm -f $DIR/f
19107         restore_lustre_params < $save
19108         rm -f $save
19109 }
19110 run_test 154f "get parent fids by reading link ea"
19111
19112 test_154g()
19113 {
19114         [[ $MDS1_VERSION -ge $(version_code 2.6.92) &&
19115            $CLIENT_VERSION -gt $(version_code 2.6.99) ]] ||
19116                 skip "Need MDS version at least 2.6.92"
19117
19118         mkdir_on_mdt0 $DIR/$tdir
19119         llapi_fid_test -d $DIR/$tdir
19120 }
19121 run_test 154g "various llapi FID tests"
19122
19123 test_154h()
19124 {
19125         (( $CLIENT_VERSION >= $(version_code 2.15.55.1) )) ||
19126                 skip "Need client at least version 2.15.55.1"
19127
19128         # Create an empty file
19129         touch $DIR/$tfile
19130
19131         # Get FID (interactive mode) and save under $TMP/$tfile.log
19132         $LFS 2>&1 <<-EOF | tee $TMP/$tfile.log
19133                 path2fid $DIR/$tfile
19134         EOF
19135
19136         fid=$(cat $TMP/$tfile.log)
19137         # $fid should not be empty
19138         [[ ! -z $fid ]] || error "FID is empty"
19139         $LFS rmfid $DIR "$fid" || error "rmfid failed for $fid"
19140 }
19141 run_test 154h "Verify interactive path2fid"
19142
19143 test_154i()
19144 {
19145         local long=thislongpathnameisforaverydeepsubdirthatwewanttotestagainst
19146         local depth
19147         local path
19148         local max
19149         local fid
19150
19151         (( $MDS1_VERSION >= $(version_code v2_15_65-55-gf5251cb7af) )) ||
19152                 skip "need MDS >= 2.15.65.55 for fid2path > PATH_MAX handling"
19153
19154         mkdir -p $DIR/$tdir
19155         cd $DIR/$tdir
19156
19157         # create a directory tree with full path longer than PATH_MAX=4096
19158         max=$((4096 / $(wc -c <<< $long) + 5))
19159         for (( depth = 0; depth <= max; depth++)); do
19160                 mkdir -v $long$depth || error "mkdir $long$depth failed"
19161                 cd $long$depth
19162         done
19163
19164         fid=$($LFS path2fid .) || error "path2fid failed"
19165         path=$($LFS fid2path $MOUNT $fid) || error "fid2path failed (1)"
19166         echo -e "Path for fid $fid is:\n$path"
19167
19168         path=$($LFS fid2path $(cd ..; pwd) $fid) || error "fid2path failed (2)"
19169         echo -e "Path for fid $fid is:\n$path"
19170 }
19171 run_test 154i "fid2path for path longer than PATH_MAX"
19172
19173 test_155_small_load() {
19174     local temp=$TMP/$tfile
19175     local file=$DIR/$tfile
19176
19177     dd if=/dev/urandom of=$temp bs=6096 count=1 || \
19178         error "dd of=$temp bs=6096 count=1 failed"
19179     cp $temp $file
19180     cancel_lru_locks $OSC
19181     cmp $temp $file || error "$temp $file differ"
19182
19183     $TRUNCATE $temp 6000
19184     $TRUNCATE $file 6000
19185     cmp $temp $file || error "$temp $file differ (truncate1)"
19186
19187     echo "12345" >>$temp
19188     echo "12345" >>$file
19189     cmp $temp $file || error "$temp $file differ (append1)"
19190
19191     echo "12345" >>$temp
19192     echo "12345" >>$file
19193     cmp $temp $file || error "$temp $file differ (append2)"
19194
19195     rm -f $temp $file
19196     true
19197 }
19198
19199 test_155_big_load() {
19200         remote_ost_nodsh && skip "remote OST with nodsh"
19201
19202         local temp=$TMP/$tfile
19203         local file=$DIR/$tfile
19204
19205         free_min_max
19206         local cache_size=$(do_facet ost$((MAXI+1)) \
19207                 "awk '/cache/ {sum+=\\\$4} END {print sum}' /proc/cpuinfo")
19208
19209         # LU-16042: can not get the cache size on Arm64 VM here, fallback to a
19210         # pre-set value
19211         if [ -z "$cache_size" ]; then
19212                 cache_size=256
19213         fi
19214         local large_file_size=$((cache_size * 2))
19215
19216         echo "OSS cache size: $cache_size KB"
19217         echo "Large file size: $large_file_size KB"
19218
19219         [ $MAXV -le $large_file_size ] &&
19220                 skip_env "max available OST size needs > $large_file_size KB"
19221
19222         $LFS setstripe $file -c 1 -i $MAXI || error "$LFS setstripe $file failed"
19223
19224         dd if=/dev/urandom of=$temp bs=$large_file_size count=1k ||
19225                 error "dd of=$temp bs=$large_file_size count=1k failed"
19226         cp $temp $file
19227         ls -lh $temp $file
19228         cancel_lru_locks osc
19229         cmp $temp $file || error "$temp $file differ"
19230
19231         rm -f $temp $file
19232         true
19233 }
19234
19235 save_writethrough() {
19236         local facets=$(get_facets OST)
19237
19238         save_lustre_params $facets "osd-*.*.writethrough_cache_enable" > $1
19239 }
19240
19241 test_155a() {
19242         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19243
19244         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19245         local osts=$(osts_nodes)
19246
19247         save_writethrough $p
19248
19249         set_cache $osts read on
19250         set_cache $osts writethrough on
19251         test_155_small_load
19252         restore_lustre_params < $p
19253         rm -f $p
19254 }
19255 run_test 155a "Verify small file correctness: read cache:on write_cache:on"
19256
19257 test_155b() {
19258         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19259
19260         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19261         local osts=$(osts_nodes)
19262
19263         save_writethrough $p
19264
19265         set_cache $osts read on
19266         set_cache $osts writethrough off
19267         test_155_small_load
19268         restore_lustre_params < $p
19269         rm -f $p
19270 }
19271 run_test 155b "Verify small file correctness: read cache:on write_cache:off"
19272
19273 test_155c() {
19274         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19275
19276         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19277         local osts=$(osts_nodes)
19278
19279         save_writethrough $p
19280
19281         set_cache $osts read off
19282         set_cache $osts writethrough on
19283         test_155_small_load
19284         restore_lustre_params < $p
19285         rm -f $p
19286 }
19287 run_test 155c "Verify small file correctness: read cache:off write_cache:on"
19288
19289 test_155d() {
19290         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19291
19292         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19293         local osts=$(osts_nodes)
19294
19295         save_writethrough $p
19296
19297         set_cache $osts read off
19298         set_cache $osts writethrough off
19299         test_155_small_load
19300         restore_lustre_params < $p
19301         rm -f $p
19302 }
19303 run_test 155d "Verify small file correctness: read cache:off write_cache:off"
19304
19305 test_155e() {
19306         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19307
19308         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19309         local osts=$(osts_nodes)
19310
19311         save_writethrough $p
19312
19313         set_cache $osts read on
19314         set_cache $osts writethrough on
19315         test_155_big_load
19316         restore_lustre_params < $p
19317         rm -f $p
19318 }
19319 run_test 155e "Verify big file correctness: read cache:on write_cache:on"
19320
19321 test_155f() {
19322         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19323
19324         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19325         local osts=$(osts_nodes)
19326
19327         save_writethrough $p
19328
19329         set_cache $osts read on
19330         set_cache $osts writethrough off
19331         test_155_big_load
19332         restore_lustre_params < $p
19333         rm -f $p
19334 }
19335 run_test 155f "Verify big file correctness: read cache:on write_cache:off"
19336
19337 test_155g() {
19338         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19339
19340         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19341         local osts=$(osts_nodes)
19342
19343         save_writethrough $p
19344
19345         set_cache $osts read off
19346         set_cache $osts writethrough on
19347         test_155_big_load
19348         restore_lustre_params < $p
19349         rm -f $p
19350 }
19351 run_test 155g "Verify big file correctness: read cache:off write_cache:on"
19352
19353 test_155h() {
19354         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19355
19356         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19357         local osts=$(osts_nodes)
19358
19359         save_writethrough $p
19360
19361         set_cache $osts read off
19362         set_cache $osts writethrough off
19363         test_155_big_load
19364         restore_lustre_params < $p
19365         rm -f $p
19366 }
19367 run_test 155h "Verify big file correctness: read cache:off write_cache:off"
19368
19369 test_156() {
19370         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19371         remote_ost_nodsh && skip "remote OST with nodsh"
19372         [ $OST1_VERSION -lt $(version_code 2.6.93) ] &&
19373                 skip "stats not implemented on old servers"
19374         [ "$ost1_FSTYPE" = "zfs" ] &&
19375                 skip "LU-1956/LU-2261: stats not implemented on OSD ZFS"
19376         (( CLIENT_VERSION == OST1_VERSION )) ||
19377                 skip "LU-13081: no interop testing for OSS cache"
19378
19379         local CPAGES=3
19380         local BEFORE
19381         local AFTER
19382         local file="$DIR/$tfile"
19383         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
19384         local osts=$(osts_nodes)
19385
19386         save_writethrough $p
19387         roc_hit_init $osts
19388
19389         log "Turn on read and write cache"
19390         set_cache $osts read on
19391         set_cache $osts writethrough on
19392
19393         log "Write data and read it back."
19394         log "Read should be satisfied from the cache."
19395         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
19396         BEFORE=$(roc_hit $osts)
19397         cancel_lru_locks osc
19398         cat $file >/dev/null
19399         AFTER=$(roc_hit $osts)
19400         if ! let "AFTER - BEFORE == CPAGES"; then
19401                 error "NOT IN CACHE (2): before: $BEFORE, after: $AFTER"
19402         else
19403                 log "cache hits: before: $BEFORE, after: $AFTER"
19404         fi
19405
19406         log "Read again; it should be satisfied from the cache."
19407         BEFORE=$AFTER
19408         cancel_lru_locks osc
19409         cat $file >/dev/null
19410         AFTER=$(roc_hit $osts)
19411         if ! let "AFTER - BEFORE == CPAGES"; then
19412                 error "NOT IN CACHE (3): before: $BEFORE, after: $AFTER"
19413         else
19414                 log "cache hits:: before: $BEFORE, after: $AFTER"
19415         fi
19416
19417         log "Turn off the read cache and turn on the write cache"
19418         set_cache $osts read off
19419         set_cache $osts writethrough on
19420
19421         log "Read again; it should be satisfied from the cache."
19422         BEFORE=$(roc_hit $osts)
19423         cancel_lru_locks osc
19424         cat $file >/dev/null
19425         AFTER=$(roc_hit $osts)
19426         if ! let "AFTER - BEFORE == CPAGES"; then
19427                 error "NOT IN CACHE (4): before: $BEFORE, after: $AFTER"
19428         else
19429                 log "cache hits:: before: $BEFORE, after: $AFTER"
19430         fi
19431
19432         if [ $OST1_VERSION -lt $(version_code 2.12.55) ]; then
19433                 # > 2.12.56 uses pagecache if cached
19434                 log "Read again; it should not be satisfied from the cache."
19435                 BEFORE=$AFTER
19436                 cancel_lru_locks osc
19437                 cat $file >/dev/null
19438                 AFTER=$(roc_hit $osts)
19439                 if ! let "AFTER - BEFORE == 0"; then
19440                         error "IN CACHE (5): before: $BEFORE, after: $AFTER"
19441                 else
19442                         log "cache hits:: before: $BEFORE, after: $AFTER"
19443                 fi
19444         fi
19445
19446         log "Write data and read it back."
19447         log "Read should be satisfied from the cache."
19448         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
19449         BEFORE=$(roc_hit $osts)
19450         cancel_lru_locks osc
19451         cat $file >/dev/null
19452         AFTER=$(roc_hit $osts)
19453         if ! let "AFTER - BEFORE == CPAGES"; then
19454                 error "NOT IN CACHE (6): before: $BEFORE, after: $AFTER"
19455         else
19456                 log "cache hits:: before: $BEFORE, after: $AFTER"
19457         fi
19458
19459         if [ $OST1_VERSION -lt $(version_code 2.12.55) ]; then
19460                 # > 2.12.56 uses pagecache if cached
19461                 log "Read again; it should not be satisfied from the cache."
19462                 BEFORE=$AFTER
19463                 cancel_lru_locks osc
19464                 cat $file >/dev/null
19465                 AFTER=$(roc_hit $osts)
19466                 if ! let "AFTER - BEFORE == 0"; then
19467                         error "IN CACHE (7): before: $BEFORE, after: $AFTER"
19468                 else
19469                         log "cache hits:: before: $BEFORE, after: $AFTER"
19470                 fi
19471         fi
19472
19473         log "Turn off read and write cache"
19474         set_cache $osts read off
19475         set_cache $osts writethrough off
19476
19477         log "Write data and read it back"
19478         log "It should not be satisfied from the cache."
19479         rm -f $file
19480         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
19481         cancel_lru_locks osc
19482         BEFORE=$(roc_hit $osts)
19483         cat $file >/dev/null
19484         AFTER=$(roc_hit $osts)
19485         if ! let "AFTER - BEFORE == 0"; then
19486                 error_ignore bz20762 "IN CACHE (8):before:$BEFORE,after:$AFTER"
19487         else
19488                 log "cache hits:: before: $BEFORE, after: $AFTER"
19489         fi
19490
19491         log "Turn on the read cache and turn off the write cache"
19492         set_cache $osts read on
19493         set_cache $osts writethrough off
19494
19495         log "Write data and read it back"
19496         log "It should not be satisfied from the cache."
19497         rm -f $file
19498         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
19499         BEFORE=$(roc_hit $osts)
19500         cancel_lru_locks osc
19501         cat $file >/dev/null
19502         AFTER=$(roc_hit $osts)
19503         if ! let "AFTER - BEFORE == 0"; then
19504                 error_ignore bz20762 "IN CACHE (9):before:$BEFORE,after:$AFTER"
19505         else
19506                 log "cache hits:: before: $BEFORE, after: $AFTER"
19507         fi
19508
19509         log "Read again; it should be satisfied from the cache."
19510         BEFORE=$(roc_hit $osts)
19511         cancel_lru_locks osc
19512         cat $file >/dev/null
19513         AFTER=$(roc_hit $osts)
19514         if ! let "AFTER - BEFORE == CPAGES"; then
19515                 error "NOT IN CACHE (1): before: $BEFORE, after: $AFTER"
19516         else
19517                 log "cache hits:: before: $BEFORE, after: $AFTER"
19518         fi
19519
19520         restore_lustre_params < $p
19521         rm -f $p $file
19522 }
19523 run_test 156 "Verification of tunables"
19524
19525 test_160a() {
19526         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19527         remote_mds_nodsh && skip "remote MDS with nodsh"
19528         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
19529                 skip "Need MDS version at least 2.2.0"
19530
19531         changelog_register || error "changelog_register failed"
19532         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
19533         changelog_users $SINGLEMDS | grep -q $cl_user ||
19534                 error "User $cl_user not found in changelog_users"
19535
19536         mkdir_on_mdt0 $DIR/$tdir
19537
19538         # change something
19539         test_mkdir -p $DIR/$tdir/pics/2008/zachy
19540         changelog_clear 0 || error "changelog_clear failed"
19541         touch $DIR/$tdir/pics/2008/zachy/$tfile                 # open 1
19542         cp /etc/hosts $DIR/$tdir/pics/2008/zachy/pic1.jpg       # open 2
19543         mv $DIR/$tdir/pics/2008/zachy $DIR/$tdir/pics/zach
19544         ln $DIR/$tdir/pics/zach/pic1.jpg $DIR/$tdir/pics/2008/portland.jpg
19545         ln -s $DIR/$tdir/pics/2008/portland.jpg $DIR/$tdir/pics/desktop.jpg
19546         rm $DIR/$tdir/pics/desktop.jpg
19547
19548         echo "verifying changelog mask"
19549         changelog_chmask "-MKDIR"
19550         changelog_chmask "-CLOSE"
19551
19552         test_mkdir -p $DIR/$tdir/pics/zach/sofia                # not logged
19553         echo "zzzzzz" > $DIR/$tdir/pics/zach/file               # not logged
19554
19555         changelog_chmask "+MKDIR"
19556         changelog_chmask "+CLOSE"
19557
19558         test_mkdir -p $DIR/$tdir/pics/2008/sofia                # mkdir 1
19559         echo "zzzzzz" > $DIR/$tdir/pics/zach/file               # open 3
19560
19561         MKDIRS=$(changelog_dump | grep -c "MKDIR")
19562         CLOSES=$(changelog_dump | grep -c "CLOSE")
19563         [ $MKDIRS -eq 1 ] || error "MKDIR changelog mask count $MKDIRS != 1"
19564         [ $CLOSES -eq 3 ] || error "CLOSE changelog mask count $CLOSES != 3"
19565
19566         # verify contents
19567         echo "verifying target fid"
19568         local fidc=$(changelog_extract_field "CREAT" "$tfile" "t=")
19569         local fidf=$($LFS path2fid $DIR/$tdir/pics/zach/$tfile)
19570         [ "$fidc" == "$fidf" ] ||
19571                 error "changelog '$tfile' fid $fidc != file fid $fidf"
19572         echo "verifying parent fid"
19573         # The FID returned from the Changelog may be the directory shard on
19574         # a different MDT, and not the FID returned by path2fid on the parent.
19575         # Instead of comparing FIDs, verify that fid2path(fidp) is correct,
19576         # since this is what will matter when recreating this file in the tree.
19577         local fidp=$(changelog_extract_field "CREAT" "$tfile" "p=")
19578         local pathp=$($LFS fid2path $MOUNT "$fidp")
19579         [ "${pathp%/}" == "$DIR/$tdir/pics/zach" ] ||
19580                 error "changelog fid2path($fidc) $pathp != $DIR/$tdir/pics/zach"
19581
19582         echo "getting records for $cl_user"
19583         changelog_users $SINGLEMDS
19584         local user_rec1=$(changelog_user_rec $SINGLEMDS $cl_user)
19585         local nclr=3
19586         __changelog_clear $SINGLEMDS $cl_user +$nclr ||
19587                 error "changelog_clear failed"
19588         local user_rec2=$(changelog_user_rec $SINGLEMDS $cl_user)
19589         echo "verifying user clear: $user_rec1 + $nclr == $user_rec2"
19590         [ $user_rec2 == $((user_rec1 + nclr)) ] ||
19591                 error "user index expect $user_rec1 + $nclr != $user_rec2"
19592
19593         local min0_rec=$(changelog_users $SINGLEMDS |
19594                 awk 'min == "" || $2 < min { min = $2 }; END { print min }')
19595         local first_rec=$($LFS changelog $(facet_svc $SINGLEMDS) |
19596                           awk '{ print $1; exit; }')
19597
19598         changelog_dump | tail -n 5
19599         echo "verifying user min purge: $min0_rec + 1 == $first_rec"
19600         [ $first_rec == $((min0_rec + 1)) ] ||
19601                 error "first index should be $min0_rec + 1 not $first_rec"
19602
19603         # LU-3446 changelog index reset on MDT restart
19604         local cur_rec1=$(changelog_users $SINGLEMDS |
19605                          awk '/^current.index:/ { print $NF }')
19606         changelog_clear 0 ||
19607                 error "clear all changelog records for $cl_user failed"
19608         stop $SINGLEMDS || error "Fail to stop $SINGLEMDS"
19609         start $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) $MDS_MOUNT_OPTS ||
19610                 error "Fail to start $SINGLEMDS"
19611         local cur_rec2=$(changelog_users $SINGLEMDS |
19612                          awk '/^current.index:/ { print $NF }')
19613         echo "verifying index survives MDT restart: $cur_rec1 == $cur_rec2"
19614         [ $cur_rec1 == $cur_rec2 ] ||
19615                 error "current index should be $cur_rec1 not $cur_rec2"
19616
19617         echo "verifying users from this test are deregistered"
19618         changelog_deregister || error "changelog_deregister failed"
19619         changelog_users $SINGLEMDS | grep -q $cl_user &&
19620                 error "User '$cl_user' still in changelog_users"
19621
19622         # lctl get_param -n mdd.*.changelog_users
19623         # current_index: 144
19624         # ID    index (idle seconds)
19625         # cl3   144   (2) mask=<list>
19626         if [ -z "$(changelog_users $SINGLEMDS | grep -v current.index)" ]; then
19627                 # this is the normal case where all users were deregistered
19628                 # make sure no new records are added when no users are present
19629                 local last_rec1=$(changelog_users $SINGLEMDS |
19630                                   awk '/^current.index:/ { print $NF }')
19631                 touch $DIR/$tdir/chloe
19632                 local last_rec2=$(changelog_users $SINGLEMDS |
19633                                   awk '/^current.index:/ { print $NF }')
19634                 echo "verify changelogs are off: $last_rec1 == $last_rec2"
19635                 [ $last_rec1 == $last_rec2 ] || error "changelogs not off"
19636         else
19637                 # any changelog users must be leftovers from a previous test
19638                 changelog_users $SINGLEMDS
19639                 echo "other changelog users; can't verify off"
19640         fi
19641 }
19642 run_test 160a "changelog sanity"
19643
19644 test_160b() { # LU-3587
19645         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19646         remote_mds_nodsh && skip "remote MDS with nodsh"
19647         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
19648                 skip "Need MDS version at least 2.2.0"
19649
19650         changelog_register || error "changelog_register failed"
19651         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
19652         changelog_users $SINGLEMDS | grep -q $cl_user ||
19653                 error "User '$cl_user' not found in changelog_users"
19654
19655         local longname1=$(str_repeat a 255)
19656         local longname2=$(str_repeat b 255)
19657
19658         cd $DIR
19659         echo "creating very long named file"
19660         touch $longname1 || error "create of '$longname1' failed"
19661         echo "renaming very long named file"
19662         mv $longname1 $longname2
19663
19664         changelog_dump | grep RENME | tail -n 5
19665         rm -f $longname2
19666 }
19667 run_test 160b "Verify that very long rename doesn't crash in changelog"
19668
19669 test_160c() {
19670         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19671         remote_mds_nodsh && skip "remote MDS with nodsh"
19672
19673         [[ $MDS1_VERSION -gt $(version_code 2.5.57) ]] ||
19674                 [[ $MDS1_VERSION -gt $(version_code 2.5.1) &&
19675                    $MDS1_VERSION -lt $(version_code 2.5.50) ]] ||
19676                 skip "Need MDS version at least 2.5.58 or 2.5.2+"
19677
19678         local rc=0
19679
19680         # Registration step
19681         changelog_register || error "changelog_register failed"
19682
19683         rm -rf $DIR/$tdir
19684         mkdir -p $DIR/$tdir
19685         $MCREATE $DIR/$tdir/foo_160c
19686         changelog_chmask "-TRUNC"
19687         $TRUNCATE $DIR/$tdir/foo_160c 200
19688         changelog_chmask "+TRUNC"
19689         $TRUNCATE $DIR/$tdir/foo_160c 199
19690         changelog_dump | tail -n 5
19691         local truncs=$(changelog_dump | tail -n 5 | grep -c TRUNC)
19692         [ $truncs -eq 1 ] || error "TRUNC changelog mask count $truncs != 1"
19693 }
19694 run_test 160c "verify that changelog log catch the truncate event"
19695
19696 test_160d() {
19697         remote_mds_nodsh && skip "remote MDS with nodsh"
19698         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
19699         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19700         [[ $MDS1_VERSION -ge $(version_code 2.7.60) ]] ||
19701                 skip "Need MDS version at least 2.7.60"
19702
19703         # Registration step
19704         changelog_register || error "changelog_register failed"
19705
19706         mkdir -p $DIR/$tdir/migrate_dir
19707
19708         local src_mdt=$($LFS getdirstripe -m $DIR/$tdir/migrate_dir)
19709         local tgt_mdt=1
19710
19711         [[ "$src_mdt" == "$tgt_mdt" ]] && tgt_mdt=0
19712
19713         changelog_clear 0 || error "changelog_clear failed"
19714
19715         $LFS migrate -m $tgt_mdt $DIR/$tdir/migrate_dir || error "migrate fails"
19716         changelog_dump | tail -n 5
19717         local migrates=$(changelog_dump | grep -c "MIGRT")
19718         [ $migrates -eq 1 ] || error "MIGRATE changelog count $migrates != 1"
19719 }
19720 run_test 160d "verify that changelog log catch the migrate event"
19721
19722 test_160e() {
19723         remote_mds_nodsh && skip "remote MDS with nodsh"
19724
19725         # Create a user
19726         changelog_register || error "changelog_register failed"
19727
19728         local MDT0=$(facet_svc $SINGLEMDS)
19729         local rc
19730
19731         # No user (expect fail)
19732         do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister
19733         rc=$?
19734         if [ $rc -eq 0 ]; then
19735                 error "Should fail without user"
19736         elif [ $rc -ne 4 ]; then
19737                 error "changelog_deregister failed with $rc, expect 4(CMD_HELP)"
19738         fi
19739
19740         # Delete a future user (expect fail)
19741         do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister "cl77"
19742         rc=$?
19743         if [ $rc -eq 0 ]; then
19744                 error "Deleted non-existant user cl77"
19745         elif [ $rc -ne 2 ]; then
19746                 error "changelog_deregister failed with $rc, expect 2 (ENOENT)"
19747         fi
19748
19749         # Clear to a bad index (1 billion should be safe)
19750         $LFS changelog_clear $MDT0 "${CL_USERS[$SINGLEMDS]%% *}" 1000000000
19751         rc=$?
19752
19753         if [ $rc -eq 0 ]; then
19754                 error "Successfully cleared to invalid CL index"
19755         elif [ $rc -ne 22 ]; then
19756                 error "changelog_clear failed with $rc, expected 22 (EINVAL)"
19757         fi
19758 }
19759 run_test 160e "changelog negative testing (should return errors)"
19760
19761 test_160f() {
19762         remote_mds_nodsh && skip "remote MDS with nodsh" && return
19763         [[ $MDS1_VERSION -ge $(version_code 2.10.56) ]] ||
19764                 skip "Need MDS version at least 2.10.56"
19765
19766         local mdts=$(mdts_nodes)
19767
19768         # Create a user
19769         changelog_register || error "first changelog_register failed"
19770         changelog_register || error "second changelog_register failed"
19771         local cl_users
19772         declare -A cl_user1
19773         declare -A cl_user2
19774         local user_rec1
19775         local user_rec2
19776         local i
19777
19778         # generate some changelog records to accumulate on each MDT
19779         # use all_char because created files should be evenly distributed
19780         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
19781                 error "test_mkdir $tdir failed"
19782         log "$(date +%s): creating first dirs"
19783         for ((idx = 0; idx < MDSCOUNT * 2; idx++)); do
19784                 local d=$DIR/$tdir/d$idx.$((idx/MDSCOUNT))
19785                 $LFS mkdir -i $((idx%MDSCOUNT)) $d ||
19786                         error "create $d on MDT$idx failed"
19787         done
19788
19789         # check changelogs have been generated
19790         local start=$SECONDS
19791         local idle_time=$((MDSCOUNT * 5 + 5))
19792         local nbcl=$(changelog_dump | wc -l)
19793         (( $nbcl != 0 )) || error "no changelogs found"
19794
19795         for param in "changelog_max_idle_time=$idle_time" \
19796                      "changelog_gc=1" \
19797                      "changelog_min_gc_interval=2" \
19798                      "changelog_min_free_cat_entries=3"; do
19799                 local MDT0=$(facet_svc $SINGLEMDS)
19800                 local var="${param%=*}"
19801                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
19802
19803                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
19804                 do_nodes $mdts $LCTL set_param mdd.*.$param
19805         done
19806
19807         # force cl_user2 to be idle (1st part), but also cancel the
19808         # cl_user1 records so that it is not evicted later in the test.
19809         local sleep1=$((idle_time / 2))
19810         echo "$(date +%s): sleep1 $sleep1/${idle_time}s"
19811         sleep $sleep1
19812
19813         # simulate changelog catalog almost full
19814         #define OBD_FAIL_CAT_FREE_RECORDS       0x1313
19815         do_nodes $mdts "$LCTL set_param fail_loc=0x1313 fail_val=3"
19816
19817         for ((i = 1; i <= $MDSCOUNT; i++)); do
19818                 cl_users=(${CL_USERS[mds$i]})
19819                 cl_user1[mds$i]="${cl_users[0]}"
19820                 cl_user2[mds$i]="${cl_users[1]}"
19821
19822                 [ -n "${cl_user1[mds$i]}" ] ||
19823                         error "mds$i: no user registered"
19824                 [ -n "${cl_user2[mds$i]}" ] ||
19825                         error "mds$i: only ${cl_user2[mds$i]} is registered"
19826
19827                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19828                 [ -n "$user_rec1" ] ||
19829                         error "mds$i: User ${cl_user1[mds$i]} not registered"
19830                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
19831                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19832                 [ -n "$user_rec2" ] ||
19833                         error "mds$i: User ${cl_user1[mds$i]} not registered"
19834                 echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
19835                      "$user_rec1 + 2 == $user_rec2"
19836                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
19837                         error "mds$i: user ${cl_user1[mds$i]} index expected " \
19838                               "$user_rec1 + 2, but is $user_rec2"
19839                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
19840                 [ -n "$user_rec2" ] ||
19841                         error "mds$i: User ${cl_user2[mds$i]} not registered"
19842                 [ $user_rec1 == $user_rec2 ] ||
19843                         error "mds$i: user ${cl_user2[mds$i]} index expected " \
19844                               "$user_rec1, but is $user_rec2"
19845         done
19846
19847         # force cl_user2 idle (2nd part) to just exceed changelog_max_idle_time
19848         local sleep2=$((idle_time - (SECONDS - start) + 1))
19849         echo "$(date +%s): sleep2 $sleep2/${idle_time}s"
19850         sleep $sleep2
19851
19852         # Generate one more changelog to trigger GC at fail_loc for cl_user2.
19853         # cl_user1 should be OK because it recently processed records.
19854         echo "$(date +%s): creating $((MDSCOUNT * 2)) dirs"
19855         for ((idx = 0; idx < MDSCOUNT * 2; idx++)); do
19856                 local d=$DIR/$tdir/d$idx.$((idx/MDSCOUNT+2))
19857
19858                 $LFS mkdir -i $((idx%MDSCOUNT)) $d ||
19859                         error "create dir $d on MDT$idx failed"
19860         done
19861
19862         # ensure gc thread is done
19863         for mds in ${mdts//,/ }; do
19864                 wait_update $mds "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
19865                         error "$mds: GC-thread not done"
19866         done
19867
19868         local first_rec
19869         for (( i = 1; i <= MDSCOUNT; i++ )); do
19870                 # check cl_user1 still registered
19871                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
19872                         error "mds$i: User ${cl_user1[mds$i]} not registered"
19873                 # check cl_user2 unregistered
19874                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
19875                         error "mds$i: User ${cl_user2[mds$i]} still registered"
19876
19877                 # check changelogs are present and starting at $user_rec1 + 1
19878                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19879                 [ -n "$user_rec1" ] ||
19880                         error "mds$i: User ${cl_user1[mds$i]} not registered"
19881                 first_rec=$($LFS changelog $(facet_svc mds$i) |
19882                             awk '{ print $1; exit; }')
19883
19884                 echo "mds$i: $(date +%s) verify rec $user_rec1+1 == $first_rec"
19885                 [ $((user_rec1 + 1)) == $first_rec ] ||
19886                         error "mds$i: rec $first_rec != $user_rec1 + 1"
19887         done
19888 }
19889 run_test 160f "changelog garbage collect (timestamped users)"
19890
19891 test_160g() {
19892         remote_mds_nodsh && skip "remote MDS with nodsh"
19893         [[ $MDS1_VERSION -ge $(version_code 2.14.55) ]] ||
19894                 skip "Need MDS version at least 2.14.55"
19895
19896         local mdts=$(mdts_nodes)
19897
19898         # Create a user
19899         changelog_register || error "first changelog_register failed"
19900         changelog_register || error "second changelog_register failed"
19901         local cl_users
19902         declare -A cl_user1
19903         declare -A cl_user2
19904         local user_rec1
19905         local user_rec2
19906         local i
19907
19908         # generate some changelog records to accumulate on each MDT
19909         # use all_char because created files should be evenly distributed
19910         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
19911                 error "test_mkdir $tdir failed"
19912         for ((idx = 0; idx < MDSCOUNT; idx++)); do
19913                 $LFS mkdir -i $idx $DIR/$tdir/d$idx.1 $DIR/$tdir/d$idx.2 ||
19914                         error "create $DIR/$tdir/d$idx.1 failed"
19915         done
19916
19917         # check changelogs have been generated
19918         local nbcl=$(changelog_dump | wc -l)
19919         (( $nbcl > 0 )) || error "no changelogs found"
19920
19921         # reduce the max_idle_indexes value to make sure we exceed it
19922         for param in "changelog_max_idle_indexes=2" \
19923                      "changelog_gc=1" \
19924                      "changelog_min_gc_interval=2"; do
19925                 local MDT0=$(facet_svc $SINGLEMDS)
19926                 local var="${param%=*}"
19927                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
19928
19929                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
19930                 do_nodes $mdts $LCTL set_param mdd.*.$param ||
19931                         error "unable to set mdd.*.$param"
19932         done
19933
19934         local start=$SECONDS
19935         for ((i=1; i <= $MDSCOUNT; i++)); do
19936                 cl_users=(${CL_USERS[mds$i]})
19937                 cl_user1[mds$i]="${cl_users[0]}"
19938                 cl_user2[mds$i]="${cl_users[1]}"
19939
19940                 [ -n "${cl_user1[mds$i]}" ] ||
19941                         error "mds$i: user1 is not registered"
19942                 [ -n "${cl_user2[mds$i]}" ] ||
19943                         error "mds$i: only ${cl_user1[mds$i]} is registered"
19944
19945                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19946                 [ -n "$user_rec1" ] ||
19947                         error "mds$i: user1 ${cl_user1[mds$i]} not found"
19948                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
19949                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19950                 [ -n "$user_rec2" ] ||
19951                         error "mds$i: user1 ${cl_user1[mds$i]} not found (2)"
19952                 echo "mds$i: verifying user1 ${cl_user1[mds$i]} clear: " \
19953                      "$user_rec1 + 2 == $user_rec2"
19954                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
19955                         error "mds$i: user1 ${cl_user1[mds$i]} index " \
19956                               "expected $user_rec1 + 2, but is $user_rec2"
19957                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
19958                 [ -n "$user_rec2" ] ||
19959                         error "mds$i: user2 ${cl_user2[mds$i]} not found"
19960                 [ $user_rec1 == $user_rec2 ] ||
19961                         error "mds$i: user2 ${cl_user2[mds$i]} index " \
19962                               "expected $user_rec1, but is $user_rec2"
19963         done
19964
19965         # ensure we are past the previous changelog_min_gc_interval set above
19966         local sleep2=$((start + 2 - SECONDS))
19967         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
19968         # Generate one more changelog to trigger GC at fail_loc for cl_user2.
19969         # cl_user1 should be OK because it recently processed records.
19970         for ((idx = 0; idx < MDSCOUNT; idx++)); do
19971                 $LFS mkdir -i $idx $DIR/$tdir/d$idx.3 ||
19972                         error "create $DIR/$tdir/d$idx.3 failed"
19973         done
19974
19975         # ensure gc thread is done
19976         for mds in ${mdts//,/ }; do
19977                 wait_update $mds "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
19978                         error "$mds: GC-thread not done"
19979         done
19980
19981         local first_rec
19982         for (( i = 1; i <= MDSCOUNT; i++ )); do
19983                 # check cl_user1 still registered
19984                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
19985                         error "mds$i: user1 ${cl_user1[mds$i]} not found (3)"
19986                 # check cl_user2 unregistered
19987                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
19988                         error "mds$i: user2 ${cl_user2[mds$i]} is registered"
19989
19990                 # check changelogs are present and starting at $user_rec1 + 1
19991                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
19992                 [ -n "$user_rec1" ] ||
19993                         error "mds$i: user1 ${cl_user1[mds$i]} not found (4)"
19994                 first_rec=$($LFS changelog $(facet_svc mds$i) |
19995                             awk '{ print $1; exit; }')
19996
19997                 echo "mds$i: $(date +%s) verify rec $user_rec1+1 == $first_rec"
19998                 [ $((user_rec1 + 1)) == $first_rec ] ||
19999                         error "mds$i: rec $first_rec != $user_rec1 + 1"
20000         done
20001 }
20002 run_test 160g "changelog garbage collect on idle records"
20003
20004 test_160h() {
20005         remote_mds_nodsh && skip "remote MDS with nodsh" && return
20006         (( $MDS1_VERSION >= $(version_code 2.10.56) )) ||
20007                 skip "Need MDS version at least 2.10.56"
20008
20009         local mdts=$(mdts_nodes)
20010
20011         # Create a user
20012         changelog_register || error "first changelog_register failed"
20013         changelog_register || error "second changelog_register failed"
20014         local cl_users
20015         declare -A cl_user1
20016         declare -A cl_user2
20017         local user_rec1
20018         local user_rec2
20019         local i
20020
20021         # generate some changelog records to accumulate on each MDT
20022         # use all_char because created files should be evenly distributed
20023         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
20024                 error "test_mkdir $tdir failed"
20025         for ((idx = 0; idx < MDSCOUNT; idx++)); do
20026                 $LFS mkdir -i $idx $DIR/$tdir/d$idx.1 $DIR/$tdir/d$idx.2 ||
20027                         error "create $DIR/$tdir/d$idx.1 failed"
20028         done
20029
20030         # check changelogs have been generated
20031         local nbcl=$(changelog_dump | wc -l)
20032         [[ $nbcl -eq 0 ]] && error "no changelogs found"
20033
20034         for param in "changelog_max_idle_time=10" \
20035                      "changelog_gc=1" \
20036                      "changelog_min_gc_interval=2"; do
20037                 local MDT0=$(facet_svc $SINGLEMDS)
20038                 local var="${param%=*}"
20039                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
20040
20041                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
20042                 do_nodes $mdts $LCTL set_param mdd.*.$param
20043         done
20044
20045         # force cl_user2 to be idle (1st part)
20046         sleep 9
20047
20048         for ((i=1; i <= $MDSCOUNT; i++)); do
20049                 cl_users=(${CL_USERS[mds$i]})
20050                 cl_user1[mds$i]="${cl_users[0]}"
20051                 cl_user2[mds$i]="${cl_users[1]}"
20052
20053                 [ -n "${cl_user1[mds$i]}" ] ||
20054                         error "mds$i: no user registered"
20055                 [ -n "${cl_user2[mds$i]}" ] ||
20056                         error "mds$i: only ${cl_user2[mds$i]} is registered"
20057
20058                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
20059                 [ -n "$user_rec1" ] ||
20060                         error "mds$i: User ${cl_user1[mds$i]} not registered"
20061                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
20062                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
20063                 [ -n "$user_rec2" ] ||
20064                         error "mds$i: User ${cl_user1[mds$i]} not registered"
20065                 echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
20066                      "$user_rec1 + 2 == $user_rec2"
20067                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
20068                         error "mds$i: user ${cl_user1[mds$i]} index expected " \
20069                               "$user_rec1 + 2, but is $user_rec2"
20070                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
20071                 [ -n "$user_rec2" ] ||
20072                         error "mds$i: User ${cl_user2[mds$i]} not registered"
20073                 [ $user_rec1 == $user_rec2 ] ||
20074                         error "mds$i: user ${cl_user2[mds$i]} index expected " \
20075                               "$user_rec1, but is $user_rec2"
20076         done
20077
20078         # force cl_user2 to be idle (2nd part) and to reach
20079         # changelog_max_idle_time
20080         sleep 2
20081
20082         # force each GC-thread start and block then
20083         # one per MDT/MDD, set fail_val accordingly
20084         #define OBD_FAIL_FORCE_GC_THREAD 0x1316
20085         do_nodes $mdts $LCTL set_param fail_loc=0x1316
20086
20087         # generate more changelogs to trigger fail_loc
20088         createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
20089                 error "create $DIR/$tdir/${tfile}bis failed"
20090
20091         # stop MDT to stop GC-thread, should be done in back-ground as it will
20092         # block waiting for the thread to be released and exit
20093         declare -A stop_pids
20094         for ((i=1; i <= $MDSCOUNT; i++)); do
20095                 stop mds$i &
20096                 stop_pids[mds$i]=$!
20097         done
20098
20099         for mds in ${mdts//,/ }; do
20100                 local facet
20101                 local nb=0
20102                 local facets=$(facets_up_on_host $mds)
20103
20104                 for facet in ${facets//,/ }; do
20105                         if [[ $facet == mds* ]]; then
20106                                 nb=$((nb + 1))
20107                         fi
20108                 done
20109                 # ensure each MDS's gc threads are still present and all in "R"
20110                 # state (OBD_FAIL_FORCE_GC_THREAD effect!)
20111                 [[ $(do_node $mds pgrep chlg_gc_thread | wc -l) -eq $nb ]] ||
20112                         error "$mds: expected $nb GC-thread"
20113                 wait_update $mds \
20114                         "ps -C chlg_gc_thread -o state --no-headers | uniq" \
20115                         "R" 20 ||
20116                         error "$mds: GC-thread not found in R-state"
20117                 # check umounts of each MDT on MDS have reached kthread_stop()
20118                 [[ $(do_node $mds pgrep umount | wc -l) -eq $nb ]] ||
20119                         error "$mds: expected $nb umount"
20120                 wait_update $mds \
20121                         "ps -C umount -o state --no-headers | uniq" "D" 20 ||
20122                         error "$mds: umount not found in D-state"
20123         done
20124
20125         # release all GC-threads
20126         do_nodes $mdts $LCTL set_param fail_loc=0
20127
20128         # wait for MDT stop to complete
20129         for ((i=1; i <= $MDSCOUNT; i++)); do
20130                 wait ${stop_pids[mds$i]} || error "mds$i: stop failed"
20131         done
20132
20133         # XXX
20134         # may try to check if any orphan changelog records are present
20135         # via ldiskfs/zfs and llog_reader...
20136
20137         # re-start/mount MDTs
20138         for ((i=1; i <= $MDSCOUNT; i++)); do
20139                 start mds$i $(mdsdevname $i) $MDS_MOUNT_OPTS ||
20140                         error "Fail to start mds$i"
20141         done
20142
20143         local first_rec
20144         for ((i=1; i <= $MDSCOUNT; i++)); do
20145                 # check cl_user1 still registered
20146                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
20147                         error "mds$i: User ${cl_user1[mds$i]} not registered"
20148                 # check cl_user2 unregistered
20149                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
20150                         error "mds$i: User ${cl_user2[mds$i]} still registered"
20151
20152                 # check changelogs are present and starting at $user_rec1 + 1
20153                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
20154                 [ -n "$user_rec1" ] ||
20155                         error "mds$i: User ${cl_user1[mds$i]} not registered"
20156                 first_rec=$($LFS changelog $(facet_svc mds$i) |
20157                             awk '{ print $1; exit; }')
20158
20159                 echo "mds$i: verifying first index $user_rec1 + 1 == $first_rec"
20160                 [ $((user_rec1 + 1)) == $first_rec ] ||
20161                         error "mds$i: first index should be $user_rec1 + 1, " \
20162                               "but is $first_rec"
20163         done
20164 }
20165 run_test 160h "changelog gc thread stop upon umount, orphan records delete " \
20166               "during mount"
20167
20168 test_160i() {
20169         local mdts=$(mdts_nodes)
20170
20171         changelog_register || error "first changelog_register failed"
20172
20173         # generate some changelog records to accumulate on each MDT
20174         # use all_char because created files should be evenly distributed
20175         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
20176                 error "test_mkdir $tdir failed"
20177         for ((i = 0; i < MDSCOUNT; i++)); do
20178                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
20179                         error "create $DIR/$tdir/d$i.1 failed"
20180         done
20181
20182         # check changelogs have been generated
20183         local nbcl=$(changelog_dump | wc -l)
20184         [[ $nbcl -eq 0 ]] && error "no changelogs found"
20185
20186         # simulate race between register and unregister
20187         # XXX as fail_loc is set per-MDS, with DNE configs the race
20188         # simulation will only occur for one MDT per MDS and for the
20189         # others the normal race scenario will take place
20190         #define CFS_FAIL_CHLOG_USER_REG_UNREG_RACE          0x1315
20191         do_nodes $mdts $LCTL set_param fail_loc=0x10001315
20192         do_nodes $mdts $LCTL set_param fail_val=1
20193
20194         # unregister 1st user
20195         changelog_deregister &
20196         local pid1=$!
20197         # wait some time for deregister work to reach race rdv
20198         sleep 2
20199         # register 2nd user
20200         changelog_register || error "2nd user register failed"
20201
20202         wait $pid1 || error "1st user deregister failed"
20203
20204         local i
20205         local last_rec
20206         declare -A LAST_REC
20207         for ((i=1; i <= $MDSCOUNT; i++)); do
20208                 if changelog_users mds$i | grep "^cl"; then
20209                         # make sure new records are added with one user present
20210                         LAST_REC[mds$i]=$(changelog_users $SINGLEMDS |
20211                                           awk '/^current.index:/ { print $NF }')
20212                 else
20213                         error "mds$i has no user registered"
20214                 fi
20215         done
20216
20217         # generate more changelog records to accumulate on each MDT
20218         createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
20219                 error "create $DIR/$tdir/${tfile}bis failed"
20220
20221         for ((i=1; i <= $MDSCOUNT; i++)); do
20222                 last_rec=$(changelog_users $SINGLEMDS |
20223                            awk '/^current.index:/ { print $NF }')
20224                 echo "verify changelogs are on: $last_rec != ${LAST_REC[mds$i]}"
20225                 [ $last_rec != ${LAST_REC[mds$i]} ] ||
20226                         error "changelogs are off on mds$i"
20227         done
20228 }
20229 run_test 160i "changelog user register/unregister race"
20230
20231 test_160j() {
20232         remote_mds_nodsh && skip "remote MDS with nodsh"
20233         [[ $MDS1_VERSION -lt $(version_code 2.12.56) ]] &&
20234                 skip "Need MDS version at least 2.12.56"
20235
20236         mount_client $MOUNT2 || error "mount_client on $MOUNT2 failed"
20237         stack_trap "umount $MOUNT2" EXIT
20238
20239         changelog_register || error "first changelog_register failed"
20240         stack_trap "changelog_deregister" EXIT
20241
20242         # generate some changelog
20243         # use all_char because created files should be evenly distributed
20244         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
20245                 error "mkdir $tdir failed"
20246         for ((i = 0; i < MDSCOUNT; i++)); do
20247                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
20248                         error "create $DIR/$tdir/d$i.1 failed"
20249         done
20250
20251         # open the changelog device
20252         exec 3>/dev/changelog-$FSNAME-MDT0000
20253         stack_trap "exec 3>&-" EXIT
20254         exec 4</dev/changelog-$FSNAME-MDT0000
20255         stack_trap "exec 4<&-" EXIT
20256
20257         # umount the first lustre mount
20258         umount $MOUNT
20259         stack_trap "mount_client $MOUNT" EXIT
20260
20261         # read changelog, which may or may not fail, but should not crash
20262         cat <&4 >/dev/null
20263
20264         # clear changelog
20265         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
20266         changelog_users $SINGLEMDS | grep -q $cl_user ||
20267                 error "User $cl_user not found in changelog_users"
20268
20269         printf 'clear:'$cl_user':0' >&3
20270 }
20271 run_test 160j "client can be umounted while its chanangelog is being used"
20272
20273 test_160k() {
20274         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20275         remote_mds_nodsh && skip "remote MDS with nodsh"
20276
20277         mkdir -p $DIR/$tdir/1/1
20278
20279         changelog_register || error "changelog_register failed"
20280         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
20281
20282         changelog_users $SINGLEMDS | grep -q $cl_user ||
20283                 error "User '$cl_user' not found in changelog_users"
20284 #define OBD_FAIL_MDS_CHANGELOG_REORDER 0x15d
20285         do_facet mds1 $LCTL set_param fail_loc=0x8000015d fail_val=3
20286         rmdir $DIR/$tdir/1/1 & sleep 1
20287         mkdir $DIR/$tdir/2
20288         touch $DIR/$tdir/2/2
20289         rm -rf $DIR/$tdir/2
20290
20291         wait
20292         sleep 4
20293
20294         changelog_dump | grep rmdir || error "rmdir not recorded"
20295 }
20296 run_test 160k "Verify that changelog records are not lost"
20297
20298 # Verifies that a file passed as a parameter has recently had an operation
20299 # performed on it that has generated an MTIME changelog which contains the
20300 # correct parent FID. As files might reside on a different MDT from the
20301 # parent directory in DNE configurations, the FIDs are translated to paths
20302 # before being compared, which should be identical
20303 compare_mtime_changelog() {
20304         local file="${1}"
20305         local mdtidx
20306         local mtime
20307         local cl_fid
20308         local pdir
20309         local dir
20310
20311         mdtidx=$($LFS getstripe --mdt-index $file)
20312         mdtidx=$(printf "%04x" $mdtidx)
20313
20314         # Obtain the parent FID from the MTIME changelog
20315         mtime=$($LFS changelog $FSNAME-MDT$mdtidx | tail -n 1 | grep MTIME)
20316         [ -z "$mtime" ] && error "MTIME changelog not recorded"
20317
20318         cl_fid=$(sed -e 's/.* p=//' -e 's/ .*//' <<<$mtime)
20319         [ -z "$cl_fid" ] && error "parent FID not present"
20320
20321         # Verify that the path for the parent FID is the same as the path for
20322         # the test directory
20323         pdir=$($LFS fid2path $MOUNT "$cl_fid")
20324
20325         dir=$(dirname $1)
20326
20327         [[ "${pdir%/}" == "$dir" ]] ||
20328                 error "MTIME changelog parent FID is wrong, expected $dir, got $pdir"
20329 }
20330
20331 test_160l() {
20332         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20333
20334         remote_mds_nodsh && skip "remote MDS with nodsh"
20335         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
20336                 skip "Need MDS version at least 2.13.55"
20337
20338         local cl_user
20339
20340         changelog_register || error "changelog_register failed"
20341         cl_user="${CL_USERS[$SINGLEMDS]%% *}"
20342
20343         changelog_users $SINGLEMDS | grep -q $cl_user ||
20344                 error "User '$cl_user' not found in changelog_users"
20345
20346         # Clear some types so that MTIME changelogs are generated
20347         changelog_chmask "-CREAT"
20348         changelog_chmask "-CLOSE"
20349
20350         test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
20351
20352         # Test CL_MTIME during setattr
20353         touch $DIR/$tdir/$tfile
20354         compare_mtime_changelog $DIR/$tdir/$tfile
20355
20356         # Test CL_MTIME during close
20357         $MULTIOP $DIR/$tdir/${tfile}_2 O_2w4096c || error "multiop failed"
20358         compare_mtime_changelog $DIR/$tdir/${tfile}_2
20359 }
20360 run_test 160l "Verify that MTIME changelog records contain the parent FID"
20361
20362 test_160m() {
20363         remote_mds_nodsh && skip "remote MDS with nodsh" && return
20364         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
20365                 skip "Need MDS version at least 2.14.51"
20366         local cl_users
20367         local cl_user1
20368         local cl_user2
20369         local pid1
20370
20371         # Create a user
20372         changelog_register || error "first changelog_register failed"
20373         changelog_register || error "second changelog_register failed"
20374
20375         cl_users=(${CL_USERS[mds1]})
20376         cl_user1="${cl_users[0]}"
20377         cl_user2="${cl_users[1]}"
20378         # generate some changelog records to accumulate on MDT0
20379         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
20380         createmany -m $DIR/$tdir/$tfile 50 ||
20381                 error "create $DIR/$tdir/$tfile failed"
20382         unlinkmany $DIR/$tdir/$tfile 50 || error "unlinkmany failed"
20383         rm -f $DIR/$tdir
20384
20385         # check changelogs have been generated
20386         local nbcl=$(changelog_dump | wc -l)
20387         [[ $nbcl -eq 0 ]] && error "no changelogs found"
20388
20389 #define OBD_FAIL_MDS_CHANGELOG_RACE      0x15f
20390         do_facet mds1 $LCTL set_param fail_loc=0x8000015f fail_val=0
20391
20392         __changelog_clear mds1 $cl_user1 +10
20393         __changelog_clear mds1 $cl_user2 0 &
20394         pid1=$!
20395         sleep 2
20396         __changelog_clear mds1 $cl_user1 0 ||
20397                 error "fail to cancel record for $cl_user1"
20398         wait $pid1
20399         [[ $? -eq 0 ]] || error "fail to cancel record for $cl_user2"
20400 }
20401 run_test 160m "Changelog clear race"
20402
20403 test_160n() {
20404         remote_mds_nodsh && skip "remote MDS with nodsh" && return
20405         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
20406                 skip "Need MDS version at least 2.14.51"
20407         local cl_users
20408         local cl_user1
20409         local pid1
20410         local first_rec
20411         local last_rec=0
20412
20413         # Create a user
20414         changelog_register || error "first changelog_register failed"
20415
20416         cl_users=(${CL_USERS[mds1]})
20417         cl_user1="${cl_users[0]}"
20418
20419         # generate some changelog records to accumulate on MDT0
20420         test_mkdir -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
20421         first_rec=$(changelog_users $SINGLEMDS |
20422                         awk '/^current.index:/ { print $NF }')
20423         while (( last_rec < (( first_rec + 65000)) )); do
20424                 createmany -m $DIR/$tdir/$tfile 10000 ||
20425                         error "create $DIR/$tdir/$tfile failed"
20426
20427                 for i in $(seq 0 10000); do
20428                         mrename $DIR/$tdir/$tfile$i $DIR/$tdir/$tfile-new$i \
20429                                 > /dev/null
20430                 done
20431
20432                 unlinkmany $DIR/$tdir/$tfile-new 10000 ||
20433                         error "unlinkmany failed unlink"
20434                 last_rec=$(changelog_users $SINGLEMDS |
20435                         awk '/^current.index:/ { print $NF }')
20436                 echo last record $last_rec
20437                 (( last_rec == 0 )) && error "no changelog found"
20438         done
20439
20440 #define OBD_FAIL_MDS_CHANGELOG_DEL       0x16c
20441         do_facet mds1 $LCTL set_param fail_loc=0x8000016c fail_val=0
20442
20443         __changelog_clear mds1 $cl_user1 0 &
20444         pid1=$!
20445         sleep 2
20446         __changelog_clear mds1 $cl_user1 0 ||
20447                 error "fail to cancel record for $cl_user1 (forground)"
20448         wait $pid1
20449         [[ $? -eq 0 ]] || error "fail to cancel record for $cl_user1 (background)"
20450 }
20451 run_test 160n "Changelog destroy race"
20452
20453 test_160o() {
20454         local mdt="$(facet_svc $SINGLEMDS)"
20455
20456         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
20457         remote_mds_nodsh && skip "remote MDS with nodsh"
20458         [ $MDS1_VERSION -ge $(version_code 2.14.52) ] ||
20459                 skip "Need MDS version at least 2.14.52"
20460
20461         changelog_register --user test_160o -m unlnk+close+open ||
20462                 error "changelog_register failed"
20463
20464         do_facet $SINGLEMDS $LCTL --device $mdt \
20465                                 changelog_register -u "Tt3_-#" &&
20466                 error "bad symbols in name should fail"
20467
20468         do_facet $SINGLEMDS $LCTL --device $mdt \
20469                                 changelog_register -u test_160o &&
20470                 error "the same name registration should fail"
20471
20472         do_facet $SINGLEMDS $LCTL --device $mdt \
20473                         changelog_register -u test_160toolongname &&
20474                 error "too long name registration should fail"
20475
20476         changelog_chmask "MARK+HSM"
20477         lctl get_param mdd.*.changelog*mask
20478         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
20479         changelog_users $SINGLEMDS | grep -q $cl_user ||
20480                 error "User $cl_user not found in changelog_users"
20481         #verify username
20482         echo $cl_user | grep -q test_160o ||
20483                 error "User $cl_user has no specific name 'test160o'"
20484
20485         # change something
20486         changelog_clear 0 || error "changelog_clear failed"
20487         # generate some changelog records to accumulate on MDT0
20488         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
20489         touch $DIR/$tdir/$tfile                 # open 1
20490
20491         OPENS=$(changelog_dump | grep -c "OPEN")
20492         [[ $OPENS -eq 1 ]] || error "OPEN changelog mask count $OPENS != 1"
20493
20494         # must be no MKDIR it wasn't set as user mask
20495         MKDIR=$(changelog_dump | grep -c "MKDIR")
20496         [[ $MKDIR -eq 0 ]] || error "MKDIR changelog mask found $MKDIR > 0"
20497
20498         oldmask=$(do_facet $SINGLEMDS $LCTL get_param \
20499                                 mdd.$mdt.changelog_current_mask -n)
20500         # register maskless user
20501         changelog_register || error "changelog_register failed"
20502         # effective mask should be not changed because it is not minimal
20503         mask=$(do_facet $SINGLEMDS $LCTL get_param \
20504                                 mdd.$mdt.changelog_current_mask -n)
20505         [[ $mask == $oldmask ]] || error "mask was changed: $mask vs $oldmask"
20506         # set server mask to minimal value
20507         changelog_chmask "MARK"
20508         # check effective mask again, should be treated as DEFMASK now
20509         mask=$(do_facet $SINGLEMDS $LCTL get_param \
20510                                 mdd.$mdt.changelog_current_mask -n)
20511         [[ $mask == *"HLINK"* ]] || error "mask is not DEFMASK as expected"
20512
20513         if (( $MDS1_VERSION >= $(version_code 2.15.52) )) ; then
20514                 # set server mask back to some value
20515                 changelog_chmask "CLOSE,UNLNK"
20516                 # check effective mask again, should not remain as DEFMASK
20517                 mask=$(do_facet $SINGLEMDS $LCTL get_param \
20518                                 mdd.$mdt.changelog_current_mask -n)
20519                 [[ $mask != *"HLINK"* ]] || error "mask is still DEFMASK"
20520         fi
20521
20522         do_facet $SINGLEMDS $LCTL --device $mdt \
20523                                 changelog_deregister -u test_160o ||
20524                 error "cannot deregister by name"
20525 }
20526 run_test 160o "changelog user name and mask"
20527
20528 test_160p() {
20529         remote_mds_nodsh && skip "remote MDS with nodsh" && return
20530         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
20531                 skip "Need MDS version at least 2.14.51"
20532         [[ "$mds1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
20533         local cl_users
20534         local cl_user1
20535         local entry_count
20536
20537         # Create a user
20538         changelog_register || error "first changelog_register failed"
20539
20540         cl_users=(${CL_USERS[mds1]})
20541         cl_user1="${cl_users[0]}"
20542
20543         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
20544         createmany -m $DIR/$tdir/$tfile 50 ||
20545                 error "create $DIR/$tdir/$tfile failed"
20546         unlinkmany $DIR/$tdir/$tfile 50 || error "unlinkmany failed"
20547         rm -rf $DIR/$tdir
20548
20549         # check changelogs have been generated
20550         entry_count=$(changelog_dump | wc -l)
20551         ((entry_count != 0)) || error "no changelog entries found"
20552
20553         # remove changelog_users and check that orphan entries are removed
20554         stop mds1
20555         local dev=$(mdsdevname 1)
20556         do_facet mds1 "$DEBUGFS -w -R 'rm changelog_users' $dev"
20557         start mds1 $dev $MDS_MOUNT_OPTS || error "cannot start mds1"
20558         entry_count=$(changelog_dump | wc -l)
20559         ((entry_count == 0)) ||
20560                 error "found $entry_count changelog entries, expected none"
20561 }
20562 run_test 160p "Changelog orphan cleanup with no users"
20563
20564 test_160q() {
20565         local mdt="$(facet_svc $SINGLEMDS)"
20566         local clu
20567
20568         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
20569         remote_mds_nodsh && skip "remote MDS with nodsh"
20570         [ $MDS1_VERSION -ge $(version_code 2.14.54) ] ||
20571                 skip "Need MDS version at least 2.14.54"
20572
20573         # set server mask to minimal value like server init does
20574         changelog_chmask "MARK"
20575         clu=$(do_facet $SINGLEMDS $LCTL --device $mdt changelog_register -n) ||
20576                 error "changelog_register failed"
20577         # check effective mask again, should be treated as DEFMASK now
20578         mask=$(do_facet $SINGLEMDS $LCTL get_param \
20579                                 mdd.$mdt.changelog_current_mask -n)
20580         do_facet $SINGLEMDS $LCTL --device $mdt changelog_deregister $clu ||
20581                 error "changelog_deregister failed"
20582         [[ $mask == *"HLINK"* ]] || error "mask is not DEFMASK as expected"
20583 }
20584 run_test 160q "changelog effective mask is DEFMASK if not set"
20585
20586 test_160s() {
20587         remote_mds_nodsh && skip "remote MDS with nodsh"
20588         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
20589                 skip "Need MDS version at least 2.14.55"
20590
20591         local mdts=$(mdts_nodes)
20592
20593         #define OBD_FAIL_TIME_IN_CHLOG_USER     0x1314
20594         do_nodes $mdts $LCTL set_param fail_loc=0x1314 \
20595                                        fail_val=$((24 * 3600 * 10))
20596
20597         # Create a user which is 10 days old
20598         changelog_register || error "first changelog_register failed"
20599         local cl_users
20600         declare -A cl_user1
20601         local i
20602
20603         # generate some changelog records to accumulate on each MDT
20604         # use all_char because created files should be evenly distributed
20605         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
20606                 error "test_mkdir $tdir failed"
20607         for ((idx = 0; idx < MDSCOUNT; idx++)); do
20608                 $LFS mkdir -i $idx $DIR/$tdir/d$idx.1 $DIR/$tdir/d$idx.2 ||
20609                         error "create $DIR/$tdir/d$idx.1 on MDT$idx failed"
20610         done
20611
20612         # check changelogs have been generated
20613         local nbcl=$(changelog_dump | wc -l)
20614         (( nbcl > 0 )) || error "no changelogs found"
20615
20616         # reduce the max_idle_indexes value to make sure we exceed it
20617         for param in "changelog_max_idle_indexes=2097446912" \
20618                      "changelog_max_idle_time=2592000" \
20619                      "changelog_gc=1" \
20620                      "changelog_min_gc_interval=2"; do
20621                 local MDT0=$(facet_svc $SINGLEMDS)
20622                 local var="${param%=*}"
20623                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
20624
20625                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
20626                 do_nodes $mdts $LCTL set_param mdd.*.$param ||
20627                         error "unable to set mdd.*.$param"
20628         done
20629
20630         local start=$SECONDS
20631         for ((i=1; i <= $MDSCOUNT; i++)); do
20632                 cl_users=(${CL_USERS[mds$i]})
20633                 cl_user1[mds$i]="${cl_users[0]}"
20634
20635                 [[ -n "${cl_user1[mds$i]}" ]] ||
20636                         error "mds$i: no user registered"
20637         done
20638
20639         #define OBD_FAIL_MDS_CHANGELOG_IDX_PUMP   0x16d
20640         do_nodes $mdts $LCTL set_param fail_loc=0x16d fail_val=500000000
20641
20642         # ensure we are past the previous changelog_min_gc_interval set above
20643         local sleep2=$((start + 2 - SECONDS))
20644         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
20645
20646         # Generate one more changelog to trigger GC
20647         for ((i = 0; i < MDSCOUNT; i++)); do
20648                 $LFS mkdir -i $i $DIR/$tdir/d$i.3 $DIR/$tdir/d$i.4 ||
20649                         error "create $DIR/$tdir/d$i.3 failed"
20650         done
20651
20652         # ensure gc thread is done
20653         for mds in ${mdts//,/ }; do
20654                 wait_update $mds "pgrep chlg_gc_thread" "" 20 ||
20655                         error "$mds: GC-thread not done"
20656         done
20657
20658         do_nodes $mdts $LCTL set_param fail_loc=0
20659
20660         for ((i = 1; i <= MDSCOUNT; i++)); do
20661                 # check cl_user1 is purged
20662                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" &&
20663                         error "mds$i: User ${cl_user1[mds$i]} is registered"
20664         done
20665         return 0
20666 }
20667 run_test 160s "changelog garbage collect on idle records * time"
20668
20669 test_160t() {
20670         remote_mds_nodsh && skip "remote MDS with nodsh"
20671         (( $MDS1_VERSION >= $(version_code 2.15.50) )) ||
20672                 skip "Need MDS version at least 2.15.50"
20673
20674         local MDT0=$(facet_svc $SINGLEMDS)
20675         local cl_users
20676         local cl_user1
20677         local cl_user2
20678         local start
20679
20680         changelog_register --user user1 -m all ||
20681                 error "user1 failed to register"
20682
20683         mkdir_on_mdt0 $DIR/$tdir
20684         # create default overstripe to maximize changelog size
20685         $LFS setstripe  -C 8 $DIR/$tdir || error "setstripe failed"
20686         createmany -o $DIR/$tdir/u1_ 2000 || error "createmany for user1 failed"
20687         stack_trap "unlinkmany $DIR/$tdir/u1_ 2000"
20688         llog_size1=$(do_facet mds1 $LCTL get_param -n mdd.$MDT0.changelog_size)
20689
20690         # user2 consumes less records so less space
20691         changelog_register --user user2 || error "user2 failed to register"
20692         createmany -o $DIR/$tdir/u2_ 500 || error "createmany for user2 failed"
20693         llog_size2=$(do_facet mds1 $LCTL get_param -n mdd.$MDT0.changelog_size)
20694
20695         # check changelogs have been generated
20696         local nbcl=$(changelog_dump | wc -l)
20697         (( nbcl > 0 )) || error "no changelogs found"
20698
20699         # reduce the changelog_min_gc_interval to force check
20700         for param in "changelog_gc=1" "changelog_min_gc_interval=2"; do
20701                 local var="${param%=*}"
20702                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
20703
20704                 stack_trap "do_facet mds1 $LCTL set_param mdd.$MDT0.$var=$old"
20705                 do_facet mds1 $LCTL set_param mdd.$MDT0.$param ||
20706                         error "unable to set mdd.*.$param"
20707         done
20708
20709         start=$SECONDS
20710         cl_users=(${CL_USERS[mds1]})
20711         cl_user1="${cl_users[0]}"
20712         cl_user2="${cl_users[1]}"
20713
20714         [[ -n $cl_user1 ]] ||
20715                 error "mds1: user #1 isn't registered"
20716         [[ -n $cl_user2 ]] ||
20717                 error "mds1: user #2 isn't registered"
20718
20719         # ensure we are past the previous changelog_min_gc_interval set above
20720         local sleep2=$((start + 2 - SECONDS))
20721         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
20722
20723         #define OBD_FAIL_MDS_CHANGELOG_ENOSPC 0x018c
20724         do_facet mds1 $LCTL set_param fail_loc=0x018c \
20725                         fail_val=$(((llog_size1 + llog_size2) / 2))
20726
20727         # Generate more changelog to trigger GC
20728         createmany -o $DIR/$tdir/u3_ 4 ||
20729                 error "create failed for more files"
20730
20731         # ensure gc thread is done
20732         wait_update_facet mds1 "pgrep chlg_gc_thread" "" 20 ||
20733                 error "mds1: GC-thread not done"
20734
20735         do_facet mds1 $LCTL set_param fail_loc=0
20736
20737         # check cl_user1 is purged
20738         changelog_users mds1 | grep -q "$cl_user1" &&
20739                 error "User $cl_user1 is registered"
20740         # check cl_user2 is not purged
20741         changelog_users mds1 | grep -q "$cl_user2" ||
20742                 error "User $cl_user2 is not registered"
20743 }
20744 run_test 160t "changelog garbage collect on lack of space"
20745
20746 test_160u() { # LU-17400
20747         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20748         remote_mds_nodsh && skip "remote MDS with nodsh"
20749         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
20750                 skip "Need MDS version at least 2.2.0"
20751
20752         cd $DIR || error "cd $DIR failed"
20753
20754         # ensure changelog has a clean view if tests are run multiple times
20755         [ -d rename ] && rm -rf rename
20756
20757         changelog_register || error "changelog_register failed"
20758         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
20759
20760         changelog_users $SINGLEMDS | grep -q $cl_user ||
20761                 error "User '$cl_user' not found in changelog_users"
20762
20763         local longname1=$(str_repeat a 255)
20764
20765         echo "creating simple directory tree"
20766         mkdir -p rename/a || error "create of simple directory tree failed"
20767         echo "creating rename/hw file"
20768         echo "hello world" > rename/hw || error "create of rename/hw failed"
20769         echo "creating very long named file"
20770         touch rename/$longname1 || error "create of 'rename/$longname1' failed"
20771         echo "move rename/hw to rename/a/a.hw"
20772         mv rename/hw rename/a/a.hw || error "mv failed"
20773
20774         RENME=($(changelog_dump | grep "RENME"))
20775         #declare -p RENME # for debugging captured value with indexes
20776
20777         [[ "${RENME[11]}" == "a.hw" && "${RENME[14]}" == "hw" ]] ||
20778                 error "changelog rename record type name/sname error"
20779 }
20780 run_test 160u "changelog rename record type name and sname strings are correct"
20781
20782 test_161a() {
20783         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20784
20785         test_mkdir -c1 $DIR/$tdir
20786         cp /etc/hosts $DIR/$tdir/$tfile
20787         test_mkdir -c1 $DIR/$tdir/foo1
20788         test_mkdir -c1 $DIR/$tdir/foo2
20789         ln $DIR/$tdir/$tfile $DIR/$tdir/foo1/sofia
20790         ln $DIR/$tdir/$tfile $DIR/$tdir/foo2/zachary
20791         ln $DIR/$tdir/$tfile $DIR/$tdir/foo1/luna
20792         ln $DIR/$tdir/$tfile $DIR/$tdir/foo2/thor
20793         local FID=$($LFS path2fid $DIR/$tdir/$tfile | tr -d '[]')
20794         if [ "$($LFS fid2path $DIR $FID | wc -l)" != "5" ]; then
20795                 $LFS fid2path $DIR $FID
20796                 error "bad link ea"
20797         fi
20798         # middle
20799         rm $DIR/$tdir/foo2/zachary
20800         # last
20801         rm $DIR/$tdir/foo2/thor
20802         # first
20803         rm $DIR/$tdir/$tfile
20804         # rename
20805         mv $DIR/$tdir/foo1/sofia $DIR/$tdir/foo2/maggie
20806         [ "$($LFS fid2path $FSNAME --link 1 $FID)" != "$tdir/foo2/maggie" ] &&
20807                 { $LFS fid2path $DIR $FID; error "bad link rename"; }
20808         rm $DIR/$tdir/foo2/maggie
20809
20810         # overflow the EA
20811         local longname=$tfile.avg_len_is_thirty_two_
20812         stack_trap "unlinkmany $DIR/$tdir/foo2/$longname 1000 || \
20813                 error_noexit 'failed to unlink many hardlinks'" EXIT
20814         createmany -l$DIR/$tdir/foo1/luna $DIR/$tdir/foo2/$longname 1000 ||
20815                 error "failed to hardlink many files"
20816         links=$($LFS fid2path $DIR $FID | wc -l)
20817         echo -n "${links}/1000 links in link EA"
20818         [[ $links -gt 60 ]] || error "expected at least 60 links in link EA"
20819 }
20820 run_test 161a "link ea sanity"
20821
20822 test_161b() {
20823         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20824         [ $MDSCOUNT -lt 2 ] && skip_env "skipping remote directory test"
20825
20826         local MDTIDX=1
20827         local remote_dir=$DIR/$tdir/remote_dir
20828
20829         mkdir -p $DIR/$tdir
20830         $LFS mkdir -i $MDTIDX $remote_dir ||
20831                 error "create remote directory failed"
20832
20833         cp /etc/hosts $remote_dir/$tfile
20834         mkdir -p $remote_dir/foo1
20835         mkdir -p $remote_dir/foo2
20836         ln $remote_dir/$tfile $remote_dir/foo1/sofia
20837         ln $remote_dir/$tfile $remote_dir/foo2/zachary
20838         ln $remote_dir/$tfile $remote_dir/foo1/luna
20839         ln $remote_dir/$tfile $remote_dir/foo2/thor
20840
20841         local FID=$($LFS path2fid $remote_dir/$tfile | tr -d '[' |
20842                      tr -d ']')
20843         if [ "$($LFS fid2path $DIR $FID | wc -l)" != "5" ]; then
20844                 $LFS fid2path $DIR $FID
20845                 error "bad link ea"
20846         fi
20847         # middle
20848         rm $remote_dir/foo2/zachary
20849         # last
20850         rm $remote_dir/foo2/thor
20851         # first
20852         rm $remote_dir/$tfile
20853         # rename
20854         mv $remote_dir/foo1/sofia $remote_dir/foo2/maggie
20855         local link_path=$($LFS fid2path $FSNAME --link 1 $FID)
20856         if [ "$DIR/$link_path" != "$remote_dir/foo2/maggie" ]; then
20857                 $LFS fid2path $DIR $FID
20858                 error "bad link rename"
20859         fi
20860         rm $remote_dir/foo2/maggie
20861
20862         # overflow the EA
20863         local longname=filename_avg_len_is_thirty_two_
20864         createmany -l$remote_dir/foo1/luna $remote_dir/foo2/$longname 1000 ||
20865                 error "failed to hardlink many files"
20866         links=$($LFS fid2path $DIR $FID | wc -l)
20867         echo -n "${links}/1000 links in link EA"
20868         [[ ${links} -gt 60 ]] ||
20869                 error "expected at least 60 links in link EA"
20870         unlinkmany $remote_dir/foo2/$longname 1000 ||
20871         error "failed to unlink many hardlinks"
20872 }
20873 run_test 161b "link ea sanity under remote directory"
20874
20875 test_161c() {
20876         remote_mds_nodsh && skip "remote MDS with nodsh"
20877         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20878         [[ $MDS1_VERSION -lt $(version_code 2.1.5) ]] &&
20879                 skip "Need MDS version at least 2.1.5"
20880
20881         # define CLF_RENAME_LAST 0x0001
20882         # rename overwrite a target having nlink = 1 (changelog flag 0x1)
20883         changelog_register || error "changelog_register failed"
20884
20885         rm -rf $DIR/$tdir
20886         test_mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir
20887         touch $DIR/$tdir/foo_161c
20888         touch $DIR/$tdir/bar_161c
20889         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/bar_161c
20890         changelog_dump | grep RENME | tail -n 5
20891         local flags=$(changelog_dump | grep "RENME.*bar_161c" | cut -f5 -d' ')
20892         changelog_clear 0 || error "changelog_clear failed"
20893         if [ x$flags != "x0x1" ]; then
20894                 error "flag $flags is not 0x1"
20895         fi
20896
20897         echo "rename overwrite target with nlink = 1, changelog flags=$flags"
20898         # rename overwrite a target having nlink > 1 (changelog flag 0x0)
20899         touch $DIR/$tdir/foo_161c
20900         touch $DIR/$tdir/bar_161c
20901         ln $DIR/$tdir/bar_161c $DIR/$tdir/foobar_161c
20902         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/bar_161c
20903         changelog_dump | grep RENME | tail -n 5
20904         flags=$(changelog_dump | grep "RENME.*bar_161c" | cut -f5 -d' ')
20905         changelog_clear 0 || error "changelog_clear failed"
20906         if [ x$flags != "x0x0" ]; then
20907                 error "flag $flags is not 0x0"
20908         fi
20909         echo "rename overwrite a target having nlink > 1," \
20910                 "changelog record has flags of $flags"
20911
20912         # rename doesn't overwrite a target (changelog flag 0x0)
20913         touch $DIR/$tdir/foo_161c
20914         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/foo2_161c
20915         changelog_dump | grep RENME | tail -n 5
20916         flags=$(changelog_dump | grep RENME | tail -1 | cut -f5 -d' ')
20917         changelog_clear 0 || error "changelog_clear failed"
20918         if [ x$flags != "x0x0" ]; then
20919                 error "flag $flags is not 0x0"
20920         fi
20921         echo "rename doesn't overwrite a target," \
20922                 "changelog record has flags of $flags"
20923
20924         # define CLF_UNLINK_LAST 0x0001
20925         # unlink a file having nlink = 1 (changelog flag 0x1)
20926         rm -f $DIR/$tdir/foo2_161c
20927         changelog_dump | grep UNLNK | tail -n 5
20928         flags=$(changelog_dump | grep UNLNK | tail -1 | cut -f5 -d' ')
20929         changelog_clear 0 || error "changelog_clear failed"
20930         if [ x$flags != "x0x1" ]; then
20931                 error "flag $flags is not 0x1"
20932         fi
20933         echo "unlink a file having nlink = 1," \
20934                 "changelog record has flags of $flags"
20935
20936         # unlink a file having nlink > 1 (changelog flag 0x0)
20937         ln -f $DIR/$tdir/bar_161c $DIR/$tdir/foobar_161c
20938         rm -f $DIR/$tdir/foobar_161c
20939         changelog_dump | grep UNLNK | tail -n 5
20940         flags=$(changelog_dump | grep UNLNK | tail -1 | cut -f5 -d' ')
20941         changelog_clear 0 || error "changelog_clear failed"
20942         if [ x$flags != "x0x0" ]; then
20943                 error "flag $flags is not 0x0"
20944         fi
20945         echo "unlink a file having nlink > 1, changelog record flags '$flags'"
20946
20947         (( MDS1_VERSION >= $(version_code v2_16_53-39) )) ||
20948                 { echo "CLF_UNLINK_LAST is not set with open file (LU-18860)";
20949                 return 0; }
20950
20951         # unlink a file open having nlink = 1 (changelog flag 0x1)
20952         local pid
20953         touch $DIR/$tdir/open_161c
20954         tail -f $DIR/$tdir/open_161c & pid=$!
20955         sleep 0.2
20956         unlink $DIR/$tdir/open_161c
20957         kill $pid
20958         changelog_dump | grep UNLNK | tail -n 5
20959         flags=$(changelog_dump | awk '/UNLNK/ {f=$5} END {print f}')
20960         changelog_clear 0 || error "changelog_clear failed"
20961         [[ "$flags" == "0x1" ]] || error "flag $flags is not 0x1"
20962         echo "unlink a open file having nlink = 1, changelog record has flags of $flags"
20963 }
20964 run_test 161c "check CL_RENME[UNLINK] changelog record flags"
20965
20966 test_161d() {
20967         remote_mds_nodsh && skip "remote MDS with nodsh"
20968
20969         local pid
20970         local fid
20971
20972         changelog_register || error "changelog_register failed"
20973
20974         # work in a standalone dir to avoid locking on $DIR/$MOUNT to
20975         # interfer with $MOUNT/.lustre/fid/ access
20976         mkdir $DIR/$tdir
20977         [[ $? -eq 0 ]] || error "mkdir failed"
20978
20979         #define OBD_FAIL_LLITE_CREATE_NODE_PAUSE 0x140c | CFS_FAIL_ONCE
20980         $LCTL set_param fail_loc=0x8000140c
20981         # 5s pause
20982         $LCTL set_param fail_val=5
20983
20984         # create file
20985         echo foofoo > $DIR/$tdir/$tfile &
20986         pid=$!
20987
20988         # wait for create to be delayed
20989         sleep 2
20990
20991         ps -p $pid
20992         [[ $? -eq 0 ]] || error "create should be blocked"
20993
20994         local tempfile="$(mktemp --tmpdir $tfile.XXXXXX)"
20995         stack_trap "rm -f $tempfile"
20996         fid=$(changelog_extract_field "CREAT" "$tfile" "t=")
20997         $MULTIOP $MOUNT/.lustre/fid/$fid orp16384c >$tempfile || error "read failed"
20998         # some delay may occur during ChangeLog publishing and file read just
20999         # above, that could allow file write to happen finally
21000         [[ -s $tempfile ]] && echo "file should be empty"
21001
21002         $LCTL set_param fail_loc=0
21003
21004         wait $pid
21005         [[ $? -eq 0 ]] || error "create failed"
21006 }
21007 run_test 161d "create with concurrent .lustre/fid access"
21008
21009 check_path() {
21010         local expected="$1"
21011         shift
21012         local fid="$2"
21013
21014         local path
21015         path=$($LFS fid2path "$@")
21016         local rc=$?
21017
21018         if [ $rc -ne 0 ]; then
21019                 error "path looked up of '$expected' failed: rc=$rc"
21020         elif [ "$path" != "$expected" ]; then
21021                 error "path looked up '$path' instead of '$expected'"
21022         else
21023                 echo "FID '$fid' resolves to path '$path' as expected"
21024         fi
21025 }
21026
21027 test_162a() { # was test_162
21028         test_mkdir -p -c1 $DIR/$tdir/d2
21029         touch $DIR/$tdir/d2/$tfile
21030         touch $DIR/$tdir/d2/x1
21031         touch $DIR/$tdir/d2/x2
21032         test_mkdir -p -c1 $DIR/$tdir/d2/a/b/c
21033         test_mkdir -p -c1 $DIR/$tdir/d2/p/q/r
21034         # regular file
21035         local fid=$($LFS path2fid $DIR/$tdir/d2/$tfile | tr -d '[]')
21036         check_path "$tdir/d2/$tfile" $FSNAME "$fid" --link 0
21037
21038         # softlink
21039         ln -s $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/p/q/r/slink
21040         fid=$($LFS path2fid $DIR/$tdir/d2/p/q/r/slink | tr -d '[]')
21041         check_path "$tdir/d2/p/q/r/slink" $FSNAME "$fid" --link 0
21042
21043         # softlink to wrong file
21044         ln -s /this/is/garbage $DIR/$tdir/d2/p/q/r/slink.wrong
21045         fid=$($LFS path2fid $DIR/$tdir/d2/p/q/r/slink.wrong | tr -d '[]')
21046         check_path "$tdir/d2/p/q/r/slink.wrong" $FSNAME "$fid" --link 0
21047
21048         # hardlink
21049         ln $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/p/q/r/hlink
21050         mv $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/a/b/c/new_file
21051         fid=$($LFS path2fid $DIR/$tdir/d2/a/b/c/new_file | tr -d '[]')
21052         # fid2path dir/fsname should both work
21053         check_path "$tdir/d2/a/b/c/new_file" $FSNAME "$fid" --link 1
21054         check_path "$DIR/$tdir/d2/p/q/r/hlink" $DIR "$fid" --link 0
21055
21056         # hardlink count: check that there are 2 links
21057         local nlinks=$($LFS fid2path $DIR "$fid" | wc -l)
21058         [ $nlinks -eq 2 ] || error "expect 2 links, found $nlinks"
21059
21060         # hardlink indexing: remove the first link
21061         rm $DIR/$tdir/d2/p/q/r/hlink
21062         check_path "$tdir/d2/a/b/c/new_file" $FSNAME $fid --link 0
21063 }
21064 run_test 162a "path lookup sanity"
21065
21066 test_162b() {
21067         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21068         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
21069
21070         mkdir $DIR/$tdir
21071         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
21072                                 error "create striped dir failed"
21073
21074         local FID=$($LFS getdirstripe $DIR/$tdir/striped_dir |
21075                                         tail -n 1 | awk '{print $2}')
21076         stat $MOUNT/.lustre/fid/$FID && error "sub_stripe can be accessed"
21077
21078         touch $DIR/$tdir/striped_dir/f{0..4} || error "touch f0..4 failed"
21079         mkdir $DIR/$tdir/striped_dir/d{0..4} || error "mkdir d0..4 failed"
21080
21081         # regular file
21082         for ((i=0;i<5;i++)); do
21083                 FID=$($LFS path2fid $DIR/$tdir/striped_dir/f$i | tr -d '[]') ||
21084                         error "get fid for f$i failed"
21085                 check_path "$tdir/striped_dir/f$i" $FSNAME $FID --link 0
21086
21087                 FID=$($LFS path2fid $DIR/$tdir/striped_dir/d$i | tr -d '[]') ||
21088                         error "get fid for d$i failed"
21089                 check_path "$tdir/striped_dir/d$i" $FSNAME $FID --link 0
21090         done
21091
21092         return 0
21093 }
21094 run_test 162b "striped directory path lookup sanity"
21095
21096 # LU-4239: Verify fid2path works with paths 100 or more directories deep
21097 test_162c() {
21098         [[ $MDS1_VERSION -lt $(version_code 2.7.51) ]] &&
21099                 skip "Need MDS version at least 2.7.51"
21100
21101         local lpath=$tdir.local
21102         local rpath=$tdir.remote
21103
21104         test_mkdir $DIR/$lpath
21105         test_mkdir $DIR/$rpath
21106         stack_trap "rm -rf $DIR/$lpath $DIR/$rpath"
21107
21108         for ((i = 0; i <= 101; i++)); do
21109                 lpath="$lpath/$i"
21110                 mkdir $DIR/$lpath
21111                 FID=$($LFS path2fid $DIR/$lpath | tr -d '[]') ||
21112                         error "get fid for local directory $DIR/$lpath failed"
21113                 check_path "$DIR/$lpath" $MOUNT $FID --link 0
21114
21115                 rpath="$rpath/$i"
21116                 test_mkdir $DIR/$rpath
21117                 FID=$($LFS path2fid $DIR/$rpath | tr -d '[]') ||
21118                         error "get fid for remote directory $DIR/$rpath failed"
21119                 check_path "$DIR/$rpath" $MOUNT $FID --link 0
21120         done
21121
21122         return 0
21123 }
21124 run_test 162c "fid2path works with paths 100 or more directories deep"
21125
21126 oalr_event_count() {
21127         local event="${1}"
21128         local trace="${2}"
21129
21130         awk -v name="${FSNAME}-OST0000" \
21131             -v event="${event}" \
21132             '$1 == "TRACE" && $2 == event && $3 == name' \
21133             "${trace}" |
21134         wc -l
21135 }
21136
21137 oalr_expect_event_count() {
21138         local event="${1}"
21139         local trace="${2}"
21140         local expect="${3}"
21141         local count
21142
21143         count=$(oalr_event_count "${event}" "${trace}")
21144         if ((count == expect)); then
21145                 return 0
21146         fi
21147
21148         error_noexit "${event} event count was '${count}', expected ${expect}"
21149         cat "${trace}" >&2
21150         exit 1
21151 }
21152
21153 cleanup_165() {
21154         do_facet ost1 killall --quiet -KILL ofd_access_log_reader || true
21155         stop ost1
21156         start ost1 "$(ostdevname 1)" $OST_MOUNT_OPTS
21157 }
21158
21159 setup_165() {
21160         sync # Flush previous IOs so we can count log entries.
21161         do_facet ost1 $LCTL set_param "obdfilter.${FSNAME}-OST0000.access_log_size=4096"
21162         stack_trap cleanup_165 EXIT
21163 }
21164
21165 test_165a() {
21166         local trace="/tmp/${tfile}.trace"
21167         local rc
21168         local count
21169
21170         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
21171                 skip "OFD access log unsupported"
21172
21173         setup_165
21174         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
21175         sleep 5
21176
21177         do_facet ost1 ofd_access_log_reader --list
21178         stop ost1
21179
21180         do_facet ost1 killall -TERM ofd_access_log_reader
21181         wait
21182         rc=$?
21183
21184         if ((rc != 0)); then
21185                 error "ofd_access_log_reader exited with rc = '${rc}'"
21186         fi
21187
21188         # Parse trace file for discovery events:
21189         oalr_expect_event_count alr_log_add "${trace}" 1
21190         oalr_expect_event_count alr_log_eof "${trace}" 1
21191         oalr_expect_event_count alr_log_free "${trace}" 1
21192 }
21193 run_test 165a "ofd access log discovery"
21194
21195 test_165b() {
21196         local trace="/tmp/${tfile}.trace"
21197         local file="${DIR}/${tfile}"
21198         local pfid1
21199         local pfid2
21200         local -a entry
21201         local rc
21202         local count
21203         local size
21204         local flags
21205
21206         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
21207                 skip "OFD access log unsupported"
21208
21209         setup_165
21210         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
21211         sleep 5
21212
21213         do_facet ost1 ofd_access_log_reader --list
21214
21215         lfs setstripe -c 1 -i 0 "${file}"
21216         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
21217                 error "cannot create '${file}'"
21218
21219         sleep 5
21220         do_facet ost1 killall -TERM ofd_access_log_reader
21221         wait
21222         rc=$?
21223
21224         if ((rc != 0)); then
21225                 error "ofd_access_log_reader exited with rc = '${rc}'"
21226         fi
21227
21228         oalr_expect_event_count alr_log_entry "${trace}" 1
21229
21230         pfid1=$($LFS path2fid "${file}")
21231
21232         # 1     2             3   4    5     6   7    8    9     10
21233         # TRACE alr_log_entry OST PFID BEGIN END TIME SIZE COUNT FLAGS
21234         entry=( - $(awk -v pfid="${pfid}" '$1 == "TRACE" && $2 == "alr_log_entry"' "${trace}" ) )
21235
21236         echo "entry = '${entry[*]}'" >&2
21237
21238         pfid2=${entry[4]}
21239         if [[ "${pfid1}" != "${pfid2}" ]]; then
21240                 error "entry '${entry[*]}' has invalid PFID '${pfid2}', expected ${pfid1}"
21241         fi
21242
21243         size=${entry[8]}
21244         if ((size != 1048576)); then
21245                 error "entry '${entry[*]}' has invalid io size '${size}', expected 1048576"
21246         fi
21247
21248         flags=${entry[10]}
21249         if [[ "${flags}" != "w" ]]; then
21250                 error "entry '${entry[*]}' has invalid io flags '${flags}', expected 'w'"
21251         fi
21252
21253         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
21254         sleep 5
21255
21256         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r524288c ||
21257                 error "cannot read '${file}'"
21258         sleep 5
21259
21260         do_facet ost1 killall -TERM ofd_access_log_reader
21261         wait
21262         rc=$?
21263
21264         if ((rc != 0)); then
21265                 error "ofd_access_log_reader exited with rc = '${rc}'"
21266         fi
21267
21268         oalr_expect_event_count alr_log_entry "${trace}" 1
21269
21270         entry=( - $(awk -v pfid="${pfid}" '$1 == "TRACE" && $2 == "alr_log_entry"' "${trace}" ) )
21271         echo "entry = '${entry[*]}'" >&2
21272
21273         pfid2=${entry[4]}
21274         if [[ "${pfid1}" != "${pfid2}" ]]; then
21275                 error "entry '${entry[*]}' has invalid PFID '${pfid2}', expected ${pfid1}"
21276         fi
21277
21278         size=${entry[8]}
21279         if ((size != 524288)); then
21280                 error "entry '${entry[*]}' has invalid io size '${size}', 524288"
21281         fi
21282
21283         flags=${entry[10]}
21284         if [[ "${flags}" != "r" ]]; then
21285                 error "entry '${entry[*]}' has invalid io flags '${flags}', expected 'r'"
21286         fi
21287 }
21288 run_test 165b "ofd access log entries are produced and consumed"
21289
21290 test_165c() {
21291         local trace="/tmp/${tfile}.trace"
21292         local file="${DIR}/${tdir}/${tfile}"
21293
21294         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
21295                 skip "OFD access log unsupported"
21296
21297         test_mkdir "${DIR}/${tdir}"
21298
21299         setup_165
21300         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
21301         sleep 5
21302
21303         lfs setstripe -c 1 -i 0 "${DIR}/${tdir}"
21304
21305         # 4096 / 64 = 64. Create twice as many entries.
21306         for ((i = 0; i < 128; i++)); do
21307                 $MULTIOP "${file}-${i}" oO_CREAT:O_WRONLY:w512c ||
21308                         error "cannot create file"
21309         done
21310
21311         sync
21312
21313         do_facet ost1 killall -TERM ofd_access_log_reader
21314         wait
21315         rc=$?
21316         if ((rc != 0)); then
21317                 error "ofd_access_log_reader exited with rc = '${rc}'"
21318         fi
21319
21320         unlinkmany  "${file}-%d" 128
21321 }
21322 run_test 165c "full ofd access logs do not block IOs"
21323
21324 oal_get_read_count() {
21325         local stats="$1"
21326
21327         # STATS lustre-OST0001 alr_read_count 1
21328
21329         do_facet ost1 cat "${stats}" |
21330         awk '$1 == "STATS" && $3 == "alr_read_count" { count = $4; }
21331              END { print count; }'
21332 }
21333
21334 oal_expect_read_count() {
21335         local stats="$1"
21336         local count
21337         local expect="$2"
21338
21339         # Ask ofd_access_log_reader to write stats.
21340         do_facet ost1 killall -USR1 ofd_access_log_reader
21341
21342         # Allow some time for things to happen.
21343         sleep 1
21344
21345         count=$(oal_get_read_count "${stats}")
21346         if ((count == expect)); then
21347                 return 0
21348         fi
21349
21350         error_noexit "bad read count, got ${count}, expected ${expect}"
21351         do_facet ost1 cat "${stats}" >&2
21352         exit 1
21353 }
21354
21355 test_165d() {
21356         local stats="/tmp/${tfile}.stats"
21357         local file="${DIR}/${tdir}/${tfile}"
21358         local param="obdfilter.${FSNAME}-OST0000.access_log_mask"
21359
21360         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
21361                 skip "OFD access log unsupported"
21362
21363         test_mkdir "${DIR}/${tdir}"
21364
21365         setup_165
21366         do_facet ost1 ofd_access_log_reader --stats="${stats}" &
21367         sleep 5
21368
21369         lfs setstripe -c 1 -i 0 "${file}"
21370
21371         do_facet ost1 lctl set_param "${param}=rw"
21372         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
21373                 error "cannot create '${file}'"
21374         oal_expect_read_count "${stats}" 1
21375
21376         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
21377                 error "cannot read '${file}'"
21378         oal_expect_read_count "${stats}" 2
21379
21380         do_facet ost1 lctl set_param "${param}=r"
21381         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
21382                 error "cannot create '${file}'"
21383         oal_expect_read_count "${stats}" 2
21384
21385         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
21386                 error "cannot read '${file}'"
21387         oal_expect_read_count "${stats}" 3
21388
21389         do_facet ost1 lctl set_param "${param}=w"
21390         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
21391                 error "cannot create '${file}'"
21392         oal_expect_read_count "${stats}" 4
21393
21394         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
21395                 error "cannot read '${file}'"
21396         oal_expect_read_count "${stats}" 4
21397
21398         do_facet ost1 lctl set_param "${param}=0"
21399         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
21400                 error "cannot create '${file}'"
21401         oal_expect_read_count "${stats}" 4
21402
21403         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
21404                 error "cannot read '${file}'"
21405         oal_expect_read_count "${stats}" 4
21406
21407         do_facet ost1 killall -TERM ofd_access_log_reader
21408         wait
21409         rc=$?
21410         if ((rc != 0)); then
21411                 error "ofd_access_log_reader exited with rc = '${rc}'"
21412         fi
21413 }
21414 run_test 165d "ofd_access_log mask works"
21415
21416 test_165e() {
21417         local stats="/tmp/${tfile}.stats"
21418         local file0="${DIR}/${tdir}-0/${tfile}"
21419         local file1="${DIR}/${tdir}-1/${tfile}"
21420
21421         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
21422                 skip "OFD access log unsupported"
21423
21424         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
21425
21426         test_mkdir -c 1 -i 0 "${DIR}/${tdir}-0"
21427         test_mkdir -c 1 -i 1 "${DIR}/${tdir}-1"
21428
21429         lfs setstripe -c 1 -i 0 "${file0}"
21430         lfs setstripe -c 1 -i 0 "${file1}"
21431
21432         setup_165
21433         do_facet ost1 ofd_access_log_reader -I 1 --stats="${stats}" &
21434         sleep 5
21435
21436         $MULTIOP "${file0}" oO_CREAT:O_WRONLY:w512c ||
21437                 error "cannot create '${file0}'"
21438         sync
21439         oal_expect_read_count "${stats}" 0
21440
21441         $MULTIOP "${file1}" oO_CREAT:O_WRONLY:w512c ||
21442                 error "cannot create '${file1}'"
21443         sync
21444         oal_expect_read_count "${stats}" 1
21445
21446         do_facet ost1 killall -TERM ofd_access_log_reader
21447         wait
21448         rc=$?
21449         if ((rc != 0)); then
21450                 error "ofd_access_log_reader exited with rc = '${rc}'"
21451         fi
21452 }
21453 run_test 165e "ofd_access_log MDT index filter works"
21454
21455 test_165f() {
21456         local trace="/tmp/${tfile}.trace"
21457         local rc
21458         local count
21459
21460         setup_165
21461         do_facet ost1 timeout 60 ofd_access_log_reader \
21462                 --exit-on-close --debug=- --trace=- > "${trace}" &
21463         sleep 5
21464         stop ost1
21465
21466         wait
21467         rc=$?
21468
21469         if ((rc != 0)); then
21470                 error_noexit "ofd_access_log_reader exited with rc = '${rc}'"
21471                 cat "${trace}"
21472                 exit 1
21473         fi
21474 }
21475 run_test 165f "ofd_access_log_reader --exit-on-close works"
21476
21477 test_165g() {
21478         local count
21479         local trace=$TMP/${tfile}.trace
21480         local ofd_keepalive=$(do_facet ost1 ofd_access_log_reader --help |
21481                                 grep keepalive)
21482
21483         [[ -n "$ofd_keepalive" ]] || skip "ALR keepalive message unsupported"
21484
21485         setup_165
21486         do_facet ost1 timeout 60 ofd_access_log_reader \
21487                 --keepalive=3 --batch-interval=4 --debug=- > "${trace}" &
21488         sleep 40
21489         stop ost1
21490
21491         do_facet ost1 killall -TERM ofd_access_log_reader
21492         wait
21493         rc=$?
21494
21495         if ((rc != 0)); then
21496                 error "ofd_access_log_reader exited with rc = '${rc}'"
21497         fi
21498
21499         count=$(grep -c "send keepalive" ${trace})
21500
21501         # Normal duration 40 seconds / 4 secs interval = 10 times or so.
21502         # But sometimes the duration may be unpredictably long
21503         (( count >= 7 )) || error "keepalive msg received $count. Expected >= 7"
21504
21505         echo "keepalive msg received $count"
21506 }
21507 run_test 165g "ofd_access_log_reader --keepalive works"
21508
21509 test_169() {
21510         # do directio so as not to populate the page cache
21511         log "creating a 10 Mb file"
21512         $MULTIOP $DIR/$tfile oO_CREAT:O_DIRECT:O_RDWR:w$((10*1048576))c ||
21513                 error "multiop failed while creating a file"
21514         log "starting reads"
21515         dd if=$DIR/$tfile of=/dev/null bs=4096 &
21516         log "truncating the file"
21517         $MULTIOP $DIR/$tfile oO_TRUNC:c ||
21518                 error "multiop failed while truncating the file"
21519         log "killing dd"
21520         kill %+ || true # reads might have finished
21521         echo "wait until dd is finished"
21522         wait
21523         log "removing the temporary file"
21524         rm -rf $DIR/$tfile || error "tmp file removal failed"
21525 }
21526 run_test 169 "parallel read and truncate should not deadlock"
21527
21528 test_170a() {
21529         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21530
21531         $LCTL clear     # bug 18514
21532         $LCTL debug_daemon start $TMP/${tfile}_log_good
21533         touch $DIR/$tfile
21534         $LCTL debug_daemon stop
21535         sed -e "s/^...../a/g" $TMP/${tfile}_log_good > $TMP/${tfile}_log_bad ||
21536                 error "sed failed to read log_good"
21537
21538         $LCTL debug_daemon start $TMP/${tfile}_log_good
21539         rm -rf $DIR/$tfile
21540         $LCTL debug_daemon stop
21541
21542         $LCTL df $TMP/${tfile}_log_bad > $TMP/${tfile}_log_bad.out 2>&1 ||
21543                error "lctl df log_bad failed"
21544
21545         local bad_line=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $9}')
21546         local good_line1=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $5}')
21547
21548         $LCTL df $TMP/${tfile}_log_good > $TMP/${tfile}_log_good.out 2>&1
21549         local good_line2=$(tail -n 1 $TMP/${tfile}_log_good.out | awk '{print $5}')
21550
21551         [ "$bad_line" ] && [ "$good_line1" ] && [ "$good_line2" ] ||
21552                 error "bad_line good_line1 good_line2 are empty"
21553
21554         cat $TMP/${tfile}_log_good >> $TMP/${tfile}_logs_corrupt
21555         cat $TMP/${tfile}_log_bad >> $TMP/${tfile}_logs_corrupt
21556         cat $TMP/${tfile}_log_good >> $TMP/${tfile}_logs_corrupt
21557
21558         $LCTL df $TMP/${tfile}_logs_corrupt > $TMP/${tfile}_log_bad.out 2>&1
21559         local bad_line_new=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $9}')
21560         local good_line_new=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $5}')
21561
21562         [ "$bad_line_new" ] && [ "$good_line_new" ] ||
21563                 error "bad_line_new good_line_new are empty"
21564
21565         local expected_good=$((good_line1 + good_line2*2))
21566
21567         rm -f $TMP/${tfile}*
21568         # LU-231, short malformed line may not be counted into bad lines
21569         if [ $bad_line -ne $bad_line_new ] &&
21570                    [ $bad_line -ne $((bad_line_new - 1)) ]; then
21571                 error "expected $bad_line bad lines, but got $bad_line_new"
21572                 return 1
21573         fi
21574
21575         if [ $expected_good -ne $good_line_new ]; then
21576                 error "expected $expected_good good lines, but got $good_line_new"
21577                 return 2
21578         fi
21579         true
21580 }
21581 run_test 170a "test lctl df to handle corrupted log"
21582
21583 test_170b() {
21584         # enable filename encoding on one client, ost and mdt respectively
21585         declare -a old_fl
21586         local param="enable_fname_encoding"
21587         local nodes_list=$HOSTNAME
21588         local log=$TMP/sanity.$testnum
21589         local i=0
21590
21591         (( $MDS1_VERSION >= $(version_code 2.16.52) )) &&
21592                 nodes_list="$nodes_list,$(facet_active_host mds1)"
21593         (( $OST1_VERSION >= $(version_code 2.16.52) )) &&
21594                 nodes_list="$nodes_list,$(facet_active_host ost1)"
21595         local_mode && nodes_list=$HOSTNAME
21596
21597         old_fl=($(do_nodes $nodes_list $LCTL get_param -n $param))
21598
21599         # Test with filename encoding on
21600         set_params_nodes $nodes_list "$param=on"
21601         for node in ${nodes_list//,/ }; do
21602                 stack_trap "set_params_nodes $node "$param=${old_fl[$i]}""
21603                 i=$((i+1))
21604         done
21605         do_nodes $nodes_list "$LCTL get_param -n $param" | grep 0 &&
21606                 error "Failed to enable filename encoding on all the nodes"
21607
21608         # Start full debug to collect the logs
21609         start_full_debug_logging $nodes_list
21610         do_nodes $nodes_list "$LCTL clear"
21611
21612         # Do some operations on $tfile
21613         touch $DIR/$tfile || error "Failed to touch $tfile"
21614         cp $DIR/$tfile $DIR/$testnum.cp || error "Failed to cp $tfile"
21615         ln -s $DIR/$tfile $DIR/$testnum.ln || error "Failed to ln -s $tfile"
21616         $LFS migrate -c $OSTCOUNT $DIR/$tfile ||
21617                 error "Failed to migrate $tfile"
21618         $LFS mirror extend -N $DIR/$tfile ||
21619                 error "Failed to extend mirrored $tfile"
21620         mv $DIR/$tfile $DIR/$testnum.mv || error "Failed to mv $tfile"
21621         rm -f $DIR/$tfile $DIR/$testnum.* || error "Failed to rm $tfile"
21622
21623         # Do some operations on $tdir
21624         mkdir -p $DIR/$tdir || error "Failed to mkdir $tdir"
21625         cp -r $DIR/$tdir $DIR/$testnum.cp || error "Failed to cp $tdir"
21626         ln -s $DIR/$tdir $DIR/$testnum.ln || error "Failed to ln -s $tdir"
21627         $LFS migrate -d -m 0 -c $MDSCOUNT $DIR/$tdir ||
21628                 error "Failed to migrate $tdir"
21629         mv $DIR/$tdir $DIR/$testnum.mv || error "Failed to mv $tdir"
21630         rm -rf $DIR/$tdir $DIR/$testnum.* || error "Failed to rm $tdir"
21631
21632         # Stop the full debug
21633         do_nodes $nodes_list "$LCTL dk > $log"
21634         stack_trap "do_nodes $nodes_list rm -f $log"
21635         stop_full_debug_logging
21636
21637         # Verify if $tfile and $tdir names are encoded in the logs
21638         do_nodes $nodes_list "grep -E '$tfile|$tdir' $log" &&
21639                 error "Still found '$tfile' and '$tdir' in the logs"
21640         return 0
21641 }
21642 run_test 170b "check filename encoding"
21643
21644 test_171() { # bug20592
21645         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21646
21647         #define OBD_FAIL_PTLRPC_DUMP_LOG         0x50e
21648         $LCTL set_param fail_loc=0x50e
21649         $LCTL set_param fail_val=3000
21650         multiop_bg_pause $DIR/$tfile O_s || true
21651         local MULTIPID=$!
21652         kill -USR1 $MULTIPID
21653         # cause log dump
21654         sleep 3
21655         wait $MULTIPID
21656         if dmesg | grep "recursive fault"; then
21657                 error "caught a recursive fault"
21658         fi
21659         $LCTL set_param fail_loc=0
21660         true
21661 }
21662 run_test 171 "test libcfs_debug_dumplog_thread stuck in do_exit() ======"
21663
21664 test_172() {
21665
21666         #define OBD_FAIL_OBD_CLEANUP  0x60e
21667         $LCTL set_param fail_loc=0x60e
21668         umount $MOUNT || error "umount $MOUNT failed"
21669         stack_trap "mount_client $MOUNT"
21670
21671         (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )) ||
21672                 error "no client OBDs are remained"
21673
21674         $LCTL dl | while read devno state type name foo; do
21675                 case $type in
21676                 lov|osc|lmv|mdc)
21677                         $LCTL --device $name cleanup
21678                         $LCTL --device $name detach
21679                         ;;
21680                 *)
21681                         # skip server devices
21682                         ;;
21683                 esac
21684         done
21685
21686         if (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )); then
21687                 $LCTL dl | egrep " osc | lov | lmv | mdc "
21688                 error "some client OBDs are still remained"
21689         fi
21690
21691 }
21692 run_test 172 "manual device removal with lctl cleanup/detach ======"
21693
21694 # it would be good to share it with obdfilter-survey/iokit-libecho code
21695 setup_obdecho_osc () {
21696         local rc=0
21697         local ost_nid=$1
21698         local obdfilter_name=$2
21699         echo "Creating new osc for $obdfilter_name on $ost_nid"
21700         # make sure we can find loopback nid
21701         $LCTL add_uuid $ost_nid $ost_nid >/dev/null 2>&1
21702
21703         [ $rc -eq 0 ] && { $LCTL attach osc ${obdfilter_name}_osc     \
21704                            ${obdfilter_name}_osc_UUID || rc=2; }
21705         [ $rc -eq 0 ] && { $LCTL --device ${obdfilter_name}_osc setup \
21706                            ${obdfilter_name}_UUID  $ost_nid || rc=3; }
21707         return $rc
21708 }
21709
21710 cleanup_obdecho_osc () {
21711         local obdfilter_name=$1
21712         $LCTL --device ${obdfilter_name}_osc cleanup >/dev/null
21713         $LCTL --device ${obdfilter_name}_osc detach  >/dev/null
21714         return 0
21715 }
21716
21717 obdecho_test() {
21718         local OBD=$1
21719         local node=$2
21720         local pages=${3:-64}
21721         local rc=0
21722         local id
21723
21724         local count=10
21725         local obd_size=$(get_obd_size $node $OBD)
21726         local page_size=$(get_page_size $node)
21727         if [[ -n "$obd_size" ]]; then
21728                 local new_count=$((obd_size / (pages * page_size / 1024)))
21729                 [[ $new_count -ge $count ]] || count=$new_count
21730         fi
21731
21732         do_facet $node "$LCTL attach echo_client ec ec_uuid" || rc=1
21733         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec setup $OBD" ||
21734                            rc=2; }
21735         if [ $rc -eq 0 ]; then
21736             id=$(do_facet $node "$LCTL --device ec create 1"  | awk '/object id/ {print $6}')
21737             [ ${PIPESTATUS[0]} -eq 0 -a -n "$id" ] || rc=3
21738         fi
21739         echo "New object id is $id"
21740         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec getattr $id" ||
21741                            rc=4; }
21742         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec "                 \
21743                            "test_brw $count w v $pages $id" || rc=4; }
21744         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec destroy $id 1" ||
21745                            rc=4; }
21746         [ $rc -eq 0 ] || [ $rc -gt 2 ] &&
21747                 { do_facet $node "$LCTL --device ec cleanup" || rc=5; }
21748         [ $rc -eq 0 ] || [ $rc -gt 1 ] &&
21749                 { do_facet $node "$LCTL --device ec detach" || rc=6; }
21750         [ $rc -ne 0 ] && echo "obecho_create_test failed: $rc"
21751         return $rc
21752 }
21753
21754 test_180a() {
21755         skip "obdecho on osc is no longer supported"
21756 }
21757 run_test 180a "test obdecho on osc"
21758
21759 test_180b() {
21760         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21761         remote_ost_nodsh && skip "remote OST with nodsh"
21762
21763         do_rpc_nodes $(facet_active_host ost1) load_module obdecho/obdecho &&
21764                 stack_trap "do_facet ost1 rmmod obdecho" EXIT ||
21765                 error "failed to load module obdecho"
21766
21767         local target=$(do_facet ost1 $LCTL dl |
21768                        awk '/obdfilter/ { print $4; exit; }')
21769
21770         if [ -n "$target" ]; then
21771                 obdecho_test $target ost1 || error "obdecho_test failed with $?"
21772         else
21773                 do_facet ost1 $LCTL dl
21774                 error "there is no obdfilter target on ost1"
21775         fi
21776 }
21777 run_test 180b "test obdecho directly on obdfilter"
21778
21779 test_180c() { # LU-2598
21780         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21781         remote_ost_nodsh && skip "remote OST with nodsh"
21782         [[ $MDS1_VERSION -lt $(version_code 2.4.0) ]] &&
21783                 skip "Need MDS version at least 2.4.0"
21784
21785         do_rpc_nodes $(facet_active_host ost1) load_module obdecho/obdecho &&
21786                 stack_trap "do_facet ost1 rmmod obdecho" EXIT ||
21787                 error "failed to load module obdecho"
21788
21789         local target=$(do_facet ost1 $LCTL dl |
21790                        awk '/obdfilter/ { print $4; exit; }')
21791
21792         if [ -n "$target" ]; then
21793                 local pages=16384 # 64MB bulk I/O RPC size
21794
21795                 obdecho_test "$target" ost1 "$pages" ||
21796                         error "obdecho_test with pages=$pages failed with $?"
21797         else
21798                 do_facet ost1 $LCTL dl
21799                 error "there is no obdfilter target on ost1"
21800         fi
21801 }
21802 run_test 180c "test huge bulk I/O size on obdfilter, don't LASSERT"
21803
21804 test_181() { # bug 22177
21805         test_mkdir $DIR/$tdir
21806         # create enough files to index the directory
21807         createmany -o $DIR/$tdir/foobar 4000
21808         # print attributes for debug purpose
21809         lsattr -d .
21810         # open dir
21811         multiop_bg_pause $DIR/$tdir D_Sc || return 1
21812         MULTIPID=$!
21813         # remove the files & current working dir
21814         unlinkmany $DIR/$tdir/foobar 4000
21815         rmdir $DIR/$tdir
21816         kill -USR1 $MULTIPID
21817         wait $MULTIPID
21818         stat $DIR/$tdir && error "open-unlinked dir was not removed!"
21819         return 0
21820 }
21821 run_test 181 "Test open-unlinked dir ========================"
21822
21823 test_182a() {
21824         local fcount=1000
21825         local tcount=10
21826
21827         mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir"
21828
21829         $LCTL set_param mdc.*.rpc_stats=clear
21830
21831         for (( i = 0; i < $tcount; i++ )) ; do
21832                 mkdir $DIR/$tdir/$i
21833         done
21834
21835         for (( i = 0; i < $tcount; i++ )) ; do
21836                 createmany -o $DIR/$tdir/$i/f- $fcount &
21837         done
21838         wait
21839
21840         for (( i = 0; i < $tcount; i++ )) ; do
21841                 unlinkmany $DIR/$tdir/$i/f- $fcount &
21842         done
21843         wait
21844
21845         $LCTL get_param mdc.*.rpc_stats
21846
21847         rm -rf $DIR/$tdir
21848 }
21849 run_test 182a "Test parallel modify metadata operations from mdc"
21850
21851 test_182b() {
21852         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
21853         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
21854         local dcount=1000
21855         local tcount=10
21856         local stime
21857         local etime
21858         local delta
21859
21860         do_facet mds1 $LCTL list_param \
21861                 osp.$FSNAME-MDT*-osp-MDT*.rpc_stats ||
21862                 skip "MDS lacks parallel RPC handling"
21863
21864         $LFS mkdir -i 0 $DIR/$tdir || error "creating dir $DIR/$tdir"
21865
21866         rpc_count=$(do_facet mds1 $LCTL get_param -n \
21867                     osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight)
21868
21869         stime=$(date +%s)
21870         createmany -i 0 -d $DIR/$tdir/t- $tcount
21871
21872         for (( i = 0; i < $tcount; i++ )) ; do
21873                 createmany -i 0 -d $DIR/$tdir/t-$i/d- 0 $dcount &
21874         done
21875         wait
21876         etime=$(date +%s)
21877         delta=$((etime - stime))
21878         echo "Time for file creation $delta sec for $rpc_count parallel RPCs"
21879
21880         stime=$(date +%s)
21881         for (( i = 0; i < $tcount; i++ )) ; do
21882                 unlinkmany -d $DIR/$tdir/$i/d- $dcount &
21883         done
21884         wait
21885         etime=$(date +%s)
21886         delta=$((etime - stime))
21887         echo "Time for file removal $delta sec for $rpc_count parallel RPCs"
21888
21889         rm -rf $DIR/$tdir
21890
21891         $LFS mkdir -i 0 $DIR/$tdir || error "creating dir $DIR/$tdir"
21892
21893         do_facet mds1 $LCTL set_param osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight=1
21894
21895         stime=$(date +%s)
21896         createmany -i 0 -d $DIR/$tdir/t- $tcount
21897
21898         for (( i = 0; i < $tcount; i++ )) ; do
21899                 createmany -i 0 -d $DIR/$tdir/t-$i/d- 0 $dcount &
21900         done
21901         wait
21902         etime=$(date +%s)
21903         delta=$((etime - stime))
21904         echo "Time for file creation $delta sec for 1 RPC sent at a time"
21905
21906         stime=$(date +%s)
21907         for (( i = 0; i < $tcount; i++ )) ; do
21908                 unlinkmany -d $DIR/$tdir/t-$i/d- $dcount &
21909         done
21910         wait
21911         etime=$(date +%s)
21912         delta=$((etime - stime))
21913         echo "Time for file removal $delta sec for 1 RPC sent at a time"
21914
21915         do_facet mds1 $LCTL set_param osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight=$rpc_count
21916 }
21917 run_test 182b "Test parallel modify metadata operations from osp"
21918
21919 test_183() { # LU-2275
21920         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21921         remote_mds_nodsh && skip "remote MDS with nodsh"
21922         [[ $MDS1_VERSION -lt $(version_code 2.3.56) ]] &&
21923                 skip "Need MDS version at least 2.3.56"
21924
21925         mkdir_on_mdt0 $DIR/$tdir || error "creating dir $DIR/$tdir"
21926         echo aaa > $DIR/$tdir/$tfile
21927
21928 #define OBD_FAIL_MDS_NEGATIVE_POSITIVE  0x148
21929         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x148
21930
21931         ls -l $DIR/$tdir && error "ls succeeded, should have failed"
21932         cat $DIR/$tdir/$tfile && error "cat succeeded, should have failed"
21933
21934         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
21935
21936         # Flush negative dentry cache
21937         touch $DIR/$tdir/$tfile
21938
21939         # We are not checking for any leaked references here, they'll
21940         # become evident next time we do cleanup with module unload.
21941         rm -rf $DIR/$tdir
21942 }
21943 run_test 183 "No crash or request leak in case of strange dispositions ========"
21944
21945 # test suite 184 is for LU-2016, LU-2017
21946 test_184a() {
21947         check_swap_layouts_support
21948
21949         dir0=$DIR/$tdir/$testnum
21950         test_mkdir -p -c1 $dir0
21951         ref1=/etc/passwd
21952         ref2=/etc/group
21953         file1=$dir0/f1
21954         file2=$dir0/f2
21955         $LFS setstripe -c1 $file1
21956         cp $ref1 $file1
21957         $LFS setstripe -c2 $file2
21958         cp $ref2 $file2
21959         gen1=$($LFS getstripe -g $file1)
21960         gen2=$($LFS getstripe -g $file2)
21961
21962         $LFS swap_layouts $file1 $file2 || error "swap of file layout failed"
21963         gen=$($LFS getstripe -g $file1)
21964         [[ $gen1 != $gen ]] ||
21965                 error "Layout generation on $file1 does not change"
21966         gen=$($LFS getstripe -g $file2)
21967         [[ $gen2 != $gen ]] ||
21968                 error "Layout generation on $file2 does not change"
21969
21970         cmp $ref1 $file2 || error "content compare failed ($ref1 != $file2)"
21971         cmp $ref2 $file1 || error "content compare failed ($ref2 != $file1)"
21972
21973         lfsck_verify_pfid $file1 $file2 || error "PFID are not transferred"
21974 }
21975 run_test 184a "Basic layout swap"
21976
21977 test_184b() {
21978         check_swap_layouts_support
21979
21980         dir0=$DIR/$tdir/$testnum
21981         mkdir -p $dir0 || error "creating dir $dir0"
21982         file1=$dir0/f1
21983         file2=$dir0/f2
21984         file3=$dir0/f3
21985         dir1=$dir0/d1
21986         dir2=$dir0/d2
21987         mkdir $dir1 $dir2
21988         $LFS setstripe -c1 $file1
21989         $LFS setstripe -c2 $file2
21990         $LFS setstripe -c1 $file3
21991         chown $RUNAS_ID $file3
21992         gen1=$($LFS getstripe -g $file1)
21993         gen2=$($LFS getstripe -g $file2)
21994
21995         $LFS swap_layouts $dir1 $dir2 &&
21996                 error "swap of directories layouts should fail"
21997         $LFS swap_layouts $dir1 $file1 &&
21998                 error "swap of directory and file layouts should fail"
21999         $RUNAS $LFS swap_layouts $file1 $file2 &&
22000                 error "swap of file we cannot write should fail"
22001         $LFS swap_layouts $file1 $file3 &&
22002                 error "swap of file with different owner should fail"
22003         /bin/true # to clear error code
22004 }
22005 run_test 184b "Forbidden layout swap (will generate errors)"
22006
22007 test_184c() {
22008         local cmpn_arg=$(cmp -n 2>&1 | grep "invalid option")
22009         [ -n "$cmpn_arg" ] && skip_env "cmp does not support -n"
22010         check_swap_layouts_support
22011         check_swap_layout_no_dom $DIR
22012
22013         local dir0=$DIR/$tdir/$testnum
22014         mkdir -p $dir0 || error "creating dir $dir0"
22015
22016         local ref1=$dir0/ref1
22017         local ref2=$dir0/ref2
22018         local file1=$dir0/file1
22019         local file2=$dir0/file2
22020         # create a file large enough for the concurrent test
22021         dd if=/dev/urandom of=$ref1 bs=1M count=$((RANDOM % 50 + 20))
22022         dd if=/dev/urandom of=$ref2 bs=1M count=$((RANDOM % 50 + 20))
22023         echo "ref file size: ref1($(stat -c %s $ref1))," \
22024              "ref2($(stat -c %s $ref2))"
22025
22026         cp $ref2 $file2
22027         dd if=$ref1 of=$file1 bs=16k &
22028         local DD_PID=$!
22029
22030         # Make sure dd starts to copy file, but wait at most 5 seconds
22031         local loops=0
22032         while [ ! -s $file1 -a $((loops++)) -lt 50 ]; do sleep 0.1; done
22033
22034         $LFS swap_layouts $file1 $file2
22035         local rc=$?
22036         wait $DD_PID
22037         [[ $? == 0 ]] || error "concurrent write on $file1 failed"
22038         [[ $rc == 0 ]] || error "swap of $file1 and $file2 failed"
22039
22040         # how many bytes copied before swapping layout
22041         local copied=$(stat -c %s $file2)
22042         local remaining=$(stat -c %s $ref1)
22043         remaining=$((remaining - copied))
22044         echo "Copied $copied bytes before swapping layout..."
22045
22046         cmp -n $copied $file1 $ref2 | grep differ &&
22047                 error "Content mismatch [0, $copied) of ref2 and file1"
22048         cmp -n $copied $file2 $ref1 ||
22049                 error "Content mismatch [0, $copied) of ref1 and file2"
22050         cmp -i $copied:$copied -n $remaining $file1 $ref1 ||
22051                 error "Content mismatch [$copied, EOF) of ref1 and file1"
22052
22053         # clean up
22054         rm -f $ref1 $ref2 $file1 $file2
22055 }
22056 run_test 184c "Concurrent write and layout swap"
22057
22058 test_184d() {
22059         check_swap_layouts_support
22060         check_swap_layout_no_dom $DIR
22061         [ -z "$(which getfattr 2>/dev/null)" ] &&
22062                 skip_env "no getfattr command"
22063
22064         local file1=$DIR/$tdir/$tfile-1
22065         local file2=$DIR/$tdir/$tfile-2
22066         local file3=$DIR/$tdir/$tfile-3
22067         local lovea1
22068         local lovea2
22069
22070         mkdir -p $DIR/$tdir
22071         touch $file1 || error "create $file1 failed"
22072         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file2 ||
22073                 error "create $file2 failed"
22074         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file3 ||
22075                 error "create $file3 failed"
22076         lovea1=$(get_layout_param $file1)
22077
22078         $LFS swap_layouts $file2 $file3 ||
22079                 error "swap $file2 $file3 layouts failed"
22080         $LFS swap_layouts $file1 $file2 ||
22081                 error "swap $file1 $file2 layouts failed"
22082
22083         lovea2=$(get_layout_param $file2)
22084         echo "$lovea1"
22085         echo "$lovea2"
22086         [ "$lovea1" == "$lovea2" ] || error "lovea $lovea1 != $lovea2"
22087
22088         lovea1=$(getfattr -n trusted.lov $file1 | grep ^trusted)
22089         [[ -z "$lovea1" ]] || error "$file1 shouldn't have lovea"
22090 }
22091 run_test 184d "allow stripeless layouts swap"
22092
22093 test_184e() {
22094         [[ $MDS1_VERSION -ge $(version_code 2.6.94) ]] ||
22095                 skip "Need MDS version at least 2.6.94"
22096         check_swap_layouts_support
22097         check_swap_layout_no_dom $DIR
22098         [ -z "$(which getfattr 2>/dev/null)" ] &&
22099                 skip_env "no getfattr command"
22100
22101         local file1=$DIR/$tdir/$tfile-1
22102         local file2=$DIR/$tdir/$tfile-2
22103         local file3=$DIR/$tdir/$tfile-3
22104         local lovea
22105
22106         mkdir -p $DIR/$tdir
22107         touch $file1 || error "create $file1 failed"
22108         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file2 ||
22109                 error "create $file2 failed"
22110         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file3 ||
22111                 error "create $file3 failed"
22112
22113         $LFS swap_layouts $file1 $file2 ||
22114                 error "swap $file1 $file2 layouts failed"
22115
22116         lovea=$(getfattr -n trusted.lov $file1 | grep ^trusted)
22117         [[ -z "$lovea" ]] || error "$file1 shouldn't have lovea"
22118
22119         echo 123 > $file1 || error "Should be able to write into $file1"
22120
22121         $LFS swap_layouts $file1 $file3 ||
22122                 error "swap $file1 $file3 layouts failed"
22123
22124         echo 123 > $file1 || error "Should be able to write into $file1"
22125
22126         rm -rf $file1 $file2 $file3
22127 }
22128 run_test 184e "Recreate layout after stripeless layout swaps"
22129
22130 test_184f() {
22131         # Create a file with name longer than sizeof(struct stat) ==
22132         # 144 to see if we can get chars from the file name to appear
22133         # in the returned striping. Note that 'f' == 0x66.
22134         local file=$(for ((i = 0; i < 200; i++)); do echo -n f; done)
22135
22136         mkdir -p $DIR/$tdir
22137         mcreate $DIR/$tdir/$file
22138         if lfs find --stripe-count 0x6666 $DIR/$tdir | grep $file; then
22139                 error "IOC_MDC_GETFILEINFO returned garbage striping"
22140         fi
22141 }
22142 run_test 184f "IOC_MDC_GETFILEINFO for files with long names but no striping"
22143
22144 test_185() { # LU-2441
22145         # LU-3553 - no volatile file support in old servers
22146         [[ $MDS1_VERSION -ge $(version_code 2.3.60) ]] ||
22147                 skip "Need MDS version at least 2.3.60"
22148
22149         mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir"
22150         touch $DIR/$tdir/spoo
22151         local mtime1=$(stat -c "%Y" $DIR/$tdir)
22152         local fid=$($MULTIOP $DIR/$tdir VFw4096c) ||
22153                 error "cannot create/write a volatile file"
22154         $CHECKSTAT -t file $MOUNT/.lustre/fid/$fid 2>/dev/null &&
22155                 error "FID is still valid after close"
22156
22157         multiop_bg_pause $DIR/$tdir Vw4096_c
22158         local multi_pid=$!
22159
22160         local OLD_IFS=$IFS
22161         IFS=":"
22162         local fidv=($fid)
22163         IFS=$OLD_IFS
22164         # assume that the next FID for this client is sequential, since stdout
22165         # is unfortunately eaten by multiop_bg_pause
22166         local n=$((${fidv[1]} + 1))
22167         local next_fid="${fidv[0]}:$(printf "0x%x" $n):${fidv[2]}"
22168         $CHECKSTAT -t file $MOUNT/.lustre/fid/$next_fid ||
22169                 error "FID is missing before close"
22170         kill -USR1 $multi_pid
22171         # 1 second delay, so if mtime change we will see it
22172         sleep 1
22173         local mtime2=$(stat -c "%Y" $DIR/$tdir)
22174         [[ $mtime1 == $mtime2 ]] || error "mtime has changed"
22175 }
22176 run_test 185 "Volatile file support"
22177
22178 function create_check_volatile() {
22179         local idx=$1
22180         local tgt
22181
22182         $MULTIOP $MOUNT/.lustre/fid V${idx}Fw4096_c >&/tmp/${tfile}.fid &
22183         local PID=$!
22184         sleep 1
22185         local FID=$(cat /tmp/${tfile}.fid)
22186         [ "$FID" == "" ] && error "can't get FID for volatile"
22187         $CHECKSTAT -t file $MOUNT/.lustre/fid/$FID || error "can't stat $FID"
22188         tgt=$($LFS getstripe -m $MOUNT/.lustre/fid/$FID)
22189         [ "$tgt" != "$idx" ] && error "wrong MDS $tgt, expected $idx"
22190         kill -USR1 $PID
22191         wait
22192         sleep 1
22193         cancel_lru_locks mdc # flush opencache
22194         $CHECKSTAT -t file $MOUNT/.lustre/fid/$FID && error "can stat $FID"
22195         return 0
22196 }
22197
22198 test_185a(){
22199         # LU-12516 - volatile creation via .lustre
22200         (( $MDS1_VERSION >= $(version_code 2.12.55) )) ||
22201                 skip "Need MDS version at least 2.12.55"
22202         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
22203
22204         create_check_volatile 0
22205         [ $MDSCOUNT -lt 2 ] && return 0
22206
22207         # DNE case
22208         create_check_volatile 1
22209
22210         return 0
22211 }
22212 run_test 185a "Volatile file creation in .lustre/fid/"
22213
22214 test_187a() {
22215         remote_mds_nodsh && skip "remote MDS with nodsh"
22216         [ $MDS1_VERSION -lt $(version_code 2.3.0) ] &&
22217                 skip "Need MDS version at least 2.3.0"
22218
22219         local dir0=$DIR/$tdir/$testnum
22220         mkdir -p $dir0 || error "creating dir $dir0"
22221
22222         local file=$dir0/file1
22223         dd if=/dev/urandom of=$file count=10 bs=1M conv=fsync
22224         stack_trap "rm -f $file"
22225         local dv1=$($LFS data_version $file)
22226         dd if=/dev/urandom of=$file seek=10 count=1 bs=1M conv=fsync
22227         local dv2=$($LFS data_version $file)
22228         [[ $dv1 != $dv2 ]] ||
22229                 error "data version did not change on write $dv1 == $dv2"
22230 }
22231 run_test 187a "Test data version change"
22232
22233 test_187b() {
22234         remote_mds_nodsh && skip "remote MDS with nodsh"
22235         [ $MDS1_VERSION -lt $(version_code 2.3.0) ] &&
22236                 skip "Need MDS version at least 2.3.0"
22237
22238         local dir0=$DIR/$tdir/$testnum
22239         mkdir -p $dir0 || error "creating dir $dir0"
22240
22241         declare -a DV=$($MULTIOP $dir0 Vw1000xYw1000xY | cut -f3 -d" ")
22242         [[ ${DV[0]} != ${DV[1]} ]] ||
22243                 error "data version did not change on write"\
22244                       " ${DV[0]} == ${DV[1]}"
22245
22246         # clean up
22247         rm -f $file1
22248 }
22249 run_test 187b "Test data version change on volatile file"
22250
22251 test_200() {
22252         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22253         remote_mgs_nodsh && skip "remote MGS with nodsh"
22254
22255         local POOL=${POOL:-cea1}
22256         local POOL_ROOT=${POOL_ROOT:-$DIR/$tdir}
22257         local POOL_DIR_NAME=${POOL_DIR_NAME:-dir_tst}
22258         # Pool OST targets
22259         local first_ost=0
22260         local last_ost=$(($OSTCOUNT - 1))
22261         local ost_step=2
22262         local ost_list=$(seq $first_ost $ost_step $last_ost)
22263         local ost_range="$first_ost $last_ost $ost_step"
22264         local test_path=$POOL_ROOT/$POOL_DIR_NAME
22265         local file_dir=$POOL_ROOT/file_tst
22266         local subdir=$test_path/subdir
22267         local rc=0
22268
22269         while : ; do
22270                 # former test_200a test_200b
22271                 pool_add $POOL                          || { rc=$? ; break; }
22272                 pool_add_targets  $POOL $ost_range      || { rc=$? ; break; }
22273                 # former test_200c test_200d
22274                 mkdir -p $test_path
22275                 pool_set_dir      $POOL $test_path      || { rc=$? ; break; }
22276                 pool_check_dir    $POOL $test_path      || { rc=$? ; break; }
22277                 mkdir -p $subdir
22278                 pool_check_dir    $POOL $subdir         || { rc=$? ; break; }
22279                 pool_dir_rel_path $POOL $POOL_DIR_NAME $POOL_ROOT \
22280                                                         || { rc=$? ; break; }
22281                 # former test_200e test_200f
22282                 local files=$((OSTCOUNT*3))
22283                 pool_alloc_files  $POOL $test_path $files "$ost_list" \
22284                                                         || { rc=$? ; break; }
22285                 pool_create_files $POOL $file_dir $files "$ost_list" \
22286                                                         || { rc=$? ; break; }
22287                 # former test_200g test_200h
22288                 pool_lfs_df $POOL                       || { rc=$? ; break; }
22289                 pool_file_rel_path $POOL $test_path     || { rc=$? ; break; }
22290
22291                 # former test_201a test_201b test_201c
22292                 pool_remove_first_target $POOL          || { rc=$? ; break; }
22293
22294                 local f=$test_path/$tfile
22295                 pool_remove_all_targets $POOL $f        || { rc=$? ; break; }
22296                 pool_remove $POOL $f                    || { rc=$? ; break; }
22297                 break
22298         done
22299
22300         destroy_test_pools
22301
22302         return $rc
22303 }
22304 run_test 200 "OST pools"
22305
22306 # usage: default_attr <count | size | offset>
22307 default_attr() {
22308         $LCTL get_param -n lov.$FSNAME-clilov-\*.stripe${1}
22309 }
22310
22311 # usage: check_default_stripe_attr
22312 check_default_stripe_attr() {
22313         ACTUAL=$($LFS getstripe $* $DIR/$tdir)
22314         case $1 in
22315         --stripe-count|-c)
22316                 [ -n "$2" ] && EXPECTED=0 || EXPECTED=$(default_attr count);;
22317         --stripe-size|-S)
22318                 [ -n "$2" ] && EXPECTED=0 || EXPECTED=$(default_attr size);;
22319         --stripe-index|-i)
22320                 EXPECTED=-1;;
22321         *)
22322                 error "unknown getstripe attr '$1'"
22323         esac
22324
22325         [ $ACTUAL == $EXPECTED ] ||
22326                 error "$DIR/$tdir has $1 '$ACTUAL', not '$EXPECTED'"
22327 }
22328
22329 test_204a() {
22330         test_mkdir $DIR/$tdir
22331         $LFS setstripe --stripe-count 0 --stripe-size 0 --stripe-index -1 $DIR/$tdir
22332
22333         check_default_stripe_attr --stripe-count
22334         check_default_stripe_attr --stripe-size
22335         check_default_stripe_attr --stripe-index
22336 }
22337 run_test 204a "Print default stripe attributes"
22338
22339 test_204b() {
22340         test_mkdir $DIR/$tdir
22341         $LFS setstripe --stripe-count 1 $DIR/$tdir
22342
22343         check_default_stripe_attr --stripe-size
22344         check_default_stripe_attr --stripe-index
22345 }
22346 run_test 204b "Print default stripe size and offset"
22347
22348 test_204c() {
22349         test_mkdir $DIR/$tdir
22350         $LFS setstripe --stripe-size 65536 $DIR/$tdir
22351
22352         check_default_stripe_attr --stripe-count
22353         check_default_stripe_attr --stripe-index
22354 }
22355 run_test 204c "Print default stripe count and offset"
22356
22357 test_204d() {
22358         test_mkdir $DIR/$tdir
22359         $LFS setstripe --stripe-index 0 $DIR/$tdir
22360
22361         check_default_stripe_attr --stripe-count
22362         check_default_stripe_attr --stripe-size
22363 }
22364 run_test 204d "Print default stripe count and size"
22365
22366 test_204e() {
22367         test_mkdir $DIR/$tdir
22368         $LFS setstripe -d $DIR/$tdir
22369
22370         # LU-16904 check if root is set as PFL layout
22371         local numcomp=$($LFS getstripe --component-count $MOUNT)
22372
22373         if [[ $numcomp -gt 0 ]]; then
22374                 check_default_stripe_attr --stripe-count
22375         else
22376                 check_default_stripe_attr --stripe-count --raw
22377         fi
22378         check_default_stripe_attr --stripe-size --raw
22379         check_default_stripe_attr --stripe-index --raw
22380 }
22381 run_test 204e "Print raw stripe attributes"
22382
22383 test_204f() {
22384         test_mkdir $DIR/$tdir
22385         $LFS setstripe --stripe-count 1 $DIR/$tdir
22386
22387         check_default_stripe_attr --stripe-size --raw
22388         check_default_stripe_attr --stripe-index --raw
22389 }
22390 run_test 204f "Print raw stripe size and offset"
22391
22392 test_204g() {
22393         test_mkdir $DIR/$tdir
22394         $LFS setstripe --stripe-size 65536 $DIR/$tdir
22395
22396         check_default_stripe_attr --stripe-count --raw
22397         check_default_stripe_attr --stripe-index --raw
22398 }
22399 run_test 204g "Print raw stripe count and offset"
22400
22401 test_204h() {
22402         test_mkdir $DIR/$tdir
22403         $LFS setstripe --stripe-index 0 $DIR/$tdir
22404
22405         check_default_stripe_attr --stripe-count --raw
22406         check_default_stripe_attr --stripe-size --raw
22407 }
22408 run_test 204h "Print raw stripe count and size"
22409
22410 # Figure out which job scheduler is being used, if any,
22411 # or use a fake one
22412 if [ -n "$SLURM_JOB_ID" ]; then # SLURM
22413         JOBENV=SLURM_JOB_ID
22414 elif [ -n "$LSB_JOBID" ]; then # Load Sharing Facility
22415         JOBENV=LSB_JOBID
22416 elif [ -n "$PBS_JOBID" ]; then # PBS/Maui/Moab
22417         JOBENV=PBS_JOBID
22418 elif [ -n "$LOADL_STEPID" ]; then # LoadLeveller
22419         JOBENV=LOADL_STEP_ID
22420 elif [ -n "$JOB_ID" ]; then # Sun Grid Engine
22421         JOBENV=JOB_ID
22422 else
22423         $LCTL list_param jobid_name > /dev/null 2>&1
22424         if [ $? -eq 0 ]; then
22425                 JOBENV=nodelocal
22426         else
22427                 JOBENV=FAKE_JOBID
22428         fi
22429 fi
22430 LUSTRE_JOBID_SIZE=31 # plus NUL terminator
22431
22432 verify_jobstats() {
22433         local cmd=($1)
22434         shift
22435         local facets="$@"
22436
22437 # we don't really need to clear the stats for this test to work, since each
22438 # command has a unique jobid, but it makes debugging easier if needed.
22439 #       for facet in $facets; do
22440 #               local dev=$(convert_facet2label $facet)
22441 #               # clear old jobstats
22442 #               do_facet $facet lctl set_param *.$dev.job_stats="clear"
22443 #       done
22444
22445         # use a new JobID for each test, or we might see an old one
22446         [ "$JOBENV" = "FAKE_JOBID" ] &&
22447                 FAKE_JOBID=id.$testnum.$(basename ${cmd[0]}).$RANDOM
22448
22449         JOBVAL=${!JOBENV:0:$LUSTRE_JOBID_SIZE}
22450
22451         [ "$JOBENV" = "nodelocal" ] && {
22452                 FAKE_JOBID=id.$testnum.%e.$RANDOM
22453                 $LCTL set_param jobid_name=$FAKE_JOBID
22454                 JOBVAL=${FAKE_JOBID/\%e/$(basename ${cmd[0]})}
22455         }
22456
22457         log "Test: ${cmd[*]}"
22458         log "Using JobID environment $($LCTL get_param -n jobid_var)=$JOBVAL"
22459
22460         if [ $JOBENV = "FAKE_JOBID" ]; then
22461                 FAKE_JOBID=$JOBVAL ${cmd[*]}
22462         else
22463                 ${cmd[*]}
22464         fi
22465
22466         # all files are created on OST0000
22467         for facet in $facets; do
22468                 local stats="*.$(convert_facet2label $facet).job_stats"
22469
22470                 # strip out libtool wrappers for in-tree executables
22471                 if (( $(do_facet $facet lctl get_param $stats |
22472                         sed -e 's/\.lt-/./' | grep -cw $JOBVAL) != 1 )); then
22473                         do_facet $facet lctl get_param $stats
22474                         error "No jobstats for $JOBVAL found on $facet::$stats"
22475                 fi
22476         done
22477 }
22478
22479 jobstats_set() {
22480         local new_jobenv=$1
22481
22482         set_persistent_param_and_check client "jobid_var" \
22483                 "$FSNAME.sys.jobid_var" $new_jobenv
22484 }
22485
22486 test_205a() { # Job stats
22487         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22488         [[ $MDS1_VERSION -ge $(version_code 2.7.1) ]] ||
22489                 skip "Need MDS version with at least 2.7.1"
22490         remote_mgs_nodsh && skip "remote MGS with nodsh"
22491         remote_mds_nodsh && skip "remote MDS with nodsh"
22492         remote_ost_nodsh && skip "remote OST with nodsh"
22493         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep jobstats)" ] &&
22494                 skip "Server doesn't support jobstats"
22495         [[ $JOBID_VAR = disable ]] && skip_env "jobstats is disabled"
22496
22497         local old_jobenv=$($LCTL get_param -n jobid_var)
22498         [ $old_jobenv != $JOBENV ] && jobstats_set $JOBENV
22499         stack_trap "jobstats_set $old_jobenv" EXIT
22500
22501         changelog_register
22502
22503         local old_jobid_name=$($LCTL get_param jobid_name)
22504         stack_trap "$LCTL set_param $old_jobid_name" EXIT
22505
22506         local old_interval=$(do_facet $SINGLEMDS lctl get_param -n \
22507                                 mdt.*.job_cleanup_interval | head -n 1)
22508         local new_interval=5
22509         do_facet $SINGLEMDS \
22510                 $LCTL set_param mdt.*.job_cleanup_interval=$new_interval
22511         stack_trap "do_facet $SINGLEMDS \
22512                 $LCTL set_param mdt.*.job_cleanup_interval=$old_interval" EXIT
22513         local start=$SECONDS
22514
22515         local cmd
22516         # mkdir
22517         cmd="$LFS mkdir -i 0 -c 1 $DIR/$tdir"
22518         verify_jobstats "$cmd" "$SINGLEMDS"
22519         # rmdir
22520         cmd="rmdir $DIR/$tdir"
22521         verify_jobstats "$cmd" "$SINGLEMDS"
22522         # mkdir on secondary MDT
22523         if [ $MDSCOUNT -gt 1 ]; then
22524                 cmd="lfs mkdir -i 1 $DIR/$tdir.remote"
22525                 verify_jobstats "$cmd" "mds2"
22526         fi
22527         # mknod
22528         cmd="mknod $DIR/$tfile c 1 3"
22529         verify_jobstats "$cmd" "$SINGLEMDS"
22530         # unlink
22531         cmd="rm -f $DIR/$tfile"
22532         verify_jobstats "$cmd" "$SINGLEMDS"
22533         # create all files on OST0000 so verify_jobstats can find OST stats
22534         # open & close
22535         cmd="$LFS setstripe -i 0 -c 1 $DIR/$tfile"
22536         verify_jobstats "$cmd" "$SINGLEMDS"
22537         # setattr
22538         cmd="touch $DIR/$tfile"
22539         verify_jobstats "$cmd" "$SINGLEMDS ost1"
22540         # write
22541         cmd="dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=sync"
22542         verify_jobstats "$cmd" "ost1"
22543         # read
22544         cancel_lru_locks osc
22545         cmd="dd if=$DIR/$tfile of=/dev/null bs=1M count=1 iflag=direct"
22546         verify_jobstats "$cmd" "ost1"
22547         # truncate
22548         cmd="$TRUNCATE $DIR/$tfile 0"
22549         verify_jobstats "$cmd" "$SINGLEMDS ost1"
22550         # rename
22551         cmd="mv -f $DIR/$tfile $DIR/$tdir.rename"
22552         verify_jobstats "$cmd" "$SINGLEMDS"
22553         # jobstats expiry - sleep until old stats should be expired
22554         local left=$((new_interval + 5 - (SECONDS - start)))
22555         [ $left -ge 0 ] && wait_update_facet $SINGLEMDS \
22556                 "lctl get_param *.*.job_stats | grep -c 'job_id.*mkdir'" \
22557                         "0" $left
22558         cmd="$LFS mkdir -i 0 -c 1 $DIR/$tdir.expire"
22559         verify_jobstats "$cmd" "$SINGLEMDS"
22560         [ $(do_facet $SINGLEMDS lctl get_param *.*.job_stats |
22561             grep -c "job_id.*mkdir") -gt 1 ] && error "old jobstats not expired"
22562
22563         # Ensure that jobid are present in changelog (if supported by MDS)
22564         if [ $MDS1_VERSION -ge $(version_code 2.6.52) ];then
22565                 changelog_dump | tail -10
22566                 jobids=$(changelog_dump | tail -9 | grep -c "j=")
22567                 [ $jobids -eq 9 ] ||
22568                         error "Wrong changelog jobid count $jobids != 9"
22569
22570                 # LU-5862
22571                 JOBENV="disable"
22572                 jobstats_set $JOBENV
22573                 touch $DIR/$tfile
22574                 changelog_dump | grep $tfile
22575                 jobids=$(changelog_dump | grep $tfile | tail -1 | grep -c "j=")
22576                 [ $jobids -eq 0 ] ||
22577                         error "Unexpected jobids when jobid_var=$JOBENV"
22578         fi
22579
22580         # test '%j' access to environment variable - if supported
22581         if lctl set_param jobid_var=USER jobid_name="S.%j.%e.%u.%h.E"; then
22582                 JOBENV="JOBCOMPLEX"
22583                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname).E"
22584
22585                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
22586         fi
22587
22588         if lctl set_param jobid_var=USER jobid_name="S.%j.%e.%u.%H.E"; then
22589                 JOBENV="JOBCOMPLEX"
22590                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname -s).E"
22591
22592                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
22593         fi
22594
22595         # test '%j' access to per-session jobid - if supported
22596         if lctl list_param jobid_this_session > /dev/null 2>&1
22597         then
22598                 lctl set_param jobid_var=session jobid_name="S.%j.%e.%u.%h.E"
22599                 lctl set_param jobid_this_session=$USER
22600
22601                 JOBENV="JOBCOMPLEX"
22602                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname).E"
22603
22604                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
22605         fi
22606 }
22607 run_test 205a "Verify job stats"
22608
22609 # LU-13117, LU-13597, LU-16599
22610 test_205b() {
22611         (( $MDS1_VERSION >= $(version_code 2.13.54.91) )) ||
22612                 skip "Need MDS version at least 2.13.54.91"
22613
22614         local job_stats="mdt.*.job_stats"
22615         local old_jobid=$(do_facet mds1 $LCTL get_param jobid_var)
22616
22617         do_facet mds1 $LCTL set_param $job_stats=clear
22618
22619         # Setting jobid_var to USER might not be supported
22620         [[ -n "$old_jobid" ]] && stack_trap "$LCTL set_param $old_jobid"
22621         $LCTL set_param jobid_var=USER || true
22622         stack_trap "$LCTL set_param $($LCTL get_param jobid_name)"
22623         $LCTL set_param jobid_name="%j.%e.%u"
22624
22625         env -i USERTESTJOBSTATS=foolish touch $DIR/$tfile.1
22626         do_facet mds1 $LCTL get_param $job_stats | grep "job_id:.*foolish" &&
22627                 { do_facet mds1 $LCTL get_param $job_stats;
22628                   error "Unexpected jobid found"; }
22629         do_facet mds1 $LCTL get_param $job_stats | grep "open:.*min.*max.*sum"||
22630                 { do_facet mds1 $LCTL get_param $job_stats;
22631                   error "wrong job_stats format found"; }
22632
22633         (( $MDS1_VERSION <= $(version_code 2.15.0) )) &&
22634                 echo "MDS does not yet escape jobid" && return 0
22635
22636         mkdir_on_mdt0 $DIR/$tdir
22637         $LCTL set_param jobid_var=TEST205b
22638         env -i TEST205b="has sp" touch $DIR/$tdir/$tfile.2
22639         local jobid=$(do_facet mds1 $LCTL get_param $job_stats |
22640                       awk '/has\\x20sp/ {print $3}')
22641         [[ -n "$jobid" ]] || { do_facet mds1 $LCTL get_param $job_stats;
22642                   error "jobid not escaped"; }
22643
22644         if (( $MDS1_VERSION >= $(version_code 2.15.53.139) )); then
22645                 # need to run such a command on mds1:
22646                 # lctl set_param mdt.$FSNAME-MDT0000.job_stats='"has\x20sp.touch.0"'
22647                 #
22648                 # there might be multiple MDTs on single mds server, so need to
22649                 # specifiy MDT0000. Or the command will fail due to other MDTs
22650                 do_facet_vp mds1 $LCTL set_param mdt.$FSNAME-MDT0000.job_stats=$jobid ||
22651                         error "cannot clear escaped jobid in job_stats";
22652         else
22653                 echo "MDS does not support clearing escaped jobid"
22654         fi
22655 }
22656 run_test 205b "Verify job stats jobid and output format"
22657
22658 # LU-13733
22659 test_205c() {
22660         $LCTL set_param llite.*.stats=0
22661         dd if=/dev/zero of=$DIR/$tfile.1 bs=4k count=1
22662         $LCTL get_param llite.*.stats
22663         $LCTL get_param llite.*.stats | grep \
22664                 "write_bytes *1 samples \[bytes\] 4096 4096 4096 16777216" ||
22665                         error "wrong client stats format found"
22666 }
22667 run_test 205c "Verify client stats format"
22668
22669 test_205d() {
22670         local file=$DIR/$tdir/$tfile
22671
22672         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
22673                 skip "need lustre >= 2.15.53 for lljobstat"
22674         (( $OST1_VERSION >= $(version_code 2.15.53) )) ||
22675                 skip "need lustre >= 2.15.53 for lljobstat"
22676         verify_yaml_available || skip_env "YAML verification not installed"
22677
22678         test_mkdir -i 0 $DIR/$tdir
22679         $LFS setstripe -E 1M -L mdt -E -1 $file || error "create file failed"
22680         stack_trap "rm -rf $DIR/$tdir"
22681
22682         dd if=/dev/zero of=$file bs=1M count=10 conv=sync ||
22683                 error "failed to write data to $file"
22684         mv $file $file.2
22685
22686         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.rename_stats"
22687         echo -n 'verify rename_stats...'
22688         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.rename_stats" |
22689                 verify_yaml || error "rename_stats is not valid YAML"
22690         echo " OK"
22691
22692         echo -n 'verify mdt job_stats...'
22693         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.job_stats" |
22694                 verify_yaml || error "job_stats on mds1 is not valid YAML"
22695         echo " OK"
22696
22697         echo -n 'verify ost job_stats...'
22698         do_facet ost1 "$LCTL get_param -n obdfilter.$FSNAME-OST0000.job_stats" |
22699                 verify_yaml || error "job_stats on ost1 is not valid YAML"
22700         echo " OK"
22701 }
22702 run_test 205d "verify the format of some stats files"
22703
22704 test_205e() {
22705         local ops_comma
22706         local file=$DIR/$tdir/$tfile
22707         local -a cli_params
22708
22709         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
22710                 skip "need lustre >= 2.15.53 for lljobstat"
22711         (( $OST1_VERSION >= $(version_code 2.15.53) )) ||
22712                 skip "need lustre >= 2.15.53 for lljobstat"
22713         verify_yaml_available || skip_env "YAML verification not installed"
22714
22715         cli_params=( $($LCTL get_param jobid_name jobid_var) )
22716         $LCTL set_param jobid_var=nodelocal jobid_name=205e.%e.%u
22717         stack_trap "$LCTL set_param ${cli_params[*]}" EXIT
22718
22719         mkdir_on_mdt0 $DIR/$tdir || error "failed to create dir"
22720         stack_trap "rm -rf $DIR/$tdir"
22721
22722         $LFS setstripe -E EOF -i 0 -c 1 $file ||
22723                 error "failed to create $file on ost1"
22724         dd if=/dev/zero of=$file bs=1M count=10 oflag=sync ||
22725                 error "failed to write data to $file"
22726
22727         do_facet mds1 "$LCTL get_param *.*.job_stats"
22728         do_facet ost1 "$LCTL get_param *.*.job_stats"
22729
22730         do_facet ost1 "lljobstat -n 1 -i 0 -c 1000"
22731         do_facet ost1 "lljobstat -n 1 -i 0 -c 1000" | verify_yaml ||
22732                 error "The output of lljobstat is not an valid YAML"
22733
22734         # verify that job dd.0 does exist and has some ops on ost1
22735         # typically this line is like:
22736         # - 205e.dd.0:            {ops: 20, ...}
22737         ops_comma=$(do_facet ost1 "lljobstat -n 1 -i 0 -c 1000" |
22738                     awk '$2=="205e.dd.0:" {print $4}')
22739
22740         (( ${ops_comma%,} >= 10 )) ||
22741                 error "cannot find job 205e.dd.0 with ops >= 10"
22742 }
22743 run_test 205e "verify the output of lljobstat"
22744
22745 test_205f() {
22746         verify_yaml_available || skip_env "YAML verification not installed"
22747
22748         # check both qos_ost_weights and qos_mdt_weights
22749         do_facet mds1 $LCTL get_param -n lod.*.qos*weights
22750         do_facet mds1 $LCTL get_param -n lod.*.qos*weights | verify_yaml ||
22751                 error "qos_ost_weights is not valid YAML"
22752 }
22753 run_test 205f "verify qos_ost_weights YAML format "
22754
22755 __test_205_jobstats_dump() {
22756         local -a pids
22757         local nbr_instance=$1
22758
22759         while true; do
22760                 if (( ${#pids[@]} >= nbr_instance )); then
22761                         wait ${pids[@]}
22762                         pids=()
22763                 fi
22764
22765                 do_facet mds1 "$LCTL get_param mdt.*.job_stats > /dev/null" &
22766                 pids+=( $! )
22767         done
22768 }
22769
22770 __test_205_cleanup() {
22771         kill $@
22772         # Clear all job entries
22773         do_facet mds1 "$LCTL set_param mdt.*.job_stats=clear"
22774 }
22775
22776 test_205g() {
22777         local -a mds1_params
22778         local -a cli_params
22779         local pids
22780         local interval=5
22781
22782         mds1_params=( $(do_facet mds1 $LCTL get_param mdt.*.job_cleanup_interval) )
22783         do_facet mds1 $LCTL set_param mdt.*.job_cleanup_interval=$interval
22784         stack_trap "do_facet mds1 $LCTL set_param ${mds1_params[*]}" EXIT
22785
22786         cli_params=( $($LCTL get_param jobid_name jobid_var) )
22787         $LCTL set_param jobid_var=TEST205G_ID jobid_name=%j.%p
22788         stack_trap "$LCTL set_param ${cli_params[*]}" EXIT
22789
22790         # start jobs loop
22791         export TEST205G_ID=205g
22792         stack_trap "unset TEST205G_ID" EXIT
22793         while true; do
22794                 printf $DIR/$tfile.{0001..1000} | xargs -P10 -n1 touch
22795         done & pids="$! "
22796
22797         __test_205_jobstats_dump 4 & pids+="$! "
22798         stack_trap "__test_205_cleanup $pids" EXIT INT
22799
22800         [[ $SLOW == "no" ]] && sleep 90 || sleep 240
22801 }
22802 run_test 205g "stress test for job_stats procfile"
22803
22804 test_205h() {
22805         (( $MDS1_VERSION >= $(version_code 2.15.57.7) )) ||
22806                 skip "Need MDS >= v2_15_57-7-g23a2db28dc for jobid xattr"
22807         which getfattr > /dev/null 2>&1 || skip_env "no getfattr command"
22808
22809         local dir=$DIR/$tdir
22810         local f=$dir/$tfile
22811         local f2=$dir/$tfile-2
22812         local f3=$dir/$tfile-3
22813         local subdir=$DIR/dir
22814         local val
22815
22816         local mdts=$(mdts_nodes)
22817         local mds_saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
22818         local client_saved=$($LCTL get_param -n jobid_var)
22819
22820         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$mds_saved" EXIT
22821         stack_trap "$LCTL set_param jobid_var=$client_saved" EXIT
22822
22823         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.job ||
22824                 error "failed to set job_xattr parameter to user.job"
22825         $LCTL set_param jobid_var=procname.uid ||
22826                 error "failed to set jobid_var parameter"
22827
22828         test_mkdir $dir
22829
22830         touch $f
22831         val=$(getfattr -n user.job $f | grep user.job)
22832         [[ $val = user.job=\"touch.0\" ]] ||
22833                 error "expected user.job=\"touch.0\", got '$val'"
22834
22835         mkdir $subdir
22836         val=$(getfattr -n user.job $subdir | grep user.job)
22837         [[ $val = user.job=\"mkdir.0\" ]] ||
22838                 error "expected user.job=\"mkdir.0\", got '$val'"
22839
22840         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=NONE ||
22841                 error "failed to set job_xattr parameter to NONE"
22842
22843         touch $f2
22844         val=$(getfattr -d $f2)
22845         [[ -z $val ]] ||
22846                 error "expected no user xattr, got '$val'"
22847
22848         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=trusted.job ||
22849                 error "failed to set job_xattr parameter to trusted.job"
22850
22851         touch $f3
22852         val=$(getfattr -n trusted.job $f3 | grep trusted.job)
22853         [[ $val = trusted.job=\"touch.0\" ]] ||
22854                 error "expected trusted.job=\"touch.0\", got '$val'"
22855 }
22856 run_test 205h "check jobid xattr is stored correctly"
22857
22858 test_205i() {
22859         (( $MDS1_VERSION >= $(version_code 2.15.57.7) )) ||
22860                 skip "Need MDS >= v2_15_57-7-g23a2db28dc for jobid xattr"
22861
22862         local mdts=$(mdts_nodes)
22863         local mds_saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
22864
22865         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$mds_saved" EXIT
22866
22867         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.1234567 ||
22868                 error "failed to set mdt.*.job_xattr to user.1234567"
22869
22870         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.12345678 &&
22871                 error "failed to reject too long job_xattr name"
22872
22873         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=userjob &&
22874                 error "failed to reject job_xattr name in bad format"
22875
22876         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.job/ &&
22877                 error "failed to reject job_xattr name with invalid character"
22878
22879         do_nodes $mdts "printf 'mdt.*.job_xattr=user.job\x80' |
22880                         xargs $LCTL set_param" &&
22881                 error "failed to reject job_xattr name with non-ascii character"
22882
22883         return 0
22884 }
22885 run_test 205i "check job_xattr parameter accepts and rejects values correctly"
22886
22887         # LU-17512
22888         # test '?' operator
22889 test_205k(){
22890         (( MDS1_VERSION >= $(version_code 2.15.64.85) )) ||
22891                 skip "need MDS >= v2_15_64-85-gecdcaa3986 for jobstats fix"
22892
22893         # copied from test_205a
22894         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
22895         remote_mds_nodsh && skip "remote MDS with nodsh"
22896         [[ "$($LCTL get_param -n mdc.*.connect_flags)" =~ jobstats ]] ||
22897                 skip "Server doesn't support jobstats"
22898         [[ "$JOBID_VAR" == "disable" ]] && skip_env "jobstats is disabled"
22899
22900         local jobid_save=$($LCTL get_param jobid_var jobid_name)
22901         stack_trap "$LCTL set_param $jobid_save"
22902
22903         do_facet mds1 $LCTL set_param mdt.*.job_stats=clear
22904         $LCTL set_param jobid_var=FAKE jobid_name=%j?%H:%e:%u
22905         cp -a /etc/hosts $DIR;
22906         job_id_name=($(do_facet mds1 $LCTL get_param mdt.*.job_stats |
22907                 awk '/job_id:/ { print $3 }' | tr -d '"'))
22908         [[ "$job_id_name" == "$(hostname -s):cp:0" ]] ||
22909                 error "expected $(hostname -s):cp:0, got $job_id_name instead"
22910
22911         do_facet mds1 $LCTL set_param mdt.*.job_stats=clear
22912         $LCTL set_param jobid_var=USER jobid_name=%j?%H:%e:%u
22913         cp -a /etc/hosts $DIR;
22914         job_id_name=($(do_facet mds1 $LCTL get_param mdt.*.job_stats |
22915                         awk '/job_id:/ { print $3 }' | tr -d '"'))
22916         [[ "$job_id_name" == "$USER:cp:0" ]] ||
22917                 error "expected $USER:cp:0 but got $job_id_name instead"
22918 }
22919 run_test 205k "Verify '?' operator on job stats"
22920
22921 test_205l() {
22922         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
22923         remote_mds_nodsh && skip "remote MDS with nodsh"
22924         [[ "$($LCTL get_param -n mdc.*.connect_flags)" =~ jobstats ]] ||
22925                 skip "Server doesn't support jobstats"
22926         [[ "$JOBID_VAR" != "disable" ]] || skip_env "jobstats is disabled"
22927
22928         local jobid_save=$($LCTL get_param jobid_var jobid_name)
22929         stack_trap "$LCTL set_param $jobid_save"
22930         local tmpdir=$(mktemp -d /tmp/jobstat-XXXXXX)
22931         local jobs=$tmpdir/jobs.txt
22932         local mv_save=${tmpdir}/local_mv
22933         local mv_job
22934         local n=1
22935         local limit=500
22936         [[ $SLOW == "no" ]] || limit=500000
22937
22938         do_facet mds1 $LCTL set_param jobid_var=procname_uid jobid_name='%e.%u'
22939         cp -a /etc/hosts $DIR/hosts
22940         cp $(which mv) ${mv_save}
22941         do_facet mds1 $LCTL set_param mdt.*.job_cleanup_interval=5
22942         sleep 5
22943         do_facet mds1 $LCTL set_param mdt.*.job_stats=clear
22944         do_facet mds1 $LCTL set_param mdt.*.job_cleanup_interval=0
22945         sleep 5
22946         # Add a series of easily identifyable jobs
22947         for ((n = 0; n < limit; n++)); do
22948                 mv_job=${tmpdir}/mv.$(printf %08d $n)
22949                 mv ${mv_save} ${mv_job}
22950                 ${mv_job} $DIR/hosts $DIR/hosts.$(printf %08d $n)
22951                 ${mv_job} $DIR/hosts.$(printf %08d $n) $DIR/hosts
22952                 mv ${mv_job} ${mv_save}
22953         done
22954         # Duplicates indicate restart issues
22955         do_facet mds1 \
22956                 "$LCTL get_param mdt.*.job_stats | grep job_id: | cut -d. -f2" \
22957                 > ${jobs}
22958         local dupes=$(grep -v -e "^${RUNAS_ID}\$" -e '^0$' ${jobs} | sort |
22959                       uniq -d | wc -l)
22960         (( ${dupes} == 0 )) ||
22961                 error "seq_write wrote ${dupes} duplicate entries."
22962         # Unexpected jobs indicate cleanup issues
22963         local njobs=$(grep -v -e "^${RUNAS_ID}\$" -e '^0$' ${jobs} | wc -l)
22964         (( ${njobs} == ${limit} )) ||
22965                 error "seq_write wrote ${njobs} jobs expected ${limit}."
22966         do_facet mds1 $LCTL set_param mdt.*.job_cleanup_interval=5
22967         sleep 5
22968         do_facet mds1 $LCTL set_param mdt.*.job_stats=clear
22969         # On success the scrach files are not interesting
22970         rm -fr ${tmpdir}
22971 }
22972 run_test 205l "Verify job stats can scale"
22973
22974 test_205m() {
22975         local trunc_hostname=${HOSTNAME:0:2}
22976         local dir=$DIR/205m/
22977         local tests=(
22978             "%.3e.%u"       "cp /etc/hosts $dir" "cp.500"
22979             "%.3e.%u"       "touch $dir/1"       "tou.500"
22980             "%.3e.%u.%.2h"  "touch $dir/2"       "tou.500.${trunc_hostname}"
22981             "%.3e"          "touch $dir/3"       "tou"
22982             "%.1e.%u.%.2h"  "touch $dir/4"       "t.500.${trunc_hostname}"
22983             "%.2p"          "touch $dir/8"       '${pid:0:2}'
22984         )
22985
22986         cli_params=( $($LCTL get_param jobid_name jobid_var) )
22987         stack_trap "$LCTL set_param ${cli_params[*]}" EXIT
22988         stack_trap "do_facet mds1 $LCTL set_param mdt.*.job_stats=clear" EXIT
22989
22990         mkdir $DIR/205m
22991         chown $RUNAS_ID $DIR/205m
22992         chgrp $RUNAS_ID $DIR/205m
22993         for (( i = 0; i < ${#tests[@]} ; i += 3 )); do
22994                 local jobid_name=${tests[i]}
22995                 local cmd=${tests[i+1]}
22996
22997                 do_facet mds1 $LCTL set_param mdt.*.job_stats=clear
22998                 $LCTL set_param jobid_var=nodelocal jobid_name=${jobid_name}
22999
23000                 runas -u 500 $cmd & pid=$!
23001                 wait $pid
23002                 eval "expected=${tests[i+2]}"
23003
23004                 do_facet mds1 $LCTL get_param mdt.*.job_stats |
23005                 awk '/job_id:/ {print} /job_id:/ && $3 == "'$expected'"
23006                 {found=1} END {exit(!found)}' ||
23007                         error "expected ${expected}, got ${job_id_name} instead"
23008         done
23009 }
23010 run_test 205m "Test width parsing of job_stats"
23011
23012 # LU-1480, LU-1773 and LU-1657
23013 test_206() {
23014         mkdir -p $DIR/$tdir
23015         $LFS setstripe -c -1 $DIR/$tdir
23016 #define OBD_FAIL_LOV_INIT 0x1403
23017         $LCTL set_param fail_loc=0xa0001403
23018         $LCTL set_param fail_val=1
23019         touch $DIR/$tdir/$tfile || true
23020 }
23021 run_test 206 "fail lov_init_raid0() doesn't lbug"
23022
23023 test_207a() {
23024         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((RANDOM%10+1))
23025         local fsz=`stat -c %s $DIR/$tfile`
23026         cancel_lru_locks mdc
23027
23028         # do not return layout in getattr intent
23029 #define OBD_FAIL_MDS_NO_LL_GETATTR 0x170
23030         $LCTL set_param fail_loc=0x170
23031         local sz=`stat -c %s $DIR/$tfile`
23032
23033         [ $fsz -eq $sz ] || error "file size expected $fsz, actual $sz"
23034
23035         rm -rf $DIR/$tfile
23036 }
23037 run_test 207a "can refresh layout at glimpse"
23038
23039 test_207b() {
23040         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((RANDOM%10+1))
23041         local cksum=`md5sum $DIR/$tfile`
23042         local fsz=`stat -c %s $DIR/$tfile`
23043         cancel_lru_locks mdc
23044         cancel_lru_locks osc
23045
23046         # do not return layout in getattr intent
23047 #define OBD_FAIL_MDS_NO_LL_OPEN 0x171
23048         $LCTL set_param fail_loc=0x171
23049
23050         # it will refresh layout after the file is opened but before read issues
23051         echo checksum is "$cksum"
23052         echo "$cksum" |md5sum -c --quiet || error "file differs"
23053
23054         rm -rf $DIR/$tfile
23055 }
23056 run_test 207b "can refresh layout at open"
23057
23058 test_208() {
23059         # FIXME: in this test suite, only RD lease is used. This is okay
23060         # for now as only exclusive open is supported. After generic lease
23061         # is done, this test suite should be revised. - Jinshan
23062
23063         remote_mds_nodsh && skip "remote MDS with nodsh"
23064         [[ $MDS1_VERSION -ge $(version_code 2.4.52) ]] ||
23065                 skip "Need MDS version at least 2.4.52"
23066
23067         echo "==== test 1: verify get lease work"
23068         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:eRE+eU || error "get lease error"
23069
23070         echo "==== test 2: verify lease can be broken by upcoming open"
23071         $MULTIOP $DIR/$tfile oO_RDWR:eR_E-eUc &
23072         local PID=$!
23073         sleep 2
23074
23075         $MULTIOP $DIR/$tfile oO_RDWR:c
23076         kill -USR1 $PID && wait $PID || error "break lease error"
23077
23078         echo "==== test 3: verify lease can't be granted if an open already exists"
23079         $MULTIOP $DIR/$tfile oO_RDWR:_c &
23080         local PID=$!
23081         sleep 2
23082
23083         $MULTIOP $DIR/$tfile oO_RDWR:eReUc && error "apply lease should fail"
23084         kill -USR1 $PID && wait $PID || error "open file error"
23085
23086         echo "==== test 4: lease can sustain over recovery"
23087         $MULTIOP $DIR/$tfile oO_RDWR:eR_E+eUc &
23088         PID=$!
23089         sleep 2
23090
23091         fail mds1
23092
23093         kill -USR1 $PID && wait $PID || error "lease broken over recovery"
23094
23095         echo "==== test 5: lease broken can't be regained by replay"
23096         $MULTIOP $DIR/$tfile oO_RDWR:eR_E-eUc &
23097         PID=$!
23098         sleep 2
23099
23100         # open file to break lease and then recovery
23101         $MULTIOP $DIR/$tfile oO_RDWR:c || error "open file error"
23102         fail mds1
23103
23104         kill -USR1 $PID && wait $PID || error "lease not broken over recovery"
23105
23106         rm -f $DIR/$tfile
23107 }
23108 run_test 208 "Exclusive open"
23109
23110 test_209() {
23111         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep disp_stripe)" ] &&
23112                 skip_env "must have disp_stripe"
23113
23114         touch $DIR/$tfile
23115         sync; sleep 5; sync;
23116
23117         echo 3 > /proc/sys/vm/drop_caches
23118         [ -f /sys/kernel/slab/ptlrpc_cache/shrink ] &&
23119                 echo 1 > /sys/kernel/slab/ptlrpc_cache/shrink
23120         req_before=$(awk '/ptlrpc_cache / { print $2 }' /proc/slabinfo)
23121
23122         # open/close 500 times
23123         for i in $(seq 500); do
23124                 cat $DIR/$tfile
23125         done
23126
23127         echo 3 > /proc/sys/vm/drop_caches
23128         [ -f /sys/kernel/slab/ptlrpc_cache/shrink ] &&
23129                 echo 1 > /sys/kernel/slab/ptlrpc_cache/shrink
23130         req_after=$(awk '/ptlrpc_cache / { print $2 }' /proc/slabinfo)
23131
23132         echo "before: $req_before, after: $req_after"
23133         [ $((req_after - req_before)) -ge 300 ] &&
23134                 error "open/close requests are not freed"
23135         return 0
23136 }
23137 run_test 209 "read-only open/close requests should be freed promptly"
23138
23139 test_210() {
23140         local pid
23141
23142         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:eW_E+eUc &
23143         pid=$!
23144         sleep 1
23145
23146         $LFS getstripe $DIR/$tfile
23147         kill -USR1 $pid
23148         wait $pid || error "multiop failed"
23149
23150         $MULTIOP $DIR/$tfile oO_RDONLY:eR_E+eUc &
23151         pid=$!
23152         sleep 1
23153
23154         $LFS getstripe $DIR/$tfile
23155         kill -USR1 $pid
23156         wait $pid || error "multiop failed"
23157 }
23158 run_test 210 "lfs getstripe does not break leases"
23159
23160 test_212() {
23161         size=`date +%s`
23162         size=$((size % 8192 + 1))
23163         dd if=/dev/urandom of=$DIR/f212 bs=1k count=$size
23164         sendfile $DIR/f212 $DIR/f212.xyz || error "sendfile wrong"
23165         rm -f $DIR/f212 $DIR/f212.xyz
23166 }
23167 run_test 212 "Sendfile test ============================================"
23168
23169 test_213() {
23170         dd if=/dev/zero of=$DIR/$tfile bs=4k count=4
23171         cancel_lru_locks osc
23172         lctl set_param fail_loc=0x8000040f
23173         # generate a read lock
23174         cat $DIR/$tfile > /dev/null
23175         # write to the file, it will try to cancel the above read lock.
23176         cat /etc/hosts >> $DIR/$tfile
23177 }
23178 run_test 213 "OSC lock completion and cancel race don't crash - bug 18829"
23179
23180 test_214() { # for bug 20133
23181         mkdir -p $DIR/$tdir/d214c || error "mkdir $DIR/$tdir/d214c failed"
23182         for (( i=0; i < 340; i++ )) ; do
23183                 touch $DIR/$tdir/d214c/a$i
23184         done
23185
23186         ls -l $DIR/$tdir || error "ls -l $DIR/d214p failed"
23187         mv $DIR/$tdir/d214c $DIR/ || error "mv $DIR/d214p/d214c $DIR/ failed"
23188         ls $DIR/d214c || error "ls $DIR/d214c failed"
23189         rm -rf $DIR/$tdir || error "rm -rf $DIR/d214* failed"
23190         rm -rf $DIR/d214* || error "rm -rf $DIR/d214* failed"
23191 }
23192 run_test 214 "hash-indexed directory test - bug 20133"
23193
23194 # having "abc" as 1st arg, creates $TMP/lnet_abc.out and $TMP/lnet_abc.sys
23195 create_lnet_proc_files() {
23196         lctl get_param -n $1 >$TMP/lnet_$1.sys || error "cannot read lnet.$1"
23197 }
23198
23199 # counterpart of create_lnet_proc_files
23200 remove_lnet_proc_files() {
23201         rm -f $TMP/lnet_$1.sys
23202 }
23203
23204 # uses 1st arg as trailing part of filename, 2nd arg as description for reports,
23205 # 3rd arg as regexp for body
23206 check_lnet_proc_stats() {
23207         local l=$(cat "$TMP/lnet_$1" |wc -l)
23208         [ $l = 1 ] || (cat "$TMP/lnet_$1" && error "$2 is not of 1 line: $l")
23209
23210         grep -E "$3" "$TMP/lnet_$1" || (cat "$TMP/lnet_$1" && error "$2 misformatted")
23211 }
23212
23213 # uses 1st arg as trailing part of filename, 2nd arg as description for reports,
23214 # 3rd arg as regexp for body, 4th arg as regexp for 1st line, 5th arg is
23215 # optional and can be regexp for 2nd line (lnet.routes case)
23216 check_lnet_proc_entry() {
23217         local blp=2          # blp stands for 'position of 1st line of body'
23218         [ -z "$5" ] || blp=3 # lnet.routes case
23219
23220         local l=$(cat "$TMP/lnet_$1" |wc -l)
23221         # subtracting one from $blp because the body can be empty
23222         [ "$l" -ge "$(($blp - 1))" ] || (cat "$TMP/lnet_$1" && error "$2 is too short: $l")
23223
23224         sed -n '1 p' "$TMP/lnet_$1" |grep -E "$4" >/dev/null ||
23225                 (cat "$TMP/lnet_$1" && error "1st line of $2 misformatted")
23226
23227         [ "$5" = "" ] || sed -n '2 p' "$TMP/lnet_$1" |grep -E "$5" >/dev/null ||
23228                 (cat "$TMP/lnet_$1" && error "2nd line of $2 misformatted")
23229
23230         # bail out if any unexpected line happened
23231         sed -n "$blp p" "$TMP/lnet_$1" | grep -Ev "$3"
23232         [ "$?" != 0 ] || error "$2 misformatted"
23233 }
23234
23235 test_215() { # for bugs 18102, 21079, 21517
23236         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23237
23238         local N='(0|[1-9][0-9]*)'       # non-negative numeric
23239         local P='[1-9][0-9]*'           # positive numeric
23240         local I='(0|-?[1-9][0-9]*|NA)'  # any numeric (0 | >0 | <0) or NA if no value
23241         local NET='[a-z][a-z0-9]*'      # LNet net like o2ib2
23242         local ADDR='[0-9.]+'            # LNet addr like 10.0.0.1
23243         local ADDR6='([0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}' # IPv6 LNet addr
23244         local NID="$ADDR@$NET"          # LNet nid like 10.0.0.1@o2ib2
23245         local NID6="$ADDR6@$NET"        # LNet nid like 2601:8c1:c180::cbdd@tcp
23246
23247         local L1 # regexp for 1st line
23248         local L2 # regexp for 2nd line (optional)
23249         local BR # regexp for the rest (body)
23250
23251         # lnet.stats should look as 11 space-separated non-negative numerics
23252         BR="^$N $N $N $N $N $N $N $N $N $N $N$"
23253         create_lnet_proc_files "stats"
23254         check_lnet_proc_stats "stats.sys" "lnet.stats" "$BR"
23255         remove_lnet_proc_files "stats"
23256
23257         # lnet.routes should look like this:
23258         # Routing disabled/enabled
23259         # net hops priority state router
23260         # where net is a string like tcp0, hops > 0, priority >= 0,
23261         # state is up/down,
23262         # router is a string like 192.168.1.1@tcp2
23263         L1="^Routing (disabled|enabled)$"
23264         L2="^net +hops +priority +state +router$"
23265         BR="^$NET +$N +(0|1) +(up|down) +($NID|$NID6)$"
23266         create_lnet_proc_files "routes"
23267         check_lnet_proc_entry "routes.sys" "lnet.routes" "$BR" "$L1" "$L2"
23268         remove_lnet_proc_files "routes"
23269
23270         # lnet.routers should look like this:
23271         # ref rtr_ref alive_cnt state last_ping ping_sent deadline down_ni router
23272         # where ref > 0, rtr_ref > 0, alive_cnt >= 0, state is up/down,
23273         # last_ping >= 0, ping_sent is boolean (0/1), deadline and down_ni are
23274         # numeric (0 or >0 or <0), router is a string like 192.168.1.1@tcp2
23275         L1="^ref +rtr_ref +alive +router$"
23276         BR="^$P +$P +(up|down) +($NID|$NID6)$"
23277         create_lnet_proc_files "routers"
23278         check_lnet_proc_entry "routers.sys" "lnet.routers" "$BR" "$L1"
23279         remove_lnet_proc_files "routers"
23280
23281         # lnet.peers should look like this:
23282         # nid refs state last max rtr min tx min queue
23283         # where nid is a string like 192.168.1.1@tcp2, refs > 0,
23284         # state is up/down/NA, max >= 0. last, rtr, min, tx, min are
23285         # numeric (0 or >0 or <0), queue >= 0.
23286         L1="^nid +refs +state +last +max +rtr +min +tx +min +queue$"
23287         BR="^($NID|$NID6) +$P +(up|down|NA) +$I +$N +$I +$I +$I +$I +$N$"
23288         create_lnet_proc_files "peers"
23289         check_lnet_proc_entry "peers.sys" "lnet.peers" "$BR" "$L1"
23290         remove_lnet_proc_files "peers"
23291
23292         # lnet.buffers  should look like this:
23293         # pages count credits min
23294         # where pages >=0, count >=0, credits and min are numeric (0 or >0 or <0)
23295         L1="^pages +count +credits +min$"
23296         BR="^ +$N +$N +$I +$I$"
23297         create_lnet_proc_files "buffers"
23298         check_lnet_proc_entry "buffers.sys" "lnet.buffers" "$BR" "$L1"
23299         remove_lnet_proc_files "buffers"
23300
23301         # lnet.nis should look like this:
23302         # nid status alive refs peer rtr max tx min
23303         # where nid is a string like 192.168.1.1@tcp2, status is up/down,
23304         # alive is numeric (0 or >0 or <0), refs >= 0, peer >= 0,
23305         # rtr >= 0, max >=0, tx and min are numeric (0 or >0 or <0).
23306         L1="^nid +status +alive +refs +peer +rtr +max +tx +min$"
23307         BR="^($NID|$NID6) +(up|down) +$I +$N +$N +$N +$N +$I +$I$"
23308         create_lnet_proc_files "nis"
23309         check_lnet_proc_entry "nis.sys" "lnet.nis" "$BR" "$L1"
23310         remove_lnet_proc_files "nis"
23311
23312         # can we successfully write to lnet.stats?
23313         lctl set_param -n stats=0 || error "cannot write to lnet.stats"
23314 }
23315 run_test 215 "lnet exists and has proper content - bugs 18102, 21079, 21517"
23316
23317 test_216() { # bug 20317
23318         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23319         remote_ost_nodsh && skip "remote OST with nodsh"
23320
23321         local node
23322         local facets=$(get_facets OST)
23323         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
23324
23325         save_lustre_params $facets \
23326                 "ldlm.namespaces.filter-*.max_nolock_bytes" > $p
23327         save_lustre_params $facets \
23328                 "ldlm.namespaces.filter-*.contended_locks" >> $p
23329         save_lustre_params $facets \
23330                 "ldlm.namespaces.filter-*.contention_seconds" >> $p
23331         clear_stats osc.*.osc_stats
23332         local osts=$(osts_nodes)
23333
23334         # agressive lockless i/o settings
23335         do_nodes $osts \
23336                 "lctl set_param -n ldlm.namespaces.*.max_nolock_bytes=2000000 \
23337                         ldlm.namespaces.filter-*.contended_locks=0 \
23338                         ldlm.namespaces.filter-*.contention_seconds=60"
23339
23340         $DIRECTIO write $DIR/$tfile 0 10 4096
23341         $CHECKSTAT -s 40960 $DIR/$tfile
23342
23343         # disable lockless i/o
23344         do_nodes $osts \
23345                 "lctl set_param -n ldlm.namespaces.filter-*.max_nolock_bytes=0 \
23346                         ldlm.namespaces.filter-*.contended_locks=32 \
23347                         ldlm.namespaces.filter-*.contention_seconds=0"
23348         clear_stats osc.*.osc_stats
23349
23350         dd if=/dev/zero of=$DIR/$tfile count=0
23351         $CHECKSTAT -s 0 $DIR/$tfile
23352
23353         restore_lustre_params <$p
23354         rm -f $p
23355         rm $DIR/$tfile
23356 }
23357 run_test 216 "check lockless direct write updates file size and kms correctly"
23358
23359 test_217() { # bug 22430
23360         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23361
23362         local nodes=$(nodes_list)
23363         local node
23364
23365         for node in ${nodes//,/ }; do
23366                 local nid=$(host_nids_address $node $NETTYPE)
23367                 local node_ip=$(do_node $node getent ahostsv4 $node |
23368                                 awk '{ print $1; exit; }')
23369
23370                 echo "node: '$node', nid: '$nid', node_ip='$node_ip'"
23371                 # if hostname matches any NID, use hostname for better testing
23372                 if [[ -z "$nid" || "$nid" =~ "$node_ip" ]]; then
23373                         echo "lctl ping node $node@$NETTYPE"
23374                         lctl ping $node@$NETTYPE ||
23375                                 error "ping $node@$NETTYPE failed rc=$?"
23376                 else # otherwise, at least test 'lctl ping' is working
23377                         echo "lctl ping nid $(h2nettype $nid)"
23378                         lctl ping $(h2nettype $nid) ||
23379                                 error "ping $(h2nettype $nid) failed rc=$?"
23380                         echo "skipping $node (no hyphen detected)"
23381                 fi
23382         done
23383
23384         return 0
23385 }
23386 run_test 217 "check lctl ping for hostnames with embedded hyphen ('-')"
23387
23388 test_218() {
23389         # do directio so as not to populate the page cache
23390         log "creating a 10 Mb file"
23391         $MULTIOP $DIR/$tfile oO_CREAT:O_DIRECT:O_RDWR:w$((10*1048576))c ||
23392                 error "multiop failed while creating a file"
23393         log "starting reads"
23394         dd if=$DIR/$tfile of=/dev/null bs=4096 &
23395         log "truncating the file"
23396         $MULTIOP $DIR/$tfile oO_TRUNC:c ||
23397                 error "multiop failed while truncating the file"
23398         log "killing dd"
23399         kill %+ || true # reads might have finished
23400         echo "wait until dd is finished"
23401         wait
23402         log "removing the temporary file"
23403         rm -rf $DIR/$tfile || error "tmp file removal failed"
23404 }
23405 run_test 218 "parallel read and truncate should not deadlock"
23406
23407 test_219() {
23408         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23409
23410         # write one partial page
23411         dd if=/dev/zero of=$DIR/$tfile bs=1024 count=1
23412         # set no grant so vvp_io_commit_write will do sync write
23413         $LCTL set_param fail_loc=0x411
23414         # write a full page at the end of file
23415         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 seek=1 conv=notrunc
23416
23417         $LCTL set_param fail_loc=0
23418         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 seek=3
23419         $LCTL set_param fail_loc=0x411
23420         dd if=/dev/zero of=$DIR/$tfile bs=1024 count=1 seek=2 conv=notrunc
23421
23422         # LU-4201
23423         dd if=/dev/zero of=$DIR/$tfile-2 bs=1024 count=1
23424         $CHECKSTAT -s 1024 $DIR/$tfile-2 || error "checkstat wrong size"
23425 }
23426 run_test 219 "LU-394: Write partial won't cause uncontiguous pages vec at LND"
23427
23428 test_220() { #LU-325
23429         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23430         remote_ost_nodsh && skip "remote OST with nodsh"
23431         remote_mds_nodsh && skip "remote MDS with nodsh"
23432         remote_mgs_nodsh && skip "remote MGS with nodsh"
23433
23434         local OSTIDX=0
23435
23436         # create on MDT0000 so the last_id and next_id are correct
23437         mkdir_on_mdt0 $DIR/$tdir
23438         local OST=$($LFS df $DIR | awk '/OST:'$OSTIDX'/ { print $1 }')
23439         OST=${OST%_UUID}
23440
23441         # on the mdt's osc
23442         local mdtosc_proc1=$(get_mdtosc_proc_path $SINGLEMDS $OST)
23443         local last_id=$(do_facet $SINGLEMDS lctl get_param -n \
23444                         osp.$mdtosc_proc1.prealloc_last_id)
23445         local next_id=$(do_facet $SINGLEMDS lctl get_param -n \
23446                         osp.$mdtosc_proc1.prealloc_next_id)
23447
23448         $LFS df -i
23449
23450         do_facet ost$((OSTIDX + 1)) lctl set_param fail_val=-1
23451         #define OBD_FAIL_OST_ENOINO              0x229
23452         do_facet ost$((OSTIDX + 1)) lctl set_param fail_loc=0x229
23453         create_pool $FSNAME.$TESTNAME || return 1
23454         do_facet mgs $LCTL pool_add $FSNAME.$TESTNAME $OST || return 2
23455
23456         $LFS setstripe $DIR/$tdir -i $OSTIDX -c 1 -p $FSNAME.$TESTNAME
23457
23458         MDSOBJS=$((last_id - next_id))
23459         echo "preallocated objects on MDS is $MDSOBJS" "($last_id - $next_id)"
23460
23461         blocks=$($LFS df $MOUNT | awk '($1 == '$OSTIDX') { print $4 }')
23462         echo "OST still has $count kbytes free"
23463
23464         echo "create $MDSOBJS files @next_id..."
23465         createmany -o $DIR/$tdir/f $MDSOBJS || return 3
23466
23467         local last_id2=$(do_facet mds${MDSIDX} lctl get_param -n \
23468                         osp.$mdtosc_proc1.prealloc_last_id)
23469         local next_id2=$(do_facet mds${MDSIDX} lctl get_param -n \
23470                         osp.$mdtosc_proc1.prealloc_next_id)
23471
23472         echo "after creation, last_id=$last_id2, next_id=$next_id2"
23473         $LFS df -i
23474
23475         echo "cleanup..."
23476
23477         do_facet ost$((OSTIDX + 1)) lctl set_param fail_val=0
23478         do_facet ost$((OSTIDX + 1)) lctl set_param fail_loc=0
23479
23480         do_facet mgs $LCTL pool_remove $FSNAME.$TESTNAME $OST ||
23481                 error "$LCTL pool_remove $FSNAME.$TESTNAME $OST failed"
23482         do_facet mgs $LCTL pool_destroy $FSNAME.$TESTNAME ||
23483                 error "$LCTL pool_destroy $FSNAME.$TESTNAME failed"
23484         echo "unlink $MDSOBJS files @$next_id..."
23485         unlinkmany $DIR/$tdir/f $MDSOBJS || error "unlinkmany failed"
23486 }
23487 run_test 220 "preallocated MDS objects still used if ENOSPC from OST"
23488
23489 test_221() {
23490         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23491
23492         dd if=`which date` of=$MOUNT/date oflag=sync
23493         chmod +x $MOUNT/date
23494
23495         #define OBD_FAIL_LLITE_FAULT_TRUNC_RACE  0x1401
23496         $LCTL set_param fail_loc=0x80001401
23497
23498         $MOUNT/date > /dev/null
23499         rm -f $MOUNT/date
23500 }
23501 run_test 221 "make sure fault and truncate race to not cause OOM"
23502
23503 test_222a () {
23504         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23505
23506         rm -rf $DIR/$tdir
23507         test_mkdir $DIR/$tdir
23508         $LFS setstripe -c 1 -i 0 $DIR/$tdir
23509         createmany -o $DIR/$tdir/$tfile 10
23510         cancel_lru_locks mdc
23511         cancel_lru_locks osc
23512         #define OBD_FAIL_LDLM_AGL_DELAY           0x31a
23513         $LCTL set_param fail_loc=0x31a
23514         ls -l $DIR/$tdir > /dev/null || error "AGL for ls failed"
23515         $LCTL set_param fail_loc=0
23516         rm -r $DIR/$tdir
23517 }
23518 run_test 222a "AGL for ls should not trigger CLIO lock failure"
23519
23520 test_222b () {
23521         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23522
23523         rm -rf $DIR/$tdir
23524         test_mkdir $DIR/$tdir
23525         $LFS setstripe -c 1 -i 0 $DIR/$tdir
23526         createmany -o $DIR/$tdir/$tfile 10
23527         cancel_lru_locks mdc
23528         cancel_lru_locks osc
23529         #define OBD_FAIL_LDLM_AGL_DELAY           0x31a
23530         $LCTL set_param fail_loc=0x31a
23531         rm -r $DIR/$tdir || error "AGL for rmdir failed"
23532         $LCTL set_param fail_loc=0
23533 }
23534 run_test 222b "AGL for rmdir should not trigger CLIO lock failure"
23535
23536 test_223 () {
23537         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23538
23539         rm -rf $DIR/$tdir
23540         test_mkdir $DIR/$tdir
23541         $LFS setstripe -c 1 -i 0 $DIR/$tdir
23542         createmany -o $DIR/$tdir/$tfile 10
23543         cancel_lru_locks mdc
23544         cancel_lru_locks osc
23545         #define OBD_FAIL_LDLM_AGL_NOLOCK          0x31b
23546         $LCTL set_param fail_loc=0x31b
23547         ls -l $DIR/$tdir > /dev/null || error "reenqueue failed"
23548         $LCTL set_param fail_loc=0
23549         rm -r $DIR/$tdir
23550 }
23551 run_test 223 "osc reenqueue if without AGL lock granted ======================="
23552
23553 test_224a() { # LU-1039, MRP-303
23554         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23555         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB   0x508
23556         $LCTL set_param fail_loc=0x508
23557         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 conv=fsync
23558         stack_trap "rm -f $DIR/$tfile"
23559         $LCTL set_param fail_loc=0
23560         df $DIR
23561 }
23562 run_test 224a "Don't panic on bulk IO failure"
23563
23564 test_224bd_sub() { # LU-1039, MRP-303
23565         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23566         local timeout=$1
23567
23568         shift
23569         dd if=/dev/urandom of=$TMP/$tfile bs=1M count=1
23570
23571         $LFS setstripe -c 1 -i 0 $DIR/$tfile
23572
23573         dd if=$TMP/$tfile of=$DIR/$tfile bs=1M count=1
23574         stack_trap "rm -f $DIR/$tfile"
23575         cancel_lru_locks osc
23576         set_checksums 0
23577         stack_trap "set_checksums $ORIG_CSUM" EXIT
23578         local at_max_saved=0
23579
23580         # adaptive timeouts may prevent seeing the issue
23581         if at_is_enabled; then
23582                 at_max_saved=$(at_max_get mds)
23583                 at_max_set 0 mds client
23584                 stack_trap "at_max_set $at_max_saved mds client" EXIT
23585         fi
23586
23587         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB2   0x515
23588         do_facet ost1 $LCTL set_param fail_val=$timeout fail_loc=0x80000515
23589         dd of=$TMP/$tfile.new if=$DIR/$tfile bs=1M count=1 || "$@"
23590
23591         do_facet ost1 $LCTL set_param fail_loc=0
23592         cmp $TMP/$tfile $TMP/$tfile.new || error "file contents wrong"
23593         df $DIR
23594 }
23595
23596 test_224b() {
23597         test_224bd_sub 3 error "dd failed"
23598 }
23599 run_test 224b "Don't panic on bulk IO failure"
23600
23601 test_224c() { # LU-6441
23602         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23603         remote_mds_nodsh && skip "remote MDS with nodsh"
23604
23605         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
23606         local osts=$(osts_nodes)
23607
23608         save_writethrough $p
23609         set_cache $osts writethrough on
23610
23611         local pages_per_rpc=$($LCTL get_param osc.*.max_pages_per_rpc)
23612         local at_max=$($LCTL get_param -n at_max)
23613         local timeout=$($LCTL get_param -n timeout)
23614         local test_at="at_max"
23615         local param_at="$FSNAME.sys.at_max"
23616         local test_timeout="timeout"
23617         local param_timeout="$FSNAME.sys.timeout"
23618
23619         $LCTL set_param -n osc.*.max_pages_per_rpc=1024
23620
23621         set_persistent_param_and_check client "$test_at" "$param_at" 0
23622         set_persistent_param_and_check client "$test_timeout" "$param_timeout" 5
23623
23624         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB3 0x520
23625         do_facet ost1 "$LCTL set_param fail_loc=0x520"
23626         $LFS setstripe -c 1 -i 0 $DIR/$tfile
23627         stack_trap "rm -f $DIR/$tfile"
23628         dd if=/dev/zero of=$DIR/$tfile bs=8MB count=1
23629         sync
23630         do_facet ost1 "$LCTL set_param fail_loc=0"
23631
23632         set_persistent_param_and_check client "$test_at" "$param_at" $at_max
23633         set_persistent_param_and_check client "$test_timeout" "$param_timeout" \
23634                 $timeout
23635
23636         $LCTL set_param -n $pages_per_rpc
23637         restore_lustre_params < $p
23638         rm -f $p
23639 }
23640 run_test 224c "Don't hang if one of md lost during large bulk RPC"
23641
23642 test_224d() { # LU-11169
23643         test_224bd_sub $((TIMEOUT + 2)) error "dd failed"
23644 }
23645 run_test 224d "Don't corrupt data on bulk IO timeout"
23646
23647 MDSSURVEY=${MDSSURVEY:-$(which mds-survey 2>/dev/null || true)}
23648 test_225a () {
23649         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23650         if [ -z ${MDSSURVEY} ]; then
23651                 skip_env "mds-survey not found"
23652         fi
23653         [ $MDS1_VERSION -ge $(version_code 2.2.51) ] ||
23654                 skip "Need MDS version at least 2.2.51"
23655
23656         local mds=$(facet_host $SINGLEMDS)
23657         local target=$(do_nodes $mds 'lctl dl' |
23658                        awk '{ if ($2 == "UP" && $3 == "mdt") { print $4 }}')
23659
23660         local cmd1="file_count=1000 thrhi=4"
23661         local cmd2="dir_count=2 layer=mdd stripe_count=0"
23662         local cmd3="rslt_loc=${TMP} targets=\"$mds:$target\" $MDSSURVEY"
23663         local cmd="$cmd1 $cmd2 $cmd3"
23664
23665         rm -f ${TMP}/mds_survey*
23666         echo + $cmd
23667         eval $cmd || error "mds-survey with zero-stripe failed"
23668         cat ${TMP}/mds_survey*
23669         rm -f ${TMP}/mds_survey*
23670 }
23671 run_test 225a "Metadata survey sanity with zero-stripe"
23672
23673 test_225b () {
23674         if [ -z ${MDSSURVEY} ]; then
23675                 skip_env "mds-survey not found"
23676         fi
23677         [ $MDS1_VERSION -ge $(version_code 2.2.51) ] ||
23678                 skip "Need MDS version at least 2.2.51"
23679         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23680         remote_mds_nodsh && skip "remote MDS with nodsh"
23681         if [ $($LCTL dl | grep -c osc) -eq 0 ]; then
23682                 skip_env "Need to mount OST to test"
23683         fi
23684
23685         local mds=$(facet_host $SINGLEMDS)
23686         local target=$(do_nodes $mds 'lctl dl' |
23687                        awk '{ if ($2 == "UP" && $3 == "mdt") { print $4 }}')
23688
23689         local cmd1="file_count=1000 thrhi=4"
23690         local cmd2="dir_count=2 layer=mdd stripe_count=1"
23691         local cmd3="rslt_loc=${TMP} targets=\"$mds:$target\" $MDSSURVEY"
23692         local cmd="$cmd1 $cmd2 $cmd3"
23693
23694         rm -f ${TMP}/mds_survey*
23695         echo + $cmd
23696         eval $cmd || error "mds-survey with stripe_count failed"
23697         cat ${TMP}/mds_survey*
23698         rm -f ${TMP}/mds_survey*
23699 }
23700 run_test 225b "Metadata survey sanity with stripe_count = 1"
23701
23702 mcreate_path2fid () {
23703         local mode=$1
23704         local major=$2
23705         local minor=$3
23706         local name=$4
23707         local desc=$5
23708         local path=$DIR/$tdir/$name
23709         local fid
23710         local rc
23711         local fid_path
23712
23713         $MCREATE --mode=$1 --major=$2 --minor=$3 $path ||
23714                 error "cannot create $desc"
23715
23716         fid=$($LFS path2fid $path | tr -d '[' | tr -d ']')
23717         rc=$?
23718         [ $rc -ne 0 ] && error "cannot get fid of a $desc"
23719
23720         fid_path=$($LFS fid2path $MOUNT $fid)
23721         rc=$?
23722         [ $rc -ne 0 ] && error "cannot get path of $desc by $DIR $path $fid"
23723
23724         [ "$path" == "$fid_path" ] ||
23725                 error "fid2path returned $fid_path, expected $path"
23726
23727         echo "pass with $path and $fid"
23728 }
23729
23730 test_226a () {
23731         rm -rf $DIR/$tdir
23732         mkdir -p $DIR/$tdir
23733
23734         mcreate_path2fid 0010666 0 0 fifo "FIFO"
23735         mcreate_path2fid 0020666 1 3 null "character special file (null)"
23736         mcreate_path2fid 0020666 1 255 none "character special file (no device)"
23737         mcreate_path2fid 0040666 0 0 dir "directory"
23738         mcreate_path2fid 0060666 7 0 loop0 "block special file (loop)"
23739         mcreate_path2fid 0100666 0 0 file "regular file"
23740         mcreate_path2fid 0120666 0 0 link "symbolic link"
23741         mcreate_path2fid 0140666 0 0 sock "socket"
23742 }
23743 run_test 226a "call path2fid and fid2path on files of all type"
23744
23745 test_226b () {
23746         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
23747
23748         local MDTIDX=1
23749
23750         rm -rf $DIR/$tdir
23751         mkdir -p $DIR/$tdir
23752         $LFS setdirstripe -i $MDTIDX $DIR/$tdir/remote_dir ||
23753                 error "create remote directory failed"
23754         mcreate_path2fid 0010666 0 0 "remote_dir/fifo" "FIFO"
23755         mcreate_path2fid 0020666 1 3 "remote_dir/null" \
23756                                 "character special file (null)"
23757         mcreate_path2fid 0020666 1 255 "remote_dir/none" \
23758                                 "character special file (no device)"
23759         mcreate_path2fid 0040666 0 0 "remote_dir/dir" "directory"
23760         mcreate_path2fid 0060666 7 0 "remote_dir/loop0" \
23761                                 "block special file (loop)"
23762         mcreate_path2fid 0100666 0 0 "remote_dir/file" "regular file"
23763         mcreate_path2fid 0120666 0 0 "remote_dir/link" "symbolic link"
23764         mcreate_path2fid 0140666 0 0 "remote_dir/sock" "socket"
23765 }
23766 run_test 226b "call path2fid and fid2path on files of all type under remote dir"
23767
23768 test_226c () {
23769         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
23770         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
23771                 skip "Need MDS version at least 2.13.55"
23772
23773         local submnt=/mnt/submnt
23774         local srcfile=/etc/passwd
23775         local dstfile=$submnt/passwd
23776         local path
23777         local fid
23778
23779         rm -rf $DIR/$tdir
23780         rm -rf $submnt
23781         $LFS setdirstripe -c -1 -i 1 $DIR/$tdir ||
23782                 error "create remote directory failed"
23783         mkdir -p $submnt || error "create $submnt failed"
23784         FILESET="$FILESET/$tdir" mount_client $submnt ||
23785                 error "mount $submnt failed"
23786         stack_trap "umount $submnt;rm -rf $submit" EXIT
23787
23788         cp $srcfile $dstfile
23789         fid=$($LFS path2fid $dstfile)
23790         path=$($LFS fid2path $submnt "$fid")
23791         [ "$path" = "$dstfile" ] ||
23792                 error "fid2path $submnt $fid failed ($path != $dstfile)"
23793 }
23794 run_test 226c "call path2fid and fid2path under remote dir with subdir mount"
23795
23796 test_226d () {
23797         (( $CLIENT_VERSION >= $(version_code 2.15.57) )) ||
23798                 skip "Need client at least version 2.15.57"
23799
23800         # Define First test dataset
23801         local testdirs_01=$DIR/$tdir
23802         local testdata_01=$testdirs_01/${tdir}_01
23803         local testresult_01=${tdir}_01
23804         # Define Second test dataset
23805         local testdirs_02=$DIR/$tdir/$tdir
23806         local testdata_02=$testdirs_02/${tdir}_02
23807         local testresult_02=${tdir}_02
23808         # Define third test dataset (top level)
23809         local testdata_03=$DIR/${tdir}_03
23810         local testresult_03=${tdir}_03
23811
23812         # Create first test dataset
23813         mkdir -p $testdirs_01 || error "cannot create dir $testdirs_01"
23814         touch $testdata_01 || error "cannot create file $testdata_01"
23815
23816         # Create second test dataset
23817         mkdir -p $testdirs_02 || error "cannot create dir $testdirs_02"
23818         touch $testdata_02 || error "cannot create file $testdata_02"
23819
23820         # Create third test dataset
23821         touch $testdata_03 || error "cannot create file $testdata_03"
23822
23823         local fid01=$($LFS getstripe -F "$testdata_01") ||
23824                 error "getstripe failed on $testdata_01"
23825         local fid02=$($LFS getstripe -F "$testdata_02") ||
23826                 error "getstripe failed on $testdata_01"
23827         local fid03=$($LFS getstripe -F "$testdata_03") ||
23828                 error "getstripe failed on $testdata_03"
23829
23830         # Verify only -n option
23831         local out1=$($LFS fid2path -n $DIR $fid01) ||
23832                 error "fid2path failed on $fid01"
23833         local out2=$($LFS fid2path -n $DIR $fid02) ||
23834                 error "fid2path failed on $fid02"
23835         local out3=$($LFS fid2path -n $DIR $fid03) ||
23836                 error "fid2path failed on $fid03"
23837
23838         [[ "$out1" == "$testresult_01" ]] ||
23839                 error "fid2path failed: Expected $testresult_01 got $out1"
23840         [[ "$out2" == "$testresult_02" ]] ||
23841                 error "fid2path failed: Expected $testresult_02 got $out2"
23842         [[ "$out3" == "$testresult_03" ]] ||
23843                 error "fid2path failed: Expected $testresult_03 got $out3"
23844
23845         # Verify with option -fn together
23846         out1=$($LFS fid2path -fn $DIR $fid01) ||
23847                 error "fid2path -fn failed on $fid01"
23848         out2=$($LFS fid2path -fn $DIR $fid02) ||
23849                 error "fid2path -fn failed on $fid02"
23850         out3=$($LFS fid2path -fn $DIR $fid03) ||
23851                 error "fid2path -fn failed on $fid03"
23852
23853         local tmpout=$(echo $out1 | cut -d" " -f2)
23854         [[ "$tmpout" == "$testresult_01" ]] ||
23855                 error "fid2path -fn failed: Expected $testresult_01 got $out1"
23856
23857         tmpout=$(echo $out2 | cut -d" " -f2)
23858         [[ "$tmpout" == "$testresult_02" ]] ||
23859                 error "fid2path -fn failed: Expected $testresult_02 got $out2"
23860
23861         tmpout=$(echo $out3 | cut -d" " -f2)
23862         [[ "$tmpout" == "$testresult_03" ]] ||
23863                 error "fid2path -fn failed: Expected $testresult_03 got $out3"
23864 }
23865 run_test 226d "verify fid2path with -n and -fn option"
23866
23867 test_226e () {
23868         (( $CLIENT_VERSION >= $(version_code 2.15.56) )) ||
23869                 skip "Need client at least version 2.15.56"
23870
23871         # Define filename with 'newline' and a space
23872         local testfile="Test"$'\n'"file 01"
23873         # Define link name with multiple 'newline' and a space
23874         local linkfile="Link"$'\n'"file "$'\n'"01"
23875         # Remove prior hard link
23876         rm -f $DIR/"$linkfile"
23877
23878         # Create file
23879         touch $DIR/"$testfile"
23880         # Create link
23881         ln $DIR/"$testfile" $DIR/"$linkfile"
23882
23883         local fid=$($LFS getstripe -F "$DIR/$testfile") ||
23884                 error "getstripe failed on $DIR/$testfile"
23885
23886         # Call with -0 option
23887         local out1=$($LFS fid2path -0 $DIR $fid | xargs --null -n1 \
23888                 echo "FILE:" | grep -c "FILE:")
23889
23890         # With -0 option the output should be exactly 2 lines.
23891         (( $out1 == 2 )) || error "fid2path -0 failed on $fid, $out1"
23892 }
23893 run_test 226e "Verify path2fid -0 option with newline and space"
23894
23895 # LU-1299 Executing or running ldd on a truncated executable does not
23896 # cause an out-of-memory condition.
23897 test_227() {
23898         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23899         [ -z "$(which ldd)" ] && skip_env "should have ldd tool"
23900
23901         dd if=$(which date) of=$MOUNT/date bs=1k count=1
23902         chmod +x $MOUNT/date
23903
23904         $MOUNT/date > /dev/null
23905         ldd $MOUNT/date > /dev/null
23906         rm -f $MOUNT/date
23907 }
23908 run_test 227 "running truncated executable does not cause OOM"
23909
23910 # LU-1512 try to reuse idle OI blocks
23911 test_228a() {
23912         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23913         remote_mds_nodsh && skip "remote MDS with nodsh"
23914         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
23915
23916         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
23917         local myDIR=$DIR/$tdir
23918
23919         mkdir -p $myDIR
23920         #define OBD_FAIL_SEQ_EXHAUST             0x1002
23921         $LCTL set_param fail_loc=0x80001002
23922         createmany -o $myDIR/t- 10000
23923         $LCTL set_param fail_loc=0
23924         # The guard is current the largest FID holder
23925         touch $myDIR/guard
23926         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
23927                     tr -d '[')
23928         local IDX=$(($SEQ % 64))
23929
23930         do_facet $SINGLEMDS sync
23931         # Make sure journal flushed.
23932         sleep 6
23933         local blk1=$(do_facet $SINGLEMDS \
23934                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
23935                      grep Blockcount | awk '{print $4}')
23936
23937         # Remove old files, some OI blocks will become idle.
23938         unlinkmany $myDIR/t- 10000
23939         # Create new files, idle OI blocks should be reused.
23940         createmany -o $myDIR/t- 2000
23941         do_facet $SINGLEMDS sync
23942         # Make sure journal flushed.
23943         sleep 6
23944         local blk2=$(do_facet $SINGLEMDS \
23945                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
23946                      grep Blockcount | awk '{print $4}')
23947
23948         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
23949 }
23950 run_test 228a "try to reuse idle OI blocks"
23951
23952 test_228b() {
23953         [ $PARALLEL == "yes" ] && skip "skip parallel run"
23954         remote_mds_nodsh && skip "remote MDS with nodsh"
23955         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
23956
23957         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
23958         local myDIR=$DIR/$tdir
23959
23960         mkdir -p $myDIR
23961         #define OBD_FAIL_SEQ_EXHAUST             0x1002
23962         $LCTL set_param fail_loc=0x80001002
23963         createmany -o $myDIR/t- 10000
23964         $LCTL set_param fail_loc=0
23965         # The guard is current the largest FID holder
23966         touch $myDIR/guard
23967         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
23968                     tr -d '[')
23969         local IDX=$(($SEQ % 64))
23970
23971         do_facet $SINGLEMDS sync
23972         # Make sure journal flushed.
23973         sleep 6
23974         local blk1=$(do_facet $SINGLEMDS \
23975                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
23976                      grep Blockcount | awk '{print $4}')
23977
23978         # Remove old files, some OI blocks will become idle.
23979         unlinkmany $myDIR/t- 10000
23980
23981         # stop the MDT
23982         stop $SINGLEMDS || error "Fail to stop MDT."
23983         # remount the MDT
23984         start $SINGLEMDS $(facet_device $SINGLEMDS) $MDS_MOUNT_OPTS ||
23985                 error "Fail to start MDT."
23986
23987         client_up || error "Fail to df."
23988         # Create new files, idle OI blocks should be reused.
23989         createmany -o $myDIR/t- 2000
23990         do_facet $SINGLEMDS sync
23991         # Make sure journal flushed.
23992         sleep 6
23993         local blk2=$(do_facet $SINGLEMDS \
23994                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
23995                      grep Blockcount | awk '{print $4}')
23996
23997         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
23998 }
23999 run_test 228b "idle OI blocks can be reused after MDT restart"
24000
24001 #LU-1881
24002 test_228c() {
24003         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24004         remote_mds_nodsh && skip "remote MDS with nodsh"
24005         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
24006
24007         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
24008         local myDIR=$DIR/$tdir
24009
24010         mkdir -p $myDIR
24011         #define OBD_FAIL_SEQ_EXHAUST             0x1002
24012         $LCTL set_param fail_loc=0x80001002
24013         # 20000 files can guarantee there are index nodes in the OI file
24014         createmany -o $myDIR/t- 20000
24015         $LCTL set_param fail_loc=0
24016         # The guard is current the largest FID holder
24017         touch $myDIR/guard
24018         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
24019                     tr -d '[')
24020         local IDX=$(($SEQ % 64))
24021
24022         do_facet $SINGLEMDS sync
24023         # Make sure journal flushed.
24024         sleep 6
24025         local blk1=$(do_facet $SINGLEMDS \
24026                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
24027                      grep Blockcount | awk '{print $4}')
24028
24029         # Remove old files, some OI blocks will become idle.
24030         unlinkmany $myDIR/t- 20000
24031         rm -f $myDIR/guard
24032         # The OI file should become empty now
24033
24034         # Create new files, idle OI blocks should be reused.
24035         createmany -o $myDIR/t- 2000
24036         do_facet $SINGLEMDS sync
24037         # Make sure journal flushed.
24038         sleep 6
24039         local blk2=$(do_facet $SINGLEMDS \
24040                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
24041                      grep Blockcount | awk '{print $4}')
24042
24043         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
24044 }
24045 run_test 228c "NOT shrink the last entry in OI index node to recycle idle leaf"
24046
24047 test_229() { # LU-2482, LU-3448
24048         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
24049         (( $OSTCOUNT >= 2 )) || skip_env "needs >= 2 OSTs"
24050         (( $MDS1_VERSION >= $(version_code 2.4.50.0-53-ga61ff5914b) )) ||
24051                 skip "need MDS >= 2.4.50.53 for HSM released file"
24052
24053         rm -f $DIR/$tfile
24054
24055         # Create a file with a released layout and stripe count 2.
24056         $MULTIOP $DIR/$tfile H2c ||
24057                 error "failed to create file with released layout"
24058
24059         $LFS getstripe -v $DIR/$tfile
24060
24061         local pattern=$($LFS getstripe -L $DIR/$tfile)
24062         [[ "$pattern" =~ "released" ]] || error "pattern error ($pattern)"
24063
24064         local stripe_count=$($LFS getstripe -c $DIR/$tfile) ||
24065                 error "getstripe"
24066         (( $stripe_count == 2 )) || error "stripe count not 2 ($stripe_count)"
24067         stat $DIR/$tfile || error "failed to stat released file"
24068
24069         chown $RUNAS_ID $DIR/$tfile ||
24070                 error "chown $RUNAS_ID $DIR/$tfile failed"
24071
24072         chgrp $RUNAS_ID $DIR/$tfile ||
24073                 error "chgrp $RUNAS_ID $DIR/$tfile failed"
24074
24075         touch $DIR/$tfile || error "touch $DIR/$tfile failed"
24076         rm $DIR/$tfile || error "failed to remove released file"
24077 }
24078 run_test 229 "getstripe/stat/rm/attr changes work on released files"
24079
24080 test_230a() {
24081         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24082         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24083         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24084                 skip "Need MDS version at least 2.11.52"
24085
24086         local MDTIDX=1
24087
24088         test_mkdir $DIR/$tdir
24089         test_mkdir -i0 -c1 $DIR/$tdir/test_230_local
24090         local mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230_local)
24091         [ $mdt_idx -ne 0 ] &&
24092                 error "create local directory on wrong MDT $mdt_idx"
24093
24094         $LFS mkdir -i $MDTIDX $DIR/$tdir/test_230 ||
24095                         error "create remote directory failed"
24096         local mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230)
24097         [ $mdt_idx -ne $MDTIDX ] &&
24098                 error "create remote directory on wrong MDT $mdt_idx"
24099
24100         createmany -o $DIR/$tdir/test_230/t- 10 ||
24101                 error "create files on remote directory failed"
24102         mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230/t-0)
24103         [ $mdt_idx -ne $MDTIDX ] && error "create files on wrong MDT $mdt_idx"
24104         rm -r $DIR/$tdir || error "unlink remote directory failed"
24105 }
24106 run_test 230a "Create remote directory and files under the remote directory"
24107
24108 test_230b() {
24109         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24110         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24111         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24112                 skip "Need MDS version at least 2.11.52"
24113
24114         local MDTIDX=1
24115         local mdt_index
24116         local i
24117         local file
24118         local pid
24119         local stripe_count
24120         local migrate_dir=$DIR/$tdir/migrate_dir
24121         local other_dir=$DIR/$tdir/other_dir
24122
24123         test_mkdir $DIR/$tdir
24124         test_mkdir -i0 -c1 $migrate_dir
24125         test_mkdir -i0 -c1 $other_dir
24126         for ((i=0; i<10; i++)); do
24127                 mkdir -p $migrate_dir/dir_${i}
24128                 createmany -o $migrate_dir/dir_${i}/f 10 ||
24129                         error "create files under remote dir failed $i"
24130         done
24131
24132         cp /etc/passwd $migrate_dir/$tfile
24133         cp /etc/passwd $other_dir/$tfile
24134         chattr +SAD $migrate_dir
24135         chattr +SAD $migrate_dir/$tfile
24136
24137         local old_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
24138         local old_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
24139         local old_dir_mode=$(stat -c%f $migrate_dir)
24140         local old_file_mode=$(stat -c%f $migrate_dir/$tfile)
24141
24142         mkdir -p $migrate_dir/dir_default_stripe2
24143         $LFS setstripe -c 2 $migrate_dir/dir_default_stripe2
24144         $LFS setstripe -c 2 $migrate_dir/${tfile}_stripe2
24145
24146         mkdir -p $other_dir
24147         ln $migrate_dir/$tfile $other_dir/luna
24148         ln $migrate_dir/$tfile $migrate_dir/sofia
24149         ln $other_dir/$tfile $migrate_dir/david
24150         ln -s $migrate_dir/$tfile $other_dir/zachary
24151         ln -s $migrate_dir/$tfile $migrate_dir/${tfile}_ln
24152         ln -s $other_dir/$tfile $migrate_dir/${tfile}_ln_other
24153
24154         local len
24155         local lnktgt
24156
24157         # inline symlink
24158         for len in 58 59 60; do
24159                 lnktgt=$(str_repeat 'l' $len)
24160                 touch $migrate_dir/$lnktgt
24161                 ln -s $lnktgt $migrate_dir/${len}char_ln
24162         done
24163
24164         # PATH_MAX
24165         for len in 4094 4095; do
24166                 lnktgt=$(str_repeat 'l' $len)
24167                 ln -s $lnktgt $migrate_dir/${len}char_ln
24168         done
24169
24170         # NAME_MAX
24171         for len in 254 255; do
24172                 touch $migrate_dir/$(str_repeat 'l' $len)
24173         done
24174
24175         $LFS migrate -m $MDTIDX $migrate_dir ||
24176                 error "fails on migrating remote dir to MDT1"
24177
24178         echo "migratate to MDT1, then checking.."
24179         for ((i = 0; i < 10; i++)); do
24180                 for file in $(find $migrate_dir/dir_${i}); do
24181                         mdt_index=$($LFS getstripe -m $file)
24182                         # broken symlink getstripe will fail
24183                         [ $mdt_index -ne $MDTIDX ] && stat -L $file &&
24184                                 error "$file is not on MDT${MDTIDX}"
24185                 done
24186         done
24187
24188         # the multiple link file should still in MDT0
24189         mdt_index=$($LFS getstripe -m $migrate_dir/$tfile)
24190         [ $mdt_index == 0 ] ||
24191                 error "$file is not on MDT${MDTIDX}"
24192
24193         local new_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
24194         [ "$old_dir_flag" = "$new_dir_flag" ] ||
24195                 error " expect $old_dir_flag get $new_dir_flag"
24196
24197         local new_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
24198         [ "$old_file_flag" = "$new_file_flag" ] ||
24199                 error " expect $old_file_flag get $new_file_flag"
24200
24201         local new_dir_mode=$(stat -c%f $migrate_dir)
24202         [ "$old_dir_mode" = "$new_dir_mode" ] ||
24203                 error "expect mode $old_dir_mode get $new_dir_mode"
24204
24205         local new_file_mode=$(stat -c%f $migrate_dir/$tfile)
24206         [ "$old_file_mode" = "$new_file_mode" ] ||
24207                 error "expect mode $old_file_mode get $new_file_mode"
24208
24209         diff /etc/passwd $migrate_dir/$tfile ||
24210                 error "$tfile different after migration"
24211
24212         diff /etc/passwd $other_dir/luna ||
24213                 error "luna different after migration"
24214
24215         diff /etc/passwd $migrate_dir/sofia ||
24216                 error "sofia different after migration"
24217
24218         diff /etc/passwd $migrate_dir/david ||
24219                 error "david different after migration"
24220
24221         diff /etc/passwd $other_dir/zachary ||
24222                 error "zachary different after migration"
24223
24224         diff /etc/passwd $migrate_dir/${tfile}_ln ||
24225                 error "${tfile}_ln different after migration"
24226
24227         diff /etc/passwd $migrate_dir/${tfile}_ln_other ||
24228                 error "${tfile}_ln_other different after migration"
24229
24230         stripe_count=$($LFS getstripe -c $migrate_dir/dir_default_stripe2)
24231         [ $stripe_count = 2 ] ||
24232                 error "dir strpe_count $d != 2 after migration."
24233
24234         stripe_count=$($LFS getstripe -c $migrate_dir/${tfile}_stripe2)
24235         [ $stripe_count = 2 ] ||
24236                 error "file strpe_count $d != 2 after migration."
24237
24238         #migrate back to MDT0
24239         MDTIDX=0
24240
24241         $LFS migrate -m $MDTIDX $migrate_dir ||
24242                 error "fails on migrating remote dir to MDT0"
24243
24244         echo "migrate back to MDT0, checking.."
24245         for file in $(find $migrate_dir); do
24246                 mdt_index=$($LFS getstripe -m $file)
24247                 [ $mdt_index -ne $MDTIDX ] && stat -L $file &&
24248                         error "$file is not on MDT${MDTIDX}"
24249         done
24250
24251         local new_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
24252         [ "$old_dir_flag" = "$new_dir_flag" ] ||
24253                 error " expect $old_dir_flag get $new_dir_flag"
24254
24255         local new_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
24256         [ "$old_file_flag" = "$new_file_flag" ] ||
24257                 error " expect $old_file_flag get $new_file_flag"
24258
24259         local new_dir_mode=$(stat -c%f $migrate_dir)
24260         [ "$old_dir_mode" = "$new_dir_mode" ] ||
24261                 error "expect mode $old_dir_mode get $new_dir_mode"
24262
24263         local new_file_mode=$(stat -c%f $migrate_dir/$tfile)
24264         [ "$old_file_mode" = "$new_file_mode" ] ||
24265                 error "expect mode $old_file_mode get $new_file_mode"
24266
24267         diff /etc/passwd ${migrate_dir}/$tfile ||
24268                 error "$tfile different after migration"
24269
24270         diff /etc/passwd ${other_dir}/luna ||
24271                 error "luna different after migration"
24272
24273         diff /etc/passwd ${migrate_dir}/sofia ||
24274                 error "sofia different after migration"
24275
24276         diff /etc/passwd ${other_dir}/zachary ||
24277                 error "zachary different after migration"
24278
24279         diff /etc/passwd $migrate_dir/${tfile}_ln ||
24280                 error "${tfile}_ln different after migration"
24281
24282         diff /etc/passwd $migrate_dir/${tfile}_ln_other ||
24283                 error "${tfile}_ln_other different after migration"
24284
24285         stripe_count=$($LFS getstripe -c ${migrate_dir}/dir_default_stripe2)
24286         [ $stripe_count = 2 ] ||
24287                 error "dir strpe_count $d != 2 after migration."
24288
24289         stripe_count=$($LFS getstripe -c ${migrate_dir}/${tfile}_stripe2)
24290         [ $stripe_count = 2 ] ||
24291                 error "file strpe_count $d != 2 after migration."
24292
24293         rm -rf $DIR/$tdir || error "rm dir failed after migration"
24294 }
24295 run_test 230b "migrate directory"
24296
24297 test_230c() {
24298         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24299         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24300         remote_mds_nodsh && skip "remote MDS with nodsh"
24301         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24302                 skip "Need MDS version at least 2.11.52"
24303
24304         local MDTIDX=1
24305         local total=3
24306         local mdt_index
24307         local file
24308         local migrate_dir=$DIR/$tdir/migrate_dir
24309
24310         #If migrating directory fails in the middle, all entries of
24311         #the directory is still accessiable.
24312         test_mkdir $DIR/$tdir
24313         test_mkdir -i0 -c1 $migrate_dir
24314         test_mkdir -i1 -c1 $DIR/$tdir/remote_dir
24315         stat $migrate_dir
24316         createmany -o $migrate_dir/f $total ||
24317                 error "create files under ${migrate_dir} failed"
24318
24319         # fail after migrating top dir, and this will fail only once, so the
24320         # first sub file migration will fail (currently f3), others succeed.
24321         #OBD_FAIL_MIGRATE_ENTRIES       0x1801
24322         do_facet mds1 lctl set_param fail_loc=0x1801
24323         local t=$(ls $migrate_dir | wc -l)
24324         $LFS migrate --mdt-index $MDTIDX $migrate_dir &&
24325                 error "migrate should fail"
24326         local u=$(ls $migrate_dir | wc -l)
24327         [ "$u" == "$t" ] || error "$u != $t during migration"
24328
24329         # add new dir/file should succeed
24330         mkdir $migrate_dir/dir ||
24331                 error "mkdir failed under migrating directory"
24332         touch $migrate_dir/file ||
24333                 error "create file failed under migrating directory"
24334
24335         # add file with existing name should fail
24336         for file in $migrate_dir/f*; do
24337                 stat $file > /dev/null || error "stat $file failed"
24338                 $OPENFILE -f O_CREAT:O_EXCL $file &&
24339                         error "open(O_CREAT|O_EXCL) $file should fail"
24340                 $MULTIOP $file m && error "create $file should fail"
24341                 touch $DIR/$tdir/remote_dir/$tfile ||
24342                         error "touch $tfile failed"
24343                 ln $DIR/$tdir/remote_dir/$tfile $file &&
24344                         error "link $file should fail"
24345                 mdt_index=$($LFS getstripe -m $file)
24346                 if [ $mdt_index == 0 ]; then
24347                         # file failed to migrate is not allowed to rename to
24348                         mv $DIR/$tdir/remote_dir/$tfile $file &&
24349                                 error "rename to $file should fail"
24350                 else
24351                         mv $DIR/$tdir/remote_dir/$tfile $file ||
24352                                 error "rename to $file failed"
24353                 fi
24354                 echo hello >> $file || error "write $file failed"
24355         done
24356
24357         # resume migration with different options should fail
24358         $LFS migrate -m 0 $migrate_dir &&
24359                 error "migrate -m 0 $migrate_dir should fail"
24360
24361         $LFS migrate -m $MDTIDX -c 2 $migrate_dir &&
24362                 error "migrate -c 2 $migrate_dir should fail"
24363
24364         # resume migration should succeed
24365         $LFS migrate -m $MDTIDX $migrate_dir ||
24366                 error "migrate $migrate_dir failed"
24367
24368         echo "Finish migration, then checking.."
24369         for file in $(find $migrate_dir); do
24370                 mdt_index=$($LFS getstripe -m $file)
24371                 [ $mdt_index == $MDTIDX ] ||
24372                         error "$file is not on MDT${MDTIDX}"
24373         done
24374
24375         if (($MDS1_VERSION >= $(version_code 2.16.50) )); then
24376                 echo "Migrate a dir with an open file"
24377                 touch $migrate_dir/foo
24378                 local foo_fid=$($LFS path2fid $migrate_dir/foo)
24379                 $MULTIOP $migrate_dir/foo o_c &
24380                 local bg_pid=$!
24381                 sleep 1
24382
24383                 $LFS migrate -m 0 $migrate_dir || {
24384                         kill -USR1 $bg_pid
24385                         error "migrate a dir with an open file fails"
24386                 }
24387
24388                 kill -USR1 $bg_pid
24389                 wait $bg_pid || error "multiop fails"
24390
24391                 local foo_fid_new=$($LFS path2fid $migrate_dir/foo)
24392                 [[ "$foo_fid" == "$foo_fid_new" ]] ||
24393                         error "migrate should skip an open file $foo_fid != $foo_fid_new"
24394
24395                 for file in $(find $migrate_dir); do
24396                         [[ $file == "$migrate_dir/foo" ]] && continue
24397                         mdt_index=$($LFS getstripe -m $file)
24398                         [[ "$mdt_index" == "0" ]] ||
24399                                 error "$file is not on MDT0"
24400                 done
24401
24402                 # repeating the migrate should leave the dir's FID the same
24403                 # and update only the skipped file's FID
24404                 local old_dir_fid=$($LFS path2fid $migrate_dir)
24405                 local old_file_fid=$($LFS path2fid $migrate_dir/file)
24406
24407                 $LFS migrate -m 0 $migrate_dir || error "Repeating migrate fails"
24408
24409                 local new_dir_fid=$($LFS path2fid $migrate_dir)
24410                 local new_file_fid=$($LFS path2fid $migrate_dir/file)
24411
24412                 foo_fid_new=$($LFS path2fid $migrate_dir/foo)
24413
24414                 [[ "$foo_fid_old" != "$foo_fid_new" ]] ||
24415                         error "Expecting the skipped file to be migrated, but its FID is the same"
24416                 [[ "$old_dir_fid" != "$new_fid_dir" ]] ||
24417                         error "The top-level dir has been migrated after repeating the same migrate cmd"
24418                 [[ "$old_file_fid" == "$new_file_fid" ]] ||
24419                         error "The migrated file has been migrated again"
24420         fi
24421
24422         rm -rf $DIR/$tdir || error "rm dir failed after migration"
24423 }
24424 run_test 230c "check directory accessiblity if migration failed"
24425
24426 test_230d() {
24427         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24428         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24429         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24430                 skip "Need MDS version at least 2.11.52"
24431         # LU-11235
24432         [ "$mds1_FSTYPE" == "zfs" ] && skip "skip ZFS backend"
24433
24434         local migrate_dir=$DIR/$tdir/migrate_dir
24435         local old_index
24436         local new_index
24437         local old_count
24438         local new_count
24439         local new_hash
24440         local mdt_index
24441         local i
24442         local j
24443
24444         old_index=$((RANDOM % MDSCOUNT))
24445         old_count=$((MDSCOUNT - old_index))
24446         new_index=$((RANDOM % MDSCOUNT))
24447         new_count=$((MDSCOUNT - new_index))
24448         new_hash=1 # for all_char
24449
24450         [ $old_count -gt 1 ] && old_count=$((old_count - RANDOM % old_count))
24451         [ $new_count -gt 1 ] && new_count=$((new_count - RANDOM % new_count))
24452
24453         test_mkdir $DIR/$tdir
24454         test_mkdir -i $old_index -c $old_count $migrate_dir
24455
24456         for ((i=0; i<100; i++)); do
24457                 test_mkdir -i0 -c1 $migrate_dir/dir_${i}
24458                 createmany -o $migrate_dir/dir_${i}/f 100 ||
24459                         error "create files under remote dir failed $i"
24460         done
24461
24462         echo -n "Migrate from MDT$old_index "
24463         [ $old_count -gt 1 ] && echo -n "... MDT$((old_index + old_count - 1)) "
24464         echo -n "to MDT$new_index"
24465         [ $new_count -gt 1 ] && echo -n " ... MDT$((new_index + new_count - 1))"
24466         echo
24467
24468         echo "$LFS migrate -m$new_index -c$new_count -H $new_hash $migrate_dir"
24469         $LFS migrate -m $new_index -c $new_count -H $new_hash $migrate_dir ||
24470                 error "migrate remote dir error"
24471
24472         echo "Finish migration, then checking.."
24473         for file in $(find $migrate_dir -maxdepth 1); do
24474                 mdt_index=$($LFS getstripe -m $file)
24475                 if [ $mdt_index -lt $new_index ] ||
24476                    [ $mdt_index -gt $((new_index + new_count - 1)) ]; then
24477                         error "$file is on MDT$mdt_index"
24478                 fi
24479         done
24480
24481         rm -rf $DIR/$tdir || error "rm dir failed after migration"
24482 }
24483 run_test 230d "check migrate big directory"
24484
24485 test_230e() {
24486         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24487         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24488         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24489                 skip "Need MDS version at least 2.11.52"
24490
24491         local i
24492         local j
24493         local a_fid
24494         local b_fid
24495
24496         mkdir_on_mdt0 $DIR/$tdir
24497         mkdir $DIR/$tdir/migrate_dir
24498         mkdir $DIR/$tdir/other_dir
24499         touch $DIR/$tdir/migrate_dir/a
24500         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/b
24501         ls $DIR/$tdir/other_dir
24502
24503         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
24504                 error "migrate dir fails"
24505
24506         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir)
24507         [ $mdt_index == 1 ] || error "migrate_dir is not on MDT1"
24508
24509         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
24510         [ $mdt_index == 0 ] || error "a is not on MDT0"
24511
24512         $LFS migrate -m 1 $DIR/$tdir/other_dir ||
24513                 error "migrate dir fails"
24514
24515         mdt_index=$($LFS getstripe -m $DIR/$tdir/other_dir)
24516         [ $mdt_index == 1 ] || error "other_dir is not on MDT1"
24517
24518         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
24519         [ $mdt_index == 1 ] || error "a is not on MDT1"
24520
24521         mdt_index=$($LFS getstripe -m $DIR/$tdir/other_dir/b)
24522         [ $mdt_index == 1 ] || error "b is not on MDT1"
24523
24524         a_fid=$($LFS path2fid $DIR/$tdir/migrate_dir/a)
24525         b_fid=$($LFS path2fid $DIR/$tdir/other_dir/b)
24526
24527         [ "$a_fid" = "$b_fid" ] || error "different fid after migration"
24528
24529         rm -rf $DIR/$tdir || error "rm dir failed after migration"
24530 }
24531 run_test 230e "migrate mulitple local link files"
24532
24533 test_230f() {
24534         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24535         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24536         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24537                 skip "Need MDS version at least 2.11.52"
24538
24539         local a_fid
24540         local ln_fid
24541
24542         mkdir -p $DIR/$tdir
24543         mkdir $DIR/$tdir/migrate_dir
24544         $LFS mkdir -i1 $DIR/$tdir/other_dir
24545         touch $DIR/$tdir/migrate_dir/a
24546         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln1
24547         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln2
24548         ls $DIR/$tdir/other_dir
24549
24550         # a should be migrated to MDT1, since no other links on MDT0
24551         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
24552                 error "#1 migrate dir fails"
24553         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir)
24554         [ $mdt_index == 1 ] || error "migrate_dir is not on MDT1"
24555         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
24556         [ $mdt_index == 1 ] || error "a is not on MDT1"
24557
24558         # a should stay on MDT1, because it is a mulitple link file
24559         $LFS migrate -m 0 $DIR/$tdir/migrate_dir ||
24560                 error "#2 migrate dir fails"
24561         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
24562         [ $mdt_index == 1 ] || error "a is not on MDT1"
24563
24564         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
24565                 error "#3 migrate dir fails"
24566
24567         a_fid=$($LFS path2fid $DIR/$tdir/migrate_dir/a)
24568         ln_fid=$($LFS path2fid $DIR/$tdir/other_dir/ln1)
24569         [ "$a_fid" = "$ln_fid" ] || error "different fid after migrate to MDT1"
24570
24571         rm -rf $DIR/$tdir/other_dir/ln1 || error "unlink ln1 fails"
24572         rm -rf $DIR/$tdir/other_dir/ln2 || error "unlink ln2 fails"
24573
24574         # a should be migrated to MDT0, since no other links on MDT1
24575         $LFS migrate -m 0 $DIR/$tdir/migrate_dir ||
24576                 error "#4 migrate dir fails"
24577         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
24578         [ $mdt_index == 0 ] || error "a is not on MDT0"
24579
24580         rm -rf $DIR/$tdir || error "rm dir failed after migration"
24581 }
24582 run_test 230f "migrate mulitple remote link files"
24583
24584 test_230g() {
24585         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24586         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24587         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24588                 skip "Need MDS version at least 2.11.52"
24589
24590         mkdir -p $DIR/$tdir/migrate_dir
24591
24592         $LFS migrate -m 1000 $DIR/$tdir/migrate_dir &&
24593                 error "migrating dir to non-exist MDT succeeds"
24594         true
24595 }
24596 run_test 230g "migrate dir to non-exist MDT"
24597
24598 test_230h() {
24599         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24600         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24601         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24602                 skip "Need MDS version at least 2.11.52"
24603
24604         local mdt_index
24605
24606         mkdir -p $DIR/$tdir/migrate_dir
24607
24608         $LFS migrate -m1 $DIR &&
24609                 error "migrating mountpoint1 should fail"
24610
24611         $LFS migrate -m1 $DIR/$tdir/.. &&
24612                 error "migrating mountpoint2 should fail"
24613
24614         # same as mv
24615         $LFS migrate -m1 $DIR/$tdir/migrate_dir/.. &&
24616                 error "migrating $tdir/migrate_dir/.. should fail"
24617
24618         true
24619 }
24620 run_test 230h "migrate .. and root"
24621
24622 test_230i() {
24623         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24624         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
24625         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
24626                 skip "Need MDS version at least 2.11.52"
24627
24628         mkdir -p $DIR/$tdir/migrate_dir
24629
24630         $LFS migrate -m 1 $DIR/$tdir/migrate_dir/ ||
24631                 error "migration fails with a tailing slash"
24632
24633         $LFS migrate -m 0 $DIR/$tdir/migrate_dir// ||
24634                 error "migration fails with two tailing slashes"
24635 }
24636 run_test 230i "lfs migrate -m tolerates trailing slashes"
24637
24638 test_230j() {
24639         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
24640         [ $MDS1_VERSION -lt $(version_code 2.13.52) ] &&
24641                 skip "Need MDS version at least 2.11.52"
24642
24643         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $tdir failed"
24644         $LFS setstripe -E 1M -L mdt $DIR/$tdir/$tfile ||
24645                 error "create $tfile failed"
24646         cat /etc/passwd > $DIR/$tdir/$tfile
24647
24648         $LFS migrate -m 1 $DIR/$tdir || error "migrate failed"
24649
24650         cmp /etc/passwd $DIR/$tdir/$tfile ||
24651                 error "DoM file mismatch after migration"
24652 }
24653 run_test 230j "DoM file data not changed after dir migration"
24654
24655 test_230k() {
24656         [ $MDSCOUNT -lt 4 ] && skip "needs >= 4 MDTs"
24657
24658         (( $MDS1_VERSION > $(version_code v2_12_9-38-g80e9ebc1b1e4) )) ||
24659                 skip "Need MDS > v2_12_9-38-g80e9ebc1b1e4"
24660
24661         local total=20
24662         local files_on_starting_mdt=0
24663
24664         $LFS mkdir -i -1 -c 2 $DIR/$tdir || error "mkdir failed"
24665         $LFS getdirstripe $DIR/$tdir
24666         for i in $(seq $total); do
24667                 echo $((i*i - i)) > $DIR/$tdir/$tfile.$i || error "write failed"
24668                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 0 ]] &&
24669                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
24670         done
24671
24672         echo "$files_on_starting_mdt files on MDT0"
24673
24674         $LFS migrate -m 1,3 $DIR/$tdir || error "migrate -m 1,3 failed"
24675         $LFS getdirstripe $DIR/$tdir
24676
24677         files_on_starting_mdt=0
24678         for i in $(seq $total); do
24679                 $(echo $((i*i - i)) | cmp $DIR/$tdir/$tfile.$i -) ||
24680                         error "file $tfile.$i mismatch after migration"
24681                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 1 ]] &&
24682                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
24683         done
24684
24685         echo "$files_on_starting_mdt files on MDT1 after migration"
24686         [[ $files_on_starting_mdt -eq $total ]] && error "all files on MDT1"
24687
24688         $LFS migrate -m 0 -c 2 $DIR/$tdir || error "migrate -m 0 -c 2 failed"
24689         $LFS getdirstripe $DIR/$tdir
24690
24691         files_on_starting_mdt=0
24692         for i in $(seq $total); do
24693                 $(echo $((i*i - i)) | cmp $DIR/$tdir/$tfile.$i -) ||
24694                         error "file $tfile.$i mismatch after 2nd migration"
24695                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 0 ]] &&
24696                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
24697         done
24698
24699         echo "$files_on_starting_mdt files on MDT0 after 2nd migration"
24700         [[ $files_on_starting_mdt -eq $total ]] && error "all files on MDT0"
24701
24702         true
24703 }
24704 run_test 230k "file data not changed after dir migration"
24705
24706 test_230l() {
24707         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
24708         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
24709                 skip "Need MDS version at least 2.11.56"
24710
24711         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir failed"
24712         createmany -o $DIR/$tdir/f___________________________________ 1000 ||
24713                 error "create files under remote dir failed $i"
24714         $LFS migrate -m 1 $DIR/$tdir || error "migrate failed"
24715 }
24716 run_test 230l "readdir between MDTs won't crash"
24717
24718 test_230m() {
24719         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
24720         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
24721                 skip "Need MDS version at least 2.11.56"
24722
24723         local MDTIDX=1
24724         local mig_dir=$DIR/$tdir/migrate_dir
24725         local longstr="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
24726         local shortstr="b"
24727         local val
24728
24729         echo "Creating files and dirs with xattrs"
24730         test_mkdir $DIR/$tdir
24731         test_mkdir -i0 -c1 $mig_dir
24732         mkdir $mig_dir/dir
24733         setfattr -n user.attr1 -v $longstr $mig_dir/dir ||
24734                 error "cannot set xattr attr1 on dir"
24735         setfattr -n user.attr2 -v $shortstr $mig_dir/dir ||
24736                 error "cannot set xattr attr2 on dir"
24737         touch $mig_dir/dir/f0
24738         setfattr -n user.attr1 -v $longstr $mig_dir/dir/f0 ||
24739                 error "cannot set xattr attr1 on file"
24740         setfattr -n user.attr2 -v $shortstr $mig_dir/dir/f0 ||
24741                 error "cannot set xattr attr2 on file"
24742         sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
24743         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir 2>/dev/null)
24744         [ "$val" = $longstr ] || error "xattr attr1 not set properly on dir"
24745         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir 2>/dev/null)
24746         [ "$val" = $shortstr ] || error "xattr attr2 not set properly on dir"
24747         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir/f0 2>/dev/null)
24748         [ "$val" = $longstr ] || error "xattr attr1 not set properly on file"
24749         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir/f0 2>/dev/null)
24750         [ "$val" = $shortstr ] || error "xattr attr2 not set properly on file"
24751
24752         echo "Migrating to MDT1"
24753         $LFS migrate -m $MDTIDX $mig_dir ||
24754                 error "fails on migrating dir to MDT1"
24755
24756         sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
24757         echo "Checking xattrs"
24758         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir 2>/dev/null)
24759         [ "$val" = $longstr ] ||
24760                 error "expecting xattr1 $longstr on dir, found $val"
24761         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir 2>/dev/null)
24762         [ "$val" = $shortstr ] ||
24763                 error "expecting xattr2 $shortstr on dir, found $val"
24764         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir/f0 2>/dev/null)
24765         [ "$val" = $longstr ] ||
24766                 error "expecting xattr1 $longstr on file, found $val"
24767         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir/f0 2>/dev/null)
24768         [ "$val" = $shortstr ] ||
24769                 error "expecting xattr2 $shortstr on file, found $val"
24770 }
24771 run_test 230m "xattrs not changed after dir migration"
24772
24773 test_230n() {
24774         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
24775         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
24776                 skip "Need MDS version at least 2.13.53"
24777
24778         $LFS mkdir -i 0 $DIR/$tdir || error "mkdir $tdir failed"
24779         cat /etc/hosts > $DIR/$tdir/$tfile
24780         $LFS mirror extend -N1 $DIR/$tdir/$tfile || error "Mirroring failed"
24781         $LFS migrate -m 1 $DIR/$tdir || error "Migration failed"
24782
24783         cmp /etc/hosts $DIR/$tdir/$tfile ||
24784                 error "File data mismatch after migration"
24785 }
24786 run_test 230n "Dir migration with mirrored file"
24787
24788 test_230o() {
24789         [ $MDSCOUNT -ge 2 ] || skip "needs >= 2 MDTs"
24790         [ $MDS1_VERSION -ge $(version_code 2.13.52) ] ||
24791                 skip "Need MDS version at least 2.13.52"
24792
24793         local mdts=$(mdts_nodes)
24794         local timeout=100
24795         local restripe_status
24796         local delta
24797         local i
24798
24799         [[ $mds1_FSTYPE == zfs ]] && timeout=300
24800
24801         # in case "crush" hash type is not set
24802         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
24803
24804         restripe_status=$(do_facet mds1 $LCTL get_param -n \
24805                            mdt.*MDT0000.enable_dir_restripe)
24806         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
24807         stack_trap "do_nodes $mdts $LCTL set_param \
24808                     mdt.*.enable_dir_restripe=$restripe_status"
24809
24810         mkdir $DIR/$tdir
24811         createmany -m $DIR/$tdir/f 100 ||
24812                 error "create files under remote dir failed $i"
24813         createmany -d $DIR/$tdir/d 100 ||
24814                 error "create dirs under remote dir failed $i"
24815
24816         for i in $(seq 2 $MDSCOUNT); do
24817                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
24818                 $LFS setdirstripe -c $i $DIR/$tdir ||
24819                         error "split -c $i $tdir failed"
24820                 wait_update $HOSTNAME \
24821                         "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
24822                         error "dir split not finished"
24823                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
24824                         awk '/migrate/ {sum += $2} END { print sum }')
24825                 echo "$delta migrated when dir split $((i - 1)) to $i stripes"
24826                 # delta is around total_files/stripe_count
24827                 (( $delta < 200 / (i - 1) + 4 )) ||
24828                         error "$delta files migrated >= $((200 / (i - 1) + 4))"
24829         done
24830 }
24831 run_test 230o "dir split"
24832
24833 test_230p() {
24834         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
24835         (( MDS1_VERSION >= $(version_code 2.13.52) )) ||
24836                 skip "Need MDS version at least 2.13.52"
24837
24838         local mdts=$(mdts_nodes)
24839         local timeout=100
24840         local restripe_status
24841         local delta
24842         local c
24843
24844         [[ $mds1_FSTYPE == zfs ]] && timeout=300
24845
24846         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
24847
24848         restripe_status=$(do_facet mds1 $LCTL get_param -n \
24849                            mdt.*MDT0000.enable_dir_restripe)
24850         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
24851         stack_trap "do_nodes $mdts $LCTL set_param \
24852                     mdt.*.enable_dir_restripe=$restripe_status"
24853
24854         test_mkdir -c $MDSCOUNT -H crush $DIR/$tdir
24855         createmany -m $DIR/$tdir/f 100 ||
24856                 error "create files under remote dir failed"
24857         createmany -d $DIR/$tdir/d 100 ||
24858                 error "create dirs under remote dir failed"
24859
24860         for ((c = $MDSCOUNT - 1; c >= 1; c--)); do
24861                 local mdt_hash="crush"
24862
24863                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
24864                 $LFS setdirstripe -c $c $DIR/$tdir ||
24865                         error "split -c $c $tdir failed"
24866                 if (( MDS1_VERSION >= $(version_code 2.14.51) )); then
24867                         mdt_hash="$mdt_hash,fixed"
24868                 elif [ $c -eq 1 ]; then
24869                         mdt_hash="none"
24870                 fi
24871                 wait_update $HOSTNAME \
24872                         "$LFS getdirstripe -H $DIR/$tdir" $mdt_hash $timeout ||
24873                         error "dir merge not finished"
24874                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
24875                         awk '/migrate/ {sum += $2} END { print sum }')
24876                 echo "$delta migrated when dir merge $((c + 1)) to $c stripes"
24877                 # delta is around total_files/stripe_count
24878                 (( delta < 200 / c + 4 )) ||
24879                         error "$delta files migrated >= $((200 / c + 4))"
24880         done
24881
24882         # and restripe to -c 2
24883         echo Splitting the dir back to 2 stripes.
24884         $LFS setdirstripe -c 2 $DIR/$tdir || {
24885                 $LFS getdirstripe $DIR/$tdir
24886                 error "split $tdir to 2 stripes failed"
24887         }
24888         wait_update $HOSTNAME \
24889                 "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
24890                 error "dir split not finished"
24891 }
24892 run_test 230p "dir merge"
24893
24894 test_230q() {
24895         (( MDSCOUNT > 1)) || skip "needs >= 2 MDTs"
24896         (( MDS1_VERSION >= $(version_code 2.13.52) )) ||
24897                 skip "Need MDS version at least 2.13.52"
24898
24899         local mdts=$(mdts_nodes)
24900         local saved_threshold=$(do_facet mds1 \
24901                         $LCTL get_param -n mdt.*-MDT0000.dir_split_count)
24902         local saved_delta=$(do_facet mds1 \
24903                         $LCTL get_param -n mdt.*-MDT0000.dir_split_delta)
24904         local threshold=100
24905         local delta=2
24906         local total=0
24907         local stripe_count=0
24908         local stripe_index
24909         local nr_files
24910         local create
24911
24912         # test with fewer files on ZFS
24913         [ "$mds1_FSTYPE" == "zfs" ] && threshold=40
24914
24915         stack_trap "do_nodes $mdts $LCTL set_param \
24916                     mdt.*.dir_split_count=$saved_threshold"
24917         stack_trap "do_nodes $mdts $LCTL set_param \
24918                     mdt.*.dir_split_delta=$saved_delta"
24919         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.dir_restripe_nsonly=1"
24920         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_auto_split=1"
24921         do_nodes $mdts "$LCTL set_param mdt.*.dir_split_count=$threshold"
24922         do_nodes $mdts "$LCTL set_param mdt.*.dir_split_delta=$delta"
24923         do_nodes $mdts "$LCTL set_param mdt.*.dir_restripe_nsonly=0"
24924         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
24925
24926         $LFS mkdir -i -1 -c 1 $DIR/$tdir || error "mkdir $tdir failed"
24927         stripe_index=$($LFS getdirstripe -i $DIR/$tdir)
24928
24929         create=$((threshold * 3 / 2))
24930         while [ $stripe_count -lt $MDSCOUNT ]; do
24931                 createmany -m $DIR/$tdir/f $total $create ||
24932                         error "create sub files failed"
24933                 stat $DIR/$tdir > /dev/null
24934                 total=$((total + create))
24935                 stripe_count=$((stripe_count + delta))
24936                 [ $stripe_count -gt $MDSCOUNT ] && stripe_count=$MDSCOUNT
24937
24938                 wait_update $HOSTNAME \
24939                         "$LFS getdirstripe -c $DIR/$tdir" "$stripe_count" 40 ||
24940                         error "stripe count $($LFS getdirstripe -c $DIR/$tdir) != $stripe_count"
24941
24942                 wait_update $HOSTNAME \
24943                         "$LFS getdirstripe -H $DIR/$tdir" "crush" 200 ||
24944                         error "stripe hash $($LFS getdirstripe -H $DIR/$tdir) != crush"
24945
24946                 nr_files=$($LFS find -m 1 $DIR/$tdir | grep -c -w $stripe_index)
24947                 echo "$nr_files/$total files on MDT$stripe_index after split"
24948                 # allow 10% margin of imbalance with crush hash
24949                 (( $nr_files <= $total / $stripe_count + $create / 10)) ||
24950                         error "$nr_files files on MDT$stripe_index after split"
24951
24952                 nr_files=$($LFS find -type f $DIR/$tdir | wc -l)
24953                 [ $nr_files -eq $total ] ||
24954                         error "total sub files $nr_files != $total"
24955         done
24956
24957         (( MDS1_VERSION >= $(version_code 2.14.51) )) || return 0
24958
24959         echo "fixed layout directory won't auto split"
24960         $LFS migrate -m 0 $DIR/$tdir || error "migrate $tdir failed"
24961         wait_update $HOSTNAME "$LFS getdirstripe -H $DIR/$tdir" "crush,fixed" \
24962                 10 || error "stripe hash $($LFS getdirstripe -H $DIR/$tdir)"
24963         wait_update $HOSTNAME "$LFS getdirstripe -c $DIR/$tdir" 1 10 ||
24964                 error "stripe count $($LFS getdirstripe -c $DIR/$tdir)"
24965 }
24966 run_test 230q "dir auto split"
24967
24968 test_230r() {
24969         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
24970         [[ $MDSCOUNT -ge 2 ]] || skip_env "needs >= 2 MDTs"
24971         [[ $MDS1_VERSION -ge $(version_code 2.13.54) ]] ||
24972                 skip "Need MDS version at least 2.13.54"
24973
24974         # maximum amount of local locks:
24975         # parent striped dir - 2 locks
24976         # new stripe in parent to migrate to - 1 lock
24977         # source and target - 2 locks
24978         # Total 5 locks for regular file
24979         mkdir -p $DIR/$tdir
24980         $LFS mkdir -i1 -c2 $DIR/$tdir/dir1
24981         touch $DIR/$tdir/dir1/eee
24982
24983         # create 4 hardlink for 4 more locks
24984         # Total: 9 locks > RS_MAX_LOCKS (8)
24985         $LFS mkdir -i1 -c1 $DIR/$tdir/dir2
24986         $LFS mkdir -i1 -c1 $DIR/$tdir/dir3
24987         $LFS mkdir -i1 -c1 $DIR/$tdir/dir4
24988         $LFS mkdir -i1 -c1 $DIR/$tdir/dir5
24989         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir2/eee
24990         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir3/eee
24991         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir4/eee
24992         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir5/eee
24993
24994         cancel_lru_locks mdc
24995
24996         $LFS migrate -m1 -c1 $DIR/$tdir/dir1 ||
24997                 error "migrate dir fails"
24998
24999         rm -rf $DIR/$tdir || error "rm dir failed after migration"
25000 }
25001 run_test 230r "migrate with too many local locks"
25002
25003 test_230s() {
25004         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
25005                 skip "Need MDS version at least 2.14.52"
25006
25007         local mdts=$(mdts_nodes)
25008         local restripe_status=$(do_facet mds1 $LCTL get_param -n \
25009                                 mdt.*MDT0000.enable_dir_restripe)
25010
25011         stack_trap "do_nodes $mdts $LCTL set_param \
25012                     mdt.*.enable_dir_restripe=$restripe_status"
25013
25014         local st
25015         for st in 0 1; do
25016                 do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=$st"
25017                 test_mkdir $DIR/$tdir
25018                 $LFS mkdir $DIR/$tdir |& grep "File exists" ||
25019                         error "$LFS mkdir should return EEXIST if target exists"
25020                 rmdir $DIR/$tdir
25021         done
25022 }
25023 run_test 230s "lfs mkdir should return -EEXIST if target exists"
25024
25025 test_230t()
25026 {
25027         (( $MDSCOUNT >= 2 )) || skip_env "needs >= 2 MDTs"
25028         (( $MDS1_VERSION >= $(version_code 2.14.50) )) ||
25029                 skip "Need MDS version at least 2.14.50"
25030
25031         test_mkdir $DIR/$tdir || error "mkdir $tdir failed"
25032         test_mkdir $DIR/$tdir/subdir || error "mkdir subdir failed"
25033         $LFS project -p 1 -s $DIR/$tdir ||
25034                 error "set $tdir project id failed"
25035         $LFS project -p 2 -s $DIR/$tdir/subdir ||
25036                 error "set subdir project id failed"
25037         local pbefore="$($LFS project -d $DIR/$tdir)"
25038         local sbefore="$($LFS project -d $DIR/$tdir/subdir)"
25039         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir || error "migrate failed"
25040
25041         local pafter="$($LFS project -d $DIR/$tdir)"
25042         local safter="$($LFS project -d $DIR/$tdir/subdir)"
25043         [[ "$pbefore" == "$pafter" ]] || error "projid '$pbefore' != '$pafter'"
25044         [[ "$sbefore" == "$safter" ]] || error "projid '$sbefore' != '$safter'"
25045
25046         (( $MDS1_VERSION >= $(version_code 2.15.59.107) )) ||
25047                 { echo "Need MDS >= 2.15.59.107 for projid rename"; return 0; }
25048
25049         # check rename works, even if source parent projid differs (LU-17016)
25050         test_mkdir $DIR/$tdir.2 || error "mkdir $tdir.2 failed"
25051         local fid_before=$($LFS path2fid $DIR/$tdir/subdir)
25052
25053         $LFS project -p 2 -s $DIR/$tdir.2 || error "set $tdir.2 projid failed"
25054         mrename $DIR/$tdir/subdir $DIR/$tdir.2/subdir ||
25055                 error "subdir failed rename for different source parent projid"
25056         local fid_after=$($LFS path2fid $DIR/$tdir.2/subdir)
25057
25058         [[ "$fid_before" == "$fid_after" ]] ||
25059                 error "fid before '$fid_before' != after '$fid_after'"
25060 }
25061 run_test 230t "migrate directory with project ID set"
25062
25063 test_230u()
25064 {
25065         (( MDSCOUNT > 3 )) || skip_env "needs >= 4 MDTs"
25066         (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
25067                 skip "Need MDS version at least 2.14.53"
25068
25069         local count
25070
25071         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
25072         mkdir $DIR/$tdir/sub{0..99} || error "mkdir sub failed"
25073         $LFS migrate -m -1 $DIR/$tdir/sub{0..99} || error "migrate sub failed"
25074         for i in $(seq 0 $((MDSCOUNT - 1))); do
25075                 count=$($LFS getstripe -m $DIR/$tdir/sub* | grep -c ^$i)
25076                 echo "$count dirs migrated to MDT$i"
25077         done
25078         count=$($LFS getstripe -m $DIR/$tdir/sub* | sort -u | wc -l)
25079         (( count >= MDSCOUNT - 1 )) || error "dirs migrated to $count MDTs"
25080 }
25081 run_test 230u "migrate directory by QOS"
25082
25083 test_230v()
25084 {
25085         (( MDSCOUNT > 3 )) || skip_env "needs >= 4 MDTs"
25086         (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
25087                 skip "Need MDS version at least 2.14.53"
25088
25089         local count
25090
25091         mkdir $DIR/$tdir || error "mkdir $tdir failed"
25092         mkdir $DIR/$tdir/sub{0..99} || error "mkdir sub failed"
25093         $LFS migrate -m 0,2,1 $DIR/$tdir || error "migrate $tdir failed"
25094         for i in $(seq 0 $((MDSCOUNT - 1))); do
25095                 count=$($LFS getstripe -m $DIR/$tdir/sub* | grep -c ^$i)
25096                 echo "$count subdirs migrated to MDT$i"
25097                 (( i == 3 )) && (( count > 0 )) &&
25098                         error "subdir shouldn't be migrated to MDT3"
25099         done
25100         count=$($LFS getstripe -m $DIR/$tdir/sub* | sort -u | wc -l)
25101         (( count == 3 )) || error "dirs migrated to $count MDTs"
25102 }
25103 run_test 230v "subdir migrated to the MDT where its parent is located"
25104
25105 test_230w() {
25106         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
25107         (( MDS1_VERSION >= $(version_code 2.15.0) )) ||
25108                 skip "Need MDS version at least 2.15.0"
25109
25110         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
25111         createmany -o $DIR/$tdir/f 10 || error "create files failed"
25112         createmany -d $DIR/$tdir/d 10 || error "create dirs failed"
25113
25114         $LFS migrate -m 1 -c $MDSCOUNT -d $DIR/$tdir ||
25115                 error "migrate failed"
25116
25117         (( $($LFS getdirstripe -c $DIR/$tdir) == MDSCOUNT )) ||
25118                 error "$tdir stripe count mismatch"
25119
25120         for i in $(seq 0 9); do
25121                 (( $($LFS getdirstripe -c $DIR/$tdir/d$i) == 0 )) ||
25122                         error "d$i is striped"
25123         done
25124 }
25125 run_test 230w "non-recursive mode dir migration"
25126
25127 test_230x() {
25128         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
25129         (( MDS1_VERSION >= $(version_code v2_15_52-83-g6aee406c84) )) ||
25130                 skip "Need MDS >= 2.15.53 for migrate space check"
25131
25132         mkdir -p $DIR/$tdir || error "mkdir failed"
25133         createmany -d $DIR/$tdir/sub 100 || error "createmany failed"
25134
25135         local mdt_name=$(mdtname_from_index 0)
25136         local low=$(do_facet mds2 $LCTL get_param -n \
25137                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low)
25138         local high=$(do_facet mds2 $LCTL get_param -n \
25139                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high)
25140         local ffree=$($LFS df -i $MOUNT | awk "/$mdt_name/ { print \$4 }")
25141         local maxage=$(do_facet mds2 $LCTL get_param -n \
25142                 osp.*$mdt_name-osp-MDT0001.maxage)
25143
25144         stack_trap "do_facet mds2 $LCTL set_param -n \
25145                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$low \
25146                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high=$high" EXIT
25147         stack_trap "do_facet mds2 $LCTL set_param -n \
25148                 osp.*$mdt_name-osp-MDT0001.maxage=$maxage" EXIT
25149
25150         do_facet mds2 $LCTL set_param -n \
25151                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$((ffree + 1))
25152         do_facet mds2 $LCTL set_param -n osp.*$mdt_name-osp-MDT0001.maxage=1
25153         sleep 4
25154         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir &&
25155                 error "migrate $tdir should fail"
25156
25157         do_facet mds2 $LCTL set_param -n \
25158                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$low
25159         do_facet mds2 $LCTL set_param -n \
25160                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high=$high
25161         sleep 4
25162         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir ||
25163                 error "migrate failed"
25164         (( $($LFS getdirstripe -c $DIR/$tdir) == $MDSCOUNT )) ||
25165                 error "$tdir stripe count mismatch"
25166 }
25167 run_test 230x "dir migration check space"
25168
25169 test_230y() {
25170         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
25171         (( MDS1_VERSION >= $(version_code 2.15.55.45) )) ||
25172                 skip "Need MDS version at least 2.15.55.45"
25173
25174         local pid
25175
25176         test_mkdir -c -1 $DIR/$tdir || error "mkdir $tdir failed"
25177         $LFS getdirstripe $DIR/$tdir
25178         createmany -d $DIR/$tdir/d 100 || error "createmany failed"
25179         $LFS migrate -m 1 -c 2 $DIR/$tdir &
25180         pid=$!
25181         sleep 1
25182
25183         #OBD_FAIL_MIGRATE_BAD_HASH      0x1802
25184         do_facet mds2 lctl set_param fail_loc=0x1802
25185
25186         wait $pid
25187         do_facet mds2 lctl set_param fail_loc=0
25188         $LFS getdirstripe $DIR/$tdir
25189         unlinkmany -d $DIR/$tdir/d 100 || error "unlinkmany failed"
25190         rmdir $DIR/$tdir || error "rmdir $tdir failed"
25191 }
25192 run_test 230y "unlink dir with bad hash type"
25193
25194 test_230z() {
25195         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
25196         (( MDS1_VERSION >= $(version_code 2.15.55.45) )) ||
25197                 skip "Need MDS version at least 2.15.55.45"
25198
25199         local pid
25200
25201         test_mkdir -c -1 $DIR/$tdir || error "mkdir $tdir failed"
25202         $LFS getdirstripe $DIR/$tdir
25203         createmany -d $DIR/$tdir/d 100 || error "createmany failed"
25204         $LFS migrate -m 1 -c 2 -H fnv_1a_64 $DIR/$tdir &
25205         pid=$!
25206         sleep 1
25207
25208         #OBD_FAIL_MIGRATE_BAD_HASH      0x1802
25209         do_facet mds2 lctl set_param fail_loc=0x1802
25210
25211         wait $pid
25212         do_facet mds2 lctl set_param fail_loc=0
25213         $LFS getdirstripe $DIR/$tdir
25214
25215         # resume migration
25216         $LFS migrate -m 1 -c 2 -H fnv_1a_64 $DIR/$tdir ||
25217                 error "resume migration failed"
25218         $LFS getdirstripe $DIR/$tdir
25219         [ $($LFS getdirstripe -H $DIR/$tdir) == "fnv_1a_64,fixed" ] ||
25220                 error "migration is not finished"
25221 }
25222 run_test 230z "resume dir migration with bad hash type"
25223
25224 test_231a()
25225 {
25226         # For simplicity this test assumes that max_pages_per_rpc
25227         # is the same across all OSCs
25228         local max_pages=$($LCTL get_param -n osc.*.max_pages_per_rpc | head -n1)
25229         local bulk_size=$((max_pages * PAGE_SIZE))
25230         local brw_size=$(do_facet ost1 $LCTL get_param -n obdfilter.*.brw_size |
25231                                        head -n 1)
25232
25233         mkdir -p $DIR/$tdir
25234         $LFS setstripe -S ${brw_size}M $DIR/$tdir ||
25235                 error "failed to set stripe with -S ${brw_size}M option"
25236         stack_trap "rm -rf $DIR/$tdir"
25237
25238         # clear the OSC stats
25239         $LCTL set_param osc.*.stats=0 &>/dev/null
25240         stop_writeback
25241
25242         # Client writes $bulk_size - there must be 1 rpc for $max_pages.
25243         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=$bulk_size count=1 \
25244                 oflag=direct &>/dev/null || error "dd failed"
25245
25246         sync; sleep 1; sync # just to be safe
25247         local nrpcs=$($LCTL get_param osc.*.stats |awk '/ost_write/ {print $2}')
25248         if [ x$nrpcs != "x1" ]; then
25249                 $LCTL get_param osc.*.stats
25250                 error "found $nrpcs ost_write RPCs, not 1 as expected"
25251         fi
25252
25253         start_writeback
25254         # Drop the OSC cache, otherwise we will read from it
25255         cancel_lru_locks osc
25256
25257         # clear the OSC stats
25258         $LCTL set_param osc.*.stats=0 &>/dev/null
25259
25260         # Client reads $bulk_size.
25261         dd if=$DIR/$tdir/$tfile of=/dev/null bs=$bulk_size count=1 \
25262                 iflag=direct &>/dev/null || error "dd failed"
25263
25264         nrpcs=$($LCTL get_param osc.*.stats | awk '/ost_read/ { print $2 }')
25265         if [ x$nrpcs != "x1" ]; then
25266                 $LCTL get_param osc.*.stats
25267                 error "found $nrpcs ost_read RPCs, not 1 as expected"
25268         fi
25269 }
25270 run_test 231a "checking that reading/writing of BRW RPC size results in one RPC"
25271
25272 test_231b() {
25273         mkdir -p $DIR/$tdir
25274         stack_trap "rm -rf $DIR/$tdir"
25275         local i
25276         for i in {0..1023}; do
25277                 dd if=/dev/zero of=$DIR/$tdir/$tfile conv=notrunc \
25278                         seek=$((2 * i)) bs=4096 count=1 &>/dev/null ||
25279                         error "dd of=$DIR/$tdir/$tfile seek=$((2 * i)) failed"
25280         done
25281         sync
25282 }
25283 run_test 231b "must not assert on fully utilized OST request buffer"
25284
25285 test_232a() {
25286         mkdir -p $DIR/$tdir
25287         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
25288
25289         #define OBD_FAIL_LDLM_OST_LVB            0x31c
25290         do_facet ost1 $LCTL set_param fail_loc=0x31c
25291
25292         # ignore dd failure
25293         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 || true
25294         stack_trap "rm -f $DIR/$tdir/$tfile"
25295
25296         do_facet ost1 $LCTL set_param fail_loc=0
25297         umount_client $MOUNT || error "umount failed"
25298         mount_client $MOUNT || error "mount failed"
25299         stop ost1 || error "cannot stop ost1"
25300         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
25301 }
25302 run_test 232a "failed lock should not block umount"
25303
25304 test_232b() {
25305         [ $MDS1_VERSION -ge $(version_code 2.10.58) ] ||
25306                 skip "Need MDS version at least 2.10.58"
25307
25308         mkdir -p $DIR/$tdir
25309         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
25310         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1
25311         stack_trap "rm -f $DIR/$tdir/$tfile"
25312         sync
25313         cancel_lru_locks osc
25314
25315         #define OBD_FAIL_LDLM_OST_LVB            0x31c
25316         do_facet ost1 $LCTL set_param fail_loc=0x31c
25317
25318         # ignore failure
25319         $LFS data_version $DIR/$tdir/$tfile || true
25320
25321         do_facet ost1 $LCTL set_param fail_loc=0
25322         umount_client $MOUNT || error "umount failed"
25323         mount_client $MOUNT || error "mount failed"
25324         stop ost1 || error "cannot stop ost1"
25325         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
25326 }
25327 run_test 232b "failed data version lock should not block umount"
25328
25329 test_233a() {
25330         [ $MDS1_VERSION -ge $(version_code 2.3.64) ] ||
25331                 skip "Need MDS version at least 2.3.64"
25332         [ -n "$FILESET" ] && skip_env "SKIP due to FILESET set"
25333
25334         local fid=$($LFS path2fid $MOUNT)
25335
25336         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
25337                 error "cannot access $MOUNT using its FID '$fid'"
25338 }
25339 run_test 233a "checking that OBF of the FS root succeeds"
25340
25341 test_233b() {
25342         [ $MDS1_VERSION -ge $(version_code 2.5.90) ] ||
25343                 skip "Need MDS version at least 2.5.90"
25344         [ -n "$FILESET" ] && skip_env "SKIP due to FILESET set"
25345
25346         local fid=$($LFS path2fid $MOUNT/.lustre)
25347
25348         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
25349                 error "cannot access $MOUNT/.lustre using its FID '$fid'"
25350
25351         fid=$($LFS path2fid $MOUNT/.lustre/fid)
25352         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
25353                 error "cannot access $MOUNT/.lustre/fid using its FID '$fid'"
25354 }
25355 run_test 233b "checking that OBF of the FS .lustre succeeds"
25356
25357 test_234() {
25358         local p="$TMP/sanityN-$TESTNAME.parameters"
25359         save_lustre_params client "llite.*.xattr_cache" > $p
25360         lctl set_param llite.*.xattr_cache 1 ||
25361                 skip_env "xattr cache is not supported"
25362
25363         mkdir -p $DIR/$tdir || error "mkdir failed"
25364         touch $DIR/$tdir/$tfile || error "touch failed"
25365         # OBD_FAIL_LLITE_XATTR_ENOMEM
25366         $LCTL set_param fail_loc=0x1405
25367         getfattr -n user.attr $DIR/$tdir/$tfile &&
25368                 error "getfattr should have failed with ENOMEM"
25369         $LCTL set_param fail_loc=0x0
25370         rm -rf $DIR/$tdir
25371
25372         restore_lustre_params < $p
25373         rm -f $p
25374 }
25375 run_test 234 "xattr cache should not crash on ENOMEM"
25376
25377 test_235() {
25378         [ $MDS1_VERSION -lt $(version_code 2.4.52) ] &&
25379                 skip "Need MDS version at least 2.4.52"
25380
25381         flock_deadlock $DIR/$tfile
25382         local RC=$?
25383         case $RC in
25384                 0)
25385                 ;;
25386                 124) error "process hangs on a deadlock"
25387                 ;;
25388                 *) error "error executing flock_deadlock $DIR/$tfile"
25389                 ;;
25390         esac
25391 }
25392 run_test 235 "LU-1715: flock deadlock detection does not work properly"
25393
25394 #LU-2935
25395 test_236() {
25396         check_swap_layouts_support
25397
25398         local ref1=/etc/passwd
25399         local ref2=/etc/group
25400         local file1=$DIR/$tdir/f1
25401         local file2=$DIR/$tdir/f2
25402
25403         test_mkdir -c1 $DIR/$tdir
25404         $LFS setstripe -c 1 $file1 || error "cannot setstripe on '$file1': rc = $?"
25405         cp $ref1 $file1 || error "cp $ref1 $file1 failed: rc = $?"
25406         $LFS setstripe -c 2 $file2 || error "cannot setstripe on '$file2': rc = $?"
25407         cp $ref2 $file2 || error "cp $ref2 $file2 failed: rc = $?"
25408         local fd=$(free_fd)
25409         local cmd="exec $fd<>$file2"
25410         eval $cmd
25411         rm $file2
25412         $LFS swap_layouts $file1 /proc/self/fd/${fd} ||
25413                 error "cannot swap layouts of '$file1' and /proc/self/fd/${fd}"
25414         cmd="exec $fd>&-"
25415         eval $cmd
25416         cmp $ref2 $file1 || error "content compare failed ($ref2 != $file1)"
25417
25418         #cleanup
25419         rm -rf $DIR/$tdir
25420 }
25421 run_test 236 "Layout swap on open unlinked file"
25422
25423 # LU-4659 linkea consistency
25424 test_238() {
25425         [[ $MDS1_VERSION -gt $(version_code 2.5.57) ]] ||
25426                 [[ $MDS1_VERSION -gt $(version_code 2.5.1) &&
25427                    $MDS1_VERSION -lt $(version_code 2.5.50) ]] ||
25428                 skip "Need MDS version at least 2.5.58 or 2.5.2+"
25429
25430         touch $DIR/$tfile
25431         ln $DIR/$tfile $DIR/$tfile.lnk
25432         touch $DIR/$tfile.new
25433         mv $DIR/$tfile.new $DIR/$tfile
25434         local fid1=$($LFS path2fid $DIR/$tfile)
25435         local fid2=$($LFS path2fid $DIR/$tfile.lnk)
25436         local path1=$($LFS fid2path $FSNAME "$fid1")
25437         [ $tfile == $path1 ] || error "linkea inconsistent: $tfile $fid1 $path1"
25438         local path2=$($LFS fid2path $FSNAME "$fid2")
25439         [ $tfile.lnk == $path2 ] ||
25440                 error "linkea inconsistent: $tfile.lnk $fid2 $path2!"
25441         rm -f $DIR/$tfile*
25442 }
25443 run_test 238 "Verify linkea consistency"
25444
25445 test_239A() { # was test_239
25446         [ $MDS1_VERSION -lt $(version_code 2.5.60) ] &&
25447                 skip "Need MDS version at least 2.5.60"
25448
25449         local list=$(comma_list $(mdts_nodes))
25450
25451         mkdir -p $DIR/$tdir
25452         createmany -o $DIR/$tdir/f- 5000
25453         unlinkmany $DIR/$tdir/f- 5000
25454         [ $MDS1_VERSION -gt $(version_code 2.10.4) ] &&
25455                 do_nodes $list "lctl set_param -n osp.*.force_sync=1"
25456         changes=$(do_nodes $list "lctl get_param -n osp.*MDT*.sync_changes \
25457                         osp.*MDT*.sync_in_flight" | calc_sum)
25458         [ "$changes" -eq 0 ] || error "$changes not synced"
25459 }
25460 run_test 239A "osp_sync test"
25461
25462 test_239a() { #LU-5297
25463         remote_mds_nodsh && skip "remote MDS with nodsh"
25464
25465         touch $DIR/$tfile
25466         #define OBD_FAIL_OSP_CHECK_INVALID_REC     0x2100
25467         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2100
25468         chgrp $RUNAS_GID $DIR/$tfile
25469         wait_delete_completed
25470 }
25471 run_test 239a "process invalid osp sync record correctly"
25472
25473 test_239b() { #LU-5297
25474         remote_mds_nodsh && skip "remote MDS with nodsh"
25475
25476         touch $DIR/$tfile1
25477         #define OBD_FAIL_OSP_CHECK_ENOMEM     0x2101
25478         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2101
25479         chgrp $RUNAS_GID $DIR/$tfile1
25480         wait_delete_completed
25481         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
25482         touch $DIR/$tfile2
25483         chgrp $RUNAS_GID $DIR/$tfile2
25484         wait_delete_completed
25485 }
25486 run_test 239b "process osp sync record with ENOMEM error correctly"
25487
25488 test_240() {
25489         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25490         remote_mds_nodsh && skip "remote MDS with nodsh"
25491
25492         mkdir -p $DIR/$tdir
25493
25494         $LFS mkdir -i 0 $DIR/$tdir/d0 ||
25495                 error "failed to mkdir $DIR/$tdir/d0 on MDT0"
25496         $LFS mkdir -i 1 $DIR/$tdir/d0/d1 ||
25497                 error "failed to mkdir $DIR/$tdir/d0/d1 on MDT1"
25498
25499         umount_client $MOUNT || error "umount failed"
25500         #define OBD_FAIL_TGT_DELAY_CONDITIONAL   0x713
25501         do_facet mds2 lctl set_param fail_loc=0x713 fail_val=1
25502         mount_client $MOUNT || error "failed to mount client"
25503
25504         echo "stat $DIR/$tdir/d0/d1, should not fail/ASSERT"
25505         stat $DIR/$tdir/d0/d1 || error "fail to stat $DIR/$tdir/d0/d1"
25506 }
25507 run_test 240 "race between ldlm enqueue and the connection RPC (no ASSERT)"
25508
25509 test_241_bio() {
25510         local count=$1
25511         local bsize=$2
25512
25513         for LOOP in $(seq $count); do
25514                 dd if=$DIR/$tfile of=/dev/null bs=$bsize count=1 2>/dev/null
25515                 cancel_lru_locks $OSC || true
25516         done
25517 }
25518
25519 test_241_dio() {
25520         local count=$1
25521         local bsize=$2
25522
25523         for LOOP in $(seq $1); do
25524                 dd if=$DIR/$tfile of=/dev/null bs=$bsize count=1 iflag=direct \
25525                         2>/dev/null
25526         done
25527 }
25528
25529 test_241a() { # was test_241
25530         local bsize=$PAGE_SIZE
25531
25532         (( bsize < 40960 )) && bsize=40960
25533         dd if=/dev/zero of=$DIR/$tfile count=1 bs=$bsize
25534         ls -la $DIR/$tfile
25535         cancel_lru_locks $OSC
25536         test_241_bio 1000 $bsize &
25537         PID=$!
25538         test_241_dio 1000 $bsize
25539         wait $PID
25540 }
25541 run_test 241a "bio vs dio"
25542
25543 test_241b() {
25544         local bsize=$PAGE_SIZE
25545
25546         (( bsize < 40960 )) && bsize=40960
25547         dd if=/dev/zero of=$DIR/$tfile count=1 bs=$bsize
25548         ls -la $DIR/$tfile
25549         test_241_dio 1000 $bsize &
25550         PID=$!
25551         test_241_dio 1000 $bsize
25552         wait $PID
25553 }
25554 run_test 241b "dio vs dio"
25555
25556 test_242() {
25557         remote_mds_nodsh && skip "remote MDS with nodsh"
25558
25559         mkdir_on_mdt0 $DIR/$tdir
25560         touch $DIR/$tdir/$tfile
25561
25562         #define OBD_FAIL_MDS_READPAGE_PACK      0x105
25563         do_facet mds1 lctl set_param fail_loc=0x105
25564         /bin/ls $DIR/$tdir && error "ls $DIR/$tdir should fail"
25565
25566         do_facet mds1 lctl set_param fail_loc=0
25567         /bin/ls $DIR/$tdir || error "ls $DIR/$tdir failed"
25568 }
25569 run_test 242 "mdt_readpage failure should not cause directory unreadable"
25570
25571 test_243()
25572 {
25573         test_mkdir $DIR/$tdir
25574         group_lock_test -d $DIR/$tdir || error "A group lock test failed"
25575 }
25576 run_test 243 "various group lock tests"
25577
25578 test_244a()
25579 {
25580         test_mkdir $DIR/$tdir
25581         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=35
25582         sendfile_grouplock $DIR/$tdir/$tfile || \
25583                 error "sendfile+grouplock failed"
25584         rm -rf $DIR/$tdir
25585 }
25586 run_test 244a "sendfile with group lock tests"
25587
25588 test_244b()
25589 {
25590         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
25591
25592         local threads=50
25593         local size=$((1024*1024))
25594
25595         test_mkdir $DIR/$tdir
25596         for i in $(seq 1 $threads); do
25597                 local file=$DIR/$tdir/file_$((i / 10))
25598                 $MULTIOP $file OG1234w$size_$((i % 3))w$size_$((i % 4))g1234c &
25599                 local pids[$i]=$!
25600         done
25601         for i in $(seq 1 $threads); do
25602                 wait ${pids[$i]}
25603         done
25604 }
25605 run_test 244b "multi-threaded write with group lock"
25606
25607 test_245a() {
25608         local flagname="multi_mod_rpcs"
25609         local connect_data_name="max_mod_rpcs"
25610         local out
25611
25612         # check if multiple modify RPCs flag is set
25613         out=$($LCTL get_param mdc.$FSNAME-MDT0000-*.import |
25614                 grep "connect_flags:")
25615         echo "$out"
25616
25617         echo "$out" | grep -qw $flagname
25618         if [ $? -ne 0 ]; then
25619                 echo "connect flag $flagname is not set"
25620                 return
25621         fi
25622
25623         # check if multiple modify RPCs data is set
25624         out=$($LCTL get_param mdc.$FSNAME-MDT0000-*.import)
25625         echo "$out"
25626
25627         echo "$out" | grep -qw $connect_data_name ||
25628                 error "import should have connect data $connect_data_name"
25629 }
25630 run_test 245a "check mdc connection flag/data: multiple modify RPCs"
25631
25632 test_245b() {
25633         local flagname="multi_mod_rpcs"
25634         local connect_data_name="max_mod_rpcs"
25635         local out
25636
25637         remote_mds_nodsh && skip "remote MDS with nodsh"
25638         [[ $MDSCOUNT -ge 2 ]] || skip "needs >= 2 MDTs"
25639
25640         # check if multiple modify RPCs flag is set
25641         out=$(do_facet mds1 \
25642               $LCTL get_param osp.$FSNAME-MDT0001-osp-MDT0000.import |
25643               grep "connect_flags:")
25644         echo "$out"
25645
25646         [[ "$out" =~ $flagname ]] || skip "connect flag $flagname is not set"
25647
25648         # check if multiple modify RPCs data is set
25649         out=$(do_facet mds1 \
25650               $LCTL get_param osp.$FSNAME-MDT0001-osp-MDT0000.import)
25651
25652         [[ "$out" =~ $connect_data_name ]] ||
25653                 {
25654                         echo "$out"
25655                         error "missing connect data $connect_data_name"
25656                 }
25657 }
25658 run_test 245b "check osp connection flag/data: multiple modify RPCs"
25659
25660 cleanup_247() {
25661         local submount=$1
25662
25663         trap 0
25664         umount_client $submount
25665         rmdir $submount
25666 }
25667
25668 test_247a() {
25669         lctl get_param -n mdc.$FSNAME-MDT0000*.import |
25670                 grep -q subtree ||
25671                 skip_env "Fileset feature is not supported"
25672
25673         local submount=${MOUNT}_$tdir
25674
25675         mkdir $MOUNT/$tdir
25676         mkdir -p $submount || error "mkdir $submount failed"
25677         FILESET="$FILESET/$tdir" mount_client $submount ||
25678                 error "mount $submount failed"
25679         trap "cleanup_247 $submount" EXIT
25680         echo foo > $submount/$tfile || error "write $submount/$tfile failed"
25681         [ $(cat $MOUNT/$tdir/$tfile) = "foo" ] ||
25682                 error "read $MOUNT/$tdir/$tfile failed"
25683         cleanup_247 $submount
25684 }
25685 run_test 247a "mount subdir as fileset"
25686
25687 test_247b() {
25688         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
25689                 skip_env "Fileset feature is not supported"
25690
25691         local submount=${MOUNT}_$tdir
25692
25693         rm -rf $MOUNT/$tdir
25694         mkdir -p $submount || error "mkdir $submount failed"
25695         SKIP_FILESET=1
25696         FILESET="$FILESET/$tdir" mount_client $submount &&
25697                 error "mount $submount should fail"
25698         rmdir $submount
25699 }
25700 run_test 247b "mount subdir that dose not exist"
25701
25702 test_247c() {
25703         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
25704                 skip_env "Fileset feature is not supported"
25705
25706         local submount=${MOUNT}_$tdir
25707
25708         mkdir -p $MOUNT/$tdir/dir1
25709         mkdir -p $submount || error "mkdir $submount failed"
25710         trap "cleanup_247 $submount" EXIT
25711         FILESET="$FILESET/$tdir" mount_client $submount ||
25712                 error "mount $submount failed"
25713         local fid=$($LFS path2fid $MOUNT/)
25714         $LFS fid2path $submount $fid && error "fid2path should fail"
25715         cleanup_247 $submount
25716 }
25717 run_test 247c "running fid2path outside subdirectory root"
25718
25719 test_247d() {
25720         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
25721                 skip "Fileset feature is not supported"
25722
25723         local submount=${MOUNT}_$tdir
25724
25725         mkdir -p $MOUNT/$tdir/dir1
25726         mkdir -p $submount || error "mkdir $submount failed"
25727         FILESET="$FILESET/$tdir" mount_client $submount ||
25728                 error "mount $submount failed"
25729         trap "cleanup_247 $submount" EXIT
25730
25731         local td=$submount/dir1
25732         local fid=$($LFS path2fid $td)
25733         [ -z "$fid" ] && error "path2fid unable to get $td FID"
25734
25735         # check that we get the same pathname back
25736         local rootpath
25737         local found
25738         for rootpath in "$submount" "$submount///" "$submount/dir1"; do
25739                 echo "$rootpath $fid"
25740                 found=$($LFS fid2path $rootpath "$fid")
25741                 [ -n "$found" ] || error "fid2path should succeed"
25742                 [ "$found" == "$td" ] || error "fid2path $found != $td"
25743         done
25744         # check wrong root path format
25745         rootpath=$submount"_wrong"
25746         found=$($LFS fid2path $rootpath "$fid")
25747         [ -z "$found" ] || error "fid2path should fail ($rootpath != $submount)"
25748
25749         cleanup_247 $submount
25750 }
25751 run_test 247d "running fid2path inside subdirectory root"
25752
25753 # LU-8037
25754 test_247e() {
25755         lctl get_param -n mdc.$FSNAME-MDT0000*.import |
25756                 grep -q subtree ||
25757                 skip "Fileset feature is not supported"
25758
25759         local submount=${MOUNT}_$tdir
25760
25761         mkdir $MOUNT/$tdir
25762         mkdir -p $submount || error "mkdir $submount failed"
25763         FILESET="$FILESET/.." mount_client $submount &&
25764                 error "mount $submount should fail"
25765         rmdir $submount
25766 }
25767 run_test 247e "mount .. as fileset"
25768
25769 test_247f() {
25770         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
25771         (( $MDS1_VERSION >= $(version_code 2.14.50.162) )) ||
25772                 skip "Need at least version 2.14.50.162"
25773         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
25774                 skip "Fileset feature is not supported"
25775
25776         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
25777         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/remote ||
25778                 error "mkdir remote failed"
25779         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/remote/subdir ||
25780                 error "mkdir remote/subdir failed"
25781         $LFS mkdir -i 0 -c $MDSCOUNT $DIR/$tdir/striped ||
25782                 error "mkdir striped failed"
25783         mkdir $DIR/$tdir/striped/subdir || error "mkdir striped/subdir failed"
25784
25785         local submount=${MOUNT}_$tdir
25786
25787         mkdir -p $submount || error "mkdir $submount failed"
25788         stack_trap "rmdir $submount"
25789
25790         local dir
25791         local fileset=$FILESET
25792         local mdts=$(comma_list $(mdts_nodes))
25793
25794         do_nodes $mdts "$LCTL set_param mdt.*.enable_remote_subdir_mount=1"
25795         for dir in $tdir/remote $tdir/remote/subdir $tdir/striped \
25796                 $tdir/striped/subdir $tdir/striped/.; do
25797                 FILESET="$fileset/$dir" mount_client $submount ||
25798                         error "mount $dir failed"
25799                 umount_client $submount
25800         done
25801 }
25802 run_test 247f "mount striped or remote directory as fileset"
25803
25804 test_subdir_mount_lock()
25805 {
25806         local testdir=$1
25807         local submount=${MOUNT}_$(basename $testdir)
25808
25809         touch $DIR/$testdir/$tfile || error "touch $tfile failed"
25810
25811         mkdir -p $submount || error "mkdir $submount failed"
25812         stack_trap "rmdir $submount"
25813
25814         FILESET="$FILESET/$testdir" mount_client $submount ||
25815                 error "mount $FILESET failed"
25816         stack_trap "umount $submount"
25817
25818         local mdts=$(comma_list $(mdts_nodes))
25819
25820         local nrpcs
25821
25822         stat $submount > /dev/null || error "stat $submount failed"
25823         cancel_lru_locks $MDC
25824         stat $submount > /dev/null || error "stat $submount failed"
25825         stat $submount/$tfile > /dev/null || error "stat $tfile failed"
25826         do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear > /dev/null"
25827         stat $submount/$tfile > /dev/null || error "stat $tfile failed"
25828         nrpcs=$(do_nodes $mdts "lctl get_param -n mdt.*.md_stats" |
25829                 awk '/getattr/ {sum += $2} END {print sum}')
25830
25831         [ -z "$nrpcs" ] || error "$nrpcs extra getattr sent"
25832 }
25833
25834 test_247g() {
25835         (( $MDSCOUNT > 1 )) || skip_env "needs > 1 MDTs"
25836
25837         $LFS mkdir -i 0 -c 4 -H fnv_1a_64 $DIR/$tdir ||
25838                 error "mkdir $tdir failed"
25839         test_subdir_mount_lock $tdir
25840 }
25841 run_test 247g "striped directory submount revalidate ROOT from cache"
25842
25843 test_247h() {
25844         (( $MDSCOUNT > 1 )) || skip_env "needs > 1 MDTs"
25845         (( $MDS1_VERSION >= $(version_code 2.15.51) )) ||
25846                 skip "Need MDS version at least 2.15.51"
25847
25848         $LFS mkdir -i 1 -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
25849         test_subdir_mount_lock $tdir
25850         mkdir_on_mdt -i 0 $DIR/$tdir/$tdir.0 || error "mkdir $tdir.0 failed"
25851         mkdir_on_mdt -i 1 $DIR/$tdir/$tdir.0/$tdir.1 ||
25852                 error "mkdir $tdir.1 failed"
25853         test_subdir_mount_lock $tdir/$tdir.0/$tdir.1
25854 }
25855 run_test 247h "remote directory submount revalidate ROOT from cache"
25856
25857 test_248a() {
25858         local fast_read_sav=$($LCTL get_param -n llite.*.fast_read 2>/dev/null)
25859         [ -z "$fast_read_sav" ] && skip "no fast read support"
25860
25861         # create a large file for fast read verification
25862         dd if=/dev/zero of=$DIR/$tfile bs=1M count=128 > /dev/null 2>&1
25863
25864         # make sure the file is created correctly
25865         $CHECKSTAT -s $((128*1024*1024)) $DIR/$tfile ||
25866                 { rm -f $DIR/$tfile; skip "file creation error"; }
25867
25868         echo "Test 1: verify that fast read is 4 times faster on cache read"
25869
25870         # small read with fast read enabled
25871         $LCTL set_param -n llite.*.fast_read=1
25872         local t_fast=$(dd if=$DIR/$tfile of=/dev/null bs=4k 2>&1 |
25873                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
25874                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
25875         # small read with fast read disabled
25876         $LCTL set_param -n llite.*.fast_read=0
25877         local t_slow=$(dd if=$DIR/$tfile of=/dev/null bs=4k 2>&1 |
25878                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
25879                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
25880
25881         # verify that fast read is 4 times faster for cache read
25882         [ $(bc <<< "4 * $t_fast < $t_slow") -eq 1 ] ||
25883                 error_not_in_vm "fast read was not 4 times faster: " \
25884                            "$t_fast vs $t_slow"
25885
25886         echo "Test 2: verify the performance between big and small read"
25887         $LCTL set_param -n llite.*.fast_read=1
25888
25889         # 1k non-cache read
25890         cancel_lru_locks osc
25891         local t_1k=$(dd if=$DIR/$tfile of=/dev/null bs=1k 2>&1 |
25892                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
25893                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
25894
25895         # 1M non-cache read
25896         cancel_lru_locks osc
25897         local t_1m=$(dd if=$DIR/$tfile of=/dev/null bs=1k 2>&1 |
25898                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
25899                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
25900
25901         # verify that big IO is not 4 times faster than small IO
25902         [ $(bc <<< "4 * $t_1k >= $t_1m") -eq 1 ] ||
25903                 error_not_in_vm "bigger IO is way too fast: $t_1k vs $t_1m"
25904
25905         $LCTL set_param -n llite.*.fast_read=$fast_read_sav
25906         rm -f $DIR/$tfile
25907 }
25908 run_test 248a "fast read verification"
25909
25910 test_248b() {
25911         # Default short_io_bytes=16384, try both smaller and larger sizes.
25912         # Lustre O_DIRECT read and write needs to be a multiple of PAGE_SIZE.
25913         # 6017024 = 2^12*13*113 = 47008*128 = 11752*512 = 4096*1469 = 53248*113
25914         echo "bs=53248 count=113 normal buffered write"
25915         dd if=/dev/urandom of=$TMP/$tfile.0 bs=53248 count=113 ||
25916                 error "dd of initial data file failed"
25917         stack_trap "rm -f $DIR/$tfile.[0-3] $TMP/$tfile.[0-3]" EXIT
25918
25919         echo "bs=47008 count=128 oflag=dsync normal write $tfile.0"
25920         dd if=$TMP/$tfile.0 of=$DIR/$tfile.0 bs=47008 count=128 oflag=dsync ||
25921                 error "dd with sync normal writes failed"
25922         cmp $TMP/$tfile.0 $DIR/$tfile.0 || error "compare $DIR/$tfile.0 failed"
25923
25924         echo "bs=11752 count=512 oflag=dsync small write $tfile.1"
25925         dd if=$TMP/$tfile.0 of=$DIR/$tfile.1 bs=11752 count=512 oflag=dsync ||
25926                 error "dd with sync small writes failed"
25927         cmp $TMP/$tfile.0 $DIR/$tfile.1 || error "compare $DIR/$tfile.1 failed"
25928
25929         cancel_lru_locks osc
25930
25931         # calculate the small O_DIRECT size and count for the client PAGE_SIZE
25932         local num=$((13 * 113 / (PAGE_SIZE / 4096)))
25933         echo "bs=$PAGE_SIZE count=$num iflag=direct small read $tfile.1"
25934         dd if=$DIR/$tfile.1 of=$TMP/$tfile.1 bs=$PAGE_SIZE count=$num \
25935                 iflag=direct || error "dd with O_DIRECT small read failed"
25936         # adjust bytes checked to handle larger PAGE_SIZE for ARM/PPC
25937         cmp --bytes=$((PAGE_SIZE * num)) $TMP/$tfile.0 $TMP/$tfile.1 ||
25938                 error "compare $TMP/$tfile.1 failed"
25939
25940         local save=$($LCTL get_param -n osc.*OST000*.short_io_bytes | head -n 1)
25941         stack_trap "$LCTL set_param osc.$FSNAME-*.short_io_bytes=$save" EXIT
25942
25943         # just to see what the maximum tunable value is, and test parsing
25944         echo "test invalid parameter 2MB"
25945         $LCTL set_param osc.$FSNAME-OST0000*.short_io_bytes=2M &&
25946                 error "too-large short_io_bytes allowed"
25947         echo "test maximum parameter 512KB"
25948         # if we can set a larger short_io_bytes, run test regardless of version
25949         if ! $LCTL set_param osc.$FSNAME-OST0000*.short_io_bytes=512K; then
25950                 # older clients may not allow setting it this large, that's OK
25951                 [ $CLIENT_VERSION -ge $(version_code 2.13.50) ] ||
25952                         skip "Need at least client version 2.13.50"
25953                 error "medium short_io_bytes failed"
25954         fi
25955         $LCTL get_param osc.$FSNAME-OST0000*.short_io_bytes
25956         size=$($LCTL get_param -n osc.$FSNAME-OST0000*.short_io_bytes)
25957
25958         echo "test large parameter 64KB"
25959         $LCTL set_param osc.$FSNAME-*.short_io_bytes=65536
25960         $LCTL get_param osc.$FSNAME-OST0000*.short_io_bytes
25961
25962         echo "bs=47008 count=128 oflag=dsync large write $tfile.2"
25963         dd if=$TMP/$tfile.0 of=$DIR/$tfile.2 bs=47008 count=128 oflag=dsync ||
25964                 error "dd with sync large writes failed"
25965         cmp $TMP/$tfile.0 $DIR/$tfile.2 || error "compare $DIR/$tfile.2 failed"
25966
25967         # calculate the large O_DIRECT size and count for the client PAGE_SIZE
25968         local size=$(((4096 * 13 + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE))
25969         num=$((113 * 4096 / PAGE_SIZE))
25970         echo "bs=$size count=$num oflag=direct large write $tfile.3"
25971         dd if=$TMP/$tfile.0 of=$DIR/$tfile.3 bs=$size count=$num oflag=direct ||
25972                 error "dd with O_DIRECT large writes failed"
25973         cmp --bytes=$((size * num)) $TMP/$tfile.0 $DIR/$tfile.3 ||
25974                 error "compare $DIR/$tfile.3 failed"
25975
25976         cancel_lru_locks osc
25977
25978         echo "bs=$size count=$num iflag=direct large read $tfile.2"
25979         dd if=$DIR/$tfile.2 of=$TMP/$tfile.2 bs=$size count=$num iflag=direct ||
25980                 error "dd with O_DIRECT large read failed"
25981         cmp --bytes=$((size * num)) $TMP/$tfile.0 $TMP/$tfile.2 ||
25982                 error "compare $TMP/$tfile.2 failed"
25983
25984         echo "bs=$size count=$num iflag=direct large read $tfile.3"
25985         dd if=$DIR/$tfile.3 of=$TMP/$tfile.3 bs=$size count=$num iflag=direct ||
25986                 error "dd with O_DIRECT large read failed"
25987         cmp --bytes=$((size * num)) $TMP/$tfile.0 $TMP/$tfile.3 ||
25988                 error "compare $TMP/$tfile.3 failed"
25989 }
25990 run_test 248b "test short_io read and write for both small and large sizes"
25991
25992 test_248c() {
25993         $LCTL set_param llite.*.read_ahead_stats=c
25994         # This test compares whole file readahead to non-whole file readahead
25995         # The performance should be consistently slightly faster for whole file,
25996         # and the bug caused whole file readahead to be 80-100x slower, but to
25997         # account for possible test system lag, we require whole file to be
25998         # <= 1.5xnon-whole file, and require 3 failures in a row to fail the
25999         # test
26000         local time1
26001         local time2
26002         local counter
26003         local whole_mb=$($LCTL get_param -n llite.*.max_read_ahead_whole_mb)
26004         stack_trap "$LCTL set_param llite.*.max_read_ahead_whole_mb=$whole_mb"
26005
26006         # LU-16904 Use stripe counct 1 for root before the readahead issue
26007         # described in LU-17755 and LU-15155 get fixed
26008         test_mkdir $DIR/$tdir || error "mkdir $tdir failed"
26009         $LFS setstripe -c 1 $DIR/$tdir || error "setstripe $tdir failed"
26010
26011         for (( counter = 0; counter < 3; counter++ )); do
26012                 $LCTL set_param llite.*.max_read_ahead_whole_mb=64
26013                 rm -f $DIR/$tdir/$tfile
26014                 touch $DIR/$tdir/$tfile || error "(0) failed to create file"
26015                 # 64 MiB
26016                 $TRUNCATE $DIR/$tdir/$tfile 67108864 || error "(1) trunc failed"
26017                 time1=$(dd if=$DIR/$tdir/$tfile bs=4K of=/dev/null 2>&1 |
26018                         awk '/bytes/ { print $8 }')
26019                 echo "whole file readahead of 64 MiB took $time1 seconds"
26020                 $LCTL get_param llite.*.read_ahead_stats
26021
26022                 $LCTL set_param llite.*.read_ahead_stats=clear
26023                 $LCTL set_param llite.*.max_read_ahead_whole_mb=8
26024                 rm -f $DIR/$tdir/$tfile
26025                 touch $DIR/$tdir/$tfile || error "(2) failed to create file"
26026                 # 64 MiB
26027                 $TRUNCATE $DIR/$tdir/$tfile 67108864 || error "(3) trunc failed"
26028                 time2=$(dd if=$DIR/$tdir/$tfile bs=4K of=/dev/null 2>&1 |
26029                         awk '/bytes/ { print $8 }')
26030                 echo "non-whole file readahead of 64 MiB took $time2 seconds"
26031                 $LCTL get_param llite.*.read_ahead_stats
26032
26033                 # Check if time1 is not more than 1.5 times2
26034                 timecheck=$(echo "$time1 <= (1.5 * $time2)" | bc -l)
26035
26036                 if (( $timecheck == 1 )); then
26037                         echo "Test passed on attempt $counter"
26038                         break
26039                 fi
26040                 echo "Try $counter failed: whole file readahead took: $time1, greater than non: $time2"
26041         done
26042         (( $counter < 3 )) ||
26043                 error "whole file readahead failed 3x, probably not just VM lag"
26044 }
26045 run_test 248c "verify whole file read behavior"
26046
26047 test_249() { # LU-7890
26048         [ $MDS1_VERSION -lt $(version_code 2.8.53) ] &&
26049                 skip "Need at least version 2.8.54"
26050
26051         rm -f $DIR/$tfile
26052         $LFS setstripe -c 1 $DIR/$tfile
26053         # Offset 2T == 4k * 512M
26054         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 seek=512M ||
26055                 error "dd to 2T offset failed"
26056 }
26057 run_test 249 "Write above 2T file size"
26058
26059 test_250() {
26060         [ "$(facet_fstype ost$(($($LFS getstripe -i $DIR/$tfile) + 1)))" = "zfs" ] \
26061          && skip "no 16TB file size limit on ZFS"
26062
26063         [ "$(facet_fstype ost$(($($LFS getstripe -i $DIR/$tfile) + 1)))" = "wbcfs" ] \
26064          && skip "no 16TB file size limit on wbcfs"
26065
26066         $LFS setstripe -c 1 $DIR/$tfile
26067         # ldiskfs extent file size limit is (16TB - 4KB - 1) bytes
26068         local size=$((16 * 1024 * 1024 * 1024 * 1024 - 4096 - 1))
26069         $TRUNCATE $DIR/$tfile $size || error "truncate $tfile to $size failed"
26070         dd if=/dev/zero of=$DIR/$tfile bs=10 count=1 oflag=append \
26071                 conv=notrunc,fsync && error "append succeeded"
26072         return 0
26073 }
26074 run_test 250 "Write above 16T limit"
26075
26076 test_251a() {
26077         $LFS setstripe -c -1 -S 1048576 $DIR/$tfile
26078
26079         #define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407
26080         #Skip once - writing the first stripe will succeed
26081         $LCTL set_param fail_loc=0xa0001407 fail_val=1
26082         $MULTIOP $DIR/$tfile o:O_RDWR:w2097152c 2>&1 | grep -q "short write" &&
26083                 error "short write happened"
26084
26085         $LCTL set_param fail_loc=0xa0001407 fail_val=1
26086         $MULTIOP $DIR/$tfile or2097152c 2>&1 | grep -q "short read" &&
26087                 error "short read happened"
26088
26089         rm -f $DIR/$tfile
26090 }
26091 run_test 251a "Handling short read and write correctly"
26092
26093 test_251b() {
26094         dd if=/dev/zero of=$DIR/$tfile bs=1k count=4 ||
26095                 error "write $tfile failed"
26096
26097         sleep 2 && echo 12345 >> $DIR/$tfile &
26098
26099         #define OBD_FAIL_LLITE_READ_PAUSE 0x1431
26100         $LCTL set_param fail_loc=0x1431 fail_val=5
26101         # seek to 4096, 2 seconds later, file size expand to 4102, and after
26102         # 5 seconds, read 10 bytes, the short read should
26103         # report:
26104         #                start ->+ read_len -> offset_after_read read_count
26105         #     short read: 4096 ->+ 10 -> 4096 0
26106         # not:
26107         #     short read: 4096 ->+ 10 -> 4102 0
26108         local off=$($MULTIOP $DIR/$tfile oO_RDONLY:z4096r10c 2>&1 | \
26109                         awk '/short read/ { print $7 }')
26110         (( off == 4096 )) ||
26111                 error "short read should set offset at 4096, not $off"
26112 }
26113 run_test 251b "short read restore offset correctly"
26114
26115 test_252() {
26116         remote_mds_nodsh && skip "remote MDS with nodsh"
26117         remote_ost_nodsh && skip "remote OST with nodsh"
26118         if [ "$ost1_FSTYPE" != ldiskfs ] || [ "$mds1_FSTYPE" != ldiskfs ]; then
26119                 skip_env "ldiskfs only test"
26120         fi
26121
26122         local tgt
26123         local dev
26124         local out
26125         local uuid
26126         local num
26127         local gen
26128
26129         # check lr_reader on OST0000
26130         tgt=ost1
26131         dev=$(facet_device $tgt)
26132         out=$(do_facet $tgt $LR_READER $dev)
26133         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
26134         echo "$out"
26135         uuid=$(echo "$out" | grep -i uuid | awk '{ print $2 }')
26136         [ "$uuid" == "$(ostuuid_from_index 0)" ] ||
26137                 error "Invalid uuid returned by $LR_READER on target $tgt"
26138         echo -e "uuid returned by $LR_READER is '$uuid'\n"
26139
26140         # check lr_reader -c on MDT0000
26141         tgt=mds1
26142         dev=$(facet_device $tgt)
26143         if ! do_facet $tgt $LR_READER -h | grep -q OPTIONS; then
26144                 skip "$LR_READER does not support additional options"
26145         fi
26146         out=$(do_facet $tgt $LR_READER -c $dev)
26147         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
26148         echo "$out"
26149         num=$(echo "$out" | grep -c "mdtlov")
26150         [ "$num" -eq $((MDSCOUNT - 1)) ] ||
26151                 error "Invalid number of mdtlov clients returned by $LR_READER"
26152         echo -e "Number of mdtlov clients returned by $LR_READER is '$num'\n"
26153
26154         # check lr_reader -cr on MDT0000
26155         out=$(do_facet $tgt $LR_READER -cr $dev)
26156         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
26157         echo "$out"
26158         echo "$out" | grep -q "^reply_data:$" ||
26159                 error "$LR_READER should have returned 'reply_data' section"
26160         num=$(echo "$out" | grep -c "client_generation")
26161         echo -e "Number of reply data returned by $LR_READER is '$num'\n"
26162 }
26163 run_test 252 "check lr_reader tool"
26164
26165 test_253() {
26166         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26167         remote_mds_nodsh && skip "remote MDS with nodsh"
26168         remote_mgs_nodsh && skip "remote MGS with nodsh"
26169         check_set_fallocate_or_skip
26170
26171         local ostidx=0
26172         local rc=0
26173         local ost_name=$(ostname_from_index $ostidx)
26174
26175         # on the mdt's osc
26176         local mdtosc_proc1=$(get_mdtosc_proc_path $SINGLEMDS $ost_name)
26177         do_facet $SINGLEMDS $LCTL get_param -n \
26178                 osp.$mdtosc_proc1.reserved_mb_high ||
26179                 skip  "remote MDS does not support reserved_mb_high"
26180
26181         rm -rf $DIR/$tdir
26182         wait_mds_ost_sync
26183         wait_delete_completed
26184         mkdir $DIR/$tdir
26185         stack_trap "rm -rf $DIR/$tdir"
26186
26187         pool_add $TESTNAME || error "Pool creation failed"
26188         pool_add_targets $TESTNAME 0 || error "Pool add targets failed"
26189
26190         $LFS setstripe $DIR/$tdir -i $ostidx -c 1 -p $FSNAME.$TESTNAME ||
26191                 error "Setstripe failed"
26192
26193         dd if=/dev/zero of=$DIR/$tdir/$tfile.0 bs=1M count=10
26194
26195         local wms=$(ost_watermarks_get $ostidx)
26196
26197         ost_watermarks_set $ostidx 60 50
26198         stack_trap "ost_watermarks_set $ostidx $wms"
26199
26200         local free_kb=$($LFS df $MOUNT | awk "/$ost_name/ { print \$4 }")
26201         local size=$((free_kb * 1024))
26202
26203         fallocate -l $size $DIR/$tdir/fill_ost$ostidx ||
26204                 error "fallocate failed"
26205         sleep_maxage
26206
26207         local oa_status=$(do_facet $SINGLEMDS $LCTL get_param -n \
26208                         osp.$mdtosc_proc1.prealloc_status)
26209         echo "prealloc_status $oa_status"
26210
26211         dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=1M count=1 &&
26212                 error "File creation should fail"
26213
26214         #object allocation was stopped, but we still able to append files
26215         dd if=/dev/zero of=$DIR/$tdir/$tfile.0 bs=1M seek=6 count=5 \
26216                 oflag=append || error "Append failed"
26217
26218         rm -f $DIR/$tdir/$tfile.0
26219         rm -f $DIR/$tdir/fill_ost$ostidx
26220
26221         wait_delete_completed
26222         sleep_maxage
26223
26224         for i in $(seq 10 12); do
26225                 dd if=/dev/zero of=$DIR/$tdir/$tfile.$i bs=1M count=1 \
26226                         2>/dev/null || error "File creation failed after rm"
26227         done
26228
26229         oa_status=$(do_facet $SINGLEMDS $LCTL get_param -n \
26230                         osp.$mdtosc_proc1.prealloc_status)
26231         echo "prealloc_status $oa_status"
26232
26233         if (( oa_status != 0 )); then
26234                 error "Object allocation still disable after rm"
26235         fi
26236 }
26237 run_test 253 "Check object allocation limit"
26238
26239 test_254() {
26240         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26241         remote_mds_nodsh && skip "remote MDS with nodsh"
26242
26243         local mdt=$(facet_svc $SINGLEMDS)
26244
26245         do_facet $SINGLEMDS $LCTL get_param -n mdd.$mdt.changelog_size ||
26246                 skip "MDS does not support changelog_size"
26247
26248         local cl_user
26249
26250         changelog_register || error "changelog_register failed"
26251
26252         changelog_clear 0 || error "changelog_clear failed"
26253
26254         local size1=$(do_facet $SINGLEMDS \
26255                       $LCTL get_param -n mdd.$mdt.changelog_size)
26256         echo "Changelog size $size1"
26257
26258         rm -rf $DIR/$tdir
26259         $LFS mkdir -i 0 $DIR/$tdir
26260         # change something
26261         mkdir -p $DIR/$tdir/pics/2008/zachy
26262         touch $DIR/$tdir/pics/2008/zachy/timestamp
26263         cp /etc/hosts $DIR/$tdir/pics/2008/zachy/pic1.jpg
26264         mv $DIR/$tdir/pics/2008/zachy $DIR/$tdir/pics/zach
26265         ln $DIR/$tdir/pics/zach/pic1.jpg $DIR/$tdir/pics/2008/portland.jpg
26266         ln -s $DIR/$tdir/pics/2008/portland.jpg $DIR/$tdir/pics/desktop.jpg
26267         rm $DIR/$tdir/pics/desktop.jpg
26268
26269         local size2=$(do_facet $SINGLEMDS \
26270                       $LCTL get_param -n mdd.$mdt.changelog_size)
26271         echo "Changelog size after work $size2"
26272
26273         (( $size2 > $size1 )) ||
26274                 error "new Changelog size=$size2 less than old size=$size1"
26275 }
26276 run_test 254 "Check changelog size"
26277
26278 ladvise_no_type()
26279 {
26280         local type=$1
26281         local file=$2
26282
26283         lfs ladvise -a invalid $file 2>&1 | grep "Valid types" |
26284                 awk -F: '{print $2}' | grep $type > /dev/null
26285         if [ $? -ne 0 ]; then
26286                 return 0
26287         fi
26288         return 1
26289 }
26290
26291 ladvise_no_ioctl()
26292 {
26293         local file=$1
26294
26295         lfs ladvise -a willread $file > /dev/null 2>&1
26296         if [ $? -eq 0 ]; then
26297                 return 1
26298         fi
26299
26300         lfs ladvise -a willread $file 2>&1 |
26301                 grep "Inappropriate ioctl for device" > /dev/null
26302         if [ $? -eq 0 ]; then
26303                 return 0
26304         fi
26305         return 1
26306 }
26307
26308 percent() {
26309         # don't print any decimal places to avoid bash comparison issues
26310         bc <<< "scale=0; ($1 - $2) * 100 / $2"
26311 }
26312
26313 # run a random read IO workload
26314 # usage: random_read_iops <filename> <filesize> <iosize>
26315 random_read_iops() {
26316         local file=$1
26317         local fsize=$2
26318         local iosize=${3:-4096}
26319
26320         $READS -f $file -s $fsize -b $iosize -n $((fsize / iosize)) -t 60 |
26321                 sed -e '/^$/d' -e 's#.*s, ##' -e 's#MB/s##'
26322 }
26323
26324 drop_file_oss_cache() {
26325         local file="$1"
26326         local nodes="$2"
26327
26328         $LFS ladvise -a dontneed $file 2>/dev/null ||
26329                 do_nodes $nodes "echo 3 > /proc/sys/vm/drop_caches"
26330 }
26331
26332 ladvise_willread_performance()
26333 {
26334         local repeat=10
26335         local average_origin=0
26336         local average_cache=0
26337         local average_ladvise=0
26338         local osts=$(osts_nodes)
26339
26340         # Hybrid IO switches to DIO, which invalidates much of the caching
26341         # So disable it for this test
26342         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
26343         $LCTL set_param llite.*.hybrid_io=0
26344         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
26345
26346         for ((i = 1; i <= $repeat; i++)); do
26347                 echo "Iter $i/$repeat: reading without willread hint"
26348                 cancel_lru_locks osc
26349                 drop_file_oss_cache $DIR/$tfile $osts
26350                 local speed_origin=$(random_read_iops $DIR/$tfile $size)
26351                 echo "Iter $i/$repeat: uncached speed: $speed_origin"
26352                 average_origin=$(bc <<<"$average_origin + $speed_origin")
26353
26354                 cancel_lru_locks osc
26355                 local speed_cache=$(random_read_iops $DIR/$tfile $size)
26356                 echo "Iter $i/$repeat: OSS cache speed: $speed_cache"
26357                 average_cache=$(bc <<<"$average_cache + $speed_cache")
26358
26359                 cancel_lru_locks osc
26360                 drop_file_oss_cache $DIR/$tfile $osts
26361                 $LFS ladvise -a willread $DIR/$tfile || error "ladvise failed"
26362                 local speed_ladvise=$(random_read_iops $DIR/$tfile $size)
26363                 echo "Iter $i/$repeat: ladvise speed: $speed_ladvise"
26364                 average_ladvise=$(bc <<<"$average_ladvise + $speed_ladvise")
26365         done
26366         average_origin=$(bc <<<"scale=2; $average_origin / $repeat")
26367         average_cache=$(bc <<<"scale=2; $average_cache / $repeat")
26368         average_ladvise=$(bc <<<"scale=2; $average_ladvise / $repeat")
26369
26370         speedup_cache=$(percent $average_cache $average_origin)
26371         speedup_ladvise=$(percent $average_ladvise $average_origin)
26372
26373         echo "Average uncached read: $average_origin"
26374         echo "Average speedup with OSS cached read: " \
26375                 "$average_cache = +$speedup_cache%"
26376         echo "Average speedup with ladvise willread: " \
26377                 "$average_ladvise = +$speedup_ladvise%"
26378
26379         local lowest_speedup=20
26380         if (( $speedup_cache < $lowest_speedup )); then
26381                 echo "Speedup with OSS cached read less than $lowest_speedup%,"\
26382                      " got $speedup_cache%. Skipping ladvise willread check."
26383                 return 0
26384         fi
26385
26386         # the test won't work on ZFS until it supports 'ladvise dontneed', but
26387         # it is still good to run until then to exercise 'ladvise willread'
26388         ! $LFS ladvise -a dontneed $DIR/$tfile &&
26389                 [ "$ost1_FSTYPE" = "zfs" ] &&
26390                 echo "osd-zfs does not support dontneed or drop_caches" &&
26391                 return 0
26392
26393         lowest_speedup=$(bc <<< "scale=0; $average_cache / 2")
26394         (( $speedup_ladvise > $lowest_speedup )) ||
26395                 error_not_in_vm "Speedup with willread is less than " \
26396                         "$lowest_speedup%, got $speedup_ladvise%"
26397 }
26398
26399 test_255a() {
26400         [ $OST1_VERSION -lt $(version_code 2.8.54) ] &&
26401                 skip "lustre < 2.8.54 does not support ladvise "
26402         remote_ost_nodsh && skip "remote OST with nodsh"
26403
26404         stack_trap "rm -f $DIR/$tfile"
26405         lfs setstripe -c -1 -i 0 $DIR/$tfile || error "$tfile failed"
26406
26407         ladvise_no_type willread $DIR/$tfile &&
26408                 skip "willread ladvise is not supported"
26409
26410         ladvise_no_ioctl $DIR/$tfile &&
26411                 skip "ladvise ioctl is not supported"
26412
26413         local size_mb=100
26414         local size=$((size_mb * 1048576))
26415         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=$size_mb ||
26416                 error "dd to $DIR/$tfile failed"
26417
26418         lfs ladvise -a willread $DIR/$tfile ||
26419                 error "Ladvise failed with no range argument"
26420
26421         lfs ladvise -a willread -s 0 $DIR/$tfile ||
26422                 error "Ladvise failed with no -l or -e argument"
26423
26424         lfs ladvise -a willread -e 1 $DIR/$tfile ||
26425                 error "Ladvise failed with only -e argument"
26426
26427         lfs ladvise -a willread -l 1 $DIR/$tfile ||
26428                 error "Ladvise failed with only -l argument"
26429
26430         lfs ladvise -a willread -s 2 -e 1 $DIR/$tfile &&
26431                 error "End offset should not be smaller than start offset"
26432
26433         lfs ladvise -a willread -s 2 -e 2 $DIR/$tfile &&
26434                 error "End offset should not be equal to start offset"
26435
26436         lfs ladvise -a willread -s $size -l 1 $DIR/$tfile ||
26437                 error "Ladvise failed with overflowing -s argument"
26438
26439         lfs ladvise -a willread -s 1 -e $((size + 1)) $DIR/$tfile ||
26440                 error "Ladvise failed with overflowing -e argument"
26441
26442         lfs ladvise -a willread -s 1 -l $size $DIR/$tfile ||
26443                 error "Ladvise failed with overflowing -l argument"
26444
26445         lfs ladvise -a willread -l 1 -e 2 $DIR/$tfile &&
26446                 error "Ladvise succeeded with conflicting -l and -e arguments"
26447
26448         echo "Synchronous ladvise should wait"
26449         local delay=8
26450         local osts=$(osts_nodes)
26451
26452         #define OBD_FAIL_OST_LADVISE_PAUSE       0x237
26453         do_nodes $osts $LCTL set_param fail_val=$delay fail_loc=0x237
26454         stack_trap "do_nodes $osts $LCTL set_param fail_loc=0"
26455
26456         local start_ts=$SECONDS
26457         lfs ladvise -a willread $DIR/$tfile ||
26458                 error "Ladvise failed with no range argument"
26459         local end_ts=$SECONDS
26460         local inteval_ts=$((end_ts - start_ts))
26461
26462         if [ $inteval_ts -lt $(($delay - 1)) ]; then
26463                 error "Synchronous advice didn't wait reply"
26464         fi
26465
26466         echo "Asynchronous ladvise shouldn't wait"
26467         local start_ts=$SECONDS
26468         lfs ladvise -a willread -b $DIR/$tfile ||
26469                 error "Ladvise failed with no range argument"
26470         local end_ts=$SECONDS
26471         local inteval_ts=$((end_ts - start_ts))
26472
26473         if [ $inteval_ts -gt $(($delay / 2)) ]; then
26474                 error "Asynchronous advice blocked"
26475         fi
26476
26477         ladvise_willread_performance
26478 }
26479 run_test 255a "check 'lfs ladvise -a willread'"
26480
26481 facet_meminfo() {
26482         local facet=$1
26483         local info=$2
26484
26485         do_facet $facet "cat /proc/meminfo | grep ^${info}:" | awk '{print $2}'
26486 }
26487
26488 test_255b() {
26489         [ $OST1_VERSION -lt $(version_code 2.8.54) ] &&
26490                 skip "lustre < 2.8.54 does not support ladvise "
26491         remote_ost_nodsh && skip "remote OST with nodsh"
26492
26493         stack_trap "rm -f $DIR/$tfile"
26494         lfs setstripe -c 1 -i 0 $DIR/$tfile
26495
26496         ladvise_no_type dontneed $DIR/$tfile &&
26497                 skip "dontneed ladvise is not supported"
26498
26499         ladvise_no_ioctl $DIR/$tfile &&
26500                 skip "ladvise ioctl is not supported"
26501
26502         ! $LFS ladvise -a dontneed $DIR/$tfile &&
26503                 [ "$ost1_FSTYPE" = "zfs" ] &&
26504                 skip "zfs-osd does not support 'ladvise dontneed'"
26505
26506         local size_mb=100
26507         local size=$((size_mb * 1048576))
26508         # In order to prevent disturbance of other processes, only check 3/4
26509         # of the memory usage
26510         local kibibytes=$((size_mb * 1024 * 3 / 4))
26511
26512         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=$size_mb ||
26513                 error "dd to $DIR/$tfile failed"
26514
26515         #force write to complete before dropping OST cache & checking memory
26516         sync
26517
26518         local total=$(facet_meminfo ost1 MemTotal)
26519         echo "Total memory: $total KiB"
26520
26521         do_facet ost1 "sync && echo 3 > /proc/sys/vm/drop_caches"
26522         local before_read=$(facet_meminfo ost1 Cached)
26523         echo "Cache used before read: $before_read KiB"
26524
26525         lfs ladvise -a willread $DIR/$tfile ||
26526                 error "Ladvise willread failed"
26527         local after_read=$(facet_meminfo ost1 Cached)
26528         echo "Cache used after read: $after_read KiB"
26529
26530         lfs ladvise -a dontneed $DIR/$tfile ||
26531                 error "Ladvise dontneed again failed"
26532         local no_read=$(facet_meminfo ost1 Cached)
26533         echo "Cache used after dontneed ladvise: $no_read KiB"
26534
26535         if [ $total -lt $((before_read + kibibytes)) ]; then
26536                 echo "Memory is too small, abort checking"
26537                 return 0
26538         fi
26539
26540         if [ $((before_read + kibibytes)) -gt $after_read ]; then
26541                 error "Ladvise willread should use more memory" \
26542                         "than $kibibytes KiB"
26543         fi
26544
26545         if [ $((no_read + kibibytes)) -gt $after_read ]; then
26546                 error "Ladvise dontneed should release more memory" \
26547                         "than $kibibytes KiB"
26548         fi
26549 }
26550 run_test 255b "check 'lfs ladvise -a dontneed'"
26551
26552 test_255c() {
26553         [ $OST1_VERSION -lt $(version_code 2.10.50) ] &&
26554                 skip "lustre < 2.10.50 does not support lockahead"
26555
26556         local ost1_imp=$(get_osc_import_name client ost1)
26557         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
26558                          cut -d'.' -f2)
26559         local count
26560         local new_count
26561         local difference
26562         local i
26563         local rc
26564
26565         test_mkdir -p $DIR/$tdir
26566         $LFS setstripe -i 0 -c 1 $DIR/$tdir
26567
26568         #test 10 returns only success/failure
26569         i=10
26570         lockahead_test -d $DIR/$tdir -t $i -f $tfile
26571         rc=$?
26572         if [ $rc -eq 255 ]; then
26573                 error "Ladvise test${i} failed, ${rc}"
26574         fi
26575
26576         #test 11 counts lock enqueue requests, all others count new locks
26577         i=11
26578         count=$(do_facet ost1 \
26579                 $LCTL get_param -n ost.OSS.ost.stats)
26580         count=$(echo "$count" | grep ldlm_extent_enqueue | awk '{ print $2 }')
26581
26582         lockahead_test -d $DIR/$tdir -t $i -f $tfile
26583         rc=$?
26584         if [ $rc -eq 255 ]; then
26585                 error "Ladvise test${i} failed, ${rc}"
26586         fi
26587
26588         new_count=$(do_facet ost1 \
26589                 $LCTL get_param -n ost.OSS.ost.stats)
26590         new_count=$(echo "$new_count" | grep ldlm_extent_enqueue | \
26591                    awk '{ print $2 }')
26592
26593         difference="$((new_count - count))"
26594         if [ $difference -ne $rc ]; then
26595                 error "Ladvise test${i}, bad enqueue count, returned " \
26596                       "${rc}, actual ${difference}"
26597         fi
26598
26599         for i in $(seq 12 21); do
26600                 # If we do not do this, we run the risk of having too many
26601                 # locks and starting lock cancellation while we are checking
26602                 # lock counts.
26603                 cancel_lru_locks osc
26604
26605                 count=$($LCTL get_param -n \
26606                        ldlm.namespaces.$imp_name.lock_unused_count)
26607
26608                 lockahead_test -d $DIR/$tdir -t $i -f $tfile
26609                 rc=$?
26610                 if [ $rc -eq 255 ]; then
26611                         error "Ladvise test ${i} failed, ${rc}"
26612                 fi
26613
26614                 new_count=$($LCTL get_param -n \
26615                        ldlm.namespaces.$imp_name.lock_unused_count)
26616                 difference="$((new_count - count))"
26617
26618                 # Test 15 output is divided by 100 to map down to valid return
26619                 if [ $i -eq 15 ]; then
26620                         rc="$((rc * 100))"
26621                 fi
26622
26623                 if [ $difference -ne $rc ]; then
26624                         error "Ladvise test ${i}, bad lock count, returned " \
26625                               "${rc}, actual ${difference}"
26626                 fi
26627         done
26628
26629         #test 22 returns only success/failure
26630         i=22
26631         lockahead_test -d $DIR/$tdir -t $i -f $tfile
26632         rc=$?
26633         if [ $rc -eq 255 ]; then
26634                 error "Ladvise test${i} failed, ${rc}"
26635         fi
26636 }
26637 run_test 255c "suite of ladvise lockahead tests"
26638
26639 test_256() {
26640         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26641         remote_mds_nodsh && skip "remote MDS with nodsh"
26642         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
26643         changelog_users $SINGLEMDS | grep "^cl" &&
26644                 skip "active changelog user"
26645
26646         local cl_user
26647         local cat_sl
26648         local mdt_dev
26649
26650         mdt_dev=$(facet_device $SINGLEMDS)
26651         echo $mdt_dev
26652
26653         changelog_register || error "changelog_register failed"
26654
26655         rm -rf $DIR/$tdir
26656         mkdir_on_mdt -i$(($(facet_number $SINGLEMDS) - 1)) $DIR/$tdir
26657
26658         changelog_clear 0 || error "changelog_clear failed"
26659
26660         # change something
26661         touch $DIR/$tdir/{1..10}
26662
26663         # stop the MDT
26664         stop $SINGLEMDS || error "Fail to stop MDT"
26665
26666         # remount the MDT
26667         start $SINGLEMDS $(facet_device $SINGLEMDS) $MDS_MOUNT_OPTS ||
26668                 error "Fail to start MDT"
26669
26670         #after mount new plainllog is used
26671         touch $DIR/$tdir/{11..19}
26672         local tmpfile="$(mktemp --tmpdir -u $tfile.XXXXXX)"
26673         stack_trap "rm -f $tmpfile"
26674         cat_sl=$(do_facet $SINGLEMDS "sync; \
26675                  $DEBUGFS -c -R 'dump changelog_catalog $tmpfile' $mdt_dev; \
26676                  llog_reader $tmpfile | grep -c type=1064553b")
26677         do_facet $SINGLEMDS llog_reader $tmpfile
26678
26679         [ $cat_sl != 2 ] && error "Changelog catalog has $cat_sl != 2 slots"
26680
26681         changelog_clear 0 || error "changelog_clear failed"
26682
26683         cat_sl=$(do_facet $SINGLEMDS "sync; \
26684                  $DEBUGFS -c -R 'dump changelog_catalog $tmpfile' $mdt_dev; \
26685                  llog_reader $tmpfile | grep -c type=1064553b")
26686
26687         if (( cat_sl == 2 )); then
26688                 error "Empty plain llog was not deleted from changelog catalog"
26689         elif (( cat_sl != 1 )); then
26690                 error "Active plain llog shouldn't be deleted from catalog"
26691         fi
26692 }
26693 run_test 256 "Check llog delete for empty and not full state"
26694
26695 test_257() {
26696         remote_mds_nodsh && skip "remote MDS with nodsh"
26697         [[ $MDS1_VERSION -lt $(version_code 2.8.55) ]] &&
26698                 skip "Need MDS version at least 2.8.55"
26699
26700         test_mkdir $DIR/$tdir
26701
26702         setfattr -n trusted.name1 -v value1 $DIR/$tdir ||
26703                 error "setfattr -n trusted.name1=value1 $DIR/$tdir failed"
26704         stat $DIR/$tdir
26705
26706 #define OBD_FAIL_MDS_XATTR_REP                  0x161
26707         local mdtidx=$($LFS getstripe -m $DIR/$tdir)
26708         local facet=mds$((mdtidx + 1))
26709         set_nodes_failloc $(facet_active_host $facet) 0x80000161
26710         getfattr -n trusted.name1 $DIR/$tdir 2> /dev/null
26711
26712         stop $facet || error "stop MDS failed"
26713         start $facet $(mdsdevname $((mdtidx + 1))) $MDS_MOUNT_OPTS ||
26714                 error "start MDS fail"
26715         wait_recovery_complete $facet
26716 }
26717 run_test 257 "xattr locks are not lost"
26718
26719 # Verify we take the i_mutex when security requires it
26720 test_258a() {
26721 #define OBD_FAIL_IMUTEX_SEC 0x141c
26722         $LCTL set_param fail_loc=0x141c
26723         touch $DIR/$tfile
26724         chmod u+s $DIR/$tfile
26725         chmod a+rwx $DIR/$tfile
26726         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 oflag=append
26727         RC=$?
26728         if [ $RC -ne 0 ]; then
26729                 error "error, failed to take i_mutex, rc=$?"
26730         fi
26731         rm -f $DIR/$tfile
26732 }
26733 run_test 258a "verify i_mutex security behavior when suid attributes is set"
26734
26735 # Verify we do NOT take the i_mutex in the normal case
26736 test_258b() {
26737 #define OBD_FAIL_IMUTEX_NOSEC 0x141d
26738         $LCTL set_param fail_loc=0x141d
26739         touch $DIR/$tfile
26740         chmod a+rwx $DIR
26741         chmod a+rw $DIR/$tfile
26742         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 oflag=append
26743         RC=$?
26744         if [ $RC -ne 0 ]; then
26745                 error "error, took i_mutex unnecessarily, rc=$?"
26746         fi
26747         rm -f $DIR/$tfile
26748
26749 }
26750 run_test 258b "verify i_mutex security behavior"
26751
26752 test_259() {
26753         local file=$DIR/$tfile
26754         local before
26755         local after
26756
26757         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
26758
26759         stack_trap "rm -f $file" EXIT
26760
26761         wait_delete_completed
26762         before=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
26763         echo "before: $before"
26764
26765         $LFS setstripe -i 0 -c 1 $file
26766         dd if=/dev/zero of=$file bs=1M count=10 || error "couldn't write"
26767         sync_all_data
26768         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
26769         echo "after write: $after"
26770
26771 #define OBD_FAIL_OSD_FAIL_AT_TRUNCATE          0x2301
26772         do_facet ost1 $LCTL set_param fail_loc=0x2301
26773         $TRUNCATE $file 0
26774         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
26775         echo "after truncate: $after"
26776
26777         stop ost1
26778         do_facet ost1 $LCTL set_param fail_loc=0
26779         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
26780         sleep 2
26781         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
26782         echo "after restart: $after"
26783         [ $((after - before)) -ge $(fs_log_size ost1) ] &&
26784                 error "missing truncate?"
26785
26786         return 0
26787 }
26788 run_test 259 "crash at delayed truncate"
26789
26790 test_260() {
26791 #define OBD_FAIL_MDC_CLOSE               0x806
26792         $LCTL set_param fail_loc=0x80000806
26793         touch $DIR/$tfile
26794
26795 }
26796 run_test 260 "Check mdc_close fail"
26797
26798 ### Data-on-MDT sanity tests ###
26799 test_270a() {
26800         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
26801                 skip "Need MDS version at least 2.10.55 for DoM"
26802
26803         # create DoM file
26804         local dom=$DIR/$tdir/dom_file
26805         local tmp=$DIR/$tdir/tmp_file
26806
26807         mkdir_on_mdt0 $DIR/$tdir
26808
26809         # basic checks for DoM component creation
26810         $LFS setstripe -E 1024K -E 2048K -L mdt $dom 2>/dev/null &&
26811                 error "Can set MDT layout to non-first entry"
26812
26813         $LFS setstripe -E 1024K -L mdt -E 2048K -L mdt $dom 2>/dev/null &&
26814                 error "Can define multiple entries as MDT layout"
26815
26816         $LFS setstripe -E 1M -L mdt $dom || error "Can't create DoM layout"
26817
26818         [ $($LFS getstripe -L $dom) == "mdt" ] || error "bad pattern"
26819         [ $($LFS getstripe -c $dom) == 0 ] || error "bad stripe count"
26820         [ $($LFS getstripe -S $dom) == 1048576 ] || error "bad stripe size"
26821
26822         local mdtidx=$($LFS getstripe -m $dom)
26823         local mdtname=MDT$(printf %04x $mdtidx)
26824         local facet=mds$((mdtidx + 1))
26825         local space_check=1
26826
26827         # Skip free space checks with ZFS
26828         [ "$(facet_fstype $facet)" == "zfs" ] && space_check=0
26829
26830         # write
26831         sync
26832         local size_tmp=$((65536 * 3))
26833         local mdtfree1=$(do_facet $facet \
26834                          lctl get_param -n osd*.*$mdtname.kbytesfree)
26835
26836         dd if=/dev/urandom of=$tmp bs=1024 count=$((size_tmp / 1024))
26837         # check also direct IO along write
26838         # IO size must be a multiple of PAGE_SIZE on all platforms (ARM=64KB)
26839         dd if=$tmp of=$dom bs=65536 count=$((size_tmp / 65536)) oflag=direct
26840         sync
26841         cmp $tmp $dom || error "file data is different"
26842         [ $(stat -c%s $dom) == $size_tmp ] ||
26843                 error "bad size after write: $(stat -c%s $dom) != $size_tmp"
26844         if [ $space_check == 1 ]; then
26845                 local mdtfree2=$(do_facet $facet \
26846                                  lctl get_param -n osd*.*$mdtname.kbytesfree)
26847
26848                 # increase in usage from by $size_tmp
26849                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_tmp / 1024)) ] ||
26850                         error "MDT free space wrong after write: " \
26851                               "$mdtfree1 >= $mdtfree2 + $size_tmp/1024"
26852         fi
26853
26854         # truncate
26855         local size_dom=10000
26856
26857         $TRUNCATE $dom $size_dom
26858         [ $(stat -c%s $dom) == $size_dom ] ||
26859                 error "bad size after truncate: $(stat -c%s $dom) != $size_dom"
26860         if [ $space_check == 1 ]; then
26861                 mdtfree1=$(do_facet $facet \
26862                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
26863                 # decrease in usage from $size_tmp to new $size_dom
26864                 [ $(($mdtfree1 - $mdtfree2)) -ge \
26865                   $(((size_tmp - size_dom) / 1024)) ] ||
26866                         error "MDT free space is wrong after truncate: " \
26867                               "$mdtfree1 >= $mdtfree2 + ($size_tmp - $size_dom) / 1024"
26868         fi
26869
26870         # append
26871         cat $tmp >> $dom
26872         sync
26873         size_dom=$((size_dom + size_tmp))
26874         [ $(stat -c%s $dom) == $size_dom ] ||
26875                 error "bad size after append: $(stat -c%s $dom) != $size_dom"
26876         if [ $space_check == 1 ]; then
26877                 mdtfree2=$(do_facet $facet \
26878                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
26879                 # increase in usage by $size_tmp from previous
26880                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_tmp / 1024)) ] ||
26881                         error "MDT free space is wrong after append: " \
26882                               "$mdtfree1 >= $mdtfree2 + $size_tmp/1024"
26883         fi
26884
26885         # delete
26886         rm $dom
26887         if [ $space_check == 1 ]; then
26888                 mdtfree1=$(do_facet $facet \
26889                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
26890                 # decrease in usage by $size_dom from previous
26891                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_dom / 1024)) ] ||
26892                         error "MDT free space is wrong after removal: " \
26893                               "$mdtfree1 >= $mdtfree2 + $size_dom/1024"
26894         fi
26895
26896         # combined striping
26897         $LFS setstripe -E 1024K -L mdt -E EOF $dom ||
26898                 error "Can't create DoM + OST striping"
26899
26900         size_tmp=2031616 # must be a multiple of PAGE_SIZE=65536 on ARM
26901         dd if=/dev/urandom of=$tmp bs=1024 count=$((size_tmp / 1024))
26902         # check also direct IO along write
26903         dd if=$tmp of=$dom bs=65536 count=$((size_tmp / 65536)) oflag=direct
26904         sync
26905         cmp $tmp $dom || error "file data is different"
26906         [ $(stat -c%s $dom) == $size_tmp ] ||
26907                 error "bad size after write: $(stat -c%s $dom) != $size_tmp"
26908         rm $dom $tmp
26909
26910         return 0
26911 }
26912 run_test 270a "DoM: basic functionality tests"
26913
26914 test_270b() {
26915         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
26916                 skip "Need MDS version at least 2.10.55"
26917
26918         local dom=$DIR/$tdir/dom_file
26919         local max_size=1048576
26920
26921         mkdir -p $DIR/$tdir
26922         $LFS setstripe -E $max_size -L mdt $dom
26923
26924         # truncate over the limit
26925         $TRUNCATE $dom $(($max_size + 1)) &&
26926                 error "successful truncate over the maximum size"
26927         # write over the limit
26928         dd if=/dev/zero of=$dom bs=$max_size seek=1 count=1 &&
26929                 error "successful write over the maximum size"
26930         # append over the limit
26931         dd if=/dev/zero of=$dom bs=$(($max_size - 3)) count=1
26932         echo "12345" >> $dom && error "successful append over the maximum size"
26933         rm $dom
26934
26935         return 0
26936 }
26937 run_test 270b "DoM: maximum size overflow checks for DoM-only file"
26938
26939 test_270c() {
26940         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
26941                 skip "Need MDS version at least 2.10.55"
26942
26943         mkdir -p $DIR/$tdir
26944         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
26945
26946         # check files inherit DoM EA
26947         touch $DIR/$tdir/first
26948         [ $($LFS getstripe -L $DIR/$tdir/first) == "mdt" ] ||
26949                 error "bad pattern"
26950         [ $($LFS getstripe -c $DIR/$tdir/first) == 0 ] ||
26951                 error "bad stripe count"
26952         [ $($LFS getstripe -S $DIR/$tdir/first) == 1048576 ] ||
26953                 error "bad stripe size"
26954
26955         # check directory inherits DoM EA and uses it as default
26956         mkdir $DIR/$tdir/subdir
26957         touch $DIR/$tdir/subdir/second
26958         [ $($LFS getstripe -L $DIR/$tdir/subdir/second) == "mdt" ] ||
26959                 error "bad pattern in sub-directory"
26960         [ $($LFS getstripe -c $DIR/$tdir/subdir/second) == 0 ] ||
26961                 error "bad stripe count in sub-directory"
26962         [ $($LFS getstripe -S $DIR/$tdir/subdir/second) == 1048576 ] ||
26963                 error "bad stripe size in sub-directory"
26964         return 0
26965 }
26966 run_test 270c "DoM: DoM EA inheritance tests"
26967
26968 test_270d() {
26969         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
26970                 skip "Need MDS version at least 2.10.55"
26971
26972         mkdir -p $DIR/$tdir
26973         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
26974
26975         # inherit default DoM striping
26976         mkdir $DIR/$tdir/subdir
26977         touch $DIR/$tdir/subdir/f1
26978
26979         # change default directory striping
26980         $LFS setstripe -c 1 $DIR/$tdir/subdir
26981         touch $DIR/$tdir/subdir/f2
26982         [ $($LFS getstripe -c $DIR/$tdir/subdir/f2) == 1 ] ||
26983                 error "wrong default striping in file 2"
26984         [ $($LFS getstripe -L $DIR/$tdir/subdir/f2) == "raid0" ] ||
26985                 error "bad pattern in file 2"
26986         return 0
26987 }
26988 run_test 270d "DoM: change striping from DoM to RAID0"
26989
26990 test_270e() {
26991         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
26992                 skip "Need MDS version at least 2.10.55"
26993
26994         mkdir -p $DIR/$tdir/dom
26995         mkdir -p $DIR/$tdir/norm
26996         DOMFILES=20
26997         NORMFILES=10
26998         $LFS setstripe -E 1M -L mdt $DIR/$tdir/dom
26999         $LFS setstripe -i 0 -S 2M $DIR/$tdir/norm
27000
27001         createmany -o $DIR/$tdir/dom/dom- $DOMFILES
27002         createmany -o $DIR/$tdir/norm/norm- $NORMFILES
27003
27004         # find DoM files by layout
27005         NUM=$($LFS find -L mdt -type f $DIR/$tdir 2>/dev/null | wc -l)
27006         [ $NUM -eq  $DOMFILES ] ||
27007                 error "lfs find -L: found $NUM, expected $DOMFILES"
27008         echo "Test 1: lfs find 20 DOM files by layout: OK"
27009
27010         # there should be 1 dir with default DOM striping
27011         NUM=$($LFS find -L mdt -type d $DIR/$tdir 2>/dev/null | wc -l)
27012         [ $NUM -eq  1 ] ||
27013                 error "lfs find -L: found $NUM, expected 1 dir"
27014         echo "Test 2: lfs find 1 DOM dir by layout: OK"
27015
27016         # find DoM files by stripe size
27017         NUM=$($LFS find -S -1200K -type f $DIR/$tdir 2>/dev/null | wc -l)
27018         [ $NUM -eq  $DOMFILES ] ||
27019                 error "lfs find -S: found $NUM, expected $DOMFILES"
27020         echo "Test 4: lfs find 20 DOM files by stripe size: OK"
27021
27022         # find files by stripe offset except DoM files
27023         NUM=$($LFS find -i 0 -type f $DIR/$tdir 2>/dev/null | wc -l)
27024         [ $NUM -eq  $NORMFILES ] ||
27025                 error "lfs find -i: found $NUM, expected $NORMFILES"
27026         echo "Test 5: lfs find no DOM files by stripe index: OK"
27027         return 0
27028 }
27029 run_test 270e "DoM: lfs find with DoM files test"
27030
27031 test_270f() {
27032         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
27033                 skip "Need MDS version at least 2.10.55"
27034
27035         local mdtname=${FSNAME}-MDT0000-mdtlov
27036         local dom=$DIR/$tdir/dom_file
27037         local dom_limit_saved=$(do_facet mds1 $LCTL get_param -n \
27038                                                 lod.$mdtname.dom_stripesize)
27039         local dom_limit=131072
27040
27041         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=$dom_limit
27042         local dom_current=$(do_facet mds1 $LCTL get_param -n \
27043                                                 lod.$mdtname.dom_stripesize)
27044         [ ${dom_limit} -eq ${dom_current} ] ||
27045                 error "Cannot change per-MDT DoM stripe limit to $dom_limit"
27046
27047         $LFS mkdir -i 0 -c 1 $DIR/$tdir
27048         $LFS setstripe -d $DIR/$tdir
27049         $LFS setstripe -E $dom_limit -L mdt $DIR/$tdir ||
27050                 error "Can't set directory default striping"
27051
27052         # exceed maximum stripe size
27053         $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom ||
27054                 error "Can't create file with $((dom_limit * 2)) DoM stripe"
27055         [ $($LFS getstripe -S $dom) -eq $((dom_limit * 2)) ] &&
27056                 error "Able to create DoM component size more than LOD limit"
27057
27058         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=0
27059         dom_current=$(do_facet mds1 $LCTL get_param -n \
27060                                                 lod.$mdtname.dom_stripesize)
27061         [ 0 -eq ${dom_current} ] ||
27062                 error "Can't set zero DoM stripe limit"
27063         rm $dom
27064
27065         # attempt to create DoM file on server with disabled DoM should
27066         # remove DoM entry from layout and be succeed
27067         $LFS setstripe -E $dom_limit -L mdt -E -1 $dom ||
27068                 error "Can't create DoM file (DoM is disabled)"
27069         [ $($LFS getstripe -L $dom) == "mdt" ] &&
27070                 error "File has DoM component while DoM is disabled"
27071         rm $dom
27072
27073         # attempt to create DoM file with only DoM stripe should return error
27074         $LFS setstripe -E $dom_limit -L mdt $dom &&
27075                 error "Able to create DoM-only file while DoM is disabled"
27076
27077         # too low values to be aligned with smallest stripe size 64K
27078         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=30000
27079         dom_current=$(do_facet mds1 $LCTL get_param -n \
27080                                                 lod.$mdtname.dom_stripesize)
27081         [ 30000 -eq ${dom_current} ] &&
27082                 error "Can set too small DoM stripe limit"
27083
27084         # 64K is a minimal stripe size in Lustre, expect limit of that size
27085         [ 65536 -eq ${dom_current} ] ||
27086                 error "Limit is not set to 64K but ${dom_current}"
27087
27088         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=2147483648
27089         dom_current=$(do_facet mds1 $LCTL get_param -n \
27090                                                 lod.$mdtname.dom_stripesize)
27091         echo $dom_current
27092         [ 2147483648 -eq ${dom_current} ] &&
27093                 error "Can set too large DoM stripe limit"
27094
27095         do_facet mds1 $LCTL set_param -n \
27096                                 lod.$mdtname.dom_stripesize=$((dom_limit * 2))
27097         $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom ||
27098                 error "Can't create DoM component size after limit change"
27099         do_facet mds1 $LCTL set_param -n \
27100                                 lod.$mdtname.dom_stripesize=$((dom_limit / 2))
27101         $LFS setstripe -E $dom_limit -L mdt ${dom}_big ||
27102                 error "Can't create DoM file after limit decrease"
27103         [ $($LFS getstripe -S ${dom}_big) -eq $((dom_limit / 2)) ] ||
27104                 error "Can create big DoM component after limit decrease"
27105         touch ${dom}_def ||
27106                 error "Can't create file with old default layout"
27107
27108         do_facet mds1 $LCTL set_param -n lod.*.dom_stripesize=$dom_limit_saved
27109         return 0
27110 }
27111 run_test 270f "DoM: maximum DoM stripe size checks"
27112
27113 test_270g() {
27114         [ $MDS1_VERSION -ge $(version_code 2.13.52) ] ||
27115                 skip "Need MDS version at least 2.13.52"
27116         local dom=$DIR/$tdir/$tfile
27117
27118         $LFS mkdir -i 0 -c 1 $DIR/$tdir
27119         local lodname=${FSNAME}-MDT0000-mdtlov
27120
27121         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
27122         save_lustre_params mds1 "lod.${lodname}.dom_stripesize_max_kb" > $save
27123         save_lustre_params mds1 "lod.${lodname}.dom_threshold_free_mb" >> $save
27124         stack_trap "restore_lustre_params < $save; rm -f $save" EXIT
27125
27126         local dom_limit=1024
27127         local dom_threshold="50%"
27128
27129         $LFS setstripe -d $DIR/$tdir
27130         $LFS setstripe -E ${dom_limit}K -L mdt $DIR/$tdir ||
27131                 error "Can't set directory default striping"
27132
27133         do_facet mds1 $LCTL set_param -n \
27134                                 lod.${lodname}.dom_stripesize_max_kb=$dom_limit
27135         # set 0 threshold and create DOM file to change tunable stripesize
27136         do_facet mds1 $LCTL set_param -n lod.${lodname}.dom_threshold_free_mb=0
27137         $LFS setstripe -E ${dom_limit}K -L mdt -E -1 $dom ||
27138                 error "Failed to create $dom file"
27139         # now tunable dom_cur_stripesize should reach maximum
27140         local dom_current=$(do_facet mds1 $LCTL get_param -n \
27141                                         lod.${lodname}.dom_stripesize_cur_kb)
27142         [[ $dom_current == $dom_limit ]] ||
27143                 error "Current DOM stripesize is not maximum"
27144         rm $dom
27145
27146         # set threshold for further tests
27147         do_facet mds1 $LCTL set_param -n \
27148                         lod.${lodname}.dom_threshold_free_mb=$dom_threshold
27149         echo "DOM threshold is $dom_threshold free space"
27150         local dom_def
27151         local dom_set
27152         # Spoof bfree to exceed threshold
27153         #define OBD_FAIL_MDS_STATFS_SPOOF   0x168
27154         do_facet mds1 $LCTL set_param -n fail_loc=0x0168
27155         for spfree in 40 20 0 15 30 55; do
27156                 do_facet mds1 $LCTL set_param -n fail_val=$spfree
27157                 $LFS setstripe -E ${dom_limit}K -L mdt -E -1 $dom ||
27158                         error "Failed to create $dom file"
27159                 dom_def=$(do_facet mds1 $LCTL get_param -n \
27160                                         lod.${lodname}.dom_stripesize_cur_kb)
27161                 echo "Free space: ${spfree}%, default DOM stripe: ${dom_def}K"
27162                 [[ $dom_def != $dom_current ]] ||
27163                         error "Default stripe size was not changed"
27164                 if (( spfree > 0 )) ; then
27165                         dom_set=$($LFS getstripe -S $dom)
27166                         (( dom_set == dom_def * 1024 )) ||
27167                                 error "DOM component size is still old"
27168                 else
27169                         [[ $($LFS getstripe -L $dom) != "mdt" ]] ||
27170                                 error "DoM component is set with no free space"
27171                 fi
27172                 rm $dom
27173                 dom_current=$dom_def
27174         done
27175 }
27176 run_test 270g "DoM: default DoM stripe size depends on free space"
27177
27178 test_270h() {
27179         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
27180                 skip "Need MDS version at least 2.13.53"
27181
27182         local mdtname=${FSNAME}-MDT0000-mdtlov
27183         local dom=$DIR/$tdir/$tfile
27184         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
27185
27186         save_lustre_params mds1 "lod.*.dom_stripesize" > $save
27187         stack_trap "restore_lustre_params < $save; rm -f $save" EXIT
27188
27189         $LFS mkdir -i 0 -c 1 $DIR/$tdir
27190         $LFS setstripe -E 1M -c1  -E -1 -c2 ${dom}_1 ||
27191                 error "can't create OST file"
27192         # mirrored file with DOM entry in the second mirror
27193         $LFS mirror extend -N -E 1M -L mdt -E eof -c2 ${dom}_1 ||
27194                 error "can't create mirror with DoM component"
27195
27196         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=0
27197
27198         # DOM component in the middle and has other enries in the same mirror,
27199         # should succeed but lost DoM component
27200         local fid1=$($LFS path2fid ${dom}_1)
27201
27202         $LFS setstripe --copy=$fid1 $dom ||
27203                 error "Can't create file from OST|DOM mirror layout"
27204         # check new file has no DoM layout after all
27205         [[ $($LFS getstripe -L $dom) != "mdt" ]] ||
27206                 error "File has DoM component while DoM is disabled"
27207 }
27208 run_test 270h "DoM: DoM stripe removal when disabled on server"
27209
27210 test_270i() {
27211         (( $MDS1_VERSION >= $(version_code 2.14.54) )) ||
27212                 skip "Need MDS version at least 2.14.54"
27213
27214         mkdir $DIR/$tdir
27215         # DoM with plain layout
27216         $LFS setstripe -L mdt -S 128k -c -1 $DIR/$tdir &&
27217                 error "default plain layout with DoM must fail"
27218         $LFS setstripe -L mdt -S 128k -c -1 $DIR/$tdir/$tfile &&
27219                 error "setstripe plain file layout with DoM must fail"
27220         $LFS setstripe -E 1M -L mdt -S 128k -c -1 -E eof $DIR/$tdir &&
27221                 error "default DoM layout with bad striping must fail"
27222         $LFS setstripe -E 1M -L mdt -S 128k -c -1 -E eof $DIR/$tdir/$tfile &&
27223                 error "setstripe to DoM layout with bad striping must fail"
27224         return 0
27225 }
27226 run_test 270i "DoM: setting invalid DoM striping should fail"
27227
27228 test_270j() {
27229         (( $MDS1_VERSION >= $(version_code 2.15.55.203) )) ||
27230                 skip "Need MDS version at least 2.15.55.203"
27231
27232         local dom=$DIR/$tdir/$tfile
27233         local odv
27234         local ndv
27235
27236         mkdir -p $DIR/$tdir
27237
27238         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
27239         stack_trap "rm -f $dom"
27240
27241         odv=$($LFS data_version $dom)
27242         chmod 666 $dom
27243         mv $dom ${dom}_moved
27244         link ${dom}_moved $dom
27245         setfattr -n user.attrx -v "some_attr" $dom
27246         ndv=$($LFS data_version $dom)
27247         (( $ndv == $odv )) ||
27248                 error "data version was changed by metadata operations"
27249
27250         dd if=/dev/urandom of=$dom bs=1M count=1 ||
27251                 error "failed to write data into $dom"
27252         cancel_lru_locks mdc
27253         ndv=$($LFS data_version $dom)
27254         (( $ndv != $odv )) ||
27255                 error "data version wasn't changed on write"
27256
27257         odv=$ndv
27258         $TRUNCATE $dom 1000 || error "failed to truncate $dom"
27259         ndv=$($LFS data_version $dom)
27260         (( $ndv != $odv )) ||
27261                 error "data version wasn't changed on truncate down"
27262
27263         odv=$ndv
27264         $TRUNCATE $dom 25000
27265         ndv=$($LFS data_version $dom)
27266         (( $ndv != $odv )) ||
27267                 error "data version wasn't changed on truncate up"
27268
27269         # check also fallocate for ldiskfs
27270         if [[ "$mds1_FSTYPE" == ldiskfs ]]; then
27271                 odv=$ndv
27272                 fallocate -l 1048576 $dom
27273                 ndv=$($LFS data_version $dom)
27274                 (( $ndv != $odv )) ||
27275                         error "data version wasn't changed on fallocate"
27276
27277                 odv=$ndv
27278                 fallocate -p --offset 4096 -l 4096 $dom
27279                 ndv=$($LFS data_version $dom)
27280                 (( $ndv != $odv )) ||
27281                         error "data version wasn't changed on fallocate punch"
27282         fi
27283 }
27284 run_test 270j "DoM migration: DOM file to the OST-striped file (plain)"
27285
27286 test_271a() {
27287         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
27288                 skip "Need MDS version at least 2.10.55"
27289
27290         local dom=$DIR/$tdir/dom
27291
27292         mkdir -p $DIR/$tdir
27293
27294         $LFS setstripe -E 1024K -L mdt $dom
27295
27296         lctl set_param -n mdc.*.stats=clear
27297         dd if=/dev/zero of=$dom bs=4096 count=1 || return 1
27298         cat $dom > /dev/null
27299         local reads=$(lctl get_param -n mdc.*.stats | grep -c ost_read)
27300         [ $reads -eq 0 ] || error "Unexpected $reads READ RPCs"
27301         ls $dom
27302         rm -f $dom
27303 }
27304 run_test 271a "DoM: data is cached for read after write"
27305
27306 test_271b() {
27307         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
27308                 skip "Need MDS version at least 2.10.55"
27309
27310         local dom=$DIR/$tdir/dom
27311
27312         mkdir -p $DIR/$tdir
27313
27314         $LFS setstripe -E 1024K -L mdt -E EOF $dom
27315
27316         lctl set_param -n mdc.*.stats=clear
27317         dd if=/dev/zero of=$dom bs=4096 count=1 || return 1
27318         cancel_lru_locks mdc
27319         $CHECKSTAT -t file -s 4096 $dom || error "stat #1 fails"
27320         # second stat to check size is cached on client
27321         $CHECKSTAT -t file -s 4096 $dom || error "stat #2 fails"
27322         local gls=$(lctl get_param -n mdc.*.stats | grep -c ldlm_glimpse)
27323         [ $gls -eq 0 ] || error "Unexpected $gls glimpse RPCs"
27324         rm -f $dom
27325 }
27326 run_test 271b "DoM: no glimpse RPC for stat (DoM only file)"
27327
27328 test_271ba() {
27329         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
27330                 skip "Need MDS version at least 2.10.55"
27331
27332         local dom=$DIR/$tdir/dom
27333
27334         mkdir -p $DIR/$tdir
27335
27336         $LFS setstripe -E 1024K -L mdt -E EOF $dom
27337
27338         lctl set_param -n mdc.*.stats=clear
27339         lctl set_param -n osc.*.stats=clear
27340         # Hybrid switches to DIO, so does not hold the required lock to skip
27341         # the glimpse, so we disable it here...
27342         local hybrid=$($LCTL get_param -n llite.*.hybrid_io)
27343         $LCTL set_param llite.*.hybrid_io=0
27344         stack_trap "$LCTL set_param -n llite.*.hybrid_io=$hybrid" EXIT
27345         dd if=/dev/zero of=$dom bs=2048K count=1 || return 1
27346         cancel_lru_locks mdc
27347         $CHECKSTAT -t file -s 2097152 $dom || error "stat"
27348         # second stat to check size is cached on client
27349         $CHECKSTAT -t file -s 2097152 $dom || error "stat"
27350         local gls=$(lctl get_param -n mdc.*.stats | grep -c ldlm_glimpse)
27351         [ $gls == 0 ] || error "Unexpected $gls glimpse RPCs"
27352         local gls=$(lctl get_param -n osc.*.stats | grep -c ldlm_glimpse)
27353         [ $gls == 0 ] || error "Unexpected $gls OSC glimpse RPCs"
27354         rm -f $dom
27355 }
27356 run_test 271ba "DoM: no glimpse RPC for stat (combined file)"
27357
27358
27359 get_mdc_stats() {
27360         local mdtidx=$1
27361         local param=$2
27362         local mdt=MDT$(printf %04x $mdtidx)
27363
27364         if [ -z $param ]; then
27365                 lctl get_param -n mdc.*$mdt*.stats
27366         else
27367                 lctl get_param -n mdc.*$mdt*.stats | awk "/$param/"'{print $2}'
27368         fi
27369 }
27370
27371 test_271c() {
27372         (( $MDS1_VERSION >= $(version_code v2_10_55_0-74-g2f09984f3f) )) ||
27373                 skip "Need MDS >= 2.10.55.74 for combined DoM lock bits"
27374
27375         local dom=$DIR/$tdir/dom
27376
27377         mkdir -p $DIR/$tdir
27378
27379         $LFS setstripe -E 1024K -L mdt $DIR/$tdir ||
27380                 error "unable to set DoM layout on $DIR/$tdir"
27381
27382         local mdtidx=$($LFS getstripe -m $DIR/$tdir)
27383         local facet=mds$((mdtidx + 1))
27384
27385         cancel_lru_locks mdc
27386         do_facet $facet lctl set_param -n mdt.*.dom_lock=0
27387         createmany -o $dom 1000
27388         lctl set_param -n mdc.*.stats=clear
27389         smalliomany -w $dom 1000 200
27390         get_mdc_stats $mdtidx
27391         local enq=$(get_mdc_stats $mdtidx ldlm_ibits_enqueue)
27392         # Each file has 1 open, 1 IO enqueues, total 2000
27393         # but now we have also +1 getxattr for security.capability, total 3000
27394         [ $enq -ge 2000 ] || error "Too few enqueues $enq, expected > 2000"
27395         unlinkmany $dom 1000
27396
27397         cancel_lru_locks mdc
27398         do_facet $facet lctl set_param -n mdt.*.dom_lock=1
27399         createmany -o $dom 1000
27400         lctl set_param -n mdc.*.stats=clear
27401         smalliomany -w $dom 1000 200
27402         local enq_2=$(get_mdc_stats $mdtidx ldlm_ibits_enqueue)
27403         # Expect to see reduced amount of RPCs by 1000 due to single enqueue
27404         # for OPEN and IO lock.
27405         [ $((enq - enq_2)) -ge 1000 ] ||
27406                 error "Too many enqueues $enq_2, expected about $((enq - 1000))"
27407         unlinkmany $dom 1000
27408         return 0
27409 }
27410 run_test 271c "DoM: IO lock at open saves enqueue RPCs"
27411
27412 cleanup_271def_tests() {
27413         trap 0
27414         rm -f $1
27415 }
27416
27417 test_271d() {
27418         [ $MDS1_VERSION -lt $(version_code 2.10.57) ] &&
27419                 skip "Need MDS version at least 2.10.57"
27420
27421         local dom=$DIR/$tdir/dom
27422         local tmp=$TMP/$tfile
27423         trap "cleanup_271def_tests $tmp" EXIT
27424
27425         mkdir -p $DIR/$tdir
27426
27427         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
27428
27429         local mdtidx=$($LFS getstripe --mdt-index $DIR/$tdir)
27430
27431         cancel_lru_locks mdc
27432         dd if=/dev/urandom of=$tmp bs=1000 count=1
27433         dd if=$tmp of=$dom bs=1000 count=1
27434         cancel_lru_locks mdc
27435
27436         cat /etc/hosts >> $tmp
27437         lctl set_param -n mdc.*.stats=clear
27438
27439         # append data to the same file it should update local page
27440         echo "Append to the same page"
27441         cat /etc/hosts >> $dom
27442         local num=$(get_mdc_stats $mdtidx ost_read)
27443         local ra=$(get_mdc_stats $mdtidx req_active)
27444         local rw=$(get_mdc_stats $mdtidx req_waittime)
27445
27446         [ -z $num ] || error "$num READ RPC occured"
27447         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
27448         echo "... DONE"
27449
27450         # compare content
27451         cmp $tmp $dom || error "file miscompare"
27452
27453         cancel_lru_locks mdc
27454         lctl set_param -n mdc.*.stats=clear
27455
27456         echo "Open and read file"
27457         cat $dom > /dev/null
27458         local num=$(get_mdc_stats $mdtidx ost_read)
27459         local ra=$(get_mdc_stats $mdtidx req_active)
27460         local rw=$(get_mdc_stats $mdtidx req_waittime)
27461
27462         [ -z $num ] || error "$num READ RPC occured"
27463         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
27464         echo "... DONE"
27465
27466         # compare content
27467         cmp $tmp $dom || error "file miscompare"
27468
27469         return 0
27470 }
27471 run_test 271d "DoM: read on open (1K file in reply buffer)"
27472
27473 test_271f() {
27474         [ $MDS1_VERSION -lt $(version_code 2.10.57) ] &&
27475                 skip "Need MDS version at least 2.10.57"
27476
27477         local dom=$DIR/$tdir/dom
27478         local tmp=$TMP/$tfile
27479         trap "cleanup_271def_tests $tmp" EXIT
27480
27481         mkdir -p $DIR/$tdir
27482
27483         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
27484
27485         local mdtidx=$($LFS getstripe --mdt-index $DIR/$tdir)
27486
27487         cancel_lru_locks mdc
27488         dd if=/dev/urandom of=$tmp bs=265000 count=1
27489         dd if=$tmp of=$dom bs=265000 count=1
27490         cancel_lru_locks mdc
27491         cat /etc/hosts >> $tmp
27492         lctl set_param -n mdc.*.stats=clear
27493
27494         echo "Append to the same page"
27495         cat /etc/hosts >> $dom
27496         local num=$(get_mdc_stats $mdtidx ost_read)
27497         local ra=$(get_mdc_stats $mdtidx req_active)
27498         local rw=$(get_mdc_stats $mdtidx req_waittime)
27499
27500         [ -z $num ] || error "$num READ RPC occured"
27501         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
27502         echo "... DONE"
27503
27504         # compare content
27505         cmp $tmp $dom || error "file miscompare"
27506
27507         cancel_lru_locks mdc
27508         lctl set_param -n mdc.*.stats=clear
27509
27510         echo "Open and read file"
27511         cat $dom > /dev/null
27512         local num=$(get_mdc_stats $mdtidx ost_read)
27513         local ra=$(get_mdc_stats $mdtidx req_active)
27514         local rw=$(get_mdc_stats $mdtidx req_waittime)
27515
27516         [ -z $num ] && num=0
27517         [ $num -eq 1 ] || error "expect 1 READ RPC, $num occured"
27518         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
27519         echo "... DONE"
27520
27521         # compare content
27522         cmp $tmp $dom || error "file miscompare"
27523
27524         return 0
27525 }
27526 run_test 271f "DoM: read on open (200K file and read tail)"
27527
27528 test_271g() {
27529         [[ $($LCTL get_param mdc.*.import) =~ async_discard ]] ||
27530                 skip "Skipping due to old client or server version"
27531
27532         $LFS setstripe -E 1024K -L mdt -E EOF $DIR1/$tfile
27533         # to get layout
27534         $CHECKSTAT -t file $DIR1/$tfile
27535
27536         $MULTIOP $DIR1/$tfile Ow40960_w4096c &
27537         MULTIOP_PID=$!
27538         sleep 1
27539         #define OBD_FAIL_LDLM_CANCEL_BL_CB_RACE
27540         $LCTL set_param fail_loc=0x80000314
27541         rm $DIR1/$tfile || error "Unlink fails"
27542         RC=$?
27543         kill -USR1 $MULTIOP_PID && wait $MULTIOP_PID || error "multiop failure"
27544         [ $RC -eq 0 ] || error "Failed write to stale object"
27545 }
27546 run_test 271g "Discard DoM data vs client flush race"
27547
27548 test_272a() {
27549         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
27550                 skip "Need MDS version at least 2.11.50"
27551
27552         local dom=$DIR/$tdir/dom
27553         mkdir -p $DIR/$tdir
27554
27555         $LFS setstripe -E 256K -L mdt -E -1 -c1 $dom
27556         dd if=/dev/urandom of=$dom bs=512K count=1 ||
27557                 error "failed to write data into $dom"
27558         local old_md5=$(md5sum $dom)
27559
27560         $LFS migrate -E 256K -L mdt -E -1 -c2 $dom ||
27561                 error "failed to migrate to the same DoM component"
27562
27563         local new_md5=$(md5sum $dom)
27564
27565         [ "$old_md5" == "$new_md5" ] ||
27566                 error "md5sum differ: $old_md5, $new_md5"
27567
27568         [ $($LFS getstripe -c $dom) -eq 2 ] ||
27569                 error "bad final stripe count: $($LFS getstripe -c $dom) != 2"
27570 }
27571 run_test 272a "DoM migration: new layout with the same DOM component"
27572
27573 test_272b() {
27574         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
27575                 skip "Need MDS version at least 2.11.50"
27576
27577         local dom=$DIR/$tdir/dom
27578         mkdir -p $DIR/$tdir
27579         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
27580         stack_trap "rm -rf $DIR/$tdir"
27581
27582         local mdtidx=$($LFS getstripe -m $dom)
27583         local mdtname=MDT$(printf %04x $mdtidx)
27584         local facet=mds$((mdtidx + 1))
27585
27586         local mdtfree1=$(do_facet $facet \
27587                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27588         dd if=/dev/urandom of=$dom bs=2M count=1 ||
27589                 error "failed to write data into $dom"
27590         local old_md5=$(md5sum $dom)
27591         cancel_lru_locks mdc
27592         local mdtfree1=$(do_facet $facet \
27593                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27594
27595         $LFS migrate -c2 $dom ||
27596                 error "failed to migrate to the new composite layout"
27597         [[ $($LFS getstripe --component-start=0 -L $dom) != 'mdt' ]] ||
27598                 error "MDT stripe was not removed"
27599         ! getfattr -n trusted.dataver $dom &> /dev/null ||
27600                 error "$dir1 shouldn't have DATAVER EA"
27601
27602         cancel_lru_locks mdc
27603         local new_md5=$(md5sum $dom)
27604         [ "$old_md5" == "$new_md5" ] ||
27605                 error "$old_md5 != $new_md5"
27606
27607         # Skip free space checks with ZFS
27608         if [ "$(facet_fstype $facet)" != "zfs" ]; then
27609                 local mdtfree2=$(do_facet $facet \
27610                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27611                 [ $mdtfree2 -gt $mdtfree1 ] ||
27612                         error "MDT space is not freed after migration"
27613         fi
27614         return 0
27615 }
27616 run_test 272b "DoM migration: DOM file to the OST-striped file (plain)"
27617
27618 test_272c() {
27619         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
27620                 skip "Need MDS version at least 2.11.50"
27621
27622         local dom=$DIR/$tdir/$tfile
27623         mkdir -p $DIR/$tdir
27624         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
27625         stack_trap "rm -rf $DIR/$tdir"
27626
27627         local mdtidx=$($LFS getstripe -m $dom)
27628         local mdtname=MDT$(printf %04x $mdtidx)
27629         local facet=mds$((mdtidx + 1))
27630
27631         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
27632                 error "failed to write data into $dom"
27633         local old_md5=$(md5sum $dom)
27634         cancel_lru_locks mdc
27635         local mdtfree1=$(do_facet $facet \
27636                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27637
27638         $LFS migrate -E 2M -c1 -E -1 -c2 $dom ||
27639                 error "failed to migrate to the new composite layout"
27640         [[ $($LFS getstripe --component-start=0 -L $dom) != 'mdt' ]] ||
27641                 error "MDT stripe was not removed"
27642
27643         cancel_lru_locks mdc
27644         local new_md5=$(md5sum $dom)
27645         [ "$old_md5" == "$new_md5" ] ||
27646                 error "$old_md5 != $new_md5"
27647
27648         # Skip free space checks with ZFS
27649         if [ "$(facet_fstype $facet)" != "zfs" ]; then
27650                 local mdtfree2=$(do_facet $facet \
27651                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27652                 [ $mdtfree2 -gt $mdtfree1 ] ||
27653                         error "MDS space is not freed after migration"
27654         fi
27655         return 0
27656 }
27657 run_test 272c "DoM migration: DOM file to the OST-striped file (composite)"
27658
27659 test_272d() {
27660         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
27661                 skip "Need MDS version at least 2.12.55"
27662
27663         local dom=$DIR/$tdir/$tfile
27664         mkdir -p $DIR/$tdir
27665         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
27666         stack_trap "rm -f $dom"
27667
27668         local mdtidx=$($LFS getstripe -m $dom)
27669         local mdtname=MDT$(printf %04x $mdtidx)
27670         local facet=mds$((mdtidx + 1))
27671
27672         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
27673                 error "failed to write data into $dom"
27674         local old_md5=$(md5sum $dom)
27675         cancel_lru_locks mdc
27676         local mdtfree1=$(do_facet $facet \
27677                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27678
27679         $LFS mirror extend -N -E 2M -c1 -E -1 -c2 $dom ||
27680                 error "failed mirroring to the new composite layout"
27681         $LFS mirror resync $dom ||
27682                 error "failed mirror resync"
27683         $LFS mirror split --mirror-id 1 -d $dom ||
27684                 error "failed mirror split"
27685
27686         [ $($LFS getstripe -L $dom) != 'mdt' ] ||
27687                 error "MDT stripe was not removed"
27688
27689         cancel_lru_locks mdc
27690         local new_md5=$(md5sum $dom)
27691         [ "$old_md5" == "$new_md5" ] ||
27692                 error "$old_md5 != $new_md5"
27693
27694         # Skip free space checks with ZFS
27695         if [ "$(facet_fstype $facet)" != "zfs" ]; then
27696                 local mdtfree2=$(do_facet $facet \
27697                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
27698                 [ $mdtfree2 -gt $mdtfree1 ] ||
27699                         error "MDS space is not freed after DOM mirror deletion"
27700         fi
27701         return 0
27702 }
27703 run_test 272d "DoM mirroring: OST-striped mirror to DOM file"
27704
27705 test_272e() {
27706         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
27707                 skip "Need MDS version at least 2.12.55"
27708
27709         local dom=$DIR/$tdir/$tfile
27710         mkdir -p $DIR/$tdir
27711         $LFS setstripe -c 2 $dom
27712         stack_trap "rm -f $dom"
27713
27714         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
27715                 error "failed to write data into $dom"
27716         local old_md5=$(md5sum $dom)
27717         cancel_lru_locks
27718
27719         $LFS mirror extend -N -E 1M -L mdt -E eof -c2 $dom ||
27720                 error "failed mirroring to the DOM layout"
27721         $LFS mirror resync $dom ||
27722                 error "failed mirror resync"
27723         $LFS mirror split --mirror-id 1 -d $dom ||
27724                 error "failed mirror split"
27725
27726         [[ $($LFS getstripe -L --component-start=0 $dom) == 'mdt' ]] ||
27727                 error "MDT stripe wasn't set"
27728
27729         cancel_lru_locks
27730         local new_md5=$(md5sum $dom)
27731         [ "$old_md5" == "$new_md5" ] ||
27732                 error "$old_md5 != $new_md5"
27733
27734         return 0
27735 }
27736 run_test 272e "DoM mirroring: DOM mirror to the OST-striped file"
27737
27738 test_272f() {
27739         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
27740                 skip "Need MDS version at least 2.12.55"
27741
27742         local dom=$DIR/$tdir/$tfile
27743         mkdir -p $DIR/$tdir
27744         $LFS setstripe -c 2 $dom
27745         stack_trap "rm -f $dom"
27746
27747         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
27748                 error "failed to write data into $dom"
27749         local old_md5=$(md5sum $dom)
27750         cancel_lru_locks
27751
27752         $LFS migrate -E 1M -L mdt -E eof -c2 -v $dom ||
27753                 error "failed migrating to the DOM file"
27754
27755         [[ $($LFS getstripe -L --component-start=0 $dom) == 'mdt' ]] ||
27756                 error "MDT stripe wasn't set"
27757
27758         cancel_lru_locks
27759         local new_md5=$(md5sum $dom)
27760         [ "$old_md5" != "$new_md5" ] &&
27761                 error "$old_md5 != $new_md5"
27762
27763         return 0
27764 }
27765 run_test 272f "DoM migration: OST-striped file to DOM file"
27766
27767 test_273a() {
27768         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
27769                 skip "Need MDS version at least 2.11.50"
27770
27771         # Layout swap cannot be done if either file has DOM component,
27772         # this will never be supported, migration should be used instead
27773
27774         local dom=$DIR/$tdir/$tfile
27775         mkdir -p $DIR/$tdir
27776
27777         $LFS setstripe -c2 ${dom}_plain
27778         $LFS setstripe -E 1M -L mdt -E -1 -c2 ${dom}_dom
27779         $LFS swap_layouts ${dom}_plain ${dom}_dom &&
27780                 error "can swap layout with DoM component"
27781         $LFS swap_layouts ${dom}_dom ${dom}_plain &&
27782                 error "can swap layout with DoM component"
27783
27784         $LFS setstripe -E 1M -c1 -E -1 -c2 ${dom}_comp
27785         $LFS swap_layouts ${dom}_comp ${dom}_dom &&
27786                 error "can swap layout with DoM component"
27787         $LFS swap_layouts ${dom}_dom ${dom}_comp &&
27788                 error "can swap layout with DoM component"
27789         return 0
27790 }
27791 run_test 273a "DoM: layout swapping should fail with DOM"
27792
27793 test_273b() {
27794         mkdir -p $DIR/$tdir
27795         $LFS setstripe -E 1M -L mdt -E -1 -c -1 $DIR/$tdir
27796
27797 #define OBD_FAIL_MDS_COMMITRW_DELAY      0x16b
27798         do_facet mds1 $LCTL set_param fail_loc=0x8000016b fail_val=2
27799
27800         $MULTIOP $DIR/$tdir/$tfile Ouw2097152c
27801 }
27802 run_test 273b "DoM: race writeback and object destroy"
27803
27804 test_273c() {
27805         mkdir -p $DIR/$tdir
27806         $LFS setstripe -E 1M -E-1 -c-1 $DIR/$tdir
27807
27808         #define OBD_FAIL_OFD_COMMITRW_DELAY      0x1e1
27809         do_facet ost1 $LCTL set_param fail_loc=0x800001e1 fail_val=2
27810
27811         $MULTIOP $DIR/$tdir/$tfile Ouw2097152c
27812 }
27813 run_test 273c "race writeback and object destroy"
27814
27815 test_275() {
27816         remote_ost_nodsh && skip "remote OST with nodsh"
27817         [ $OST1_VERSION -lt $(version_code 2.10.57) ] &&
27818                 skip "Need OST version >= 2.10.57"
27819
27820         local file=$DIR/$tfile
27821         local osts=$(osts_nodes)
27822
27823         dd if=/dev/urandom of=$file bs=1M count=2 ||
27824                 error "failed to create a file"
27825         stack_trap "rm -f $file"
27826         cancel_lru_locks osc
27827
27828         #lock 1
27829         dd if=$file of=/dev/null bs=1M count=1 iflag=direct ||
27830                 error "failed to read a file"
27831
27832 #define OBD_FAIL_LDLM_PAUSE_CANCEL2      0x31f
27833         $LCTL set_param fail_loc=0x8000031f
27834
27835         cancel_lru_locks osc &
27836         sleep 1
27837
27838 #define OBD_FAIL_LDLM_PROLONG_PAUSE      0x32b
27839         do_nodes $osts $LCTL set_param fail_loc=0x8000032b
27840         #IO takes another lock, but matches the PENDING one
27841         #and places it to the IO RPC
27842         dd if=$file of=/dev/null bs=1M count=1 iflag=direct ||
27843                 error "failed to read a file with PENDING lock"
27844 }
27845 run_test 275 "Read on a canceled duplicate lock"
27846
27847 test_276() {
27848         remote_ost_nodsh && skip "remote OST with nodsh"
27849         local pid
27850
27851         do_facet ost1 "(while true; do \
27852                 $LCTL get_param obdfilter.*.filesfree > /dev/null 2>&1; \
27853                 done) & pid=\\\$!; echo \\\$pid > $TMP/sanity_276_pid" &
27854         pid=$!
27855
27856         for LOOP in $(seq 20); do
27857                 stop ost1
27858                 start ost1 $(ostdevname 1) $OST_MOUNT_OPTS
27859         done
27860         kill -9 $pid
27861         do_facet ost1 "pid=\\\$(cat $TMP/sanity_276_pid); kill -9 \\\$pid; \
27862                 rm $TMP/sanity_276_pid"
27863 }
27864 run_test 276 "Race between mount and obd_statfs"
27865
27866 test_277() {
27867         $LCTL set_param ldlm.namespaces.*.lru_size=0
27868         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
27869         local cached_mb=$($LCTL get_param llite.*.max_cached_mb |
27870                           awk '/^used_mb/ { print $2 }')
27871         [ $cached_mb -eq 1 ] || error "expected mb 1 got $cached_mb"
27872         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 \
27873                 oflag=direct conv=notrunc
27874         stack_trap "rm -f $DIR/$tfile"
27875         cached_mb=$($LCTL get_param llite.*.max_cached_mb |
27876                     awk '/^used_mb/ { print $2 }')
27877         [ $cached_mb -eq 0 ] || error "expected mb 0 got $cached_mb"
27878 }
27879 run_test 277 "Direct IO shall drop page cache"
27880
27881 test_278() {
27882         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
27883         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
27884         [[ "$(facet_host mds1)" != "$(facet_host mds2)" ]] &&
27885                 skip "needs the same host for mdt1 mdt2" && return
27886
27887         local pid1
27888         local pid2
27889
27890 #define OBD_FAIL_OBD_STOP_MDS_RACE     0x60b
27891         do_facet mds2 $LCTL set_param fail_loc=0x8000060c
27892         stop mds2 &
27893         pid2=$!
27894
27895         stop mds1
27896
27897         echo "Starting MDTs"
27898         start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
27899         wait $pid2
27900 #For the error assertion will happen. lu_env_get_key(..., &mdt_thread_key)
27901 #will return NULL
27902         do_facet mds2 $LCTL set_param fail_loc=0
27903
27904         start mds2 $(mdsdevname 2) $MDS_MOUNT_OPTS
27905         wait_recovery_complete mds2
27906 }
27907 run_test 278 "Race starting MDS between MDTs stop/start"
27908
27909 test_280() {
27910         [ $MGS_VERSION -lt $(version_code 2.13.52) ] &&
27911                 skip "Need MGS version at least 2.13.52"
27912         [ $PARALLEL == "yes" ] && skip "skip parallel run"
27913         combined_mgs_mds || skip "needs combined MGS/MDT"
27914
27915         umount_client $MOUNT
27916 #define OBD_FAIL_MDS_LLOG_UMOUNT_RACE   0x15e
27917         do_facet mgs $LCTL set_param fail_loc=0x8000015e fail_val=0
27918
27919         mount_client $MOUNT &
27920         sleep 1
27921         stop mgs || error "stop mgs failed"
27922         #for a race mgs would crash
27923         start mgs $(mgsdevname) $MGS_MOUNT_OPTS || error "start mgs failed"
27924         # make sure we unmount client before remounting
27925         wait
27926         umount_client $MOUNT
27927         mount_client $MOUNT || error "mount client failed"
27928 }
27929 run_test 280 "Race between MGS umount and client llog processing"
27930
27931 cleanup_test_300() {
27932         trap 0
27933         umask $SAVE_UMASK
27934 }
27935
27936 test_striped_dir() {
27937         local mdt_index=$1
27938         local stripe_count=$2
27939         local overstriping=$3
27940         local stripe_index
27941         local getstripe_count
27942
27943         mkdir -p $DIR/$tdir
27944
27945         SAVE_UMASK=$(umask)
27946         trap cleanup_test_300 RETURN EXIT
27947
27948         if [ -z $overstriping ]; then
27949                 $LFS setdirstripe -i $mdt_index -c $stripe_count -H all_char \
27950                                         -o 755 $DIR/$tdir/striped_dir ||
27951                         error "set striped dir error"
27952         else
27953                 $LFS setdirstripe -i $mdt_index -C $stripe_count -H all_char \
27954                                         -o 755 $DIR/$tdir/striped_dir ||
27955                         error "set striped dir error"
27956         fi
27957
27958         local mode=$(stat -c%a $DIR/$tdir/striped_dir)
27959         [ "$mode" = "755" ] || error "expect 755 got $mode"
27960
27961         $LFS getdirstripe $DIR/$tdir/striped_dir > /dev/null 2>&1 ||
27962                 error "getdirstripe failed"
27963         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir)
27964         if [ "$getstripe_count" != "$stripe_count" ]; then
27965                 error "1:stripe_count is $getstripe_count, expect $stripe_count"
27966         fi
27967         getstripe_count=$($LFS getdirstripe -T $DIR/$tdir/striped_dir)
27968         if [ "$getstripe_count" != "$stripe_count" ]; then
27969                 error "2:stripe_count is $getstripe_count, expect $stripe_count"
27970         fi
27971
27972         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir)
27973         if [ "$stripe_index" != "$mdt_index" ]; then
27974                 error "stripe_index is $stripe_index, expect $mdt_index"
27975         fi
27976
27977         [ $(stat -c%h $DIR/$tdir/striped_dir) == '2' ] ||
27978                 error "nlink error after create striped dir"
27979
27980         mkdir $DIR/$tdir/striped_dir/a
27981         mkdir $DIR/$tdir/striped_dir/b
27982
27983         stat $DIR/$tdir/striped_dir/a ||
27984                 error "create dir under striped dir failed"
27985         stat $DIR/$tdir/striped_dir/b ||
27986                 error "create dir under striped dir failed"
27987
27988         [ $(stat -c%h $DIR/$tdir/striped_dir) == '4' ] ||
27989                 error "nlink error after mkdir"
27990
27991         rmdir $DIR/$tdir/striped_dir/a
27992         [ $(stat -c%h $DIR/$tdir/striped_dir) == '3' ] ||
27993                 error "nlink error after rmdir"
27994
27995         rmdir $DIR/$tdir/striped_dir/b
27996         [ $(stat -c%h $DIR/$tdir/striped_dir) == '2' ] ||
27997                 error "nlink error after rmdir"
27998
27999         chattr +i $DIR/$tdir/striped_dir
28000         createmany -o $DIR/$tdir/striped_dir/f 10 &&
28001                 error "immutable flags not working under striped dir!"
28002         chattr -i $DIR/$tdir/striped_dir
28003
28004         rmdir $DIR/$tdir/striped_dir ||
28005                 error "rmdir striped dir error"
28006
28007         cleanup_test_300
28008
28009         true
28010 }
28011
28012 test_300a() {
28013         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
28014                 skip "skipped for lustre < 2.7.0"
28015         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28016         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28017
28018         test_striped_dir 0 2 || error "failed on striped dir on MDT0"
28019         test_striped_dir 1 2 || error "failed on striped dir on MDT0"
28020 }
28021 run_test 300a "basic striped dir sanity test"
28022
28023 test_300b() {
28024         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
28025                 skip "skipped for lustre < 2.7.0"
28026         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28027         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28028
28029         local i
28030         local mtime1
28031         local mtime2
28032         local mtime3
28033
28034         test_mkdir $DIR/$tdir || error "mkdir fail"
28035         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
28036                 error "set striped dir error"
28037         for i in {0..9}; do
28038                 mtime1=$(stat -c %Y $DIR/$tdir/striped_dir)
28039                 sleep 1
28040                 touch $DIR/$tdir/striped_dir/file_$i || error "touch error $i"
28041                 mtime2=$(stat -c %Y $DIR/$tdir/striped_dir)
28042                 [ $mtime1 -eq $mtime2 ] && error "mtime unchanged after create"
28043                 sleep 1
28044                 rm -f $DIR/$tdir/striped_dir/file_$i || error "unlink error $i"
28045                 mtime3=$(stat -c %Y $DIR/$tdir/striped_dir)
28046                 [ $mtime2 -eq $mtime3 ] && error "mtime unchanged after unlink"
28047         done
28048         true
28049 }
28050 run_test 300b "check ctime/mtime for striped dir"
28051
28052 test_300c() {
28053         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
28054                 skip "skipped for lustre < 2.7.0"
28055         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28056         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28057
28058         local file_count
28059
28060         mkdir_on_mdt0 $DIR/$tdir
28061         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir ||
28062                 error "set striped dir error"
28063
28064         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/striped_dir ||
28065                 error "chown striped dir failed"
28066
28067         $RUNAS createmany -o $DIR/$tdir/striped_dir/f 5000 ||
28068                 error "create 5k files failed"
28069
28070         file_count=$(ls $DIR/$tdir/striped_dir | wc -l)
28071
28072         [ "$file_count" = 5000 ] || error "file count $file_count != 5000"
28073
28074         rm -rf $DIR/$tdir
28075 }
28076 run_test 300c "chown && check ls under striped directory"
28077
28078 test_300d() {
28079         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
28080                 skip "skipped for lustre < 2.7.0"
28081         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28082         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28083
28084         local stripe_count
28085         local file
28086
28087         mkdir -p $DIR/$tdir
28088         $LFS setstripe -c 2 $DIR/$tdir
28089
28090         #local striped directory
28091         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
28092                 error "set striped dir error"
28093         #look at the directories for debug purposes
28094         ls -l $DIR/$tdir
28095         $LFS getdirstripe $DIR/$tdir
28096         ls -l $DIR/$tdir/striped_dir
28097         $LFS getdirstripe $DIR/$tdir/striped_dir
28098         createmany -o $DIR/$tdir/striped_dir/f 10 ||
28099                 error "create 10 files failed"
28100
28101         #remote striped directory
28102         $LFS setdirstripe -i 1 -c 2 $DIR/$tdir/remote_striped_dir ||
28103                 error "set striped dir error"
28104         #look at the directories for debug purposes
28105         ls -l $DIR/$tdir
28106         $LFS getdirstripe $DIR/$tdir
28107         ls -l $DIR/$tdir/remote_striped_dir
28108         $LFS getdirstripe $DIR/$tdir/remote_striped_dir
28109         createmany -o $DIR/$tdir/remote_striped_dir/f 10 ||
28110                 error "create 10 files failed"
28111
28112         for file in $(find $DIR/$tdir); do
28113                 stripe_count=$($LFS getstripe -c $file)
28114                 [ $stripe_count -eq 2 ] ||
28115                         error "wrong stripe $stripe_count for $file"
28116         done
28117
28118         rm -rf $DIR/$tdir
28119 }
28120 run_test 300d "check default stripe under striped directory"
28121
28122 test_300e() {
28123         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28124                 skip "Need MDS version at least 2.7.55"
28125         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28126         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28127
28128         local stripe_count
28129         local file
28130
28131         mkdir -p $DIR/$tdir
28132
28133         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
28134                 error "set striped dir error"
28135
28136         touch $DIR/$tdir/striped_dir/a
28137         touch $DIR/$tdir/striped_dir/b
28138         touch $DIR/$tdir/striped_dir/c
28139
28140         mkdir $DIR/$tdir/striped_dir/dir_a
28141         mkdir $DIR/$tdir/striped_dir/dir_b
28142         mkdir $DIR/$tdir/striped_dir/dir_c
28143
28144         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_a ||
28145                 error "set striped adir under striped dir error"
28146
28147         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_b ||
28148                 error "set striped bdir under striped dir error"
28149
28150         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_c ||
28151                 error "set striped cdir under striped dir error"
28152
28153         mrename $DIR/$tdir/striped_dir/dir_a $DIR/$tdir/striped_dir/dir_b ||
28154                 error "rename dir under striped dir fails"
28155
28156         mrename $DIR/$tdir/striped_dir/stp_a $DIR/$tdir/striped_dir/stp_b ||
28157                 error "rename dir under different stripes fails"
28158
28159         mrename $DIR/$tdir/striped_dir/a $DIR/$tdir/striped_dir/c ||
28160                 error "rename file under striped dir should succeed"
28161
28162         mrename $DIR/$tdir/striped_dir/dir_b $DIR/$tdir/striped_dir/dir_c ||
28163                 error "rename dir under striped dir should succeed"
28164
28165         rm -rf $DIR/$tdir
28166 }
28167 run_test 300e "check rename under striped directory"
28168
28169 test_300f() {
28170         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28171         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28172         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28173                 skip "Need MDS version at least 2.7.55"
28174
28175         local stripe_count
28176         local file
28177
28178         rm -rf $DIR/$tdir
28179         mkdir -p $DIR/$tdir
28180
28181         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
28182                 error "set striped dir error"
28183
28184         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir1 ||
28185                 error "set striped dir error"
28186
28187         touch $DIR/$tdir/striped_dir/a
28188         mkdir $DIR/$tdir/striped_dir/dir_a
28189         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir/stp_a ||
28190                 error "create striped dir under striped dir fails"
28191
28192         touch $DIR/$tdir/striped_dir1/b
28193         mkdir $DIR/$tdir/striped_dir1/dir_b
28194         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir/stp_b ||
28195                 error "create striped dir under striped dir fails"
28196
28197         mrename $DIR/$tdir/striped_dir/dir_a $DIR/$tdir/striped_dir1/dir_b ||
28198                 error "rename dir under different striped dir should fail"
28199
28200         mrename $DIR/$tdir/striped_dir/stp_a $DIR/$tdir/striped_dir1/stp_b ||
28201                 error "rename striped dir under diff striped dir should fail"
28202
28203         mrename $DIR/$tdir/striped_dir/a $DIR/$tdir/striped_dir1/a ||
28204                 error "rename file under diff striped dirs fails"
28205
28206         rm -rf $DIR/$tdir
28207 }
28208 run_test 300f "check rename cross striped directory"
28209
28210 test_300_check_default_striped_dir()
28211 {
28212         local dirname=$1
28213         local default_count=$2
28214         local default_index=$3
28215         local stripe_count
28216         local stripe_index
28217         local dir_stripe_index
28218         local dir
28219
28220         echo "checking $dirname $default_count $default_index"
28221         $LFS setdirstripe -D -c $default_count -i $default_index \
28222                                 -H all_char $DIR/$tdir/$dirname ||
28223                 error "set default stripe on striped dir error"
28224         stripe_count=$($LFS getdirstripe -D -c $DIR/$tdir/$dirname)
28225         [ $stripe_count -eq $default_count ] ||
28226                 error "expect $default_count get $stripe_count for $dirname"
28227
28228         stripe_index=$($LFS getdirstripe -D -i $DIR/$tdir/$dirname)
28229         [ $stripe_index -eq $default_index ] ||
28230                 error "expect $default_index get $stripe_index for $dirname"
28231
28232         mkdir $DIR/$tdir/$dirname/{test1,test2,test3,test4} ||
28233                                                 error "create dirs failed"
28234
28235         createmany -o $DIR/$tdir/$dirname/f- 10 || error "create files failed"
28236         unlinkmany $DIR/$tdir/$dirname/f- 10    || error "unlink files failed"
28237         for dir in $(find $DIR/$tdir/$dirname/*); do
28238                 stripe_count=$($LFS getdirstripe -c $dir)
28239                 (( $stripe_count == $default_count )) ||
28240                 (( $stripe_count == $MDSCOUNT && $default_count == -1 )) ||
28241                 (( $stripe_count == 0 )) || (( $default_count == 1 )) ||
28242                 error "stripe count $default_count != $stripe_count for $dir"
28243
28244                 stripe_index=$($LFS getdirstripe -i $dir)
28245                 [ $default_index -eq -1 ] ||
28246                         [ $stripe_index -eq $default_index ] ||
28247                         error "$stripe_index != $default_index for $dir"
28248
28249                 #check default stripe
28250                 stripe_count=$($LFS getdirstripe -D -c $dir)
28251                 [ $stripe_count -eq $default_count ] ||
28252                 error "default count $default_count != $stripe_count for $dir"
28253
28254                 stripe_index=$($LFS getdirstripe -D -i $dir)
28255                 [ $stripe_index -eq $default_index ] ||
28256                 error "default index $default_index != $stripe_index for $dir"
28257         done
28258         rmdir $DIR/$tdir/$dirname/* || error "rmdir failed"
28259 }
28260
28261 test_300g() {
28262         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28263         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28264                 skip "Need MDS version at least 2.7.55"
28265
28266         local dir
28267         local stripe_count
28268         local stripe_index
28269
28270         mkdir_on_mdt0 $DIR/$tdir
28271         mkdir $DIR/$tdir/normal_dir
28272
28273         #Checking when client cache stripe index
28274         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
28275         $LFS setdirstripe -D -i1 $DIR/$tdir/striped_dir ||
28276                 error "create striped_dir failed"
28277
28278         $LFS setdirstripe -i0 $DIR/$tdir/striped_dir/dir0 ||
28279                 error "create dir0 fails"
28280         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/dir0)
28281         [ $stripe_index -eq 0 ] ||
28282                 error "dir0 expect index 0 got $stripe_index"
28283
28284         mkdir $DIR/$tdir/striped_dir/dir1 ||
28285                 error "create dir1 fails"
28286         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/dir1)
28287         [ $stripe_index -eq 1 ] ||
28288                 error "dir1 expect index 1 got $stripe_index"
28289
28290         #check default stripe count/stripe index
28291         test_300_check_default_striped_dir normal_dir $MDSCOUNT 1
28292         test_300_check_default_striped_dir normal_dir 1 0
28293         test_300_check_default_striped_dir normal_dir -1 1
28294         test_300_check_default_striped_dir normal_dir 2 -1
28295
28296         #delete default stripe information
28297         echo "delete default stripeEA"
28298         $LFS setdirstripe -d $DIR/$tdir/normal_dir ||
28299                 error "set default stripe on striped dir error"
28300
28301         mkdir -p $DIR/$tdir/normal_dir/{test1,test2,test3,test4}
28302         for dir in $(find $DIR/$tdir/normal_dir/*); do
28303                 stripe_count=$($LFS getdirstripe -c $dir)
28304                 [ $stripe_count -eq 0 ] ||
28305                         error "expect 1 get $stripe_count for $dir"
28306         done
28307 }
28308 run_test 300g "check default striped directory for normal directory"
28309
28310 test_300h() {
28311         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28312         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28313                 skip "Need MDS version at least 2.7.55"
28314
28315         local dir
28316         local stripe_count
28317
28318         mkdir $DIR/$tdir
28319         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
28320                 error "set striped dir error"
28321
28322         test_300_check_default_striped_dir striped_dir $MDSCOUNT 1
28323         test_300_check_default_striped_dir striped_dir 1 0
28324         test_300_check_default_striped_dir striped_dir -1 1
28325         test_300_check_default_striped_dir striped_dir 2 -1
28326
28327         #delete default stripe information
28328         $LFS setdirstripe -d $DIR/$tdir/striped_dir ||
28329                 error "set default stripe on striped dir error"
28330
28331         mkdir -p $DIR/$tdir/striped_dir/{test1,test2,test3,test4}
28332         for dir in $(find $DIR/$tdir/striped_dir/*); do
28333                 stripe_count=$($LFS getdirstripe -c $dir)
28334                 [ $stripe_count -eq 0 ] ||
28335                         error "expect 1 get $stripe_count for $dir"
28336         done
28337 }
28338 run_test 300h "check default striped directory for striped directory"
28339
28340 test_300i() {
28341         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
28342         (( $MDSCOUNT >= 2 )) || skip_env "needs >= 2 MDTs"
28343         (( $MDS1_VERSION >= $(version_code 2.7.55) )) ||
28344                 skip "Need MDS version at least 2.7.55"
28345
28346         local stripe_count
28347         local file
28348
28349         mkdir $DIR/$tdir
28350
28351         $LFS setdirstripe -i 0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
28352                 error "set striped dir error"
28353
28354         createmany -o $DIR/$tdir/striped_dir/f- 10 ||
28355                 error "create files under striped dir failed"
28356
28357         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir ||
28358                 error "set striped hashdir error"
28359
28360         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir/d0 ||
28361                 error "create dir0 under hash dir failed"
28362         $LFS setdirstripe -i0 -c$MDSCOUNT -H fnv_1a_64 $DIR/$tdir/hashdir/d1 ||
28363                 error "create dir1 under hash dir failed"
28364         $LFS setdirstripe -i0 -c$MDSCOUNT -H crush $DIR/$tdir/hashdir/d2 ||
28365                 error "create dir2 under hash dir failed"
28366
28367         # unfortunately, we need to umount to clear dir layout cache for now
28368         # once we fully implement dir layout, we can drop this
28369         umount_client $MOUNT || error "umount failed"
28370         mount_client $MOUNT || error "mount failed"
28371
28372         $LFS find -H fnv_1a_64,crush $DIR/$tdir/hashdir
28373         local dircnt=$($LFS find -H fnv_1a_64,crush $DIR/$tdir/hashdir | wc -l)
28374         (( $dircnt == 2 )) || error "lfs find striped dir got $dircnt != 2"
28375
28376         if (( $MDS1_VERSION > $(version_code v2_15_50-185-g1ac4b9598a) )); then
28377                 $LFS mkdir -i0 -c$MDSCOUNT -H crush2 $DIR/$tdir/hashdir/d3 ||
28378                         error "create crush2 dir $tdir/hashdir/d3 failed"
28379                 $LFS find -H crush2 $DIR/$tdir/hashdir
28380                 dircnt=$($LFS find -H crush2 $DIR/$tdir/hashdir | wc -l)
28381                 (( $dircnt == 1 )) || error "find crush2 dir got $dircnt != 1"
28382
28383                 # mkdir with an invalid hash type (hash=fail_val) from client
28384                 # should be replaced on MDS with a valid (default) hash type
28385                 #define OBD_FAIL_LMV_UNKNOWN_STRIPE     0x1901
28386                 $LCTL set_param fail_loc=0x1901 fail_val=99
28387                 $LFS mkdir -c2 $DIR/$tdir/hashdir/d99
28388
28389                 local hash=$($LFS getdirstripe -H $DIR/$tdir/hashdir/d99)
28390                 local expect=$(do_facet mds1 \
28391                         $LCTL get_param -n lod.$FSNAME-MDT0000-mdtlov.mdt_hash)
28392                 [[ $hash == $expect ]] ||
28393                         error "d99 hash '$hash' != expected hash '$expect'"
28394         fi
28395
28396         #set the stripe to be unknown hash type on read
28397         #define OBD_FAIL_LMV_UNKNOWN_STRIPE     0x1901
28398         $LCTL set_param fail_loc=0x1901 fail_val=99
28399         for ((i = 0; i < 10; i++)); do
28400                 $CHECKSTAT -t file $DIR/$tdir/striped_dir/f-$i ||
28401                         error "stat f-$i failed"
28402                 rm $DIR/$tdir/striped_dir/f-$i || error "unlink f-$i failed"
28403         done
28404
28405         touch $DIR/$tdir/striped_dir/f0 &&
28406                 error "create under striped dir with unknown hash should fail"
28407
28408         $LCTL set_param fail_loc=0
28409
28410         umount_client $MOUNT || error "umount failed"
28411         mount_client $MOUNT || error "mount failed"
28412
28413         return 0
28414 }
28415 run_test 300i "client handle unknown hash type striped directory"
28416
28417 test_300j() {
28418         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28419         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28420         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28421                 skip "Need MDS version at least 2.7.55"
28422
28423         local stripe_count
28424         local file
28425
28426         mkdir $DIR/$tdir
28427
28428         #define OBD_FAIL_SPLIT_UPDATE_REC       0x1702
28429         $LCTL set_param fail_loc=0x1702
28430         $LFS setdirstripe -i 0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
28431                 error "set striped dir error"
28432
28433         createmany -o $DIR/$tdir/striped_dir/f- 10 ||
28434                 error "create files under striped dir failed"
28435
28436         $LCTL set_param fail_loc=0
28437
28438         rm -rf $DIR/$tdir || error "unlink striped dir fails"
28439
28440         return 0
28441 }
28442 run_test 300j "test large update record"
28443
28444 test_300k() {
28445         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28446         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28447         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28448                 skip "Need MDS version at least 2.7.55"
28449
28450         # this test needs a huge transaction
28451         local kb
28452         kb=$(do_facet $SINGLEMDS "$LCTL get_param -n \
28453              osd*.$FSNAME-MDT0000.kbytestotal")
28454         [ $kb -lt $((1024*1024)) ] && skip "MDT0 too small: $kb"
28455
28456         local stripe_count
28457         local file
28458
28459         mkdir $DIR/$tdir
28460
28461         #define OBD_FAIL_LARGE_STRIPE   0x1703
28462         $LCTL set_param fail_loc=0x1703
28463         $LFS setdirstripe -i 0 -c192 $DIR/$tdir/striped_dir ||
28464                 error "set striped dir error"
28465         $LCTL set_param fail_loc=0
28466
28467         $LFS getdirstripe $DIR/$tdir/striped_dir ||
28468                 error "getstripeddir fails"
28469         rm -rf $DIR/$tdir/striped_dir ||
28470                 error "unlink striped dir fails"
28471
28472         return 0
28473 }
28474 run_test 300k "test large striped directory"
28475
28476 test_300l() {
28477         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28478         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28479         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28480                 skip "Need MDS version at least 2.7.55"
28481
28482         local stripe_index
28483
28484         test_mkdir -p $DIR/$tdir/striped_dir
28485         chown $RUNAS_ID $DIR/$tdir/striped_dir ||
28486                         error "chown $RUNAS_ID failed"
28487         $LFS setdirstripe -i 1 -D $DIR/$tdir/striped_dir ||
28488                 error "set default striped dir failed"
28489
28490         do_facet mds2 $LCTL set_param mdt.*MDT0001.enable_remote_dir_gid=-1
28491         stack_trap "do_facet mds2 $LCTL set_param mdt.*MDT0001.enable_remote_dir_gid=0"
28492         #define OBD_FAIL_MDS_STALE_DIR_LAYOUT    0x158
28493         $LCTL set_param fail_loc=0x80000158
28494         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir || error "create dir fails"
28495
28496         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/test_dir)
28497         [ $stripe_index -eq 1 ] ||
28498                 error "expect 1 get $stripe_index for $dir"
28499 }
28500 run_test 300l "non-root user to create dir under striped dir with stale layout"
28501
28502 test_300m() {
28503         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28504         [ $MDSCOUNT -ge 2 ] && skip_env "Only for single MDT"
28505         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28506                 skip "Need MDS version at least 2.7.55"
28507
28508         mkdir -p $DIR/$tdir/striped_dir
28509         $LFS setdirstripe -D -c 1 $DIR/$tdir/striped_dir ||
28510                 error "set default stripes dir error"
28511
28512         mkdir $DIR/$tdir/striped_dir/a || error "mkdir a fails"
28513
28514         stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir/a)
28515         [ $stripe_count -eq 0 ] ||
28516                         error "expect 0 get $stripe_count for a"
28517
28518         $LFS setdirstripe -D -c 2 $DIR/$tdir/striped_dir ||
28519                 error "set default stripes dir error"
28520
28521         mkdir $DIR/$tdir/striped_dir/b || error "mkdir b fails"
28522
28523         stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir/b)
28524         [ $stripe_count -eq 0 ] ||
28525                         error "expect 0 get $stripe_count for b"
28526
28527         $LFS setdirstripe -D -c1 -i2 $DIR/$tdir/striped_dir ||
28528                 error "set default stripes dir error"
28529
28530         mkdir $DIR/$tdir/striped_dir/c &&
28531                 error "default stripe_index is invalid, mkdir c should fails"
28532
28533         rm -rf $DIR/$tdir || error "rmdir fails"
28534 }
28535 run_test 300m "setstriped directory on single MDT FS"
28536
28537 cleanup_300n() {
28538         local list=$(comma_list $(mdts_nodes))
28539
28540         trap 0
28541         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
28542 }
28543
28544 test_300n() {
28545         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28546         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28547         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28548                 skip "Need MDS version at least 2.7.55"
28549         remote_mds_nodsh && skip "remote MDS with nodsh"
28550
28551         local stripe_index
28552         local list=$(comma_list $(mdts_nodes))
28553
28554         trap cleanup_300n RETURN EXIT
28555         mkdir -p $DIR/$tdir
28556         chmod 777 $DIR/$tdir
28557         $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT \
28558                                 $DIR/$tdir/striped_dir > /dev/null 2>&1 &&
28559                 error "create striped dir succeeds with gid=0"
28560
28561         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1
28562         $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir ||
28563                 error "create striped dir fails with gid=-1"
28564
28565         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
28566         $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D \
28567                                 $DIR/$tdir/striped_dir > /dev/null 2>&1 &&
28568                 error "set default striped dir succeeds with gid=0"
28569
28570
28571         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1
28572         $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D $DIR/$tdir/striped_dir ||
28573                 error "set default striped dir fails with gid=-1"
28574
28575
28576         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
28577         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir ||
28578                                         error "create test_dir fails"
28579         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir1 ||
28580                                         error "create test_dir1 fails"
28581         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir2 ||
28582                                         error "create test_dir2 fails"
28583         cleanup_300n
28584 }
28585 run_test 300n "non-root user to create dir under striped dir with default EA"
28586
28587 test_300o() {
28588         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28589         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28590         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28591                 skip "Need MDS version at least 2.7.55"
28592
28593         local numfree1
28594         local numfree2
28595
28596         mkdir -p $DIR/$tdir
28597
28598         numfree1=$(lctl get_param -n mdc.*MDT0000*.filesfree)
28599         numfree2=$(lctl get_param -n mdc.*MDT0001*.filesfree)
28600         if [ $numfree1 -lt 66000 ] || [ $numfree2 -lt 66000 ]; then
28601                 skip "not enough free inodes $numfree1 $numfree2"
28602         fi
28603
28604         numfree1=$(lctl get_param -n mdc.*MDT0000-mdc-*.kbytesfree)
28605         numfree2=$(lctl get_param -n mdc.*MDT0001-mdc-*.kbytesfree)
28606         if [ $numfree1 -lt 300000 ] || [ $numfree2 -lt 300000 ]; then
28607                 skip "not enough free space $numfree1 $numfree2"
28608         fi
28609
28610         $LFS setdirstripe -c2 $DIR/$tdir/striped_dir ||
28611                 error "setdirstripe fails"
28612
28613         createmany -d $DIR/$tdir/striped_dir/d 131000 ||
28614                 error "create dirs fails"
28615
28616         $LCTL set_param ldlm.namespaces.*mdc-*.lru_size=0
28617         ls $DIR/$tdir/striped_dir > /dev/null ||
28618                 error "ls striped dir fails"
28619         unlinkmany -d $DIR/$tdir/striped_dir/d 131000 ||
28620                 error "unlink big striped dir fails"
28621 }
28622 run_test 300o "unlink big sub stripe(> 65000 subdirs)"
28623
28624 test_300p() {
28625         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28626         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28627         remote_mds_nodsh && skip "remote MDS with nodsh"
28628
28629         mkdir_on_mdt0 $DIR/$tdir
28630
28631         #define OBD_FAIL_OUT_ENOSPC     0x1704
28632         do_facet mds2 lctl set_param fail_loc=0x1704
28633         $LFS setdirstripe -i 0,1 $DIR/$tdir/bad_striped_dir &&
28634                 error "create striped directory should fail"
28635
28636         ! [ -e $DIR/$tdir/bad_striped_dir ] || error "striped dir exists"
28637 }
28638 run_test 300p "create striped directory without space"
28639
28640 test_300q() {
28641         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28642         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28643
28644         local fd=$(free_fd)
28645         local cmd="exec $fd<$tdir"
28646         cd $DIR
28647         $LFS mkdir -c $MDSCOUNT $tdir || error "create $tdir fails"
28648         eval $cmd
28649         cmd="exec $fd<&-"
28650         trap "eval $cmd" EXIT
28651         cd $tdir || error "cd $tdir fails"
28652         rmdir  ../$tdir || error "rmdir $tdir fails"
28653         mkdir local_dir && error "create dir succeeds"
28654         $LFS setdirstripe -i1 remote_dir && error "create remote dir succeeds"
28655         eval $cmd
28656         return 0
28657 }
28658 run_test 300q "create remote directory under orphan directory"
28659
28660 test_300r() {
28661         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28662                 skip "Need MDS version at least 2.7.55" && return
28663         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
28664
28665         mkdir $DIR/$tdir
28666
28667         $LFS setdirstripe -i 0 -c -1 $DIR/$tdir/striped_dir ||
28668                 error "set striped dir error"
28669
28670         $LFS getdirstripe $DIR/$tdir/striped_dir ||
28671                 error "getstripeddir fails"
28672
28673         local stripe_count
28674         stripe_count=$($LFS getdirstripe $DIR/$tdir/striped_dir |
28675                       awk '/lmv_stripe_count:/ { print $2 }')
28676
28677         [ $MDSCOUNT -ne $stripe_count ] &&
28678                 error "wrong stripe count $stripe_count expected $MDSCOUNT"
28679
28680         rm -rf $DIR/$tdir/striped_dir ||
28681                 error "unlink striped dir fails"
28682 }
28683 run_test 300r "test -1 striped directory"
28684
28685 test_300s_helper() {
28686         local count=$1
28687
28688         local stripe_dir=$DIR/$tdir/striped_dir.$count
28689
28690         $LFS mkdir -c $count $stripe_dir ||
28691                 error "lfs mkdir -c error"
28692
28693         $LFS getdirstripe $stripe_dir ||
28694                 error "lfs getdirstripe fails"
28695
28696         local stripe_count
28697         stripe_count=$($LFS getdirstripe $stripe_dir |
28698                       awk '/lmv_stripe_count:/ { print $2 }')
28699
28700         [ $count -ne $stripe_count ] &&
28701                 error_noexit "bad stripe count $stripe_count expected $count"
28702
28703         local dupe_stripes
28704         dupe_stripes=$($LFS getdirstripe $stripe_dir |
28705                 awk '/0x/ {count[$1] += 1}; END {
28706                         for (idx in count) {
28707                                 if (count[idx]>1) {
28708                                         print "index " idx " count " count[idx]
28709                                 }
28710                         }
28711                 }')
28712
28713         if [[ -n "$dupe_stripes" ]] ; then
28714                 lfs getdirstripe $stripe_dir
28715                 error_noexit "Dupe MDT above: $dupe_stripes "
28716         fi
28717
28718         rm -rf $stripe_dir ||
28719                 error_noexit "unlink $stripe_dir fails"
28720 }
28721
28722 test_300s() {
28723         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
28724                 skip "Need MDS version at least 2.7.55" && return
28725         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
28726
28727         mkdir $DIR/$tdir
28728         for count in $(seq 2 $MDSCOUNT); do
28729                 test_300s_helper $count
28730         done
28731 }
28732 run_test 300s "test lfs mkdir -c without -i"
28733
28734 test_300t() {
28735         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
28736                 skip "need MDS 2.14.55 or later"
28737         (( $MDSCOUNT >= 2 )) || skip "needs at least 2 MDTs"
28738
28739         local testdir="$DIR/$tdir/striped_dir"
28740         local dir1=$testdir/dir1
28741         local dir2=$testdir/dir2
28742
28743         mkdir -p $testdir
28744
28745         $LFS setdirstripe -D -c -1 --max-inherit=3 $testdir ||
28746                 error "failed to set default stripe count for $testdir"
28747
28748         mkdir $dir1
28749         local stripe_count=$($LFS getdirstripe -c $dir1)
28750
28751         (( $stripe_count == $MDSCOUNT )) || error "wrong stripe count"
28752
28753         local max_count=$((MDSCOUNT - 1))
28754         local mdts=$(comma_list $(mdts_nodes))
28755
28756         do_nodes $mdts $LCTL set_param lod.*.max_mdt_stripecount=$max_count
28757         stack_trap "do_nodes $mdts $LCTL set_param lod.*.max_mdt_stripecount=0"
28758
28759         mkdir $dir2
28760         stripe_count=$($LFS getdirstripe -c $dir2)
28761
28762         if (( $MDSCOUNT == 2 &&
28763               $MDS1_VERSION >= $(version_code 2.16.0) )); then
28764                 (( $stripe_count == 0 )) || error "(0) wrong stripe count"
28765         else
28766                 (( $stripe_count == $max_count )) ||
28767                         error "(1) wrong stripe count"
28768         fi
28769 }
28770 run_test 300t "test max_mdt_stripecount"
28771
28772 mdts=$(comma_list $(mdts_nodes))
28773 max_stripes_per_mdt=$(do_facet mds1 $LCTL get_param -n \
28774                       lod.$FSNAME-MDT0000-mdtlov.max_stripes_per_mdt || echo 0)
28775 ((max_stripes_per_mdt == 0)) ||
28776         do_nodes $mdts $LCTL set_param -n \
28777         lod.$FSNAME-MDT*.max_stripes_per_mdt=$LMV_MAX_STRIPES_PER_MDT
28778 # 300u family tests MDT overstriping
28779 test_300ua() {
28780         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
28781
28782         local setcount=$((MDSCOUNT * 2))
28783
28784         local expected_count
28785
28786         mkdir $DIR/$tdir
28787         $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.0 ||
28788                 error "(0) failed basic overstriped dir creation test"
28789         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
28790
28791         # This does a basic interop test - if the MDS does not support mdt
28792         # overstriping, we should get stripes == number of MDTs
28793         if (( max_stripes_per_mdt == 0 )); then
28794                 expected_count=$MDSCOUNT
28795         else
28796                 expected_count=$setcount
28797         fi
28798         (( getstripe_count == expected_count )) ||
28799                 error "(1) incorrect stripe count for simple overstriped dir"
28800
28801         rm -rf $DIR/$tdir/${tdir}.0 ||
28802                 error "(2) unable to rm overstriped dir"
28803
28804         # Tests after this require overstriping support
28805         (( max_stripes_per_mdt > 0 )) || return 0
28806
28807         test_striped_dir 0 $setcount true ||
28808                 error "(3)failed on overstriped dir"
28809         test_striped_dir 1 $setcount true ||
28810                 error "(4)failed on overstriped dir"
28811
28812         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
28813
28814         test_striped_dir 0 $setcount true ||
28815                 error "(5)failed on overstriped dir"
28816 }
28817 run_test 300ua "basic overstriped dir sanity test"
28818
28819 test_300ub() {
28820         (( max_stripes_per_mdt > 0 )) ||
28821                 skip "skipped for MDS that doesn't support metadata overstripe"
28822         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
28823
28824         mkdir $DIR/$tdir
28825
28826         echo "Testing invalid stripe count, failure expected"
28827         local setcount=$((MDSCOUNT * 2))
28828
28829         $LFS setdirstripe -c $setcount $DIR/$tdir/${tdir}.0
28830         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
28831
28832         (( getstripe_count <= MDSCOUNT )) ||
28833                 error "(0)stripe count ($setcount) > MDT count ($MDSCOUNT) succeeded with -c"
28834
28835         # When a user requests > LMV_MAX_STRIPES_PER_MDT, we reduce to that
28836         setcount=$((MDSCOUNT * 2 * LMV_MAX_STRIPES_PER_MDT))
28837         $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.1
28838
28839         local maxcount=$((MDSCOUNT * LMV_MAX_STRIPES_PER_MDT))
28840
28841         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
28842         (( getstripe_count == maxcount )) ||
28843                 error "(1)stripe_count is $getstripe_count, expect $maxcount"
28844
28845         # Test specific striping with -i
28846         $LFS setdirstripe -i 0,0,0,0 $DIR/$tdir/${tdir}.2
28847
28848         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.2)
28849         (( getstripe_count == 4 )) ||
28850                 error "(2)stripe_count is $getstripe_count, expect 4"
28851
28852         local nonzeroindices=$($LFS getdirstripe $DIR/$tdir/${tdir}.2 | grep "\[" | \
28853                                grep -v mdtidx | awk '{print $1}' | grep -c -v 0)
28854
28855         [[ -n "$nonzeroindices" ]] ||
28856                 error "(3) stripes indices not all 0: $nonzeroindices"
28857
28858         # Test specific striping with too many stripes on one MDT
28859         echo "Testing invalid striping, failure expected"
28860         $LFS setdirstripe -i 0,1,0,1,0,1,0,1,0,1,0 $DIR/$tdir/${tdir}.3
28861         $LFS getdirstripe $DIR/$tdir/${tdir}.3
28862         getstripe_count=$($LFS getdirstripe $DIR/$tdir/${tdir}.3 | grep "\[" | \
28863                           grep -v mdtidx | awk '{print $1}' | grep -c '0')
28864         echo "stripes on MDT0: $getstripe_count"
28865         (( getstripe_count <= LMV_MAX_STRIPES_PER_MDT )) ||
28866                 error "(4) setstripe with too many stripes on MDT0 succeeded"
28867
28868         setcount=$((MDSCOUNT * 2))
28869         $LFS setdirstripe -C $setcount -H all_char $DIR/${tdir}.4 ||
28870                 error "(5) can't setdirstripe with manually set hash function"
28871
28872         getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.4)
28873         (( getstripe_count == setcount )) ||
28874                 error "(6)stripe_count is $getstripe_count, expect $setcount"
28875
28876         setcount=$((MDSCOUNT * 2))
28877         mkdir $DIR/${tdir}.5
28878         $LFS setdirstripe -C $setcount -D -H crush $DIR/${tdir}.5 ||
28879                 error "(7) can't setdirstripe with manually set hash function"
28880         mkdir $DIR/${tdir}.5/${tdir}.6
28881
28882         getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.5/${tdir}.6)
28883         (( getstripe_count == setcount )) ||
28884                 error "(8)stripe_count is $getstripe_count, expect $setcount"
28885 }
28886 run_test 300ub "test MDT overstriping interface & limits"
28887
28888 test_300uc() {
28889         (( max_stripes_per_mdt > 0 )) ||
28890                 skip "skipped for MDS that doesn't support metadata overstripe"
28891         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
28892
28893         mkdir $DIR/$tdir
28894
28895         local setcount=$((MDSCOUNT * 2))
28896
28897         $LFS setdirstripe -D -C $setcount $DIR/$tdir
28898
28899         mkdir $DIR/$tdir/${tdir}.1
28900
28901         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
28902
28903         (( getstripe_count == setcount )) ||
28904                 error "(0)stripe_count is $getstripe_count, expect $setcount"
28905
28906         mkdir $DIR/$tdir/${tdir}.1/${tdir}.2
28907
28908         local getstripe_count=$($LFS getdirstripe -c \
28909                                 $DIR/$tdir/${tdir}.1/${tdir}.2)
28910
28911         (( getstripe_count == setcount )) ||
28912                 error "(1)stripe_count is $getstripe_count, expect $setcount"
28913 }
28914 run_test 300uc "test MDT overstriping as default & inheritance"
28915
28916 test_300ud() {
28917         (( max_stripes_per_mdt > 0 )) ||
28918                 skip "skipped for MDS that doesn't support metadata overstripe"
28919         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
28920
28921         local mdts=$(comma_list $(mdts_nodes))
28922         local timeout=100
28923
28924         local restripe_status
28925         local delta
28926         local i
28927
28928         [[ $mds1_FSTYPE == zfs ]] && timeout=300
28929
28930         # in case "crush" hash type is not set
28931         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
28932
28933         restripe_status=$(do_facet mds1 $LCTL get_param -n \
28934                            mdt.*MDT0000.enable_dir_restripe)
28935         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
28936         stack_trap "do_nodes $mdts $LCTL set_param \
28937                     mdt.*.enable_dir_restripe=$restripe_status"
28938
28939         mkdir $DIR/$tdir
28940         createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
28941                 error "create files under remote dir failed $i"
28942         createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
28943                 error "create dirs under remote dir failed $i"
28944
28945         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
28946
28947         (( setcount < 13 )) || setcount=12
28948         for i in $(seq 2 $setcount); do
28949                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
28950                 $LFS setdirstripe -C $i $DIR/$tdir ||
28951                         error "split -C $i $tdir failed"
28952                 wait_update $HOSTNAME \
28953                         "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
28954                         error "dir split not finished"
28955                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
28956                         awk '/migrate/ {sum += $2} END { print sum }')
28957                 echo "$delta migrated when dir split $((i - 1)) to $i stripes"
28958                 # delta is around total_files/stripe_count, deviation 3%
28959                 (( delta < 100 * MDSCOUNT / i + 3 * MDSCOUNT )) ||
28960                         error "$delta files migrated >= $((100 * MDSCOUNT / i + 3 * MDSCOUNT))"
28961         done
28962 }
28963 run_test 300ud "dir split"
28964
28965 test_300ue() {
28966         (( max_stripes_per_mdt > 0 )) ||
28967                 skip "skipped for MDS that doesn't support metadata overstripe"
28968         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
28969
28970         local mdts=$(comma_list $(mdts_nodes))
28971         local timeout=100
28972
28973         local restripe_status
28974         local delta
28975         local c
28976
28977         [[ $mds1_FSTYPE == zfs ]] && timeout=300
28978
28979         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
28980
28981         restripe_status=$(do_facet mds1 $LCTL get_param -n \
28982                            mdt.*MDT0000.enable_dir_restripe)
28983         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
28984         stack_trap "do_nodes $mdts $LCTL set_param \
28985                     mdt.*.enable_dir_restripe=$restripe_status"
28986
28987         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
28988
28989         (( setcount < 13 )) || setcount=12
28990         test_mkdir -C $setcount -H crush $DIR/$tdir
28991         createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
28992                 error "create files under remote dir failed"
28993         createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
28994                 error "create dirs under remote dir failed"
28995
28996         for c in $(seq $((setcount - 1)) -1 1); do
28997                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
28998                 $LFS setdirstripe -C $c $DIR/$tdir ||
28999                         error "split -C $c $tdir failed"
29000                 wait_update $HOSTNAME \
29001                         "$LFS getdirstripe -H $DIR/$tdir" "crush,fixed" $timeout ||
29002                         error "dir merge not finished"
29003                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
29004                         awk '/migrate/ {sum += $2} END { print sum }')
29005                 echo "$delta migrated when dir merge $((c + 1)) to $c stripes"
29006                 # delta is around total_files/stripe_count, deviation 3%
29007                 (( delta < 100 * MDSCOUNT / c + 3 * MDSCOUNT )) ||
29008                         error "$delta files migrated >= $((100 * MDSCOUNT / c + 3 * MDSCOUNT))"
29009         done
29010 }
29011 run_test 300ue "dir merge"
29012
29013 test_300uf() {
29014         (( max_stripes_per_mdt > 0 )) ||
29015                 skip "skipped for MDS that doesn't support metadata overstripe"
29016         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
29017
29018         # maximum amount of local locks:
29019         # parent striped dir - 2 locks
29020         # new stripe in parent to migrate to - 1 lock
29021         # source and target - 2 locks
29022         # Total 5 locks for regular file
29023         #
29024         # NB: Overstriping should add several extra local locks
29025         # FIXME: Remove this once understood
29026         #lctl set_param *debug=-1 debug_mb=10000
29027         lctl clear
29028         lctl mark "touch/create"
29029         mkdir -p $DIR/$tdir
29030         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
29031         local setcount=$((MDSCOUNT * 5))
29032
29033         $LFS mkdir -i1 -C $setcount $DIR/$tdir/dir1
29034         touch $DIR/$tdir/dir1/eee
29035
29036         lctl mark "hardlinks"
29037         # create 4 hardlink for 4 more locks
29038         # Total: 9 locks > RS_MAX_LOCKS (8)
29039         $LFS mkdir -i1 -c1 $DIR/$tdir/dir2
29040         $LFS mkdir -i1 -c1 $DIR/$tdir/dir3
29041         $LFS mkdir -i1 -c1 $DIR/$tdir/dir4
29042         $LFS mkdir -i1 -c1 $DIR/$tdir/dir5
29043         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir2/eee
29044         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir3/eee
29045         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir4/eee
29046         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir5/eee
29047
29048         lctl mark "cancel lru"
29049         cancel_lru_locks mdc
29050
29051         lctl mark "migrate"
29052         $LFS migrate -m1 -c1 $DIR/$tdir/dir1 ||
29053                 error "migrate dir fails"
29054
29055         rm -rf $DIR/$tdir || error "rm dir failed after migration"
29056 }
29057 run_test 300uf "migrate with too many local locks"
29058
29059 test_300ug() {
29060         (( max_stripes_per_mdt > 0 )) ||
29061                 skip "skipped for MDS that doesn't support metadata overstripe"
29062         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
29063
29064         mkdir -p $DIR/$tdir
29065         local migrate_dir=$DIR/$tdir/migrate_dir
29066         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
29067         local setcount2=$((setcount - 2))
29068
29069         $LFS setdirstripe -c 2 $migrate_dir ||
29070                 error "(0) failed to create striped directory"
29071
29072         $LFS migrate -m 0 -C $setcount $migrate_dir ||
29073                 error "(1)failed to migrate to overstriped directory"
29074         local getstripe_count=$($LFS getdirstripe -c $migrate_dir)
29075
29076         (( getstripe_count == setcount )) ||
29077                 error "(2)stripe_count is $getstripe_count, expect $setcount"
29078         touch $DIR/$tdir/migrate_dir/$tfile ||
29079                 error "(3)failed to create file in overstriped directory"
29080         $LFS migrate -m 0 -C $setcount2 $migrate_dir ||
29081                 error "(4)failed to migrate overstriped directory"
29082         # Check stripe count after migration
29083         $LFS getdirstripe $migrate_dir
29084         getstripe_count=$($LFS getdirstripe -c $migrate_dir)
29085         (( getstripe_count == setcount2 )) ||
29086                 error "(5)stripe_count is $getstripe_count, expect $setcount2"
29087
29088         rm -rf $migrate_dir || error "(6) unable to rm overstriped dir"
29089 }
29090 run_test 300ug "migrate overstriped dirs"
29091
29092 test_300uh() {
29093         (( max_stripes_per_mdt > 0 )) ||
29094                 skip "skipped for MDS that doesn't support metadata overstripe"
29095         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
29096
29097         local mdts=$(comma_list $(mdts_nodes))
29098         local val=$(do_facet mds1 $LCTL get_param -n \
29099                     lod.$FSNAME-MDT0000-mdtlov.max_stripes_per_mdt)
29100
29101         stack_trap "do_nodes $mdts $LCTL set_param -n \
29102                     lod.$FSNAME-MDT*.max_stripes_per_mdt=$val"
29103
29104         # create 5 stripes will be silently clamped down
29105         do_nodes $mdts $LCTL set_param -n \
29106                 lod.$FSNAME-MDT*.max_stripes_per_mdt=2
29107         $LFS setdirstripe -C $((MDSCOUNT * 5)) $DIR/$tdir ||
29108                 error "mkdir $tdir failed"
29109         $LFS getdirstripe -H $DIR/$tdir | grep overstriped ||
29110                 error "overstriped flag not found"
29111
29112         local count=$($LFS getdirstripe -c $DIR/$tdir)
29113
29114         ((count == 2 * MDSCOUNT)) || error "count $count != $((2 * MDSCOUNT))"
29115
29116         # create 3 stripes on MDT0 should fail
29117         $LFS setdirstripe -i 0,0,0 $DIR/$tdir/sub && error "mkdir sub succeeded"
29118
29119         # OVERSTRIPED flag will be cleared if not really overstriped
29120         $LFS setdirstripe -C $MDSCOUNT $DIR/$tdir/sub ||
29121                 error "mkdir sub failed"
29122         $LFS getdirstripe -H $DIR/$tdir/sub | grep -v overstriped ||
29123                 error "overstriped flag found"
29124 }
29125 run_test 300uh "overstripe tunable max_stripes_per_mdt"
29126
29127 test_300ui() {
29128         (( max_stripes_per_mdt > 0 )) ||
29129                 skip "skipped for MDS that doesn't support metadata overstripe"
29130         (( MDSCOUNT == 1 )) || skip "1 MDT only"
29131
29132         $LFS setdirstripe -C 2 $DIR/$tdir && error "mkdir $tdir succeeded" ||
29133                 true
29134 }
29135 run_test 300ui "overstripe is not supported on one MDT system"
29136
29137 test_300uj() {
29138         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
29139         (( MDS1_VERSION >= $(version_code 2.16.0) )) ||
29140                 skip "need MDS >= 2.16.0 for llog timestamps"
29141
29142         local setcount=-2
29143         local expected_count=$((MDSCOUNT * 2))
29144
29145         mkdir $DIR/$tdir
29146         $LFS mkdir -C $setcount $DIR/$tdir/${tdir}.0 ||
29147                 error "(0) failed overstriped dir creation with -C -N test"
29148         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
29149         (( getstripe_count == expected_count )) ||
29150                 error "(1) incorrect stripe count for -C -N overstriped dir"
29151         rm -f $DIR/$tdir/${tdir}.0
29152
29153         # limit testing
29154         setcount=-6
29155         $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.1 2>&1 |
29156                 grep "invalid stripe count" ||
29157                 error "(0) failed overstriped dir creation limit test"
29158 }
29159 run_test 300uj "overstriped dir with -C -N sanity test"
29160
29161 (( max_stripes_per_mdt == 0 )) ||
29162         do_nodes $mdts $LCTL set_param -n \
29163                 lod.$FSNAME-MDT*.max_stripes_per_mdt=$max_stripes_per_mdt
29164
29165 prepare_remote_file() {
29166         mkdir $DIR/$tdir/src_dir ||
29167                 error "create remote source failed"
29168
29169         cp /etc/hosts $DIR/$tdir/src_dir/a ||
29170                  error "cp to remote source failed"
29171         touch $DIR/$tdir/src_dir/a
29172
29173         $LFS mkdir -i 1 $DIR/$tdir/tgt_dir ||
29174                 error "create remote target dir failed"
29175
29176         touch $DIR/$tdir/tgt_dir/b
29177
29178         mrename $DIR/$tdir/src_dir/a $DIR/$tdir/tgt_dir/b ||
29179                 error "rename dir cross MDT failed!"
29180
29181         $CHECKSTAT -t file $DIR/$tdir/src_dir/a &&
29182                 error "src_child still exists after rename"
29183
29184         $CHECKSTAT -t file $DIR/$tdir/tgt_dir/b ||
29185                 error "missing file(a) after rename"
29186
29187         diff /etc/hosts $DIR/$tdir/tgt_dir/b ||
29188                 error "diff after rename"
29189 }
29190
29191 test_310a() {
29192         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 4 MDTs"
29193         [ $PARALLEL == "yes" ] && skip "skip parallel run"
29194
29195         local remote_file=$DIR/$tdir/tgt_dir/b
29196
29197         mkdir -p $DIR/$tdir
29198
29199         prepare_remote_file || error "prepare remote file failed"
29200
29201         #open-unlink file
29202         $OPENUNLINK $remote_file $remote_file ||
29203                 error "openunlink $remote_file failed"
29204         $CHECKSTAT -a $remote_file || error "$remote_file exists"
29205 }
29206 run_test 310a "open unlink remote file"
29207
29208 test_310b() {
29209         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 4 MDTs"
29210         [ $PARALLEL == "yes" ] && skip "skip parallel run"
29211
29212         local remote_file=$DIR/$tdir/tgt_dir/b
29213
29214         mkdir -p $DIR/$tdir
29215
29216         prepare_remote_file || error "prepare remote file failed"
29217
29218         ln $remote_file $DIR/$tfile || error "link failed for remote file"
29219         $MULTIOP $DIR/$tfile Ouc || error "mulitop failed"
29220         $CHECKSTAT -t file $remote_file || error "check file failed"
29221 }
29222 run_test 310b "unlink remote file with multiple links while open"
29223
29224 test_310c() {
29225         [ $PARALLEL == "yes" ] && skip "skip parallel run"
29226         [[ $MDSCOUNT -lt 4 ]] && skip_env "needs >= 4 MDTs"
29227
29228         local remote_file=$DIR/$tdir/tgt_dir/b
29229
29230         mkdir -p $DIR/$tdir
29231
29232         prepare_remote_file || error "prepare remote file failed"
29233
29234         ln $remote_file $DIR/$tfile || error "link failed for remote file"
29235         multiop_bg_pause $remote_file O_uc ||
29236                         error "mulitop failed for remote file"
29237         MULTIPID=$!
29238         $MULTIOP $DIR/$tfile Ouc
29239         kill -USR1 $MULTIPID
29240         wait $MULTIPID
29241 }
29242 run_test 310c "open-unlink remote file with multiple links"
29243
29244 #LU-4825
29245 test_311() {
29246         [ $PARALLEL == "yes" ] && skip "skip parallel run"
29247         [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"
29248         [ $MDS1_VERSION -lt $(version_code 2.8.54) ] &&
29249                 skip "lustre < 2.8.54 does not contain LU-4825 fix"
29250         remote_mds_nodsh && skip "remote MDS with nodsh"
29251
29252         local old_iused=$($LFS df -i | awk '/OST0000/ { print $3; exit; }')
29253         echo "old_iused=$old_iused"
29254         local mdts=$(comma_list $(mdts_nodes))
29255
29256         mkdir -p $DIR/$tdir
29257         $LFS setstripe -i 0 -c 1 $DIR/$tdir
29258         createmany -o $DIR/$tdir/$tfile. 1000
29259
29260         # statfs data is not real time, let's just calculate it
29261         old_iused=$((old_iused + 1000))
29262         echo "suppose current old_iused=$old_iused"
29263
29264         local count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
29265                         osp.*OST0000*MDT0000.create_count")
29266         local max_count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
29267                                 osp.*OST0000*MDT0000.max_create_count")
29268         echo "create_count=$count, max_create_count=$max_count"
29269         do_nodes $mdts "$LCTL set_param -n osp.*OST0000*.max_create_count=0"
29270
29271         $LFS setstripe -i 0 $DIR/$tdir/$tfile || error "setstripe failed"
29272         local index=$($LFS getstripe -i $DIR/$tdir/$tfile)
29273         [ $index -ne 0 ] || error "$tfile stripe index is 0"
29274
29275         unlinkmany $DIR/$tdir/$tfile. 1000
29276         wait_delete_completed
29277         wait_zfs_commit $SINGLEMDS 10
29278
29279         do_nodes $mdts "$LCTL set_param -n \
29280                         osp.*OST0000*.max_create_count=$max_count"
29281         [ $MDS1_VERSION -lt $(version_code 2.12.51) ] &&
29282                 do_nodes $mdts "$LCTL set_param -n \
29283                                 osp.*OST0000*.create_count=$count"
29284         do_nodes $mdts "$LCTL get_param osp.*OST0000*.create_count" |
29285                         grep "=0" && error "create_count is zero"
29286
29287         local new_iused
29288         for i in $(seq 120); do
29289                 new_iused=$($LFS df -i | awk '/OST0000/ { print $3; exit; }')
29290                 echo -n "$new_iused "
29291                 # system may be too busy to destroy all objs in time, use
29292                 # a somewhat small value to not fail autotest
29293                 ((old_iused - new_iused > 400)) && break
29294                 sleep 1
29295         done
29296
29297         echo -e "\nwaited $i sec, old Iused $old_iused, new Iused $new_iused"
29298         ((old_iused - new_iused > 400)) ||
29299                 error "objs not destroyed after unlink"
29300 }
29301 run_test 311 "disable OSP precreate, and unlink should destroy objs"
29302
29303 zfs_get_objid()
29304 {
29305         local ost=$1
29306         local tf=$2
29307         local fid=($($LFS getstripe $tf | grep 0x))
29308         local seq=${fid[3]#0x}
29309         local objid=${fid[1]}
29310
29311         local vdevdir=$(dirname $(facet_vdevice $ost))
29312         local cmd="$ZDB -e -p $vdevdir -ddddd $(facet_device $ost)"
29313         local zfs_zapid=$(do_facet $ost $cmd |
29314                           grep -w "/O/$seq/d$((objid%32))" -C 5 |
29315                           awk '/Object/{getline; print $1}')
29316         local zfs_objid=$(do_facet $ost $cmd $zfs_zapid |
29317                           awk "/$objid = /"'{printf $3}')
29318
29319         echo $zfs_objid
29320 }
29321
29322 zfs_object_blksz() {
29323         local ost=$1
29324         local objid=$2
29325
29326         local vdevdir=$(dirname $(facet_vdevice $ost))
29327         local cmd="$ZDB -e -p $vdevdir -dddd $(facet_device $ost)"
29328         local blksz=$(do_facet $ost $cmd $objid |
29329                       awk '/dblk/{getline; printf $4}')
29330
29331         case "${blksz: -1}" in
29332                 k|K) blksz=$((${blksz:0:$((${#blksz} - 1))}*1024)) ;;
29333                 m|M) blksz=$((${blksz:0:$((${#blksz} - 1))}*1024*1024)) ;;
29334                 *) ;;
29335         esac
29336
29337         echo $blksz
29338 }
29339
29340 test_312() { # LU-4856
29341         remote_ost_nodsh && skip "remote OST with nodsh"
29342         [[ "$ost1_FSTYPE" == "zfs" ]] || skip "the test only applies to zfs"
29343
29344         local max_blksz=$(do_facet ost1 \
29345                           $ZFS get -p recordsize $(facet_device ost1) |
29346                           awk '!/VALUE/{print $3}')
29347         local tf=$DIR/$tfile
29348
29349         $LFS setstripe -c1 $tf
29350         local facet="ost$(($($LFS getstripe -i $tf) + 1))"
29351
29352         # Get ZFS object id
29353         local zfs_objid=$(zfs_get_objid $facet $tf)
29354         # block size change by sequential overwrite
29355         local bs
29356
29357         for ((bs=$PAGE_SIZE; bs <= max_blksz; bs *= 4)) ; do
29358                 dd if=/dev/zero of=$tf bs=$bs count=1 oflag=sync conv=notrunc
29359
29360                 local blksz=$(zfs_object_blksz $facet $zfs_objid)
29361                 [[ $blksz -eq $bs ]] || error "blksz error: $blksz, expected: $bs"
29362         done
29363         rm -f $tf
29364
29365         $LFS setstripe -c1 $tf
29366         facet="ost$(($($LFS getstripe -i $tf) + 1))"
29367
29368         # block size change by sequential append write
29369         dd if=/dev/zero of=$tf bs=$PAGE_SIZE count=1 oflag=sync conv=notrunc
29370         zfs_objid=$(zfs_get_objid $facet $tf)
29371         local count
29372
29373         for ((count = 1; count < $((max_blksz / PAGE_SIZE)); count *= 2)); do
29374                 dd if=/dev/zero of=$tf bs=$PAGE_SIZE count=$count seek=$count \
29375                         oflag=sync conv=notrunc
29376
29377                 blksz=$(zfs_object_blksz $facet $zfs_objid)
29378                 (( $blksz == 2 * count * PAGE_SIZE )) ||
29379                         error "blksz error, actual $blksz, " \
29380                                 "expected: 2 * $count * $PAGE_SIZE"
29381         done
29382         rm -f $tf
29383
29384         # random write
29385         $LFS setstripe -c1 $tf
29386         facet="ost$(($($LFS getstripe -i $tf) + 1))"
29387         zfs_objid=$(zfs_get_objid $facet $tf)
29388
29389         dd if=/dev/zero of=$tf bs=1K count=1 oflag=sync conv=notrunc
29390         blksz=$(zfs_object_blksz $facet $zfs_objid)
29391         (( blksz == PAGE_SIZE )) ||
29392                 error "blksz error: $blksz, expected: $PAGE_SIZE"
29393
29394         dd if=/dev/zero of=$tf bs=64K count=1 oflag=sync conv=notrunc seek=128
29395         blksz=$(zfs_object_blksz $facet $zfs_objid)
29396         (( blksz == 65536 )) || error "blksz error: $blksz, expected: 64k"
29397
29398         dd if=/dev/zero of=$tf bs=1M count=1 oflag=sync conv=notrunc
29399         blksz=$(zfs_object_blksz $facet $zfs_objid)
29400         (( blksz == 65536 )) || error "rewrite error: $blksz, expected: 64k"
29401 }
29402 run_test 312 "make sure ZFS adjusts its block size by write pattern"
29403
29404 test_313() {
29405         remote_ost_nodsh && skip "remote OST with nodsh"
29406
29407         local file=$DIR/$tfile
29408
29409         rm -f $file
29410         $LFS setstripe -c 1 -i 0 $file || error "setstripe failed"
29411
29412         # define OBD_FAIL_TGT_RCVD_EIO           0x720
29413         do_facet ost1 "$LCTL set_param fail_loc=0x720"
29414         dd if=/dev/zero of=$file bs=$PAGE_SIZE oflag=direct count=1 &&
29415                 error "write should failed"
29416         do_facet ost1 "$LCTL set_param fail_loc=0"
29417         rm -f $file
29418 }
29419 run_test 313 "io should fail after last_rcvd update fail"
29420
29421 test_314() {
29422         [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"
29423
29424         $LFS setstripe -c 2 -i 0 $DIR/$tfile || error "setstripe failed"
29425         do_facet ost1 "$LCTL set_param fail_loc=0x720"
29426         rm -f $DIR/$tfile
29427         wait_delete_completed
29428         do_facet ost1 "$LCTL set_param fail_loc=0"
29429 }
29430 run_test 314 "OSP shouldn't fail after last_rcvd update failure"
29431
29432 test_315() { # LU-618
29433         [ -f /proc/$$/io ] || skip_env "no IO accounting in kernel"
29434
29435         local file=$DIR/$tfile
29436         rm -f $file
29437
29438         $MULTIOP $file oO_CREAT:O_DIRECT:O_RDWR:w4063232c ||
29439                 error "multiop file write failed"
29440         $MULTIOP $file oO_RDONLY:r4063232_c &
29441         PID=$!
29442
29443         sleep 2
29444
29445         local rbytes=$(awk '/read_bytes/ { print $2 }' /proc/$PID/io)
29446         kill -USR1 $PID
29447
29448         [ $rbytes -gt 4000000 ] || error "read is not accounted ($rbytes)"
29449         rm -f $file
29450 }
29451 run_test 315 "read should be accounted"
29452
29453 test_316() {
29454         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
29455         large_xattr_enabled || skip "ea_inode feature disabled"
29456
29457         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
29458         mkdir $DIR/$tdir/d || error "mkdir $tdir/d failed"
29459         chown nobody $DIR/$tdir/d || error "chown $tdir/d failed"
29460         touch $DIR/$tdir/d/$tfile || error "touch $tdir/d/$tfile failed"
29461
29462         $LFS migrate -m1 $DIR/$tdir/d || error "lfs migrate -m1 failed"
29463 }
29464 run_test 316 "lfs migrate of file with large_xattr enabled"
29465
29466 test_317() {
29467         [ $MDS1_VERSION -lt $(version_code 2.11.53) ] &&
29468                 skip "Need MDS version at least 2.11.53"
29469         if [ "$ost1_FSTYPE" == "zfs" ]; then
29470                 skip "LU-10370: no implementation for ZFS"
29471         fi
29472
29473         local trunc_sz
29474         local grant_blk_size
29475
29476         grant_blk_size=$($LCTL get_param osc.$FSNAME*.import |
29477                         awk '/grant_block_size:/ { print $2; exit; }')
29478         #
29479         # Create File of size 5M. Truncate it to below size's and verify
29480         # blocks count.
29481         #
29482         dd if=/dev/zero of=$DIR/$tfile bs=5M count=1 conv=fsync ||
29483                 error "Create file $DIR/$tfile failed"
29484         stack_trap "rm -f $DIR/$tfile" EXIT
29485
29486         for trunc_sz in 2097152 4097 4000 509 0; do
29487                 $TRUNCATE $DIR/$tfile $trunc_sz ||
29488                         error "truncate $tfile to $trunc_sz failed"
29489                 local sz=$(stat --format=%s $DIR/$tfile)
29490                 local blk=$(stat --format=%b $DIR/$tfile)
29491                 local trunc_blk=$((((trunc_sz + (grant_blk_size - 1) ) /
29492                                      grant_blk_size) * 8))
29493
29494                 if [[ $blk -ne $trunc_blk ]]; then
29495                         $(which stat) $DIR/$tfile
29496                         error "Expected Block $trunc_blk got $blk for $tfile"
29497                 fi
29498
29499                 $CHECKSTAT -s $trunc_sz $DIR/$tfile ||
29500                         error "Expected Size $trunc_sz got $sz for $tfile"
29501         done
29502
29503         #
29504         # sparse file test
29505         # Create file with a hole and write actual 65536 bytes which aligned
29506         # with 4K and 64K PAGE_SIZE. Block count must be 128.
29507         #
29508         local bs=65536
29509         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 seek=5 conv=fsync ||
29510                 error "Create file : $DIR/$tfile"
29511
29512         #
29513         # Truncate to size $trunc_sz bytes. Strip tail blocks and leave only 8
29514         # blocks. The block count must drop to 8.
29515         #
29516         trunc_sz=$(($(stat --format=%s $DIR/$tfile) -
29517                 ((bs - grant_blk_size) + 1)))
29518         $TRUNCATE $DIR/$tfile $trunc_sz ||
29519                 error "truncate $tfile to $trunc_sz failed"
29520
29521         local trunc_bsz=$((grant_blk_size / $(stat --format=%B $DIR/$tfile)))
29522         sz=$(stat --format=%s $DIR/$tfile)
29523         blk=$(stat --format=%b $DIR/$tfile)
29524
29525         if [[ $blk -ne $trunc_bsz ]]; then
29526                 $(which stat) $DIR/$tfile
29527                 error "Expected Block $trunc_bsz got $blk for $tfile"
29528         fi
29529
29530         $CHECKSTAT -s $trunc_sz $DIR/$tfile ||
29531                 error "Expected Size $trunc_sz got $sz for $tfile"
29532 }
29533 run_test 317 "Verify blocks get correctly update after truncate"
29534
29535 test_318() {
29536         local llite_name="llite.$($LFS getname $MOUNT | awk '{print $1}')"
29537         local old_max_active=$($LCTL get_param -n \
29538                             ${llite_name}.max_read_ahead_async_active \
29539                             2>/dev/null)
29540
29541         $LCTL set_param llite.*.max_read_ahead_async_active=256
29542         local max_active=$($LCTL get_param -n \
29543                            ${llite_name}.max_read_ahead_async_active \
29544                            2>/dev/null)
29545         [ $max_active -ne 256 ] && error "expected 256 but got $max_active"
29546
29547         $LCTL set_param llite.*.max_read_ahead_async_active=0 ||
29548                 error "set max_read_ahead_async_active should succeed"
29549
29550         $LCTL set_param llite.*.max_read_ahead_async_active=512
29551         max_active=$($LCTL get_param -n \
29552                      ${llite_name}.max_read_ahead_async_active 2>/dev/null)
29553         [ $max_active -eq 512 ] || error "expected 512 but got $max_active"
29554
29555         # restore @max_active
29556         [ $old_max_active -ne 0 ] && $LCTL set_param \
29557                 llite.*.max_read_ahead_async_active=$old_max_active
29558
29559         local old_threshold=$($LCTL get_param -n \
29560                 ${llite_name}.read_ahead_async_file_threshold_mb 2>/dev/null)
29561         local max_per_file_mb=$($LCTL get_param -n \
29562                 ${llite_name}.max_read_ahead_per_file_mb 2>/dev/null)
29563
29564         local invalid=$(($max_per_file_mb + 1))
29565         $LCTL set_param \
29566                 llite.*.read_ahead_async_file_threshold_mb=$invalid\
29567                         && error "set $invalid should fail"
29568
29569         local valid=$(($invalid - 1))
29570         $LCTL set_param \
29571                 llite.*.read_ahead_async_file_threshold_mb=$valid ||
29572                         error "set $valid should succeed"
29573         local threshold=$($LCTL get_param -n \
29574                 ${llite_name}.read_ahead_async_file_threshold_mb 2>/dev/null)
29575         [ $threshold -eq $valid ] || error \
29576                 "expect threshold $valid got $threshold"
29577         $LCTL set_param \
29578                 llite.*.read_ahead_async_file_threshold_mb=$old_threshold
29579 }
29580 run_test 318 "Verify async readahead tunables"
29581
29582 test_319() {
29583         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
29584
29585         local before=$(date +%s)
29586         local evict
29587         local mdir=$DIR/$tdir
29588         local file=$mdir/xxx
29589
29590         $LFS mkdir -i0 $mdir || error "mkdir $mdir fails"
29591         touch $file
29592
29593 #define OBD_FAIL_LDLM_LOCAL_CANCEL_PAUSE 0x32c
29594         $LCTL set_param fail_val=5 fail_loc=0x8000032c
29595         $LFS migrate -m1 $mdir &
29596
29597         sleep 1
29598         dd if=$file of=/dev/null
29599         wait
29600         evict=$($LCTL get_param mdc.$FSNAME-MDT*.state |
29601           awk -F"[ [,]" '/EVICTED ]$/ { if (mx<$5) {mx=$5;} } END { print mx }')
29602
29603         [ -z "$evict" ] || [[ $evict -le $before ]] || error "eviction happened"
29604 }
29605 run_test 319 "lost lease lock on migrate error"
29606
29607 test_350() {
29608         local mdts=$(comma_list $(mdts_nodes))
29609
29610         mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
29611         stack_trap "rm -r $DIR/$tdir"
29612
29613         #force 1/100 of replies to take "NID mismatch" codepath
29614         #define CFS_FAIL_MATCH_MD_NID 0xe001  CFS_FAIL_SOME 0x10000000
29615         do_nodes $mdts $LCTL set_param fail_loc=0x1000e001 fail_val=100
29616
29617         while ls -lR $DIR/$tdir > /dev/null; do :; done &
29618         stack_trap "killall -9 ls || killall -9 ls"
29619
29620         cp -a /etc $DIR/$tdir || error "cp failed"
29621 }
29622 run_test 350 "force NID mismatch path to be exercised"
29623
29624 test_360() {
29625         (( $OST1_VERSION >= $(version_code 2.15.58.96) )) ||
29626                 skip "Need OST version at least 2.15.58.96"
29627         [[ "$ost1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
29628
29629         check_set_fallocate_or_skip
29630         local param="osd-ldiskfs.delayed_unlink_mb"
29631         local old=($(do_facet ost1 "$LCTL get_param -n $param"))
29632
29633         do_facet ost1 "$LCTL set_param $param=1MiB"
29634         stack_trap "do_facet ost1 $LCTL set_param $param=${old[0]}"
29635
29636         mkdir $DIR/$tdir/
29637         # LU-16904 Use stripe count 1 for test dir to make sure the files
29638         # created under it have object greater than 1M on single OST
29639         # to test delayed iput
29640         $LFS setstripe -c 1 $DIR/$tdir/
29641
29642         do_facet ost1 $LCTL set_param debug=+inode
29643         do_facet ost1 $LCTL clear
29644         local files=100
29645
29646         for ((i = 0; i < $files; i++)); do
29647                 fallocate -l 1280k $DIR/$tdir/$tfile.$i ||
29648                         error "fallocate 1280k $DIR/$tdir/$tfile.$i failed"
29649         done
29650         local min=$(($($LFS find $DIR/$tdir --ost 0 | wc -l) / 2))
29651
29652         for ((i = 0; i < $files; i++)); do
29653                 unlink $DIR/$tdir/$tfile.$i ||
29654                         error "unlink $DIR/$tdir/$tfile.$i failed"
29655         done
29656
29657         local count=0
29658         local loop
29659
29660         for (( loop = 0; loop < 30 && count < min; loop++)); do
29661                 sleep 1
29662                 (( count += $(do_facet ost1 $LCTL dk | grep -c "delayed iput")))
29663                 echo "Count[$loop]: $count"
29664         done
29665         (( count >= min )) || error "$count < $min delayed iput after $loop s"
29666 }
29667 run_test 360 "ldiskfs unlink in a separate thread"
29668
29669 test_398a() { # LU-4198
29670         local ost1_imp=$(get_osc_import_name client ost1)
29671         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
29672                          cut -d'.' -f2)
29673
29674         $LFS setstripe -c 1 -i 0 $DIR/$tfile
29675         stack_trap "rm -f $DIR/$tfile"
29676         $LCTL set_param ldlm.namespaces.*.lru_size=clear
29677
29678         # request a new lock on client
29679         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
29680
29681         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct conv=notrunc
29682         local lock_count=$($LCTL get_param -n \
29683                            ldlm.namespaces.$imp_name.lru_size)
29684         [[ $lock_count -eq 0 ]] || error "lock should be cancelled by direct IO"
29685
29686         $LCTL set_param ldlm.namespaces.$imp_name.lru_size=clear
29687
29688         # no lock cached, should use lockless DIO and not enqueue new lock
29689         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct conv=notrunc
29690         lock_count=$($LCTL get_param -n \
29691                      ldlm.namespaces.$imp_name.lru_size)
29692         [[ $lock_count -eq 0 ]] || error "no lock should be held by direct IO"
29693
29694         $LCTL set_param ldlm.namespaces.$imp_name.lru_size=clear
29695
29696         # no lock cached, should use locked DIO append
29697         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct oflag=append \
29698                 conv=notrunc || error "DIO append failed"
29699         lock_count=$($LCTL get_param -n \
29700                      ldlm.namespaces.$imp_name.lru_size)
29701         [[ $lock_count -ne 0 ]] || error "lock still must be held by DIO append"
29702 }
29703 run_test 398a "direct IO should cancel lock otherwise lockless"
29704
29705 test_398b() { # LU-4198
29706         local before=$(date +%s)
29707         local njobs=4
29708         local size=48
29709
29710         which fio || skip_env "no fio installed"
29711         $LFS setstripe -c -1 -S 1M $DIR/$tfile
29712         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$size
29713
29714         # Single page, multiple pages, stripe size, 4*stripe size
29715         for bsize in $(( $PAGE_SIZE )) $(( 4*$PAGE_SIZE )) 1048576 4194304; do
29716                 echo "mix direct rw ${bsize} by fio with $njobs jobs..."
29717                 fio --name=rand-rw --rw=randrw --bs=$bsize --direct=1 \
29718                         --numjobs=$njobs --fallocate=none \
29719                         --iodepth=16 --allow_file_create=0 \
29720                         --size=$((size/njobs))M \
29721                         --filename=$DIR/$tfile &
29722                 bg_pid=$!
29723
29724                 echo "mix buffer rw ${bsize} by fio with $njobs jobs..."
29725                 fio --name=rand-rw --rw=randrw --bs=$bsize \
29726                         --numjobs=$njobs --fallocate=none \
29727                         --iodepth=16 --allow_file_create=0 \
29728                         --size=$((size/njobs))M \
29729                         --filename=$DIR/$tfile || true
29730                 wait $bg_pid
29731         done
29732
29733         evict=$(do_facet client $LCTL get_param \
29734                 osc.$FSNAME-OST*-osc-*/state |
29735             awk -F"[ [,]" '/EVICTED ]$/ { if (t<$5) {t=$5;} } END { print t }')
29736
29737         [ -z "$evict" ] || [[ $evict -le $before ]] ||
29738                 (do_facet client $LCTL get_param \
29739                         osc.$FSNAME-OST*-osc-*/state;
29740                     error "eviction happened: $evict before:$before")
29741
29742         rm -f $DIR/$tfile
29743 }
29744 run_test 398b "DIO and buffer IO race"
29745
29746 test_398c() { # LU-4198
29747         local ost1_imp="osc.$(get_osc_import_name client ost1)"
29748         local imp_name=($($LCTL list_param $ost1_imp | cut -d'.' -f2))
29749
29750         which fio || skip_env "no fio installed"
29751
29752         saved_debug=$($LCTL get_param -n debug)
29753         $LCTL set_param debug=0
29754
29755         local size=($($LCTL get_param -n $ost1_imp.kbytesavail))
29756         (( size /= 1024 )) # by megabytes
29757         (( size /= 2 )) # write half of the OST at most
29758         (( size <= 40 )) || size=40 #reduce test time anyway
29759
29760         $LFS setstripe -c 1 $DIR/$tfile
29761
29762         # it seems like ldiskfs reserves more space than necessary if the
29763         # writing blocks are not mapped, so it extends the file firstly
29764         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$size && sync
29765         cancel_lru_locks osc
29766
29767         # clear and verify rpc_stats later
29768         $LCTL set_param $ost1_imp.rpc_stats=clear
29769
29770         local njobs=4
29771         echo "writing ${size}M to OST0 by fio with $njobs jobs..."
29772         fio --name=rand-write --rw=randwrite --bs=$PAGE_SIZE --direct=1 \
29773                 --numjobs=$njobs --fallocate=none --ioengine=libaio \
29774                 --iodepth=16 --allow_file_create=0 --size=$((size/njobs))M \
29775                 --filename=$DIR/$tfile
29776         [ $? -eq 0 ] || error "fio write error"
29777
29778         (( $($LCTL get_param -n ldlm.namespaces.$imp_name.lock_count) == 0 )) ||
29779                 error "Locks were requested while doing AIO"
29780
29781         # get the percentage of 1-page I/O
29782         pct=$($LCTL get_param osc.${imp_name}.rpc_stats |
29783                 grep -A 1 'pages per rpc' | grep -v 'pages per rpc' |
29784                 awk '{print $7}')
29785         (( $pct <= 50 )) || {
29786                 $LCTL get_param osc.${imp_name}.rpc_stats
29787                 error "$pct% of I/O are 1-page"
29788         }
29789
29790         echo "mix rw ${size}M to OST0 by fio with $njobs jobs..."
29791         fio --name=rand-rw --rw=randrw --bs=$PAGE_SIZE --direct=1 \
29792                 --numjobs=$njobs --fallocate=none --ioengine=libaio \
29793                 --iodepth=16 --allow_file_create=0 --size=$((size/njobs))M \
29794                 --filename=$DIR/$tfile
29795         [ $? -eq 0 ] || error "fio mixed read write error"
29796
29797         echo "AIO with large block size ${size}M"
29798         fio --name=rand-rw --rw=randrw --bs=${size}M --direct=1 \
29799                 --numjobs=1 --fallocate=none --ioengine=libaio \
29800                 --iodepth=16 --allow_file_create=0 --size=${size}M \
29801                 --filename=$DIR/$tfile
29802         [ $? -eq 0 ] || error "fio large block size failed"
29803
29804         rm -f $DIR/$tfile
29805         $LCTL set_param debug="$saved_debug"
29806 }
29807 run_test 398c "run fio to test AIO"
29808
29809 test_398d() { #  LU-13846
29810         which aiocp || skip_env "no aiocp installed"
29811         local aio_file=$DIR/$tfile.aio
29812
29813         $LFS setstripe -c -1 -S 1M $DIR/$tfile $aio_file
29814
29815         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=64
29816         aiocp -a $PAGE_SIZE -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file
29817         stack_trap "rm -f $DIR/$tfile $aio_file"
29818
29819         diff $DIR/$tfile $aio_file || error "file diff after aiocp"
29820
29821         # test memory unaligned aio
29822         # LU-18032 - unaligned AIO is disabled
29823         #aiocp -a 512 -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file ||
29824         #       error "unaligned aio failed"
29825         #diff $DIR/$tfile $aio_file || error "file diff after aiocp"
29826
29827         rm -f $DIR/$tfile $aio_file
29828 }
29829 run_test 398d "run aiocp to verify block size > stripe size"
29830
29831 test_398e() {
29832         dd if=/dev/zero of=$DIR/$tfile bs=1234 count=1
29833         touch $DIR/$tfile.new
29834         dd if=$DIR/$tfile of=$DIR/$tfile.new bs=1M count=1 oflag=direct
29835 }
29836 run_test 398e "O_Direct open cleared by fcntl doesn't cause hang"
29837
29838 test_398f() { #  LU-14687
29839         which aiocp || skip_env "no aiocp installed"
29840         local aio_file=$DIR/$tfile.aio
29841
29842         $LFS setstripe -c -1 -S 1M $DIR/$tfile $aio_file
29843
29844         dd if=/dev/zero of=$DIR/$tfile bs=1M count=64
29845         stack_trap "rm -f $DIR/$tfile $aio_file"
29846
29847         #define OBD_FAIL_LLITE_PAGE_ALLOC 0x1418
29848         $LCTL set_param fail_loc=0x1418
29849         # make sure we don't crash and fail properly
29850         aiocp -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file &&
29851                 error "aio with page allocation failure succeeded"
29852         $LCTL set_param fail_loc=0
29853         diff $DIR/$tfile $aio_file
29854         [[ $? != 0 ]] || error "no diff after failed aiocp"
29855 }
29856 run_test 398f "verify aio handles ll_direct_rw_pages errors correctly"
29857
29858 # NB: To get the parallel DIO behavior in LU-13798, there must be > 1
29859 # stripe and i/o size must be > stripe size
29860 # Old style synchronous DIO waits after submitting each chunk, resulting in a
29861 # single RPC in flight.  This test shows async DIO submission is working by
29862 # showing multiple RPCs in flight.
29863 test_398g() { #  LU-13798
29864         $LFS setstripe -o 0,0 -S 1M $DIR/$tfile
29865
29866         # We need to do some i/o first to acquire enough grant to put our RPCs
29867         # in flight; otherwise a new connection may not have enough grant
29868         # available
29869         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
29870                 error "parallel dio failed"
29871         stack_trap "rm -f $DIR/$tfile"
29872
29873         # Reduce RPC size to 1M to avoid combination in to larger RPCs
29874         local pages_per_rpc=$($LCTL get_param osc.*-OST0000-*.max_pages_per_rpc)
29875         $LCTL set_param osc.*-OST0000-*.max_pages_per_rpc=1M
29876         stack_trap "$LCTL set_param -n $pages_per_rpc"
29877
29878         # Recreate file so it's empty
29879         rm -f $DIR/$tfile
29880         $LFS setstripe -o 0,0 -S 1M $DIR/$tfile
29881         #Pause rpc completion to guarantee we see multiple rpcs in flight
29882         #define OBD_FAIL_OST_BRW_PAUSE_BULK
29883         do_facet ost1 $LCTL set_param fail_loc=0x214 fail_val=2
29884         stack_trap "do_facet ost1 $LCTL set_param fail_loc=0"
29885
29886         # Clear rpc stats
29887         $LCTL set_param osc.*.rpc_stats=c
29888
29889         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
29890                 error "parallel dio failed"
29891         stack_trap "rm -f $DIR/$tfile"
29892
29893         $LCTL get_param osc.*-OST0000-*.rpc_stats
29894         pct=$($LCTL get_param osc.*-OST0000-*.rpc_stats |
29895                 grep -A 8 'rpcs in flight' | grep -v 'rpcs in flight' |
29896                 grep "8:" | awk '{print $8}')
29897         # We look at the "8 rpcs in flight" field, and verify A) it is present
29898         # and B) it includes all RPCs.  This proves we had 8 RPCs in flight,
29899         # as expected for an 8M DIO to a file with 1M stripes.
29900         # NB: There is occasionally a mystery extra write RPC to a different
29901         # file.  I can't identify why that's happening, so we set up a margin
29902         # of 1 RPC here, ie, 8/9 RPCs at this size, or ~88%
29903         [ $pct -gt 87 ] || error "we should see 8 RPCs in flight"
29904
29905         # Verify turning off parallel dio works as expected
29906         # Clear rpc stats
29907         $LCTL set_param osc.*.rpc_stats=c
29908         $LCTL set_param llite.*.parallel_dio=0
29909         stack_trap '$LCTL set_param llite.*.parallel_dio=1'
29910
29911         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
29912                 error "dio with parallel dio disabled failed"
29913
29914         # Ideally, we would see only one RPC in flight here, but there is an
29915         # unavoidable race between i/o completion and RPC in flight counting,
29916         # so while only 1 i/o is in flight at a time, the RPC in flight counter
29917         # will sometimes exceed 1 (3 or 4 is not rare on VM testing).
29918         # So instead we just verify it's always < 8.
29919         $LCTL get_param osc.*-OST0000-*.rpc_stats
29920         ret=$($LCTL get_param osc.*-OST0000-*.rpc_stats |
29921                 grep -A 8 'rpcs in flight' | grep -v 'rpcs in flight' |
29922                 grep '^$' -B1 | grep . | awk '{print $1}')
29923         [ $ret != "8:" ] ||
29924                 error "we should see fewer than 8 RPCs in flight (saw $ret)"
29925 }
29926 run_test 398g "verify parallel dio async RPC submission"
29927
29928 test_398h() { #  LU-13798
29929         local dio_file=$DIR/$tfile.dio
29930
29931         $LFS setstripe -C 2 -S 1M $DIR/$tfile $dio_file
29932
29933         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
29934         stack_trap "rm -f $DIR/$tfile $dio_file"
29935
29936         dd if=$DIR/$tfile of=$dio_file bs=8M count=8 iflag=direct oflag=direct ||
29937                 error "parallel dio failed"
29938         diff $DIR/$tfile $dio_file
29939         [[ $? == 0 ]] || error "file diff after aiocp"
29940 }
29941 run_test 398h "verify correctness of read & write with i/o size >> stripe size"
29942
29943 test_398i() { #  LU-13798
29944         local dio_file=$DIR/$tfile.dio
29945
29946         $LFS setstripe -C 2 -S 1M $DIR/$tfile $dio_file
29947
29948         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
29949         stack_trap "rm -f $DIR/$tfile $dio_file"
29950
29951         #define OBD_FAIL_LLITE_PAGE_ALLOC 0x1418
29952         $LCTL set_param fail_loc=0x1418
29953         # make sure we don't crash and fail properly
29954         dd if=$DIR/$tfile of=$dio_file bs=8M count=8 iflag=direct oflag=direct &&
29955                 error "parallel dio page allocation failure succeeded"
29956         diff $DIR/$tfile $dio_file
29957         [[ $? != 0 ]] || error "no diff after failed aiocp"
29958 }
29959 run_test 398i "verify parallel dio handles ll_direct_rw_pages errors correctly"
29960
29961 test_398j() { #  LU-13798
29962         # Stripe size > RPC size but less than i/o size tests split across
29963         # stripes and RPCs for individual i/o op
29964         $LFS setstripe -o 0,0 -S 4M $DIR/$tfile $DIR/$tfile.2
29965
29966         # Reduce RPC size to 1M to guarantee split to multiple RPCs per stripe
29967         local pages_per_rpc=$($LCTL get_param osc.*-OST0000-*.max_pages_per_rpc)
29968         $LCTL set_param osc.*-OST0000-*.max_pages_per_rpc=1M
29969         stack_trap "$LCTL set_param -n $pages_per_rpc"
29970
29971         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
29972                 error "parallel dio write failed"
29973         stack_trap "rm -f $DIR/$tfile $DIR/$tfile.2"
29974
29975         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct ||
29976                 error "parallel dio read failed"
29977         diff $DIR/$tfile $DIR/$tfile.2
29978         [[ $? == 0 ]] || error "file diff after parallel dio read"
29979 }
29980 run_test 398j "test parallel dio where stripe size > rpc_size"
29981
29982 test_398k() { #  LU-13798
29983         wait_delete_completed
29984         wait_mds_ost_sync
29985
29986         # 4 stripe file; we will cause out of space on OST0
29987         $LFS setstripe -o 0,1,0,1 -S 1M $DIR/$tfile
29988
29989         # Fill OST0 (if it's not too large)
29990         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
29991                    head -n1)
29992         if [[ $ORIGFREE -gt $MAXFREE ]]; then
29993                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
29994         fi
29995         $LFS setstripe -i 0 -c 1 $DIR/$tfile.1
29996         dd if=/dev/zero of=$DIR/$tfile.1 bs=1024 count=$MAXFREE &&
29997                 error "dd should fill OST0"
29998         stack_trap "rm -f $DIR/$tfile.1"
29999
30000         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
30001         err=$?
30002
30003         ls -la $DIR/$tfile
30004         $CHECKSTAT -t file -s 0 $DIR/$tfile ||
30005                 error "file is not 0 bytes in size"
30006
30007         # dd above should not succeed, but don't error until here so we can
30008         # get debug info above
30009         [[ $err != 0 ]] ||
30010                 error "parallel dio write with enospc succeeded"
30011         stack_trap "rm -f $DIR/$tfile"
30012 }
30013 run_test 398k "test enospc on first stripe"
30014
30015 test_398l() { #  LU-13798
30016         wait_delete_completed
30017         wait_mds_ost_sync
30018         # Clean up after the test
30019         stack_trap wait_delete_completed
30020         stack_trap wait_mds_ost_sync
30021
30022         # 4 stripe file; we will cause out of space on OST0
30023         # Note the 1M stripe size and the > 1M i/o size mean this ENOSPC
30024         # happens on the second i/o chunk we issue
30025         $LFS setstripe -o 1,0,1,0 -S 1M $DIR/$tfile $DIR/$tfile.2
30026
30027         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=2 oflag=direct
30028         stack_trap "rm -f $DIR/$tfile"
30029
30030         # Fill OST0 (if it's not too large)
30031         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
30032                    head -n1)
30033         if [[ $ORIGFREE -gt $MAXFREE ]]; then
30034                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
30035         fi
30036         $LFS setstripe -i 0 -c 1 $DIR/$tfile.1
30037         dd if=/dev/zero of=$DIR/$tfile.1 bs=1024 count=$MAXFREE &&
30038                 error "dd should fill OST0"
30039         stack_trap "rm -f $DIR/$tfile.1"
30040
30041         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 oflag=direct
30042         err=$?
30043         stack_trap "rm -f $DIR/$tfile.2"
30044
30045         # Check that short write completed as expected
30046         ls -la $DIR/$tfile.2
30047         $CHECKSTAT -t file -s 1048576 $DIR/$tfile.2 ||
30048                 error "file is not 1M in size"
30049
30050         # dd above should not succeed, but don't error until here so we can
30051         # get debug info above
30052         [[ $err != 0 ]] ||
30053                 error "parallel dio write with enospc succeeded"
30054
30055         # Truncate source file to same length as output file and diff them
30056         $TRUNCATE $DIR/$tfile 1048576
30057         diff $DIR/$tfile $DIR/$tfile.2
30058         [[ $? == 0 ]] || error "data incorrect after short write"
30059 }
30060 run_test 398l "test enospc on intermediate stripe/RPC"
30061
30062 test_398m() { #  LU-13798
30063         $LFS setstripe -o 0,1,0,1 -S 1M $DIR/$tfile
30064
30065         # Set up failure on OST0, the first stripe:
30066         #define OBD_FAIL_OST_BRW_WRITE_BULK     0x20e
30067         #NB: Fail val is ost # + 1, because we cannot use cfs_fail_val = 0
30068         # OST0 is on ost1, OST1 is on ost2.
30069         # So this fail_val specifies OST0
30070         do_facet ost1 $LCTL set_param fail_loc=0x20e fail_val=1
30071         stack_trap "do_facet ost1 $LCTL set_param fail_loc=0"
30072
30073         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct &&
30074                 error "parallel dio write with failure on first stripe succeeded"
30075         stack_trap "rm -f $DIR/$tfile"
30076         do_facet ost1 $LCTL set_param fail_loc=0 fail_val=0
30077
30078         # Place data in file for read
30079         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
30080                 error "parallel dio write failed"
30081
30082         # Fail read on OST0, first stripe
30083         #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
30084         do_facet ost1 $LCTL set_param fail_loc=0x20f fail_val=1
30085         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct &&
30086                 error "parallel dio read with error on first stripe succeeded"
30087         rm -f $DIR/$tfile.2
30088         do_facet ost1 $LCTL set_param fail_loc=0 fail_val=0
30089
30090         # Switch to testing on OST1, second stripe
30091         # Clear file contents, maintain striping
30092         echo > $DIR/$tfile
30093         # Set up failure on OST1, second stripe:
30094         do_facet ost2 $LCTL set_param fail_loc=0x20e fail_val=2
30095         stack_trap "do_facet ost2 $LCTL set_param fail_loc=0"
30096
30097         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct &&
30098                 error "parallel dio write with failure on second stripe succeeded"
30099         stack_trap "rm -f $DIR/$tfile"
30100         do_facet ost2 $LCTL set_param fail_loc=0 fail_val=0
30101
30102         # Place data in file for read
30103         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
30104                 error "parallel dio write failed"
30105
30106         # Fail read on OST1, second stripe
30107         #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
30108         do_facet ost2 $LCTL set_param fail_loc=0x20f fail_val=2
30109         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct &&
30110                 error "parallel dio read with error on second stripe succeeded"
30111         rm -f $DIR/$tfile.2
30112         do_facet ost2 $LCTL set_param fail_loc=0 fail_val=0
30113 }
30114 run_test 398m "test RPC failures with parallel dio"
30115
30116 # Parallel submission of DIO should not cause problems for append, but it's
30117 # important to verify.
30118 test_398n() { #  LU-13798
30119         $LFS setstripe -C 2 -S 1M $DIR/$tfile
30120
30121         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 ||
30122                 error "dd to create source file failed"
30123         stack_trap "rm -f $DIR/$tfile"
30124
30125         dd if=$DIR/$tfile of=$DIR/$tfile.1 bs=8M count=8 oflag=direct oflag=append ||
30126                 error "parallel dio write with failure on second stripe succeeded"
30127         stack_trap "rm -f $DIR/$tfile $DIR/$tfile.1"
30128         diff $DIR/$tfile $DIR/$tfile.1
30129         [[ $? == 0 ]] || error "data incorrect after append"
30130
30131 }
30132 run_test 398n "test append with parallel DIO"
30133
30134 test_398o() {
30135         directio rdwr $DIR/$tfile 0 1 1 || error "bad KMS"
30136 }
30137 run_test 398o "right kms with DIO"
30138
30139 test_398p()
30140 {
30141         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
30142         which aiocp || skip_env "no aiocp installed"
30143
30144         local stripe_size=$((1024 * 1024)) #1 MiB
30145         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
30146         local file_size=$((25 * stripe_size))
30147
30148         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
30149         stack_trap "rm -f $DIR/$tfile*"
30150         # Just a bit bigger than the largest size in the test set below
30151         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
30152                 error "buffered i/o to create file failed"
30153
30154         for bs in $PAGE_SIZE $((PAGE_SIZE * 4)) $stripe_size \
30155                 $((stripe_size * 4)); do
30156
30157                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
30158
30159                 echo "bs: $bs, file_size $file_size"
30160                 aiocp -a $PAGE_SIZE -b $bs -s $file_size -f O_DIRECT \
30161                         $DIR/$tfile.1 $DIR/$tfile.2 &
30162                 pid_dio1=$!
30163                 # Buffered I/O with similar but not the same block size
30164                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
30165                         conv=notrunc &
30166                 pid_bio2=$!
30167                 wait $pid_dio1
30168                 rc1=$?
30169                 wait $pid_bio2
30170                 rc2=$?
30171                 if (( rc1 != 0 )); then
30172                         error "aio copy 1 w/bsize $bs failed: $rc1"
30173                 fi
30174                 if (( rc2 != 0 )); then
30175                         error "buffered copy 2 w/bsize $bs failed: $rc2"
30176                 fi
30177
30178                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
30179                         error "size incorrect"
30180                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
30181                         error "files differ, bsize $bs"
30182                 rm -f $DIR/$tfile.2
30183         done
30184 }
30185 run_test 398p "race aio with buffered i/o"
30186
30187 test_398q()
30188 {
30189         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
30190
30191         local stripe_size=$((1024 * 1024)) #1 MiB
30192         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
30193         local file_size=$((25 * stripe_size))
30194
30195         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
30196         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
30197
30198         # Just a bit bigger than the largest size in the test set below
30199         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
30200                 error "buffered i/o to create file failed"
30201
30202         for bs in $PAGE_SIZE $((PAGE_SIZE * 4)) $stripe_size \
30203                 $((stripe_size * 4)); do
30204
30205                 echo "bs: $bs, file_size $file_size"
30206                 dd if=$DIR/$tfile.1 bs=$((bs *2 )) of=$DIR/$tfile.2 \
30207                         conv=notrunc oflag=direct iflag=direct &
30208                 pid_dio1=$!
30209                 # Buffered I/O with similar but not the same block size
30210                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
30211                         conv=notrunc &
30212                 pid_bio2=$!
30213                 wait $pid_dio1
30214                 rc1=$?
30215                 wait $pid_bio2
30216                 rc2=$?
30217                 if (( rc1 != 0 )); then
30218                         error "dio copy 1 w/bsize $bs failed: $rc1"
30219                 fi
30220                 if (( rc2 != 0 )); then
30221                         error "buffered copy 2 w/bsize $bs failed: $rc2"
30222                 fi
30223
30224                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
30225                         error "size incorrect"
30226                 diff $DIR/$tfile.1 $DIR/$tfile.2 ||
30227                         error "files differ, bsize $bs"
30228         done
30229
30230         rm -f $DIR/$tfile*
30231 }
30232 run_test 398q "race dio with buffered i/o"
30233
30234 test_398r() {
30235         $LFS setstripe -i 0 -c 1 $DIR/$tfile || error "setstripe failed"
30236         echo "hello, world" > $DIR/$tfile
30237
30238         cancel_lru_locks osc
30239
30240 #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
30241         do_facet ost1 $LCTL set_param fail_loc=0x20f
30242         cat $DIR/$tfile > /dev/null && error "cat should fail"
30243         return 0
30244 }
30245 run_test 398r "i/o error on file read"
30246
30247 test_398s() {
30248         [[ $OSTCOUNT -ge 2 && "$ost1_HOST" = "$ost2_HOST" ]] ||
30249                 skip "remote OST"
30250
30251         $LFS mirror create -N -i 0 -c 1 -N -i 1 -c 1 $DIR/$tfile ||
30252                 error "mirror create failed"
30253
30254         echo "hello, world" > $DIR/$tfile
30255         $LFS mirror resync $DIR/$tfile || error "mirror resync failed"
30256
30257         cancel_lru_locks osc
30258
30259 #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
30260         do_facet ost1 $LCTL set_param fail_loc=0x20f
30261         cat $DIR/$tfile > /dev/null && error "cat should fail"
30262         return 0
30263 }
30264 run_test 398s "i/o error on mirror file read"
30265
30266 test_fake_rw() {
30267         local read_write=$1
30268         if [ "$read_write" = "write" ]; then
30269                 local dd_cmd="dd if=/dev/zero of=$DIR/$tfile"
30270         elif [ "$read_write" = "read" ]; then
30271                 local dd_cmd="dd of=/dev/null if=$DIR/$tfile"
30272         else
30273                 error "argument error"
30274         fi
30275
30276         # turn off debug for performance testing
30277         local saved_debug=$($LCTL get_param -n debug)
30278         $LCTL set_param debug=0
30279
30280         $LFS setstripe -c 1 -i 0 $DIR/$tfile
30281
30282         # get ost1 size - $FSNAME-OST0000
30283         local ost1_avail_size=$($LFS df $DIR | awk /${ost1_svc}/'{ print $4 }')
30284         local blocks=$((ost1_avail_size/2/1024)) # half avail space by megabytes
30285         [ $blocks -gt 1000 ] && blocks=1000 # 1G in maximum
30286
30287         if [ "$read_write" = "read" ]; then
30288                 $TRUNCATE $DIR/$tfile $(expr 1048576 \* $blocks)
30289         fi
30290
30291         local start_time=$(date +%s.%N)
30292         $dd_cmd bs=1M count=$blocks oflag=sync ||
30293                 error "real dd $read_write error"
30294         local duration=$(bc <<< "$(date +%s.%N) - $start_time")
30295
30296         if [ "$read_write" = "write" ]; then
30297                 rm -f $DIR/$tfile
30298         fi
30299
30300         # define OBD_FAIL_OST_FAKE_RW           0x238
30301         do_facet ost1 $LCTL set_param fail_loc=0x238
30302
30303         local start_time=$(date +%s.%N)
30304         $dd_cmd bs=1M count=$blocks oflag=sync ||
30305                 error "fake dd $read_write error"
30306         local duration_fake=$(bc <<< "$(date +%s.%N) - $start_time")
30307
30308         if [ "$read_write" = "write" ]; then
30309                 # verify file size
30310                 cancel_lru_locks osc
30311                 $CHECKSTAT -t file -s $((blocks * 1024 * 1024)) $DIR/$tfile ||
30312                         error "$tfile size not $blocks MB"
30313         fi
30314         do_facet ost1 $LCTL set_param fail_loc=0
30315
30316         echo "fake $read_write $duration_fake vs. normal $read_write" \
30317                 "$duration in seconds"
30318         [ $(bc <<< "$duration_fake < $duration") -eq 1 ] ||
30319                 error_not_in_vm "fake write is slower"
30320
30321         $LCTL set_param -n debug="$saved_debug"
30322         rm -f $DIR/$tfile
30323 }
30324 test_399a() { # LU-7655 for OST fake write
30325         remote_ost_nodsh && skip "remote OST with nodsh"
30326
30327         test_fake_rw write
30328 }
30329 run_test 399a "fake write should not be slower than normal write"
30330
30331 test_399b() { # LU-8726 for OST fake read
30332         remote_ost_nodsh && skip "remote OST with nodsh"
30333         if [ "$ost1_FSTYPE" != "ldiskfs" ]; then
30334                 skip_env "ldiskfs only test"
30335         fi
30336
30337         test_fake_rw read
30338 }
30339 run_test 399b "fake read should not be slower than normal read"
30340
30341 test_400a() { # LU-1606, was conf-sanity test_74
30342         if ! which $CC > /dev/null 2>&1; then
30343                 skip_env "$CC is not installed"
30344         fi
30345
30346         local extra_flags=''
30347         local out=$TMP/$tfile
30348         local prefix=/usr/include/lustre
30349         local prog
30350
30351         # Oleg removes .c files in his test rig so test if any c files exist
30352         [[ -n "$(ls -A $LUSTRE_TESTS_API_DIR)" ]] ||
30353                 skip_env "Needed .c test files are missing"
30354
30355         if ! [[ -d $prefix ]]; then
30356                 # Assume we're running in tree and fixup the include path.
30357                 extra_flags+=" -I$LUSTRE/../lnet/include/uapi"
30358                 extra_flags+=" -I$LUSTRE/include/uapi -I$LUSTRE/include"
30359                 extra_flags+=" -L$LUSTRE/utils/.libs"
30360         fi
30361
30362         for prog in $LUSTRE_TESTS_API_DIR/*.c; do
30363                 $CC -Wall -Werror $extra_flags -o $out $prog -llustreapi ||
30364                         error "client api broken"
30365         done
30366         rm -f $out
30367 }
30368 run_test 400a "Lustre client api program can compile and link"
30369
30370 test_400b() { # LU-1606, LU-5011
30371         local header
30372         local out=$TMP/$tfile
30373         local prefix=/usr/include/linux/lustre
30374
30375         # We use a hard coded prefix so that this test will not fail
30376         # when run in tree. There are headers in lustre/include/lustre/
30377         # that are not packaged (like lustre_idl.h) and have more
30378         # complicated include dependencies (like config.h and lnet/types.h).
30379         # Since this test about correct packaging we just skip them when
30380         # they don't exist (see below) rather than try to fixup cppflags.
30381
30382         if ! which $CC > /dev/null 2>&1; then
30383                 skip_env "$CC is not installed"
30384         fi
30385
30386         for header in $prefix/*.h; do
30387                 if ! [[ -f "$header" ]]; then
30388                         continue
30389                 fi
30390
30391                 if [[ "$(basename $header)" == lustre_ioctl.h ]]; then
30392                         continue # lustre_ioctl.h is internal header
30393                 fi
30394
30395                 $CC -Wall -Werror -include $header -c -x c /dev/null -o $out ||
30396                         error "cannot compile '$header'"
30397         done
30398         rm -f $out
30399 }
30400 run_test 400b "packaged headers can be compiled"
30401
30402 test_401a() { #LU-7437
30403         local printf_arg=$(find -printf 2>&1 | grep "unrecognized:")
30404         [ -n "$printf_arg" ] && skip_env "find does not support -printf"
30405
30406         #count the number of parameters by "list_param -R"
30407         local params=$($LCTL list_param -R '*' 2>/dev/null | wc -l)
30408         #count the number of parameters by listing proc files
30409         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
30410         echo "proc_dirs='$proc_dirs'"
30411         [ -n "$proc_dirs" ] || error "no proc_dirs on $HOSTNAME"
30412         local procs=$(find -L $proc_dirs -mindepth 1 -printf '%P\n' 2>/dev/null|
30413                       sort -u | wc -l)
30414
30415         [ $params -eq $procs ] ||
30416                 error "found $params parameters vs. $procs proc files"
30417
30418         # test the list_param -D option only returns directories
30419         params=$($LCTL list_param -R -D '*' 2>/dev/null | wc -l)
30420         #count the number of parameters by listing proc directories
30421         procs=$(find -L $proc_dirs -mindepth 1 -type d -printf '%P\n' 2>/dev/null |
30422                 sort -u | wc -l)
30423
30424         [ $params -eq $procs ] ||
30425                 error "found $params parameters vs. $procs proc files '-D'"
30426 }
30427 run_test 401a "Verify if 'lctl list_param -R' can list parameters recursively"
30428
30429 test_401aa() {
30430         $LCTL list_param -p osc.* | while read path; do
30431                 [[ -r $path ]] && echo "$path" || error "'$path' does not exist"
30432         done
30433 }
30434 run_test 401aa "Verify that 'lctl list_param -p' lists the correct path names"
30435
30436 test_401ab() {
30437         $LCTL list_param -pr "*" | while read path; do
30438                 [[ -r $path ]] || error "'$path' not readable"
30439         done
30440
30441         $LCTL list_param -pLr "*" | while read path; do
30442                 [[ -r $path ]] || error "'$path' not readable (--no-links)"
30443         done
30444 }
30445 run_test 401ab "Check that 'lctl list_param -r' lists only readable params"
30446
30447 test_401ac() {
30448         $LCTL list_param -pw "*" | while read path; do
30449                 [[ -w $path ]] || error "'$path' not writable"
30450         done
30451
30452         $LCTL list_param -pLw "*" | while read path; do
30453                 [[ -w $path ]] || error "'$path' not writable (--no-links)"
30454         done
30455 }
30456 run_test 401ac "Check that 'lctl list_param -w' lists only writable params"
30457
30458 test_401ad() {
30459         $LCTL list_param -prw "*" | while read path; do
30460                 [[ -r $path && -w $path ]] ||
30461                         error "'$path' not readable and writable"
30462         done
30463
30464         $LCTL list_param -pLrw "*" | while read path; do
30465                 [[ -r $path && -w $path ]] ||
30466                         error "'$path' not readable and writable (--no-links)"
30467         done
30468 }
30469 run_test 401ad "Check that 'lctl list_param -wr' is conjunctive"
30470
30471 test_401b() {
30472         # jobid_var may not allow arbitrary values, so use jobid_name
30473         # if available
30474         if $LCTL list_param jobid_name > /dev/null 2>&1; then
30475                 local jobvarname=jobid_name tmp='testing%p'
30476         else
30477                 local jobvarname=jobid_var tmp=testing
30478         fi
30479
30480         local save=$($LCTL get_param -n $jobvarname)
30481
30482         $LCTL set_param foo=bar $jobvarname=$tmp bar=baz &&
30483                 error "no error returned when setting bad parameters"
30484
30485         local jobid_new=$($LCTL get_param -n foe $jobvarname baz)
30486         [[ "$jobid_new" == "$tmp" ]] || error "jobid tmp $jobid_new != $tmp"
30487
30488         $LCTL set_param -n fog=bam $jobvarname=$save bat=fog
30489         local jobid_old=$($LCTL get_param -n foe $jobvarname bag)
30490         [[ "$jobid_old" == "$save" ]] || error "jobid new $jobid_old != $save"
30491 }
30492 run_test 401b "Verify 'lctl {get,set}_param' continue after error"
30493
30494 test_401c() {
30495         # jobid_var may not allow arbitrary values, so use jobid_name
30496         # if available
30497         if $LCTL list_param jobid_name > /dev/null 2>&1; then
30498                 local jobvarname=jobid_name
30499         else
30500                 local jobvarname=jobid_var
30501         fi
30502
30503         local jobid_var_old=$($LCTL get_param -n $jobvarname)
30504         local jobid_var_new
30505
30506         $LCTL set_param $jobvarname= &&
30507                 error "no error returned for 'set_param a='"
30508
30509         jobid_var_new=$($LCTL get_param -n $jobvarname)
30510         [[ "$jobid_var_old" == "$jobid_var_new" ]] ||
30511                 error "$jobvarname was changed by setting without value"
30512
30513         $LCTL set_param $jobvarname &&
30514                 error "no error returned for 'set_param a'"
30515
30516         jobid_var_new=$($LCTL get_param -n $jobvarname)
30517         [[ "$jobid_var_old" == "$jobid_var_new" ]] ||
30518                 error "$jobvarname was changed by setting without value"
30519 }
30520 run_test 401c "Verify 'lctl set_param' without value fails in either format."
30521
30522 test_401d() {
30523         # jobid_var may not allow arbitrary values, so use jobid_name
30524         # if available
30525         if $LCTL list_param jobid_name > /dev/null 2>&1; then
30526                 local jobvarname=jobid_name new_value='foo=bar%p'
30527         else
30528                 local jobvarname=jobid_var new_value=foo=bar
30529         fi
30530
30531         local jobid_var_old=$($LCTL get_param -n $jobvarname)
30532         local jobid_var_new
30533
30534         $LCTL set_param $jobvarname=$new_value ||
30535                 error "'set_param a=b' did not accept a value containing '='"
30536
30537         jobid_var_new=$($LCTL get_param -n $jobvarname)
30538         [[ "$jobid_var_new" == "$new_value" ]] ||
30539                 error "'set_param a=b' failed on a value containing '='"
30540
30541         # Reset the $jobvarname to test the other format
30542         $LCTL set_param $jobvarname=$jobid_var_old
30543         jobid_var_new=$($LCTL get_param -n $jobvarname)
30544         [[ "$jobid_var_new" == "$jobid_var_old" ]] ||
30545                 error "failed to reset $jobvarname"
30546
30547         $LCTL set_param $jobvarname $new_value ||
30548                 error "'set_param a b' did not accept a value containing '='"
30549
30550         jobid_var_new=$($LCTL get_param -n $jobvarname)
30551         [[ "$jobid_var_new" == "$new_value" ]] ||
30552                 error "'set_param a b' failed on a value containing '='"
30553
30554         $LCTL set_param $jobvarname $jobid_var_old
30555         jobid_var_new=$($LCTL get_param -n $jobvarname)
30556         [[ "$jobid_var_new" == "$jobid_var_old" ]] ||
30557                 error "failed to reset $jobvarname"
30558 }
30559 run_test 401d "Verify 'lctl set_param' accepts values containing '='"
30560
30561 cleanup_401db() {
30562         local saved_val=$1
30563
30564         echo "start cleanup... "
30565         do_facet mgs $LCTL set_param -P at_min="$saved_val"
30566         wait_update $HOSTNAME "$LCTL get_param -n at_min" "$saved_val"
30567         echo "done"
30568 }
30569
30570 test_401db() { #LU-9544
30571         local new_val=6
30572
30573         local saved_val=$($LCTL get_param -n at_min)
30574
30575         stack_trap "cleanup_401db $saved_val"
30576
30577         do_facet mgs $LCTL set_param -P at_min=$new_val ||
30578                 error "failed to set at_min=$new_val"
30579
30580         wait_update $HOSTNAME "$LCTL get_param -n at_min" $new_val
30581         local expected=$($LCTL get_param -n at_min)
30582
30583         do_facet mgs $LCTL set_param -P -d at_min=$new_val ||
30584                 error "failed to delete at_min"
30585
30586         echo "Wait for erroneous changes"
30587         wait_update_cond $HOSTNAME "$LCTL get_param -n at_min" != $new_val
30588         local result=$($LCTL get_param -n at_min)
30589
30590         ! [[ "$result" =~ "=" ]] || {
30591                 echo "result:$result"
30592                 error "'lctl set_param -P -d a=b' added trailing '='"
30593         }
30594
30595         [[ $result == $expected ]] || {
30596                 echo -e "result:$result\nexpected:$expected"
30597                 error "'lctl set_param -P -d a=b' changed value of a"
30598         }
30599 }
30600 run_test 401db "Verify 'lctl set_param' does not add trailing '='"
30601
30602 test_401e() { # LU-14779
30603         $LCTL list_param -R "ldlm.namespaces.MGC*" ||
30604                 error "lctl list_param MGC* failed"
30605         $LCTL get_param "ldlm.namespaces.MGC*" || error "lctl get_param failed"
30606         $LCTL get_param "ldlm.namespaces.MGC*.lru_size" ||
30607                 error "lctl get_param lru_size failed"
30608 }
30609 run_test 401e "verify 'lctl get_param' works with NID in parameter"
30610
30611 test_401f() {
30612         $LCTL list_param -RpL "*" | while read path; do
30613                 [[ ! -L $path ]] ||
30614                         error "list_param -RpL returned the symlink: '$path'"
30615         done
30616 }
30617 run_test 401f "check 'lctl list_param' doesn't follow symlinks with --no-links"
30618
30619 test_401ga() {
30620         local paramdir=/etc/lustre
30621         local fsnamefile=$paramdir/mount.$FSNAME.params
30622         local clientfile=$paramdir/mount.client.params
30623
30624         local param1="osc.$FSNAME-OST0000-*.max_dirty_mb"
30625         local param2="at_max"
30626
30627         local value1_new value2_new
30628         local value1_old=$($LCTL get_param -n $param1)
30629         local value2_old=$($LCTL get_param -n $param2)
30630
30631         local value1_client=$(( value1_old - 1 ))
30632         local value1_fsname=$(( value1_old - 3 ))
30633         local value2_client=$(( value2_old - 10 ))
30634         local value2_fsname=$(( value2_old - 13 ))
30635
30636         stack_trap "$LCTL set_param $param1=$value1_old"
30637         stack_trap "$LCTL set_param $param2=$value2_old"
30638
30639         if [[ -e $fsnamefile ]]; then
30640                 mv $fsnamefile $fsnamefile.$TESTNAME
30641                 stack_trap "mv $fsnamefile.$TESTNAME $fsnamefile"
30642         else
30643                 stack_trap "rm -f $fsnamefile"
30644         fi
30645
30646         if [[ -e $clientfile ]]; then
30647                 mv $clientfile $clientfile.$TESTNAME
30648                 stack_trap "mv $clientfile.$TESTNAME $clientfile"
30649         else
30650                 stack_trap "rm -f $clientfile"
30651         fi
30652
30653         # do not allow bad params to be set
30654         $LCTL set_param --client $TESTNAME=$TESTNAME &&
30655                 error "set $TESTNAME as param in $clientfile" || true
30656
30657         # set garbage val to be overwritten
30658         $LCTL set_param --client $param1=$TESTNAME ||
30659                 error "failed to set $param1 in $clientfile"
30660
30661         $LCTL set_param --client $param1=$value1_client ||
30662                 error "failed to overwrite $param1 in $clientfile"
30663
30664         # nothing should be changed
30665         $LCTL set_param --client $param1=$value1_client ||
30666                 error "error setting duplicate param $param1 in $clientfile"
30667
30668         $LCTL set_param --client=$FSNAME $param1=$value1_fsname ||
30669                 error "failed to set $param1 in $fsnamefile"
30670
30671         $LCTL set_param --client=$FSNAME $param2=$value2_fsname &&
30672                 error "set $param2 in $fsnamefile without containing $FSNAME" ||
30673                 true
30674
30675         $LCTL set_param --client $TESTNAME= $param2=$value2_client || true
30676         grep -q "$param2=$value2_client" $clientfile ||
30677                 error "set_param -C did not continue after error"
30678
30679         remount_client $MOUNT
30680
30681         value1_new=$($LCTL get_param -n $param1)
30682         value2_new=$($LCTL get_param -n $param2)
30683
30684         [[ "$value1_new" == "$value1_client" ]] &&
30685                 error "$param1 not $value1_fsname, got client param $value1_new"
30686         [[ "$value1_new" == "$value1_fsname" ]] ||
30687                 error "$param1 not $FSNAME param $value1_fsname, got $value1_new"
30688         [[ "$value2_new" == "$value2_client" ]] ||
30689                 error "$param2 not client param $value2_client, got $value2_new"
30690 }
30691 run_test 401ga "check 'set_param -C' sets params upon mount"
30692
30693 test_401gb() {
30694         local paramdir=/etc/lustre
30695         local fsnamefile=$paramdir/mount.$FSNAME.params
30696         local clientfile=$paramdir/mount.client.params
30697
30698         local param1="osc.$FSNAME-OST0000-*.max_dirty_mb"
30699         local param2="at_max"
30700
30701         local value1_new value2_new
30702         local value1_old=$($LCTL get_param -n $param1)
30703         local value2_old=$($LCTL get_param -n $param2)
30704
30705         local value1_client=$(( value1_old - 1 ))
30706         local value1_fsname=$(( value1_old - 3 ))
30707         local value2_client=$(( value2_old - 10 ))
30708
30709         stack_trap "$LCTL set_param $param1=$value1_old"
30710         stack_trap "$LCTL set_param $param2=$value2_old"
30711
30712         if [[ -e $fsnamefile ]]; then
30713                 mv $fsnamefile $fsnamefile.$TESTNAME
30714                 stack_trap "mv $fsnamefile.$TESTNAME $fsnamefile"
30715         else
30716                 stack_trap "rm $fsnamefile"
30717         fi
30718
30719         if [[ -e $clientfile ]]; then
30720                 mv $clientfile $clientfile.$TESTNAME
30721                 stack_trap "mv $clientfile.$TESTNAME $clientfile"
30722         else
30723                 stack_trap "rm $clientfile"
30724         fi
30725
30726         $LCTL set_param --client $param1=$value1_client $param2=$value2_client
30727         $LCTL set_param --client=$FSNAME $param1=$value1_fsname
30728
30729         $LCTL set_param -d --client $TESTNAME=$TESTNAME ||
30730                 error "error deleting bad param $TESTNAME from $clientfile"
30731
30732         $LCTL set_param -d --client $param2 ||
30733                 error "error deleting $param2 from $clientfile"
30734
30735         $LCTL set_param -d --client=$FSNAME $param1 $param2 ||
30736                 error "error deleting $param1 and $param2 from $fsnamefile"
30737
30738         remount_client $MOUNT
30739
30740         value1_new=$($LCTL get_param -n $param1)
30741         value2_new=$($LCTL get_param -n $param2)
30742
30743         [[ "$value1_new" == "$value1_fsname" ]] &&
30744                 error "$param1 not $value1_client, got $FSNAME param $value1_new"
30745         [[ "$value1_new" == "$value1_client" ]] ||
30746                 error "$param1 not client param $value1_client, got $value1_new"
30747         [[ "$value2_new" == "$value2_old" ]] ||
30748                 error "$param2 not $value2_old, got $value2_new"
30749 }
30750 run_test 401gb "check 'set_param -d -C' removes client params"
30751
30752 test_402() {
30753         [[ $MDS1_VERSION -ge $(version_code 2.7.66) ]] ||
30754         [[ $MDS1_VERSION -ge $(version_code 2.7.18.4) &&
30755                 $MDS1_VERSION -lt $(version_code 2.7.50) ]] ||
30756         [[ $MDS1_VERSION -ge $(version_code 2.7.2) &&
30757                 $MDS1_VERSION -lt $(version_code 2.7.11) ]] ||
30758                 skip "Need MDS version 2.7.2+ or 2.7.18.4+ or 2.7.66+"
30759         remote_mds_nodsh && skip "remote MDS with nodsh"
30760
30761         $LFS setdirstripe -i 0 $DIR/$tdir || error "setdirstripe -i 0 failed"
30762 #define OBD_FAIL_MDS_FLD_LOOKUP 0x15c
30763         do_facet mds1 "lctl set_param fail_loc=0x8000015c"
30764         touch $DIR/$tdir/$tfile && error "touch should fail with ENOENT" ||
30765                 echo "Touch failed - OK"
30766 }
30767 run_test 402 "Return ENOENT to lod_generate_and_set_lovea"
30768
30769 test_403() {
30770         local file1=$DIR/$tfile.1
30771         local file2=$DIR/$tfile.2
30772         local tfile=$TMP/$tfile
30773
30774         rm -f $file1 $file2 $tfile
30775
30776         touch $file1
30777         ln $file1 $file2
30778
30779         # 30 sec OBD_TIMEOUT in ll_getattr()
30780         # right before populating st_nlink
30781         $LCTL set_param fail_loc=0x80001409
30782         stat -c %h $file1 > $tfile &
30783
30784         # create an alias, drop all locks and reclaim the dentry
30785         < $file2
30786         cancel_lru_locks mdc
30787         cancel_lru_locks osc
30788         sysctl -w vm.drop_caches=2
30789
30790         wait
30791
30792         [ $(cat $tfile) -gt 0 ] || error "wrong nlink count: $(cat $tfile)"
30793
30794         rm -f $tfile $file1 $file2
30795 }
30796 run_test 403 "i_nlink should not drop to zero due to aliasing"
30797
30798 test_404() { # LU-6601
30799         [[ $MDS1_VERSION -ge $(version_code 2.8.53) ]] ||
30800                 skip "Need server version newer than 2.8.52"
30801         remote_mds_nodsh && skip "remote MDS with nodsh"
30802
30803         local mosps=$(do_facet $SINGLEMDS $LCTL dl |
30804                 awk '/osp .*-osc-MDT/ { print $4}')
30805
30806         local osp
30807         for osp in $mosps; do
30808                 echo "Deactivate: " $osp
30809                 do_facet $SINGLEMDS $LCTL --device %$osp deactivate
30810                 local stat=$(do_facet $SINGLEMDS $LCTL dl |
30811                         awk -vp=$osp '$4 == p { print $2 }')
30812                 [ $stat = IN ] || {
30813                         do_facet $SINGLEMDS $LCTL dl | grep -w $osp
30814                         error "deactivate error"
30815                 }
30816                 echo "Activate: " $osp
30817                 do_facet $SINGLEMDS $LCTL --device %$osp activate
30818                 local stat=$(do_facet $SINGLEMDS $LCTL dl |
30819                         awk -vp=$osp '$4 == p { print $2 }')
30820                 [ $stat = UP ] || {
30821                         do_facet $SINGLEMDS $LCTL dl | grep -w $osp
30822                         error "activate error"
30823                 }
30824         done
30825 }
30826 run_test 404 "validate manual {de}activated works properly for OSPs"
30827
30828 test_405() {
30829         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
30830         [ $MDS1_VERSION -lt $(version_code 2.6.92) ] ||
30831                 [ $CLIENT_VERSION -lt $(version_code 2.6.99) ] &&
30832                         skip "Layout swap lock is not supported"
30833
30834         check_swap_layouts_support
30835         check_swap_layout_no_dom $DIR
30836
30837         test_mkdir $DIR/$tdir
30838         swap_lock_test -d $DIR/$tdir ||
30839                 error "One layout swap locked test failed"
30840 }
30841 run_test 405 "Various layout swap lock tests"
30842
30843 test_406() {
30844         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
30845         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
30846         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
30847         [ $PARALLEL == "yes" ] && skip "skip parallel run"
30848         [ $MDS1_VERSION -lt $(version_code 2.8.50) ] &&
30849                 skip "Need MDS version at least 2.8.50"
30850
30851         local def_stripe_size=$($LFS getstripe -S $MOUNT)
30852         local test_pool=$TESTNAME
30853
30854         pool_add $test_pool || error "pool_add failed"
30855         pool_add_targets $test_pool 0 $(($OSTCOUNT - 1)) 1 ||
30856                 error "pool_add_targets failed"
30857
30858         save_layout_restore_at_exit $MOUNT
30859
30860         # parent set default stripe count only, child will stripe from both
30861         # parent and fs default
30862         $LFS setstripe -c 1 -i 1 -S $((def_stripe_size * 2)) -p $test_pool $MOUNT ||
30863                 error "setstripe $MOUNT failed"
30864         $LFS mkdir -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
30865         $LFS setstripe -c $OSTCOUNT $DIR/$tdir || error "setstripe $tdir failed"
30866         for i in $(seq 10); do
30867                 local f=$DIR/$tdir/$tfile.$i
30868                 touch $f || error "touch failed"
30869                 local count=$($LFS getstripe -c $f)
30870                 [ $count -eq $OSTCOUNT ] ||
30871                         error "$f stripe count $count != $OSTCOUNT"
30872                 local offset=$($LFS getstripe -i $f)
30873                 [ $offset -eq 1 ] || error "$f stripe offset $offset != 1"
30874                 local size=$($LFS getstripe -S $f)
30875                 [ $size -eq $((def_stripe_size * 2)) ] ||
30876                         error "$f stripe size $size != $((def_stripe_size * 2))"
30877                 local pool=$($LFS getstripe -p $f)
30878                 [ $pool == $test_pool ] || error "$f pool $pool != $test_pool"
30879         done
30880
30881         # change fs default striping, delete parent default striping, now child
30882         # will stripe from new fs default striping only
30883         $LFS setstripe -c 1 -S $def_stripe_size -i 0 $MOUNT ||
30884                 error "change $MOUNT default stripe failed"
30885         $LFS setstripe -c 0 $DIR/$tdir ||
30886                 error "delete $tdir default stripe failed"
30887         for i in $(seq 11 20); do
30888                 local f=$DIR/$tdir/$tfile.$i
30889                 touch $f || error "touch $f failed"
30890                 local count=$($LFS getstripe -c $f)
30891                 [ $count -eq 1 ] || error "$f stripe count $count != 1"
30892                 local offset=$($LFS getstripe -i $f)
30893                 [ $offset -eq 0 ] || error "$f stripe offset $offset != 0"
30894                 local size=$($LFS getstripe -S $f)
30895                 [ $size -eq $def_stripe_size ] ||
30896                         error "$f stripe size $size != $def_stripe_size"
30897                 local pool=$($LFS getstripe -p $f)
30898                 [ $pool == $test_pool ] || error "$f pool $pool isn't set"
30899         done
30900
30901         unlinkmany $DIR/$tdir/$tfile. 1 20
30902
30903         local f=$DIR/$tdir/$tfile
30904         pool_remove_all_targets $test_pool $f
30905         pool_remove $test_pool $f
30906 }
30907 run_test 406 "DNE support fs default striping"
30908
30909 test_407() {
30910         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
30911         [[ $MDS1_VERSION -lt $(version_code 2.8.55) ]] &&
30912                 skip "Need MDS version at least 2.8.55"
30913         remote_mds_nodsh && skip "remote MDS with nodsh"
30914
30915         $LFS mkdir -i 0 -c 1 $DIR/$tdir.0 ||
30916                 error "$LFS mkdir -i 0 -c 1 $tdir.0 failed"
30917         $LFS mkdir -i 1 -c 1 $DIR/$tdir.1 ||
30918                 error "$LFS mkdir -i 1 -c 1 $tdir.1 failed"
30919         touch $DIR/$tdir.0/$tfile.0 || error "touch $tdir.0/$tfile.0 failed"
30920
30921         #define OBD_FAIL_DT_TXN_STOP    0x2019
30922         for idx in $(seq $MDSCOUNT); do
30923                 do_facet mds$idx "lctl set_param fail_loc=0x2019"
30924         done
30925         $LFS mkdir -c 2 $DIR/$tdir && error "$LFS mkdir -c 2 $tdir should fail"
30926         mv $DIR/$tdir.0/$tfile.0 $DIR/$tdir.1/$tfile.1 &&
30927                 error "mv $tdir.0/$tfile.0 $tdir.1/$tfile.1 should fail"
30928         true
30929 }
30930 run_test 407 "transaction fail should cause operation fail"
30931
30932 test_408() {
30933         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1 oflag=direct
30934
30935         #define OBD_FAIL_OSC_BRW_PREP_REQ2        0x40a
30936         lctl set_param fail_loc=0x8000040a
30937         # let ll_prepare_partial_page() fail
30938         dd if=/dev/zero of=$DIR/$tfile bs=2048 count=1 conv=notrunc || true
30939
30940         rm -f $DIR/$tfile
30941
30942         # create at least 100 unused inodes so that
30943         # shrink_icache_memory(0) should not return 0
30944         touch $DIR/$tfile-{0..100}
30945         rm -f $DIR/$tfile-{0..100}
30946         sync
30947
30948         echo 2 > /proc/sys/vm/drop_caches
30949 }
30950 run_test 408 "drop_caches should not hang due to page leaks"
30951
30952 test_409()
30953 {
30954         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
30955
30956         mkdir -p $DIR/$tdir || error "(0) Fail to mkdir"
30957         $LFS mkdir -i 1 -c 2 $DIR/$tdir/foo || error "(1) Fail to mkdir"
30958         touch $DIR/$tdir/guard || error "(2) Fail to create"
30959
30960         local PREFIX=$(str_repeat 'A' 128)
30961         echo "Create 1K hard links start at $(date)"
30962         createmany -l $DIR/$tdir/guard $DIR/$tdir/foo/${PREFIX}_ 1000 ||
30963                 error "(3) Fail to hard link"
30964
30965         echo "Links count should be right although linkEA overflow"
30966         stat $DIR/$tdir/guard || error "(4) Fail to stat"
30967         local linkcount=$(stat --format=%h $DIR/$tdir/guard)
30968         [ $linkcount -eq 1001 ] ||
30969                 error "(5) Unexpected hard links count: $linkcount"
30970
30971         echo "List all links start at $(date)"
30972         ls -l $DIR/$tdir/foo > /dev/null ||
30973                 error "(6) Fail to list $DIR/$tdir/foo"
30974
30975         echo "Unlink hard links start at $(date)"
30976         unlinkmany $DIR/$tdir/foo/${PREFIX}_ 1000 ||
30977                 error "(7) Fail to unlink"
30978         echo "Unlink hard links finished at $(date)"
30979 }
30980 run_test 409 "Large amount of cross-MDTs hard links on the same file"
30981
30982 test_410()
30983 {
30984         [[ $CLIENT_VERSION -lt $(version_code 2.9.59) ]] &&
30985                 skip "Need client version at least 2.9.59"
30986
30987         # Create a file, and stat it from the kernel
30988         local testfile=$DIR/$tfile
30989         touch $testfile
30990
30991         local run_id=$RANDOM
30992         local my_ino=$(stat --format "%i" $testfile)
30993
30994         # Try to insert the module.
30995         load_module kunit/kinode run_id=$run_id fname=$testfile ||
30996                 error "load_module failed"
30997
30998         # Anything but success is a test failure
30999         dmesg | grep -q \
31000             "lustre_kinode_$run_id: inode numbers are identical: $my_ino" ||
31001             error "no inode match"
31002
31003         # Remove the test module
31004         rmmod -v kinode ||
31005                 error "rmmod failed (may trigger a failure in a later test)"
31006 }
31007 run_test 410 "Test inode number returned from kernel thread"
31008
31009 cleanup_test411_cgroup() {
31010         trap 0
31011         cat $1/memory.stat
31012         rmdir "$1"
31013 }
31014
31015 test_411a() {
31016         local cg_basedir=/sys/fs/cgroup/memory
31017         # LU-9966
31018         test -f "$cg_basedir/memory.kmem.limit_in_bytes" ||
31019                 skip "no setup for cgroup"
31020
31021         dd if=/dev/zero of=$DIR/$tfile bs=1M count=100 conv=fsync ||
31022                 error "test file creation failed"
31023         cancel_lru_locks osc
31024
31025         # Create a very small memory cgroup to force a slab allocation error
31026         local cgdir=$cg_basedir/osc_slab_alloc
31027         mkdir $cgdir || error "cgroup mkdir '$cgdir' failed"
31028         trap "cleanup_test411_cgroup $cgdir" EXIT
31029         echo 2M > $cgdir/memory.kmem.limit_in_bytes
31030         echo 1M > $cgdir/memory.limit_in_bytes
31031
31032         # Should not LBUG, just be killed by oom-killer
31033         # dd will return 0 even allocation failure in some environment.
31034         # So don't check return value
31035         bash -c "echo \$$ > $cgdir/tasks && dd if=$DIR/$tfile of=/dev/null"
31036         cleanup_test411_cgroup $cgdir
31037
31038         return 0
31039 }
31040 run_test 411a "Slab allocation error with cgroup does not LBUG"
31041
31042 test_411b() {
31043         local cg_basedir=/sys/fs/cgroup/memory
31044         # LU-9966
31045         [ -e "$cg_basedir/memory.kmem.limit_in_bytes" ] ||
31046                 skip "no setup for cgroup"
31047
31048         local count=2
31049
31050         (( OSTCOUNT < 2 )) && count=$OSTCOUNT
31051         $LFS setstripe -c $count $DIR/$tfile || error "unable to setstripe"
31052
31053         # To avoid testing failures on x86 and arm, we set the memcg limit
31054         # with 1024M on both systems.
31055         local memlimit_mb=1024
31056         local min_size_ost=$($LFS df | awk "/$FSNAME-OST/ { print \$4 }" |
31057                              sort -un | head -1)
31058
31059         (( memlimit_mb * 4 * 1024 < min_size_ost * count - 100 )) ||
31060                 skip "OST space are too small: ${min_size_ost}K"
31061
31062         echo "count=$count/$OSTCOUNT min_size_ost=${min_size_ost}K"
31063         $LFS df
31064
31065         # Create a cgroup and set memory limit
31066         # (tfile is used as an easy way to get a recognizable cgroup name)
31067         local cgdir=$cg_basedir/$tfile
31068         mkdir $cgdir || error "cgroup mkdir '$cgdir' failed"
31069         stack_trap "cleanup_test411_cgroup $cgdir" EXIT
31070         echo $((memlimit_mb * 1024 * 1024)) > $cgdir/memory.limit_in_bytes
31071
31072         echo "writing first file"
31073         # Write a file 4x the memory limit in size
31074         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile bs=1M count=$((memlimit_mb * 4))" ||
31075                 error "(1) failed to write successfully"
31076
31077         sync
31078         cancel_lru_locks osc
31079
31080         rm -f $DIR/$tfile
31081         $LFS setstripe -c $count $DIR/$tfile || error "unable to setstripe"
31082
31083         # Try writing at a larger block size
31084         # NB: if block size is >= 1/2 cgroup size, we sometimes get OOM killed
31085         # so test with 1/4 cgroup size (this seems reasonable to me - we do
31086         # need *some* memory to do IO in)
31087         echo "writing at larger block size"
31088         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile bs=64M count=$((memlimit_mb * 4 / 128))" ||
31089                 error "(3) failed to write successfully"
31090
31091         sync
31092         cancel_lru_locks osc
31093         rm -f $DIR/$tfile
31094
31095         $LFS setstripe -c $count $DIR/$tfile.{1..4} || error "unable to setstripe"
31096
31097         # Try writing multiple files at once
31098         (( memlimit_mb * 4 * 1024 * 2 < min_size_ost * count - 100 )) ||
31099                 skip "OST space are too small: ${min_size_ost}K"
31100
31101         echo "writing multiple files"
31102         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.1 bs=32M count=$((memlimit_mb * 4 / 64))" &
31103         local pid1=$!
31104         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.2 bs=32M count=$((memlimit_mb * 4 / 64))" &
31105         local pid2=$!
31106         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.3 bs=32M count=$((memlimit_mb * 4 / 64))" &
31107         local pid3=$!
31108         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.4 bs=32M count=$((memlimit_mb * 4 / 64))" &
31109         local pid4=$!
31110
31111         wait $pid1
31112         local rc1=$?
31113         wait $pid2
31114         local rc2=$?
31115         wait $pid3
31116         local rc3=$?
31117         wait $pid4
31118         local rc4=$?
31119         if (( rc1 != 0)); then
31120                 error "error $rc1 writing to file from $pid1"
31121         fi
31122         if (( rc2 != 0)); then
31123                 error "error $rc2 writing to file from $pid2"
31124         fi
31125         if (( rc3 != 0)); then
31126                 error "error $rc3 writing to file from $pid3"
31127         fi
31128         if (( rc4 != 0)); then
31129                 error "error $rc4 writing to file from $pid4"
31130         fi
31131
31132         sync
31133         cancel_lru_locks osc
31134
31135         # These files can be large-ish (~1 GiB total), so delete them rather
31136         # than leave for later cleanup
31137         rm -f $DIR/$tfile.*
31138         return 0
31139 }
31140 run_test 411b "confirm Lustre can avoid OOM with reasonable cgroups limits"
31141
31142 test_412() {
31143         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
31144         (( $MDS1_VERSION >= $(version_code 2.10.55) )) ||
31145                 skip "Need server version at least 2.10.55"
31146
31147         $LFS mkdir -i $((MDSCOUNT - 1)),$((MDSCOUNT - 2)) $DIR/$tdir ||
31148                 error "mkdir failed"
31149         $LFS getdirstripe $DIR/$tdir
31150         local stripe_index=$($LFS getdirstripe -i $DIR/$tdir)
31151         [ $stripe_index -eq $((MDSCOUNT - 1)) ] ||
31152                 error "expect $((MDSCOUT - 1)) get $stripe_index"
31153         local stripe_count=$($LFS getdirstripe -T $DIR/$tdir)
31154         [ $stripe_count -eq 2 ] ||
31155                 error "expect 2 get $stripe_count"
31156
31157         (( $MDS1_VERSION >= $(version_code 2.14.55) )) || return 0
31158
31159         local index
31160         local index2
31161
31162         # subdirs should be on the same MDT as parent
31163         for i in $(seq 0 $((MDSCOUNT - 1))); do
31164                 $LFS mkdir -i $i $DIR/$tdir/mdt$i || error "mkdir mdt$i failed"
31165                 mkdir $DIR/$tdir/mdt$i/sub || error "mkdir sub failed"
31166                 index=$($LFS getstripe -m $DIR/$tdir/mdt$i/sub)
31167                 (( index == i )) || error "mdt$i/sub on MDT$index"
31168         done
31169
31170         # stripe offset -1, ditto
31171         for i in {1..10}; do
31172                 $LFS mkdir -i -1 $DIR/$tdir/qos$i || error "mkdir qos$i failed"
31173                 index=$($LFS getstripe -m $DIR/$tdir/qos$i)
31174                 mkdir $DIR/$tdir/qos$i/sub || error "mkdir sub failed"
31175                 index2=$($LFS getstripe -m $DIR/$tdir/qos$i/sub)
31176                 (( index == index2 )) ||
31177                         error "qos$i on MDT$index, sub on MDT$index2"
31178         done
31179
31180         local testdir=$DIR/$tdir/inherit
31181
31182         $LFS mkdir -i 1 --max-inherit=3 $testdir || error "mkdir inherit failed"
31183         # inherit 2 levels
31184         for i in 1 2; do
31185                 testdir=$testdir/s$i
31186                 mkdir $testdir || error "mkdir $testdir failed"
31187                 index=$($LFS getstripe -m $testdir)
31188                 (( index == 1 )) ||
31189                         error "$testdir on MDT$index"
31190         done
31191
31192         # not inherit any more
31193         testdir=$testdir/s3
31194         mkdir $testdir || error "mkdir $testdir failed"
31195         getfattr -d -m dmv $testdir | grep dmv &&
31196                 error "default LMV set on $testdir" || true
31197 }
31198 run_test 412 "mkdir on specific MDTs"
31199
31200 TEST413_COUNT=${TEST413_COUNT:-200}
31201
31202 #
31203 # set_maxage() is used by test_413 only.
31204 # This is a helper function to set maxage. Does not return any value.
31205 # Input: maxage to set
31206 #
31207 set_maxage() {
31208         local lmv_qos_maxage
31209         local lod_qos_maxage
31210         local new_maxage=$1
31211
31212         lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
31213         $LCTL set_param lmv.*.qos_maxage=$new_maxage
31214         stack_trap "$LCTL set_param \
31215                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null"
31216         lod_qos_maxage=$(do_facet mds1 $LCTL get_param -n \
31217                 lod.$FSNAME-MDT0000-mdtlov.qos_maxage | awk '{ print $1 }')
31218         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
31219                 lod.*.mdt_qos_maxage=$new_maxage
31220         stack_trap "do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
31221                 lod.*.mdt_qos_maxage=$lod_qos_maxage > /dev/null"
31222 }
31223
31224 generate_uneven_mdts() {
31225         local threshold=$1
31226         local ffree
31227         local bavail
31228         local max
31229         local min
31230         local max_index
31231         local min_index
31232         local tmp
31233         local i
31234
31235         echo
31236         echo "Check for uneven MDTs: "
31237
31238         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
31239         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
31240         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
31241
31242         max=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
31243         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
31244         max_index=0
31245         min_index=0
31246         for ((i = 1; i < ${#ffree[@]}; i++)); do
31247                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
31248                 if [ $tmp -gt $max ]; then
31249                         max=$tmp
31250                         max_index=$i
31251                 fi
31252                 if [ $tmp -lt $min ]; then
31253                         min=$tmp
31254                         min_index=$i
31255                 fi
31256         done
31257
31258         (( min > 0 )) || skip "low space on MDT$min_index"
31259         (( ${ffree[min_index]} > 0 )) ||
31260                 skip "no free files on MDT$min_index"
31261         (( ${ffree[min_index]} < 10000000 )) ||
31262                 skip "too many free files on MDT$min_index"
31263
31264         # Check if we need to generate uneven MDTs
31265         local diff=$(((max - min) * 100 / min))
31266         local testdirp=$DIR/$tdir-fillmdt # parent fill folder
31267         local testdir # individual folder within $testdirp
31268         local start
31269         local cmd
31270
31271         # fallocate is faster to consume space on MDT, if available
31272         if check_fallocate_supported mds$((min_index + 1)); then
31273                 cmd="fallocate -l 128K "
31274         else
31275                 cmd="$DD bs=128K count=1 of="
31276         fi
31277
31278         echo "using cmd $cmd"
31279         for (( i = 0; diff < threshold; i++ )); do
31280                 testdir=${testdirp}/$i
31281                 [ -d $testdir ] && continue
31282
31283                 (( i % 10 > 0 )) || { $LFS df; $LFS df -i; }
31284
31285                 mkdir -p $testdirp
31286                 # generate uneven MDTs, create till $threshold% diff
31287                 echo -n "weight diff=$diff% must be > $threshold% ..."
31288                 echo "Fill MDT$min_index with $TEST413_COUNT files: loop $i"
31289                 $LFS mkdir -i $min_index $testdir ||
31290                         error "mkdir $testdir failed"
31291                 $LFS setstripe -E 1M -L mdt $testdir ||
31292                         error "setstripe $testdir failed"
31293                 start=$SECONDS
31294                 for (( f = 0; f < TEST413_COUNT; f++ )); do
31295                         $cmd$testdir/f.$f || error "$cmd$testdir $f failed"
31296                 done
31297                 sync; sleep 1; sync
31298
31299                 # wait for QOS to update
31300                 (( SECONDS < start + 2 )) && sleep $((start + 2 - SECONDS))
31301
31302                 ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-*.filesfree))
31303                 bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-*.kbytesavail))
31304                 max=$(((${ffree[max_index]} >> 8) *
31305                         (${bavail[max_index]} * bsize >> 16)))
31306                 min=$(((${ffree[min_index]} >> 8) *
31307                         (${bavail[min_index]} * bsize >> 16)))
31308                 (( min > 0 )) || skip "low space on MDT$min_index"
31309                 diff=$(((max - min) * 100 / min))
31310         done
31311
31312         echo "MDT filesfree available: ${ffree[*]}"
31313         echo "MDT blocks available: ${bavail[*]}"
31314         echo "weight diff=$diff%"
31315 }
31316
31317 test_qos_mkdir() {
31318         local mkdir_cmd=$1
31319         local stripe_count=$2
31320         local mdts=$(comma_list $(mdts_nodes))
31321
31322         local testdir
31323         local lmv_qos_prio_free
31324         local lmv_qos_threshold_rr
31325         local lod_qos_prio_free
31326         local lod_qos_threshold_rr
31327         local total
31328         local count
31329         local i
31330
31331         # @total is total directories created if it's testing plain
31332         # directories, otherwise it's total stripe object count for
31333         # striped directories test.
31334         # remote/striped directory unlinking is slow on zfs and may
31335         # timeout, test with fewer directories
31336         [ "$mds1_FSTYPE" = "zfs" ] && total=120 || total=240
31337
31338         lmv_qos_prio_free=$($LCTL get_param -n lmv.*.qos_prio_free | head -n1)
31339         lmv_qos_prio_free=${lmv_qos_prio_free%%%}
31340         lmv_qos_threshold_rr=$($LCTL get_param -n lmv.*.qos_threshold_rr |
31341                 head -n1)
31342         lmv_qos_threshold_rr=${lmv_qos_threshold_rr%%%}
31343         stack_trap "$LCTL set_param \
31344                 lmv.*.qos_prio_free=$lmv_qos_prio_free > /dev/null"
31345         stack_trap "$LCTL set_param \
31346                 lmv.*.qos_threshold_rr=$lmv_qos_threshold_rr > /dev/null"
31347
31348         lod_qos_prio_free=$(do_facet mds1 $LCTL get_param -n \
31349                 lod.$FSNAME-MDT0000-mdtlov.mdt_qos_prio_free | head -n1)
31350         lod_qos_prio_free=${lod_qos_prio_free%%%}
31351         lod_qos_threshold_rr=$(do_facet mds1 $LCTL get_param -n \
31352                 lod.$FSNAME-MDT0000-mdtlov.mdt_qos_threshold_rr | head -n1)
31353         lod_qos_threshold_rr=${lod_qos_threshold_rr%%%}
31354         stack_trap "do_nodes $mdts $LCTL set_param \
31355                 lod.*.mdt_qos_prio_free=$lod_qos_prio_free > /dev/null"
31356         stack_trap "do_nodes $mdts $LCTL set_param \
31357                 lod.*.mdt_qos_threshold_rr=$lod_qos_threshold_rr > /dev/null"
31358
31359         # decrease statfs age, so that it can be updated in time
31360         $LCTL set_param lmv.*.qos_maxage=1 > /dev/null
31361         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_maxage=1 > /dev/null
31362
31363         $LCTL set_param lmv.*.qos_threshold_rr=100 > /dev/null
31364         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_threshold_rr=100 > /dev/null
31365
31366         testdir=$DIR/$tdir-s$stripe_count/rr
31367
31368         local stripe_index=$($LFS getstripe -m $testdir)
31369         local test_mkdir_rr=true
31370
31371         getfattr -d -m dmv -e hex $testdir | grep dmv
31372         if (( $? == 0 && $MDS1_VERSION >= $(version_code 2.14.51) )); then
31373                 echo "defstripe: '$($LFS getdirstripe -D $testdir)'"
31374                 (( $($LFS getdirstripe -D --max-inherit-rr $testdir) == 0 )) &&
31375                         test_mkdir_rr=false
31376         fi
31377
31378         echo
31379         $test_mkdir_rr &&
31380                 echo "Mkdir (stripe_count $stripe_count) roundrobin:" ||
31381                 echo "Mkdir (stripe_count $stripe_count) on stripe $stripe_index"
31382
31383         stack_trap "unlinkmany -d $testdir/subdir $((total / stripe_count))"
31384         for (( i = 0; i < total / stripe_count; i++ )); do
31385                 eval $mkdir_cmd $testdir/subdir$i ||
31386                         error "$mkdir_cmd subdir$i failed"
31387         done
31388
31389         for (( i = 0; i < $MDSCOUNT; i++ )); do
31390                 count=$($LFS getdirstripe -i $testdir/* | grep -c "^$i$")
31391                 echo "$count directories created on MDT$i"
31392                 if $test_mkdir_rr; then
31393                         (( count == total / stripe_count / MDSCOUNT )) ||
31394                                 error "subdirs are not evenly distributed"
31395                 elif (( i == stripe_index )); then
31396                         (( count == total / stripe_count )) ||
31397                                 error "$count subdirs created on MDT$i"
31398                 else
31399                         (( count == 0 )) ||
31400                                 error "$count subdirs created on MDT$i"
31401                 fi
31402
31403                 if $test_mkdir_rr && [ $stripe_count -gt 1 ]; then
31404                         count=$($LFS getdirstripe $testdir/* |
31405                                 grep -c -P "^\s+$i\t")
31406                         echo "$count stripes created on MDT$i"
31407                         # deviation should < 5% of average
31408                         delta=$((count - total / MDSCOUNT))
31409                         (( ${delta#-} <= total / MDSCOUNT / 20 )) ||
31410                                 error "stripes are not evenly distributed"
31411                 fi
31412         done
31413
31414         echo
31415         echo "Check for uneven MDTs: "
31416
31417         local ffree
31418         local bavail
31419         local max
31420         local min
31421         local max_index
31422         local min_index
31423         local tmp
31424
31425         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
31426         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
31427         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
31428
31429         max=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
31430         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
31431         max_index=0
31432         min_index=0
31433         for ((i = 1; i < ${#ffree[@]}; i++)); do
31434                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
31435                 if [ $tmp -gt $max ]; then
31436                         max=$tmp
31437                         max_index=$i
31438                 fi
31439                 if [ $tmp -lt $min ]; then
31440                         min=$tmp
31441                         min_index=$i
31442                 fi
31443         done
31444         echo "stripe_count=$stripe_count min_idx=$min_index max_idx=$max_index"
31445
31446         (( min > 0 )) || skip "low space on MDT$min_index"
31447         (( ${ffree[min_index]} < 10000000 )) ||
31448                 skip "too many free files on MDT$min_index"
31449
31450         generate_uneven_mdts 120
31451
31452         echo "MDT filesfree available: ${ffree[*]}"
31453         echo "MDT blocks available: ${bavail[*]}"
31454         echo "weight diff=$(((max - min) * 100 / min))%"
31455         echo
31456         echo "Mkdir (stripe_count $stripe_count) with balanced space usage:"
31457
31458         $LCTL set_param lmv.*.qos_threshold_rr=0 > /dev/null
31459         $LCTL set_param lmv.*.qos_prio_free=100 > /dev/null
31460         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_threshold_rr=0 > /dev/null
31461         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_prio_free=100 > /dev/null
31462
31463         sleep 1
31464
31465         testdir=$DIR/$tdir-s$stripe_count/qos
31466
31467         stack_trap "unlinkmany -d $testdir/subdir $((total / stripe_count))"
31468         for (( i = 0; i < total / stripe_count; i++ )); do
31469                 eval $mkdir_cmd $testdir/subdir$i ||
31470                         error "$mkdir_cmd subdir$i failed"
31471         done
31472
31473         max=0
31474         for (( i = 0; i < $MDSCOUNT; i++ )); do
31475                 count=$($LFS getdirstripe -i $testdir/* | grep -c "^$i$")
31476                 (( count > max )) && max=$count
31477                 echo "$count directories created on MDT$i : curmax=$max"
31478         done
31479
31480         min=$($LFS getdirstripe -i $testdir/* | grep -c "^$min_index$")
31481
31482         # D-value should > 10% of average
31483         (( max - min > total / stripe_count / MDSCOUNT / 10 )) ||
31484                 error "subdirs shouldn't be evenly distributed: $max - $min <= $((total / stripe_count / MDSCOUNT / 10))"
31485
31486         # ditto for stripes
31487         if (( stripe_count > 1 )); then
31488                 max=0
31489                 for (( i = 0; i < $MDSCOUNT; i++ )); do
31490                         count=$($LFS getdirstripe $testdir/* |
31491                                 grep -c -P "^\s+$i\t")
31492                         (( count > max )) && max=$count
31493                         echo "$count stripes created on MDT$i"
31494                 done
31495
31496                 min=$($LFS getdirstripe $testdir/* |
31497                         grep -c -P "^\s+$min_index\t")
31498                 (( max - min > total / MDSCOUNT / 10 )) ||
31499                         error "stripes shouldn't be evenly distributed: $max - $min <= $((total / MDSCOUNT / 10))"
31500         fi
31501 }
31502
31503 most_full_mdt() {
31504         local ffree
31505         local bavail
31506         local bsize
31507         local min
31508         local min_index
31509         local tmp
31510
31511         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
31512         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
31513         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
31514
31515         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
31516         min_index=0
31517         for ((i = 1; i < ${#ffree[@]}; i++)); do
31518                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
31519                 (( tmp < min )) && min=$tmp && min_index=$i
31520         done
31521
31522         echo -n $min_index
31523 }
31524
31525 test_413a() {
31526         [ $MDSCOUNT -lt 2 ] &&
31527                 skip "We need at least 2 MDTs for this test"
31528
31529         [ $MDS1_VERSION -lt $(version_code 2.12.52) ] &&
31530                 skip "Need server version at least 2.12.52"
31531
31532         local stripe_max=$((MDSCOUNT - 1))
31533         local stripe_count
31534
31535         # let caller set maxage for latest result
31536         set_maxage 1
31537
31538         # fill MDT unevenly
31539         generate_uneven_mdts 120
31540
31541         # test 4-stripe directory at most, otherwise it's too slow
31542         # We are being very defensive. Although Autotest uses 4 MDTs.
31543         # We make sure stripe_max does not go over 4.
31544         (( stripe_max > 4 )) && stripe_max=4
31545         # unlinking striped directory is slow on zfs, and may timeout, only test
31546         # plain directory
31547         [ "$mds1_FSTYPE" == "zfs" ] && stripe_max=1
31548         for stripe_count in $(seq 1 $stripe_max); do
31549                 mkdir $DIR/$tdir-s$stripe_count || error "mkdir failed"
31550                 mkdir $DIR/$tdir-s$stripe_count/rr || error "mkdir failed"
31551                 $LFS mkdir -i $(most_full_mdt) $DIR/$tdir-s$stripe_count/qos ||
31552                         error "mkdir failed"
31553                 test_qos_mkdir "$LFS mkdir -i -1 -c $stripe_count" $stripe_count
31554         done
31555 }
31556 run_test 413a "QoS mkdir with 'lfs mkdir -i -1'"
31557
31558 test_413b() {
31559         [ $MDSCOUNT -lt 2 ] &&
31560                 skip "We need at least 2 MDTs for this test"
31561
31562         [ $MDS1_VERSION -lt $(version_code 2.12.52) ] &&
31563                 skip "Need server version at least 2.12.52"
31564
31565         local stripe_max=$((MDSCOUNT - 1))
31566         local testdir
31567         local stripe_count
31568
31569         # let caller set maxage for latest result
31570         set_maxage 1
31571
31572         # fill MDT unevenly
31573         generate_uneven_mdts 120
31574
31575         # test 4-stripe directory at most, otherwise it's too slow
31576         # We are being very defensive. Although Autotest uses 4 MDTs.
31577         # We make sure stripe_max does not go over 4.
31578         (( stripe_max > 4 )) && stripe_max=4
31579         [ "$mds1_FSTYPE" == "zfs" ] && stripe_max=1
31580         for stripe_count in $(seq 1 $stripe_max); do
31581                 testdir=$DIR/$tdir-s$stripe_count
31582                 mkdir $testdir || error "mkdir $testdir failed"
31583                 mkdir $testdir/rr || error "mkdir rr failed"
31584                 $LFS mkdir -i $(most_full_mdt) $testdir/qos ||
31585                         error "mkdir qos failed"
31586                 $LFS setdirstripe -D -c $stripe_count --max-inherit-rr 2 \
31587                         $testdir/rr || error "setdirstripe rr failed"
31588                 $LFS setdirstripe -D -c $stripe_count $testdir/qos ||
31589                         error "setdirstripe failed"
31590                 test_qos_mkdir "mkdir" $stripe_count
31591         done
31592 }
31593 run_test 413b "QoS mkdir under dir whose default LMV starting MDT offset is -1"
31594
31595 test_413c() {
31596         (( $MDSCOUNT >= 2 )) ||
31597                 skip "We need at least 2 MDTs for this test"
31598
31599         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
31600                 skip "Need server version at least 2.14.51"
31601
31602         local testdir
31603         local inherit
31604         local inherit_rr
31605         local lmv_qos_maxage
31606         local lod_qos_maxage
31607
31608         # let caller set maxage for latest result
31609         lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
31610         $LCTL set_param lmv.*.qos_maxage=1
31611         stack_trap "$LCTL set_param \
31612                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null" RETURN
31613         lod_qos_maxage=$(do_facet mds1 $LCTL get_param -n \
31614                 lod.$FSNAME-MDT0000-mdtlov.qos_maxage | awk '{ print $1 }')
31615         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
31616                 lod.*.mdt_qos_maxage=1
31617         stack_trap "do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
31618                 lod.*.mdt_qos_maxage=$lod_qos_maxage > /dev/null" RETURN
31619
31620         # fill MDT unevenly
31621         generate_uneven_mdts 120
31622
31623         testdir=$DIR/${tdir}-s1
31624         mkdir $testdir || error "mkdir $testdir failed"
31625         mkdir $testdir/rr || error "mkdir rr failed"
31626         $LFS mkdir -i $(most_full_mdt) $testdir/qos || error "mkdir qos failed"
31627         # default max_inherit is -1, default max_inherit_rr is 0
31628         $LFS setdirstripe -D -c 1 $testdir/rr ||
31629                 error "setdirstripe rr failed"
31630         $LFS setdirstripe -D -c 1 -i -1 -X 2 --max-inherit-rr 1 $testdir/qos ||
31631                 error "setdirstripe qos failed"
31632         test_qos_mkdir "mkdir" 1
31633
31634         mkdir $testdir/rr/level1 || error "mkdir rr/level1 failed"
31635         inherit=$($LFS getdirstripe -D -X $testdir/rr/level1)
31636         (( $inherit == -1 )) || error "rr/level1 inherit $inherit != -1"
31637         inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir/rr/level1)
31638         (( $inherit_rr == 0 )) || error "rr/level1 inherit-rr $inherit_rr != 0"
31639
31640         mkdir $testdir/qos/level1 || error "mkdir qos/level1 failed"
31641         inherit=$($LFS getdirstripe -D -X $testdir/qos/level1)
31642         (( $inherit == 1 )) || error "qos/level1 inherit $inherit != 1"
31643         inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir/qos/level1)
31644         (( $inherit_rr == 0 )) || error "qos/level1 inherit-rr $inherit_rr != 0"
31645         mkdir $testdir/qos/level1/level2 || error "mkdir level2 failed"
31646         getfattr -d -m dmv -e hex $testdir/qos/level1/level2 | grep dmv &&
31647                 error "level2 shouldn't have default LMV" || true
31648 }
31649 run_test 413c "mkdir with default LMV max inherit rr"
31650
31651 test_413d() {
31652         (( MDSCOUNT >= 2 )) ||
31653                 skip "We need at least 2 MDTs for this test"
31654
31655         (( MDS1_VERSION >= $(version_code 2.14.51) )) ||
31656                 skip "Need server version at least 2.14.51"
31657
31658         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
31659
31660         local lmv_qos_threshold_rr
31661
31662         lmv_qos_threshold_rr=$($LCTL get_param -n lmv.*.qos_threshold_rr |
31663                 head -n1)
31664         stack_trap "$LCTL set_param \
31665                 lmv.*.qos_threshold_rr=$lmv_qos_threshold_rr > /dev/null" EXIT
31666
31667         $LCTL set_param lmv.*.qos_threshold_rr=100 > /dev/null
31668         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
31669         getfattr -d -m dmv -e hex $DIR/$tdir | grep dmv &&
31670                 error "$tdir shouldn't have default LMV"
31671         createmany -d $DIR/$tdir/sub $((100 * MDSCOUNT)) ||
31672                 error "mkdir sub failed"
31673
31674         local count=$($LFS getstripe -m $DIR/$tdir/* | grep -c ^0)
31675
31676         (( count == 100 )) || error "$count subdirs on MDT0"
31677 }
31678 run_test 413d "inherit ROOT default LMV"
31679
31680 test_413e() {
31681         (( MDSCOUNT >= 2 )) ||
31682                 skip "We need at least 2 MDTs for this test"
31683         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
31684                 skip "Need server version at least 2.14.55"
31685
31686         local testdir=$DIR/$tdir
31687         local tmpfile=$TMP/temp.setdirstripe.stderr.$$
31688         local max_inherit
31689         local sub_max_inherit
31690
31691         mkdir -p $testdir || error "failed to create $testdir"
31692
31693         # set default max-inherit to -1 if stripe count is 0 or 1
31694         $LFS setdirstripe -D -c 1 $testdir ||
31695                 error "failed to set default LMV"
31696         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
31697         (( max_inherit == -1 )) ||
31698                 error "wrong max_inherit value $max_inherit"
31699
31700         # set default max_inherit to a fixed value if stripe count is not 0 or 1
31701         $LFS setdirstripe -D -c -1 $testdir ||
31702                 error "failed to set default LMV"
31703         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
31704         (( max_inherit > 0 )) ||
31705                 error "wrong max_inherit value $max_inherit"
31706
31707         # and the subdir will decrease the max_inherit by 1
31708         mkdir -p $testdir/subdir-1 || error "failed to make subdir"
31709         sub_max_inherit=$($LFS getdirstripe -D --max-inherit $testdir/subdir-1)
31710         (( sub_max_inherit == max_inherit - 1)) ||
31711                 error "wrong max-inherit of subdir $sub_max_inherit"
31712
31713         # check specified --max-inherit and warning message
31714         stack_trap "rm -f $tmpfile"
31715         $LFS setdirstripe -D -c 2 --max-inherit=-1 $testdir 2> $tmpfile ||
31716                 error "failed to set default LMV"
31717         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
31718         (( max_inherit == -1 )) ||
31719                 error "wrong max_inherit value $max_inherit"
31720
31721         # check the warning messages
31722         if ! [[ $(cat $tmpfile) =~ "max-inherit=" ]]; then
31723                 error "failed to detect warning string"
31724         fi
31725 }
31726 run_test 413e "check default max-inherit value"
31727
31728 test_fs_dmv_inherit()
31729 {
31730         local testdir=$DIR/$tdir
31731
31732         local count
31733         local inherit
31734         local inherit_rr
31735
31736         for i in 1 2; do
31737                 mkdir $testdir || error "mkdir $testdir failed"
31738                 count=$($LFS getdirstripe -D -c $testdir)
31739                 (( count == 1 )) ||
31740                         error "$testdir default LMV count mismatch $count != 1"
31741                 inherit=$($LFS getdirstripe -D -X $testdir)
31742                 (( inherit == 3 - i )) ||
31743                         error "$testdir default LMV max-inherit $inherit != $((3 - i))"
31744                 inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir)
31745                 (( inherit_rr == 3 - i )) ||
31746                         error "$testdir default LMV max-inherit-rr $inherit_rr != $((3 - i))"
31747                 testdir=$testdir/sub
31748         done
31749
31750         mkdir $testdir || error "mkdir $testdir failed"
31751         count=$($LFS getdirstripe -D -c $testdir)
31752         (( count == 0 )) ||
31753                 error "$testdir default LMV count not zero: $count"
31754 }
31755
31756 test_413f() {
31757         (( MDSCOUNT >= 2 )) || skip "We need at least 2 MDTs for this test"
31758
31759         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
31760                 skip "Need server version at least 2.14.55"
31761
31762         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
31763                 error "dump $DIR default LMV failed"
31764         stack_trap "setfattr --restore=$TMP/dmv.ea"
31765
31766         $LFS setdirstripe -D -i -1 -c 1 -X 3 --max-inherit-rr 3 $DIR ||
31767                 error "set $DIR default LMV failed"
31768
31769         test_fs_dmv_inherit
31770 }
31771 run_test 413f "lfs getdirstripe -D list ROOT default LMV if it's not set on dir"
31772
31773 test_413g() {
31774         (( MDSCOUNT >= 2 )) || skip "We need at least 2 MDTs for this test"
31775
31776         local FILESET_orig=$FILESET
31777         if [ -n "$FILESET" ];then
31778                 cleanup_mount $MOUNT
31779                 FILESET="" mount_client $MOUNT
31780         fi
31781
31782         mkdir -p $DIR/$tdir/l2/l3/l4 || error "mkdir $tdir/l1/l2/l3 failed"
31783         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
31784                 error "dump $DIR default LMV failed"
31785         stack_trap "setfattr --restore=$TMP/dmv.ea"
31786
31787         $LFS setdirstripe -D -i -1 -c 1 -X 3 --max-inherit-rr 3 $DIR ||
31788                 error "set $DIR default LMV failed"
31789
31790         local saved_DIR=$DIR
31791         export DIR=$MOUNT2
31792         FILESET="/$tdir/l2/l3/l4" mount_client $MOUNT2 ||
31793                 error "mount $MOUNT2 failed"
31794         if [ -n "$FILESET_orig" ]; then
31795                 stack_trap "umount_client $MOUNT2; export DIR=$saved_DIR;export FILESET=$FILESET_orig; mount_client $MOUNT"
31796         else
31797                 stack_trap "umount_client $MOUNT2; export DIR=$saved_DIR"
31798         fi
31799
31800         # first check filesystem-wide default LMV inheritance
31801         test_fs_dmv_inherit || error "incorrect fs default LMV inheritance"
31802
31803         # then check subdirs are spread to all MDTs
31804         createmany -d $DIR/s $((MDSCOUNT * 100)) || error "createmany failed"
31805
31806         local count=$($LFS getstripe -m $DIR/s* | sort -u | wc -l)
31807
31808         (( $count == $MDSCOUNT )) || error "dirs are spread to $count MDTs"
31809
31810         if [ -n "$FILESET_orig" ];then
31811                 cleanup_mount $MOUNT
31812                 FILESET=$FILESET_orig
31813                 mount_client $MOUNT
31814         fi
31815 }
31816 run_test 413g "enforce ROOT default LMV on subdir mount"
31817
31818 test_413h() {
31819         (( MDSCOUNT >= 2 )) ||
31820                 skip "We need at least 2 MDTs for this test"
31821
31822         (( MDS1_VERSION >= $(version_code 2.15.50.6) )) ||
31823                 skip "Need server version at least 2.15.50.6"
31824
31825         local lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
31826
31827         stack_trap "$LCTL set_param \
31828                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null"
31829         $LCTL set_param lmv.*.qos_maxage=1
31830
31831         local depth=5
31832         local rr_depth=4
31833         local dir=$DIR/$tdir/l1/l2/l3/l4/l5
31834         local count=$((MDSCOUNT * 20))
31835
31836         generate_uneven_mdts 50
31837
31838         mkdir -p $dir || error "mkdir $dir failed"
31839         stack_trap "rm -rf $dir"
31840         $LFS setdirstripe -D -c 1 -i -1 --max-inherit=$depth \
31841                 --max-inherit-rr=$rr_depth $dir
31842
31843         for ((d=0; d < depth + 2; d++)); do
31844                 log "dir=$dir:"
31845                 for ((sub=0; sub < count; sub++)); do
31846                         mkdir $dir/d$sub
31847                 done
31848                 $LFS getdirstripe -i $dir/d* | sort | uniq -c | sort -nr
31849                 local num=($($LFS getdirstripe -i $dir/d* | sort | uniq -c))
31850                 # subdirs within $rr_depth should be created round-robin
31851                 if (( d < rr_depth )); then
31852                         (( ${num[0]} != count )) ||
31853                                 error "all objects created on MDT ${num[1]}"
31854                 fi
31855
31856                 dir=$dir/d0
31857         done
31858 }
31859 run_test 413h "don't stick to parent for round-robin dirs"
31860
31861 test_413i() {
31862         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
31863
31864         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
31865                 skip "Need server version at least 2.14.55"
31866
31867         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
31868                 error "dump $DIR default LMV failed"
31869         stack_trap "setfattr --restore=$TMP/dmv.ea"
31870
31871         local testdir=$DIR/$tdir
31872         local def_max_rr=1
31873         local def_max=3
31874         local count
31875
31876         $LFS setdirstripe -D -i-1 -c1 --max-inherit=$def_max \
31877                 --max-inherit-rr=$def_max_rr $DIR ||
31878                 error "set $DIR default LMV failed"
31879
31880         for i in $(seq 2 3); do
31881                 def_max=$((def_max - 1))
31882                 (( def_max_rr == 0 )) || def_max_rr=$((def_max_rr - 1))
31883
31884                 mkdir $testdir
31885                 # RR is decremented and keeps zeroed once exhausted
31886                 count=$($LFS getdirstripe -D --max-inherit-rr $testdir)
31887                 (( count == def_max_rr )) ||
31888                         error_noexit "$testdir: max-inherit-rr $count != $def_max_rr"
31889
31890                 # max-inherit is decremented
31891                 count=$($LFS getdirstripe -D --max-inherit $testdir)
31892                 (( count == def_max )) ||
31893                         error_noexit "$testdir: max-inherit $count != $def_max"
31894
31895                 testdir=$testdir/d$i
31896         done
31897
31898         # d3 is the last inherited from ROOT, no inheritance anymore
31899         # i.e. no the default layout anymore
31900         mkdir -p $testdir/d4/d5
31901         count=$($LFS getdirstripe -D --max-inherit $testdir)
31902         (( count == -1 )) ||
31903                 error_noexit "$testdir: max-inherit $count != -1"
31904
31905         local p_count=$($LFS getdirstripe -i $testdir)
31906
31907         for i in $(seq 4 5); do
31908                 testdir=$testdir/d$i
31909
31910                 # the root default layout is not applied once exhausted
31911                 count=$($LFS getdirstripe -i $testdir)
31912                 (( count == p_count )) ||
31913                         error_noexit "$testdir: stripe-offset $count != parent offset $p_count"
31914         done
31915
31916         $LFS setdirstripe -i 0 $DIR/d2
31917         count=$($LFS getdirstripe -D --max-inherit $DIR/d2)
31918         (( count == -1 )) ||
31919                 error_noexit "$DIR/d2: max-inherit non-striped default $count != -1"
31920 }
31921 run_test 413i "check default layout inheritance"
31922
31923 test_413j()
31924 {
31925         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
31926
31927         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
31928         $LFS setdirstripe -D -c2 --max-inherit=2 $DIR/$tdir ||
31929                 error "setdirstripe $tdir failed"
31930
31931         local value=$(getfattr -n trusted.dmv $DIR/$tdir | \
31932                       grep "trusted.dmv" |sed -e 's/[^=]\+=//')
31933
31934         mkdir -p $DIR/$tdir/sub || error "mkdir sub failed"
31935         # setfattr dmv calls setdirstripe -D
31936         setfattr -n trusted.dmv -v $value $DIR/$tdir/sub ||
31937                 error "setfattr sub failed"
31938         local value2=$(getfattr -n trusted.dmv $DIR/$tdir/sub | \
31939                        grep "trusted.dmv" |sed -e 's/[^=]\+=//')
31940
31941         [ $value == $value2 ] || error "dmv mismatch"
31942
31943         (( MDS1_VERSION >= $(version_code 2.15.58) )) || return 0
31944
31945         # do not allow remove dmv by setfattr -x
31946         do_nodes $(comma_list $(mdts_nodes)) \
31947                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=0"
31948         setfattr -x trusted.dmv $DIR/$tdir/sub || error "setfattr sub failed"
31949         getfattr -n trusted.dmv $DIR/$tdir/sub || error "default LMV deleted"
31950
31951         # allow remove dmv by setfattr -x
31952         do_nodes $(comma_list $(mdts_nodes)) \
31953                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=1"
31954         setfattr -x trusted.dmv $DIR/$tdir/sub || error "setfattr sub failed"
31955         getfattr -n trusted.dmv $DIR/$tdir/sub && error "default LMV exists"
31956         do_nodes $(comma_list $(mdts_nodes)) \
31957                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=0"
31958 }
31959 run_test 413j "set default LMV by setxattr"
31960
31961 test_413k() {
31962         (( $MDS1_VERSION >= $(version_code 2.15.60) )) ||
31963                 skip "Need server version at least 2.15.60"
31964
31965         local index1
31966         local index2
31967         local old=$($LCTL get_param -n lmv.*.qos_exclude_prefixes)
31968         local count=$($LCTL get_param -n lmv.*.qos_exclude_prefixes | wc -l)
31969         local prefixes="abc:123:foo bar"
31970
31971         # add prefixes
31972         stack_trap "$LCTL set_param lmv.*.qos_exclude_prefixes=\"$old\""
31973         $LCTL set_param lmv.*.qos_exclude_prefixes="+$prefixes"
31974
31975         mkdir $DIR/$tdir || error "mkdir $tdir failed"
31976         index1=$($LFS getstripe -m $DIR/$tdir)
31977         for dname in _temporary _temporary.XXXXXX abc 123 "foo bar"; do
31978                 mkdir "$DIR/$tdir/$dname" || error "mkdir $dname failed"
31979                 index2=$($LFS getstripe -m "$DIR/$tdir/$dname")
31980                 ((index1 == index2)) ||
31981                         error "$tdir on MDT$index1, $dname on MDT$index2"
31982         done
31983
31984         # remove prefixes
31985         $LCTL set_param lmv.*.qos_exclude_prefixes="-$prefixes"
31986
31987         # total prefixes length > PAGE_SIZE can be printed correctly
31988         for c in {a..z}; do
31989                 prefixes=$(str_repeat $c 255)
31990                 $LCTL set_param lmv.*.qos_exclude_prefixes="+$prefixes" >/dev/null
31991         done
31992         local count2=$($LCTL get_param -n lmv.*.qos_exclude_prefixes | wc -l)
31993         ((count2 == count + 26)) ||
31994                 error "prefixes count $count2 != $((count + 26))"
31995 }
31996 run_test 413k "QoS mkdir exclude prefixes"
31997
31998 test_413z() {
31999         local pids=""
32000         local subdir
32001         local pid
32002
32003         for subdir in $(\ls -1 -d $DIR/d413*-fillmdt/*); do
32004                 unlinkmany $subdir/f. $TEST413_COUNT &
32005                 pids="$pids $!"
32006         done
32007
32008         for pid in $pids; do
32009                 wait $pid
32010         done
32011
32012         true
32013 }
32014 run_test 413z "413 test cleanup"
32015
32016 test_414() {
32017 #define OBD_FAIL_PTLRPC_BULK_ATTACH      0x521
32018         $LCTL set_param fail_loc=0x80000521
32019         dd if=/dev/zero of=$DIR/$tfile bs=2M count=1 oflag=sync
32020         rm -f $DIR/$tfile
32021         # This error path has sometimes left inflight requests dangling, so
32022         # test for this by remounting the client (umount will hang if there's
32023         # a dangling request)
32024         umount_client $MOUNT
32025         mount_client $MOUNT
32026 }
32027 run_test 414 "simulate ENOMEM in ptlrpc_register_bulk()"
32028
32029 test_415() {
32030         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
32031         (( $MDS1_VERSION >= $(version_code 2.11.52) )) ||
32032                 skip "Need server version at least 2.11.52"
32033
32034         # LU-11102
32035         local total=500
32036         local max=120
32037
32038         # this test may be slow on ZFS
32039         [[ "$mds1_FSTYPE" == "zfs" ]] && total=50
32040
32041         # though this test is designed for striped directory, let's test normal
32042         # directory too since lock is always saved as CoS lock.
32043         test_mkdir $DIR/$tdir || error "mkdir $tdir"
32044         createmany -o $DIR/$tdir/$tfile. $total || error "createmany"
32045         stack_trap "unlinkmany $DIR/$tdir/$tfile. $total || true"
32046         # if looping with ONLY_REPEAT, wait for previous deletions to finish
32047         wait_delete_completed_mds
32048
32049         # run a loop without concurrent touch to measure rename duration.
32050         # only for test debug/robustness, NOT part of COS functional test.
32051         local start_time=$SECONDS
32052         for ((i = 0; i < total; i++)); do
32053                 mrename $DIR/$tdir/$tfile.$i $DIR/$tdir/$tfile-new.$i \
32054                         > /dev/null
32055         done
32056         local baseline=$((SECONDS - start_time))
32057         echo "rename $total files without 'touch' took $baseline sec"
32058
32059         (
32060                 while true; do
32061                         touch $DIR/$tdir
32062                 done
32063         ) &
32064         local setattr_pid=$!
32065
32066         # rename files back to original name so unlinkmany works
32067         start_time=$SECONDS
32068         for ((i = 0; i < total; i++)); do
32069                 mrename $DIR/$tdir/$tfile-new.$i $DIR/$tdir/$tfile.$i\
32070                         > /dev/null
32071         done
32072         local duration=$((SECONDS - start_time))
32073
32074         kill -9 $setattr_pid
32075
32076         echo "rename $total files with 'touch' took $duration sec"
32077         (( max > 2 * baseline )) || max=$((2 * baseline + 5))
32078         (( duration <= max )) ||
32079                 error_not_in_vm "rename took $duration > $max sec"
32080 }
32081 run_test 415 "lock revoke is not missing"
32082
32083 test_416() {
32084         [ $MDS1_VERSION -lt $(version_code 2.11.55) ] &&
32085                 skip "Need server version at least 2.11.55"
32086
32087         # define OBD_FAIL_OSD_TXN_START    0x19a
32088         do_facet mds1 lctl set_param fail_loc=0x19a
32089
32090         lfs mkdir -c $MDSCOUNT $DIR/$tdir
32091
32092         true
32093 }
32094 run_test 416 "transaction start failure won't cause system hung"
32095
32096 cleanup_417() {
32097         trap 0
32098         do_nodes $(comma_list $(mdts_nodes)) \
32099                 "$LCTL set_param -n mdt.*MDT*.enable_dir_migration=1"
32100         do_nodes $(comma_list $(mdts_nodes)) \
32101                 "$LCTL set_param -n mdt.*MDT*.enable_remote_dir=1"
32102         do_nodes $(comma_list $(mdts_nodes)) \
32103                 "$LCTL set_param -n mdt.*MDT*.enable_striped_dir=1"
32104 }
32105
32106 test_417() {
32107         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
32108         [[ $MDS1_VERSION -lt $(version_code 2.11.56) ]] &&
32109                 skip "Need MDS version at least 2.11.56"
32110
32111         trap cleanup_417 RETURN EXIT
32112
32113         $LFS mkdir -i 1 $DIR/$tdir.1 || error "create remote dir $tdir.1 failed"
32114         do_nodes $(comma_list $(mdts_nodes)) \
32115                 "$LCTL set_param -n mdt.*MDT*.enable_dir_migration=0"
32116         $LFS migrate -m 0 $DIR/$tdir.1 &&
32117                 error "migrate dir $tdir.1 should fail"
32118
32119         do_nodes $(comma_list $(mdts_nodes)) \
32120                 "$LCTL set_param -n mdt.*MDT*.enable_remote_dir=0"
32121         $LFS mkdir -i 1 $DIR/$tdir.2 &&
32122                 error "create remote dir $tdir.2 should fail"
32123
32124         do_nodes $(comma_list $(mdts_nodes)) \
32125                 "$LCTL set_param -n mdt.*MDT*.enable_striped_dir=0"
32126         $LFS mkdir -c 2 $DIR/$tdir.3 &&
32127                 error "create striped dir $tdir.3 should fail"
32128         true
32129 }
32130 run_test 417 "disable remote dir, striped dir and dir migration"
32131
32132 # Checks that the outputs of df [-i] and lfs df [-i] match
32133 #
32134 # usage: check_lfs_df <blocks | inodes> <mountpoint>
32135 check_lfs_df() {
32136         local dir=$2
32137         local inodes
32138         local df_out
32139         local lfs_df_out
32140         local count
32141         local passed=false
32142
32143         # blocks or inodes
32144         [ "$1" == "blocks" ] && inodes= || inodes="-i"
32145
32146         for count in {1..100}; do
32147                 do_nodes "$CLIENTS" \
32148                         $LCTL set_param ldlm.namespaces.*.lru_size=clear
32149                 sync; sleep 0.2
32150
32151                 # read the lines of interest
32152                 df_out=($(df -P $inodes $dir | tail -n +2)) ||
32153                         error "df $inodes $dir | tail -n +2 failed"
32154                 lfs_df_out=($($LFS df $inodes $dir | grep summary:)) ||
32155                         error "lfs df $inodes $dir | grep summary: failed"
32156
32157                 # skip first substrings of each output as they are different
32158                 # "<NID>:/<fsname>" for df, "filesystem_summary:" for lfs df
32159                 # compare the two outputs
32160                 passed=true
32161                 #  skip "available" on MDT until LU-13997 is fixed.
32162                 #for i in {1..5}; do
32163                 for i in 1 2 4 5; do
32164                         [ "${df_out[i]}" != "${lfs_df_out[i]}" ] && passed=false
32165                 done
32166                 $passed && break
32167         done
32168
32169         if ! $passed; then
32170                 df -P $inodes $dir
32171                 echo
32172                 lfs df $inodes $dir
32173                 error "df and lfs df $1 output mismatch: "      \
32174                       "df ${inodes}: ${df_out[*]}, "            \
32175                       "lfs df ${inodes}: ${lfs_df_out[*]}"
32176         fi
32177 }
32178
32179 test_418() {
32180         [ $PARALLEL == "yes" ] && skip "skip parallel run"
32181
32182         local dir=$DIR/$tdir
32183         local numfiles=$((RANDOM % 4096 + 2))
32184         local numblocks=$((RANDOM % 256 + 1))
32185
32186         wait_delete_completed
32187         test_mkdir $dir
32188
32189         # check block output
32190         check_lfs_df blocks $dir
32191         # check inode output
32192         check_lfs_df inodes $dir
32193
32194         # create a single file and retest
32195         echo "Creating a single file and testing"
32196         createmany -o $dir/$tfile- 1 &>/dev/null ||
32197                 error "creating 1 file in $dir failed"
32198         check_lfs_df blocks $dir
32199         check_lfs_df inodes $dir
32200
32201         # create a random number of files
32202         echo "Creating $((numfiles - 1)) files and testing"
32203         createmany -o $dir/$tfile- 1 $((numfiles - 1)) &>/dev/null ||
32204                 error "creating $((numfiles - 1)) files in $dir failed"
32205
32206         # write a random number of blocks to the first test file
32207         echo "Writing $numblocks 4K blocks and testing"
32208         dd if=/dev/urandom of=$dir/${tfile}-0 bs=4K conv=fsync \
32209                 count=$numblocks &>/dev/null ||
32210                 error "dd to $dir/${tfile}-0 failed"
32211
32212         # retest
32213         check_lfs_df blocks $dir
32214         check_lfs_df inodes $dir
32215
32216         unlinkmany $dir/$tfile- $numfiles &>/dev/null ||
32217                 error "unlinking $numfiles files in $dir failed"
32218 }
32219 run_test 418 "df and lfs df outputs match"
32220
32221 test_419()
32222 {
32223         local dir=$DIR/$tdir
32224
32225         mkdir -p $dir
32226         touch $dir/file
32227
32228         cancel_lru_locks mdc
32229
32230         #OBD_FAIL_LLITE_OPEN_BY_NAME    0x1410
32231         $LCTL set_param fail_loc=0x1410
32232         cat $dir/file
32233         $LCTL set_param fail_loc=0
32234         rm -rf $dir
32235 }
32236 run_test 419 "Verify open file by name doesn't crash kernel"
32237
32238 test_420()
32239 {
32240         [[ $MDS1_VERSION -ge $(version_code 2.12.53) ]] ||
32241                 skip "Need MDS version at least 2.12.53"
32242
32243         local SAVE_UMASK=$(umask)
32244         local dir=$DIR/$tdir
32245         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
32246
32247         mkdir -p $dir
32248         umask 0000
32249         mkdir -m03777 $dir/testdir
32250         ls -dn $dir/testdir
32251         # Need to remove trailing '.' when SELinux is enabled
32252         local dirperms=$(ls -dn $dir/testdir |
32253                          awk '{ sub(/\.$/, "", $1); print $1}')
32254         [ $dirperms == "drwxrwsrwt" ] ||
32255                 error "incorrect perms on $dir/testdir"
32256
32257         su - $uname -c "PATH=$LUSTRE/tests:\$PATH; \
32258                 openfile -f O_RDONLY:O_CREAT -m 02755 $dir/testdir/testfile"
32259         ls -n $dir/testdir/testfile
32260         local fileperms=$(ls -n $dir/testdir/testfile |
32261                           awk '{ sub(/\.$/, "", $1); print $1}')
32262         [ $fileperms == "-rwxr-xr-x" ] ||
32263                 error "incorrect perms on $dir/testdir/testfile"
32264
32265         umask $SAVE_UMASK
32266 }
32267 run_test 420 "clear SGID bit on non-directories for non-members"
32268
32269 test_421a() {
32270         local cnt
32271         local fid1
32272         local fid2
32273
32274         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32275                 skip "Need MDS version at least 2.12.54"
32276
32277         test_mkdir $DIR/$tdir
32278         createmany -o $DIR/$tdir/f 3
32279         cnt=$(ls -1 $DIR/$tdir | wc -l)
32280         [ $cnt != 3 ] && error "unexpected #files: $cnt"
32281
32282         fid1=$(lfs path2fid $DIR/$tdir/f1)
32283         fid2=$(lfs path2fid $DIR/$tdir/f2)
32284         $LFS rmfid $DIR $fid1 $fid2 || error "rmfid failed"
32285
32286         stat $DIR/$tdir/f1 && error "f1 still visible on the client"
32287         stat $DIR/$tdir/f2 && error "f2 still visible on the client"
32288
32289         cnt=$(ls -1 $DIR/$tdir | wc -l)
32290         [ $cnt == 1 ] || error "unexpected #files after: $cnt"
32291
32292         rm -f $DIR/$tdir/f3 || error "can't remove f3"
32293         createmany -o $DIR/$tdir/f 3
32294         cnt=$(ls -1 $DIR/$tdir | wc -l)
32295         [ $cnt != 3 ] && error "unexpected #files: $cnt"
32296
32297         fid1=$(lfs path2fid $DIR/$tdir/f1)
32298         fid2=$(lfs path2fid $DIR/$tdir/f2)
32299         echo "remove using fsname $FSNAME"
32300         $LFS rmfid $FSNAME $fid1 $fid2 || error "rmfid with fsname failed"
32301
32302         cnt=$(ls -1 $DIR/$tdir | wc -l)
32303         [ $cnt == 1 ] || error "unexpected #files after: $cnt"
32304 }
32305 run_test 421a "simple rm by fid"
32306
32307 test_421b() {
32308         local cnt
32309         local FID1
32310         local FID2
32311
32312         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32313                 skip "Need MDS version at least 2.12.54"
32314
32315         test_mkdir $DIR/$tdir
32316         createmany -o $DIR/$tdir/f 3
32317         multiop_bg_pause $DIR/$tdir/f1 o_c || error "multiop failed to start"
32318         MULTIPID=$!
32319
32320         FID1=$(lfs path2fid $DIR/$tdir/f1)
32321         FID2=$(lfs path2fid $DIR/$tdir/f2)
32322         $LFS rmfid $DIR $FID1 $FID2 && error "rmfid didn't fail"
32323
32324         kill -USR1 $MULTIPID
32325         wait
32326
32327         cnt=$(ls $DIR/$tdir | wc -l)
32328         [ $cnt == 2 ] || error "unexpected #files after: $cnt"
32329 }
32330 run_test 421b "rm by fid on open file"
32331
32332 test_421c() {
32333         local cnt
32334         local FIDS
32335
32336         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32337                 skip "Need MDS version at least 2.12.54"
32338
32339         test_mkdir $DIR/$tdir
32340         createmany -o $DIR/$tdir/f 3
32341         touch $DIR/$tdir/$tfile
32342         createmany -l$DIR/$tdir/$tfile $DIR/$tdir/h 180
32343         cnt=$(ls -1 $DIR/$tdir | wc -l)
32344         [ $cnt != 184 ] && error "unexpected #files: $cnt"
32345
32346         FID1=$(lfs path2fid $DIR/$tdir/$tfile)
32347         $LFS rmfid $DIR $FID1 || error "rmfid failed"
32348
32349         cnt=$(ls $DIR/$tdir | wc -l)
32350         [ $cnt == 3 ] || error "unexpected #files after: $cnt"
32351 }
32352 run_test 421c "rm by fid against hardlinked files"
32353
32354 test_421d() {
32355         local cnt
32356         local FIDS
32357
32358         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32359                 skip "Need MDS version at least 2.12.54"
32360
32361         test_mkdir $DIR/$tdir
32362         createmany -o $DIR/$tdir/f 4097
32363         cnt=$(ls -1 $DIR/$tdir | wc -l)
32364         [ $cnt != 4097 ] && error "unexpected #files: $cnt"
32365
32366         FIDS=$(lfs path2fid $DIR/$tdir/f* | sed "s/[/][^:]*://g")
32367         $LFS rmfid $DIR $FIDS || error "rmfid failed"
32368
32369         cnt=$(ls $DIR/$tdir | wc -l)
32370         rm -rf $DIR/$tdir
32371         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
32372 }
32373 run_test 421d "rmfid en masse"
32374
32375 test_421e() {
32376         local cnt
32377         local FID
32378
32379         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
32380         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32381                 skip "Need MDS version at least 2.12.54"
32382
32383         mkdir -p $DIR/$tdir
32384         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
32385         createmany -o $DIR/$tdir/striped_dir/f 512
32386         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
32387         [ $cnt != 512 ] && error "unexpected #files: $cnt"
32388
32389         FIDS=$(lfs path2fid $DIR/$tdir/striped_dir/f* |
32390                 sed "s/[/][^:]*://g")
32391         $LFS rmfid $DIR $FIDS || error "rmfid failed"
32392
32393         cnt=$(ls $DIR/$tdir/striped_dir | wc -l)
32394         rm -rf $DIR/$tdir
32395         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
32396 }
32397 run_test 421e "rmfid in DNE"
32398
32399 test_421f() {
32400         local cnt
32401         local FID
32402
32403         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32404                 skip "Need MDS version at least 2.12.54"
32405
32406         test_mkdir $DIR/$tdir
32407         touch $DIR/$tdir/f
32408         cnt=$(ls -1 $DIR/$tdir | wc -l)
32409         [ $cnt != 1 ] && error "unexpected #files: $cnt"
32410
32411         FID=$(lfs path2fid $DIR/$tdir/f)
32412         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail (1)"
32413         # rmfid should fail
32414         cnt=$(ls -1 $DIR/$tdir | wc -l)
32415         [ $cnt != 1 ] && error "unexpected #files after (2): $cnt"
32416
32417         chmod a+rw $DIR/$tdir
32418         ls -la $DIR/$tdir
32419         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail (2)"
32420         # rmfid should fail
32421         cnt=$(ls -1 $DIR/$tdir | wc -l)
32422         [ $cnt != 1 ] && error "unexpected #files after (3): $cnt"
32423
32424         rm -f $DIR/$tdir/f
32425         $RUNAS touch $DIR/$tdir/f
32426         FID=$(lfs path2fid $DIR/$tdir/f)
32427         echo "rmfid as root"
32428         $LFS rmfid $DIR $FID || error "rmfid as root failed"
32429         cnt=$(ls -1 $DIR/$tdir | wc -l)
32430         [ $cnt == 0 ] || error "unexpected #files after (4): $cnt"
32431
32432         rm -f $DIR/$tdir/f
32433         $RUNAS touch $DIR/$tdir/f
32434         cnt=$(ls -1 $DIR/$tdir | wc -l)
32435         [ $cnt != 1 ] && error "unexpected #files (4): $cnt"
32436         FID=$(lfs path2fid $DIR/$tdir/f)
32437         # rmfid w/o user_fid2path mount option should fail
32438         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail(3)"
32439         cnt=$(ls -1 $DIR/$tdir | wc -l)
32440         [ $cnt == 1 ] || error "unexpected #files after (5): $cnt"
32441
32442         tmpdir=$(mktemp -d /tmp/lustre-XXXXXX)
32443         stack_trap "rmdir $tmpdir"
32444         mount_client $tmpdir "$MOUNT_OPTS,user_fid2path" ||
32445                 error "failed to mount client'"
32446         stack_trap "umount_client $tmpdir"
32447
32448         $RUNAS $LFS rmfid $tmpdir $FID || error "rmfid failed"
32449         # rmfid should succeed
32450         cnt=$(ls -1 $tmpdir/$tdir | wc -l)
32451         [ $cnt == 0 ] || error "unexpected #files after (6): $cnt"
32452
32453         # rmfid shouldn't allow to remove files due to dir's permission
32454         chmod a+rwx $tmpdir/$tdir
32455         touch $tmpdir/$tdir/f
32456         ls -la $tmpdir/$tdir
32457         FID=$(lfs path2fid $tmpdir/$tdir/f)
32458         $RUNAS $LFS rmfid $tmpdir $FID && error "rmfid didn't fail"
32459         return 0
32460 }
32461 run_test 421f "rmfid checks permissions"
32462
32463 test_421g() {
32464         local cnt
32465         local FIDS
32466
32467         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
32468         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
32469                 skip "Need MDS version at least 2.12.54"
32470
32471         mkdir -p $DIR/$tdir
32472         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
32473         createmany -o $DIR/$tdir/striped_dir/f 512
32474         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
32475         [ $cnt != 512 ] && error "unexpected #files: $cnt"
32476
32477         FIDS=$(lfs path2fid $DIR/$tdir/striped_dir/f* |
32478                 sed "s/[/][^:]*://g")
32479
32480         rm -f $DIR/$tdir/striped_dir/f1*
32481         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
32482         removed=$((512 - cnt))
32483
32484         # few files have been just removed, so we expect
32485         # rmfid to fail on their fids
32486         errors=$($LFS rmfid $DIR $FIDS 2>&1 | wc -l)
32487         [ $removed != $errors ] && error "$errors != $removed"
32488
32489         cnt=$(ls $DIR/$tdir/striped_dir | wc -l)
32490         rm -rf $DIR/$tdir
32491         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
32492 }
32493 run_test 421g "rmfid to return errors properly"
32494
32495 test_421h() {
32496         local mount_other
32497         local mount_ret
32498         local rmfid_ret
32499         local old_fid
32500         local fidA
32501         local fidB
32502         local fidC
32503         local fidD
32504
32505         (( MDS1_VERSION >= $(version_code 2.15.53) )) ||
32506                 skip "Need MDS version at least 2.15.53"
32507
32508         test_mkdir $DIR/$tdir
32509         test_mkdir $DIR/$tdir/subdir
32510         touch $DIR/$tdir/subdir/file0
32511         old_fid=$(lfs path2fid $DIR/$tdir/subdir/file0 | sed "s/[/][^:]*://g")
32512         echo File $DIR/$tdir/subdir/file0 FID $old_fid
32513         rm -f $DIR/$tdir/subdir/file0
32514         touch $DIR/$tdir/subdir/fileA
32515         fidA=$(lfs path2fid $DIR/$tdir/subdir/fileA | sed "s/[/][^:]*://g")
32516         echo File $DIR/$tdir/subdir/fileA FID $fidA
32517         touch $DIR/$tdir/subdir/fileB
32518         fidB=$(lfs path2fid $DIR/$tdir/subdir/fileB | sed "s/[/][^:]*://g")
32519         echo File $DIR/$tdir/subdir/fileB FID $fidB
32520         ln $DIR/$tdir/subdir/fileB $DIR/$tdir/subdir/fileB_hl
32521         touch $DIR/$tdir/subdir/fileC
32522         fidC=$(lfs path2fid $DIR/$tdir/subdir/fileC | sed "s/[/][^:]*://g")
32523         echo File $DIR/$tdir/subdir/fileC FID $fidC
32524         ln $DIR/$tdir/subdir/fileC $DIR/$tdir/fileC
32525         touch $DIR/$tdir/fileD
32526         fidD=$(lfs path2fid $DIR/$tdir/fileD | sed "s/[/][^:]*://g")
32527         echo File $DIR/$tdir/fileD FID $fidD
32528
32529         # mount another client mount point with subdirectory mount
32530         mount_other=${MOUNT}_other
32531         FILESET="$FILESET/$tdir/subdir" mount_client $mount_other ${MOUNT_OPTS}
32532         mount_ret=$?
32533         FILESET=""
32534         (( mount_ret == 0 )) || error "mount $mount_other failed"
32535
32536         echo Removing FIDs:
32537         echo $LFS rmfid $mount_other $old_fid $fidA $fidD $fidB $fidC
32538         $LFS rmfid $mount_other $old_fid $fidA $fidD $fidB $fidC
32539         rmfid_ret=$?
32540
32541         umount_client $mount_other || error "umount $mount_other failed"
32542         rm -rf $mount_other
32543
32544         (( rmfid_ret != 0 )) || error "rmfid should have failed"
32545
32546         # fileA should have been deleted
32547         stat $DIR/$tdir/subdir/fileA && error "fileA not deleted"
32548
32549         # fileB should have been deleted
32550         stat $DIR/$tdir/subdir/fileB && error "fileB not deleted"
32551
32552         # fileC should not have been deleted, fid also exists outside of fileset
32553         stat $DIR/$tdir/subdir/fileC || error "fileC deleted"
32554
32555         # fileD should not have been deleted, it exists outside of fileset
32556         stat $DIR/$tdir/fileD || error "fileD deleted"
32557 }
32558 run_test 421h "rmfid with fileset mount"
32559
32560 test_422() {
32561         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d1
32562         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d2
32563         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d3
32564         dd if=/dev/zero of=$DIR/$tdir/d1/file1 bs=1k count=1
32565         dd if=/dev/zero of=$DIR/$tdir/d2/file1 bs=1k count=1
32566
32567         local amc=$(at_max_get client)
32568         local amo=$(at_max_get mds1)
32569         local timeout=`lctl get_param -n timeout`
32570
32571         at_max_set 0 client
32572         at_max_set 0 mds1
32573
32574 #define OBD_FAIL_PTLRPC_PAUSE_REQ        0x50a
32575         do_facet mds1 $LCTL set_param fail_loc=0x8000050a \
32576                         fail_val=$(((2*timeout + 10)*1000))
32577         touch $DIR/$tdir/d3/file &
32578         sleep 2
32579 #define OBD_FAIL_TGT_REPLY_DATA_RACE     0x722
32580         do_facet mds1 $LCTL set_param fail_loc=0x80000722 \
32581                         fail_val=$((2*timeout + 5))
32582         mv $DIR/$tdir/d1/file1 $DIR/$tdir/d1/file2 &
32583         local pid=$!
32584         sleep 1
32585         kill -9 $pid
32586         sleep $((2 * timeout))
32587         echo kill $pid
32588         kill -9 $pid
32589         lctl mark touch
32590         touch $DIR/$tdir/d2/file3
32591         touch $DIR/$tdir/d2/file4
32592         touch $DIR/$tdir/d2/file5
32593
32594         wait
32595         at_max_set $amc client
32596         at_max_set $amo mds1
32597
32598         # LU-12838 - verify the ptlrpc thread watchdog is not always throttled
32599         do_facet mds1 "dmesg | grep 'Dumping the stack trace for debugging'" ||
32600                 error "Watchdog is always throttled"
32601 }
32602 run_test 422 "kill a process with RPC in progress"
32603
32604 stat_test() {
32605     df -h $MOUNT &
32606     df -h $MOUNT &
32607     df -h $MOUNT &
32608     df -h $MOUNT &
32609     df -h $MOUNT &
32610     df -h $MOUNT &
32611 }
32612
32613 test_423() {
32614     local _stats
32615     # ensure statfs cache is expired
32616     sleep 2;
32617
32618     _stats=$(stat_test | grep $MOUNT | sort -u | wc -l)
32619     [[ ${_stats} -ne 1 ]] && error "statfs wrong"
32620
32621     return 0
32622 }
32623 run_test 423 "statfs should return a right data"
32624
32625 test_424() {
32626 #define OBD_FAIL_PTLRPC_BULK_REPLY_ATTACH      0x522 | CFS_FAIL_ONCE
32627         $LCTL set_param fail_loc=0x80000522
32628         dd if=/dev/zero of=$DIR/$tfile bs=2M count=1 oflag=sync
32629         rm -f $DIR/$tfile
32630 }
32631 run_test 424 "simulate ENOMEM in ptl_send_rpc bulk reply ME attach"
32632
32633 test_425() {
32634         test_mkdir -c -1 $DIR/$tdir
32635         $LFS setstripe -c -1 $DIR/$tdir
32636
32637         lru_resize_disable "" 100
32638
32639         sleep 5
32640
32641         for i in $(seq $((MDSCOUNT * 125))); do
32642                 local t=$DIR/$tdir/$tfile_$i
32643
32644                 dd if=/dev/zero of=$t bs=4K count=1 > /dev/null 2>&1 ||
32645                         error_noexit "Create file $t"
32646         done
32647         stack_trap "rm -rf $DIR/$tdir" EXIT
32648
32649         for oscparam in $($LCTL list_param ldlm.namespaces.*osc-[-0-9a-f]*); do
32650                 local lru_size=$($LCTL get_param -n $oscparam.lru_size)
32651                 local lock_count=$($LCTL get_param -n $oscparam.lock_count)
32652
32653                 [ $lock_count -le $lru_size ] ||
32654                         error "osc lock count $lock_count > lru size $lru_size"
32655         done
32656
32657         for mdcparam in $($LCTL list_param ldlm.namespaces.*mdc-*); do
32658                 local lru_size=$($LCTL get_param -n $mdcparam.lru_size)
32659                 local lock_count=$($LCTL get_param -n $mdcparam.lock_count)
32660
32661                 [ $lock_count -le $lru_size ] ||
32662                         error "mdc lock count $lock_count > lru size $lru_size"
32663         done
32664 }
32665 run_test 425 "lock count should not exceed lru size"
32666
32667 test_426() {
32668         splice-test -r $DIR/$tfile
32669         splice-test -rd $DIR/$tfile
32670         splice-test $DIR/$tfile
32671         splice-test -d $DIR/$tfile
32672 }
32673 run_test 426 "splice test on Lustre"
32674
32675 test_427() {
32676         [ $MDSCOUNT -ge 2 ] || skip "needs >= 2 MDTs"
32677         (( $MDS1_VERSION >= $(version_code 2.12.4) )) ||
32678                 skip "Need MDS version at least 2.12.4"
32679         local log
32680
32681         mkdir $DIR/$tdir
32682         mkdir $DIR/$tdir/1
32683         mkdir $DIR/$tdir/2
32684         test_mkdir -c $MDSCOUNT -i 1 $DIR/$tdir/1/dir
32685         test_mkdir -c $MDSCOUNT -i 1 $DIR/$tdir/2/dir2
32686
32687         $LFS getdirstripe $DIR/$tdir/1/dir
32688
32689         #first setfattr for creating updatelog
32690         setfattr -n user.attr0 -v "some text" $DIR/$tdir/1/dir
32691
32692 #define OBD_FAIL_OUT_OBJECT_MISS        0x1708
32693         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x80001708
32694         setfattr -n user.attr1 -v "some text" $DIR/$tdir/1/dir &
32695         setfattr -n user.attr2 -v "another attr"  $DIR/$tdir/2/dir2 &
32696
32697         sleep 2
32698         fail mds2
32699         wait_recovery_complete mds2 $((2*TIMEOUT))
32700
32701         log=$(do_facet mds1 dmesg | tac | sed "/${TESTNAME//_/ }/,$ d")
32702         echo $log | grep "get update log failed" &&
32703                 error "update log corruption is detected" || true
32704 }
32705 run_test 427 "Failed DNE2 update request shouldn't corrupt updatelog"
32706
32707 test_428() {
32708         [ $PARALLEL == "yes" ] && skip "skip parallel run"
32709         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
32710                               awk '/^max_cached_mb/ { print $2 }')
32711         stack_trap "$LCTL set_param -n llite.*.max_cached_mb=$max_cached_mb"
32712
32713         $LCTL set_param -n llite.*.max_cached_mb=64
32714
32715         mkdir $DIR/$tdir
32716         $LFS setstripe -c 1 $DIR/$tdir
32717         eval touch $DIR/$tdir/$tfile.{1..$OSTCOUNT}
32718         stack_trap "rm -f $DIR/$tdir/$tfile.*"
32719         #test write
32720         for f in $(seq 4); do
32721                 dd if=/dev/zero of=$DIR/$tdir/$tfile.$f bs=128M count=1 &
32722         done
32723         wait
32724
32725         cancel_lru_locks osc
32726         # Test read
32727         for f in $(seq 4); do
32728                 dd if=$DIR/$tdir/$tfile.$f of=/dev/null bs=128M count=1 &
32729         done
32730         wait
32731 }
32732 run_test 428 "large block size IO should not hang"
32733
32734 test_429() { # LU-7915 / LU-10948
32735         local ll_opencache_threshold_count="llite.*.opencache_threshold_count"
32736         local testfile=$DIR/$tfile
32737         local mdc_rpcstats="mdc.$FSNAME-MDT0000-*.stats"
32738         local new_flag=1
32739         local first_rpc
32740         local second_rpc
32741         local third_rpc
32742
32743         $LCTL get_param $ll_opencache_threshold_count ||
32744                 skip "client does not have opencache parameter"
32745
32746         set_opencache $new_flag
32747         stack_trap "restore_opencache"
32748         [ $($LCTL get_param -n $ll_opencache_threshold_count) == $new_flag ] ||
32749                 error "enable opencache failed"
32750         touch $testfile
32751         # drop MDC DLM locks
32752         cancel_lru_locks mdc
32753         # clear MDC RPC stats counters
32754         $LCTL set_param $mdc_rpcstats=clear
32755
32756         # According to the current implementation, we need to run 3 times
32757         # open & close file to verify if opencache is enabled correctly.
32758         # 1st, RPCs are sent for lookup/open and open handle is released on
32759         #      close finally.
32760         # 2nd, RPC is sent for open, MDS_OPEN_LOCK is fetched automatically,
32761         #      so open handle won't be released thereafter.
32762         # 3rd, No RPC is sent out.
32763         $MULTIOP $testfile oc || error "multiop failed"
32764         first_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
32765         echo "1st: $first_rpc RPCs in flight"
32766
32767         $MULTIOP $testfile oc || error "multiop failed"
32768         second_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
32769         echo "2nd: $second_rpc RPCs in flight"
32770
32771         $MULTIOP $testfile oc || error "multiop failed"
32772         third_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
32773         echo "3rd: $third_rpc RPCs in flight"
32774
32775         #verify no MDC RPC is sent
32776         [[ $second_rpc == $third_rpc ]] || error "MDC RPC is still sent"
32777 }
32778 run_test 429 "verify if opencache flag on client side does work"
32779
32780 lseek_test_430() {
32781         local offset
32782         local file=$1
32783
32784         # data at [200K, 400K)
32785         dd if=/dev/urandom of=$file bs=256K count=1 seek=1 ||
32786                 error "256K->512K dd fails"
32787         # data at [2M, 3M)
32788         dd if=/dev/urandom of=$file bs=1M count=1 seek=2 ||
32789                 error "2M->3M dd fails"
32790         # data at [4M, 5M)
32791         dd if=/dev/urandom of=$file bs=1M count=1 seek=4 ||
32792                 error "4M->5M dd fails"
32793         echo "Data at 256K...512K, 2M...3M and 4M...5M"
32794         # start at first component hole #1
32795         printf "Seeking hole from 1000 ... "
32796         offset=$(lseek_test -l 1000 $file)
32797         echo $offset
32798         [[ $offset == 1000 ]] || error "offset $offset != 1000"
32799         printf "Seeking data from 1000 ... "
32800         offset=$(lseek_test -d 1000 $file)
32801         echo $offset
32802         [[ $offset == 262144 ]] || error "offset $offset != 262144"
32803
32804         # start at first component data block
32805         printf "Seeking hole from 300000 ... "
32806         offset=$(lseek_test -l 300000 $file)
32807         echo $offset
32808         [[ $offset == 524288 ]] || error "offset $offset != 524288"
32809         printf "Seeking data from 300000 ... "
32810         offset=$(lseek_test -d 300000 $file)
32811         echo $offset
32812         [[ $offset == 300000 ]] || error "offset $offset != 300000"
32813
32814         # start at the first component but beyond end of object size
32815         printf "Seeking hole from 1000000 ... "
32816         offset=$(lseek_test -l 1000000 $file)
32817         echo $offset
32818         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
32819         printf "Seeking data from 1000000 ... "
32820         offset=$(lseek_test -d 1000000 $file)
32821         echo $offset
32822         [[ $offset == 2097152 ]] || error "offset $offset != 2097152"
32823
32824         # start at second component stripe 2 (empty file)
32825         printf "Seeking hole from 1500000 ... "
32826         offset=$(lseek_test -l 1500000 $file)
32827         echo $offset
32828         [[ $offset == 1500000 ]] || error "offset $offset != 1500000"
32829         printf "Seeking data from 1500000 ... "
32830         offset=$(lseek_test -d 1500000 $file)
32831         echo $offset
32832         [[ $offset == 2097152 ]] || error "offset $offset != 2097152"
32833
32834         # start at second component stripe 1 (all data)
32835         printf "Seeking hole from 3000000 ... "
32836         offset=$(lseek_test -l 3000000 $file)
32837         echo $offset
32838         [[ $offset == 3145728 ]] || error "offset $offset != 3145728"
32839         printf "Seeking data from 3000000 ... "
32840         offset=$(lseek_test -d 3000000 $file)
32841         echo $offset
32842         [[ $offset == 3000000 ]] || error "offset $offset != 3000000"
32843
32844         dd if=/dev/urandom of=$file bs=640K count=1 seek=1 ||
32845                 error "2nd dd fails"
32846         echo "Add data block at 640K...1280K"
32847
32848         # start at before new data block, in hole
32849         printf "Seeking hole from 600000 ... "
32850         offset=$(lseek_test -l 600000 $file)
32851         echo $offset
32852         [[ $offset == 600000 ]] || error "offset $offset != 600000"
32853         printf "Seeking data from 600000 ... "
32854         offset=$(lseek_test -d 600000 $file)
32855         echo $offset
32856         [[ $offset == 655360 ]] || error "offset $offset != 655360"
32857
32858         # start at the first component new data block
32859         printf "Seeking hole from 1000000 ... "
32860         offset=$(lseek_test -l 1000000 $file)
32861         echo $offset
32862         [[ $offset == 1310720 ]] || error "offset $offset != 1310720"
32863         printf "Seeking data from 1000000 ... "
32864         offset=$(lseek_test -d 1000000 $file)
32865         echo $offset
32866         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
32867
32868         # start at second component stripe 2, new data
32869         printf "Seeking hole from 1200000 ... "
32870         offset=$(lseek_test -l 1200000 $file)
32871         echo $offset
32872         [[ $offset == 1310720 ]] || error "offset $offset != 1310720"
32873         printf "Seeking data from 1200000 ... "
32874         offset=$(lseek_test -d 1200000 $file)
32875         echo $offset
32876         [[ $offset == 1200000 ]] || error "offset $offset != 1200000"
32877
32878         # start beyond file end
32879         printf "Using offset > filesize ... "
32880         lseek_test -l 4000000 $file && error "lseek should fail"
32881         printf "Using offset > filesize ... "
32882         lseek_test -d 4000000 $file && error "lseek should fail"
32883
32884         printf "Done\n\n"
32885 }
32886
32887 test_430a() {
32888         $LCTL get_param mdc.*.import | grep -q 'connect_flags:.*seek' ||
32889                 skip "MDT does not support SEEK_HOLE"
32890
32891         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
32892                 skip "OST does not support SEEK_HOLE"
32893
32894         local file=$DIR/$tdir/$tfile
32895
32896         mkdir -p $DIR/$tdir
32897
32898         $LFS setstripe -E 1M -L mdt -E eof -c2 $file
32899         # OST stripe #1 will have continuous data at [1M, 3M)
32900         # OST stripe #2 is empty
32901         echo "Component #1: 1M DoM, component #2: EOF, 2 stripes 1M"
32902         lseek_test_430 $file
32903         rm $file
32904         $LFS setstripe -E 1M -c2 -S 64K -E 10M -c2 -S 1M $file
32905         echo "Component #1: 1M, 2 stripes 64K, component #2: EOF, 2 stripes 1M"
32906         lseek_test_430 $file
32907         rm $file
32908         $LFS setstripe -c2 -S 512K $file
32909         echo "Two stripes, stripe size 512K"
32910         lseek_test_430 $file
32911         rm $file
32912         # FLR with stale mirror
32913         $LFS setstripe -N -E 512K -c1 -S 64K -E eof -c2 -S 512K \
32914                        -N -c2 -S 1M $file
32915         echo "Mirrored file:"
32916         echo "Component #1: 512K, stripe 64K, component #2: EOF, 2 stripes 512K"
32917         echo "Plain 2 stripes 1M"
32918         lseek_test_430 $file
32919         rm $file
32920 }
32921 run_test 430a "lseek: SEEK_DATA/SEEK_HOLE basic functionality"
32922
32923 test_430b() {
32924         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
32925                 skip "OST does not support SEEK_HOLE"
32926
32927         local offset
32928         local file=$DIR/$tdir/$tfile
32929
32930         mkdir -p $DIR/$tdir
32931         # Empty layout lseek should fail
32932         $MCREATE $file
32933         # seek from 0
32934         printf "Seeking hole from 0 ... "
32935         lseek_test -l 0 $file && error "lseek should fail"
32936         printf "Seeking data from 0 ... "
32937         lseek_test -d 0 $file && error "lseek should fail"
32938         rm $file
32939
32940         # 1M-hole file
32941         $LFS setstripe -E 1M -c2 -E eof $file
32942         $TRUNCATE $file 1048576
32943         printf "Seeking hole from 1000000 ... "
32944         offset=$(lseek_test -l 1000000 $file)
32945         echo $offset
32946         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
32947         printf "Seeking data from 1000000 ... "
32948         lseek_test -d 1000000 $file && error "lseek should fail"
32949         rm $file
32950
32951         # full component followed by non-inited one
32952         $LFS setstripe -E 1M -c2 -E eof $file
32953         dd if=/dev/urandom of=$file bs=1M count=1
32954         printf "Seeking hole from 1000000 ... "
32955         offset=$(lseek_test -l 1000000 $file)
32956         echo $offset
32957         [[ $offset == 1048576 ]] || error "offset $offset != 1048576"
32958         printf "Seeking hole from 1048576 ... "
32959         lseek_test -l 1048576 $file && error "lseek should fail"
32960         # init second component and truncate back
32961         echo "123" >> $file
32962         $TRUNCATE $file 1048576
32963         printf "Seeking hole from 1000000 ... "
32964         offset=$(lseek_test -l 1000000 $file)
32965         echo $offset
32966         [[ $offset == 1048576 ]] || error "offset $offset != 1048576"
32967         printf "Seeking hole from 1048576 ... "
32968         lseek_test -l 1048576 $file && error "lseek should fail"
32969         # boundary checks for big values
32970         dd if=/dev/urandom of=$file.10g bs=1 count=1 seek=10G
32971         offset=$(lseek_test -d 0 $file.10g)
32972         [[ $offset == 10737418240 ]] || error "offset $offset != 10737418240"
32973         dd if=/dev/urandom of=$file.100g bs=1 count=1 seek=100G
32974         offset=$(lseek_test -d 0 $file.100g)
32975         [[ $offset == 107374182400 ]] || error "offset $offset != 107374182400"
32976         return 0
32977 }
32978 run_test 430b "lseek: SEEK_DATA/SEEK_HOLE special cases"
32979
32980 test_430c() {
32981         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
32982                 skip "OST does not support SEEK_HOLE"
32983
32984         local file=$DIR/$tdir/$tfile
32985         local start
32986
32987         mkdir -p $DIR/$tdir
32988         stack_trap "rm -f $file $file.tmp"
32989         dd if=/dev/urandom of=$file bs=1k count=1 seek=5M || error "dd failed"
32990
32991         # cp version 8.33+ prefers lseek over fiemap
32992         local ver=$(cp --version | awk '{ print $4; exit; }')
32993
32994         echo "cp $ver installed"
32995         if (( $(version_code $ver) >= $(version_code 8.33) )); then
32996                 start=$SECONDS
32997                 time cp -v $file $file.tmp || error "cp $file failed"
32998                 (( SECONDS - start < 5 )) || {
32999                         strace cp $file $file.tmp |&
33000                                 grep -E "open|read|seek|FIEMAP" |
33001                                 grep -A 100 $file
33002                         error "cp: too long runtime $((SECONDS - start))"
33003                 }
33004         else
33005                 echo "cp test skipped due to $ver < 8.33"
33006         fi
33007
33008         # tar version 1.29+ supports SEEK_HOLE/DATA
33009         ver=$(tar --version | awk '{ print $4; exit; }')
33010         echo "tar $ver installed"
33011         if (( $(version_code $ver) >= $(version_code 1.29) )); then
33012                 start=$SECONDS
33013                 time tar cvf $file.tmp --sparse $file || error "tar $file error"
33014                 (( SECONDS - start < 5 )) || {
33015                         strace tar cf $file.tmp --sparse $file |&
33016                                 grep -E "open|read|seek|FIEMAP" |
33017                                 grep -A 100 $file
33018                         error "tar: too long runtime $((SECONDS - start))"
33019                 }
33020         else
33021                 echo "tar test skipped due to $ver < 1.29"
33022         fi
33023 }
33024 run_test 430c "lseek: external tools check"
33025
33026 test_431() { # LU-14187
33027         local file=$DIR/$tdir/$tfile
33028
33029         mkdir -p $DIR/$tdir
33030         $LFS setstripe -c 1 -i 0 $file || error "lfs setstripe failed"
33031         dd if=/dev/urandom of=$file bs=4k count=1
33032         dd if=/dev/urandom of=$file bs=4k count=1 seek=10 conv=notrunc
33033         dd if=/dev/urandom of=$file bs=4k count=1 seek=12 conv=notrunc
33034         #define OBD_FAIL_OST_RESTART_IO 0x251
33035         do_facet ost1 "$LCTL set_param fail_loc=0x251"
33036         $LFS setstripe -c 1 -i 0 $file.0 || error "lfs setstripe failed"
33037         cp $file $file.0
33038         cancel_lru_locks
33039         sync_all_data
33040         echo 3 > /proc/sys/vm/drop_caches
33041         diff  $file $file.0 || error "data diff"
33042 }
33043 run_test 431 "Restart transaction for IO"
33044
33045 cleanup_test_432() {
33046         do_facet mgs $LCTL nodemap_activate 0
33047         wait_nm_sync active
33048 }
33049
33050 test_432() {
33051         local tmpdir=$TMP/dir432
33052
33053         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
33054                 skip "Need MDS version at least 2.14.52"
33055
33056         stack_trap cleanup_test_432 EXIT
33057         mkdir $DIR/$tdir
33058         mkdir $tmpdir
33059
33060         do_facet mgs $LCTL nodemap_activate 1
33061         wait_nm_sync active
33062         do_facet mgs $LCTL nodemap_modify --name default \
33063                 --property admin --value 1
33064         do_facet mgs $LCTL nodemap_modify --name default \
33065                 --property trusted --value 1
33066         cancel_lru_locks mdc
33067         wait_nm_sync default admin_nodemap
33068         wait_nm_sync default trusted_nodemap
33069
33070         if [ $(mv $tmpdir $DIR/$tdir/ 2>&1 |
33071                grep -ci "Operation not permitted") -ne 0 ]; then
33072                 error "mv $tmpdir $DIR/$tdir/ hits 'Operation not permitted'"
33073         fi
33074 }
33075 run_test 432 "mv dir from outside Lustre"
33076
33077 test_433() {
33078         [ $PARALLEL == "yes" ] && skip "skip parallel run"
33079
33080         [[ -n "$($LCTL list_param llite.*.inode_cache 2>/dev/null)" ]] ||
33081                 skip "inode cache not supported"
33082
33083         $LCTL set_param llite.*.inode_cache=0
33084         stack_trap "$LCTL set_param llite.*.inode_cache=1"
33085
33086         local count=256
33087         local first
33088         local before
33089         local after
33090
33091         cancel_lru_locks mdc
33092         first=$(num_objects)
33093         test_mkdir $DIR/$tdir || error "mkdir $tdir"
33094         createmany -m $DIR/$tdir/f $count
33095         createmany -d $DIR/$tdir/d $count
33096         ls -l $DIR/$tdir > /dev/null
33097         stack_trap "rm -rf $DIR/$tdir"
33098
33099         before=$(num_objects)
33100         cancel_lru_locks mdc
33101         after=$(num_objects)
33102
33103         # sometimes even $before is less than 2 * count
33104         while (( before > first + count && before - after < count )); do
33105                 sleep 1
33106                 after=$(num_objects)
33107                 wait=$((wait + 1))
33108                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
33109                 if (( wait > 60 )); then
33110                         error "inode slab grew from $first ^ $before v $after"
33111                 fi
33112         done
33113
33114         echo "lustre_inode_cache grew from $first to $before, then $after after"
33115 }
33116 run_test 433 "ldlm lock cancel releases dentries and inodes"
33117
33118 test_434() {
33119         local file
33120         local getxattr_count
33121         local mdc_stat_param="mdc.$FSNAME-MDT0000*.md_stats"
33122         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
33123
33124         [[ $(getenforce) == "Disabled" ]] ||
33125                 skip "lsm selinux module have to be disabled for this test"
33126
33127         test_mkdir -i 0 -c1 $DIR/$tdir/ ||
33128                 error "fail to create $DIR/$tdir/ on MDT0000"
33129
33130         touch $DIR/$tdir/$tfile-{001..100}
33131
33132         # disable the xattr cache
33133         save_lustre_params client "llite.*.xattr_cache" > $p
33134         lctl set_param llite.*.xattr_cache=0
33135         stack_trap "restore_lustre_params < $p; rm -f $p" EXIT
33136
33137         # clear clients mdc stats
33138         clear_stats $mdc_stat_param ||
33139                 error "fail to clear stats on mdc MDT0000"
33140
33141         for file in $DIR/$tdir/$tfile-{001..100}; do
33142                 getfattr -n security.selinux $file |&
33143                         grep -q "Operation not supported" ||
33144                         error "getxattr on security.selinux should return EOPNOTSUPP"
33145         done
33146
33147         getxattr_count=$(calc_stats $mdc_stat_param "getxattr")
33148         (( getxattr_count < 100 )) ||
33149                 error "client sent $getxattr_count getxattr RPCs to the MDS"
33150 }
33151 run_test 434 "Client should not send RPCs for security.selinux with SElinux disabled"
33152
33153 test_440() {
33154         if [[ -f $LUSTRE/scripts/bash-completion/lustre ]]; then
33155                 source $LUSTRE/scripts/bash-completion/lustre
33156         elif [[ -f /usr/share/bash-completion/completions/lustre ]]; then
33157                 source /usr/share/bash-completion/completions/lustre
33158         else
33159                 skip "bash completion scripts not found"
33160         fi
33161
33162         local lctl_completions
33163         local lfs_completions
33164
33165         lctl_completions=$(_lustre_cmds lctl)
33166         if [[ ! $lctl_completions =~ "get_param" ]]; then
33167                 error "lctl bash completion failed"
33168         fi
33169
33170         lfs_completions=$(_lustre_cmds lfs)
33171         if [[ ! $lfs_completions =~ "setstripe" ]]; then
33172                 error "lfs bash completion failed"
33173         fi
33174 }
33175 run_test 440 "bash completion for lfs, lctl"
33176
33177 test_442() {
33178         local pid1
33179         local pid2
33180         mkdir -p $DIR/$tdir
33181         multiop $DIR/$tdir/$tfile.1 O_w1 & pid1=$!
33182         multiop $DIR/$tdir/$tfile.1 O_w1 & pid2=$!
33183         sleep 1
33184         touch $DIR/$tdir/$tfile.2
33185         $LFS swap_layouts -n $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
33186         $LCTL set_param fail_loc=0x1430
33187         kill -USR1 $pid1
33188         sleep 1
33189         kill -USR1 $pid2
33190         wait
33191 }
33192 run_test 442 "truncate vs read/write should not panic"
33193
33194 test_460d() {
33195         verify_yaml_available || skip_env "YAML verification not installed"
33196         $LCTL get_param -n sptlrpc.page_pools
33197         $LCTL get_param -n sptlrpc.page_pools | verify_yaml ||
33198                 error "The output of encrypt_page_pools is not an valid YAML"
33199 }
33200 run_test 460d "Check encrypt pools output"
33201
33202 resident_pages() {
33203         local file=$1
33204
33205         vmtouch $file | awk '/Resident Pages:/ {print $3}' |
33206                 awk -F/ '{ print $1 }'
33207 }
33208
33209 # The command "echo 2 > /proc/sys/vm/drop_caches" may revoke the DLM locks
33210 # due to slab cache reclaim. Thus we should avoid to reclaim slab cache for
33211 # DLM locks during testing since it may evict mlock()ed pages due to the
33212 # release of the DLM extent lock.
33213 # After the page cache shrinker is disabled, "echo 3 > /proc/sys/vm/drop_caches"
33214 # and "echo 2 > /proc/sys/vm/drop_caches" will not scan and clear unused pages
33215 # from the LRU list.
33216 disable_page_cache_shrink() {
33217         local enabled=$($LCTL get_param -n osc.*.enable_page_cache_shrink |
33218                         head -n 1)
33219
33220         stack_trap "$LCTL set_param osc.*.enable_page_cache_shrink=$enabled"
33221         $LCTL set_param osc.*.enable_page_cache_shrink=0
33222 }
33223
33224 enable_mlock_pages_check() {
33225         local enabled=$($LCTL get_param -n llite.*.enable_mlock_pages)
33226
33227         stack_trap "$LCTL set_param llite.*.enable_mlock_pages=$enabled"
33228         $LCTL set_param llite.*.enable_mlock_pages=1
33229 }
33230
33231 test_600a() {
33232         local file=$DIR/$tfile
33233         local size_mb=100
33234         local pcnt=$((size_mb * 1024 * 1024 / PAGE_SIZE))
33235
33236         which vmtouch || skip_env "This test needs vmtouch utility"
33237         check_set_fallocate_or_skip
33238         disable_page_cache_shrink
33239         enable_mlock_pages_check
33240
33241         fallocate -l ${size_mb}M $file || error "failed to fallocate $file"
33242         stack_trap "pkill -9 vmtouch || true"
33243         vmtouch -vltdw -m 1g $file || error "failed to vmtouch $file"
33244
33245         local rcnt=$(resident_pages $file)
33246
33247         echo "before drop_caches (0):"
33248         grep Mlocked: /proc/meminfo
33249         $LCTL get_param llite.*.max_cached_mb
33250         echo "drop page caches (1):"
33251         echo 1 > /proc/sys/vm/drop_caches
33252         grep Mlocked: /proc/meminfo
33253         $LCTL get_param llite.*.max_cached_mb
33254         vmtouch $file
33255         (( $pcnt == $rcnt )) || error "resident pages are $rcnt, expected $pcnt"
33256
33257         local unevict_mb
33258
33259         $LCTL set_param llite.*.unevict_cached_mb=clear
33260         $LCTL get_param llite.*.unevict_cached_mb
33261         unevict_mb=$($LCTL get_param -n llite.*.unevict_cached_mb)
33262         (( $unevict_mb == $size_mb )) ||
33263                 error "unevict_cached_mb is $unevict_mb, expected $size_mb"
33264
33265         $LCTL set_param $OSC.*$OSC*.osc_unevict_cached_mb=clear
33266         $LCTL get_param $OSC.*$OSC*.osc_unevict_cached_mb
33267         unevict_mb=$($LCTL get_param -n $OSC.*$OSC*.osc_unevict_cached_mb |
33268                      awk '{sum += $1 } END { print sum }')
33269         (( $unevict_mb == $size_mb )) ||
33270                 error "osc_unevict_cached_mb is $unevict_mb, expected $size_mb"
33271
33272         # The lock revocation will evict the cached pages protected by it.
33273         # This is desired behavior for conflict access from the remote client.
33274         # But how to deal with the lock revocation triggered by LRU lock
33275         # shrinking on client side, should this kind of locks that protected
33276         # the mlocked pages be canceled in this case? Or the lock protecting
33277         # mlock()ed pages should not put into lock LRU list?
33278         cancel_lru_locks $OSC
33279         echo "drop lru DLM lock:"
33280         grep Mlocked: /proc/meminfo
33281         $LCTL get_param llite.*.max_cached_mb
33282         $LCTL get_param osc.*.osc_cached_mb
33283         rcnt=$(resident_pages $file)
33284         (( $rcnt == 0 )) || error "resident pages are $rcnt, expected zero"
33285         unevict_mb=$($LCTL get_param -n llite.*.unevict_cached_mb)
33286         (( $unevict_mb == 0 )) ||
33287                 error "unevict_cached_mb is $unevict_mb, expected 0"
33288         unevict_mb=$($LCTL get_param -n $OSC.*$OSC*.osc_unevict_cached_mb |
33289                      awk '{sum += $1 } END { print sum }')
33290         (( $unevict_mb == 0 )) ||
33291                 error "osc_unevict_cached_mb is $unevict_mb, expected $size_mb"
33292
33293 }
33294 run_test 600a "basic test for mlock()ed file"
33295
33296 test_600b() {
33297         local file=$DIR/$tfile
33298         local size_mb=100
33299         local cache_limit=64
33300         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33301                               awk '/^max_cached_mb/ { print $2 }')
33302
33303         which vmtouch || skip_env "This test needs vmtouch utility"
33304         check_set_fallocate_or_skip
33305         disable_page_cache_shrink
33306         enable_mlock_pages_check
33307
33308         fallocate -l ${size_mb}M $file || error "failed to fallocate $file"
33309         stack_trap "pkill -9 vmtouch || true"
33310
33311         cancel_lru_locks $OSC
33312         $LCTL get_param llite.*.max_cached_mb
33313         stack_trap "$LCTL set_param llite.*.max_cached_mb=$max_cached_mb"
33314         $LCTL set_param llite.*.max_cached_mb=$cache_limit
33315
33316         # The required mlock()ed pages (100M) are larger than @max_cached_mb.
33317         vmtouch -vltdw -m 1g $file || error "failed to mlock $file"
33318         vmtouch $file
33319         grep Mlocked: /proc/meminfo
33320
33321         local used_mb
33322         local unevict_mb
33323
33324         echo 1 > /proc/sys/vm/drop_caches
33325         $LCTL get_param llite.*.max_cached_mb
33326         $LCTL set_param llite.*.unevict_cached_mb=clear
33327         used_mb=$($LCTL get_param llite.*.max_cached_mb |
33328                   awk '/^used_mb/ { print $2 }')
33329         unevict_mb=$($LCTL get_param -n llite.*.unevict_cached_mb)
33330         (( $used_mb == 0 )) || error "used_mb is $used_mb, expected 0"
33331         (( $unevict_mb >= $size_mb - 1)) || # allow a margin of 1 page
33332                 error "unevict_mb is $unevict_mb, expected $size_mb"
33333 }
33334 run_test 600b "mlock a file (via vmtouch) larger than max_cached_mb"
33335
33336 test_600c() {
33337         local dir=$DIR/$tdir
33338         local cache_limit=64
33339         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33340                               awk '/^max_cached_mb/ { print $2 }')
33341
33342         which vmtouch || skip_env "This test needs vmtouch utility"
33343         check_set_fallocate_or_skip
33344         disable_page_cache_shrink
33345         enable_mlock_pages_check
33346
33347         stack_trap "rm -rf $dir"
33348         stack_trap "$LCTL set_param llite.*.max_cached_mb=$max_cached_mb"
33349         $LCTL set_param llite.*.max_cached_mb=$cache_limit
33350         stack_trap "pkill -9 vmtouch || true"
33351
33352         local size=$((64 * 1048576))
33353         local file1=$dir/$tfile.1
33354         local file2=$dir/$tfile.2
33355
33356         mkdir $dir || error "failed to mkdir $dir"
33357         fallocate -l $size $file1 || error "failed to fallocate $file1"
33358         fallocate -l $size $file2 || error "failed to fallocate $file2"
33359         cancel_lru_locks $OSC
33360
33361         vmtouch -vltdw -m 1g $file1 || error "failed to vmtouch $file1"
33362         $LCTL get_param llite.*.max_cached_mb
33363         $LCTL set_param llite.*.unevict_cached_mb=clear
33364         $LCTL get_param llite.*.max_cached_mb
33365
33366         local cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33367                           awk '/^used_mb/ { print $2 }')
33368
33369         (( $cached_mb == 0 )) || error "expected used_mb 0 got $cached_mb"
33370         cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33371                     awk '/^unevict_mb/ { print $2 }')
33372         (( $cached_mb == 64 )) || error "expected unevict_mb 64 got $cached_mb"
33373
33374         vmtouch -vt $file2 || error "failed to vmtouch $file2"
33375         echo 3 > /proc/sys/vm/drop_caches
33376         dd if=$file2 of=/dev/null bs=1M count=64 ||
33377                 error "failed to reading $file2 into cache"
33378
33379         pkill -9 vmtouch || error "failed to kill vmtouch"
33380         vmtouch -vt $file2 || error "failed to load $files into cache"
33381         $LCTL get_param llite.*.max_cached_mb
33382         echo 1 > /proc/sys/vm/drop_caches
33383         $LCTL set_param llite.*.unevict_cached_mb=clear
33384         cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33385                     awk '/^used_mb/ { print $2 }')
33386         (( $cached_mb == 0 )) || error "expected used_mb 0 got $cached_mb"
33387         cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33388                     awk '/^unevict_mb/ { print $2 }')
33389         (( $cached_mb == 0 )) || error "expected unevict_mb 0 got $cached_mb"
33390 }
33391 run_test 600c "Test I/O when mlocked page count > @max_cached_mb"
33392
33393 test_600d_base() {
33394         local mlcksz=$1
33395         local fsz=$2
33396         local n=$3
33397         local dir=$DIR/$tdir
33398         local mlckf=$dir/mlockfile
33399
33400         echo "mlock size: $mlcksz file size: $fsz, n: $n"
33401         mkdir -p $dir || error "mkdir $dir failed"
33402
33403         fallocate -l $mlcksz $mlckf || error "failed to fallocate $mlckf"
33404         for ((i = 0; i < $n; i++)); do
33405                 fallocate -l $fsz $dir/$tfile.$i ||
33406                         error "failed to fallocate $dir/$tfile.$i"
33407         done
33408
33409         cancel_lru_locks $OSC
33410
33411         declare -a pids
33412
33413         vmtouch -vltdw -m 1G $mlckf || error "failed to mlock $mlckf"
33414         for ((i = 0; i < $n; i++)); do
33415                 vmtouch -t -m 1g $dir/$tfile.$i &
33416                 pids[i]=$!
33417         done
33418
33419         cat /proc/meminfo | grep 'Mlocked'
33420         $LCTL get_param llite.*.max_cached_mb
33421         echo "drop caches:"
33422         echo 1 > /proc/sys/vm/drop_caches
33423         $LCTL set_param llite.*.unevict_cached_mb=clear
33424         $LCTL get_param llite.*.max_cached_mb
33425
33426         for ((i = 0; i < $n; i++)); do
33427                 wait ${pids[i]} || error "touch $dir/$tfile.$i failed: rc = $?"
33428         done
33429
33430         cat /proc/meminfo | grep 'Mlocked:'
33431         pkill -9 vmtouch || true
33432         rm -rvf $dir || error "failed to rm $dir"
33433 }
33434
33435 test_600d() {
33436         local dir=$DIR/$tdir
33437         local cache_limit=64
33438         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
33439                               awk '/^max_cached_mb/ { print $2 }')
33440
33441         which vmtouch || skip_env "This test needs vmtouch utility"
33442         check_set_fallocate_or_skip
33443         disable_page_cache_shrink
33444         enable_mlock_pages_check
33445
33446         stack_trap "rm -rf $dir"
33447         stack_trap "$LCTL set_param llite.*.max_cached_mb=$max_cached_mb"
33448         $LCTL set_param llite.*.max_cached_mb=$cache_limit
33449         stack_trap "pkill -9 vmtouch || true"
33450
33451         local size=$((cache_limit * 1048576))
33452
33453         test_600d_base $((size - PAGE_SIZE)) 4096 16
33454         test_600d_base $((size - 2 * PAGE_SIZE)) 16384 16
33455 }
33456 run_test 600d "Test I/O with limited LRU page slots (some was mlocked)"
33457
33458 prep_801() {
33459         [[ $MDS1_VERSION -lt $(version_code 2.9.55) ]] ||
33460         [[ $OST1_VERSION -lt $(version_code 2.9.55) ]] &&
33461                 skip "Need server version at least 2.9.55"
33462
33463         start_full_debug_logging
33464 }
33465
33466 post_801() {
33467         stop_full_debug_logging
33468 }
33469
33470 barrier_stat() {
33471         if (( $MDS1_VERSION >= $(version_code 2.16.50) )); then
33472                 barrier_stat="barrier stat"
33473         else
33474                 barrier_stat="barrier_stat"
33475         fi
33476         if [ $MGS_VERSION -le $(version_code 2.10.0) ]; then
33477                 local st=$(do_facet mgs $LCTL $barrier_stat $FSNAME |
33478                            awk '/The barrier for/ { print $7 }')
33479                 echo $st
33480         else
33481                 local st=$(do_facet mgs $LCTL $barrier_stat -s $FSNAME)
33482                 echo \'$st\'
33483         fi
33484 }
33485
33486 barrier_expired() {
33487         local expired
33488
33489         if [ $MGS_VERSION -le $(version_code 2.10.0) ]; then
33490                 expired=$(do_facet mgs $LCTL barrier_stat $FSNAME |
33491                           awk '/will be expired/ { print $7 }')
33492         else
33493                 expired=$(do_facet mgs $LCTL barrier_stat -t $FSNAME)
33494         fi
33495
33496         echo $expired
33497 }
33498
33499 test_801a() {
33500         prep_801
33501
33502         echo "Start barrier_freeze at: $(date)"
33503         #define OBD_FAIL_BARRIER_DELAY          0x2202
33504         do_facet mgs $LCTL set_param fail_val=5 fail_loc=0x2202
33505         # Do not reduce barrier time - See LU-11873
33506         do_facet mgs $LCTL barrier_freeze $FSNAME 20 &
33507
33508         sleep 2
33509         local b_status=$(barrier_stat)
33510         echo "Got barrier status at: $(date)"
33511         [ "$b_status" = "'freezing_p1'" ] ||
33512                 error "(1) unexpected barrier status $b_status"
33513
33514         do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
33515         wait
33516         b_status=$(barrier_stat)
33517         [ "$b_status" = "'frozen'" ] ||
33518                 error "(2) unexpected barrier status $b_status"
33519
33520         local expired=$(barrier_expired)
33521         echo "sleep $((expired + 3)) seconds, then the barrier will be expired"
33522         sleep $((expired + 3))
33523
33524         b_status=$(barrier_stat)
33525         [ "$b_status" = "'expired'" ] ||
33526                 error "(3) unexpected barrier status $b_status"
33527
33528         # Do not reduce barrier time - See LU-11873
33529         do_facet mgs $LCTL barrier_freeze $FSNAME 20 ||
33530                 error "(4) fail to freeze barrier"
33531
33532         b_status=$(barrier_stat)
33533         [ "$b_status" = "'frozen'" ] ||
33534                 error "(5) unexpected barrier status $b_status"
33535
33536         echo "Start barrier_thaw at: $(date)"
33537         #define OBD_FAIL_BARRIER_DELAY          0x2202
33538         do_facet mgs $LCTL set_param fail_val=5 fail_loc=0x2202
33539         do_facet mgs $LCTL barrier_thaw $FSNAME &
33540
33541         sleep 2
33542         b_status=$(barrier_stat)
33543         echo "Got barrier status at: $(date)"
33544         [ "$b_status" = "'thawing'" ] ||
33545                 error "(6) unexpected barrier status $b_status"
33546
33547         do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
33548         wait
33549         b_status=$(barrier_stat)
33550         [ "$b_status" = "'thawed'" ] ||
33551                 error "(7) unexpected barrier status $b_status"
33552
33553         #define OBD_FAIL_BARRIER_FAILURE        0x2203
33554         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2203
33555         do_facet mgs $LCTL barrier_freeze $FSNAME
33556
33557         b_status=$(barrier_stat)
33558         [ "$b_status" = "'failed'" ] ||
33559                 error "(8) unexpected barrier status $b_status"
33560
33561         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
33562         do_facet mgs $LCTL barrier_thaw $FSNAME
33563
33564         post_801
33565 }
33566 run_test 801a "write barrier user interfaces and stat machine"
33567
33568 test_801b() {
33569         prep_801
33570
33571         mkdir $DIR/$tdir || error "(1) fail to mkdir"
33572         createmany -d $DIR/$tdir/d 6 || error "(2) fail to mkdir"
33573         touch $DIR/$tdir/d2/f10 || error "(3) fail to touch"
33574         touch $DIR/$tdir/d3/f11 || error "(4) fail to touch"
33575         touch $DIR/$tdir/d4/f12 || error "(5) fail to touch"
33576
33577         cancel_lru_locks mdc
33578
33579         # 180 seconds should be long enough
33580         do_facet mgs $LCTL barrier_freeze $FSNAME 180
33581
33582         local b_status=$(barrier_stat)
33583         [ "$b_status" = "'frozen'" ] ||
33584                 error "(6) unexpected barrier status $b_status"
33585
33586         mkdir $DIR/$tdir/d0/d10 &
33587         mkdir_pid=$!
33588
33589         touch $DIR/$tdir/d1/f13 &
33590         touch_pid=$!
33591
33592         ln $DIR/$tdir/d2/f10 $DIR/$tdir/d2/f14 &
33593         ln_pid=$!
33594
33595         mv $DIR/$tdir/d3/f11 $DIR/$tdir/d3/f15 &
33596         mv_pid=$!
33597
33598         rm -f $DIR/$tdir/d4/f12 &
33599         rm_pid=$!
33600
33601         stat $DIR/$tdir/d5 || error "(7) stat should succeed"
33602
33603         # To guarantee taht the 'stat' is not blocked
33604         b_status=$(barrier_stat)
33605         [ "$b_status" = "'frozen'" ] ||
33606                 error "(8) unexpected barrier status $b_status"
33607
33608         # let above commands to run at background
33609         sleep 5
33610
33611         ps -p $mkdir_pid || error "(9) mkdir should be blocked"
33612         ps -p $touch_pid || error "(10) touch should be blocked"
33613         ps -p $ln_pid || error "(11) link should be blocked"
33614         ps -p $mv_pid || error "(12) rename should be blocked"
33615         ps -p $rm_pid || error "(13) unlink should be blocked"
33616
33617         b_status=$(barrier_stat)
33618         [ "$b_status" = "'frozen'" ] ||
33619                 error "(14) unexpected barrier status $b_status"
33620
33621         do_facet mgs $LCTL barrier_thaw $FSNAME
33622         b_status=$(barrier_stat)
33623         [ "$b_status" = "'thawed'" ] ||
33624                 error "(15) unexpected barrier status $b_status"
33625
33626         wait $mkdir_pid || error "(16) mkdir should succeed"
33627         wait $touch_pid || error "(17) touch should succeed"
33628         wait $ln_pid || error "(18) link should succeed"
33629         wait $mv_pid || error "(19) rename should succeed"
33630         wait $rm_pid || error "(20) unlink should succeed"
33631
33632         post_801
33633 }
33634 run_test 801b "modification will be blocked by write barrier"
33635
33636 test_801c() {
33637         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
33638         if (( $MDS1_VERSION >= $(version_code 2.16.50) )); then
33639                 barrier_freeze="barrier freeze"
33640                 barrier_thaw="barrier thaw"
33641                 barrier_rescan="barrier rescan"
33642         else
33643                 barrier_freeze="barrier_freeze"
33644                 barrier_thaw="barrier_thaw"
33645                 barrier_rescan="barrier_rescan"
33646         fi
33647
33648         prep_801
33649
33650         stop mds2 || error "(1) Fail to stop mds2"
33651
33652         do_facet mgs $LCTL $barrier_freeze $FSNAME 30
33653
33654         local b_status=$(barrier_stat)
33655         [ "$b_status" = "'expired'" ] || [ "$b_status" = "'failed'" ] || {
33656                 do_facet mgs $LCTL $barrier_thaw $FSNAME
33657                 error "(2) unexpected barrier status $b_status"
33658         }
33659
33660         do_facet mgs $LCTL $barrier_rescan $FSNAME ||
33661                 error "(3) Fail to rescan barrier bitmap"
33662
33663         # Do not reduce barrier time - See LU-11873
33664         do_facet mgs $LCTL $barrier_freeze $FSNAME 20
33665
33666         b_status=$(barrier_stat)
33667         [ "$b_status" = "'frozen'" ] ||
33668                 error "(4) unexpected barrier status $b_status"
33669
33670         do_facet mgs $LCTL $barrier_thaw $FSNAME
33671         b_status=$(barrier_stat)
33672         [ "$b_status" = "'thawed'" ] ||
33673                 error "(5) unexpected barrier status $b_status"
33674
33675         local devname=$(mdsdevname 2)
33676
33677         start mds2 $devname $MDS_MOUNT_OPTS || error "(6) Fail to start mds2"
33678
33679         do_facet mgs $LCTL $barrier_rescan $FSNAME ||
33680                 error "(7) Fail to rescan barrier bitmap"
33681
33682         post_801
33683 }
33684 run_test 801c "rescan barrier bitmap"
33685
33686 test_802b() {
33687         [ $PARALLEL == "yes" ] && skip "skip parallel run"
33688         remote_mds_nodsh && skip "remote MDS with nodsh"
33689
33690         do_facet $SINGLEMDS $LCTL get_param mdt.*.readonly ||
33691                 skip "readonly option not available"
33692
33693         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "(1) fail to mkdir"
33694
33695         cp $LUSTRE/tests/test-framework.sh $DIR/$tdir/ ||
33696                 error "(2) Fail to copy"
33697
33698         # write back all cached data before setting MDT to readonly
33699         cancel_lru_locks
33700         sync_all_data
33701
33702         do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=1
33703         stack_trap "do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=0" EXIT
33704
33705         echo "Modify should be refused"
33706         touch $DIR/$tdir/guard && error "(6) Touch should fail under ro mode"
33707
33708         echo "Read should be allowed"
33709         diff $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh ||
33710                 error "(7) Read should succeed under ro mode"
33711
33712         # disable readonly
33713         do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=0
33714 }
33715 run_test 802b "be able to set MDTs to readonly"
33716
33717 test_802c() {
33718         [ $PARALLEL == "yes" ] && skip "skip parallel run"
33719
33720         do_facet ost1 $LCTL get_param obdfilter.*.readonly ||
33721                 skip "readonly option not available"
33722
33723         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "(1) fail to mkdir"
33724
33725         cp $LUSTRE/tests/test-framework.sh $DIR/$tdir/ ||
33726                 error "(2) Fail to copy"
33727
33728         # write back all cached data before setting OFD to readonly
33729         cancel_lru_locks
33730         sync_all_data
33731
33732         do_facet ost1 $LCTL set_param obdfilter.*.readonly=1
33733         stack_trap "do_facet ost1 $LCTL set_param obdfilter.*.readonly=0" EXIT
33734
33735         echo "Modify should be refused"
33736         touch $DIR/$tdir/guard && error "(6) Touch should fail under ro mode"
33737
33738         echo "Read should be allowed"
33739         diff $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh ||
33740                 error "(7) Read should succeed under ro mode"
33741 }
33742 run_test 802c "be able to set OFDs to readonly"
33743
33744 test_803a() {
33745         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
33746         [ $MDS1_VERSION -lt $(version_code 2.10.54) ] &&
33747                 skip "MDS needs to be newer than 2.10.54"
33748
33749         mkdir_on_mdt0 $DIR/$tdir
33750         # Create some objects on all MDTs to trigger related logs objects
33751         for idx in $(seq $MDSCOUNT); do
33752                 $LFS mkdir -c $MDSCOUNT -i $((idx % $MDSCOUNT)) \
33753                         $DIR/$tdir/dir${idx} ||
33754                         error "Fail to create $DIR/$tdir/dir${idx}"
33755         done
33756
33757         wait_delete_completed # ensure old test cleanups are finished
33758         sleep 3
33759         echo "before create:"
33760         $LFS df -i $MOUNT
33761         local before_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
33762
33763         for i in {1..10}; do
33764                 $LFS mkdir -c 1 -i 1 $DIR/$tdir/foo$i ||
33765                         error "Fail to create $DIR/$tdir/foo$i"
33766         done
33767
33768         # sync ZFS-on-MDS to refresh statfs data
33769         wait_zfs_commit mds1
33770         sleep 3
33771         echo "after create:"
33772         $LFS df -i $MOUNT
33773         local after_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
33774
33775         # allow for an llog to be cleaned up during the test
33776         [ $after_used -ge $((before_used + 10 - 1)) ] ||
33777                 error "before ($before_used) + 10 > after ($after_used)"
33778
33779         for i in {1..10}; do
33780                 rm -rf $DIR/$tdir/foo$i ||
33781                         error "Fail to remove $DIR/$tdir/foo$i"
33782         done
33783
33784         # sync ZFS-on-MDS to refresh statfs data
33785         wait_zfs_commit mds1
33786         wait_delete_completed
33787         sleep 3 # avoid MDT return cached statfs
33788         echo "after unlink:"
33789         $LFS df -i $MOUNT
33790         after_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
33791
33792         # allow for an llog to be created during the test
33793         [ $after_used -le $((before_used + 1)) ] ||
33794                 error "after ($after_used) > before ($before_used) + 1"
33795 }
33796 run_test 803a "verify agent object for remote object"
33797
33798 test_803b() {
33799         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
33800         [ $MDS1_VERSION -lt $(version_code 2.13.56) ] &&
33801                 skip "MDS needs to be newer than 2.13.56"
33802         [ $PARALLEL == "yes" ] && skip "skip parallel run"
33803
33804         for i in $(seq 0 $((MDSCOUNT - 1))); do
33805                 $LFS mkdir -i $i $DIR/$tdir.$i || error "mkdir $tdir.$i"
33806         done
33807
33808         local before=0
33809         local after=0
33810
33811         local tmp
33812
33813         stat $DIR/$tdir.* >/dev/null || error "stat $tdir.*"
33814         for i in $(seq 0 $((MDSCOUNT - 1))); do
33815                 tmp=$(do_facet mds$i $LCTL get_param mdt.*-MDT000$i.md_stats |
33816                         awk '/getattr/ { print $2 }')
33817                 before=$((before + tmp))
33818         done
33819         stat $DIR/$tdir.* >/dev/null || error "stat $tdir.*"
33820         for i in $(seq 0 $((MDSCOUNT - 1))); do
33821                 tmp=$(do_facet mds$i $LCTL get_param mdt.*-MDT000$i.md_stats |
33822                         awk '/getattr/ { print $2 }')
33823                 after=$((after + tmp))
33824         done
33825
33826         [ $before -eq $after ] || error "getattr count $before != $after"
33827 }
33828 run_test 803b "remote object can getattr from cache"
33829
33830 test_804() {
33831         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
33832         [ $MDS1_VERSION -lt $(version_code 2.10.54) ] &&
33833                 skip "MDS needs to be newer than 2.10.54"
33834         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
33835
33836         mkdir -p $DIR/$tdir
33837         $LFS mkdir -c 1 -i 1 $DIR/$tdir/dir0 ||
33838                 error "Fail to create $DIR/$tdir/dir0"
33839
33840         local fid=$($LFS path2fid $DIR/$tdir/dir0)
33841         local dev=$(mdsdevname 2)
33842
33843         do_facet mds2 "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
33844                 grep ${fid} || error "NOT found agent entry for dir0"
33845
33846         $LFS mkdir -c $MDSCOUNT -i 0 $DIR/$tdir/dir1 ||
33847                 error "Fail to create $DIR/$tdir/dir1"
33848
33849         touch $DIR/$tdir/dir1/foo0 ||
33850                 error "Fail to create $DIR/$tdir/dir1/foo0"
33851         fid=$($LFS path2fid $DIR/$tdir/dir1/foo0)
33852         local rc=0
33853
33854         for idx in $(seq $MDSCOUNT); do
33855                 dev=$(mdsdevname $idx)
33856                 do_facet mds${idx} \
33857                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
33858                         grep ${fid} && rc=$idx
33859         done
33860
33861         mv $DIR/$tdir/dir1/foo0 $DIR/$tdir/dir1/foo1 ||
33862                 error "Fail to rename foo0 to foo1"
33863         if [ $rc -eq 0 ]; then
33864                 for idx in $(seq $MDSCOUNT); do
33865                         dev=$(mdsdevname $idx)
33866                         do_facet mds${idx} \
33867                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
33868                         grep ${fid} && rc=$idx
33869                 done
33870         fi
33871
33872         mv $DIR/$tdir/dir1/foo1 $DIR/$tdir/dir1/foo2 ||
33873                 error "Fail to rename foo1 to foo2"
33874         if [ $rc -eq 0 ]; then
33875                 for idx in $(seq $MDSCOUNT); do
33876                         dev=$(mdsdevname $idx)
33877                         do_facet mds${idx} \
33878                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
33879                         grep ${fid} && rc=$idx
33880                 done
33881         fi
33882
33883         [ $rc -ne 0 ] || error "NOT found agent entry for foo"
33884
33885         ln $DIR/$tdir/dir1/foo2 $DIR/$tdir/dir0/guard ||
33886                 error "Fail to link to $DIR/$tdir/dir1/foo2"
33887         mv $DIR/$tdir/dir1/foo2 $DIR/$tdir/dir1/foo0 ||
33888                 error "Fail to rename foo2 to foo0"
33889         unlink $DIR/$tdir/dir1/foo0 ||
33890                 error "Fail to unlink $DIR/$tdir/dir1/foo0"
33891         rm -rf $DIR/$tdir/dir0 ||
33892                 error "Fail to rm $DIR/$tdir/dir0"
33893
33894         for idx in $(seq $MDSCOUNT); do
33895                 rc=0
33896
33897                 stop mds${idx}
33898                 dev=$(mdsdevname $idx)
33899                 run_e2fsck $(facet_active_host mds$idx) $dev -n ||
33900                         rc=$?
33901                 start mds${idx} $dev $MDS_MOUNT_OPTS ||
33902                         error "mount mds$idx failed"
33903                 df $MOUNT > /dev/null 2>&1
33904
33905                 # e2fsck should not return error
33906                 [ $rc -eq 0 ] ||
33907                         error "e2fsck detected error on MDT${idx}: rc=$rc"
33908         done
33909 }
33910 run_test 804 "verify agent entry for remote entry"
33911
33912 cleanup_805() {
33913         do_facet $SINGLEMDS zfs set quota=$old $fsset
33914         unlinkmany $DIR/$tdir/f- 1000000
33915         trap 0
33916 }
33917
33918 test_805() {
33919         local zfs_version=$(do_facet mds1 cat /sys/module/zfs/version)
33920         [ "$mds1_FSTYPE" != "zfs" ] && skip "ZFS specific test"
33921         [ $(version_code $zfs_version) -lt $(version_code 0.7.2) ] &&
33922                 skip "netfree not implemented before 0.7"
33923         [[ $MDS1_VERSION -ge $(version_code 2.10.57) ]] ||
33924                 skip "Need MDS version at least 2.10.57"
33925
33926         local fsset
33927         local freekb
33928         local usedkb
33929         local old
33930         local quota
33931         local pref="osd-zfs.$FSNAME-MDT0000."
33932
33933         # limit available space on MDS dataset to meet nospace issue
33934         # quickly. then ZFS 0.7.2 can use reserved space if asked
33935         # properly (using netfree flag in osd_declare_destroy()
33936         fsset=$(do_facet $SINGLEMDS lctl get_param -n $pref.mntdev)
33937         old=$(do_facet $SINGLEMDS zfs get -H quota $fsset | \
33938                 gawk '{print $3}')
33939         freekb=$(do_facet $SINGLEMDS lctl get_param -n $pref.kbytesfree)
33940         usedkb=$(do_facet $SINGLEMDS lctl get_param -n $pref.kbytestotal)
33941         let "usedkb=usedkb-freekb"
33942         let "freekb=freekb/2"
33943         if let "freekb > 5000"; then
33944                 let "freekb=5000"
33945         fi
33946         do_facet $SINGLEMDS zfs set quota=$(((usedkb+freekb)*1024)) $fsset
33947         trap cleanup_805 EXIT
33948         mkdir_on_mdt0 $DIR/$tdir
33949         $LFS setstripe -E 1M -c2 -E 4M -c2 -E -1 -c2 $DIR/$tdir ||
33950                 error "Can't set PFL layout"
33951         createmany -m $DIR/$tdir/f- 1000000 && error "ENOSPC wasn't met"
33952         rm -rf $DIR/$tdir || error "not able to remove"
33953         do_facet $SINGLEMDS zfs set quota=$old $fsset
33954         trap 0
33955 }
33956 run_test 805 "ZFS can remove from full fs"
33957
33958 # Size-on-MDS test
33959 check_lsom_data()
33960 {
33961         local file=$1
33962         local expect=$(stat -c %s $file)
33963         local msg=$2
33964
33965         check_lsom_size $1 $expect $msg
33966
33967         local blocks=$($LFS getsom -b $file)
33968         expect=$(stat -c %b $file)
33969         [[ $blocks == $expect ]] ||
33970                 error "$msg $file expected blocks: $expect, got: $blocks"
33971 }
33972
33973 check_lsom_size()
33974 {
33975         local size
33976         local expect=$2
33977         local msg=$3
33978
33979         cancel_lru_locks mdc
33980
33981         size=$($LFS getsom -s $1)
33982         [[ $size == $expect ]] ||
33983                 error "$msg $file expected size: $expect, got: $size"
33984 }
33985
33986 test_806() {
33987         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
33988                 skip "Need MDS version at least 2.11.52"
33989
33990         local bs=1048576
33991
33992         $LFS setstripe -c-1 $DIR/$tfile || error "setstripe $tfile failed"
33993
33994         disable_opencache
33995         stack_trap "restore_opencache"
33996
33997         # single-threaded write
33998         echo "Test SOM for single-threaded write"
33999         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 ||
34000                 error "write $tfile failed"
34001         check_lsom_size $DIR/$tfile $bs "(0)"
34002         # Test SOM with DIO write (dd truncates to 0)
34003         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 oflag=direct ||
34004                 error "write $tfile failed"
34005         check_lsom_size $DIR/$tfile $bs "(1)"
34006
34007         local num=32
34008         local size=$(($num * $bs))
34009         local offset=0
34010         local i
34011
34012         echo "Test SOM for single client multi-threaded($num) write"
34013         $TRUNCATE $DIR/$tfile 0
34014         for ((i = 0; i < $num; i++)); do
34015                 $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
34016                 local pids[$i]=$!
34017                 offset=$((offset + $bs))
34018         done
34019         for (( i=0; i < $num; i++ )); do
34020                 wait ${pids[$i]}
34021         done
34022         check_lsom_size $DIR/$tfile $size "(2)"
34023
34024         $TRUNCATE $DIR/$tfile 0
34025         for ((i = 0; i < $num; i++)); do
34026                 offset=$((offset - $bs))
34027                 $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
34028                 local pids[$i]=$!
34029         done
34030         for (( i=0; i < $num; i++ )); do
34031                 wait ${pids[$i]}
34032         done
34033         check_lsom_size $DIR/$tfile $size "(3)"
34034
34035         # multi-client writes
34036         num=$(get_node_count ${CLIENTS//,/ })
34037         size=$(($num * $bs))
34038         offset=0
34039         i=0
34040
34041         echo "Test SOM for multi-client ($num) writes"
34042         $TRUNCATE $DIR/$tfile 0
34043         for client in ${CLIENTS//,/ }; do
34044                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
34045                 local pids[$i]=$!
34046                 i=$((i + 1))
34047                 offset=$((offset + $bs))
34048         done
34049         for (( i=0; i < $num; i++ )); do
34050                 wait ${pids[$i]}
34051         done
34052         check_lsom_size $DIR/$tfile $offset "(4)"
34053
34054         i=0
34055         $TRUNCATE $DIR/$tfile 0
34056         for client in ${CLIENTS//,/ }; do
34057                 offset=$((offset - $bs))
34058                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
34059                 local pids[$i]=$!
34060                 i=$((i + 1))
34061         done
34062         for (( i=0; i < $num; i++ )); do
34063                 wait ${pids[$i]}
34064         done
34065         check_lsom_size $DIR/$tfile $size "(5)"
34066
34067         # verify SOM blocks count
34068         echo "Verify SOM block count"
34069         $TRUNCATE $DIR/$tfile 0
34070         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs))YSc ||
34071                 error "failed to write file $tfile with fdatasync and fstat"
34072         check_lsom_data $DIR/$tfile "(6)"
34073
34074         $TRUNCATE $DIR/$tfile 0
34075         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs * 2))Yc ||
34076                 error "failed to write file $tfile with fdatasync"
34077         check_lsom_data $DIR/$tfile "(7)"
34078
34079         $TRUNCATE $DIR/$tfile 0
34080         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:O_SYNC:w$((bs * 3))c ||
34081                 error "failed to write file $tfile with sync IO"
34082         check_lsom_data $DIR/$tfile "(8)"
34083
34084         # verify truncate
34085         echo "Test SOM for truncate"
34086         # use ftruncate to sync blocks on close request
34087         $MULTIOP $DIR/$tfile oO_WRONLY:T16384c
34088         check_lsom_size $DIR/$tfile 16384 "(9)"
34089         check_lsom_data $DIR/$tfile "(10)"
34090
34091         $TRUNCATE $DIR/$tfile 1234
34092         check_lsom_size $DIR/$tfile 1234 "(11)"
34093         # sync blocks on the MDT
34094         $MULTIOP $DIR/$tfile oc
34095         check_lsom_data $DIR/$tfile "(12)"
34096 }
34097 run_test 806 "Verify Lazy Size on MDS"
34098
34099 verify_som_sync_utility() {
34100         local utility=$1
34101         local use_llsom_sync=false
34102
34103         [[ -z "$FILESET" ]] || skip "Not functional for FILESET set"
34104         [[ $MDS1_VERSION -ge $(version_code 2.11.52) ]] ||
34105                 skip "Need MDS version at least 2.11.52"
34106
34107         case $utility in
34108                 llsom_sync ) use_llsom_sync=true ;;
34109                 somsync ) use_llsom_sync=false ;;
34110                 *) error "invalid utility $utility" ;;
34111         esac
34112
34113         if $use_llsom_sync; then
34114                 # Registration step
34115                 changelog_register || error "changelog_register failed"
34116                 local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
34117                 changelog_users $SINGLEMDS | grep -q $cl_user ||
34118                         error "User $cl_user not found in changelog_users"
34119         fi
34120
34121         rm -rf $DIR/$tdir || error "rm $tdir failed"
34122         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
34123         touch $DIR/$tdir/trunc || error "touch $tdir/trunc failed"
34124         $TRUNCATE $DIR/$tdir/trunc 1024 || error "truncate $tdir/trunc failed"
34125         $TRUNCATE $DIR/$tdir/trunc 1048576 ||
34126                 error "truncate $tdir/trunc failed"
34127
34128         local bs=1048576
34129         echo "Test SOM for single-threaded write with fsync"
34130         dd if=/dev/zero of=$DIR/$tdir/single_dd bs=$bs count=1 ||
34131                 error "write $tfile failed"
34132         sync;sync;sync
34133
34134         # multi-client wirtes
34135         local num=$(get_node_count ${CLIENTS//,/ })
34136         local offset=0
34137         local -a pids
34138
34139         echo "Test SOM for multi-client ($num) writes"
34140         touch $DIR/$tfile || error "touch $tfile failed"
34141         $TRUNCATE $DIR/$tfile 0
34142         for client in ${CLIENTS//,/ }; do
34143                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
34144                 pids+=( $! )
34145                 offset=$((offset + bs))
34146         done
34147         wait ${pids[@]}
34148
34149         do_rpc_nodes "$CLIENTS" cancel_lru_locks osc
34150         do_nodes "$CLIENTS" "sync ; sleep 5 ; sync"
34151
34152         if $use_llsom_sync; then
34153                 $LSOM_SYNC -u $cl_user -m $FSNAME-MDT0000 $MOUNT ||
34154                         error "$LSOM_SYNC failed"
34155         else
34156                 $LFS somsync $DIR/$tfile ||
34157                         error "$LFS somsync $DIR/$tfile failed"
34158                 find $DIR/$tdir -type f | xargs $LFS path2fid |
34159                         awk '{print $2}' | xargs $LFS somsync --by-fid $DIR ||
34160                                 error "$LFS somsync --by-fid $DIR failed"
34161         fi
34162
34163         check_lsom_data $DIR/$tdir/trunc "(0)"
34164         check_lsom_data $DIR/$tdir/single_dd "(1)"
34165         check_lsom_data $DIR/$tfile "(2)"
34166
34167         rm -rf $DIR/$tdir
34168         # Deregistration step
34169         ! $use_llsom_sync || changelog_deregister ||
34170                 error "changelog_deregister failed"
34171 }
34172
34173 test_807a() {
34174         verify_som_sync_utility llsom_sync
34175 }
34176 run_test 807a "verify LSOM syncing tool"
34177
34178 test_807b() {
34179         verify_som_sync_utility somsync
34180 }
34181 run_test 807b "verify lfs somsync utility"
34182
34183 check_som_nologged()
34184 {
34185         local lines=$($LFS changelog $FSNAME-MDT0000 |
34186                 grep 'x=trusted.som' | wc -l)
34187         [ $lines -ne 0 ] && error "trusted.som xattr is logged in Changelogs"
34188 }
34189
34190 test_808() {
34191         [ $MDS1_VERSION -lt $(version_code 2.11.55) ] &&
34192                 skip "Need MDS version at least 2.11.55"
34193
34194         # Registration step
34195         changelog_register || error "changelog_register failed"
34196
34197         touch $DIR/$tfile || error "touch $tfile failed"
34198         check_som_nologged
34199
34200         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=1 ||
34201                 error "write $tfile failed"
34202         check_som_nologged
34203
34204         $TRUNCATE $DIR/$tfile 1234
34205         check_som_nologged
34206
34207         $TRUNCATE $DIR/$tfile 1048576
34208         check_som_nologged
34209
34210         # Deregistration step
34211         changelog_deregister || error "changelog_deregister failed"
34212 }
34213 run_test 808 "Check trusted.som xattr not logged in Changelogs"
34214
34215 check_som_nodata()
34216 {
34217         $LFS getsom $1
34218         [[ $? -eq 61 ]] || error "DoM-only file $1 has SOM xattr"
34219 }
34220
34221 test_809() {
34222         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
34223                 skip "Need MDS version at least 2.11.56"
34224
34225         $LFS setstripe -E 1M -L mdt $DIR/$tfile ||
34226                 error "failed to create DoM-only file $DIR/$tfile"
34227         touch $DIR/$tfile || error "touch $tfile failed"
34228         check_som_nodata $DIR/$tfile
34229
34230         dd if=/dev/zero of=$DIR/$tfile bs=2048 count=1 ||
34231                 error "write $tfile failed"
34232         check_som_nodata $DIR/$tfile
34233
34234         $TRUNCATE $DIR/$tfile 1234
34235         check_som_nodata $DIR/$tfile
34236
34237         $TRUNCATE $DIR/$tfile 4097
34238         check_som_nodata $DIR/$file
34239 }
34240 run_test 809 "Verify no SOM xattr store for DoM-only files"
34241
34242 test_810() {
34243         [ $PARALLEL == "yes" ] && skip "skip parallel run"
34244         $GSS && skip_env "could not run with gss"
34245         [[ $OST1_VERSION -gt $(version_code 2.12.58) ]] ||
34246                 skip "OST < 2.12.58 doesn't align checksum"
34247
34248         set_checksums 1
34249         stack_trap "set_checksums $ORIG_CSUM" EXIT
34250         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
34251
34252         local csum
34253         local before
34254         local after
34255         for csum in $CKSUM_TYPES; do
34256                 #define OBD_FAIL_OSC_NO_GRANT   0x411
34257                 $LCTL set_param osc.*.checksum_type=$csum fail_loc=0x411
34258                 for i in "10240 0" "10000 0" "4000 1" "500 1"; do
34259                         eval set -- $i
34260                         dd if=/dev/urandom of=$DIR/$tfile bs=$1 count=2 seek=$2
34261                         before=$(md5sum $DIR/$tfile)
34262                         $LCTL set_param ldlm.namespaces.*osc*.lru_size=clear
34263                         after=$(md5sum $DIR/$tfile)
34264                         [ "$before" == "$after" ] ||
34265                                 error "$csum: $before != $after bs=$1 seek=$2"
34266                 done
34267         done
34268 }
34269 run_test 810 "partial page writes on ZFS (LU-11663)"
34270
34271 test_812a() {
34272         [ $OST1_VERSION -lt $(version_code 2.12.51) ] &&
34273                 skip "OST < 2.12.51 doesn't support this fail_loc"
34274         local old
34275
34276         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
34277         $LCTL set_param osc.*.idle_timeout=10
34278         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
34279
34280         $LFS setstripe -c 1 -i 0 $DIR/$tfile
34281         # ensure ost1 is connected
34282         stat $DIR/$tfile >/dev/null || error "can't stat"
34283         wait_osc_import_state client ost1 FULL
34284         # no locks, no reqs to let the connection idle
34285         cancel_lru_locks osc
34286
34287         # delay OST_DISCONNECT on OST1 to put OSC into intermediate state
34288 #define OBD_FAIL_OST_DISCONNECT_DELAY    0x245
34289         do_facet ost1 "$LCTL set_param fail_loc=0x245 fail_val=8"
34290         wait_osc_import_state client ost1 CONNECTING
34291         do_facet ost1 "$LCTL set_param fail_loc=0 fail_val=0"
34292
34293         stat $DIR/$tfile >/dev/null || error "can't stat file"
34294 }
34295 run_test 812a "do not drop reqs generated when imp is going to idle (LU-11951)"
34296
34297 test_812b() { # LU-12378
34298         [ $OST1_VERSION -lt $(version_code 2.12.51) ] &&
34299                 skip "OST < 2.12.51 doesn't support this fail_loc"
34300         local old
34301
34302         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
34303         $LCTL set_param osc.*.idle_timeout=10
34304         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
34305
34306         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "setstripe failed"
34307         # ensure ost1 is connected
34308         stat $DIR/$tfile >/dev/null || error "can't stat"
34309         wait_osc_import_state client ost1 FULL
34310         # no locks, no reqs to let the connection idle
34311         cancel_lru_locks osc
34312
34313         # delay OST_DISCONNECT on OST1 to put OSC into intermediate state
34314 #define OBD_FAIL_OST_DISCONNECT_DELAY    0x245
34315         do_facet ost1 "$LCTL set_param fail_loc=0x245 fail_val=8"
34316         wait_osc_import_state client ost1 CONNECTING
34317         do_facet ost1 "$LCTL set_param fail_loc=0 fail_val=0"
34318
34319         $LFS quota -u 0 $DIR/ || error "lfs quota should succeed"
34320         wait_osc_import_state client ost1 IDLE
34321 }
34322 run_test 812b "do not drop no resend request for idle connect"
34323
34324 test_812c() {
34325         local old
34326
34327         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
34328
34329         $LFS setstripe -c 1 -o 0 $DIR/$tfile
34330         $LFS getstripe $DIR/$tfile
34331         $LCTL set_param osc.*.idle_timeout=10
34332         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
34333         # ensure ost1 is connected
34334         stat $DIR/$tfile >/dev/null || error "can't stat"
34335         wait_osc_import_state client ost1 FULL
34336         # no locks, no reqs to let the connection idle
34337         cancel_lru_locks osc
34338
34339 #define OBD_FAIL_PTLRPC_IDLE_RACE        0x533
34340         $LCTL set_param fail_loc=0x80000533
34341         sleep 15
34342         dd if=/dev/zero of=$DIR/$tfile count=1 conv=sync || error "dd failed"
34343 }
34344 run_test 812c "idle import vs lock enqueue race"
34345
34346 test_813() {
34347         local file_heat_sav=$($LCTL get_param -n llite.*.file_heat 2>/dev/null)
34348         [ -z "$file_heat_sav" ] && skip "no file heat support"
34349
34350         local readsample
34351         local writesample
34352         local readbyte
34353         local writebyte
34354         local readsample1
34355         local writesample1
34356         local readbyte1
34357         local writebyte1
34358
34359         local period_second=$($LCTL get_param -n llite.*.heat_period_second)
34360         local decay_pct=$($LCTL get_param -n llite.*.heat_decay_percentage)
34361
34362         $LCTL set_param -n llite.*.file_heat=1
34363         echo "Turn on file heat"
34364         echo "Period second: $period_second, Decay percentage: $decay_pct"
34365
34366         echo "QQQQ" > $DIR/$tfile
34367         echo "QQQQ" > $DIR/$tfile
34368         echo "QQQQ" > $DIR/$tfile
34369         cat $DIR/$tfile > /dev/null
34370         cat $DIR/$tfile > /dev/null
34371         cat $DIR/$tfile > /dev/null
34372         cat $DIR/$tfile > /dev/null
34373
34374         local out=$($LFS heat_get $DIR/$tfile)
34375
34376         $LFS heat_get $DIR/$tfile
34377         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34378         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34379         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34380         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34381
34382         [ $readsample -le 4 ] || error "read sample ($readsample) is wrong"
34383         [ $writesample -le 3 ] || error "write sample ($writesample) is wrong"
34384         [ $readbyte -le 20 ] || error "read bytes ($readbyte) is wrong"
34385         [ $writebyte -le 15 ] || error "write bytes ($writebyte) is wrong"
34386
34387         sleep $((period_second + 3))
34388         echo "Sleep $((period_second + 3)) seconds..."
34389         # The recursion formula to calculate the heat of the file f is as
34390         # follow:
34391         # Hi+1(f) = (1-P)*Hi(f)+ P*Ci
34392         # Where Hi is the heat value in the period between time points i*I and
34393         # (i+1)*I; Ci is the access count in the period; the symbol P refers
34394         # to the weight of Ci.
34395         out=$($LFS heat_get $DIR/$tfile)
34396         $LFS heat_get $DIR/$tfile
34397         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34398         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34399         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34400         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34401
34402         [ $(bc <<< "$readsample <= 4 * $decay_pct / 100") -eq 1 ] ||
34403                 error "read sample ($readsample) is wrong"
34404         [ $(bc <<< "$writesample <= 3 * $decay_pct / 100") -eq 1 ] ||
34405                 error "write sample ($writesample) is wrong"
34406         [ $(bc <<< "$readbyte <= 20 * $decay_pct / 100") -eq 1 ] ||
34407                 error "read bytes ($readbyte) is wrong"
34408         [ $(bc <<< "$writebyte <= 15 * $decay_pct / 100") -eq 1 ] ||
34409                 error "write bytes ($writebyte) is wrong"
34410
34411         echo "QQQQ" > $DIR/$tfile
34412         echo "QQQQ" > $DIR/$tfile
34413         echo "QQQQ" > $DIR/$tfile
34414         cat $DIR/$tfile > /dev/null
34415         cat $DIR/$tfile > /dev/null
34416         cat $DIR/$tfile > /dev/null
34417         cat $DIR/$tfile > /dev/null
34418
34419         sleep $((period_second + 3))
34420         echo "Sleep $((period_second + 3)) seconds..."
34421
34422         out=$($LFS heat_get $DIR/$tfile)
34423         $LFS heat_get $DIR/$tfile
34424         readsample1=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34425         writesample1=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34426         readbyte1=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34427         writebyte1=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34428
34429         [ $(bc <<< "$readsample1 <= ($readsample * (100 - $decay_pct) + \
34430                 4 * $decay_pct) / 100") -eq 1 ] ||
34431                 error "read sample ($readsample1) is wrong"
34432         [ $(bc <<< "$writesample1 <= ($writesample * (100 - $decay_pct) + \
34433                 3 * $decay_pct) / 100") -eq 1 ] ||
34434                 error "write sample ($writesample1) is wrong"
34435         [ $(bc <<< "$readbyte1 <= ($readbyte * (100 - $decay_pct) + \
34436                 20 * $decay_pct) / 100") -eq 1 ] ||
34437                 error "read bytes ($readbyte1) is wrong"
34438         [ $(bc <<< "$writebyte1 <= ($writebyte * (100 - $decay_pct) + \
34439                 15 * $decay_pct) / 100") -eq 1 ] ||
34440                 error "write bytes ($writebyte1) is wrong"
34441
34442         echo "Turn off file heat for the file $DIR/$tfile"
34443         $LFS heat_set -o $DIR/$tfile
34444
34445         echo "QQQQ" > $DIR/$tfile
34446         echo "QQQQ" > $DIR/$tfile
34447         echo "QQQQ" > $DIR/$tfile
34448         cat $DIR/$tfile > /dev/null
34449         cat $DIR/$tfile > /dev/null
34450         cat $DIR/$tfile > /dev/null
34451         cat $DIR/$tfile > /dev/null
34452
34453         out=$($LFS heat_get $DIR/$tfile)
34454         $LFS heat_get $DIR/$tfile
34455         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34456         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34457         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34458         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34459
34460         [ $readsample -eq 0 ] || error "read sample ($readsample) is wrong"
34461         [ $writesample -eq 0 ] || error "write sample ($writesample) is wrong"
34462         [ $readbyte -eq 0 ] || error "read bytes ($readbyte) is wrong"
34463         [ $writebyte -eq 0 ] || error "write bytes ($writebyte) is wrong"
34464
34465         echo "Trun on file heat for the file $DIR/$tfile"
34466         $LFS heat_set -O $DIR/$tfile
34467
34468         echo "QQQQ" > $DIR/$tfile
34469         echo "QQQQ" > $DIR/$tfile
34470         echo "QQQQ" > $DIR/$tfile
34471         cat $DIR/$tfile > /dev/null
34472         cat $DIR/$tfile > /dev/null
34473         cat $DIR/$tfile > /dev/null
34474         cat $DIR/$tfile > /dev/null
34475
34476         out=$($LFS heat_get $DIR/$tfile)
34477         $LFS heat_get $DIR/$tfile
34478         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34479         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34480         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34481         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34482
34483         [ $readsample -gt 0 ] || error "read sample ($readsample) is wrong"
34484         [ $writesample -gt 0 ] || error "write sample ($writesample) is wrong"
34485         [ $readbyte -gt 0 ] || error "read bytes ($readbyte) is wrong"
34486         [ $writebyte -gt 0 ] || error "write bytes ($writebyte) is wrong"
34487
34488         $LFS heat_set -c $DIR/$tfile
34489         $LCTL set_param -n llite.*.file_heat=0
34490         echo "Turn off file heat support for the Lustre filesystem"
34491
34492         echo "QQQQ" > $DIR/$tfile
34493         echo "QQQQ" > $DIR/$tfile
34494         echo "QQQQ" > $DIR/$tfile
34495         cat $DIR/$tfile > /dev/null
34496         cat $DIR/$tfile > /dev/null
34497         cat $DIR/$tfile > /dev/null
34498         cat $DIR/$tfile > /dev/null
34499
34500         out=$($LFS heat_get $DIR/$tfile)
34501         $LFS heat_get $DIR/$tfile
34502         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
34503         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
34504         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
34505         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
34506
34507         [ $readsample -eq 0 ] || error "read sample ($readsample) is wrong"
34508         [ $writesample -eq 0 ] || error "write sample ($writesample) is wrong"
34509         [ $readbyte -eq 0 ] || error "read bytes ($readbyte) is wrong"
34510         [ $writebyte -eq 0 ] || error "write bytes ($writebyte) is wrong"
34511
34512         $LCTL set_param -n llite.*.file_heat=$file_heat_sav
34513         rm -f $DIR/$tfile
34514 }
34515 run_test 813 "File heat verfication"
34516
34517 test_814()
34518 {
34519         dd of=$DIR/$tfile seek=128 bs=1k < /dev/null
34520         echo -n y >> $DIR/$tfile
34521         cp --sparse=always $DIR/$tfile $DIR/${tfile}.cp || error "copy failed"
34522         diff $DIR/$tfile $DIR/${tfile}.cp || error "files should be same"
34523 }
34524 run_test 814 "sparse cp works as expected (LU-12361)"
34525
34526 test_815()
34527 {
34528         writeme -b 100 $DIR/$tfile || error "write 100 bytes failed"
34529         writeme -b 0 $DIR/$tfile || error "write 0 byte failed"
34530 }
34531 run_test 815 "zero byte tiny write doesn't hang (LU-12382)"
34532
34533 test_816() {
34534         local ost1_imp=$(get_osc_import_name client ost1)
34535         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
34536                          cut -d'.' -f2)
34537         local old
34538
34539         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
34540         $LCTL set_param osc.*.idle_timeout=10
34541         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
34542
34543         $LFS setstripe -c 1 -i 0 $DIR/$tfile
34544         # ensure ost1 is connected
34545
34546         stat $DIR/$tfile >/dev/null || error "can't stat"
34547         wait_osc_import_state client ost1 FULL
34548         # no locks, no reqs to let the connection idle
34549         cancel_lru_locks osc
34550         lru_resize_disable osc
34551         local before
34552         local now
34553         before=$($LCTL get_param -n \
34554                  ldlm.namespaces.$imp_name.lru_size)
34555
34556         wait_osc_import_state client ost1 IDLE
34557         dd if=/dev/null of=$DIR/$tfile bs=1k count=1 conv=sync
34558         now=$($LCTL get_param -n \
34559               ldlm.namespaces.$imp_name.lru_size)
34560         [ $before == $now ] || error "lru_size changed $before != $now"
34561 }
34562 run_test 816 "do not reset lru_resize on idle reconnect"
34563
34564 cleanup_817() {
34565         umount $tmpdir
34566         exportfs -u localhost:$DIR/nfsexp
34567         rm -rf $DIR/nfsexp
34568 }
34569
34570 test_817() {
34571         systemctl restart nfs-server.service || skip "failed to restart nfsd"
34572
34573         mkdir -p $DIR/nfsexp
34574         exportfs -orw,no_root_squash localhost:$DIR/nfsexp ||
34575                 error "failed to export nfs"
34576
34577         tmpdir=$(mktemp -d /tmp/nfs-XXXXXX)
34578         stack_trap cleanup_817 EXIT
34579
34580         mount -t nfs -orw localhost:$DIR/nfsexp $tmpdir ||
34581                 error "failed to mount nfs to $tmpdir"
34582
34583         cp /bin/true $tmpdir
34584         $DIR/nfsexp/true || error "failed to execute 'true' command"
34585 }
34586 run_test 817 "nfsd won't cache write lock for exec file"
34587
34588 test_818() {
34589         test_mkdir -i0 -c1 $DIR/$tdir
34590         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
34591         $LFS setstripe -c1 -i1 $DIR/$tdir/$tfile
34592         stop $SINGLEMDS
34593
34594         # restore osp-syn threads
34595         stack_trap "fail $SINGLEMDS"
34596
34597         # disable console ratelimit
34598         local rl=$(do_facet mds1 $LCTL get_param -n console_ratelimit)
34599         do_facet mds1 $LCTL set_param console_ratelimit=0
34600         stack_trap "do_facet mds1 $LCTL set_param console_ratelimit=$rl"
34601
34602         #define OBD_FAIL_OSP_CANT_PROCESS_LLOG          0x2105
34603         do_facet $SINGLEMDS lctl set_param fail_loc=0x80002105
34604         start $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) $MDS_MOUNT_OPTS ||
34605                 error "start $SINGLEMDS failed"
34606         rm -rf $DIR/$tdir
34607
34608         local testid=$(echo $TESTNAME | tr '_' ' ')
34609
34610         do_facet mds1 dmesg | tac | sed "/$testid/,$ d" |
34611                 grep "run LFSCK" || error "run LFSCK is not suggested"
34612 }
34613 run_test 818 "unlink with failed llog"
34614
34615 test_819a() {
34616         stack_trap "rm -f $DIR/$tfile"
34617         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
34618         cancel_lru_locks osc
34619         #define OBD_FAIL_OST_2BIG_NIOBUF                0x248
34620         do_facet $SINGLEMDS lctl set_param fail_loc=0x80000248
34621         dd if=$DIR/$tfile of=/dev/null bs=1M count=1
34622         rm -f $TDIR/$tfile
34623 }
34624 run_test 819a "too big niobuf in read"
34625
34626 test_819b() {
34627         stack_trap "rm -f $DIR/$tfile"
34628         #define OBD_FAIL_OST_2BIG_NIOBUF                0x248
34629         do_facet $SINGLEMDS lctl set_param fail_loc=0x80000248
34630         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
34631         cancel_lru_locks osc
34632         sleep 1
34633         rm -f $TDIR/$tfile
34634 }
34635 run_test 819b "too big niobuf in write"
34636
34637
34638 function test_820_start_ost() {
34639         sleep 5
34640
34641         for num in $(seq $OSTCOUNT); do
34642                 start ost$num $(ostdevname $num) $OST_MOUNT_OPTS
34643         done
34644 }
34645
34646 test_820() {
34647         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
34648
34649         mkdir $DIR/$tdir
34650         umount_client $MOUNT || error "umount failed"
34651         for num in $(seq $OSTCOUNT); do
34652                 stop ost$num
34653         done
34654
34655         # mount client with no active OSTs
34656         # so that the client can't initialize max LOV EA size
34657         # from OSC notifications
34658         mount_client $MOUNT || error "mount failed"
34659         # delay OST starting to keep this 0 max EA size for a while
34660         test_820_start_ost &
34661
34662         # create a directory on MDS2
34663         test_mkdir -i 1 -c1 $DIR/$tdir/mds2 ||
34664                 error "Failed to create directory"
34665         # open intent should update default EA size
34666         # see mdc_update_max_ea_from_body()
34667         # notice this is the very first RPC to MDS2
34668         out=$(cp /etc/services $DIR/$tdir/mds2 2>&1)
34669         ret=$?
34670         echo $out
34671         # With SSK, this situation can lead to -EPERM being returned.
34672         # In that case, simply retry.
34673         if [ $ret -ne 0 ] && $SHARED_KEY; then
34674                 if echo "$out" | grep -q "not permitted"; then
34675                         cp /etc/services $DIR/$tdir/mds2
34676                         ret=$?
34677                 fi
34678         fi
34679         [ $ret -eq 0 ] || error "Failed to copy files to mds$n"
34680 }
34681 run_test 820 "update max EA from open intent"
34682
34683 test_823() {
34684         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
34685         local OST_MAX_PRECREATE=20000
34686
34687         (( $MDS1_VERSION >= $(version_code 2.14.56) )) ||
34688                 skip "Need MDS version at least 2.14.56"
34689
34690         save_lustre_params mds1 \
34691                 "osp.$FSNAME-OST*-osc-MDT0000.max_create_count" > $p
34692         do_facet $SINGLEMDS "$LCTL set_param -n \
34693                 osp.$FSNAME-OST*MDT0000.max_create_count=0"
34694         do_facet $SINGLEMDS "$LCTL set_param -n \
34695                 osp.$FSNAME-OST0000*MDT0000.max_create_count=$OST_MAX_PRECREATE"
34696
34697         stack_trap "restore_lustre_params < $p; rm $p"
34698
34699         do_facet $SINGLEMDS "$LCTL set_param -n \
34700                 osp.$FSNAME-OST*-osc-MDT*.create_count=100200"
34701
34702         local count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
34703                       osp.$FSNAME-OST0000*MDT0000.create_count")
34704         local max=$(do_facet $SINGLEMDS "$LCTL get_param -n \
34705                     osp.$FSNAME-OST0000*MDT0000.max_create_count")
34706         local expect_count=$(((($max/2)/256) * 256))
34707
34708         log "setting create_count to 100200:"
34709         log " -result- count: $count with max: $max, expecting: $expect_count"
34710
34711         [[ $count -eq expect_count ]] ||
34712                 error "Create count not set to max precreate."
34713 }
34714 run_test 823 "Setting create_count > OST_MAX_PRECREATE is lowered to maximum"
34715
34716 test_831() {
34717         [[ $MDS1_VERSION -lt $(version_code 2.14.56) ]] &&
34718                 skip "Need MDS version 2.14.56"
34719
34720         local sync_changes=$(do_facet $SINGLEMDS \
34721                 $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
34722
34723         [ "$sync_changes" -gt 100 ] &&
34724                 skip "Sync changes $sync_changes > 100 already"
34725
34726         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
34727
34728         $LFS mkdir -i 0 $DIR/$tdir
34729         $LFS setstripe -c 1 -i 0 $DIR/$tdir
34730
34731         save_lustre_params mds1 \
34732                 "osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes" > $p
34733         save_lustre_params mds1 \
34734                 "osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress" >> $p
34735
34736         do_facet mds1 "$LCTL set_param -n \
34737                 osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes=100 \
34738                 osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress=128"
34739         stack_trap "restore_lustre_params < $p" EXIT
34740
34741         createmany -o $DIR/$tdir/f- 1000
34742         unlinkmany $DIR/$tdir/f- 1000 &
34743         local UNLINK_PID=$!
34744
34745         while sleep 1; do
34746                 sync_changes=$(do_facet mds1 \
34747                 $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
34748                 # the check in the code is racy, fail the test
34749                 # if the value above the limit by 10.
34750                 [ $sync_changes -gt 110 ] && {
34751                         kill -2 $UNLINK_PID
34752                         wait
34753                         error "osp changes throttling failed, $sync_changes>110"
34754                 }
34755                 kill -0 $UNLINK_PID 2> /dev/null || break
34756         done
34757         wait
34758 }
34759 run_test 831 "throttling unlink/setattr queuing on OSP"
34760
34761 test_832() {
34762         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
34763         (( $MDS1_VERSION >= $(version_code 2.15.52) )) ||
34764                 skip "Need MDS version 2.15.52+"
34765         is_rmentry_supported || skip "rm_entry not supported"
34766
34767         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
34768         mkdir $DIR/$tdir/local_dir || error "mkdir local_dir failed"
34769         mkdir_on_mdt -i 1 $DIR/$tdir/remote_dir ||
34770                 error "mkdir remote_dir failed"
34771         $LFS mkdir -c $MDSCOUNT $DIR/$tdir/striped_dir ||
34772                 error "mkdir striped_dir failed"
34773         touch $DIR/$tdir/file || error "touch file failed"
34774         $LFS rm_entry $DIR/$tdir/* || error "lfs rm_entry $tdir/* failed"
34775         [ -z "$(ls -A $DIR/$tdir)" ] || error "$tdir not empty"
34776 }
34777 run_test 832 "lfs rm_entry"
34778
34779 test_833() {
34780         local file=$DIR/$tfile
34781
34782         stack_trap "rm -f $file" EXIT
34783         dd if=/dev/zero of=$file bs=1M count=50 || error "Write $file failed"
34784
34785         local wpid
34786         local rpid
34787         local rpid2
34788
34789         # Buffered I/O write
34790         (
34791                 while [ ! -e $DIR/sanity.833.lck ]; do
34792                         dd if=/dev/zero of=$file bs=1M count=50 conv=notrunc ||
34793                                 error "failed to write $file"
34794                         sleep 0.$((RANDOM % 4 + 1))
34795                 done
34796         )&
34797         wpid=$!
34798
34799         # Buffered I/O read
34800         (
34801                 while [ ! -e $DIR/sanity.833.lck ]; do
34802                         dd if=$file of=/dev/null bs=1M count=50 ||
34803                                 error "failed to read $file"
34804                         sleep 0.$((RANDOM % 4 + 1))
34805                 done
34806         )&
34807         rpid=$!
34808
34809         # Direct I/O read
34810         (
34811                 while [ ! -e $DIR/sanity.833.lck ]; do
34812                         dd if=$file of=/dev/null bs=1M count=50 iflag=direct ||
34813                                 error "failed to read $file in direct I/O mode"
34814                         sleep 0.$((RANDOM % 4 + 1))
34815                 done
34816         )&
34817         rpid2=$!
34818
34819         sleep 30
34820         touch $DIR/sanity.833.lck
34821         wait $wpid || error "$?: buffered write failed"
34822         wait $rpid || error "$?: buffered read failed"
34823         wait $rpid2 || error "$?: direct read failed"
34824 }
34825 run_test 833 "Mixed buffered/direct read and write should not return -EIO"
34826
34827 test_842() {
34828         (( $MDS1_VERSION >= $(version_code 2.15.62) )) ||
34829                 skip "Need MDS version at least 2.15.62 for ldlm_extent module"
34830
34831         local oss1=$(facet_host ost1)
34832
34833         # Try to insert the module.  This will leave results in dmesg
34834         now=$(date +%s)
34835         log "STAMP $now" > /dev/kmsg
34836         do_rpc_nodes $oss1 load_module kunit/ldlm_extent ||
34837                 error "$oss1 load_module ldlm_extent failed"
34838
34839         do_node $oss1 dmesg | sed -n -e "1,/STAMP $now/d" -e '/ldlm_extent:/p'
34840         do_node $oss1 rmmod -v ldlm_extent ||
34841                 error "rmmod failed (may trigger a failure in a later test)"
34842 }
34843 run_test 842 "Measure ldlm_extent performance"
34844
34845 test_850() {
34846         local dir=$DIR/$tdir
34847         local file=$dir/$tfile
34848         local statsfile=$dir/all_job_stats.txt
34849
34850         test_mkdir -p $dir || error "failed to create dir $dir"
34851         echo "abcdefg" > $file || error "failed to create file $file"
34852
34853         # read job_stats in the living system
34854         lljobstat -n 1 ||
34855                 error "failed to run lljobstat on living system"
34856
34857         $LCTL get_param *.*.job_stats > $statsfile
34858         lljobstat --statsfile=$statsfile ||
34859                 error "failed to run lljobstat on file $statsfile"
34860 }
34861 run_test 850 "lljobstat can parse living and aggregated job_stats"
34862
34863 test_851() {
34864         local dir=$DIR/$tdir
34865         local file=$dir/f_test_851_$$
34866         local report=/tmp/report_test_851_$$
34867         local fanotify_prog=monitor_lustrefs
34868         local pid
34869         local i
34870
34871         test_mkdir $dir || error "failed to create dir $dir"
34872
34873         nice -n -10 $fanotify_prog $DIR > $report & pid=$!
34874         kill -0 $pid || error "failed to run $fanotify_prog"
34875         ps -q $pid -eo pid,ni,comm
34876         stack_trap "kill $pid"
34877         stack_trap "rm -f $report"
34878
34879         for i in {1..30}; do
34880                 if grep Started $report; then
34881                         break
34882                 else
34883                         echo "$fanotify_prog did not start working, wait 1 second for $i times..."
34884                         sleep 1
34885                 fi
34886         done
34887         ((i == 30)) && error "$fanotify_prog did not start working in 30 seconds"
34888
34889         > $report
34890
34891         echo "1234567890" > $file
34892         wait_update_cond $(facet_active_host client) "stat -c %s $report" "-gt" "0" 30 ||
34893                 error "fanotify did not report anything after 30 seconds when file is created"
34894         grep -a -E "open.*:$file:" $report ||
34895                 error "no open event for writing $file"
34896         grep -a -E "write.*:$file:" $report ||
34897                 error "no write event for writing $file"
34898         grep -a -E "close.*:$file:" $report ||
34899                 error "no close event for writing $file"
34900
34901         > $report
34902         cat $file
34903         wait_update_cond $(facet_active_host client) "stat -c %s $report" "-gt" "0" 30 ||
34904                 error "fanotify did not report anything after 30 seconds when file is read"
34905         grep -a -E "open.*:$file:" $report ||
34906                 error "no open event for reading $file"
34907         grep -a -E "read.*:$file:" $report ||
34908                 error "no write event for reading $file"
34909         grep -a -E "close.*:$file:" $report ||
34910                 error "no close event for reading $file"
34911 }
34912 run_test 851 "fanotify can monitor open/read/write/close events for lustre fs"
34913
34914 test_852() {
34915         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
34916         (( $MDS1_VERSION >= $(version_code v2_15_62-70-g668dfb53de) )) ||
34917                 skip "Need MDS version at least 2.15.62.70 for intent mkdir"
34918
34919         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
34920
34921         save_lustre_params client "llite.*.intent_mkdir" > $save
34922         stack_trap "restore_lustre_params < $save; rm -f $save" EXIT
34923         $LCTL set_param llite.*.intent_mkdir=1
34924
34925         test_mkdir -p -c$MDSCOUNT $DIR/$tdir
34926         if [ $MDSCOUNT -ge 2 ]; then
34927                 $LFS setdirstripe -D -c$MDSCOUNT $DIR/$tdir ||
34928                         error "set default dirstripe failed"
34929         fi
34930
34931         mkdir $DIR/$tdir/tdir || error "mkdir tdir failed"
34932         mkdir $DIR/$tdir/tdir/tfile || error "mkdir tdir/tfile failed"
34933         touch -d "2020-08-25 15:08" $DIR/$tdir/tdir/tfile ||
34934                 error "touch time failed"
34935         chown 0:0 $DIR/$tdir/tdir/tfile || error "chown 0:0 tdir/tfile failed"
34936         chmod 755 $DIR/$tdir/tdir/tfile || error "chmod 755 tdir/tfile failed"
34937 }
34938 run_test 852 "mkdir using intent lock for striped directory"
34939
34940 test_853() {
34941         local file=$DIR/$tfile
34942         local size=$((PAGE_SIZE * 2))
34943
34944         dd if=/dev/zero of=$file bs=1M count=100 ||
34945                 error "failed to write $file"
34946         cancel_lru_locks $OSC
34947         $LCTL set_param llite.*.read_ahead_stats=clear
34948         $MULTIOP $file or1048576c || error "failed to read $file"
34949         $LCTL get_param llite.*.read_ahead_stats
34950
34951         cancel_lru_locks $OSC
34952         $LCTL set_param llite.*.read_ahead_stats=clear
34953         $MULTIOP $file oir1048576z1048576r${size}c ||
34954                 error "failed to read $file"
34955         $LCTL get_param llite.*.read_ahead_stats
34956
34957         local ranum=$($LCTL get_param -n llite.*.read_ahead_stats |
34958                       get_named_value 'readahead.pages' | calc_sum)
34959
34960         (( ranum == 0 )) || error "should not trigger readahead"
34961
34962         local rndnum=$($LCTL get_param -n llite.*.read_ahead_stats |
34963                        get_named_value 'forceread.pages' | calc_sum)
34964
34965         (( rndnum == 2 )) || error "force random read: $rndnum, expected 2"
34966 }
34967 run_test 853 "Verify that random fadvise works as expected"
34968
34969 #
34970 # tests that do cleanup/setup should be run at the end
34971 #
34972
34973 test_900() {
34974         [ $PARALLEL == "yes" ] && skip "skip parallel run"
34975         local ls
34976
34977         #define OBD_FAIL_MGC_PAUSE_PROCESS_LOG   0x903
34978         $LCTL set_param fail_loc=0x903
34979
34980         cancel_lru_locks MGC
34981
34982         FAIL_ON_ERROR=true cleanup
34983         FAIL_ON_ERROR=true setup
34984 }
34985 run_test 900 "umount should not race with any mgc requeue thread"
34986
34987 # LUS-6253/LU-11185
34988 test_901() {
34989         local old
34990         local count
34991         local oldc
34992         local newc
34993         local olds
34994         local news
34995         [ $PARALLEL == "yes" ] && skip "skip parallel run"
34996
34997         # some get_param have a bug to handle dot in param name
34998         cancel_lru_locks MGC
34999         old=$(mount -t lustre | wc -l)
35000         # 1 config+sptlrpc
35001         # 2 params
35002         # 3 nodemap
35003         # 4 IR
35004         old=$((old * 4))
35005         oldc=0
35006         count=0
35007         while [ $old -ne $oldc ]; do
35008                 oldc=$($LCTL get_param -n 'ldlm.namespaces.MGC*.lock_count')
35009                 sleep 1
35010                 ((count++))
35011                 if [ $count -ge $TIMEOUT ]; then
35012                         error "too large timeout"
35013                 fi
35014         done
35015         umount_client $MOUNT || error "umount failed"
35016         mount_client $MOUNT || error "mount failed"
35017         cancel_lru_locks MGC
35018         newc=$($LCTL get_param -n 'ldlm.namespaces.MGC*.lock_count')
35019
35020         [ $oldc -lt $newc ] && error "mgc lock leak ($oldc != $newc)"
35021
35022         return 0
35023 }
35024 run_test 901 "don't leak a mgc lock on client umount"
35025
35026 # LU-13377
35027 test_902() {
35028         [ $CLIENT_VERSION -lt $(version_code 2.13.52) ] &&
35029                 skip "client does not have LU-13377 fix"
35030         #define OBD_FAIL_LLITE_SHORT_COMMIT 0x1415
35031         $LCTL set_param fail_loc=0x1415
35032         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
35033         cancel_lru_locks osc
35034         rm -f $DIR/$tfile
35035 }
35036 run_test 902 "test short write doesn't hang lustre"
35037
35038 # LU-14711
35039 test_903() {
35040         $LFS setstripe -i 0 -c 1 $DIR/$tfile $DIR/${tfile}-2
35041         echo "blah" > $DIR/${tfile}-2
35042         dd if=/dev/zero of=$DIR/$tfile bs=1M count=6 conv=fsync
35043         #define OBD_FAIL_OSC_SLOW_PAGE_EVICT 0x417
35044         $LCTL set_param fail_loc=0x417 fail_val=20
35045
35046         mv $DIR/${tfile}-2 $DIR/$tfile # Destroys the big object
35047         sleep 1 # To start the destroy
35048         wait_destroy_complete 150 || error "Destroy taking too long"
35049         cat $DIR/$tfile > /dev/null || error "Evicted"
35050 }
35051 run_test 903 "Test long page discard does not cause evictions"
35052
35053 test_904() {
35054         [ "$mds1_FSTYPE" == "ldiskfs" ] || skip "ldiskfs only test"
35055         do_facet mds1 $DEBUGFS -R features $(mdsdevname 1) |
35056                 grep -q project || skip "skip project quota not supported"
35057
35058         local testfile="$DIR/$tdir/$tfile"
35059         local xattr="trusted.projid"
35060         local projid
35061         local mdts=$(comma_list $(mdts_nodes))
35062         local saved=$(do_facet mds1 $LCTL get_param -n \
35063                 osd-ldiskfs.*MDT0000.enable_projid_xattr)
35064
35065         do_nodes $mdts $LCTL set_param osd-ldiskfs.*MDT*.enable_projid_xattr=0
35066         stack_trap "do_nodes $mdts $LCTL set_param \
35067                 osd-ldiskfs.*MDT*.enable_projid_xattr=$saved"
35068
35069         mkdir -p $DIR/$tdir
35070         touch $testfile
35071         #hide projid xattr on server
35072         $LFS project -p 1 $testfile ||
35073                 error "set $testfile project id failed"
35074         getfattr -m - $testfile | grep $xattr &&
35075                 error "do not show trusted.projid when disabled on server"
35076         do_nodes $mdts $LCTL set_param osd-ldiskfs.*MDT*.enable_projid_xattr=1
35077         #should be hidden when projid is 0
35078         $LFS project -p 0 $testfile ||
35079                 error "set $testfile project id failed"
35080         getfattr -m - $testfile | grep $xattr &&
35081                 error "do not show trusted.projid with project ID 0"
35082
35083         #still can getxattr explicitly
35084         projid=$(getfattr -n $xattr $testfile |
35085                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
35086         [ $projid == "0" ] ||
35087                 error "projid expected 0 not $projid"
35088
35089         #set the projid via setxattr
35090         setfattr -n $xattr -v "1000" $testfile ||
35091                 error "setattr failed with $?"
35092         projid=($($LFS project $testfile))
35093         [ ${projid[0]} == "1000" ] ||
35094                 error "projid expected 1000 not $projid"
35095
35096         #check the new projid via getxattr
35097         $LFS project -p 1001 $testfile ||
35098                 error "set $testfile project id failed"
35099         getfattr -m - $testfile | grep $xattr ||
35100                 error "should show trusted.projid when project ID != 0"
35101         projid=$(getfattr -n $xattr $testfile |
35102                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
35103         [ $projid == "1001" ] ||
35104                 error "projid expected 1001 not $projid"
35105
35106         #try to set invalid projid
35107         setfattr -n $xattr -v "4294967295" $testfile &&
35108                 error "set invalid projid should fail"
35109
35110         #remove the xattr means setting projid to 0
35111         setfattr -x $xattr $testfile ||
35112                 error "setfattr failed with $?"
35113         projid=($($LFS project $testfile))
35114         [ ${projid[0]} == "0" ] ||
35115                 error "projid expected 0 not $projid"
35116
35117         #should be hidden when parent has inherit flag and same projid
35118         $LFS project -srp 1002 $DIR/$tdir ||
35119                 error "set $tdir project id failed"
35120         getfattr -m - $testfile | grep $xattr &&
35121                 error "do not show trusted.projid with inherit flag"
35122
35123         #still can getxattr explicitly
35124         projid=$(getfattr -n $xattr $testfile |
35125                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
35126         [ $projid == "1002" ] ||
35127                 error "projid expected 1002 not $projid"
35128 }
35129 run_test 904 "virtual project ID xattr"
35130
35131 # LU-8582
35132 test_905() {
35133         (( $OST1_VERSION >= $(version_code 2.15.50.220) )) ||
35134                 skip "need OST version >= 2.15.50.220 for fail_loc"
35135
35136         remote_ost_nodsh && skip "remote OST with nodsh"
35137         $LFS setstripe -c -1 -i 0 $DIR/$tfile || error "setstripe failed"
35138
35139         $LFS ladvise -a willread $DIR/$tfile || error "ladvise does not work"
35140
35141         #define OBD_FAIL_OST_OPCODE 0x253
35142         # OST_LADVISE = 21
35143         do_facet ost1 "$LCTL set_param fail_val=21 fail_loc=0x0253"
35144         $LFS ladvise -a willread $DIR/$tfile &&
35145                 error "unexpected success of ladvise with fault injection"
35146         $LFS ladvise -a willread $DIR/$tfile |&
35147                 grep -q "Operation not supported"
35148         (( $? == 0 )) || error "unexpected stderr of ladvise with fault injection"
35149 }
35150 run_test 905 "bad or new opcode should not stuck client"
35151
35152 test_906() {
35153         grep -q io_uring_setup /proc/kallsyms ||
35154                 skip "Client OS does not support io_uring I/O engine"
35155         io_uring_probe || skip "kernel does not support io_uring fully"
35156         which fio || skip_env "no fio installed"
35157         fio --enghelp | grep -q io_uring ||
35158                 skip_env "fio does not support io_uring I/O engine"
35159
35160         local file=$DIR/$tfile
35161         local ioengine="io_uring"
35162         local numjobs=2
35163         local size=50M
35164
35165         fio --name=seqwrite --ioengine=$ioengine        \
35166                 --bs=$PAGE_SIZE --direct=1 --numjobs=$numjobs   \
35167                 --iodepth=64 --size=$size --filename=$file --rw=write ||
35168                 error "fio seqwrite $file failed"
35169
35170         fio --name=seqread --ioengine=$ioengine \
35171                 --bs=$PAGE_SIZE --direct=1 --numjobs=$numjobs   \
35172                 --iodepth=64 --size=$size --filename=$file --rw=read ||
35173                 error "fio seqread $file failed"
35174
35175         rm -f $file || error "rm -f $file failed"
35176 }
35177 run_test 906 "Simple test for io_uring I/O engine via fio"
35178
35179 test_907() {
35180         local max_pages=$($LCTL get_param -n osc.*.max_pages_per_rpc | head -n1)
35181
35182         # set stripe size to max rpc size
35183         $LFS setstripe -i 0 -c 2 -S $((max_pages * PAGE_SIZE)) $DIR/$tfile
35184         $LFS getstripe $DIR/$tfile
35185 #define OBD_FAIL_OST_EROFS               0x216
35186         do_facet ost1 "$LCTL set_param fail_val=3 fail_loc=0x80000216"
35187
35188         local bs=$((max_pages * PAGE_SIZE / 16))
35189
35190         # write full one stripe and one block
35191         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=17 || error "dd failed"
35192
35193         rm $DIR/$tfile || error "rm failed"
35194 }
35195 run_test 907 "write rpc error during unlink"
35196
35197 test_908a() {
35198         (( MDS1_VERSION >= $(version_code 2.16.0) )) ||
35199                 skip "need MDS >= 2.16.0 for llog timestamps"
35200         [[ "$mds1_FSTYPE" == ldiskfs ]] || skip "ldiskfs only test"
35201
35202         local dev=$(mdsdevname 1)
35203         local cmd="debugfs -c -R \\\"stat CONFIGS/params\\\" $dev"
35204
35205         # ctime_mds value is in hex
35206         local base_time=`date -d "24 hours ago" +%s`
35207         local ctime_mds=$(do_facet mds1 "$cmd" |&
35208                           awk -F'[: ]' '/ctime:/ { print $4 }')
35209         ctime_mds=$((ctime_mds))
35210         echo "ctime_mds=$ctime_mds, base_time=$base_time"
35211         (( "$ctime_mds" > "$base_time" )) ||
35212                 error "invalid ctime $ctime_mds <= $base_time"
35213 }
35214 run_test 908a "llog created with valid ctime"
35215
35216 test_908b() {
35217         (( MDS1_VERSION >= $(version_code 2.16.0) )) ||
35218                 skip "need MDS >= 2.16.0 for llog timestamps"
35219         [[ "$mds1_FSTYPE" == ldiskfs ]] || skip "ldiskfs only test"
35220
35221         local dev=$(mdsdevname 1)
35222
35223         changelog_register || error "cannot register changelog user"
35224         # set changelog_mask to ALL
35225         changelog_chmask "ALL"
35226         changelog_clear
35227
35228         for ((i=0; i<100; i++)); do
35229                 echo "$i" > $DIR/$tfile${i}
35230                 rm $DIR/$tfile${i}
35231         done
35232         sleep 5
35233
35234         changelog_deregister || error "changelog_deregister failed"
35235
35236         local cmd="debugfs -c -R \\\"stat changelog_catalog\\\" $dev"
35237
35238         # ctime_mdt value is in hex
35239         local ctime_mds=$(do_facet mds1 "$cmd" |&
35240                           awk -F'[: ]' '/ctime:/ { print $4 }')
35241         ctime_mds=$((ctime_mds))
35242         local mtime_mds=$(do_facet mds1 "$cmd" |&
35243                           awk -F'[: ]' '/mtime:/ { print $4 }')
35244         mtime_mds=$((mtime_mds))
35245
35246         echo "ctime_mds=$ctime_mds, mtime_mds=$mtime_mds"
35247         (( "$mtime_mds" > "$ctime_mds" )) ||
35248                 error "invalid mtime $mtime_mds <= $ctime_mds"
35249 }
35250 run_test 908b "changelog stores valid mtime"
35251
35252 complete_test $SECONDS
35253 [ -f $EXT2_DEV ] && rm $EXT2_DEV || true
35254 check_and_cleanup_lustre
35255 if [ "$I_MOUNTED" != "yes" ]; then
35256         lctl set_param debug="$OLDDEBUG" 2> /dev/null || true
35257 fi
35258 exit_status