Whamcloud - gitweb
LU-17276 tests: Enqueue same range flocks
[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"
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
45 if $SHARED_KEY; then
46         always_except LU-14181 64e 64f
47         always_except LU-17127 39o
48 fi
49
50 # skip the grant tests for ARM until they are fixed
51 if [[ $(uname -m) = aarch64 ]]; then
52         always_except LU-11671 45
53 fi
54
55 # skip nfs tests on kernels >= 4.12.0 until they are fixed
56 if [ $LINUX_VERSION_CODE -ge $(version_code 4.12.0) ]; then
57         always_except LU-12661 817
58 fi
59 # skip cgroup tests on RHEL8.1 kernels until they are fixed
60 if (( $LINUX_VERSION_CODE >= $(version_code 4.18.0) &&
61       $LINUX_VERSION_CODE <  $(version_code 5.4.0) )); then
62         always_except LU-13063 411a
63 fi
64
65 # skip cgroup tests for kernels < v4.18.0
66 if (( $LINUX_VERSION_CODE < $(version_code 4.18.0) )); then
67         always_except LU-13063 411b
68 fi
69
70 #                                  5              12     8   12  15   (min)"
71 [[ "$SLOW" = "no" ]] && EXCEPT_SLOW="27m 60i 64b 68 71 135 136 230d 300o"
72
73 if [[ "$mds1_FSTYPE" == "zfs" ]]; then
74         #                                               13    (min)"
75         [[ "$SLOW" == "no" ]] && EXCEPT_SLOW="$EXCEPT_SLOW 51b"
76 fi
77
78 if [[ "$ost1_FSTYPE" = "zfs" ]]; then
79         always_except LU-1941 130b 130c 130d 130e 130f 130g
80         always_except LU-9054 312
81 fi
82
83 proc_regexp="/{proc,sys}/{fs,sys,kernel/debug}/{lustre,lnet}/"
84
85 # Get the SLES distro version
86 #
87 # Returns a version string that should only be used in comparing
88 # strings returned by version_code()
89 sles_version_code()
90 {
91         local version=$(grep VERSION_ID /etc/os-release | cut -d'"' -f2)
92
93         # All SuSE Linux versions have one decimal. version_code expects two
94         local sles_version=$version.0
95         version_code $sles_version
96 }
97
98 # Check if we are running on Ubuntu or SLES so we can make decisions on
99 # what tests to run
100 if [ -r /etc/SuSE-release ] || [ -r /etc/SUSE-brand ]; then
101         sles_version=$(sles_version_code)
102         (( $sles_version >= $(version_code 11.4.0) )) ||
103                 always_except LU-4341 170
104
105         (( $sles_version >= $(version_code 12.0.0) )) ||
106                 always_except LU-3703 234
107 elif [ -r /etc/redhat-release ]; then
108         rhel_version=$(cat /etc/redhat-release |
109                 sed -e 's/^[^0-9.]*//g' | sed -e 's/[ ].*//')
110         if (( $(version_code $rhel_version) >= $(version_code 9.3.0) )); then
111                 # disable test_906 temporarily until rhel9.3 solves the
112                 # failure on fio io_uring I/O engine.
113                 always_except LU-17289 906
114         fi
115 fi
116
117 build_test_filter
118 FAIL_ON_ERROR=false
119
120 cleanup() {
121         echo -n "cln.."
122         pgrep ll_sa > /dev/null && { echo "There are ll_sa thread not exit!"; exit 20; }
123         cleanupall ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
124 }
125 setup() {
126         echo -n "mnt.."
127         load_modules
128         setupall || exit 10
129         echo "done"
130 }
131
132 check_swap_layouts_support()
133 {
134         $LCTL get_param -n llite.*.sbi_flags | grep -q layout ||
135                 skip "Does not support layout lock."
136 }
137
138 check_swap_layout_no_dom()
139 {
140         local FOLDER=$1
141         local SUPP=$(lfs getstripe $FOLDER | grep "pattern:       mdt" | wc -l)
142         [ $SUPP -eq 0 ] || skip "layout swap does not support DOM files so far"
143 }
144
145 check_and_setup_lustre
146 DIR=${DIR:-$MOUNT}
147 assert_DIR
148
149 MAXFREE=${MAXFREE:-$((300000 * $OSTCOUNT))}
150
151 [ -f $DIR/d52a/foo ] && chattr -a $DIR/d52a/foo
152 [ -f $DIR/d52b/foo ] && chattr -i $DIR/d52b/foo
153 rm -rf $DIR/[Rdfs][0-9]*
154
155 # $RUNAS_ID may get set incorrectly somewhere else
156 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] &&
157         error "\$RUNAS_ID set to 0, but \$UID is also 0!"
158
159 check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
160
161 if [ "${ONLY}" = "MOUNT" ] ; then
162         echo "Lustre is up, please go on"
163         exit
164 fi
165
166 echo "preparing for tests involving mounts"
167 EXT2_DEV=${EXT2_DEV:-$TMP/SANITY.LOOP}
168 touch $EXT2_DEV
169 mke2fs -j -F $EXT2_DEV 8000 > /dev/null
170 echo # add a newline after mke2fs.
171
172 umask 077
173
174 OLDDEBUG=$(lctl get_param -n debug 2> /dev/null)
175
176 # ensure all internal functions know we want full debug
177 export PTLDEBUG=all
178 lctl set_param debug=$PTLDEBUG 2> /dev/null || true
179
180 test_0a() {
181         touch $DIR/$tfile
182         $CHECKSTAT -t file $DIR/$tfile || error "$tfile is not a file"
183         rm $DIR/$tfile
184         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
185 }
186 run_test 0a "touch; rm ====================="
187
188 test_0b() {
189         chmod 0755 $DIR || error "chmod 0755 $DIR failed"
190         $CHECKSTAT -p 0755 $DIR || error "$DIR permission is not 0755"
191 }
192 run_test 0b "chmod 0755 $DIR ============================="
193
194 test_0c() {
195         $LCTL get_param mdc.*.import | grep "state: FULL" ||
196                 error "import not FULL"
197         $LCTL get_param mdc.*.import | grep "target: $FSNAME-MDT" ||
198                 error "bad target"
199 }
200 run_test 0c "check import proc"
201
202 test_0d() { # LU-3397
203         [ $MGS_VERSION -lt $(version_code 2.10.57) ] &&
204                 skip "proc exports not supported before 2.10.57"
205
206         local mgs_exp="mgs.MGS.exports"
207         local client_uuid=$($LCTL get_param -n mgc.*.uuid)
208         local exp_client_nid
209         local exp_client_version
210         local exp_val
211         local imp_val
212         local temp_imp=$DIR/$tfile.import
213         local temp_exp=$DIR/$tfile.export
214
215         # save mgc import file to $temp_imp
216         $LCTL get_param mgc.*.import | tee $temp_imp
217         # Check if client uuid is found in MGS export
218         for exp_client_nid in $(do_facet mgs $LCTL get_param -N $mgs_exp.*); do
219                 [ $(do_facet mgs $LCTL get_param -n $exp_client_nid.uuid) == \
220                         $client_uuid ] &&
221                         break;
222         done
223         # save mgs export file to $temp_exp
224         do_facet mgs $LCTL get_param $exp_client_nid.export | tee $temp_exp
225
226         # Compare the value of field "connect_flags"
227         imp_val=$(grep "connect_flags" $temp_imp)
228         exp_val=$(grep "connect_flags" $temp_exp)
229         [ "$exp_val" == "$imp_val" ] ||
230                 error "export flags '$exp_val' != import flags '$imp_val'"
231
232         # Compare client versions.  Only compare top-3 fields for compatibility
233         exp_client_version=$(awk '/target_version:/ { print $2 }' $temp_exp)
234         exp_val=$(version_code $(cut -d. -f1,2,3 <<<$exp_client_version))
235         imp_val=$(version_code $(lustre_build_version client | cut -d. -f1,2,3))
236         [ "$exp_val" == "$imp_val" ] ||
237                 error "exp version '$exp_client_version'($exp_val) != " \
238                         "'$(lustre_build_version client)'($imp_val)"
239 }
240 run_test 0d "check export proc ============================="
241
242 test_0e() { # LU-13417
243         (( $MDSCOUNT > 1 )) ||
244                 skip "We need at least 2 MDTs for this test"
245
246         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
247                 skip "Need server version at least 2.14.51"
248
249         local default_lmv_count=$($LFS getdirstripe -D -c $MOUNT)
250         local default_lmv_index=$($LFS getdirstripe -D -i $MOUNT)
251
252         [ $default_lmv_count -eq 1 ] ||
253                 error "$MOUNT default stripe count $default_lmv_count"
254
255         [ $default_lmv_index -eq -1 ] ||
256                 error "$MOUNT default stripe index $default_lmv_index"
257
258         mkdir $MOUNT/$tdir.1 || error "mkdir $MOUNT/$tdir.1 failed"
259         mkdir $MOUNT/$tdir.2 || error "mkdir $MOUNT/$tdir.2 failed"
260
261         local mdt_index1=$($LFS getdirstripe -i $MOUNT/$tdir.1)
262         local mdt_index2=$($LFS getdirstripe -i $MOUNT/$tdir.2)
263
264         [ $mdt_index1 -eq $mdt_index2 ] &&
265                 error "directories are on the same MDT $mdt_index1=$mdt_index2"
266
267         rmdir $MOUNT/$tdir.1 $MOUNT/$tdir.2
268 }
269 run_test 0e "Enable DNE MDT balancing for mkdir in the ROOT"
270
271 test_0f() { # LU-17471
272         (( $MDS1_VERSION < $(version_code 2.17.53) )) ||
273                 skip "MDS >= 2.17.53 removes /proc/.../brw_stats symlink"
274         (( $MDS1_VERSION < $(version_code 2.14.55-100-g8a84c7f9c7) ||
275            $MDS1_VERSION > $(version_code 2.15.60-25) )) ||
276                 skip "MDS was missing /proc/.../brw_stats value"
277
278         local path="lustre/osd-$FSTYPE/$FSNAME-MDT0000/brw_stats"
279         local out_proc=$(do_facet mds1 grep snapshot_time /proc/fs/$path)
280
281         [[ -n "$out_proc" ]] || error "brw_stats /proc/fs/$path not found"
282 }
283 run_test 0f "Symlink to /sys/kernel/debug/*/*/brw_stats should work properly"
284
285 test_1() {
286         test_mkdir $DIR/$tdir
287         test_mkdir $DIR/$tdir/d2
288         mkdir $DIR/$tdir/d2 && error "we expect EEXIST, but not returned"
289         $CHECKSTAT -t dir $DIR/$tdir/d2 || error "$tdir/d2 is not a dir"
290         rmdir $DIR/$tdir/d2
291         rmdir $DIR/$tdir
292         $CHECKSTAT -a $DIR/$tdir || error "$tdir was not removed"
293 }
294 run_test 1 "mkdir; remkdir; rmdir"
295
296 test_2() {
297         test_mkdir $DIR/$tdir
298         touch $DIR/$tdir/$tfile || error "touch $tdir/$tfile failed"
299         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "$tdir/$tfile not a file"
300         rm -r $DIR/$tdir
301         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$file is not removed"
302 }
303 run_test 2 "mkdir; touch; rmdir; check file"
304
305 test_3() {
306         test_mkdir $DIR/$tdir
307         $CHECKSTAT -t dir $DIR/$tdir || error "$tdir is not a directory"
308         touch $DIR/$tdir/$tfile
309         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "$tdir/$tfile not a file"
310         rm -r $DIR/$tdir
311         $CHECKSTAT -a $DIR/$tdir || error "$tdir is not removed"
312 }
313 run_test 3 "mkdir; touch; rmdir; check dir"
314
315 # LU-4471 - failed rmdir on remote directories still removes directory on MDT0
316 test_4() {
317         test_mkdir -i 1 $DIR/$tdir
318
319         touch $DIR/$tdir/$tfile ||
320                 error "Create file under remote directory failed"
321
322         rmdir $DIR/$tdir &&
323                 error "Expect error removing in-use dir $DIR/$tdir"
324
325         test -d $DIR/$tdir || error "Remote directory disappeared"
326
327         rm -rf $DIR/$tdir || error "remove remote dir error"
328 }
329 run_test 4 "mkdir; touch dir/file; rmdir; checkdir (expect error)"
330
331 test_5() {
332         test_mkdir $DIR/$tdir
333         test_mkdir $DIR/$tdir/d2
334         chmod 0707 $DIR/$tdir/d2 || error "chmod 0707 $tdir/d2 failed"
335         $CHECKSTAT -t dir -p 0707 $DIR/$tdir/d2 || error "$tdir/d2 not mode 707"
336         $CHECKSTAT -t dir $DIR/$tdir/d2 || error "$tdir/d2 is not a directory"
337 }
338 run_test 5 "mkdir .../d5 .../d5/d2; chmod .../d5/d2"
339
340 test_6a() {
341         touch $DIR/$tfile || error "touch $DIR/$tfile failed"
342         chmod 0666 $DIR/$tfile || error "chmod 0666 $tfile failed"
343         $CHECKSTAT -t file -p 0666 -u \#$UID $DIR/$tfile ||
344                 error "$tfile does not have perm 0666 or UID $UID"
345         $RUNAS chmod 0444 $DIR/$tfile && error "chmod $tfile worked on UID $UID"
346         $CHECKSTAT -t file -p 0666 -u \#$UID $DIR/$tfile ||
347                 error "$tfile should be 0666 and owned by UID $UID"
348 }
349 run_test 6a "touch f6a; chmod f6a; $RUNAS chmod f6a (should return error) =="
350
351 test_6c() {
352         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
353
354         touch $DIR/$tfile
355         chown $RUNAS_ID $DIR/$tfile || error "chown $RUNAS_ID $file failed"
356         $CHECKSTAT -t file -u \#$RUNAS_ID $DIR/$tfile ||
357                 error "$tfile should be owned by UID $RUNAS_ID"
358         $RUNAS chown $UID $DIR/$tfile && error "chown $UID $file succeeded"
359         $CHECKSTAT -t file -u \#$RUNAS_ID $DIR/$tfile ||
360                 error "$tfile should be owned by UID $RUNAS_ID"
361 }
362 run_test 6c "touch f6c; chown f6c; $RUNAS chown f6c (should return error) =="
363
364 test_6e() {
365         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
366
367         touch $DIR/$tfile
368         chgrp $RUNAS_ID $DIR/$tfile || error "chgrp $RUNAS_ID $file failed"
369         $CHECKSTAT -t file -u \#$UID -g \#$RUNAS_ID $DIR/$tfile ||
370                 error "$tfile should be owned by GID $UID"
371         $RUNAS chgrp $UID $DIR/$tfile && error "chgrp $UID $file succeeded"
372         $CHECKSTAT -t file -u \#$UID -g \#$RUNAS_ID $DIR/$tfile ||
373                 error "$tfile should be owned by UID $UID and GID $RUNAS_ID"
374 }
375 run_test 6e "touch+chgrp $tfile; $RUNAS chgrp $tfile (should return error)"
376
377 test_6g() {
378         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
379
380         test_mkdir $DIR/$tdir
381         chmod 777 $DIR/$tdir || error "chmod 0777 $tdir failed"
382         $RUNAS mkdir $DIR/$tdir/d || error "mkdir $tdir/d failed"
383         chmod g+s $DIR/$tdir/d || error "chmod g+s $tdir/d failed"
384         test_mkdir $DIR/$tdir/d/subdir
385         $CHECKSTAT -g \#$RUNAS_GID $DIR/$tdir/d/subdir ||
386                 error "$tdir/d/subdir should be GID $RUNAS_GID"
387         if [[ $MDSCOUNT -gt 1 ]]; then
388                 # check remote dir sgid inherite
389                 $LFS mkdir -i 0 $DIR/$tdir.local ||
390                         error "mkdir $tdir.local failed"
391                 chmod g+s $DIR/$tdir.local ||
392                         error "chmod $tdir.local failed"
393                 chgrp $RUNAS_GID $DIR/$tdir.local ||
394                         error "chgrp $tdir.local failed"
395                 $LFS mkdir -i 1 $DIR/$tdir.local/$tdir.remote ||
396                         error "mkdir $tdir.remote failed"
397                 $CHECKSTAT -g \#$RUNAS_GID $DIR/$tdir.local/$tdir.remote ||
398                         error "$tdir.remote should be owned by $UID.$RUNAS_ID"
399                 $CHECKSTAT -p 02755 $DIR/$tdir.local/$tdir.remote ||
400                         error "$tdir.remote should be mode 02755"
401         fi
402 }
403 run_test 6g "verify new dir in sgid dir inherits group"
404
405 test_6h() { # bug 7331
406         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID"
407
408         touch $DIR/$tfile || error "touch failed"
409         chown $RUNAS_ID:$RUNAS_GID $DIR/$tfile || error "initial chown failed"
410         $RUNAS -G$RUNAS_GID chown $RUNAS_ID:0 $DIR/$tfile &&
411                 error "chown $RUNAS_ID:0 $tfile worked as GID $RUNAS_GID"
412         $CHECKSTAT -t file -u \#$RUNAS_ID -g \#$RUNAS_GID $DIR/$tfile ||
413                 error "$tdir/$tfile should be UID $RUNAS_UID GID $RUNAS_GID"
414 }
415 run_test 6h "$RUNAS chown RUNAS_ID.0 .../$tfile (should return error)"
416
417 test_7a() {
418         test_mkdir $DIR/$tdir
419         $MCREATE $DIR/$tdir/$tfile
420         chmod 0666 $DIR/$tdir/$tfile
421         $CHECKSTAT -t file -p 0666 $DIR/$tdir/$tfile ||
422                 error "$tdir/$tfile should be mode 0666"
423 }
424 run_test 7a "mkdir .../d7; mcreate .../d7/f; chmod .../d7/f ===="
425
426 test_7b() {
427         if [ ! -d $DIR/$tdir ]; then
428                 test_mkdir $DIR/$tdir
429         fi
430         $MCREATE $DIR/$tdir/$tfile
431         echo -n foo > $DIR/$tdir/$tfile
432         [ "$(cat $DIR/$tdir/$tfile)" = "foo" ] || error "$tdir/$tfile not 'foo'"
433         $CHECKSTAT -t file -s 3 $DIR/$tdir/$tfile || error "$tfile size not 3"
434 }
435 run_test 7b "mkdir .../d7; mcreate d7/f2; echo foo > d7/f2 ====="
436
437 test_8() {
438         test_mkdir $DIR/$tdir
439         touch $DIR/$tdir/$tfile
440         chmod 0666 $DIR/$tdir/$tfile
441         $CHECKSTAT -t file -p 0666 $DIR/$tdir/$tfile ||
442                 error "$tfile mode not 0666"
443 }
444 run_test 8 "mkdir .../d8; touch .../d8/f; chmod .../d8/f ======="
445
446 test_9() {
447         test_mkdir $DIR/$tdir
448         test_mkdir $DIR/$tdir/d2
449         test_mkdir $DIR/$tdir/d2/d3
450         $CHECKSTAT -t dir $DIR/$tdir/d2/d3 || error "$tdir/d2/d3 not a dir"
451 }
452 run_test 9 "mkdir .../d9 .../d9/d2 .../d9/d2/d3 ================"
453
454 test_10() {
455         test_mkdir $DIR/$tdir
456         test_mkdir $DIR/$tdir/d2
457         touch $DIR/$tdir/d2/$tfile
458         $CHECKSTAT -t file $DIR/$tdir/d2/$tfile ||
459                 error "$tdir/d2/$tfile not a file"
460 }
461 run_test 10 "mkdir .../d10 .../d10/d2; touch .../d10/d2/f ======"
462
463 test_11() {
464         test_mkdir $DIR/$tdir
465         test_mkdir $DIR/$tdir/d2
466         chmod 0666 $DIR/$tdir/d2
467         chmod 0705 $DIR/$tdir/d2
468         $CHECKSTAT -t dir -p 0705 $DIR/$tdir/d2 ||
469                 error "$tdir/d2 mode not 0705"
470 }
471 run_test 11 "mkdir .../d11 d11/d2; chmod .../d11/d2 ============"
472
473 test_12() {
474         test_mkdir $DIR/$tdir
475         touch $DIR/$tdir/$tfile
476         chmod 0666 $DIR/$tdir/$tfile
477         chmod 0654 $DIR/$tdir/$tfile
478         $CHECKSTAT -t file -p 0654 $DIR/$tdir/$tfile ||
479                 error "$tdir/d2 mode not 0654"
480 }
481 run_test 12 "touch .../d12/f; chmod .../d12/f .../d12/f ========"
482
483 test_13() {
484         test_mkdir $DIR/$tdir
485         dd if=/dev/zero of=$DIR/$tdir/$tfile count=10
486         >  $DIR/$tdir/$tfile
487         $CHECKSTAT -t file -s 0 $DIR/$tdir/$tfile ||
488                 error "$tdir/$tfile size not 0 after truncate"
489 }
490 run_test 13 "creat .../d13/f; dd .../d13/f; > .../d13/f ========"
491
492 test_14() {
493         test_mkdir $DIR/$tdir
494         touch $DIR/$tdir/$tfile
495         rm $DIR/$tdir/$tfile
496         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$tfile not removed"
497 }
498 run_test 14 "touch .../d14/f; rm .../d14/f; rm .../d14/f ======="
499
500 test_15() {
501         test_mkdir $DIR/$tdir
502         touch $DIR/$tdir/$tfile
503         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}_2
504         $CHECKSTAT -t file $DIR/$tdir/${tfile}_2 ||
505                 error "$tdir/${tfile_2} not a file after rename"
506         rm $DIR/$tdir/${tfile}_2 || error "unlink failed after rename"
507 }
508 run_test 15 "touch .../d15/f; mv .../d15/f .../d15/f2 =========="
509
510 test_16() {
511         test_mkdir $DIR/$tdir
512         touch $DIR/$tdir/$tfile
513         rm -rf $DIR/$tdir/$tfile
514         $CHECKSTAT -a $DIR/$tdir/$tfile || error "$tdir/$tfile not removed"
515 }
516 run_test 16 "touch .../d16/f; rm -rf .../d16/f"
517
518 test_17a() {
519         test_mkdir $DIR/$tdir
520         touch $DIR/$tdir/$tfile
521         ln -s $DIR/$tdir/$tfile $DIR/$tdir/l-exist
522         ls -l $DIR/$tdir
523         $CHECKSTAT -l $DIR/$tdir/$tfile $DIR/$tdir/l-exist ||
524                 error "$tdir/l-exist not a symlink"
525         $CHECKSTAT -f -t f $DIR/$tdir/l-exist ||
526                 error "$tdir/l-exist not referencing a file"
527         rm -f $DIR/$tdir/l-exist
528         $CHECKSTAT -a $DIR/$tdir/l-exist || error "$tdir/l-exist not removed"
529 }
530 run_test 17a "symlinks: create, remove (real)"
531
532 test_17b() {
533         test_mkdir $DIR/$tdir
534         ln -s no-such-file $DIR/$tdir/l-dangle
535         ls -l $DIR/$tdir
536         $CHECKSTAT -l no-such-file $DIR/$tdir/l-dangle ||
537                 error "$tdir/l-dangle not referencing no-such-file"
538         $CHECKSTAT -fa $DIR/$tdir/l-dangle ||
539                 error "$tdir/l-dangle not referencing non-existent file"
540         rm -f $DIR/$tdir/l-dangle
541         $CHECKSTAT -a $DIR/$tdir/l-dangle || error "$tdir/l-dangle not removed"
542 }
543 run_test 17b "symlinks: create, remove (dangling)"
544
545 test_17c() { # bug 3440 - don't save failed open RPC for replay
546         test_mkdir $DIR/$tdir
547         ln -s foo $DIR/$tdir/$tfile
548         cat $DIR/$tdir/$tfile && error "opened non-existent symlink" || true
549 }
550 run_test 17c "symlinks: open dangling (should return error)"
551
552 test_17d() {
553         test_mkdir $DIR/$tdir
554         ln -s foo $DIR/$tdir/$tfile
555         touch $DIR/$tdir/$tfile || error "creating to new symlink"
556 }
557 run_test 17d "symlinks: create dangling"
558
559 test_17e() {
560         test_mkdir $DIR/$tdir
561         local foo=$DIR/$tdir/$tfile
562         ln -s $foo $foo || error "create symlink failed"
563         ls -l $foo || error "ls -l failed"
564         ls $foo && error "ls not failed" || true
565 }
566 run_test 17e "symlinks: create recursive symlink (should return error)"
567
568 test_17f() {
569         test_mkdir $DIR/$tdir
570         ln -s 1234567890/2234567890/3234567890/4234567890 $DIR/$tdir/111
571         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890 $DIR/$tdir/222
572         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890 $DIR/$tdir/333
573         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890/9234567890/a234567890/b234567890 $DIR/$tdir/444
574         ln -s 1234567890/2234567890/3234567890/4234567890/5234567890/6234567890/7234567890/8234567890/9234567890/a234567890/b234567890/c234567890/d234567890/f234567890 $DIR/$tdir/555
575         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
576         ls -l  $DIR/$tdir
577 }
578 run_test 17f "symlinks: long and very long symlink name"
579
580 # str_repeat(S, N) generate a string that is string S repeated N times
581 str_repeat() {
582         local s=$1
583         local n=$2
584         local ret=''
585         while [ $((n -= 1)) -ge 0 ]; do
586                 ret=$ret$s
587         done
588         echo $ret
589 }
590
591 # Long symlinks and LU-2241
592 test_17g() {
593         test_mkdir $DIR/$tdir
594         local TESTS="59 60 61 4094 4095"
595
596         # Fix for inode size boundary in 2.1.4
597         [ $MDS1_VERSION -lt $(version_code 2.1.4) ] &&
598                 TESTS="4094 4095"
599
600         # Patch not applied to 2.2 or 2.3 branches
601         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] &&
602         [ $MDS1_VERSION -le $(version_code 2.3.55) ] &&
603                 TESTS="4094 4095"
604
605         for i in $TESTS; do
606                 local SYMNAME=$(str_repeat 'x' $i)
607                 ln -s $SYMNAME $DIR/$tdir/f$i || error "failed $i-char symlink"
608                 readlink $DIR/$tdir/f$i || error "failed $i-char readlink"
609         done
610 }
611 run_test 17g "symlinks: really long symlink name and inode boundaries"
612
613 test_17h() { #bug 17378
614         [ $PARALLEL == "yes" ] && skip "skip parallel run"
615         remote_mds_nodsh && skip "remote MDS with nodsh"
616
617         local mdt_idx
618
619         test_mkdir $DIR/$tdir
620         mdt_idx=$($LFS getdirstripe -i $DIR/$tdir)
621         $LFS setstripe -c -1 $DIR/$tdir
622         #define OBD_FAIL_MDS_LOV_PREP_CREATE 0x141
623         do_facet mds$((mdt_idx + 1)) lctl set_param fail_loc=0x80000141
624         touch $DIR/$tdir/$tfile || true
625 }
626 run_test 17h "create objects: lov_free_memmd() doesn't lbug"
627
628 test_17i() { #bug 20018
629         [ $PARALLEL == "yes" ] && skip "skip parallel run"
630         remote_mds_nodsh && skip "remote MDS with nodsh"
631
632         local foo=$DIR/$tdir/$tfile
633         local mdt_idx
634
635         test_mkdir -c1 $DIR/$tdir
636         mdt_idx=$($LFS getdirstripe -i $DIR/$tdir)
637         ln -s $foo $foo || error "create symlink failed"
638 #define OBD_FAIL_MDS_READLINK_EPROTO     0x143
639         do_facet mds$((mdt_idx + 1)) lctl set_param fail_loc=0x80000143
640         ls -l $foo && error "error not detected"
641         return 0
642 }
643 run_test 17i "don't panic on short symlink (should return error)"
644
645 test_17k() { #bug 22301
646         [ $PARALLEL == "yes" ] && skip "skip parallel run"
647         [[ -z "$(which rsync 2>/dev/null)" ]] &&
648                 skip "no rsync command"
649         rsync --help | grep -q xattr ||
650                 skip_env "$(rsync --version | head -n1) does not support xattrs"
651         test_mkdir $DIR/$tdir
652         test_mkdir $DIR/$tdir.new
653         touch $DIR/$tdir/$tfile
654         ln -s $DIR/$tdir/$tfile $DIR/$tdir/$tfile.lnk
655         rsync -av -X $DIR/$tdir/ $DIR/$tdir.new ||
656                 error "rsync failed with xattrs enabled"
657 }
658 run_test 17k "symlinks: rsync with xattrs enabled"
659
660 test_17l() { # LU-279
661         [[ -z "$(which getfattr 2>/dev/null)" ]] &&
662                 skip "no getfattr command"
663
664         test_mkdir $DIR/$tdir
665         touch $DIR/$tdir/$tfile
666         ln -s $DIR/$tdir/$tfile $DIR/$tdir/$tfile.lnk
667         for path in "$DIR/$tdir" "$DIR/$tdir/$tfile" "$DIR/$tdir/$tfile.lnk"; do
668                 # -h to not follow symlinks. -m '' to list all the xattrs.
669                 # grep to remove first line: '# file: $path'.
670                 for xattr in `getfattr -hm '' $path 2>/dev/null | grep -v '^#'`;
671                 do
672                         lgetxattr_size_check $path $xattr ||
673                                 error "lgetxattr_size_check $path $xattr failed"
674                 done
675         done
676 }
677 run_test 17l "Ensure lgetxattr's returned xattr size is consistent"
678
679 # LU-1540
680 test_17m() {
681         [ $PARALLEL == "yes" ] && skip "skip parallel run"
682         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
683         remote_mds_nodsh && skip "remote MDS with nodsh"
684         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] &&
685         [ $MDS1_VERSION -le $(version_code 2.2.93) ] &&
686                 skip "MDS 2.2.0-2.2.93 do not NUL-terminate symlinks"
687
688         local short_sym="0123456789"
689         local wdir=$DIR/$tdir
690         local i
691
692         test_mkdir $wdir
693         long_sym=$short_sym
694         # create a long symlink file
695         for ((i = 0; i < 4; ++i)); do
696                 long_sym=${long_sym}${long_sym}
697         done
698
699         echo "create 512 short and long symlink files under $wdir"
700         for ((i = 0; i < 256; ++i)); do
701                 ln -sf ${long_sym}"a5a5" $wdir/long-$i
702                 ln -sf ${short_sym}"a5a5" $wdir/short-$i
703         done
704
705         echo "erase them"
706         rm -f $wdir/*
707         sync
708         wait_delete_completed
709
710         echo "recreate the 512 symlink files with a shorter string"
711         for ((i = 0; i < 512; ++i)); do
712                 # rewrite the symlink file with a shorter string
713                 ln -sf ${long_sym} $wdir/long-$i || error "long_sym failed"
714                 ln -sf ${short_sym} $wdir/short-$i || error "short_sym failed"
715         done
716
717         local mds_index=$(($($LFS getstripe -m $wdir) + 1))
718
719         echo "stop and checking mds${mds_index}:"
720         # e2fsck should not return error
721         stop mds${mds_index}
722         local devname=$(mdsdevname $mds_index)
723         run_e2fsck $(facet_active_host mds${mds_index}) $devname -n
724         rc=$?
725
726         start mds${mds_index} $devname $MDS_MOUNT_OPTS ||
727                 error "start mds${mds_index} failed"
728         df $MOUNT > /dev/null 2>&1
729         [ $rc -eq 0 ] ||
730                 error "e2fsck detected error for short/long symlink: rc=$rc"
731         rm -f $wdir/*
732 }
733 run_test 17m "run e2fsck against MDT which contains short/long symlink"
734
735 check_fs_consistency_17n() {
736         local mdt_index
737         local rc=0
738
739         # create/unlink in 17n only change 2 MDTs(MDT1/MDT2),
740         # so it only check MDT1/MDT2 instead of all of MDTs.
741         for mdt_index in 1 2; do
742                 # e2fsck should not return error
743                 stop mds${mdt_index}
744                 local devname=$(mdsdevname $mdt_index)
745                 run_e2fsck $(facet_active_host mds$mdt_index) $devname -n ||
746                         rc=$((rc + $?))
747
748                 start mds${mdt_index} $devname $MDS_MOUNT_OPTS ||
749                         error "mount mds$mdt_index failed"
750                 df $MOUNT > /dev/null 2>&1
751         done
752         return $rc
753 }
754
755 test_17n() {
756         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
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 i
765
766         test_mkdir $DIR/$tdir
767         for ((i=0; i<10; i++)); do
768                 $LFS mkdir -i1 -c2 $DIR/$tdir/remote_dir_${i} ||
769                         error "create remote dir error $i"
770                 createmany -o $DIR/$tdir/remote_dir_${i}/f 10 ||
771                         error "create files under remote dir failed $i"
772         done
773
774         check_fs_consistency_17n ||
775                 error "e2fsck report error after create files under remote dir"
776
777         for ((i = 0; i < 10; i++)); do
778                 rm -rf $DIR/$tdir/remote_dir_${i} ||
779                         error "destroy remote dir error $i"
780         done
781
782         check_fs_consistency_17n ||
783                 error "e2fsck report error after unlink files under remote dir"
784
785         [ $MDS1_VERSION -lt $(version_code 2.4.50) ] &&
786                 skip "lustre < 2.4.50 does not support migrate mv"
787
788         for ((i = 0; i < 10; i++)); do
789                 mkdir -p $DIR/$tdir/remote_dir_${i}
790                 createmany -o $DIR/$tdir/remote_dir_${i}/f 10 ||
791                         error "create files under remote dir failed $i"
792                 $LFS migrate --mdt-index 1 $DIR/$tdir/remote_dir_${i} ||
793                         error "migrate remote dir error $i"
794         done
795         check_fs_consistency_17n || error "e2fsck report error after migration"
796
797         for ((i = 0; i < 10; i++)); do
798                 rm -rf $DIR/$tdir/remote_dir_${i} ||
799                         error "destroy remote dir error $i"
800         done
801
802         check_fs_consistency_17n || error "e2fsck report error after unlink"
803 }
804 run_test 17n "run e2fsck against master/slave MDT which contains remote dir"
805
806 test_17o() {
807         remote_mds_nodsh && skip "remote MDS with nodsh"
808         [ $MDS1_VERSION -lt $(version_code 2.3.64) ] &&
809                 skip "Need MDS version at least 2.3.64"
810
811         local wdir=$DIR/${tdir}o
812         local mdt_index
813         local rc=0
814
815         test_mkdir $wdir
816         touch $wdir/$tfile
817         mdt_index=$($LFS getstripe -m $wdir/$tfile)
818         mdt_index=$((mdt_index + 1))
819
820         cancel_lru_locks mdc
821         #fail mds will wait the failover finish then set
822         #following fail_loc to avoid interfer the recovery process.
823         fail mds${mdt_index}
824
825         #define OBD_FAIL_OSD_LMA_INCOMPAT 0x194
826         do_facet mds${mdt_index} lctl set_param fail_loc=0x194
827         ls -l $wdir/$tfile && rc=1
828         do_facet mds${mdt_index} lctl set_param fail_loc=0
829         [[ $rc -eq 0 ]] || error "stat file should fail"
830 }
831 run_test 17o "stat file with incompat LMA feature"
832
833 test_18() {
834         touch $DIR/$tfile || error "Failed to touch $DIR/$tfile: $?"
835         ls $DIR || error "Failed to ls $DIR: $?"
836 }
837 run_test 18 "touch .../f ; ls ... =============================="
838
839 test_19a() {
840         touch $DIR/$tfile
841         ls -l $DIR
842         rm $DIR/$tfile
843         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
844 }
845 run_test 19a "touch .../f19 ; ls -l ... ; rm .../f19 ==========="
846
847 test_19b() {
848         ls -l $DIR/$tfile && error "ls -l $tfile failed"|| true
849 }
850 run_test 19b "ls -l .../f19 (should return error) =============="
851
852 test_19c() {
853         [ $RUNAS_ID -eq $UID ] &&
854                 skip_env "RUNAS_ID = UID = $UID -- skipping"
855
856         $RUNAS touch $DIR/$tfile && error "create non-root file failed" || true
857 }
858 run_test 19c "$RUNAS touch .../f19 (should return error) =="
859
860 test_19d() {
861         cat $DIR/f19 && error || true
862 }
863 run_test 19d "cat .../f19 (should return error) =============="
864
865 test_20() {
866         touch $DIR/$tfile
867         rm $DIR/$tfile
868         touch $DIR/$tfile
869         rm $DIR/$tfile
870         touch $DIR/$tfile
871         rm $DIR/$tfile
872         $CHECKSTAT -a $DIR/$tfile || error "$tfile was not removed"
873 }
874 run_test 20 "touch .../f ; ls -l ..."
875
876 test_21() {
877         test_mkdir $DIR/$tdir
878         [ -f $DIR/$tdir/dangle ] && rm -f $DIR/$tdir/dangle
879         ln -s dangle $DIR/$tdir/link
880         echo foo >> $DIR/$tdir/link
881         cat $DIR/$tdir/dangle
882         $CHECKSTAT -t link $DIR/$tdir/link || error "$tdir/link not a link"
883         $CHECKSTAT -f -t file $DIR/$tdir/link ||
884                 error "$tdir/link not linked to a file"
885 }
886 run_test 21 "write to dangling link"
887
888 test_22() {
889         local wdir=$DIR/$tdir
890         test_mkdir $wdir
891         chown $RUNAS_ID:$RUNAS_GID $wdir
892         (cd $wdir || error "cd $wdir failed";
893                 $RUNAS tar cf - /etc/hosts /etc/sysconfig/network |
894                 $RUNAS tar xf -)
895         ls -lR $wdir/etc || error "ls -lR $wdir/etc failed"
896         $CHECKSTAT -t dir $wdir/etc || error "checkstat -t dir failed"
897         $CHECKSTAT -u \#$RUNAS_ID -g \#$RUNAS_GID $wdir/etc ||
898                 error "checkstat -u failed"
899 }
900 run_test 22 "unpack tar archive as non-root user"
901
902 # was test_23
903 test_23a() {
904         test_mkdir $DIR/$tdir
905         local file=$DIR/$tdir/$tfile
906
907         openfile -f O_CREAT:O_EXCL $file || error "$file create failed"
908         openfile -f O_CREAT:O_EXCL $file &&
909                 error "$file recreate succeeded" || true
910 }
911 run_test 23a "O_CREAT|O_EXCL in subdir"
912
913 test_23b() { # bug 18988
914         test_mkdir $DIR/$tdir
915         local file=$DIR/$tdir/$tfile
916
917         rm -f $file
918         echo foo > $file || error "write filed"
919         echo bar >> $file || error "append filed"
920         $CHECKSTAT -s 8 $file || error "wrong size"
921         rm $file
922 }
923 run_test 23b "O_APPEND check"
924
925 # LU-9409, size with O_APPEND and tiny writes
926 test_23c() {
927         local file=$DIR/$tfile
928
929         # single dd
930         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800
931         $CHECKSTAT -s 6400 $file || error "wrong size, expected 6400"
932         rm -f $file
933
934         # racing tiny writes
935         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800 &
936         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=800 &
937         wait
938         $CHECKSTAT -s 12800 $file || error "wrong size, expected 12800"
939         rm -f $file
940
941         #racing tiny & normal writes
942         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=4096 count=4 &
943         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=8 count=100 &
944         wait
945         $CHECKSTAT -s 17184 $file || error "wrong size, expected 17184"
946         rm -f $file
947
948         #racing tiny & normal writes 2, ugly numbers
949         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=4099 count=11 &
950         dd conv=notrunc oflag=append if=/dev/zero of=$file bs=17 count=173 &
951         wait
952         $CHECKSTAT -s 48030 $file || error "wrong size, expected 48030"
953         rm -f $file
954 }
955 run_test 23c "O_APPEND size checks for tiny writes"
956
957 # LU-11069 file offset is correct after appending writes
958 test_23d() {
959         local file=$DIR/$tfile
960         local offset
961
962         echo CentaurHauls > $file
963         offset=$($MULTIOP $file oO_WRONLY:O_APPEND:w13Zp)
964         if ((offset != 26)); then
965                 error "wrong offset, expected 26, got '$offset'"
966         fi
967 }
968 run_test 23d "file offset is correct after appending writes"
969
970 # rename sanity
971 test_24a() {
972         echo '-- same directory rename'
973         test_mkdir $DIR/$tdir
974         touch $DIR/$tdir/$tfile.1
975         mv $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
976         $CHECKSTAT -t file $DIR/$tdir/$tfile.2 || error "$tfile.2 not a file"
977 }
978 run_test 24a "rename file to non-existent target"
979
980 test_24b() {
981         test_mkdir $DIR/$tdir
982         touch $DIR/$tdir/$tfile.{1,2}
983         mv $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
984         $CHECKSTAT -a $DIR/$tdir/$tfile.1 || error "$tfile.1 exists"
985         $CHECKSTAT -t file $DIR/$tdir/$tfile.2 || error "$tfile.2 not a file"
986 }
987 run_test 24b "rename file to existing target"
988
989 test_24c() {
990         test_mkdir $DIR/$tdir
991         test_mkdir $DIR/$tdir/d$testnum.1
992         mv $DIR/$tdir/d$testnum.1 $DIR/$tdir/d$testnum.2
993         $CHECKSTAT -a $DIR/$tdir/d$testnum.1 || error "d$testnum.1 exists"
994         $CHECKSTAT -t dir $DIR/$tdir/d$testnum.2 || error "d$testnum.2 not dir"
995 }
996 run_test 24c "rename directory to non-existent target"
997
998 test_24d() {
999         test_mkdir -c1 $DIR/$tdir
1000         test_mkdir -c1 $DIR/$tdir/d$testnum.1
1001         test_mkdir -c1 $DIR/$tdir/d$testnum.2
1002         mrename $DIR/$tdir/d$testnum.1 $DIR/$tdir/d$testnum.2
1003         $CHECKSTAT -a $DIR/$tdir/d$testnum.1 || error "d$testnum.1 exists"
1004         $CHECKSTAT -t dir $DIR/$tdir/d$testnum.2 || error "d$testnum.2 not dir"
1005 }
1006 run_test 24d "rename directory to existing target"
1007
1008 test_24e() {
1009         echo '-- cross directory renames --'
1010         test_mkdir $DIR/R5a
1011         test_mkdir $DIR/R5b
1012         touch $DIR/R5a/f
1013         mv $DIR/R5a/f $DIR/R5b/g
1014         $CHECKSTAT -a $DIR/R5a/f || error "$DIR/R5a/f exists"
1015         $CHECKSTAT -t file $DIR/R5b/g || error "$DIR/R5b/g not file type"
1016 }
1017 run_test 24e "touch .../R5a/f; rename .../R5a/f .../R5b/g ======"
1018
1019 test_24f() {
1020         test_mkdir $DIR/R6a
1021         test_mkdir $DIR/R6b
1022         touch $DIR/R6a/f $DIR/R6b/g
1023         mv $DIR/R6a/f $DIR/R6b/g
1024         $CHECKSTAT -a $DIR/R6a/f || error "$DIR/R6a/f exists"
1025         $CHECKSTAT -t file $DIR/R6b/g || error "$DIR/R6b/g not file type"
1026 }
1027 run_test 24f "touch .../R6a/f R6b/g; mv .../R6a/f .../R6b/g ===="
1028
1029 test_24g() {
1030         test_mkdir $DIR/R7a
1031         test_mkdir $DIR/R7b
1032         test_mkdir $DIR/R7a/d
1033         mv $DIR/R7a/d $DIR/R7b/e
1034         $CHECKSTAT -a $DIR/R7a/d || error "$DIR/R7a/d exists"
1035         $CHECKSTAT -t dir $DIR/R7b/e || error "$DIR/R7b/e not dir type"
1036 }
1037 run_test 24g "mkdir .../R7{a,b}/d; mv .../R7a/d .../R7b/e ======"
1038
1039 test_24h() {
1040         test_mkdir -c1 $DIR/R8a
1041         test_mkdir -c1 $DIR/R8b
1042         test_mkdir -c1 $DIR/R8a/d
1043         test_mkdir -c1 $DIR/R8b/e
1044         mrename $DIR/R8a/d $DIR/R8b/e
1045         $CHECKSTAT -a $DIR/R8a/d || error "$DIR/R8a/d exists"
1046         $CHECKSTAT -t dir $DIR/R8b/e || error "$DIR/R8b/e not dir type"
1047 }
1048 run_test 24h "mkdir .../R8{a,b}/{d,e}; rename .../R8a/d .../R8b/e"
1049
1050 test_24i() {
1051         echo "-- rename error cases"
1052         test_mkdir $DIR/R9
1053         test_mkdir $DIR/R9/a
1054         touch $DIR/R9/f
1055         mrename $DIR/R9/f $DIR/R9/a
1056         $CHECKSTAT -t file $DIR/R9/f || error "$DIR/R9/f not file type"
1057         $CHECKSTAT -t dir  $DIR/R9/a || error "$DIR/R9/a not dir type"
1058         $CHECKSTAT -a $DIR/R9/a/f || error "$DIR/R9/a/f exists"
1059 }
1060 run_test 24i "rename file to dir error: touch f ; mkdir a ; rename f a"
1061
1062 test_24j() {
1063         test_mkdir $DIR/R10
1064         mrename $DIR/R10/f $DIR/R10/g
1065         $CHECKSTAT -t dir $DIR/R10 || error "$DIR/R10 not dir type"
1066         $CHECKSTAT -a $DIR/R10/f || error "$DIR/R10/f exists"
1067         $CHECKSTAT -a $DIR/R10/g || error "$DIR/R10/g exists"
1068 }
1069 run_test 24j "source does not exist ============================"
1070
1071 test_24k() {
1072         test_mkdir $DIR/R11a
1073         test_mkdir $DIR/R11a/d
1074         touch $DIR/R11a/f
1075         mv $DIR/R11a/f $DIR/R11a/d
1076         $CHECKSTAT -a $DIR/R11a/f || error "$DIR/R11a/f exists"
1077         $CHECKSTAT -t file $DIR/R11a/d/f || error "$DIR/R11a/d/f not file type"
1078 }
1079 run_test 24k "touch .../R11a/f; mv .../R11a/f .../R11a/d ======="
1080
1081 # bug 2429 - rename foo foo foo creates invalid file
1082 test_24l() {
1083         f="$DIR/f24l"
1084         $MULTIOP $f OcNs || error "rename of ${f} to itself failed"
1085 }
1086 run_test 24l "Renaming a file to itself ========================"
1087
1088 test_24m() {
1089         f="$DIR/f24m"
1090         $MULTIOP $f OcLN ${f}2 ${f}2 || error "link ${f}2 ${f}2 failed"
1091         # on ext3 this does not remove either the source or target files
1092         # though the "expected" operation would be to remove the source
1093         $CHECKSTAT -t file ${f} || error "${f} missing"
1094         $CHECKSTAT -t file ${f}2 || error "${f}2 missing"
1095 }
1096 run_test 24m "Renaming a file to a hard link to itself ========="
1097
1098 test_24n() {
1099     f="$DIR/f24n"
1100     # this stats the old file after it was renamed, so it should fail
1101     touch ${f}
1102     $CHECKSTAT ${f} || error "${f} missing"
1103     mv ${f} ${f}.rename
1104     $CHECKSTAT ${f}.rename || error "${f}.rename missing"
1105     $CHECKSTAT -a ${f} || error "${f} exists"
1106 }
1107 run_test 24n "Statting the old file after renaming (Posix rename 2)"
1108
1109 test_24o() {
1110         test_mkdir $DIR/$tdir
1111         rename_many -s random -v -n 10 $DIR/$tdir
1112 }
1113 run_test 24o "rename of files during htree split"
1114
1115 test_24p() {
1116         test_mkdir $DIR/R12a
1117         test_mkdir $DIR/R12b
1118         DIRINO=`ls -lid $DIR/R12a | awk '{ print $1 }'`
1119         mrename $DIR/R12a $DIR/R12b
1120         $CHECKSTAT -a $DIR/R12a || error "$DIR/R12a exists"
1121         $CHECKSTAT -t dir $DIR/R12b || error "$DIR/R12b not dir type"
1122         DIRINO2=`ls -lid $DIR/R12b | awk '{ print $1 }'`
1123         [ "$DIRINO" = "$DIRINO2" ] || error "R12a $DIRINO != R12b $DIRINO2"
1124 }
1125 run_test 24p "mkdir .../R12{a,b}; rename .../R12a .../R12b"
1126
1127 cleanup_multiop_pause() {
1128         trap 0
1129         kill -USR1 $MULTIPID
1130 }
1131
1132 test_24q() {
1133         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1134
1135         test_mkdir $DIR/R13a
1136         test_mkdir $DIR/R13b
1137         local DIRINO=$(ls -lid $DIR/R13a | awk '{ print $1 }')
1138         multiop_bg_pause $DIR/R13b D_c || error "multiop failed to start"
1139         MULTIPID=$!
1140
1141         trap cleanup_multiop_pause EXIT
1142         mrename $DIR/R13a $DIR/R13b
1143         $CHECKSTAT -a $DIR/R13a || error "R13a still exists"
1144         $CHECKSTAT -t dir $DIR/R13b || error "R13b does not exist"
1145         local DIRINO2=$(ls -lid $DIR/R13b | awk '{ print $1 }')
1146         [ "$DIRINO" = "$DIRINO2" ] || error "R13a $DIRINO != R13b $DIRINO2"
1147         cleanup_multiop_pause
1148         wait $MULTIPID || error "multiop close failed"
1149 }
1150 run_test 24q "mkdir .../R13{a,b}; open R13b rename R13a R13b ==="
1151
1152 test_24r() { #bug 3789
1153         test_mkdir $DIR/R14a
1154         test_mkdir $DIR/R14a/b
1155         mrename $DIR/R14a $DIR/R14a/b && error "rename to subdir worked!"
1156         $CHECKSTAT -t dir $DIR/R14a || error "$DIR/R14a missing"
1157         $CHECKSTAT -t dir $DIR/R14a/b || error "$DIR/R14a/b missing"
1158 }
1159 run_test 24r "mkdir .../R14a/b; rename .../R14a .../R14a/b ====="
1160
1161 test_24s() {
1162         test_mkdir $DIR/R15a
1163         test_mkdir $DIR/R15a/b
1164         test_mkdir $DIR/R15a/b/c
1165         mrename $DIR/R15a $DIR/R15a/b/c && error "rename to sub-subdir worked!"
1166         $CHECKSTAT -t dir $DIR/R15a || error "$DIR/R15a missing"
1167         $CHECKSTAT -t dir $DIR/R15a/b/c || error "$DIR/R15a/b/c missing"
1168 }
1169 run_test 24s "mkdir .../R15a/b/c; rename .../R15a .../R15a/b/c ="
1170
1171 test_24t() {
1172         test_mkdir $DIR/R16a
1173         test_mkdir $DIR/R16a/b
1174         test_mkdir $DIR/R16a/b/c
1175         mrename $DIR/R16a/b/c $DIR/R16a && error "rename to sub-subdir worked!"
1176         $CHECKSTAT -t dir $DIR/R16a || error "$DIR/R16a missing"
1177         $CHECKSTAT -t dir $DIR/R16a/b/c || error "$DIR/R16a/b/c missing"
1178 }
1179 run_test 24t "mkdir .../R16a/b/c; rename .../R16a/b/c .../R16a ="
1180
1181 test_24u() { # bug12192
1182         $MULTIOP $DIR/$tfile C2w$((2048 * 1024))c || error "multiop failed"
1183         $CHECKSTAT -s $((2048 * 1024)) $DIR/$tfile || error "wrong file size"
1184 }
1185 run_test 24u "create stripe file"
1186
1187 simple_cleanup_common() {
1188         local createmany=$1
1189         local rc=0
1190
1191         [[ -z "$DIR" || -z "$tdir" || ! -d "$DIR/$tdir" ]] && return 0
1192
1193         local start=$SECONDS
1194
1195         [[ -n "$createmany" ]] && unlinkmany $DIR/$tdir/$tfile $createmany
1196         rm -rf $DIR/$tdir || error "cleanup $DIR/$tdir failed"
1197         rc=$?
1198         wait_delete_completed
1199         echo "cleanup time $((SECONDS - start))"
1200         return $rc
1201 }
1202
1203 max_pages_per_rpc() {
1204         local mdtname="$(printf "MDT%04x" ${1:-0})"
1205         $LCTL get_param -n mdc.*$mdtname*.max_pages_per_rpc
1206 }
1207
1208 test_24v() {
1209         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1210
1211         local nrfiles=${COUNT:-100000}
1212         local fname="$DIR/$tdir/$tfile"
1213
1214         # Performance issue on ZFS see LU-4072 (c.f. LU-2887)
1215         [ "$mds1_FSTYPE" = "zfs" ] && nrfiles=${COUNT:-10000}
1216
1217         test_mkdir "$(dirname $fname)"
1218         # assume MDT0000 has the fewest inodes
1219         local stripes=$($LFS getdirstripe -c $(dirname $fname))
1220         local free_inodes=$(($(mdt_free_inodes 0) * ${stripes/#0/1}))
1221         [[ $free_inodes -lt $nrfiles ]] && nrfiles=$free_inodes
1222
1223         stack_trap "simple_cleanup_common $nrfiles"
1224
1225         createmany -m "$fname" $nrfiles
1226
1227         cancel_lru_locks mdc
1228         lctl set_param mdc.*.stats clear
1229
1230         # was previously test_24D: LU-6101
1231         # readdir() returns correct number of entries after cursor reload
1232         local num_ls=$(ls $DIR/$tdir | wc -l)
1233         local num_uniq=$(ls $DIR/$tdir | sort -u | wc -l)
1234         local num_all=$(ls -a $DIR/$tdir | wc -l)
1235         if [ $num_ls -ne $nrfiles ] || [ $num_uniq -ne $nrfiles ] ||
1236                 [ $num_all -ne $((nrfiles + 2)) ]; then
1237                         error "Expected $nrfiles files, got $num_ls " \
1238                                 "($num_uniq unique $num_all .&..)"
1239         fi
1240         # LU-5 large readdir
1241         # dirent_size = 32 bytes for sizeof(struct lu_dirent) +
1242         #               N bytes for name (len($nrfiles) rounded to 8 bytes) +
1243         #               8 bytes for luda_type (4 bytes rounded to 8 bytes)
1244         # take into account of overhead in lu_dirpage header and end mark in
1245         # each page, plus one in rpc_num calculation.
1246         local dirent_size=$((32 + (${#tfile} | 7) + 1 + 8))
1247         local page_entries=$(((PAGE_SIZE - 24) / dirent_size))
1248         local mdt_idx=$($LFS getdirstripe -i $(dirname $fname))
1249         local rpc_pages=$(max_pages_per_rpc $mdt_idx)
1250         local rpc_max=$((nrfiles / (page_entries * rpc_pages) + stripes))
1251         local mds_readpage=$(calc_stats mdc.*.stats mds_readpage)
1252         echo "readpages: $mds_readpage rpc_max: $rpc_max-2/+1"
1253         (( $mds_readpage >= $rpc_max - 2 && $mds_readpage <= $rpc_max + 1)) ||
1254                 error "large readdir doesn't take effect: " \
1255                       "$mds_readpage should be about $rpc_max"
1256 }
1257 run_test 24v "list large directory (test hash collision, b=17560)"
1258
1259 test_24w() { # bug21506
1260         SZ1=234852
1261         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=4096 || return 1
1262         dd if=/dev/zero bs=$SZ1 count=1 >> $DIR/$tfile || return 2
1263         dd if=$DIR/$tfile of=$DIR/${tfile}_left bs=1M skip=4097 || return 3
1264         SZ2=`ls -l $DIR/${tfile}_left | awk '{print $5}'`
1265         [[ "$SZ1" -eq "$SZ2" ]] ||
1266                 error "Error reading at the end of the file $tfile"
1267 }
1268 run_test 24w "Reading a file larger than 4Gb"
1269
1270 test_24x() {
1271         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1272         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1273         [[ $MDS1_VERSION -lt $(version_code 2.7.56) ]] &&
1274                 skip "Need MDS version at least 2.7.56"
1275
1276         local MDTIDX=1
1277         local remote_dir=$DIR/$tdir/remote_dir
1278
1279         test_mkdir $DIR/$tdir
1280         $LFS mkdir -i $MDTIDX $remote_dir ||
1281                 error "create remote directory failed"
1282
1283         test_mkdir $DIR/$tdir/src_dir
1284         touch $DIR/$tdir/src_file
1285         test_mkdir $remote_dir/tgt_dir
1286         touch $remote_dir/tgt_file
1287
1288         mrename $DIR/$tdir/src_dir $remote_dir/tgt_dir ||
1289                 error "rename dir cross MDT failed!"
1290
1291         mrename $DIR/$tdir/src_file $remote_dir/tgt_file ||
1292                 error "rename file cross MDT failed!"
1293
1294         touch $DIR/$tdir/ln_file
1295         ln $DIR/$tdir/ln_file $remote_dir/ln_name ||
1296                 error "ln file cross MDT failed"
1297
1298         rm -rf $DIR/$tdir || error "Can not delete directories"
1299 }
1300 run_test 24x "cross MDT rename/link"
1301
1302 test_24y() {
1303         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1304         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1305
1306         local remote_dir=$DIR/$tdir/remote_dir
1307         local mdtidx=1
1308
1309         test_mkdir $DIR/$tdir
1310         $LFS mkdir -i $mdtidx $remote_dir ||
1311                 error "create remote directory failed"
1312
1313         test_mkdir $remote_dir/src_dir
1314         touch $remote_dir/src_file
1315         test_mkdir $remote_dir/tgt_dir
1316         touch $remote_dir/tgt_file
1317
1318         mrename $remote_dir/src_dir $remote_dir/tgt_dir ||
1319                 error "rename subdir in the same remote dir failed!"
1320
1321         mrename $remote_dir/src_file $remote_dir/tgt_file ||
1322                 error "rename files in the same remote dir failed!"
1323
1324         ln $remote_dir/tgt_file $remote_dir/tgt_file1 ||
1325                 error "link files in the same remote dir failed!"
1326
1327         rm -rf $DIR/$tdir || error "Can not delete directories"
1328 }
1329 run_test 24y "rename/link on the same dir should succeed"
1330
1331 test_24z() {
1332         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
1333         [[ $MDS1_VERSION -lt $(version_code 2.12.51) ]] &&
1334                 skip "Need MDS version at least 2.12.51"
1335
1336         local index
1337
1338         for index in 0 1; do
1339                 $LFS mkdir -i $index $DIR/$tdir.$index || error "mkdir failed"
1340                 touch $DIR/$tdir.0/$tfile.$index || error "touch failed"
1341         done
1342
1343         mv $DIR/$tdir.0/$tfile.0 $DIR/$tdir.1 || error "mv $tfile.0 failed"
1344
1345         index=$($LFS getstripe -m $DIR/$tdir.1/$tfile.0)
1346         [ $index -eq 0 ] || error "$tfile.0 is on MDT$index"
1347
1348         local mdts=$(comma_list $(mdts_nodes))
1349
1350         do_nodes $mdts $LCTL set_param mdt.*.enable_remote_rename=0
1351         stack_trap "do_nodes $mdts $LCTL \
1352                 set_param mdt.*.enable_remote_rename=1" EXIT
1353
1354         mv $DIR/$tdir.0/$tfile.1 $DIR/$tdir.1 || error "mv $tfile.1 failed"
1355
1356         index=$($LFS getstripe -m $DIR/$tdir.1/$tfile.1)
1357         [ $index -eq 1 ] || error "$tfile.1 is on MDT$index"
1358 }
1359 run_test 24z "cross-MDT rename is done as cp"
1360
1361 test_24A() { # LU-3182
1362         local NFILES=5000
1363
1364         test_mkdir $DIR/$tdir
1365         stack_trap "simple_cleanup_common $NFILES"
1366         createmany -m $DIR/$tdir/$tfile $NFILES
1367         local t=$(ls $DIR/$tdir | wc -l)
1368         local u=$(ls $DIR/$tdir | sort -u | wc -l)
1369         local v=$(ls -ai $DIR/$tdir | sort -u | wc -l)
1370
1371         (( $t == $NFILES && $u == $NFILES && $v == NFILES + 2 )) ||
1372                 error "Expected $NFILES files, got $t ($u unique $v .&..)"
1373 }
1374 run_test 24A "readdir() returns correct number of entries."
1375
1376 test_24B() { # LU-4805
1377         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
1378
1379         local count
1380
1381         test_mkdir $DIR/$tdir
1382         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir/ ||
1383                 error "create striped dir failed"
1384
1385         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1386         [ $count -eq 2 ] || error "Expected 2, got $count"
1387
1388         touch $DIR/$tdir/striped_dir/a
1389
1390         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1391         [ $count -eq 3 ] || error "Expected 3, got $count"
1392
1393         touch $DIR/$tdir/striped_dir/.f
1394
1395         count=$(ls -ai $DIR/$tdir/striped_dir | wc -l)
1396         [ $count -eq 4 ] || error "Expected 4, got $count"
1397
1398         rm -rf $DIR/$tdir || error "Can not delete directories"
1399 }
1400 run_test 24B "readdir for striped dir return correct number of entries"
1401
1402 test_24C() {
1403         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
1404
1405         mkdir $DIR/$tdir
1406         mkdir $DIR/$tdir/d0
1407         mkdir $DIR/$tdir/d1
1408
1409         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/d0/striped_dir ||
1410                 error "create striped dir failed"
1411
1412         cd $DIR/$tdir/d0/striped_dir
1413
1414         local d0_ino=$(ls -i -l -a $DIR/$tdir | grep "d0" | awk '{print $1}')
1415         local d1_ino=$(ls -i -l -a $DIR/$tdir | grep "d1" | awk '{print $1}')
1416         local parent_ino=$(ls -i -l -a | grep "\.\." | awk '{print $1}')
1417
1418         [ "$d0_ino" = "$parent_ino" ] ||
1419                 error ".. wrong, expect $d0_ino, get $parent_ino"
1420
1421         mv $DIR/$tdir/d0/striped_dir $DIR/$tdir/d1/ ||
1422                 error "mv striped dir failed"
1423
1424         parent_ino=$(ls -i -l -a | grep "\.\." | awk '{print $1}')
1425
1426         [ "$d1_ino" = "$parent_ino" ] ||
1427                 error ".. wrong after mv, expect $d1_ino, get $parent_ino"
1428 }
1429 run_test 24C "check .. in striped dir"
1430
1431 test_24E() {
1432         [[ $MDSCOUNT -lt 4 ]] && skip_env "needs >= 4 MDTs"
1433         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1434
1435         mkdir -p $DIR/$tdir
1436         mkdir $DIR/$tdir/src_dir
1437         $LFS mkdir -i 1 $DIR/$tdir/src_dir/src_child ||
1438                 error "create remote source failed"
1439
1440         touch $DIR/$tdir/src_dir/src_child/a
1441
1442         $LFS mkdir -i 2 $DIR/$tdir/tgt_dir ||
1443                 error "create remote target dir failed"
1444
1445         $LFS mkdir -i 3 $DIR/$tdir/tgt_dir/tgt_child ||
1446                 error "create remote target child failed"
1447
1448         mrename $DIR/$tdir/src_dir/src_child $DIR/$tdir/tgt_dir/tgt_child ||
1449                 error "rename dir cross MDT failed!"
1450
1451         find $DIR/$tdir
1452
1453         $CHECKSTAT -t dir $DIR/$tdir/src_dir/src_child &&
1454                 error "src_child still exists after rename"
1455
1456         $CHECKSTAT -t file $DIR/$tdir/tgt_dir/tgt_child/a ||
1457                 error "missing file(a) after rename"
1458
1459         rm -rf $DIR/$tdir || error "Can not delete directories"
1460 }
1461 run_test 24E "cross MDT rename/link"
1462
1463 test_24F () {
1464         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return 0
1465
1466         local repeats=1000
1467         [ "$SLOW" = "no" ] && repeats=100
1468
1469         mkdir -p $DIR/$tdir
1470
1471         echo "$repeats repeats"
1472         for ((i = 0; i < repeats; i++)); do
1473                 $LFS mkdir -i0 -c2 $DIR/$tdir/test || error "mkdir fails"
1474                 touch $DIR/$tdir/test/a || error "touch fails"
1475                 mkdir $DIR/$tdir/test/b || error "mkdir fails"
1476                 rm -rf $DIR/$tdir/test || error "rmdir fails"
1477         done
1478
1479         true
1480 }
1481 run_test 24F "hash order vs readdir (LU-11330)"
1482
1483 test_24G () {
1484         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
1485
1486         local ino1
1487         local ino2
1488
1489         $LFS mkdir -i 0 $DIR/$tdir-0 || error "mkdir $tdir-0"
1490         $LFS mkdir -i 1 $DIR/$tdir-1 || error "mkdir $tdir-1"
1491         touch $DIR/$tdir-0/f1 || error "touch f1"
1492         ln -s $DIR/$tdir-0/f1 $DIR/$tdir-0/s1 || error "ln s1"
1493         ino1=$(stat -c%i $DIR/$tdir-0/s1)
1494         mv $DIR/$tdir-0/s1 $DIR/$tdir-1 || error "mv s1"
1495         ino2=$(stat -c%i $DIR/$tdir-1/s1)
1496         [ $ino1 -ne $ino2 ] || error "s1 should be migrated"
1497 }
1498 run_test 24G "migrate symlink in rename"
1499
1500 test_24H() {
1501         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
1502         [[ $(hostname) != $(facet_active_host mds2) ]] ||
1503                 skip "MDT1 should be on another node"
1504
1505         test_mkdir -i 1 -c 1 $DIR/$tdir
1506 #define OBD_FAIL_FLD_QUERY_REQ           0x1103
1507         do_facet mds2 $LCTL set_param fail_loc=0x80001103
1508         touch $DIR/$tdir/$tfile || error "touch failed"
1509 }
1510 run_test 24H "repeat FLD_QUERY rpc"
1511
1512 test_25a() {
1513         echo '== symlink sanity ============================================='
1514
1515         test_mkdir $DIR/d25
1516         ln -s d25 $DIR/s25
1517         touch $DIR/s25/foo ||
1518                 error "File creation in symlinked directory failed"
1519 }
1520 run_test 25a "create file in symlinked directory ==============="
1521
1522 test_25b() {
1523         [ ! -d $DIR/d25 ] && test_25a
1524         $CHECKSTAT -t file $DIR/s25/foo || error "$DIR/s25/foo not file type"
1525 }
1526 run_test 25b "lookup file in symlinked directory ==============="
1527
1528 test_26a() {
1529         test_mkdir $DIR/d26
1530         test_mkdir $DIR/d26/d26-2
1531         ln -s d26/d26-2 $DIR/s26
1532         touch $DIR/s26/foo || error "File creation failed"
1533 }
1534 run_test 26a "multiple component symlink ======================="
1535
1536 test_26b() {
1537         test_mkdir -p $DIR/$tdir/d26-2
1538         ln -s $tdir/d26-2/foo $DIR/s26-2
1539         touch $DIR/s26-2 || error "File creation failed"
1540 }
1541 run_test 26b "multiple component symlink at end of lookup ======"
1542
1543 test_26c() {
1544         test_mkdir $DIR/d26.2
1545         touch $DIR/d26.2/foo
1546         ln -s d26.2 $DIR/s26.2-1
1547         ln -s s26.2-1 $DIR/s26.2-2
1548         ln -s s26.2-2 $DIR/s26.2-3
1549         chmod 0666 $DIR/s26.2-3/foo
1550 }
1551 run_test 26c "chain of symlinks"
1552
1553 # recursive symlinks (bug 439)
1554 test_26d() {
1555         ln -s d26-3/foo $DIR/d26-3
1556 }
1557 run_test 26d "create multiple component recursive symlink"
1558
1559 test_26e() {
1560         [ ! -h $DIR/d26-3 ] && test_26d
1561         rm $DIR/d26-3
1562 }
1563 run_test 26e "unlink multiple component recursive symlink"
1564
1565 # recursive symlinks (bug 7022)
1566 test_26f() {
1567         test_mkdir $DIR/$tdir
1568         test_mkdir $DIR/$tdir/$tfile
1569         cd $DIR/$tdir/$tfile           || error "cd $DIR/$tdir/$tfile failed"
1570         test_mkdir -p lndir/bar1
1571         test_mkdir $DIR/$tdir/$tfile/$tfile
1572         cd $tfile                || error "cd $tfile failed"
1573         ln -s .. dotdot          || error "ln dotdot failed"
1574         ln -s dotdot/lndir lndir || error "ln lndir failed"
1575         cd $DIR/$tdir                 || error "cd $DIR/$tdir failed"
1576         output=`ls $tfile/$tfile/lndir/bar1`
1577         [ "$output" = bar1 ] && error "unexpected output"
1578         rm -r $tfile             || error "rm $tfile failed"
1579         $CHECKSTAT -a $DIR/$tfile || error "$tfile not gone"
1580 }
1581 run_test 26f "rm -r of a directory which has recursive symlink"
1582
1583 test_27a() {
1584         test_mkdir $DIR/$tdir
1585         $LFS getstripe $DIR/$tdir
1586         $LFS setstripe -c 1 $DIR/$tdir/$tfile || error "setstripe failed"
1587         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1588         cp /etc/hosts $DIR/$tdir/$tfile || error "Can't copy to one stripe file"
1589 }
1590 run_test 27a "one stripe file"
1591
1592 test_27b() {
1593         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1594
1595         test_mkdir $DIR/$tdir
1596         $LFS setstripe -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
1597         $LFS getstripe -c $DIR/$tdir/$tfile
1598         [ $($LFS getstripe -c $DIR/$tdir/$tfile) -eq 2 ] ||
1599                 error "two-stripe file doesn't have two stripes"
1600
1601         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1602 }
1603 run_test 27b "create and write to two stripe file"
1604
1605 # 27c family tests specific striping, setstripe -o
1606 test_27ca() {
1607         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1608         test_mkdir -p $DIR/$tdir
1609         local osts="1"
1610
1611         $LFS setstripe -o $osts $DIR/$tdir/$tfile  || error "setstripe failed"
1612         $LFS getstripe -i $DIR/$tdir/$tfile
1613         [ $($LFS getstripe -i $DIR/$tdir/$tfile ) -eq $osts ] ||
1614                 error "stripe not on specified OST"
1615
1616         dd if=/dev/zero of=$DIR/$tdir/$tfile  bs=1M count=4 || error "dd failed"
1617 }
1618 run_test 27ca "one stripe on specified OST"
1619
1620 test_27cb() {
1621         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1622         test_mkdir -p $DIR/$tdir
1623         local osts="1,0"
1624         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1625         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1626         echo "$getstripe"
1627
1628         # Strip getstripe output to a space separated list of OSTs
1629         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1630                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1631         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1632                 error "stripes not on specified OSTs"
1633
1634         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1635 }
1636 run_test 27cb "two stripes on specified OSTs"
1637
1638 test_27cc() {
1639         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1640         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1641                 skip "server does not support overstriping"
1642
1643         test_mkdir -p $DIR/$tdir
1644         local osts="0,0"
1645         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1646         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1647         echo "$getstripe"
1648
1649         # Strip getstripe output to a space separated list of OSTs
1650         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1651                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1652         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1653                 error "stripes not on specified OSTs"
1654
1655         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1656 }
1657 run_test 27cc "two stripes on the same OST"
1658
1659 test_27cd() {
1660         [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test"
1661         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1662                 skip "server does not support overstriping"
1663         test_mkdir -p $DIR/$tdir
1664         local osts="0,1,1,0"
1665         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1666         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1667         echo "$getstripe"
1668
1669         # Strip getstripe output to a space separated list of OSTs
1670         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1671                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1672         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1673                 error "stripes not on specified OSTs"
1674
1675         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1676 }
1677 run_test 27cd "four stripes on two OSTs"
1678
1679 test_27ce() {
1680         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
1681                 skip_env "too many osts, skipping"
1682         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1683                 skip "server does not support overstriping"
1684         # We do one more stripe than we have OSTs
1685         [ $OSTCOUNT -lt 159 ] || large_xattr_enabled ||
1686                 skip_env "ea_inode feature disabled"
1687
1688         test_mkdir -p $DIR/$tdir
1689         local osts=""
1690         for i in $(seq 0 $OSTCOUNT);
1691         do
1692                 osts=$osts"0"
1693                 if [ $i -ne $OSTCOUNT ]; then
1694                         osts=$osts","
1695                 fi
1696         done
1697         $LFS setstripe -o $osts $DIR/$tdir/$tfile || error "setstripe failed"
1698         local getstripe=$($LFS getstripe $DIR/$tdir/$tfile)
1699         echo "$getstripe"
1700
1701         # Strip getstripe output to a space separated list of OSTs
1702         local getstripe_osts=$(echo "$getstripe" | sed -e '1,/obdidx/d' |\
1703                 awk '{print $1}' | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')
1704         [ "$getstripe_osts" = "${osts//,/ }" ] ||
1705                 error "stripes not on specified OSTs"
1706
1707         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 || error "dd failed"
1708 }
1709 run_test 27ce "more stripes than OSTs with -o"
1710
1711 test_27cf() {
1712         local osp_proc="osp.$FSNAME-OST0000-osc-MDT000*.active"
1713         local pid=0
1714
1715         test_mkdir -p $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
1716         do_facet $SINGLEMDS "$LCTL set_param -n $osp_proc=0"
1717         stack_trap "do_facet $SINGLEMDS $LCTL set_param -n $osp_proc=1" EXIT
1718         wait_update_facet $SINGLEMDS "$LCTL get_param -n $osp_proc | grep 1" ||
1719                 error "failed to set $osp_proc=0"
1720
1721         $LFS setstripe -o 0 $DIR/$tdir/$tfile &
1722         pid=$!
1723         sleep 1
1724         do_facet $SINGLEMDS "$LCTL set_param -n $osp_proc=1"
1725         wait_update_facet $SINGLEMDS "$LCTL get_param -n $osp_proc | grep 0" ||
1726                 error "failed to set $osp_proc=1"
1727         wait $pid
1728         [[ $pid -ne 0 ]] ||
1729                 error "should return error due to $osp_proc=0"
1730 }
1731 run_test 27cf "'setstripe -o' on inactive OSTs should return error"
1732
1733 test_27cg() {
1734         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
1735                 skip "server does not support overstriping"
1736         [[ $mds1_FSTYPE != "ldiskfs" ]] && skip_env "ldiskfs only test"
1737         large_xattr_enabled || skip_env "ea_inode feature disabled"
1738
1739         local osts="0"
1740
1741         for ((i=1;i<1000;i++)); do
1742                 osts+=",$((i % OSTCOUNT))"
1743         done
1744
1745         local mdts=$(comma_list $(mdts_nodes))
1746         local before=$(do_nodes $mdts \
1747                 "$LCTL get_param -n osd-ldiskfs.*MDT*.stats" |
1748                 awk '/many credits/{print $3}' |
1749                 calc_sum)
1750
1751         $LFS setstripe -o $osts $DIR/$tfile || error "setstripe failed"
1752         $LFS getstripe $DIR/$tfile | grep stripe
1753
1754         rm -f $DIR/$tfile || error "can't unlink"
1755
1756         after=$(do_nodes $mdts \
1757                 "$LCTL get_param -n osd-ldiskfs.*MDT*.stats" |
1758                 awk '/many credits/{print $3}' |
1759                 calc_sum)
1760
1761         (( before == after )) ||
1762                 error "too many credits happened: $after > $before"
1763 }
1764 run_test 27cg "1000 shouldn't cause too many credits"
1765
1766 test_27d() {
1767         test_mkdir $DIR/$tdir
1768         $LFS setstripe -c 0 -i -1 -S 0 $DIR/$tdir/$tfile ||
1769                 error "setstripe failed"
1770         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1771         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1772 }
1773 run_test 27d "create file with default settings"
1774
1775 test_27e() {
1776         # LU-5839 adds check for existed layout before setting it
1777         [[ $MDS1_VERSION -lt $(version_code 2.7.56) ]] &&
1778                 skip "Need MDS version at least 2.7.56"
1779
1780         test_mkdir $DIR/$tdir
1781         $LFS setstripe -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
1782         $LFS setstripe -c 2 $DIR/$tdir/$tfile && error "setstripe worked twice"
1783         $CHECKSTAT -t file $DIR/$tdir/$tfile || error "checkstat failed"
1784 }
1785 run_test 27e "setstripe existing file (should return error)"
1786
1787 test_27f() {
1788         test_mkdir $DIR/$tdir
1789         $LFS setstripe -S 100 -i 0 -c 1 $DIR/$tdir/$tfile &&
1790                 error "$LFS setstripe $DIR/$tdir/$tfile failed"
1791         $CHECKSTAT -t file $DIR/$tdir/$tfile &&
1792                 error "$CHECKSTAT -t file $DIR/$tdir/$tfile should fail"
1793         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
1794         $LFS getstripe $DIR/$tdir/$tfile || error "$LFS getstripe failed"
1795 }
1796 run_test 27f "setstripe with bad stripe size (should return error)"
1797
1798 test_27g() {
1799         test_mkdir $DIR/$tdir
1800         $MCREATE $DIR/$tdir/$tfile || error "mcreate failed"
1801         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "no stripe info" ||
1802                 error "$DIR/$tdir/$tfile has object"
1803 }
1804 run_test 27g "$LFS getstripe with no objects"
1805
1806 test_27ga() {
1807         test_mkdir $DIR/$tdir
1808         touch $DIR/$tdir/$tfile || error "touch failed"
1809         ln -s bogus $DIR/$tdir/$tfile.2 || error "ln failed"
1810         $LFS getstripe -m $DIR/$tdir/$tfile $DIR/$tdir/$tfile.2
1811         local rc=$?
1812         (( rc == 2 )) || error "getstripe did not return ENOENT"
1813
1814         local err_msg=$($LFS getstripe $DIR/$tdir/typo $DIR/$tdir/$tfile \
1815                         2>&1 > /dev/null)
1816         [[ $err_msg =~ "typo" ]] ||
1817                 error "expected message with correct filename, got '$err_msg'"
1818 }
1819 run_test 27ga "$LFS getstripe with missing file (should return error)"
1820
1821 test_27i() {
1822         test_mkdir $DIR/$tdir
1823         touch $DIR/$tdir/$tfile || error "touch failed"
1824         [[ $($LFS getstripe -c $DIR/$tdir/$tfile) -gt 0 ]] ||
1825                 error "missing objects"
1826 }
1827 run_test 27i "$LFS getstripe with some objects"
1828
1829 test_27j() {
1830         test_mkdir $DIR/$tdir
1831         $LFS setstripe -i $OSTCOUNT $DIR/$tdir/$tfile &&
1832                 error "setstripe failed" || true
1833 }
1834 run_test 27j "setstripe with bad stripe offset (should return error)"
1835
1836 test_27k() { # bug 2844
1837         test_mkdir $DIR/$tdir
1838         local file=$DIR/$tdir/$tfile
1839         local ll_max_blksize=$((4 * 1024 * 1024))
1840         $LFS setstripe -S 67108864 $file || error "setstripe failed"
1841         local blksize=$(stat $file | awk '/IO Block:/ { print $7 }')
1842         [ $blksize -le $ll_max_blksize ] || error "1:$blksize > $ll_max_blksize"
1843         dd if=/dev/zero of=$file bs=4k count=1
1844         blksize=$(stat $file | awk '/IO Block:/ { print $7 }')
1845         [ $blksize -le $ll_max_blksize ] || error "2:$blksize > $ll_max_blksize"
1846 }
1847 run_test 27k "limit i_blksize for broken user apps"
1848
1849 test_27l() {
1850         mcreate $DIR/$tfile || error "creating file"
1851         $RUNAS $LFS setstripe -c 1 $DIR/$tfile &&
1852                 error "setstripe should have failed" || true
1853 }
1854 run_test 27l "check setstripe permissions (should return error)"
1855
1856 test_27m() {
1857         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1858
1859         [ -n "$RCLIENTS" -o -n "$MOUNT_2" ] &&
1860                 skip_env "multiple clients -- skipping"
1861
1862         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
1863                    head -n1)
1864         if [[ $ORIGFREE -gt $MAXFREE ]]; then
1865                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
1866         fi
1867         stack_trap simple_cleanup_common
1868         test_mkdir $DIR/$tdir
1869         $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile.1
1870         dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=1024 count=$MAXFREE &&
1871                 error "dd should fill OST0"
1872         i=2
1873         while $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile.$i; do
1874                 i=$((i + 1))
1875                 [ $i -gt 256 ] && break
1876         done
1877         i=$((i + 1))
1878         touch $DIR/$tdir/$tfile.$i
1879         [ $($LFS getstripe $DIR/$tdir/$tfile.$i | grep -A 10 obdidx |
1880             awk '{print $1}'| grep -w "0") ] &&
1881                 error "OST0 was full but new created file still use it"
1882         i=$((i + 1))
1883         touch $DIR/$tdir/$tfile.$i
1884         [ $($LFS getstripe $DIR/$tdir/$tfile.$i | grep -A 10 obdidx |
1885             awk '{print $1}'| grep -w "0") ] &&
1886                 error "OST0 was full but new created file still use it" || true
1887 }
1888 run_test 27m "create file while OST0 was full"
1889
1890 # OSCs keep a NOSPC flag that will be reset after ~5s (qos_maxage)
1891 # if the OST isn't full anymore.
1892 reset_enospc() {
1893         local ostidx=${1:-""}
1894         local delay
1895         local ready
1896         local get_prealloc
1897
1898         local list=$(comma_list $(osts_nodes))
1899         [ "$ostidx" ] && list=$(facet_host ost$((ostidx + 1)))
1900
1901         do_nodes $list lctl set_param fail_loc=0
1902         wait_delete_completed   # initiate all OST_DESTROYs from MDS to OST
1903         delay=$(do_facet $SINGLEMDS lctl get_param -n lov.*.qos_maxage |
1904                 awk '{print $1 * 2;exit;}')
1905         get_prealloc="$LCTL get_param -n osc.*MDT*.prealloc_status |
1906                         grep -v \"^0$\""
1907         wait_update_facet $SINGLEMDS "$get_prealloc" "" $delay
1908 }
1909
1910 test_27n() {
1911         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1912         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1913         remote_mds_nodsh && skip "remote MDS with nodsh"
1914         remote_ost_nodsh && skip "remote OST with nodsh"
1915
1916         reset_enospc
1917         rm -f $DIR/$tdir/$tfile
1918         exhaust_precreations 0 0x80000215
1919         $LFS setstripe -c -1 $DIR/$tdir || error "setstripe failed"
1920         touch $DIR/$tdir/$tfile || error "touch failed"
1921         $LFS getstripe $DIR/$tdir/$tfile
1922         reset_enospc
1923 }
1924 run_test 27n "create file with some full OSTs"
1925
1926 test_27o() {
1927         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1928         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1929         remote_mds_nodsh && skip "remote MDS with nodsh"
1930         remote_ost_nodsh && skip "remote OST with nodsh"
1931
1932         reset_enospc
1933         rm -f $DIR/$tdir/$tfile
1934         exhaust_all_precreations 0x215
1935
1936         touch $DIR/$tdir/$tfile && error "able to create $DIR/$tdir/$tfile"
1937
1938         reset_enospc
1939         rm -rf $DIR/$tdir/*
1940 }
1941 run_test 27o "create file with all full OSTs (should error)"
1942
1943 function create_and_checktime() {
1944         local fname=$1
1945         local loops=$2
1946         local i
1947
1948         for ((i=0; i < $loops; i++)); do
1949                 local start=$SECONDS
1950                 multiop $fname-$i Oc
1951                 ((SECONDS-start < TIMEOUT)) ||
1952                         error "creation took " $((SECONDS-$start)) && return 1
1953         done
1954 }
1955
1956 test_27oo() {
1957         local mdts=$(comma_list $(mdts_nodes))
1958
1959         [ $MDS1_VERSION -lt $(version_code 2.13.57) ] &&
1960                 skip "Need MDS version at least 2.13.57"
1961
1962         local f0=$DIR/${tfile}-0
1963         local f1=$DIR/${tfile}-1
1964
1965         wait_delete_completed
1966
1967         # refill precreated objects
1968         $LFS setstripe -i0 -c1 $f0
1969
1970         saved=$(do_facet mds1 $LCTL get_param -n lov.*0000*.qos_threshold_rr)
1971         # force QoS allocation policy
1972         do_nodes $mdts $LCTL set_param lov.*.qos_threshold_rr=0%
1973         stack_trap "do_nodes $mdts $LCTL set_param \
1974                 lov.*.qos_threshold_rr=$saved" EXIT
1975         sleep_maxage
1976
1977         # one OST is unavailable, but still have few objects preallocated
1978         stop ost1
1979         stack_trap "start ost1 $(ostdevname 1) $OST_MOUNT_OPTS; \
1980                 rm -rf $f1 $DIR/$tdir*" EXIT
1981
1982         for ((i=0; i < 7; i++)); do
1983                 mkdir $DIR/$tdir$i || error "can't create dir"
1984                 $LFS setstripe -c$((OSTCOUNT-1)) $DIR/$tdir$i ||
1985                         error "can't set striping"
1986         done
1987         for ((i=0; i < 7; i++)); do
1988                 create_and_checktime $DIR/$tdir$i/$tfile 100 &
1989         done
1990         wait
1991 }
1992 run_test 27oo "don't let few threads to reserve too many objects"
1993
1994 test_27p() {
1995         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
1996         [ $PARALLEL == "yes" ] && skip "skip parallel run"
1997         remote_mds_nodsh && skip "remote MDS with nodsh"
1998         remote_ost_nodsh && skip "remote OST with nodsh"
1999
2000         reset_enospc
2001         rm -f $DIR/$tdir/$tfile
2002         test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
2003
2004         $MCREATE $DIR/$tdir/$tfile || error "mcreate failed"
2005         $TRUNCATE $DIR/$tdir/$tfile 80000000 || error "truncate failed"
2006         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat failed"
2007
2008         exhaust_precreations 0 0x80000215
2009         echo foo >> $DIR/$tdir/$tfile || error "append failed"
2010         $CHECKSTAT -s 80000004 $DIR/$tdir/$tfile || error "checkstat failed"
2011         $LFS getstripe $DIR/$tdir/$tfile
2012
2013         reset_enospc
2014 }
2015 run_test 27p "append to a truncated file with some full OSTs"
2016
2017 test_27q() {
2018         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2019         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2020         remote_mds_nodsh && skip "remote MDS with nodsh"
2021         remote_ost_nodsh && skip "remote OST with nodsh"
2022
2023         reset_enospc
2024         rm -f $DIR/$tdir/$tfile
2025
2026         mkdir_on_mdt0 $DIR/$tdir
2027         $MCREATE $DIR/$tdir/$tfile || error "mcreate $DIR/$tdir/$tfile failed"
2028         $TRUNCATE $DIR/$tdir/$tfile 80000000 ||
2029                 error "truncate $DIR/$tdir/$tfile failed"
2030         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat failed"
2031
2032         exhaust_all_precreations 0x215
2033
2034         echo foo >> $DIR/$tdir/$tfile && error "append succeeded"
2035         $CHECKSTAT -s 80000000 $DIR/$tdir/$tfile || error "checkstat 2 failed"
2036
2037         reset_enospc
2038 }
2039 run_test 27q "append to truncated file with all OSTs full (should error)"
2040
2041 test_27r() {
2042         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2043         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2044         remote_mds_nodsh && skip "remote MDS with nodsh"
2045         remote_ost_nodsh && skip "remote OST with nodsh"
2046
2047         reset_enospc
2048         rm -f $DIR/$tdir/$tfile
2049         exhaust_precreations 0 0x80000215
2050
2051         $LFS setstripe -i 0 -c 2 $DIR/$tdir/$tfile || error "setstripe failed"
2052
2053         reset_enospc
2054 }
2055 run_test 27r "stripe file with some full OSTs (shouldn't LBUG) ="
2056
2057 test_27s() { # bug 10725
2058         test_mkdir $DIR/$tdir
2059         local stripe_size=$((4096 * 1024 * 1024))       # 2^32
2060         local stripe_count=0
2061         [ $OSTCOUNT -eq 1 ] || stripe_count=2
2062         $LFS setstripe -S $stripe_size -c $stripe_count $DIR/$tdir &&
2063                 error "stripe width >= 2^32 succeeded" || true
2064
2065 }
2066 run_test 27s "lsm_xfersize overflow (should error) (bug 10725)"
2067
2068 test_27t() { # bug 10864
2069         WDIR=$(pwd)
2070         WLFS=$(which lfs)
2071         cd $DIR
2072         touch $tfile
2073         $WLFS getstripe $tfile
2074         cd $WDIR
2075 }
2076 run_test 27t "check that utils parse path correctly"
2077
2078 test_27u() { # bug 4900
2079         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2080         remote_mds_nodsh && skip "remote MDS with nodsh"
2081
2082         local index
2083         local list=$(comma_list $(mdts_nodes))
2084
2085 #define OBD_FAIL_MDS_OSC_PRECREATE      0x139
2086         do_nodes $list $LCTL set_param fail_loc=0x139
2087         test_mkdir -p $DIR/$tdir
2088         stack_trap "simple_cleanup_common 1000"
2089         createmany -o $DIR/$tdir/$tfile 1000
2090         do_nodes $list $LCTL set_param fail_loc=0
2091
2092         TLOG=$TMP/$tfile.getstripe
2093         $LFS getstripe $DIR/$tdir > $TLOG
2094         OBJS=$(awk -vobj=0 '($1 == 0) { obj += 1 } END { print obj; }' $TLOG)
2095         [[ $OBJS -gt 0 ]] &&
2096                 error "$OBJS objects created on OST-0. See $TLOG" ||
2097                 rm -f $TLOG
2098 }
2099 run_test 27u "skip object creation on OSC w/o objects"
2100
2101 test_27v() { # bug 4900
2102         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2103         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2104         remote_mds_nodsh && skip "remote MDS with nodsh"
2105         remote_ost_nodsh && skip "remote OST with nodsh"
2106
2107         exhaust_all_precreations 0x215
2108         reset_enospc
2109
2110         $LFS setstripe -c 1 $DIR/$tdir         # 1 stripe / file
2111
2112         touch $DIR/$tdir/$tfile
2113         #define OBD_FAIL_TGT_DELAY_PRECREATE     0x705
2114         # all except ost1
2115         for (( i=1; i < OSTCOUNT; i++ )); do
2116                 do_facet ost$i lctl set_param fail_loc=0x705
2117         done
2118         local START=`date +%s`
2119         createmany -o $DIR/$tdir/$tfile 32
2120
2121         local FINISH=`date +%s`
2122         local TIMEOUT=`lctl get_param -n timeout`
2123         local PROCESS=$((FINISH - START))
2124         [ $PROCESS -ge $((TIMEOUT / 2)) ] && \
2125                error "$FINISH - $START >= $TIMEOUT / 2"
2126         sleep $((TIMEOUT / 2 - PROCESS))
2127         reset_enospc
2128 }
2129 run_test 27v "skip object creation on slow OST"
2130
2131 test_27w() { # bug 10997
2132         test_mkdir $DIR/$tdir
2133         $LFS setstripe -S 65536 $DIR/$tdir/f0 || error "setstripe failed"
2134         [ $($LFS getstripe -S $DIR/$tdir/f0) -ne 65536 ] &&
2135                 error "stripe size $size != 65536" || true
2136         [ $($LFS getstripe -d $DIR/$tdir | grep -c "stripe_count") -eq 0 ] &&
2137                 error "$LFS getstripe -d $DIR/$tdir no 'stripe_count'" || true
2138 }
2139 run_test 27w "check $LFS setstripe -S and getstrip -d options"
2140
2141 test_27wa() {
2142         [[ $OSTCOUNT -lt 2 ]] &&
2143                 skip_env "skipping multiple stripe count/offset test"
2144
2145         test_mkdir $DIR/$tdir
2146         for i in $(seq 1 $OSTCOUNT); do
2147                 offset=$((i - 1))
2148                 $LFS setstripe -c $i -i $offset $DIR/$tdir/f$i ||
2149                         error "setstripe -c $i -i $offset failed"
2150                 count=$($LFS getstripe -c $DIR/$tdir/f$i)
2151                 index=$($LFS getstripe -i $DIR/$tdir/f$i)
2152                 [ $count -ne $i ] && error "stripe count $count != $i" || true
2153                 [ $index -ne $offset ] &&
2154                         error "stripe offset $index != $offset" || true
2155         done
2156 }
2157 run_test 27wa "check $LFS setstripe -c -i options"
2158
2159 test_27x() {
2160         remote_ost_nodsh && skip "remote OST with nodsh"
2161         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2162         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2163
2164         OFFSET=$(($OSTCOUNT - 1))
2165         OSTIDX=0
2166         local OST=$(ostname_from_index $OSTIDX)
2167
2168         test_mkdir $DIR/$tdir
2169         $LFS setstripe -c 1 $DIR/$tdir  # 1 stripe per file
2170         do_facet ost$((OSTIDX + 1)) lctl set_param -n obdfilter.$OST.degraded 1
2171         sleep_maxage
2172         createmany -o $DIR/$tdir/$tfile $OSTCOUNT
2173         for i in $(seq 0 $OFFSET); do
2174                 [ $($LFS getstripe $DIR/$tdir/$tfile$i | grep -A 10 obdidx |
2175                         awk '{print $1}' | grep -w "$OSTIDX") ] &&
2176                 error "OST0 was degraded but new created file still use it"
2177         done
2178         do_facet ost$((OSTIDX + 1)) lctl set_param -n obdfilter.$OST.degraded 0
2179 }
2180 run_test 27x "create files while OST0 is degraded"
2181
2182 test_27y() {
2183         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2184         remote_mds_nodsh && skip "remote MDS with nodsh"
2185         remote_ost_nodsh && skip "remote OST with nodsh"
2186         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2187
2188         local mdtosc=$(get_mdtosc_proc_path $SINGLEMDS $FSNAME-OST0000)
2189         local last_id=$(do_facet $SINGLEMDS lctl get_param -n \
2190                 osp.$mdtosc.prealloc_last_id)
2191         local next_id=$(do_facet $SINGLEMDS lctl get_param -n \
2192                 osp.$mdtosc.prealloc_next_id)
2193         local fcount=$((last_id - next_id))
2194         [[ $fcount -eq 0 ]] && skip "not enough space on OST0"
2195         [[ $fcount -gt $OSTCOUNT ]] && fcount=$OSTCOUNT
2196
2197         local MDS_OSCS=$(do_facet $SINGLEMDS lctl dl |
2198                          awk '/[oO][sS][cC].*md[ts]/ { print $4 }')
2199         local OST_DEACTIVE_IDX=-1
2200         local OSC
2201         local OSTIDX
2202         local OST
2203
2204         for OSC in $MDS_OSCS; do
2205                 OST=$(osc_to_ost $OSC)
2206                 OSTIDX=$(index_from_ostuuid $OST)
2207                 if [ $OST_DEACTIVE_IDX == -1 ]; then
2208                         OST_DEACTIVE_IDX=$OSTIDX
2209                 fi
2210                 if [ $OSTIDX != $OST_DEACTIVE_IDX ]; then
2211                         echo $OSC "is Deactivated:"
2212                         do_facet $SINGLEMDS lctl --device  %$OSC deactivate
2213                 fi
2214         done
2215
2216         OSTIDX=$(index_from_ostuuid $OST)
2217         test_mkdir $DIR/$tdir
2218         $LFS setstripe -c 1 $DIR/$tdir      # 1 stripe / file
2219
2220         for OSC in $MDS_OSCS; do
2221                 OST=$(osc_to_ost $OSC)
2222                 OSTIDX=$(index_from_ostuuid $OST)
2223                 if [ $OSTIDX == $OST_DEACTIVE_IDX ]; then
2224                         echo $OST "is degraded:"
2225                         do_facet ost$((OSTIDX+1)) lctl set_param -n \
2226                                                 obdfilter.$OST.degraded=1
2227                 fi
2228         done
2229
2230         sleep_maxage
2231         createmany -o $DIR/$tdir/$tfile $fcount
2232
2233         for OSC in $MDS_OSCS; do
2234                 OST=$(osc_to_ost $OSC)
2235                 OSTIDX=$(index_from_ostuuid $OST)
2236                 if [ $OSTIDX == $OST_DEACTIVE_IDX ]; then
2237                         echo $OST "is recovered from degraded:"
2238                         do_facet ost$((OSTIDX+1)) lctl set_param -n \
2239                                                 obdfilter.$OST.degraded=0
2240                 else
2241                         do_facet $SINGLEMDS lctl --device %$OSC activate
2242                 fi
2243         done
2244
2245         # all osp devices get activated, hence -1 stripe count restored
2246         local stripe_count=0
2247
2248         # sleep 2*lod_qos_maxage seconds waiting for lod qos to notice osp
2249         # devices get activated.
2250         sleep_maxage
2251         $LFS setstripe -c -1 $DIR/$tfile
2252         stripe_count=$($LFS getstripe -c $DIR/$tfile)
2253         rm -f $DIR/$tfile
2254         [ $stripe_count -ne $OSTCOUNT ] &&
2255                 error "Of $OSTCOUNT OSTs, only $stripe_count is available"
2256         return 0
2257 }
2258 run_test 27y "create files while OST0 is degraded and the rest inactive"
2259
2260 check_seq_oid()
2261 {
2262         log "check file $1"
2263
2264         lmm_count=$($LFS getstripe -c $1)
2265         lmm_seq=$($LFS getstripe -v $1 | awk '/lmm_seq/ { print $2 }')
2266         lmm_oid=$($LFS getstripe -v $1 | awk '/lmm_object_id/ { print $2 }')
2267
2268         local old_ifs="$IFS"
2269         IFS=$'[:]'
2270         fid=($($LFS path2fid $1))
2271         IFS="$old_ifs"
2272
2273         log "FID seq ${fid[1]}, oid ${fid[2]} ver ${fid[3]}"
2274         log "LOV seq $lmm_seq, oid $lmm_oid, count: $lmm_count"
2275
2276         # compare lmm_seq and lu_fid->f_seq
2277         [ $lmm_seq = ${fid[1]} ] || { error "SEQ mismatch"; return 1; }
2278         # compare lmm_object_id and lu_fid->oid
2279         [ $lmm_oid = ${fid[2]} ] || { error "OID mismatch"; return 2; }
2280
2281         # check the trusted.fid attribute of the OST objects of the file
2282         local have_obdidx=false
2283         local stripe_nr=0
2284         $LFS getstripe $1 | while read obdidx oid hex seq; do
2285                 # skip lines up to and including "obdidx"
2286                 [ -z "$obdidx" ] && break
2287                 [ "$obdidx" = "obdidx" ] && have_obdidx=true && continue
2288                 $have_obdidx || continue
2289
2290                 local ost=$((obdidx + 1))
2291                 local dev=$(ostdevname $ost)
2292                 local oid_hex
2293
2294                 log "want: stripe:$stripe_nr ost:$obdidx oid:$oid/$hex seq:$seq"
2295
2296                 seq=$(echo $seq | sed -e "s/^0x//g")
2297                 if [ $seq == 0 ] || [ $(facet_fstype ost$ost) == zfs ]; then
2298                         oid_hex=$(echo $oid)
2299                 else
2300                         oid_hex=$(echo $hex | sed -e "s/^0x//g")
2301                 fi
2302                 local obj_file="O/$seq/d$((oid %32))/$oid_hex"
2303
2304                 local ff=""
2305                 #
2306                 # Don't unmount/remount the OSTs if we don't need to do that.
2307                 # LU-2577 changes filter_fid to be smaller, so debugfs needs
2308                 # update too, until that use mount/ll_decode_filter_fid/mount.
2309                 # Re-enable when debugfs will understand new filter_fid.
2310                 #
2311                 if [ $(facet_fstype ost$ost) == ldiskfs ]; then
2312                         ff=$(do_facet ost$ost "$DEBUGFS -c -R 'stat $obj_file' \
2313                                 $dev 2>/dev/null" | grep "parent=")
2314                 fi
2315                 if [ -z "$ff" ]; then
2316                         stop ost$ost
2317                         mount_fstype ost$ost
2318                         ff=$(do_facet ost$ost $LL_DECODE_FILTER_FID \
2319                                 $(facet_mntpt ost$ost)/$obj_file)
2320                         unmount_fstype ost$ost
2321                         start ost$ost $dev $OST_MOUNT_OPTS
2322                         clients_up
2323                 fi
2324
2325                 [ -z "$ff" ] && error "$obj_file: no filter_fid info"
2326
2327                 echo "$ff" | sed -e 's#.*objid=#got: objid=#'
2328
2329                 # /mnt/O/0/d23/23: objid=23 seq=0 parent=[0x200000400:0x1e:0x1]
2330                 # fid: objid=23 seq=0 parent=[0x200000400:0x1e:0x0] stripe=1
2331                 #
2332                 # fid: parent=[0x200000400:0x1e:0x0] stripe=1 stripe_count=2 \
2333                 #       stripe_size=1048576 component_id=1 component_start=0 \
2334                 #       component_end=33554432
2335                 local ff_parent=$(sed -e 's/.*parent=.//' <<<$ff)
2336                 local ff_pseq=$(cut -d: -f1 <<<$ff_parent)
2337                 local ff_poid=$(cut -d: -f2 <<<$ff_parent)
2338                 local ff_pstripe
2339                 if grep -q 'stripe=' <<<$ff; then
2340                         ff_pstripe=$(sed -e 's/.*stripe=//' -e 's/ .*//' <<<$ff)
2341                 else
2342                         # $LL_DECODE_FILTER_FID does not print "stripe="; look
2343                         # into f_ver in this case.  See comment on ff_parent.
2344                         ff_pstripe=$(cut -d: -f3 <<<$ff_parent | sed -e 's/]//')
2345                 fi
2346
2347                 # compare lmm_seq and filter_fid->ff_parent.f_seq
2348                 [ $ff_pseq = $lmm_seq ] ||
2349                         error "FF parent SEQ $ff_pseq != $lmm_seq"
2350                 # compare lmm_object_id and filter_fid->ff_parent.f_oid
2351                 [ $ff_poid = $lmm_oid ] ||
2352                         error "FF parent OID $ff_poid != $lmm_oid"
2353                 (($ff_pstripe == $stripe_nr)) ||
2354                         error "FF stripe $ff_pstripe != $stripe_nr"
2355
2356                 stripe_nr=$((stripe_nr + 1))
2357                 [ $CLIENT_VERSION -lt $(version_code 2.9.55) ] &&
2358                         continue
2359                 if grep -q 'stripe_count=' <<<$ff; then
2360                         local ff_scnt=$(sed -e 's/.*stripe_count=//' \
2361                                             -e 's/ .*//' <<<$ff)
2362                         [ $lmm_count = $ff_scnt ] ||
2363                                 error "FF stripe count $lmm_count != $ff_scnt"
2364                 fi
2365         done
2366 }
2367
2368 test_27z() {
2369         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2370         remote_ost_nodsh && skip "remote OST with nodsh"
2371
2372         test_mkdir $DIR/$tdir
2373         $LFS setstripe -c 1 -i 0 -S 64k $DIR/$tdir/$tfile-1 ||
2374                 { error "setstripe -c -1 failed"; return 1; }
2375         # We need to send a write to every object to get parent FID info set.
2376         # This _should_ also work for setattr, but does not currently.
2377         # touch $DIR/$tdir/$tfile-1 ||
2378         dd if=/dev/zero of=$DIR/$tdir/$tfile-1 bs=1M count=1 ||
2379                 { error "dd $tfile-1 failed"; return 2; }
2380         $LFS setstripe -c -1 -i $((OSTCOUNT - 1)) -S 1M $DIR/$tdir/$tfile-2 ||
2381                 { error "setstripe -c -1 failed"; return 3; }
2382         dd if=/dev/zero of=$DIR/$tdir/$tfile-2 bs=1M count=$OSTCOUNT ||
2383                 { error "dd $tfile-2 failed"; return 4; }
2384
2385         # make sure write RPCs have been sent to OSTs
2386         sync; sleep 5; sync
2387
2388         check_seq_oid $DIR/$tdir/$tfile-1 || return 5
2389         check_seq_oid $DIR/$tdir/$tfile-2 || return 6
2390 }
2391 run_test 27z "check SEQ/OID on the MDT and OST filesystems"
2392
2393 test_27A() { # b=19102
2394         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2395
2396         save_layout_restore_at_exit $MOUNT
2397         $LFS setstripe -c 0 -i -1 -S 0 $MOUNT
2398         wait_update $HOSTNAME "$LFS getstripe -c $MOUNT | sed 's/  *//g'" "1" 20 ||
2399                 error "stripe count $($LFS getstripe -c $MOUNT) != 1"
2400         local default_size=$($LFS getstripe -S $MOUNT)
2401         local default_offset=$($LFS getstripe -i $MOUNT)
2402         local dsize=$(do_facet $SINGLEMDS \
2403                 "$LCTL get_param -n lod.$(facet_svc $SINGLEMDS)*.stripesize")
2404         [ $default_size -eq $dsize ] ||
2405                 error "stripe size $default_size != $dsize"
2406         [ $default_offset -eq -1 ] ||
2407                 error "stripe offset $default_offset != -1"
2408 }
2409 run_test 27A "check filesystem-wide default LOV EA values"
2410
2411 test_27B() { # LU-2523
2412         test_mkdir $DIR/$tdir
2413         rm -f $DIR/$tdir/f0 $DIR/$tdir/f1
2414         touch $DIR/$tdir/f0
2415         # open f1 with O_LOV_DELAY_CREATE
2416         # rename f0 onto f1
2417         # call setstripe ioctl on open file descriptor for f1
2418         # close
2419         multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:nB1c \
2420                 $DIR/$tdir/f0
2421
2422         rm -f $DIR/$tdir/f1
2423         # open f1 with O_LOV_DELAY_CREATE
2424         # unlink f1
2425         # call setstripe ioctl on open file descriptor for f1
2426         # close
2427         multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:uB1c
2428
2429         # Allow multiop to fail in imitation of NFS's busted semantics.
2430         true
2431 }
2432 run_test 27B "call setstripe on open unlinked file/rename victim"
2433
2434 # 27C family tests full striping and overstriping
2435 test_27Ca() { #LU-2871
2436         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2437
2438         declare -a ost_idx
2439         local index
2440         local found
2441         local i
2442         local j
2443
2444         test_mkdir $DIR/$tdir
2445         cd $DIR/$tdir
2446         for i in $(seq 0 $((OSTCOUNT - 1))); do
2447                 # set stripe across all OSTs starting from OST$i
2448                 $LFS setstripe -i $i -c -1 $tfile$i
2449                 # get striping information
2450                 ost_idx=($($LFS getstripe $tfile$i |
2451                          tail -n $((OSTCOUNT + 1)) | awk '{print $1}'))
2452                 echo "OST Index: ${ost_idx[*]}"
2453
2454                 # check the layout
2455                 [ ${#ost_idx[@]} -eq $OSTCOUNT ] ||
2456                         error "${#ost_idx[@]} != $OSTCOUNT"
2457
2458                 for index in $(seq 0 $((OSTCOUNT - 1))); do
2459                         found=0
2460                         for j in "${ost_idx[@]}"; do
2461                                 if [ $index -eq $j ]; then
2462                                         found=1
2463                                         break
2464                                 fi
2465                         done
2466                         [ $found = 1 ] ||
2467                                 error "Can not find $index in ${ost_idx[*]}"
2468                 done
2469         done
2470 }
2471 run_test 27Ca "check full striping across all OSTs"
2472
2473 test_27Cb() {
2474         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2475                 skip "server does not support overstriping"
2476         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
2477                 skip_env "too many osts, skipping"
2478
2479         test_mkdir -p $DIR/$tdir
2480         local setcount=$(($OSTCOUNT * 2))
2481         [ $setcount -lt 160 ] || large_xattr_enabled ||
2482                 skip_env "ea_inode feature disabled"
2483
2484         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2485                 error "setstripe failed"
2486
2487         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2488         [ $count -eq $setcount ] ||
2489                 error "stripe count $count, should be $setcount"
2490
2491         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2492                 error "overstriped should be set in pattern"
2493
2494         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2495                 error "dd failed"
2496 }
2497 run_test 27Cb "more stripes than OSTs with -C"
2498
2499 test_27Cc() {
2500         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2501                 skip "server does not support overstriping"
2502         [[ $OSTCOUNT -lt 2 ]] && skip_env "need > 1 OST"
2503
2504         test_mkdir -p $DIR/$tdir
2505         local setcount=$(($OSTCOUNT - 1))
2506
2507         [ $setcount -lt 160 ] || large_xattr_enabled ||
2508                 skip_env "ea_inode feature disabled"
2509
2510         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2511                 error "setstripe failed"
2512
2513         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2514         [ $count -eq $setcount ] ||
2515                 error "stripe count $count, should be $setcount"
2516
2517         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" &&
2518                 error "overstriped should not be set in pattern"
2519
2520         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2521                 error "dd failed"
2522 }
2523 run_test 27Cc "fewer stripes than OSTs does not set overstriping"
2524
2525 test_27Cd() {
2526         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2527                 skip "server does not support overstriping"
2528         [[ $OSTCOUNT -lt 2 ]] && skip_env "need > 1 OST"
2529         large_xattr_enabled || skip_env "ea_inode feature disabled"
2530
2531         force_new_seq_all
2532
2533         test_mkdir -p $DIR/$tdir
2534         local setcount=$LOV_MAX_STRIPE_COUNT
2535
2536         $LFS setstripe -C $setcount $DIR/$tdir/$tfile ||
2537                 error "setstripe failed"
2538
2539         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2540         [ $count -eq $setcount ] ||
2541                 error "stripe count $count, should be $setcount"
2542
2543         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2544                 error "overstriped should be set in pattern"
2545
2546         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2547                 error "dd failed"
2548
2549         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2550 }
2551 run_test 27Cd "test maximum stripe count"
2552
2553 test_27Ce() {
2554         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2555                 skip "server does not support overstriping"
2556         test_mkdir -p $DIR/$tdir
2557
2558         pool_add $TESTNAME || error "Pool creation failed"
2559         pool_add_targets $TESTNAME 0 || error "pool_add_targets failed"
2560
2561         local setcount=8
2562
2563         $LFS setstripe  -C $setcount -p "$TESTNAME" $DIR/$tdir/$tfile ||
2564                 error "setstripe failed"
2565
2566         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2567         [ $count -eq $setcount ] ||
2568                 error "stripe count $count, should be $setcount"
2569
2570         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2571                 error "overstriped should be set in pattern"
2572
2573         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2574                 error "dd failed"
2575
2576         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2577 }
2578 run_test 27Ce "test pool with overstriping"
2579
2580 test_27Cf() {
2581         [[ $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ]] ||
2582                 skip "server does not support overstriping"
2583         [[ $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
2584                 skip_env "too many osts, skipping"
2585
2586         test_mkdir -p $DIR/$tdir
2587
2588         local setcount=$(($OSTCOUNT * 2))
2589         [ $setcount -lt 160 ] || large_xattr_enabled ||
2590                 skip_env "ea_inode feature disabled"
2591
2592         $LFS setstripe  -C $setcount $DIR/$tdir/ ||
2593                 error "setstripe failed"
2594
2595         echo 1 > $DIR/$tdir/$tfile
2596
2597         local count=$($LFS getstripe -c $DIR/$tdir/$tfile)
2598         [ $count -eq $setcount ] ||
2599                 error "stripe count $count, should be $setcount"
2600
2601         $LFS getstripe $DIR/$tdir/$tfile 2>&1 | grep "overstriped" ||
2602                 error "overstriped should be set in pattern"
2603
2604         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=4 conv=notrunc ||
2605                 error "dd failed"
2606
2607         rm -f $DIR/$tdir/$tfile || error "Delete $tfile failed"
2608 }
2609 run_test 27Cf "test default inheritance with overstriping"
2610
2611 test_27Cg() {
2612         (( MDS1_VERSION >= $(version_code v2_15_55-80-gd96b98ee6b) )) ||
2613                 skip "need MDS version at least v2_15_55-80-gd96b98ee6b for fix"
2614
2615         $LFS setstripe -o 0,$OSTCOUNT $DIR/$tfile
2616         (( $? != 0 )) || error "must be an error for not existent OST#"
2617 }
2618 run_test 27Cg "test setstripe with wrong OST idx"
2619
2620 test_27Ci() {
2621         local tf=$DIR/$tfile
2622
2623         stack_trap "rm -f $DIR/$tfile"
2624
2625         $LFS setstripe -E1M $tf || error "create $tf failed"
2626         $LFS setstripe -Eeof --component-add -C 100 $tf ||
2627                 error "add component failed"
2628
2629         $LFS getstripe -I2 $tf | awk '/lmm_pattern/ { print $2 }' |
2630                 grep "overstriped" || {
2631                 $LFS getstripe $tf
2632                 echo "lose overstriping setting"
2633         }
2634         sc=$($LFS getstripe -I2 --stripe-count $tf)
2635         (( $sc == 100 )) || {
2636                 $LFS getstripe $tf
2637                 echo "lose overstriping setting"
2638         }
2639
2640         stack_trap "rm -f $tf"
2641         dd if=/dev/zero of=$tf bs=1M count=10 || error "write $tf"
2642         sc=$($LFS getstripe -I2 --stripe-count $tf)
2643         (( $sc == 100 )) || {
2644                 $LFS getstripe $tf
2645                 echo "lose overstriping setting after instantiation"
2646         }
2647 }
2648 run_test 27Ci "add an overstriping component"
2649
2650 test_27D() {
2651         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
2652         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
2653         remote_mds_nodsh && skip "remote MDS with nodsh"
2654
2655         local POOL=${POOL:-testpool}
2656         local first_ost=0
2657         local last_ost=$(($OSTCOUNT - 1))
2658         local ost_step=1
2659         local ost_list=$(seq $first_ost $ost_step $last_ost)
2660         local ost_range="$first_ost $last_ost $ost_step"
2661
2662         test_mkdir $DIR/$tdir
2663         pool_add $POOL || error "pool_add failed"
2664         pool_add_targets $POOL $ost_range || error "pool_add_targets failed"
2665
2666         local skip27D
2667         [ $MDS1_VERSION -lt $(version_code 2.8.55) ] &&
2668                 skip27D+="-s 29"
2669         [ $MDS1_VERSION -lt $(version_code 2.9.55) ] ||
2670                 [ $CLIENT_VERSION -lt $(version_code 2.9.55) ] &&
2671                         skip27D+=" -s 30,31"
2672         [[ ! $($LCTL get_param mdc.*.import) =~ connect_flags.*overstriping ||
2673           $OSTCOUNT -ge $(($LOV_MAX_STRIPE_COUNT / 2)) ]] &&
2674                 skip27D+=" -s 32,33"
2675         [[ $MDS_VERSION -lt $(version_code $SEL_VER) ]] &&
2676                 skip27D+=" -s 34"
2677         llapi_layout_test -d$DIR/$tdir -p$POOL -o$OSTCOUNT $skip27D ||
2678                 error "llapi_layout_test failed"
2679
2680         destroy_test_pools || error "destroy test pools failed"
2681 }
2682 run_test 27D "validate llapi_layout API"
2683
2684 # Verify that default_easize is increased from its initial value after
2685 # accessing a widely striped file.
2686 test_27E() {
2687         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
2688         [ $CLIENT_VERSION -lt $(version_code 2.5.57) ] &&
2689                 skip "client does not have LU-3338 fix"
2690
2691         # 72 bytes is the minimum space required to store striping
2692         # information for a file striped across one OST:
2693         # (sizeof(struct lov_user_md_v3) +
2694         #  sizeof(struct lov_user_ost_data_v1))
2695         local min_easize=72
2696         $LCTL set_param -n llite.*.default_easize $min_easize ||
2697                 error "lctl set_param failed"
2698         local easize=$($LCTL get_param -n llite.*.default_easize)
2699
2700         [ $easize -eq $min_easize ] ||
2701                 error "failed to set default_easize"
2702
2703         $LFS setstripe -c $OSTCOUNT $DIR/$tfile ||
2704                 error "setstripe failed"
2705         # In order to ensure stat() call actually talks to MDS we need to
2706         # do something drastic to this file to shake off all lock, e.g.
2707         # rename it (kills lookup lock forcing cache cleaning)
2708         mv $DIR/$tfile $DIR/${tfile}-1
2709         ls -l $DIR/${tfile}-1
2710         rm $DIR/${tfile}-1
2711
2712         easize=$($LCTL get_param -n llite.*.default_easize)
2713
2714         [ $easize -gt $min_easize ] ||
2715                 error "default_easize not updated"
2716 }
2717 run_test 27E "check that default extended attribute size properly increases"
2718
2719 test_27F() { # LU-5346/LU-7975
2720         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2721         [[ $OSTCOUNT -lt 2 ]] && skip "needs >= 2 OSTs"
2722         [[ $MDS1_VERSION -lt $(version_code 2.8.51) ]] &&
2723                 skip "Need MDS version at least 2.8.51"
2724         remote_ost_nodsh && skip "remote OST with nodsh"
2725
2726         test_mkdir $DIR/$tdir
2727         rm -f $DIR/$tdir/f0
2728         $LFS setstripe -c 2 $DIR/$tdir
2729
2730         # stop all OSTs to reproduce situation for LU-7975 ticket
2731         for num in $(seq $OSTCOUNT); do
2732                 stop ost$num
2733         done
2734
2735         # open/create f0 with O_LOV_DELAY_CREATE
2736         # truncate f0 to a non-0 size
2737         # close
2738         multiop $DIR/$tdir/f0 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:T1050000c
2739
2740         $CHECKSTAT -s 1050000 $DIR/$tdir/f0 || error "checkstat failed"
2741         # open/write it again to force delayed layout creation
2742         cat /etc/hosts > $DIR/$tdir/f0 &
2743         catpid=$!
2744
2745         # restart OSTs
2746         for num in $(seq $OSTCOUNT); do
2747                 start ost$num $(ostdevname $num) $OST_MOUNT_OPTS ||
2748                         error "ost$num failed to start"
2749         done
2750
2751         wait $catpid || error "cat failed"
2752
2753         cmp /etc/hosts $DIR/$tdir/f0 || error "cmp failed"
2754         [[ $($LFS getstripe -c $DIR/$tdir/f0) == 2 ]] ||
2755                 error "wrong stripecount"
2756
2757 }
2758 run_test 27F "Client resend delayed layout creation with non-zero size"
2759
2760 test_27G() { #LU-10629
2761         [ $MDS1_VERSION -lt $(version_code 2.11.51) ] &&
2762                 skip "Need MDS version at least 2.11.51"
2763         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
2764         remote_mds_nodsh && skip "remote MDS with nodsh"
2765         local POOL=${POOL:-testpool}
2766         local ostrange="0 0 1"
2767
2768         test_mkdir $DIR/$tdir
2769         touch $DIR/$tdir/$tfile.nopool
2770         pool_add $POOL || error "pool_add failed"
2771         pool_add_targets $POOL $ostrange || error "pool_add_targets failed"
2772         $LFS setstripe -p $POOL $DIR/$tdir
2773
2774         local pool=$($LFS getstripe -p $DIR/$tdir)
2775
2776         [ "$pool" = "$POOL" ] || error "Striping failed got '$pool' not '$POOL'"
2777         touch $DIR/$tdir/$tfile.default
2778         $LFS setstripe -E 1M --pool $POOL -c 1 -E eof -c 1 $DIR/$tdir/$tfile.pfl
2779         $LFS find $DIR/$tdir -type f --pool $POOL
2780         local found=$($LFS find $DIR/$tdir -type f --pool $POOL | wc -l)
2781         [[ "$found" == "2" ]] ||
2782                 error "found $found != 2 files in '$DIR/$tdir' in '$POOL'"
2783
2784         $LFS setstripe -d $DIR/$tdir
2785
2786         pool=$($LFS getstripe -p -d $DIR/$tdir)
2787
2788         [[ "$pool" != "$POOL" ]] || error "$DIR/$tdir is still '$pool'"
2789 }
2790 run_test 27G "Clear OST pool from stripe"
2791
2792 test_27H() {
2793         [[ $MDS1_VERSION -le $(version_code 2.11.54) ]] &&
2794                 skip "Need MDS version newer than 2.11.54"
2795         [[ $OSTCOUNT -lt 3 ]] && skip_env "needs >= 3 OSTs"
2796         test_mkdir $DIR/$tdir
2797         $LFS setstripe -o 0 -o 2 $DIR/$tdir || error "setstripe failed"
2798         touch $DIR/$tdir/$tfile
2799         $LFS getstripe -c $DIR/$tdir/$tfile
2800         [ $($LFS getstripe -c $DIR/$tdir/$tfile) -eq 2 ] ||
2801                 error "two-stripe file doesn't have two stripes"
2802
2803         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=4k count=4 || error "dd failed"
2804         $LFS getstripe -y $DIR/$tdir/$tfile
2805         (( $($LFS getstripe -y $DIR/$tdir/$tfile |
2806              egrep -c "l_ost_idx: [02]$") == "2" )) ||
2807                 error "expected l_ost_idx: [02]$ not matched"
2808
2809         # make sure ost list has been cleared
2810         local stripesize=$($LFS getstripe -S $DIR/$tdir)
2811         $LFS setstripe -S $((stripesize * 4)) -i 1 \
2812                 -c $((OSTCOUNT - 1)) $DIR/$tdir || error "setstripe"
2813         touch $DIR/$tdir/f3
2814         $LVERIFY $DIR/$tdir $DIR/$tdir/f3 || error "lverify failed"
2815 }
2816 run_test 27H "Set specific OSTs stripe"
2817
2818 test_27I() {
2819         [ $PARALLEL == "yes" ] && skip "skip parallel run"
2820         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
2821         [[ $MDS1_VERSION -gt $(version_code 2.12.52) ]] ||
2822                 skip "Need MDS version newer than 2.12.52"
2823         local pool=$TESTNAME
2824         local ostrange="1 1 1"
2825
2826         save_layout_restore_at_exit $MOUNT
2827         $LFS setstripe -c 2 -i 0 $MOUNT
2828         pool_add $pool || error "pool_add failed"
2829         pool_add_targets $pool $ostrange ||
2830                 error "pool_add_targets failed"
2831         test_mkdir $DIR/$tdir
2832         $LFS setstripe -p $pool $DIR/$tdir
2833         $MULTIOP $DIR/$tdir/$tfile Oc || error "multiop failed"
2834         $LFS getstripe $DIR/$tdir/$tfile
2835 }
2836 run_test 27I "check that root dir striping does not break parent dir one"
2837
2838 test_27J() {
2839         (( $MDS1_VERSION > $(version_code 2.12.51) )) ||
2840                 skip "Need MDS version newer than 2.12.51"
2841
2842         # skip basic ops on file with foreign LOV tests on 5.12-6.2 kernels
2843         # until the filemap_read() issue is fixed by v6.2-rc4-61-g5956592ce337
2844         (( $LINUX_VERSION_CODE < $(version_code 5.12.0) ||
2845            $LINUX_VERSION_CODE >= $(version_code 6.2.0) )) ||
2846                 skip "Need kernel < 5.12.0 or >= 6.2.0 for filemap_read() fix"
2847
2848         test_mkdir $DIR/$tdir
2849         local uuid1=$(cat /proc/sys/kernel/random/uuid)
2850         local uuid2=$(cat /proc/sys/kernel/random/uuid)
2851
2852         # create foreign file (raw way)
2853         ! $LFS setstripe --flags 0xda08 $DIR/$tdir/$tfile ||
2854                 error "creating $tfile w/ hex flags w/o --foreign should fail"
2855
2856         ! $LFS setstripe --foreign --flags foo \
2857                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tfile ||
2858                         error "creating $tfile with '--flags foo' should fail"
2859
2860         ! $LFS setstripe --foreign --flags 0xffffffff \
2861                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tfile ||
2862                         error "creating $tfile w/ 0xffffffff flags should fail"
2863
2864         create_foreign_file -f $DIR/$tdir/$tfile -x "${uuid1}@${uuid2}" \
2865                 -t 1 -F 0xda08 || error "create_foreign_file failed"
2866
2867         # verify foreign file (raw way)
2868         parse_foreign_file -f $DIR/$tdir/$tfile |
2869                 grep "lov_foreign_magic: 0x0BD70BD0" ||
2870                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign magic"
2871         parse_foreign_file -f $DIR/$tdir/$tfile | grep "lov_xattr_size: 89" ||
2872                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign size"
2873         parse_foreign_file -f $DIR/$tdir/$tfile |
2874                 grep "lov_foreign_size: 73" ||
2875                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign size"
2876         parse_foreign_file -f $DIR/$tdir/$tfile |
2877                 grep "lov_foreign_type: 1" ||
2878                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign type"
2879         parse_foreign_file -f $DIR/$tdir/$tfile |
2880                 grep "lov_foreign_flags: 0x0000DA08" ||
2881                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign flags"
2882         local lov=$(parse_foreign_file -f $DIR/$tdir/$tfile |
2883                 grep "lov_foreign_value: 0x" |
2884                 sed -e 's/lov_foreign_value: 0x//')
2885         local lov2=$(echo -n "${uuid1}@${uuid2}" | od -A n -t x1 -w160)
2886         [[ $lov = ${lov2// /} ]] ||
2887                 error "$DIR/$tdir/$tfile: invalid LOV EA foreign value"
2888
2889         # create foreign file (lfs + API)
2890         $LFS setstripe --foreign=none --flags 0xda08 \
2891                 -x "${uuid1}@${uuid2}" $DIR/$tdir/${tfile}2 ||
2892                 error "$DIR/$tdir/${tfile}2: create failed"
2893
2894         $LFS getstripe -v $DIR/$tdir/${tfile}2 |
2895                 grep "lfm_magic:.*0x0BD70BD0" ||
2896                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign magic"
2897         # lfm_length is LOV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
2898         $LFS getstripe -v $DIR/$tdir/${tfile}2 | grep "lfm_length:.*73" ||
2899                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign size"
2900         $LFS getstripe -v $DIR/$tdir/${tfile}2 | grep "lfm_type:.*none" ||
2901                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign type"
2902         $LFS getstripe -v $DIR/$tdir/${tfile}2 |
2903                 grep "lfm_flags:.*0x0000DA08" ||
2904                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign flags"
2905         $LFS getstripe $DIR/$tdir/${tfile}2 |
2906                 grep "lfm_value:.*${uuid1}@${uuid2}" ||
2907                 error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign value"
2908
2909         # modify striping should fail
2910         $LFS setstripe -c 2 $DIR/$tdir/$tfile &&
2911                 error "$DIR/$tdir/$tfile: setstripe should fail"
2912         $LFS setstripe -c 2 $DIR/$tdir/${tfile}2 &&
2913                 error "$DIR/$tdir/${tfile}2: setstripe should fail"
2914
2915         # R/W should fail
2916         cat $DIR/$tdir/$tfile && error "$DIR/$tdir/$tfile: read should fail"
2917         cat $DIR/$tdir/${tfile}2 &&
2918                 error "$DIR/$tdir/${tfile}2: read should fail"
2919         cat /etc/passwd > $DIR/$tdir/$tfile &&
2920                 error "$DIR/$tdir/$tfile: write should fail"
2921         cat /etc/passwd > $DIR/$tdir/${tfile}2 &&
2922                 error "$DIR/$tdir/${tfile}2: write should fail"
2923
2924         # chmod should work
2925         chmod 222 $DIR/$tdir/$tfile ||
2926                 error "$DIR/$tdir/$tfile: chmod failed"
2927         chmod 222 $DIR/$tdir/${tfile}2 ||
2928                 error "$DIR/$tdir/${tfile}2: chmod failed"
2929
2930         # chown should work
2931         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/$tfile ||
2932                 error "$DIR/$tdir/$tfile: chown failed"
2933         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tfile}2 ||
2934                 error "$DIR/$tdir/${tfile}2: chown failed"
2935
2936         # rename should work
2937         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}.new ||
2938                 error "$DIR/$tdir/$tfile: rename of foreign file has failed"
2939         mv $DIR/$tdir/${tfile}2 $DIR/$tdir/${tfile}2.new ||
2940                 error "$DIR/$tdir/${tfile}2: rename of foreign file has failed"
2941
2942         #remove foreign file
2943         rm $DIR/$tdir/${tfile}.new ||
2944                 error "$DIR/$tdir/${tfile}.new: remove of foreign file has failed"
2945         rm $DIR/$tdir/${tfile}2.new ||
2946                 error "$DIR/$tdir/${tfile}2.new: remove of foreign file has failed"
2947 }
2948 run_test 27J "basic ops on file with foreign LOV"
2949
2950 test_27K() {
2951         [[ $MDS1_VERSION -le $(version_code 2.12.49) ]] &&
2952                 skip "Need MDS version newer than 2.12.49"
2953
2954         test_mkdir $DIR/$tdir
2955         local uuid1=$(cat /proc/sys/kernel/random/uuid)
2956         local uuid2=$(cat /proc/sys/kernel/random/uuid)
2957
2958         # create foreign dir (raw way)
2959         ! $LFS setdirstripe --flags 0xda08 $DIR/$tdir/$tdir ||
2960                 error "creating $tdir w/ hex flags w/o --foreign should fail"
2961
2962         ! $LFS setdirstripe --foreign --flags foo \
2963                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tdir ||
2964                         error "creating $tdir with '--flags foo' should fail"
2965
2966         ! $LFS setdirstripe --foreign --flags 0xffffffff \
2967                 --xattr ${uuid1}@${uuid2} $DIR/$tdir/$tdir ||
2968                         error "creating $tdir w/ 0xffffffff flags should fail"
2969
2970         create_foreign_dir -d $DIR/$tdir/$tdir -x "${uuid1}@${uuid2}" -t 1 ||
2971                 error "create_foreign_dir FAILED"
2972
2973         # verify foreign dir (raw way)
2974         parse_foreign_dir -d $DIR/$tdir/$tdir |
2975                 grep "lmv_foreign_magic:.*0xcd50cd0" ||
2976                 error "$DIR/$tdir/$tfile: invalid LMV EA magic"
2977         parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_xattr_size:.*89$" ||
2978                 error "$DIR/$tdir/$tdir: invalid LMV EA size"
2979         parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_foreign_type: 1$" ||
2980                 error "$DIR/$tdir/$tdir: invalid LMV EA type"
2981         parse_foreign_dir -d $DIR/$tdir/$tdir |
2982                 grep "lmv_foreign_flags: 55813$" ||
2983                 error "$DIR/$tdir/$tdir: invalid LMV EA flags"
2984         local lmv=$(parse_foreign_dir -d $DIR/$tdir/$tdir |
2985                 grep "lmv_foreign_value: 0x" |
2986                 sed 's/lmv_foreign_value: 0x//')
2987         local lmv2=$(echo -n "${uuid1}@${uuid2}" | od -A n -t x1 -w160 |
2988                 sed 's/ //g')
2989         [[ $lmv == $lmv2 ]] || error "$DIR/$tdir/$tdir: invalid LMV EA value"
2990
2991         # create foreign dir (lfs + API)
2992         $LFS mkdir --foreign=none --xattr="${uuid1}@${uuid2}" --flags=0xda05 \
2993                 $DIR/$tdir/${tdir}2 ||
2994                 error "$DIR/$tdir/${tdir}2: create failed"
2995
2996         $LFS getdirstripe -v $DIR/$tdir/${tdir}2
2997
2998         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
2999                 grep "lfm_magic:.*0x0CD50CD0" ||
3000                 error "$DIR/$tdir/${tdir}2: invalid LMV EA magic"
3001         # lfm_length is LMV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
3002         # - sizeof(lfm_type) - sizeof(lfm_flags)
3003         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_length:.*73" ||
3004                 error "$DIR/$tdir/${tdir}2: invalid LMV EA size"
3005         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_type:.*none" ||
3006                 error "$DIR/$tdir/${tdir}2: invalid LMV EA type"
3007         $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
3008                 grep "lfm_flags:.*0x0000DA05" ||
3009                 error "$DIR/$tdir/${tdir}2: invalid LMV EA flags"
3010         $LFS getdirstripe $DIR/$tdir/${tdir}2 |
3011                 grep "lfm_value.*${uuid1}@${uuid2}" ||
3012                 error "$DIR/$tdir/${tdir}2: invalid LMV EA value"
3013
3014         # file create in dir should fail
3015         touch $DIR/$tdir/$tdir/$tfile && error "$DIR/$tdir: file create should fail"
3016         touch $DIR/$tdir/${tdir}2/$tfile &&
3017                 error "$DIR/${tdir}2: file create should fail"
3018
3019         # chmod should work
3020         chmod 777 $DIR/$tdir/$tdir ||
3021                 error "$DIR/$tdir: chmod failed"
3022         chmod 777 $DIR/$tdir/${tdir}2 ||
3023                 error "$DIR/${tdir}2: chmod failed"
3024
3025         # chown should work
3026         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/$tdir ||
3027                 error "$DIR/$tdir: chown failed"
3028         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}2 ||
3029                 error "$DIR/${tdir}2: chown failed"
3030
3031         # rename should work
3032         mv $DIR/$tdir/$tdir $DIR/$tdir/${tdir}.new ||
3033                 error "$DIR/$tdir/$tdir: rename of foreign dir has failed"
3034         mv $DIR/$tdir/${tdir}2 $DIR/$tdir/${tdir}2.new ||
3035                 error "$DIR/$tdir/${tdir}2: rename of foreign dir has failed"
3036
3037         #remove foreign dir
3038         rmdir $DIR/$tdir/${tdir}.new ||
3039                 error "$DIR/$tdir/${tdir}.new: remove of foreign dir has failed"
3040         rmdir $DIR/$tdir/${tdir}2.new ||
3041                 error "$DIR/$tdir/${tdir}2.new: remove of foreign dir has failed"
3042 }
3043 run_test 27K "basic ops on dir with foreign LMV"
3044
3045 test_27L() {
3046         remote_mds_nodsh && skip "remote MDS with nodsh"
3047
3048         local POOL=${POOL:-$TESTNAME}
3049
3050         pool_add $POOL || error "pool_add failed"
3051
3052         lfs pool_list $MOUNT | grep -Fx "${FSNAME}.${POOL}" ||
3053                  error "pool_list does not contain ${FSNAME}.${POOL}:" \
3054                        "$(lfs pool_list $MOUNT | grep -F "${POOL}")"
3055 }
3056 run_test 27L "lfs pool_list gives correct pool name"
3057
3058 test_27M() {
3059         (( $MDS1_VERSION >= $(version_code 2.12.57) )) ||
3060                 skip "Need MDS version >= than 2.12.57"
3061         remote_mds_nodsh && skip "remote MDS with nodsh"
3062         (( $OSTCOUNT > 1 )) || skip "need > 1 OST"
3063
3064         # Set default striping on directory
3065         local setcount=4
3066         local stripe_opt
3067         local mdts=$(comma_list $(mdts_nodes))
3068
3069         # if we run against a 2.12 server which lacks overstring support
3070         # then the connect_flag will not report overstriping, even if client
3071         # is 2.14+
3072         if [[ $($LCTL get_param mdc.*.connect_flags) =~ overstriping ]]; then
3073                 stripe_opt="-C $setcount"
3074         elif (( $OSTCOUNT >= $setcount )); then
3075                 stripe_opt="-c $setcount"
3076         else
3077                 skip "server does not support overstriping"
3078         fi
3079
3080         test_mkdir $DIR/$tdir
3081
3082         # Validate existing append_* params and ensure restore
3083         local pool=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_pool)
3084         [[ "$pool" == "" ]] || error "expected append_pool == '', got '$pool'"
3085         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_pool=none"
3086
3087         local orig_count=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_stripe_count)
3088         ((orig_count == 1)) || error "expected append_stripe_count == 1, got $orig_count"
3089         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=1"
3090
3091         $LFS setstripe $stripe_opt $DIR/$tdir
3092
3093         echo 1 > $DIR/$tdir/${tfile}.1
3094         local count=$($LFS getstripe -c $DIR/$tdir/${tfile}.1)
3095         (( $count == $setcount )) ||
3096                 error "(1) stripe count $count, should be $setcount"
3097
3098         local appendcount=$orig_count
3099         echo 1 >> $DIR/$tdir/${tfile}.2_append
3100         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.2_append)
3101         (( $count == $appendcount )) ||
3102                 error "(2)stripe count $count, should be $appendcount for append"
3103
3104         # Disable O_APPEND striping, verify it works
3105         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=0
3106
3107         # Should now get the default striping, which is 4
3108         setcount=4
3109         echo 1 >> $DIR/$tdir/${tfile}.3_append
3110         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.3_append)
3111         (( $count == $setcount )) ||
3112                 error "(3) stripe count $count, should be $setcount"
3113
3114         # Try changing the stripe count for append files
3115         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=2
3116
3117         # Append striping is now 2 (directory default is still 4)
3118         appendcount=2
3119         echo 1 >> $DIR/$tdir/${tfile}.4_append
3120         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.4_append)
3121         (( $count == $appendcount )) ||
3122                 error "(4) stripe count $count, should be $appendcount for append"
3123
3124         # Test append stripe count of -1
3125         # Exercise LU-16872 patch with specific striping, only if MDS has fix
3126         (( $MDS1_VERSION > $(version_code 2.15.56.46) )) &&
3127                 $LFS setstripe -o 0,$((OSTCOUNT - 1)) $DIR/$tdir &&
3128                 touch $DIR/$tdir/$tfile.specific.{1..128}
3129         stack_trap "rm -f $DIR/$tdir/$tfile.*"
3130
3131         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=-1
3132         appendcount=$OSTCOUNT
3133         echo 1 >> $DIR/$tdir/${tfile}.5
3134         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.5)
3135         (( $count == $appendcount )) ||
3136                 error "(5) stripe count $count, should be $appendcount for append"
3137
3138         # Set append striping back to default of 1
3139         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=1
3140
3141         # Try a new default striping, PFL + DOM
3142         $LFS setstripe -L mdt -E 1M -E -1 -c 2 $DIR/$tdir
3143
3144         # Create normal DOM file, DOM returns stripe count == 0
3145         setcount=0
3146         touch $DIR/$tdir/${tfile}.6
3147         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.6)
3148         (( $count == $setcount )) ||
3149                 error "(6) stripe count $count, should be $setcount"
3150
3151         # Show
3152         appendcount=1
3153         echo 1 >> $DIR/$tdir/${tfile}.7_append
3154         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.7_append)
3155         (( $count == $appendcount )) ||
3156                 error "(7) stripe count $count, should be $appendcount for append"
3157
3158         # Clean up DOM layout
3159         $LFS setstripe -d $DIR/$tdir
3160
3161         save_layout_restore_at_exit $MOUNT
3162         # Now test that append striping works when layout is from root
3163         $LFS setstripe -c 2 $MOUNT
3164         # Make a special directory for this
3165         mkdir $DIR/${tdir}/${tdir}.2
3166
3167         # Verify for normal file
3168         setcount=2
3169         echo 1 > $DIR/${tdir}/${tdir}.2/${tfile}.8
3170         count=$($LFS getstripe -c $DIR/$tdir/${tdir}.2/${tfile}.8)
3171         (( $count == $setcount )) ||
3172                 error "(8) stripe count $count, should be $setcount"
3173
3174         appendcount=1
3175         echo 1 >> $DIR/${tdir}/${tdir}.2/${tfile}.9_append
3176         count=$($LFS getstripe -c $DIR/${tdir}/${tdir}.2/${tfile}.9_append)
3177         (( $count == $appendcount )) ||
3178                 error "(9) stripe count $count, should be $appendcount for append"
3179
3180         # Now test O_APPEND striping with pools
3181         pool_add $TESTNAME || error "pool creation failed"
3182         pool_add_targets $TESTNAME 0 1 || error "Pool add targets failed"
3183         do_nodes $mdts $LCTL set_param mdd.*.append_pool="$TESTNAME"
3184
3185         echo 1 >> $DIR/$tdir/${tfile}.10_append
3186
3187         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.10_append)
3188         [[ "$pool" == "$TESTNAME" ]] || error "(10) incorrect pool: $pool"
3189
3190         # Check that count is still correct
3191         appendcount=1
3192         echo 1 >> $DIR/$tdir/${tfile}.11_append
3193         count=$($LFS getstripe -c $DIR/$tdir/${tfile}.11_append)
3194         (( $count == $appendcount )) ||
3195                 error "(11) stripe count $count, should be $appendcount for append"
3196
3197         # Disable O_APPEND stripe count, verify pool works separately
3198         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=0
3199
3200         echo 1 >> $DIR/$tdir/${tfile}.12_append
3201
3202         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.12_append)
3203         [[ "$pool" == "$TESTNAME" ]] || error "(12) incorrect pool: $pool"
3204
3205         # Remove pool setting, verify it's not applied
3206         do_nodes $mdts $LCTL set_param mdd.*.append_pool='none'
3207
3208         echo 1 >> $DIR/$tdir/${tfile}.13_append
3209
3210         pool=$($LFS getstripe -p $DIR/$tdir/${tfile}.13_append)
3211         [[ -z "$pool" ]] || error "(13) pool found: $pool"
3212 }
3213 run_test 27M "test O_APPEND striping"
3214
3215 test_27N() {
3216         combined_mgs_mds && skip "needs separate MGS/MDT"
3217
3218         pool_add $TESTNAME || error "pool_add failed"
3219         do_facet mgs "$LCTL pool_list $FSNAME" |
3220                 grep -Fx "${FSNAME}.${TESTNAME}" ||
3221                 error "lctl pool_list on MGS failed"
3222 }
3223 run_test 27N "lctl pool_list on separate MGS gives correct pool name"
3224
3225 clean_foreign_symlink() {
3226         trap 0
3227         lctl set_param llite/$FSNAME-*/foreign_symlink_enable=0
3228         for i in $DIR/$tdir/* ; do
3229                 $LFS unlink_foreign $i || true
3230         done
3231 }
3232
3233 test_27O() {
3234         [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.51) ]] &&
3235                 skip "Need MDS version newer than 2.12.51"
3236
3237         test_mkdir $DIR/$tdir
3238         local uuid1=$(cat /proc/sys/kernel/random/uuid)
3239         local uuid2=$(cat /proc/sys/kernel/random/uuid)
3240
3241         trap clean_foreign_symlink EXIT
3242
3243         # enable foreign_symlink behaviour
3244         $LCTL set_param llite/$FSNAME-*/foreign_symlink_enable=1
3245
3246         # foreign symlink LOV format is a partial path by default
3247
3248         # create foreign file (lfs + API)
3249         $LFS setstripe --foreign=symlink --flags 0xda05 \
3250                 -x "${uuid1}/${uuid2}" --mode 0600 $DIR/$tdir/${tfile} ||
3251                 error "$DIR/$tdir/${tfile}: create failed"
3252
3253         $LFS getstripe -v $DIR/$tdir/${tfile} |
3254                 grep "lfm_magic:.*0x0BD70BD0" ||
3255                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign magic"
3256         $LFS getstripe -v $DIR/$tdir/${tfile} | grep "lfm_type:.*symlink" ||
3257                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign type"
3258         $LFS getstripe -v $DIR/$tdir/${tfile} |
3259                 grep "lfm_flags:.*0x0000DA05" ||
3260                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign flags"
3261         $LFS getstripe $DIR/$tdir/${tfile} |
3262                 grep "lfm_value:.*${uuid1}/${uuid2}" ||
3263                 error "$DIR/$tdir/${tfile}: invalid LOV EA foreign value"
3264
3265         # modify striping should fail
3266         $LFS setstripe -c 2 $DIR/$tdir/$tfile &&
3267                 error "$DIR/$tdir/$tfile: setstripe should fail"
3268
3269         # R/W should fail ("/{foreign_symlink_prefix}/${uuid1}/" missing)
3270         cat $DIR/$tdir/$tfile && error "$DIR/$tdir/$tfile: read should fail"
3271         cat /etc/passwd > $DIR/$tdir/$tfile &&
3272                 error "$DIR/$tdir/$tfile: write should fail"
3273
3274         # rename should succeed
3275         mv $DIR/$tdir/$tfile $DIR/$tdir/${tfile}.new ||
3276                 error "$DIR/$tdir/$tfile: rename has failed"
3277
3278         #remove foreign_symlink file should fail
3279         rm $DIR/$tdir/${tfile}.new &&
3280                 error "$DIR/$tdir/${tfile}.new: remove of foreign_symlink file should fail"
3281
3282         #test fake symlink
3283         mkdir /tmp/${uuid1} ||
3284                 error "/tmp/${uuid1}: mkdir has failed"
3285         echo FOOFOO > /tmp/${uuid1}/${uuid2} ||
3286                 error "/tmp/${uuid1}/${uuid2}: echo has failed"
3287         $LCTL set_param llite/$FSNAME-*/foreign_symlink_prefix=/tmp/
3288         $CHECKSTAT -t link -l /tmp/${uuid1}/${uuid2} $DIR/$tdir/${tfile}.new ||
3289                 error "$DIR/$tdir/${tfile}.new: not seen as a symlink"
3290         #read should succeed now
3291         cat $DIR/$tdir/${tfile}.new | grep FOOFOO ||
3292                 error "$DIR/$tdir/${tfile}.new: symlink resolution has failed"
3293         #write should succeed now
3294         cat /etc/passwd > $DIR/$tdir/${tfile}.new ||
3295                 error "$DIR/$tdir/${tfile}.new: write should succeed"
3296         diff /etc/passwd $DIR/$tdir/${tfile}.new ||
3297                 error "$DIR/$tdir/${tfile}.new: diff has failed"
3298         diff /etc/passwd /tmp/${uuid1}/${uuid2} ||
3299                 error "/tmp/${uuid1}/${uuid2}: diff has failed"
3300
3301         #check that getstripe still works
3302         $LFS getstripe $DIR/$tdir/${tfile}.new ||
3303                 error "$DIR/$tdir/${tfile}.new: getstripe should still work with foreign_symlink enabled"
3304
3305         # chmod should still succeed
3306         chmod 644 $DIR/$tdir/${tfile}.new ||
3307                 error "$DIR/$tdir/${tfile}.new: chmod has failed"
3308
3309         # chown should still succeed
3310         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tfile}.new ||
3311                 error "$DIR/$tdir/${tfile}.new: chown has failed"
3312
3313         # rename should still succeed
3314         mv $DIR/$tdir/${tfile}.new $DIR/$tdir/${tfile} ||
3315                 error "$DIR/$tdir/${tfile}.new: rename has failed"
3316
3317         #remove foreign_symlink file should still fail
3318         rm $DIR/$tdir/${tfile} &&
3319                 error "$DIR/$tdir/${tfile}: remove of foreign_symlink file should fail"
3320
3321         #use special ioctl() to unlink foreign_symlink file
3322         $LFS unlink_foreign $DIR/$tdir/${tfile} ||
3323                 error "$DIR/$tdir/$tfile: unlink/ioctl failed"
3324
3325 }
3326 run_test 27O "basic ops on foreign file of symlink type"
3327
3328 test_27P() {
3329         [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.49) ]] &&
3330                 skip "Need MDS version newer than 2.12.49"
3331
3332         test_mkdir $DIR/$tdir
3333         local uuid1=$(cat /proc/sys/kernel/random/uuid)
3334         local uuid2=$(cat /proc/sys/kernel/random/uuid)
3335
3336         trap clean_foreign_symlink EXIT
3337
3338         # enable foreign_symlink behaviour
3339         $LCTL set_param llite/$FSNAME-*/foreign_symlink_enable=1
3340
3341         # foreign symlink LMV format is a partial path by default
3342
3343         # create foreign dir (lfs + API)
3344         $LFS mkdir --foreign=symlink --xattr="${uuid1}/${uuid2}" \
3345                 --flags=0xda05 --mode 0750 $DIR/$tdir/${tdir} ||
3346                 error "$DIR/$tdir/${tdir}: create failed"
3347
3348         $LFS getdirstripe -v $DIR/$tdir/${tdir}
3349
3350         $LFS getdirstripe -v $DIR/$tdir/${tdir} |
3351                 grep "lfm_magic:.*0x0CD50CD0" ||
3352                 error "$DIR/$tdir/${tdir}: invalid LMV EA magic"
3353         $LFS getdirstripe -v $DIR/$tdir/${tdir} | grep "lfm_type:.*symlink" ||
3354                 error "$DIR/$tdir/${tdir}: invalid LMV EA type"
3355         $LFS getdirstripe -v $DIR/$tdir/${tdir} |
3356                 grep "lfm_flags:.*0x0000DA05" ||
3357                 error "$DIR/$tdir/${tdir}: invalid LMV EA flags"
3358         $LFS getdirstripe $DIR/$tdir/${tdir} |
3359                 grep "lfm_value.*${uuid1}/${uuid2}" ||
3360                 error "$DIR/$tdir/${tdir}: invalid LMV EA value"
3361
3362         # file create in dir should fail
3363         # ("/{foreign_symlink_prefix}/${uuid1}/${uuid2}/" missing)
3364         touch $DIR/$tdir/$tdir/$tfile && error "$DIR/$tdir: file create should fail"
3365
3366         # rename should succeed
3367         mv $DIR/$tdir/$tdir $DIR/$tdir/${tdir}.new ||
3368                 error "$DIR/$tdir/$tdir: rename of foreign_symlink dir has failed"
3369
3370         #remove foreign_symlink dir should fail
3371         rmdir $DIR/$tdir/${tdir}.new &&
3372                 error "$DIR/$tdir/${tdir}.new: remove of foreign_symlink dir should fail"
3373
3374         #test fake symlink
3375         mkdir -p /tmp/${uuid1}/${uuid2} ||
3376                 error "/tmp/${uuid1}/${uuid2}: mkdir has failed"
3377         echo FOOFOO > /tmp/${uuid1}/${uuid2}/foo ||
3378                 error "/tmp/${uuid1}/${uuid2}/foo: echo has failed"
3379         $LCTL set_param llite/$FSNAME-*/foreign_symlink_prefix=/tmp/
3380         $CHECKSTAT -t link -l /tmp/${uuid1}/${uuid2} $DIR/$tdir/${tdir}.new ||
3381                 error "$DIR/$tdir/${tdir}.new: not seen as a symlink"
3382         cat $DIR/$tdir/${tdir}.new/foo | grep FOOFOO ||
3383                 error "$DIR/$tdir/${tdir}.new: symlink resolution has failed"
3384
3385         #check that getstripe fails now that foreign_symlink enabled
3386         $LFS getdirstripe $DIR/$tdir/${tdir}.new ||
3387                 error "$DIR/$tdir/${tdir}.new: getdirstripe should still work with foreign_symlink enabled"
3388
3389         # file create in dir should work now
3390         cp /etc/passwd $DIR/$tdir/${tdir}.new/$tfile ||
3391                 error "$DIR/$tdir/${tdir}.new/$tfile: file create should fail"
3392         diff /etc/passwd $DIR/$tdir/${tdir}.new/$tfile ||
3393                 error "$DIR/$tdir/${tdir}.new/$tfile: diff has failed"
3394         diff /etc/passwd /tmp/${uuid1}/${uuid2}/$tfile ||
3395                 error "/tmp/${uuid1}/${uuid2}/$tfile: diff has failed"
3396
3397         # chmod should still succeed
3398         chmod 755 $DIR/$tdir/${tdir}.new ||
3399                 error "$DIR/$tdir/${tdir}.new: chmod has failed"
3400
3401         # chown should still succeed
3402         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}.new ||
3403                 error "$DIR/$tdir/${tdir}.new: chown has failed"
3404
3405         # rename should still succeed
3406         mv $DIR/$tdir/${tdir}.new $DIR/$tdir/${tdir} ||
3407                 error "$DIR/$tdir/${tdir}.new: rename of foreign_symlink dir has failed"
3408
3409         #remove foreign_symlink dir should still fail
3410         rmdir $DIR/$tdir/${tdir} &&
3411                 error "$DIR/$tdir/${tdir}: remove of foreign_symlink dir should fail"
3412
3413         #use special ioctl() to unlink foreign_symlink file
3414         $LFS unlink_foreign $DIR/$tdir/${tdir} ||
3415                 error "$DIR/$tdir/$tdir: unlink/ioctl failed"
3416
3417         #created file should still exist
3418         [[ -f /tmp/${uuid1}/${uuid2}/$tfile ]] ||
3419                 error "/tmp/${uuid1}/${uuid2}/$tfile has been removed"
3420         diff /etc/passwd /tmp/${uuid1}/${uuid2}/$tfile ||
3421                 error "/tmp/${uuid1}/${uuid2}/$tfile: diff has failed"
3422 }
3423 run_test 27P "basic ops on foreign dir of foreign_symlink type"
3424
3425 test_27Q() {
3426         rm -f $TMP/$tfile $TMP/$tfile.loop $TMP/$tfile.none $TMP/$tfile.broken
3427         stack_trap "rm -f $TMP/$tfile*"
3428
3429         test_mkdir $DIR/$tdir-1
3430         test_mkdir $DIR/$tdir-2
3431
3432         echo 'It is what it is' > $DIR/$tdir-1/$tfile
3433         lov_getstripe_old $DIR/$tdir-1/$tfile || error "$DIR/$tdir-1/$tfile: rc = $?"
3434
3435         ln -s $DIR/$tdir-1/$tfile $DIR/$tdir-2/$tfile
3436         lov_getstripe_old $DIR/$tdir-2/$tfile || error "$DIR/$tdir-2/$tfile: rc = $?"
3437
3438         ln -s $DIR/$tdir-1/$tfile $TMP/$tfile
3439         lov_getstripe_old $TMP/$tfile || error "$TMP/$tfile: rc = $?"
3440
3441         # Create some bad symlinks and ensure that we don't loop
3442         # forever or something. These should return ELOOP (40) and
3443         # ENOENT (2) but I don't want to test for that because there's
3444         # always some weirdo architecture that needs to ruin
3445         # everything by defining these error numbers differently.
3446
3447         ln -s $TMP/$tfile.loop $TMP/$tfile.loop
3448         lov_getstripe_old $TMP/$tfile.loop && error "$TMP/$tfile.loop: rc = $?"
3449
3450         ln -s $TMP/$tfile.none $TMP/$tfile.broken
3451         lov_getstripe_old $TMP/$tfile.broken && error "$TMP/$tfile.broken: rc = $?"
3452
3453         return 0
3454 }
3455 run_test 27Q "llapi_file_get_stripe() works on symlinks"
3456
3457 test_27R() {
3458         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
3459                 skip "need MDS 2.14.55 or later"
3460         (( $OSTCOUNT >= 2 )) || skip_env "needs at least 2 OSTs"
3461
3462         local testdir="$DIR/$tdir"
3463         test_mkdir -p $testdir
3464         stack_trap "rm -rf $testdir"
3465         $LFS setstripe -c -1 $testdir || error "setstripe failed"
3466
3467         local f1="$testdir/f1"
3468         touch $f1 || error "failed to touch $f1"
3469         local count=$($LFS getstripe -c $f1)
3470         (( $count == $OSTCOUNT )) || error "wrong stripe count"
3471
3472         do_facet $SINGLEMDS $LCTL set_param lod.*.max_stripecount=-1
3473         (( $? == 34 )) || error "setting max_stripecount to -1 should fail and return ERANGE"
3474
3475         local maxcount=$(($OSTCOUNT - 1))
3476         local mdts=$(comma_list $(mdts_nodes))
3477         do_nodes $mdts $LCTL set_param lod.*.max_stripecount=$maxcount
3478         stack_trap "do_nodes $mdts $LCTL set_param lod.*.max_stripecount=0"
3479
3480         local f2="$testdir/f2"
3481         touch $f2 || error "failed to touch $f2"
3482         local count=$($LFS getstripe -c $f2)
3483         (( $count == $maxcount )) || error "wrong stripe count"
3484 }
3485 run_test 27R "test max_stripecount limitation when stripe count is set to -1"
3486
3487 test_27T() {
3488         [ $(facet_host client) == $(facet_host ost1) ] &&
3489                 skip "need ost1 and client on different nodes"
3490
3491 #define OBD_FAIL_OSC_NO_GRANT            0x411
3492         $LCTL set_param fail_loc=0x20000411 fail_val=1
3493 #define OBD_FAIL_OST_ENOSPC              0x215
3494         do_facet ost1 "$LCTL set_param fail_loc=0x80000215"
3495         $LFS setstripe -i 0 -c 1 $DIR/$tfile
3496         $MULTIOP $DIR/$tfile oO_WRONLY:P$((4 * 1024 * 1024 + 10 * 4096))c ||
3497                 error "multiop failed"
3498 }
3499 run_test 27T "no eio on close on partial write due to enosp"
3500
3501 test_27U() {
3502         local dir=$DIR/$tdir
3503         local file=$dir/$tfile
3504         local append_pool=${TESTNAME}-append
3505         local normal_pool=${TESTNAME}-normal
3506         local pool
3507         local stripe_count
3508         local stripe_count2
3509         local mdts=$(comma_list $(mdts_nodes))
3510
3511         (( $MDS1_VERSION >= $(version_code 2.15.51) )) ||
3512                 skip "Need MDS version at least 2.15.51 for append pool feature"
3513
3514         # Validate existing append_* params and ensure restore
3515         pool=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_pool)
3516         [[ "$pool" == "" ]] || error "expected append_pool == '', got '$pool'"
3517         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_pool=none"
3518
3519         stripe_count=$(do_facet mds1 $LCTL get_param -n mdd.$FSNAME-MDT0000.append_stripe_count)
3520         ((stripe_count == 1)) || error "expected append_stripe_count != 0, got $stripe_count"
3521         stack_trap "do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=$stripe_count"
3522
3523         pool_add $append_pool || error "pool creation failed"
3524         pool_add_targets $append_pool 0 1 || error "Pool add targets failed"
3525
3526         pool_add $normal_pool || error "pool creation failed"
3527         pool_add_targets $normal_pool 0 1 || error "Pool add targets failed"
3528
3529         test_mkdir $dir
3530         $LFS setstripe -E 1M -c 1 -p $normal_pool -E 2M -c 2 -p $normal_pool -E eof -c -1 $dir
3531
3532         echo XXX >> $file.1
3533         $LFS getstripe $file.1
3534
3535         pool=$($LFS getstripe -p $file.1)
3536         [[ "$pool" == "$normal_pool" ]] || error "got pool '$pool', expected '$normal_pool'"
3537
3538         stripe_count2=$($LFS getstripe -c $file.1)
3539         ((stripe_count2 == stripe_count)) ||
3540                 error "got stripe_count '$stripe_count2', expected '$stripe_count'"
3541
3542         do_nodes $mdts $LCTL set_param mdd.*.append_pool=$append_pool
3543
3544         echo XXX >> $file.2
3545         $LFS getstripe $file.2
3546
3547         pool=$($LFS getstripe -p $file.2)
3548         [[ "$pool" == "$append_pool" ]] || error "got pool '$pool', expected '$append_pool'"
3549
3550         do_nodes $mdts $LCTL set_param mdd.*.append_stripe_count=2
3551
3552         echo XXX >> $file.3
3553         $LFS getstripe $file.3
3554
3555         stripe_count2=$($LFS getstripe -c $file.3)
3556         ((stripe_count2 == 2)) || error "got stripe_count '$stripe_count2', expected 2"
3557 }
3558 run_test 27U "append pool and stripe count work with composite default layout"
3559
3560 test_27V() {
3561         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3562         (( $OSTCOUNT >= 4 )) || skip_env "needs >= 4 OSTs"
3563
3564         local dir=$DIR/$tdir
3565         local osp_param=osp.$FSNAME-OST0000-osc-MDT0000.max_create_count
3566         local lod_param=lod.$FSNAME-MDT0000-mdtlov.qos_threshold_rr
3567         local saved_max=$(do_facet mds1 $LCTL get_param -n $osp_param)
3568         local saved_qos=$(do_facet mds1 $LCTL get_param -n $lod_param)
3569         local pid
3570
3571         stack_trap "do_facet mds1 $LCTL set_param $osp_param=$saved_max"
3572
3573         do_facet mds1 $LCTL set_param $lod_param=0
3574         stack_trap "do_facet mds1 $LCTL set_param $lod_param=$saved_qos"
3575
3576         $LFS setdirstripe --mdt-count=1 --mdt-index=0 $dir
3577         stack_trap "rm -rf $dir"
3578
3579         # exercise race in LU-16981 with deactivating OST while creating a file
3580         (
3581                 while true; do
3582                         do_facet mds1 $LCTL set_param $osp_param=0 > /dev/null
3583                         sleep 0.1
3584                         do_facet mds1 \
3585                                 $LCTL set_param $osp_param=$saved_max > /dev/null
3586                 done
3587         ) &
3588
3589         pid=$!
3590         stack_trap "kill -9 $pid"
3591
3592         # errors here are OK so ignore them (just don't want to crash)
3593         $LFS setstripe -c -1 $dir/f.{1..200} 2> /dev/null
3594
3595         return 0
3596 }
3597 run_test 27V "creating widely striped file races with deactivating OST"
3598
3599 # createtest also checks that device nodes are created and
3600 # then visible correctly (#2091)
3601 test_28() { # bug 2091
3602         test_mkdir $DIR/d28
3603         $CREATETEST $DIR/d28/ct || error "createtest failed"
3604 }
3605 run_test 28 "create/mknod/mkdir with bad file types ============"
3606
3607 test_29() {
3608         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3609
3610         [ $MDS1_VERSION -ge $(version_code 2.14.51) ] && {
3611                 disable_opencache
3612                 stack_trap "restore_opencache"
3613         }
3614
3615         sync; sleep 1; sync # flush out any dirty pages from previous tests
3616         cancel_lru_locks
3617         test_mkdir $DIR/d29
3618         touch $DIR/d29/foo
3619         log 'first d29'
3620         ls -l $DIR/d29
3621
3622         local locks_orig=$(total_used_locks mdc)
3623         (( $locks_orig != 0 )) || error "No mdc lock count"
3624
3625         local locks_unused_orig=$(total_unused_locks mdc)
3626
3627         log 'second d29'
3628         ls -l $DIR/d29
3629         log 'done'
3630
3631         local locks_current=$(total_used_locks mdc)
3632
3633         local locks_unused_current=$(total_unused_locks mdc)
3634
3635         if (( $locks_current > $locks_orig )); then
3636                 $LCTL set_param -n ldlm.dump_namespaces ""
3637                 error "CURRENT: $locks_current > $locks_orig"
3638         fi
3639         if (( $locks_unused_current > $locks_unused_orig )); then
3640                 error "UNUSED: $locks_unused_current > $locks_unused_orig"
3641         fi
3642 }
3643 run_test 29 "IT_GETATTR regression  ============================"
3644
3645 test_30a() { # was test_30
3646         cp $(which ls) $DIR || cp /bin/ls $DIR
3647         $DIR/ls / || error "Can't execute binary from lustre"
3648         rm $DIR/ls
3649 }
3650 run_test 30a "execute binary from Lustre (execve) =============="
3651
3652 test_30b() {
3653         cp `which ls` $DIR || cp /bin/ls $DIR
3654         chmod go+rx $DIR/ls
3655         $RUNAS $DIR/ls / || error "Can't execute binary from lustre as non-root"
3656         rm $DIR/ls
3657 }
3658 run_test 30b "execute binary from Lustre as non-root ==========="
3659
3660 test_30c() { # b=22376
3661         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3662
3663         cp $(which ls) $DIR || cp /bin/ls $DIR
3664         chmod a-rw $DIR/ls
3665         cancel_lru_locks mdc
3666         cancel_lru_locks osc
3667         $RUNAS $DIR/ls / || error "Can't execute binary from lustre"
3668         rm -f $DIR/ls
3669 }
3670 run_test 30c "execute binary from Lustre without read perms ===="
3671
3672 test_30d() {
3673         cp $(which dd) $DIR || error "failed to copy dd to $DIR/dd"
3674
3675         for i in {1..10}; do
3676                 $DIR/dd bs=1M count=128 if=/dev/zero of=$DIR/$tfile &
3677                 local PID=$!
3678                 sleep 1
3679                 $LCTL set_param ldlm.namespaces.*MDT*.lru_size=clear
3680                 wait $PID || error "executing dd from Lustre failed"
3681                 rm -f $DIR/$tfile
3682         done
3683
3684         rm -f $DIR/dd
3685 }
3686 run_test 30d "execute binary from Lustre while clear locks"
3687
3688 test_31a() {
3689         $OPENUNLINK $DIR/f31 $DIR/f31 || error "openunlink failed"
3690         $CHECKSTAT -a $DIR/f31 || error "$DIR/f31 exists"
3691 }
3692 run_test 31a "open-unlink file =================================="
3693
3694 test_31b() {
3695         touch $DIR/f31 || error "touch $DIR/f31 failed"
3696         ln $DIR/f31 $DIR/f31b || error "ln failed"
3697         $MULTIOP $DIR/f31b Ouc || error "multiop failed"
3698         $CHECKSTAT -t file $DIR/f31 || error "$DIR/f31 not file type"
3699 }
3700 run_test 31b "unlink file with multiple links while open ======="
3701
3702 test_31c() {
3703         touch $DIR/f31 || error "touch $DIR/f31 failed"
3704         ln $DIR/f31 $DIR/f31c || error "ln failed"
3705         multiop_bg_pause $DIR/f31 O_uc ||
3706                 error "multiop_bg_pause for $DIR/f31 failed"
3707         MULTIPID=$!
3708         $MULTIOP $DIR/f31c Ouc
3709         kill -USR1 $MULTIPID
3710         wait $MULTIPID
3711 }
3712 run_test 31c "open-unlink file with multiple links ============="
3713
3714 test_31d() {
3715         opendirunlink $DIR/d31d $DIR/d31d || error "opendirunlink failed"
3716         $CHECKSTAT -a $DIR/d31d || error "$DIR/d31d exists"
3717 }
3718 run_test 31d "remove of open directory ========================="
3719
3720 test_31e() { # bug 2904
3721         openfilleddirunlink $DIR/d31e || error "openfilleddirunlink failed"
3722 }
3723 run_test 31e "remove of open non-empty directory ==============="
3724
3725 test_31f() { # bug 4554
3726         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3727
3728         set -vx
3729         test_mkdir $DIR/d31f
3730         $LFS setstripe -S 1048576 -c 1 $DIR/d31f
3731         cp /etc/hosts $DIR/d31f
3732         ls -l $DIR/d31f
3733         $LFS getstripe $DIR/d31f/hosts
3734         multiop_bg_pause $DIR/d31f D_c || return 1
3735         MULTIPID=$!
3736
3737         rm -rv $DIR/d31f || error "first of $DIR/d31f"
3738         test_mkdir $DIR/d31f
3739         $LFS setstripe -S 1048576 -c 1 $DIR/d31f
3740         cp /etc/hosts $DIR/d31f
3741         ls -l $DIR/d31f
3742         $LFS getstripe $DIR/d31f/hosts
3743         multiop_bg_pause $DIR/d31f D_c || return 1
3744         MULTIPID2=$!
3745
3746         kill -USR1 $MULTIPID || error "first opendir $MULTIPID not running"
3747         wait $MULTIPID || error "first opendir $MULTIPID failed"
3748
3749         sleep 6
3750
3751         kill -USR1 $MULTIPID2 || error "second opendir $MULTIPID not running"
3752         wait $MULTIPID2 || error "second opendir $MULTIPID2 failed"
3753         set +vx
3754 }
3755 run_test 31f "remove of open directory with open-unlink file ==="
3756
3757 test_31g() {
3758         echo "-- cross directory link --"
3759         test_mkdir -c1 $DIR/${tdir}ga
3760         test_mkdir -c1 $DIR/${tdir}gb
3761         touch $DIR/${tdir}ga/f
3762         ln $DIR/${tdir}ga/f $DIR/${tdir}gb/g
3763         $CHECKSTAT -t file $DIR/${tdir}ga/f || error "source"
3764         [ `stat -c%h $DIR/${tdir}ga/f` == '2' ] || error "source nlink"
3765         $CHECKSTAT -t file $DIR/${tdir}gb/g || error "target"
3766         [ `stat -c%h $DIR/${tdir}gb/g` == '2' ] || error "target nlink"
3767 }
3768 run_test 31g "cross directory link==============="
3769
3770 test_31h() {
3771         echo "-- cross directory link --"
3772         test_mkdir -c1 $DIR/${tdir}
3773         test_mkdir -c1 $DIR/${tdir}/dir
3774         touch $DIR/${tdir}/f
3775         ln $DIR/${tdir}/f $DIR/${tdir}/dir/g
3776         $CHECKSTAT -t file $DIR/${tdir}/f || error "source"
3777         [ `stat -c%h $DIR/${tdir}/f` == '2' ] || error "source nlink"
3778         $CHECKSTAT -t file $DIR/${tdir}/dir/g || error "target"
3779         [ `stat -c%h $DIR/${tdir}/dir/g` == '2' ] || error "target nlink"
3780 }
3781 run_test 31h "cross directory link under child==============="
3782
3783 test_31i() {
3784         echo "-- cross directory link --"
3785         test_mkdir -c1 $DIR/$tdir
3786         test_mkdir -c1 $DIR/$tdir/dir
3787         touch $DIR/$tdir/dir/f
3788         ln $DIR/$tdir/dir/f $DIR/$tdir/g
3789         $CHECKSTAT -t file $DIR/$tdir/dir/f || error "source"
3790         [ `stat -c%h $DIR/$tdir/dir/f` == '2' ] || error "source nlink"
3791         $CHECKSTAT -t file $DIR/$tdir/g || error "target"
3792         [ `stat -c%h $DIR/$tdir/g` == '2' ] || error "target nlink"
3793 }
3794 run_test 31i "cross directory link under parent==============="
3795
3796 test_31j() {
3797         test_mkdir -c1 -p $DIR/$tdir
3798         test_mkdir -c1 -p $DIR/$tdir/dir1
3799         ln $DIR/$tdir/dir1 $DIR/$tdir/dir2 && error "ln for dir"
3800         link $DIR/$tdir/dir1 $DIR/$tdir/dir3 && error "link for dir"
3801         link $DIR/$tdir/dir1 $DIR/$tdir/dir1 && error "link to the same dir"
3802         return 0
3803 }
3804 run_test 31j "link for directory"
3805
3806 test_31k() {
3807         test_mkdir -c1 -p $DIR/$tdir
3808         touch $DIR/$tdir/s
3809         touch $DIR/$tdir/exist
3810         link $DIR/$tdir/s $DIR/$tdir/t || error "link"
3811         link $DIR/$tdir/s $DIR/$tdir/exist && error "link to exist file"
3812         link $DIR/$tdir/s $DIR/$tdir/s && error "link to the same file"
3813         link $DIR/$tdir/s $DIR/$tdir && error "link to parent dir"
3814         link $DIR/$tdir $DIR/$tdir/s && error "link parent dir to target"
3815         link $DIR/$tdir/not-exist $DIR/$tdir/foo && error "link non-existing to new"
3816         link $DIR/$tdir/not-exist $DIR/$tdir/s && error "link non-existing to exist"
3817         return 0
3818 }
3819 run_test 31k "link to file: the same, non-existing, dir"
3820
3821 test_31l() {
3822         local ln_ver=$(ln --version | awk '/coreutils/ { print $4 }')
3823
3824         (( $(version_code $ln_ver) < $(version_code 8.31) )) ||
3825         (( $(version_code $(uname -r)) >= $(version_code 5.18) )) ||
3826                 skip "need coreutils < 8.31 or kernel >= 5.18 for ln"
3827
3828         touch $DIR/$tfile || error "create failed"
3829         mkdir $DIR/$tdir || error "mkdir failed"
3830         ln $DIR/$tfile $DIR/$tdir/ || error "ln to '$tdir/' failed"
3831 }
3832 run_test 31l "link to file: target dir has trailing slash"
3833
3834 test_31m() {
3835         mkdir $DIR/d31m
3836         touch $DIR/d31m/s
3837         mkdir $DIR/d31m2
3838         touch $DIR/d31m2/exist
3839         link $DIR/d31m/s $DIR/d31m2/t || error "link"
3840         link $DIR/d31m/s $DIR/d31m2/exist && error "link to exist file"
3841         link $DIR/d31m/s $DIR/d31m2 && error "link to parent dir"
3842         link $DIR/d31m2 $DIR/d31m/s && error "link parent dir to target"
3843         link $DIR/d31m/not-exist $DIR/d31m2/foo && error "link non-existing to new"
3844         link $DIR/d31m/not-exist $DIR/d31m2/s && error "link non-existing to exist"
3845         return 0
3846 }
3847 run_test 31m "link to file: the same, non-existing, dir"
3848
3849 test_31n() {
3850         touch $DIR/$tfile || error "cannot create '$DIR/$tfile'"
3851         nlink=$(stat --format=%h $DIR/$tfile)
3852         [ ${nlink:--1} -eq 1 ] || error "nlink is $nlink, expected 1"
3853         local fd=$(free_fd)
3854         local cmd="exec $fd<$DIR/$tfile"
3855         eval $cmd
3856         cmd="exec $fd<&-"
3857         trap "eval $cmd" EXIT
3858         nlink=$(stat --dereference --format=%h /proc/self/fd/$fd)
3859         [ ${nlink:--1} -eq 1 ] || error "nlink is $nlink, expected 1"
3860         rm $DIR/$tfile || error "cannot remove '$DIR/$tfile'"
3861         nlink=$(stat --dereference --format=%h /proc/self/fd/$fd)
3862         [ ${nlink:--1} -eq 0 ] || error "nlink is $nlink, expected 0"
3863         eval $cmd
3864 }
3865 run_test 31n "check link count of unlinked file"
3866
3867 link_one() {
3868         local tempfile=$(mktemp $1_XXXXXX)
3869         link $tempfile $1 2> /dev/null &&
3870                 echo "$BASHPID: link $tempfile to $1 succeeded"
3871         unlink $tempfile
3872 }
3873
3874 test_31o() { # LU-2901
3875         test_mkdir $DIR/$tdir
3876         for LOOP in $(seq 100); do
3877                 rm -f $DIR/$tdir/$tfile*
3878                 for THREAD in $(seq 8); do
3879                         link_one $DIR/$tdir/$tfile.$LOOP &
3880                 done
3881                 wait
3882                 local LINKS=$(ls -1 $DIR/$tdir | grep -c $tfile.$LOOP)
3883                 [[ $LINKS -gt 1 ]] && ls $DIR/$tdir &&
3884                         error "$LINKS duplicate links to $tfile.$LOOP" &&
3885                         break || true
3886         done
3887 }
3888 run_test 31o "duplicate hard links with same filename"
3889
3890 test_31p() {
3891         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
3892
3893         test_mkdir $DIR/$tdir
3894         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
3895         $LFS setdirstripe -D -c2 -H all_char $DIR/$tdir/striped_dir
3896
3897         opendirunlink $DIR/$tdir/striped_dir/test1 ||
3898                 error "open unlink test1 failed"
3899         opendirunlink $DIR/$tdir/striped_dir/test2 ||
3900                 error "open unlink test2 failed"
3901
3902         $CHECKSTAT -a $DIR/$tdir/striped_dir/test1 ||
3903                 error "test1 still exists"
3904         $CHECKSTAT -a $DIR/$tdir/striped_dir/test2 ||
3905                 error "test2 still exists"
3906 }
3907 run_test 31p "remove of open striped directory"
3908
3909 test_31q() {
3910         [ $MDSCOUNT -lt 3 ] && skip_env "needs >= 3 MDTs"
3911
3912         $LFS mkdir -i 3,1 $DIR/$tdir || error "mkdir failed"
3913         index=$($LFS getdirstripe -i $DIR/$tdir)
3914         [ $index -eq 3 ] || error "first stripe index $index != 3"
3915         index=$($LFS getdirstripe $DIR/$tdir | tail -1 | awk '{print $1}')
3916         [ $index -eq 1 ] || error "second stripe index $index != 1"
3917
3918         # when "-c <stripe_count>" is set, the number of MDTs specified after
3919         # "-i" should equal to the stripe count
3920         $LFS mkdir -i 3,1 -c 3 $DIR/$tdir.2 && error "mkdir should fail" || true
3921 }
3922 run_test 31q "create striped directory on specific MDTs"
3923
3924 #LU-14949
3925 test_31r() {
3926         touch $DIR/$tfile.target
3927         touch $DIR/$tfile.source
3928
3929         #OBD_FAIL_LLITE_OPEN_DELAY 0x1419
3930         $LCTL set_param fail_loc=0x1419 fail_val=3
3931         cat $DIR/$tfile.target &
3932         CATPID=$!
3933
3934         # Guarantee open is waiting before we get here
3935         sleep 1
3936         mv $DIR/$tfile.source $DIR/$tfile.target
3937
3938         wait $CATPID
3939         RC=$?
3940         if [[ $RC -ne 0 ]]; then
3941                 error "open with cat failed, rc=$RC"
3942         fi
3943 }
3944 run_test 31r "open-rename(replace) race"
3945
3946 cleanup_test32_mount() {
3947         local rc=0
3948         trap 0
3949         local loopdev=$(losetup -a | grep $EXT2_DEV | sed -ne 's/:.*$//p')
3950         $UMOUNT $DIR/$tdir/ext2-mountpoint || rc=$?
3951         losetup -d $loopdev || true
3952         rm -rf $DIR/$tdir
3953         return $rc
3954 }
3955
3956 test_32a() {
3957         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3958
3959         echo "== more mountpoints and symlinks ================="
3960         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
3961         trap cleanup_test32_mount EXIT
3962         test_mkdir -p $DIR/$tdir/ext2-mountpoint
3963         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
3964                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
3965         $CHECKSTAT -t dir $DIR/$tdir/ext2-mountpoint/.. ||
3966                 error "$DIR/$tdir/ext2-mountpoint/.. not dir type"
3967         cleanup_test32_mount
3968 }
3969 run_test 32a "stat d32a/ext2-mountpoint/.. ====================="
3970
3971 test_32b() {
3972         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3973
3974         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
3975         trap cleanup_test32_mount EXIT
3976         test_mkdir -p $DIR/$tdir/ext2-mountpoint
3977         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
3978                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
3979         ls -al $DIR/$tdir/ext2-mountpoint/.. ||
3980                 error "Can't list $DIR/$tdir/ext2-mountpoint/.."
3981         cleanup_test32_mount
3982 }
3983 run_test 32b "open d32b/ext2-mountpoint/.. ====================="
3984
3985 test_32c() {
3986         [ $PARALLEL == "yes" ] && skip "skip parallel run"
3987
3988         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
3989         trap cleanup_test32_mount EXIT
3990         test_mkdir -p $DIR/$tdir/ext2-mountpoint
3991         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
3992                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
3993         test_mkdir -p $DIR/$tdir/d2/test_dir
3994         $CHECKSTAT -t dir $DIR/$tdir/ext2-mountpoint/../d2/test_dir ||
3995                 error "$DIR/$tdir/ext2-mountpoint/../d2/test_dir not dir type"
3996         cleanup_test32_mount
3997 }
3998 run_test 32c "stat d32c/ext2-mountpoint/../d2/test_dir ========="
3999
4000 test_32d() {
4001         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4002
4003         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4004         trap cleanup_test32_mount EXIT
4005         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4006         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4007                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4008         test_mkdir -p $DIR/$tdir/d2/test_dir
4009         ls -al $DIR/$tdir/ext2-mountpoint/../d2/test_dir ||
4010                 error "Can't list $DIR/$tdir/ext2-mountpoint/../d2/test_dir"
4011         cleanup_test32_mount
4012 }
4013 run_test 32d "open d32d/ext2-mountpoint/../d2/test_dir"
4014
4015 test_32e() {
4016         rm -fr $DIR/$tdir
4017         test_mkdir -p $DIR/$tdir/tmp
4018         local tmp_dir=$DIR/$tdir/tmp
4019         ln -s $DIR/$tdir $tmp_dir/symlink11
4020         ln -s $tmp_dir/symlink11 $tmp_dir/../symlink01
4021         $CHECKSTAT -t link $DIR/$tdir/tmp/symlink11 || error "symlink11 bad"
4022         $CHECKSTAT -t link $DIR/$tdir/symlink01 || error "symlink01 bad"
4023 }
4024 run_test 32e "stat d32e/symlink->tmp/symlink->lustre-subdir"
4025
4026 test_32f() {
4027         rm -fr $DIR/$tdir
4028         test_mkdir -p $DIR/$tdir/tmp
4029         local tmp_dir=$DIR/$tdir/tmp
4030         ln -s $DIR/$tdir $tmp_dir/symlink11
4031         ln -s $tmp_dir/symlink11 $tmp_dir/../symlink01
4032         ls $DIR/$tdir/tmp/symlink11  || error "symlink11 bad"
4033         ls $DIR/$tdir/symlink01 || error "symlink01 bad"
4034 }
4035 run_test 32f "open d32f/symlink->tmp/symlink->lustre-subdir"
4036
4037 test_32g() {
4038         local tmp_dir=$DIR/$tdir/tmp
4039         test_mkdir -p $tmp_dir
4040         test_mkdir $DIR/${tdir}2
4041         ln -s $DIR/${tdir}2 $tmp_dir/symlink12
4042         ln -s $tmp_dir/symlink12 $tmp_dir/../symlink02
4043         $CHECKSTAT -t link $tmp_dir/symlink12 || error "symlink12 not a link"
4044         $CHECKSTAT -t link $DIR/$tdir/symlink02 || error "symlink02 not a link"
4045         $CHECKSTAT -t dir -f $tmp_dir/symlink12 || error "symlink12 not a dir"
4046         $CHECKSTAT -t dir -f $DIR/$tdir/symlink02 || error "symlink12 not a dir"
4047 }
4048 run_test 32g "stat d32g/symlink->tmp/symlink->lustre-subdir/${tdir}2"
4049
4050 test_32h() {
4051         rm -fr $DIR/$tdir $DIR/${tdir}2
4052         tmp_dir=$DIR/$tdir/tmp
4053         test_mkdir -p $tmp_dir
4054         test_mkdir $DIR/${tdir}2
4055         ln -s $DIR/${tdir}2 $tmp_dir/symlink12
4056         ln -s $tmp_dir/symlink12 $tmp_dir/../symlink02
4057         ls $tmp_dir/symlink12 || error "listing symlink12"
4058         ls $DIR/$tdir/symlink02  || error "listing symlink02"
4059 }
4060 run_test 32h "open d32h/symlink->tmp/symlink->lustre-subdir/${tdir}2"
4061
4062 test_32i() {
4063         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4064
4065         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4066         trap cleanup_test32_mount EXIT
4067         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4068         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4069                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4070         touch $DIR/$tdir/test_file
4071         $CHECKSTAT -t file $DIR/$tdir/ext2-mountpoint/../test_file ||
4072                 error "$DIR/$tdir/ext2-mountpoint/../test_file not file type"
4073         cleanup_test32_mount
4074 }
4075 run_test 32i "stat d32i/ext2-mountpoint/../test_file ==========="
4076
4077 test_32j() {
4078         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4079
4080         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4081         trap cleanup_test32_mount EXIT
4082         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4083         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4084                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4085         touch $DIR/$tdir/test_file
4086         cat $DIR/$tdir/ext2-mountpoint/../test_file ||
4087                 error "Can't open $DIR/$tdir/ext2-mountpoint/../test_file"
4088         cleanup_test32_mount
4089 }
4090 run_test 32j "open d32j/ext2-mountpoint/../test_file ==========="
4091
4092 test_32k() {
4093         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4094
4095         rm -fr $DIR/$tdir
4096         trap cleanup_test32_mount EXIT
4097         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4098         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4099                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4100         test_mkdir -p $DIR/$tdir/d2
4101         touch $DIR/$tdir/d2/test_file || error "touch failed"
4102         $CHECKSTAT -t file $DIR/$tdir/ext2-mountpoint/../d2/test_file ||
4103                 error "$DIR/$tdir/ext2-mountpoint/../d2/test_file not file type"
4104         cleanup_test32_mount
4105 }
4106 run_test 32k "stat d32k/ext2-mountpoint/../d2/test_file ========"
4107
4108 test_32l() {
4109         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4110
4111         rm -fr $DIR/$tdir
4112         trap cleanup_test32_mount EXIT
4113         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4114         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4115                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4116         test_mkdir -p $DIR/$tdir/d2
4117         touch $DIR/$tdir/d2/test_file || error "touch failed"
4118         cat  $DIR/$tdir/ext2-mountpoint/../d2/test_file ||
4119                 error "Can't open $DIR/$tdir/ext2-mountpoint/../d2/test_file"
4120         cleanup_test32_mount
4121 }
4122 run_test 32l "open d32l/ext2-mountpoint/../d2/test_file ========"
4123
4124 test_32m() {
4125         rm -fr $DIR/d32m
4126         test_mkdir -p $DIR/d32m/tmp
4127         TMP_DIR=$DIR/d32m/tmp
4128         ln -s $DIR $TMP_DIR/symlink11
4129         ln -s $TMP_DIR/symlink11 $TMP_DIR/../symlink01
4130         $CHECKSTAT -t link $DIR/d32m/tmp/symlink11 ||
4131                 error "symlink11 not a link"
4132         $CHECKSTAT -t link $DIR/d32m/symlink01 ||
4133                 error "symlink01 not a link"
4134 }
4135 run_test 32m "stat d32m/symlink->tmp/symlink->lustre-root ======"
4136
4137 test_32n() {
4138         rm -fr $DIR/d32n
4139         test_mkdir -p $DIR/d32n/tmp
4140         TMP_DIR=$DIR/d32n/tmp
4141         ln -s $DIR $TMP_DIR/symlink11
4142         ln -s $TMP_DIR/symlink11 $TMP_DIR/../symlink01
4143         ls -l $DIR/d32n/tmp/symlink11  || error "listing symlink11"
4144         ls -l $DIR/d32n/symlink01 || error "listing symlink01"
4145 }
4146 run_test 32n "open d32n/symlink->tmp/symlink->lustre-root ======"
4147
4148 test_32o() {
4149         touch $DIR/$tfile
4150         test_mkdir -p $DIR/d32o/tmp
4151         TMP_DIR=$DIR/d32o/tmp
4152         ln -s $DIR/$tfile $TMP_DIR/symlink12
4153         ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02
4154         $CHECKSTAT -t link $DIR/d32o/tmp/symlink12 ||
4155                 error "symlink12 not a link"
4156         $CHECKSTAT -t link $DIR/d32o/symlink02 || error "symlink02 not a link"
4157         $CHECKSTAT -t file -f $DIR/d32o/tmp/symlink12 ||
4158                 error "$DIR/d32o/tmp/symlink12 not file type"
4159         $CHECKSTAT -t file -f $DIR/d32o/symlink02 ||
4160                 error "$DIR/d32o/symlink02 not file type"
4161 }
4162 run_test 32o "stat d32o/symlink->tmp/symlink->lustre-root/$tfile"
4163
4164 test_32p() {
4165         log 32p_1
4166         rm -fr $DIR/d32p
4167         log 32p_2
4168         rm -f $DIR/$tfile
4169         log 32p_3
4170         touch $DIR/$tfile
4171         log 32p_4
4172         test_mkdir -p $DIR/d32p/tmp
4173         log 32p_5
4174         TMP_DIR=$DIR/d32p/tmp
4175         log 32p_6
4176         ln -s $DIR/$tfile $TMP_DIR/symlink12
4177         log 32p_7
4178         ln -s $TMP_DIR/symlink12 $TMP_DIR/../symlink02
4179         log 32p_8
4180         cat $DIR/d32p/tmp/symlink12 ||
4181                 error "Can't open $DIR/d32p/tmp/symlink12"
4182         log 32p_9
4183         cat $DIR/d32p/symlink02 || error "Can't open $DIR/d32p/symlink02"
4184         log 32p_10
4185 }
4186 run_test 32p "open d32p/symlink->tmp/symlink->lustre-root/$tfile"
4187
4188 test_32q() {
4189         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4190
4191         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4192         trap cleanup_test32_mount EXIT
4193         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4194         touch $DIR/$tdir/ext2-mountpoint/under_the_mount || error "touch failed"
4195         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4196                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4197         ls $DIR/$tdir/ext2-mountpoint | grep "\<under_the_mount\>" && error
4198         cleanup_test32_mount
4199 }
4200 run_test 32q "stat follows mountpoints in Lustre (should return error)"
4201
4202 test_32r() {
4203         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4204
4205         [ -e $DIR/$tdir ] && rm -fr $DIR/$tdir
4206         trap cleanup_test32_mount EXIT
4207         test_mkdir -p $DIR/$tdir/ext2-mountpoint
4208         touch $DIR/$tdir/ext2-mountpoint/under_the_mount || error "touch failed"
4209         mount -t ext2 -o loop $EXT2_DEV $DIR/$tdir/ext2-mountpoint ||
4210                 error "mount failed for $EXT2_DEV $DIR/$tdir/ext2-mountpoint"
4211         ls $DIR/$tdir/ext2-mountpoint | grep -q under_the_mount && error || true
4212         cleanup_test32_mount
4213 }
4214 run_test 32r "opendir follows mountpoints in Lustre (should return error)"
4215
4216 test_33aa() {
4217         rm -f $DIR/$tfile
4218         touch $DIR/$tfile
4219         chmod 444 $DIR/$tfile
4220         chown $RUNAS_ID $DIR/$tfile
4221         log 33_1
4222         $RUNAS $OPENFILE -f O_RDWR $DIR/$tfile && error || true
4223         log 33_2
4224 }
4225 run_test 33aa "write file with mode 444 (should return error)"
4226
4227 test_33a() {
4228         rm -fr $DIR/$tdir
4229         test_mkdir $DIR/$tdir
4230         chown $RUNAS_ID $DIR/$tdir
4231         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $DIR/$tdir/$tfile ||
4232                 error "$RUNAS create $tdir/$tfile failed"
4233         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $DIR/$tdir/$tfile &&
4234                 error "open RDWR" || true
4235 }
4236 run_test 33a "test open file(mode=0444) with O_RDWR (should return error)"
4237
4238 test_33b() {
4239         rm -fr $DIR/$tdir
4240         test_mkdir $DIR/$tdir
4241         chown $RUNAS_ID $DIR/$tdir
4242         $RUNAS $OPENFILE -f 1286739555 $DIR/$tdir/$tfile || true
4243 }
4244 run_test 33b "test open file with malformed flags (No panic)"
4245
4246 test_33c() {
4247         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4248         remote_ost_nodsh && skip "remote OST with nodsh"
4249
4250         local ostnum
4251         local ostname
4252         local write_bytes
4253         local all_zeros
4254
4255         all_zeros=true
4256         test_mkdir $DIR/$tdir
4257         # Read: 0, Write: 4, create/destroy: 2/0, stat: 1, punch: 0
4258
4259         sync
4260         for ostnum in $(seq $OSTCOUNT); do
4261                 # test-framework's OST numbering is one-based, while Lustre's
4262                 # is zero-based
4263                 ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4264                 # check if at least some write_bytes stats are counted
4265                 write_bytes=$(do_facet ost$ostnum lctl get_param -n \
4266                               obdfilter.$ostname.stats |
4267                               awk '/^write_bytes/ {print $7}' )
4268                 echo "baseline_write_bytes@ost$ostnum/$ostname=$write_bytes"
4269                 if (( ${write_bytes:-0} > 0 )); then
4270                         all_zeros=false
4271                         break
4272                 fi
4273         done
4274
4275         $all_zeros || return 0
4276
4277         # Write four bytes
4278         echo foo > $DIR/$tdir/bar
4279         # Really write them
4280         sync
4281
4282         # Total up write_bytes after writing.  We'd better find non-zeros.
4283         for ostnum in $(seq $OSTCOUNT); do
4284                 ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4285                 write_bytes=$(do_facet ost$ostnum lctl get_param -n \
4286                               obdfilter/$ostname/stats |
4287                               awk '/^write_bytes/ {print $7}' )
4288                 echo "write_bytes@ost$ostnum/$ostname=$write_bytes"
4289                 if (( ${write_bytes:-0} > 0 )); then
4290                         all_zeros=false
4291                         break
4292                 fi
4293         done
4294
4295         if $all_zeros; then
4296                 for ostnum in $(seq $OSTCOUNT); do
4297                         ostname=$(printf "$FSNAME-OST%.4x" $((ostnum - 1)))
4298                         echo "Check write_bytes is in obdfilter.*.stats:"
4299                         do_facet ost$ostnum lctl get_param -n \
4300                                 obdfilter.$ostname.stats
4301                 done
4302                 error "OST not keeping write_bytes stats (b=22312)"
4303         fi
4304 }
4305 run_test 33c "test write_bytes stats"
4306
4307 test_33d() {
4308         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
4309         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4310
4311         local MDTIDX=1
4312         local remote_dir=$DIR/$tdir/remote_dir
4313
4314         test_mkdir $DIR/$tdir
4315         $LFS mkdir -i $MDTIDX $remote_dir ||
4316                 error "create remote directory failed"
4317
4318         touch $remote_dir/$tfile
4319         chmod 444 $remote_dir/$tfile
4320         chown $RUNAS_ID $remote_dir/$tfile
4321
4322         $RUNAS $OPENFILE -f O_RDWR $DIR/$tfile && error || true
4323
4324         chown $RUNAS_ID $remote_dir
4325         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $remote_dir/f33 ||
4326                                         error "create" || true
4327         $RUNAS $OPENFILE -f O_RDWR:O_CREAT -m 0444 $remote_dir/f33 &&
4328                                     error "open RDWR" || true
4329         $RUNAS $OPENFILE -f 1286739555 $remote_dir/f33 || true
4330 }
4331 run_test 33d "openfile with 444 modes and malformed flags under remote dir"
4332
4333 test_33e() {
4334         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4335
4336         mkdir $DIR/$tdir
4337
4338         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4339         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4340         mkdir $DIR/$tdir/local_dir
4341
4342         local s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4343         local s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4344         local l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4345
4346         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4347                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode"
4348
4349         rmdir $DIR/$tdir/* || error "rmdir failed"
4350
4351         umask 777
4352         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4353         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4354         mkdir $DIR/$tdir/local_dir
4355
4356         s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4357         s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4358         l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4359
4360         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4361                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode 777"
4362
4363         rmdir $DIR/$tdir/* || error "rmdir(umask 777) failed"
4364
4365         umask 000
4366         $LFS setdirstripe -i0 -c2 $DIR/$tdir/striped_dir
4367         $LFS setdirstripe -i1 -c2 $DIR/$tdir/striped_dir1
4368         mkdir $DIR/$tdir/local_dir
4369
4370         s0_mode=$(stat -c%f $DIR/$tdir/striped_dir)
4371         s1_mode=$(stat -c%f $DIR/$tdir/striped_dir1)
4372         l_mode=$(stat -c%f $DIR/$tdir/local_dir)
4373
4374         [ "$l_mode" = "$s0_mode" -a "$l_mode" = "$s1_mode" ] ||
4375                 error "mkdir $l_mode striped0 $s0_mode striped1 $s1_mode 0"
4376 }
4377 run_test 33e "mkdir and striped directory should have same mode"
4378
4379 cleanup_33f() {
4380         trap 0
4381         do_facet $SINGLEMDS $LCTL set_param mdt.*.enable_remote_dir_gid=0
4382 }
4383
4384 test_33f() {
4385         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4386         remote_mds_nodsh && skip "remote MDS with nodsh"
4387
4388         mkdir $DIR/$tdir
4389         chmod go+rwx $DIR/$tdir
4390         do_facet $SINGLEMDS $LCTL set_param mdt.*.enable_remote_dir_gid=-1
4391         trap cleanup_33f EXIT
4392
4393         $RUNAS lfs mkdir -i 0 -c$MDSCOUNT $DIR/$tdir/striped_dir ||
4394                 error "cannot create striped directory"
4395
4396         $RUNAS touch $DIR/$tdir/striped_dir/{0..16} ||
4397                 error "cannot create files in striped directory"
4398
4399         $RUNAS rm $DIR/$tdir/striped_dir/{0..16} ||
4400                 error "cannot remove files in striped directory"
4401
4402         $RUNAS rmdir $DIR/$tdir/striped_dir ||
4403                 error "cannot remove striped directory"
4404
4405         cleanup_33f
4406 }
4407 run_test 33f "nonroot user can create, access, and remove a striped directory"
4408
4409 test_33g() {
4410         mkdir -p $DIR/$tdir/dir2
4411
4412         local err=$($RUNAS mkdir $DIR/$tdir/dir2 2>&1)
4413         echo $err
4414         [[ $err =~ "exists" ]] || error "Not exists error"
4415 }
4416 run_test 33g "nonroot user create already existing root created file"
4417
4418 sub_33h() {
4419         local hash_type=$1
4420         local count=250
4421
4422         test_mkdir -c $MDSCOUNT -H $hash_type $DIR/$tdir ||
4423                 error "lfs mkdir -H $hash_type $tdir failed"
4424         touch $DIR/$tdir/$tfile || error "touch $tfile failed"
4425
4426         local index=$($LFS getstripe -m $DIR/$tdir/$tfile)
4427         local index2
4428         local fname
4429
4430         for fname in $DIR/$tdir/$tfile.bak \
4431                      $DIR/$tdir/$tfile.SAV \
4432                      $DIR/$tdir/$tfile.orig \
4433                      $DIR/$tdir/$tfile~; do
4434                 touch $fname || error "touch $fname failed"
4435                 index2=$($LFS getstripe -m $fname)
4436                 (( $index == $index2 )) ||
4437                         error "$fname MDT index mismatch $index != $index2"
4438         done
4439
4440         local failed=0
4441         local patterns=(".$tfile.XXXXXX" "$tfile.XXXXXXXX")
4442         local pattern
4443
4444         for pattern in ${patterns[*]}; do
4445                 echo "pattern $pattern"
4446                 fname=$DIR/$tdir/$pattern
4447                 for (( i = 0; i < $count; i++ )); do
4448                         fname=$(mktemp $DIR/$tdir/$pattern) ||
4449                                 error "mktemp $DIR/$tdir/$pattern failed"
4450                         index2=$($LFS getstripe -m $fname)
4451                         (( $index == $index2 )) && continue
4452
4453                         failed=$((failed + 1))
4454                         echo "$fname MDT index mismatch $index != $index2"
4455                 done
4456         done
4457
4458         echo "$failed/$count MDT index mismatches, expect ~2-4"
4459         (( failed < 10 )) || error "MDT index mismatch $failed/$count times"
4460
4461         local same=0
4462         local expect
4463
4464         # verify that "crush" is still broken with all files on same MDT,
4465         # crush2 should have about 1/MDSCOUNT files on each MDT, with margin
4466         [[ "$hash_type" == "crush" ]] && expect=$count ||
4467                 expect=$((count / MDSCOUNT))
4468
4469         # crush2 doesn't put all-numeric suffixes on the same MDT,
4470         # filename like $tfile.12345678 should *not* be considered temp
4471         for pattern in ${patterns[*]}; do
4472                 local base=${pattern%%X*}
4473                 local suff=${pattern#$base}
4474
4475                 echo "pattern $pattern"
4476                 for (( i = 0; i < $count; i++ )); do
4477                         fname=$DIR/$tdir/$base$((${suff//X/1} + i))
4478                         touch $fname || error "touch $fname failed"
4479                         index2=$($LFS getstripe -m $fname)
4480                         (( $index != $index2 )) && continue
4481
4482                         same=$((same + 1))
4483                 done
4484         done
4485
4486         # the number of "bad" hashes is random, as it depends on the random
4487         # filenames generated by "mktemp".  Allow some margin in the results.
4488         echo "$((same/${#patterns[*]}))/$count matches, expect ~$expect for $1"
4489         (( same / ${#patterns[*]} <= expect * 9 / 7 &&
4490            same / ${#patterns[*]} > expect * 5 / 7 )) ||
4491                 error "MDT index match $((same / ${#patterns[*]}))/$count times"
4492         same=0
4493
4494         # crush2 doesn't put suffixes with special characters on the same MDT
4495         # filename like $tfile.txt.1234 should *not* be considered temp
4496         for pattern in ${patterns[*]}; do
4497                 local base=${pattern%%X*}
4498                 local suff=${pattern#$base}
4499
4500                 pattern=$base...${suff/XXX}
4501                 echo "pattern=$pattern"
4502                 for (( i = 0; i < $count; i++ )); do
4503                         fname=$(mktemp $DIR/$tdir/$pattern) ||
4504                                 error "touch $fname failed"
4505                         index2=$($LFS getstripe -m $fname)
4506                         (( $index != $index2 )) && continue
4507
4508                         same=$((same + 1))
4509                 done
4510         done
4511
4512         # the number of "bad" hashes is random, as it depends on the random
4513         # filenames generated by "mktemp".  Allow some margin in the results.
4514         echo "$((same/${#patterns[*]}))/$count matches, expect ~$expect for $1"
4515         (( same / ${#patterns[*]} <= expect * 9 / 7 &&
4516            same / ${#patterns[*]} > expect * 5 / 7 )) ||
4517                 error "MDT index match $((same / ${#patterns[*]}))/$count times"
4518 }
4519
4520 test_33h() {
4521         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4522         (( $MDS1_VERSION >= $(version_code 2.13.50) )) ||
4523                 skip "Need MDS version at least 2.13.50"
4524
4525         sub_33h crush
4526 }
4527 run_test 33h "temp file is located on the same MDT as target (crush)"
4528
4529 test_33hh() {
4530         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4531         echo "MDS1_VERSION=$MDS1_VERSION version_code=$(version_code 2.15.0)"
4532         (( $MDS1_VERSION > $(version_code 2.15.0) )) ||
4533                 skip "Need MDS version at least 2.15.0 for crush2"
4534
4535         sub_33h crush2
4536 }
4537 run_test 33hh "temp file is located on the same MDT as target (crush2)"
4538
4539 test_33i()
4540 {
4541         (( MDSCOUNT < 2 )) && skip "needs >= 2 MDTs"
4542
4543         local FNAME=$(str_repeat 'f' 250)
4544
4545         test_mkdir -i 0 -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
4546         createmany -o $DIR/$tdir/$FNAME 1000 || error "createmany failed"
4547
4548         local count
4549         local total
4550
4551         count=$($LFS getstripe -m $DIR/$tdir/* | grep -cw 1)
4552
4553         local MDC=$(lctl dl | awk '/MDT0001-mdc-[^M]/ { print $4 }')
4554
4555         lctl --device %$MDC deactivate
4556         stack_trap "lctl --device %$MDC activate"
4557         ls $DIR/$tdir > /dev/null && error "ls should return an error"
4558         total=$(\ls -l $DIR/$tdir | wc -l)
4559         # "ls -l" will list total in the first line
4560         total=$((total - 1))
4561         (( total + count == 1000 )) ||
4562                 error "ls list $total files, $count files on MDT1"
4563 }
4564 run_test 33i "striped directory can be accessed when one MDT is down"
4565
4566 test_33j() {
4567         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
4568
4569         mkdir -p $DIR/$tdir/
4570
4571         $LFS setdirstripe -D -i0,1 $DIR/$tdir/striped_dir_a &&
4572                 error "setdirstripe -D -i0,1 incorrectly succeeded"
4573
4574         $LFS setdirstripe -D -i0,1 -c1 $DIR/$tdir/striped_dir_b &&
4575                 error "setdirstripe -D -i0,1 -c1 incorrectly succeeded"
4576
4577         $LFS setdirstripe -D -i0,1 -c3 $DIR/$tdir/striped_dir_c &&
4578                 error "setdirstripe -D -i0,1 -c3 incorrectly succeeded"
4579
4580         $LFS setdirstripe -i0,1 $DIR/$tdir/striped_dir_e ||
4581                 error "-D was not specified, but still failed"
4582 }
4583 run_test 33j "lfs setdirstripe -D -i x,y,x should fail"
4584
4585 TEST_34_SIZE=${TEST_34_SIZE:-2000000000000}
4586 test_34a() {
4587         rm -f $DIR/f34
4588         $MCREATE $DIR/f34 || error "mcreate failed"
4589         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4590                 error "getstripe failed"
4591         $TRUNCATE $DIR/f34 $TEST_34_SIZE || error "truncate failed"
4592         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4593                 error "getstripe failed"
4594         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4595                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4596 }
4597 run_test 34a "truncate file that has not been opened ==========="
4598
4599 test_34b() {
4600         [ ! -f $DIR/f34 ] && test_34a
4601         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4602                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4603         $OPENFILE -f O_RDONLY $DIR/f34
4604         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" ||
4605                 error "getstripe failed"
4606         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4607                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4608 }
4609 run_test 34b "O_RDONLY opening file doesn't create objects ====="
4610
4611 test_34c() {
4612         [ ! -f $DIR/f34 ] && test_34a
4613         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4614                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4615         $OPENFILE -f O_RDWR $DIR/f34
4616         $LFS getstripe $DIR/f34 2>&1 | grep -q "no stripe info" &&
4617                 error "$LFS getstripe failed"
4618         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4619                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4620 }
4621 run_test 34c "O_RDWR opening file-with-size works =============="
4622
4623 test_34d() {
4624         [ ! -f $DIR/f34 ] && test_34a
4625         dd if=/dev/zero of=$DIR/f34 conv=notrunc bs=4k count=1 ||
4626                 error "dd failed"
4627         $CHECKSTAT -s $TEST_34_SIZE $DIR/f34 ||
4628                 error "Size of $DIR/f34 not equal to $TEST_34_SIZE bytes"
4629         rm $DIR/f34
4630 }
4631 run_test 34d "write to sparse file ============================="
4632
4633 test_34e() {
4634         rm -f $DIR/f34e
4635         $MCREATE $DIR/f34e || error "mcreate failed"
4636         $TRUNCATE $DIR/f34e 1000 || error "truncate failed"
4637         $CHECKSTAT -s 1000 $DIR/f34e ||
4638                 error "Size of $DIR/f34e not equal to 1000 bytes"
4639         $OPENFILE -f O_RDWR $DIR/f34e
4640         $CHECKSTAT -s 1000 $DIR/f34e ||
4641                 error "Size of $DIR/f34e not equal to 1000 bytes"
4642 }
4643 run_test 34e "create objects, some with size and some without =="
4644
4645 test_34f() { # bug 6242, 6243
4646         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4647
4648         SIZE34F=48000
4649         rm -f $DIR/f34f
4650         $MCREATE $DIR/f34f || error "mcreate failed"
4651         $TRUNCATE $DIR/f34f $SIZE34F || error "truncating $DIR/f3f to $SIZE34F"
4652         dd if=$DIR/f34f of=$TMP/f34f
4653         $CHECKSTAT -s $SIZE34F $TMP/f34f || error "$TMP/f34f not $SIZE34F bytes"
4654         dd if=/dev/zero of=$TMP/f34fzero bs=$SIZE34F count=1
4655         cmp $DIR/f34f $TMP/f34fzero || error "$DIR/f34f not all zero"
4656         cmp $TMP/f34f $TMP/f34fzero || error "$TMP/f34f not all zero"
4657         rm $TMP/f34f $TMP/f34fzero $DIR/f34f
4658 }
4659 run_test 34f "read from a file with no objects until EOF ======="
4660
4661 test_34g() {
4662         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4663
4664         dd if=/dev/zero of=$DIR/$tfile bs=1 count=100 seek=$TEST_34_SIZE ||
4665                 error "dd failed"
4666         $TRUNCATE $DIR/$tfile $((TEST_34_SIZE / 2))|| error "truncate failed"
4667         $CHECKSTAT -s $((TEST_34_SIZE / 2)) $DIR/$tfile ||
4668                 error "Size of $DIR/$tfile not equal to $((TEST_34_SIZE / 2))"
4669         cancel_lru_locks osc
4670         $CHECKSTAT -s $((TEST_34_SIZE / 2)) $DIR/$tfile ||
4671                 error "wrong size after lock cancel"
4672
4673         $TRUNCATE $DIR/$tfile $TEST_34_SIZE || error "truncate failed"
4674         $CHECKSTAT -s $TEST_34_SIZE $DIR/$tfile ||
4675                 error "expanding truncate failed"
4676         cancel_lru_locks osc
4677         $CHECKSTAT -s $TEST_34_SIZE $DIR/$tfile ||
4678                 error "wrong expanded size after lock cancel"
4679 }
4680 run_test 34g "truncate long file ==============================="
4681
4682 test_34h() {
4683         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4684
4685         local gid=10
4686         local sz=1000
4687
4688         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 || error "dd failed"
4689         sync # Flush the cache so that multiop below does not block on cache
4690              # flush when getting the group lock
4691         $MULTIOP $DIR/$tfile OG${gid}T${sz}g${gid}c &
4692         MULTIPID=$!
4693
4694         # Since just timed wait is not good enough, let's do a sync write
4695         # that way we are sure enough time for a roundtrip + processing
4696         # passed + 2 seconds of extra margin.
4697         dd if=/dev/zero of=$DIR/${tfile}-1 bs=$PAGE_SIZE oflag=direct count=1
4698         rm $DIR/${tfile}-1
4699         sleep 2
4700
4701         if [[ `ps h -o comm -p $MULTIPID` == "multiop" ]]; then
4702                 error "Multiop blocked on ftruncate, pid=$MULTIPID"
4703                 kill -9 $MULTIPID
4704         fi
4705         wait $MULTIPID
4706         local nsz=`stat -c %s $DIR/$tfile`
4707         [[ $nsz == $sz ]] || error "New size wrong $nsz != $sz"
4708 }
4709 run_test 34h "ftruncate file under grouplock should not block"
4710
4711 test_35a() {
4712         cp /bin/sh $DIR/f35a
4713         chmod 444 $DIR/f35a
4714         chown $RUNAS_ID $DIR/f35a
4715         $RUNAS $DIR/f35a && error || true
4716         rm $DIR/f35a
4717 }
4718 run_test 35a "exec file with mode 444 (should return and not leak)"
4719
4720 test_36a() {
4721         rm -f $DIR/f36
4722         utime $DIR/f36 || error "utime failed for MDS"
4723 }
4724 run_test 36a "MDS utime check (mknod, utime)"
4725
4726 test_36b() {
4727         echo "" > $DIR/f36
4728         utime $DIR/f36 || error "utime failed for OST"
4729 }
4730 run_test 36b "OST utime check (open, utime)"
4731
4732 test_36c() {
4733         rm -f $DIR/d36/f36
4734         test_mkdir $DIR/d36
4735         chown $RUNAS_ID $DIR/d36
4736         $RUNAS utime $DIR/d36/f36 || error "utime failed for MDS as non-root"
4737 }
4738 run_test 36c "non-root MDS utime check (mknod, utime)"
4739
4740 test_36d() {
4741         [ ! -d $DIR/d36 ] && test_36c
4742         echo "" > $DIR/d36/f36
4743         $RUNAS utime $DIR/d36/f36 || error "utime failed for OST as non-root"
4744 }
4745 run_test 36d "non-root OST utime check (open, utime)"
4746
4747 test_36e() {
4748         [ $RUNAS_ID -eq $UID ] && skip_env "RUNAS_ID = UID = $UID -- skipping"
4749
4750         test_mkdir $DIR/$tdir
4751         touch $DIR/$tdir/$tfile
4752         $RUNAS utime $DIR/$tdir/$tfile &&
4753                 error "utime worked, expected failure" || true
4754 }
4755 run_test 36e "utime on non-owned file (should return error)"
4756
4757 subr_36fh() {
4758         local fl="$1"
4759         local LANG_SAVE=$LANG
4760         local LC_LANG_SAVE=$LC_LANG
4761         export LANG=C LC_LANG=C # for date language
4762
4763         DATESTR="Dec 20  2000"
4764         test_mkdir $DIR/$tdir
4765         lctl set_param fail_loc=$fl
4766         date; date +%s
4767         cp /etc/hosts $DIR/$tdir/$tfile
4768         sync & # write RPC generated with "current" inode timestamp, but delayed
4769         sleep 1
4770         touch --date="$DATESTR" $DIR/$tdir/$tfile # setattr timestamp in past
4771         LS_BEFORE="`ls -l $DIR/$tdir/$tfile`" # old timestamp from client cache
4772         cancel_lru_locks $OSC
4773         LS_AFTER="`ls -l $DIR/$tdir/$tfile`"  # timestamp from OST object
4774         date; date +%s
4775         [ "$LS_BEFORE" != "$LS_AFTER" ] && \
4776                 echo "BEFORE: $LS_BEFORE" && \
4777                 echo "AFTER : $LS_AFTER" && \
4778                 echo "WANT  : $DATESTR" && \
4779                 error "$DIR/$tdir/$tfile timestamps changed" || true
4780
4781         export LANG=$LANG_SAVE LC_LANG=$LC_LANG_SAVE
4782 }
4783
4784 test_36f() {
4785         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4786
4787         #define OBD_FAIL_OST_BRW_PAUSE_BULK 0x214
4788         subr_36fh "0x80000214"
4789 }
4790 run_test 36f "utime on file racing with OST BRW write =========="
4791
4792 test_36g() {
4793         remote_ost_nodsh && skip "remote OST with nodsh"
4794         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4795         [ $MDS1_VERSION -lt $(version_code 2.12.51) ] &&
4796                 skip "Need MDS version at least 2.12.51"
4797
4798         local fmd_max_age
4799         local fmd
4800         local facet="ost1"
4801         local tgt="obdfilter"
4802
4803         [[ $OSC == "mdc" ]] && tgt="mdt" && facet="mds1"
4804
4805         test_mkdir $DIR/$tdir
4806         fmd_max_age=$(do_facet $facet \
4807                 "lctl get_param -n $tgt.*.tgt_fmd_seconds 2> /dev/null | \
4808                 head -n 1")
4809
4810         echo "FMD max age: ${fmd_max_age}s"
4811         touch $DIR/$tdir/$tfile
4812         fmd=$(do_facet $facet "lctl get_param -n $tgt.*.exports.*.fmd_count" |
4813                 gawk '{cnt=cnt+$1}  END{print cnt}')
4814         echo "FMD before: $fmd"
4815         [[ $fmd == 0 ]] &&
4816                 error "FMD wasn't create by touch"
4817         sleep $((fmd_max_age + 12))
4818         fmd=$(do_facet $facet "lctl get_param -n $tgt.*.exports.*.fmd_count" |
4819                 gawk '{cnt=cnt+$1}  END{print cnt}')
4820         echo "FMD after: $fmd"
4821         [[ $fmd == 0 ]] ||
4822                 error "FMD wasn't expired by ping"
4823 }
4824 run_test 36g "FMD cache expiry ====================="
4825
4826 test_36h() {
4827         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4828
4829         #define OBD_FAIL_OST_BRW_PAUSE_BULK2 0x227
4830         subr_36fh "0x80000227"
4831 }
4832 run_test 36h "utime on file racing with OST BRW write =========="
4833
4834 test_36i() {
4835         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
4836
4837         test_mkdir $DIR/$tdir
4838         $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir
4839
4840         local mtime=$(stat -c%Y $DIR/$tdir/striped_dir)
4841         local new_mtime=$((mtime + 200))
4842
4843         #change Modify time of striped dir
4844         touch -m -d @$new_mtime $DIR/$tdir/striped_dir ||
4845                         error "change mtime failed"
4846
4847         local got=$(stat -c%Y $DIR/$tdir/striped_dir)
4848
4849         [ "$new_mtime" = "$got" ] || error "expect $new_mtime got $got"
4850 }
4851 run_test 36i "change mtime on striped directory"
4852
4853 # test_37 - duplicate with tests 32q 32r
4854
4855 test_38() {
4856         local file=$DIR/$tfile
4857         touch $file
4858         openfile -f O_DIRECTORY $file
4859         local RC=$?
4860         local ENOTDIR=20
4861         [ $RC -eq 0 ] && error "opened file $file with O_DIRECTORY" || true
4862         [ $RC -eq $ENOTDIR ] || error "error $RC should be ENOTDIR ($ENOTDIR)"
4863 }
4864 run_test 38 "open a regular file with O_DIRECTORY should return -ENOTDIR ==="
4865
4866 test_39a() { # was test_39
4867         touch $DIR/$tfile
4868         touch $DIR/${tfile}2
4869 #       ls -l  $DIR/$tfile $DIR/${tfile}2
4870 #       ls -lu  $DIR/$tfile $DIR/${tfile}2
4871 #       ls -lc  $DIR/$tfile $DIR/${tfile}2
4872         sleep 2
4873         $OPENFILE -f O_CREAT:O_TRUNC:O_WRONLY $DIR/${tfile}2
4874         if [ ! $DIR/${tfile}2 -nt $DIR/$tfile ]; then
4875                 echo "mtime"
4876                 ls -l --full-time $DIR/$tfile $DIR/${tfile}2
4877                 echo "atime"
4878                 ls -lu --full-time $DIR/$tfile $DIR/${tfile}2
4879                 echo "ctime"
4880                 ls -lc --full-time $DIR/$tfile $DIR/${tfile}2
4881                 error "O_TRUNC didn't change timestamps"
4882         fi
4883 }
4884 run_test 39a "mtime changed on create"
4885
4886 test_39b() {
4887         test_mkdir -c1 $DIR/$tdir
4888         cp -p /etc/passwd $DIR/$tdir/fopen
4889         cp -p /etc/passwd $DIR/$tdir/flink
4890         cp -p /etc/passwd $DIR/$tdir/funlink
4891         cp -p /etc/passwd $DIR/$tdir/frename
4892         ln $DIR/$tdir/funlink $DIR/$tdir/funlink2
4893
4894         sleep 1
4895         echo "aaaaaa" >> $DIR/$tdir/fopen
4896         echo "aaaaaa" >> $DIR/$tdir/flink
4897         echo "aaaaaa" >> $DIR/$tdir/funlink
4898         echo "aaaaaa" >> $DIR/$tdir/frename
4899
4900         local open_new=`stat -c %Y $DIR/$tdir/fopen`
4901         local link_new=`stat -c %Y $DIR/$tdir/flink`
4902         local unlink_new=`stat -c %Y $DIR/$tdir/funlink`
4903         local rename_new=`stat -c %Y $DIR/$tdir/frename`
4904
4905         cat $DIR/$tdir/fopen > /dev/null
4906         ln $DIR/$tdir/flink $DIR/$tdir/flink2
4907         rm -f $DIR/$tdir/funlink2
4908         mv -f $DIR/$tdir/frename $DIR/$tdir/frename2
4909
4910         for (( i=0; i < 2; i++ )) ; do
4911                 local open_new2=`stat -c %Y $DIR/$tdir/fopen`
4912                 local link_new2=`stat -c %Y $DIR/$tdir/flink`
4913                 local unlink_new2=`stat -c %Y $DIR/$tdir/funlink`
4914                 local rename_new2=`stat -c %Y $DIR/$tdir/frename2`
4915
4916                 [ $open_new2 -eq $open_new ] || error "open file reverses mtime"
4917                 [ $link_new2 -eq $link_new ] || error "link file reverses mtime"
4918                 [ $unlink_new2 -eq $unlink_new ] || error "unlink file reverses mtime"
4919                 [ $rename_new2 -eq $rename_new ] || error "rename file reverses mtime"
4920
4921                 cancel_lru_locks $OSC
4922                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
4923         done
4924 }
4925 run_test 39b "mtime change on open, link, unlink, rename  ======"
4926
4927 # this should be set to past
4928 TEST_39_MTIME=`date -d "1 year ago" +%s`
4929
4930 # bug 11063
4931 test_39c() {
4932         touch $DIR1/$tfile
4933         sleep 2
4934         local mtime0=`stat -c %Y $DIR1/$tfile`
4935
4936         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
4937         local mtime1=`stat -c %Y $DIR1/$tfile`
4938         [ "$mtime1" = $TEST_39_MTIME ] || \
4939                 error "mtime is not set to past: $mtime1, should be $TEST_39_MTIME"
4940
4941         local d1=`date +%s`
4942         echo hello >> $DIR1/$tfile
4943         local d2=`date +%s`
4944         local mtime2=`stat -c %Y $DIR1/$tfile`
4945         [ "$mtime2" -ge "$d1" ] && [ "$mtime2" -le "$d2" ] || \
4946                 error "mtime is not updated on write: $d1 <= $mtime2 <= $d2"
4947
4948         mv $DIR1/$tfile $DIR1/$tfile-1
4949
4950         for (( i=0; i < 2; i++ )) ; do
4951                 local mtime3=`stat -c %Y $DIR1/$tfile-1`
4952                 [ "$mtime2" = "$mtime3" ] || \
4953                         error "mtime ($mtime2) changed (to $mtime3) on rename"
4954
4955                 cancel_lru_locks $OSC
4956                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
4957         done
4958 }
4959 run_test 39c "mtime change on rename ==========================="
4960
4961 # bug 21114
4962 test_39d() {
4963         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4964
4965         touch $DIR1/$tfile
4966         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
4967
4968         for (( i=0; i < 2; i++ )) ; do
4969                 local mtime=`stat -c %Y $DIR1/$tfile`
4970                 [ $mtime = $TEST_39_MTIME ] || \
4971                         error "mtime($mtime) is not set to $TEST_39_MTIME"
4972
4973                 cancel_lru_locks $OSC
4974                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
4975         done
4976 }
4977 run_test 39d "create, utime, stat =============================="
4978
4979 # bug 21114
4980 test_39e() {
4981         [ $PARALLEL == "yes" ] && skip "skip parallel run"
4982
4983         touch $DIR1/$tfile
4984         local mtime1=`stat -c %Y $DIR1/$tfile`
4985
4986         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
4987
4988         for (( i=0; i < 2; i++ )) ; do
4989                 local mtime2=`stat -c %Y $DIR1/$tfile`
4990                 [ $mtime2 = $TEST_39_MTIME ] || \
4991                         error "mtime($mtime2) is not set to $TEST_39_MTIME"
4992
4993                 cancel_lru_locks $OSC
4994                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
4995         done
4996 }
4997 run_test 39e "create, stat, utime, stat ========================"
4998
4999 # bug 21114
5000 test_39f() {
5001         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5002
5003         touch $DIR1/$tfile
5004         mtime1=`stat -c %Y $DIR1/$tfile`
5005
5006         sleep 2
5007         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5008
5009         for (( i=0; i < 2; i++ )) ; do
5010                 local mtime2=`stat -c %Y $DIR1/$tfile`
5011                 [ $mtime2 = $TEST_39_MTIME ] || \
5012                         error "mtime($mtime2) is not set to $TEST_39_MTIME"
5013
5014                 cancel_lru_locks $OSC
5015                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5016         done
5017 }
5018 run_test 39f "create, stat, sleep, utime, stat ================="
5019
5020 # bug 11063
5021 test_39g() {
5022         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5023
5024         echo hello >> $DIR1/$tfile
5025         local mtime1=`stat -c %Y $DIR1/$tfile`
5026
5027         sleep 2
5028         chmod o+r $DIR1/$tfile
5029
5030         for (( i=0; i < 2; i++ )) ; do
5031                 local mtime2=`stat -c %Y $DIR1/$tfile`
5032                 [ "$mtime1" = "$mtime2" ] || \
5033                         error "lost mtime: $mtime2, should be $mtime1"
5034
5035                 cancel_lru_locks $OSC
5036                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5037         done
5038 }
5039 run_test 39g "write, chmod, stat ==============================="
5040
5041 # bug 11063
5042 test_39h() {
5043         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5044
5045         touch $DIR1/$tfile
5046         sleep 1
5047
5048         local d1=`date`
5049         echo hello >> $DIR1/$tfile
5050         local mtime1=`stat -c %Y $DIR1/$tfile`
5051
5052         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5053         local d2=`date`
5054         if [ "$d1" != "$d2" ]; then
5055                 echo "write and touch not within one second"
5056         else
5057                 for (( i=0; i < 2; i++ )) ; do
5058                         local mtime2=`stat -c %Y $DIR1/$tfile`
5059                         [ "$mtime2" = $TEST_39_MTIME ] || \
5060                                 error "lost mtime: $mtime2, should be $TEST_39_MTIME"
5061
5062                         cancel_lru_locks $OSC
5063                         if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5064                 done
5065         fi
5066 }
5067 run_test 39h "write, utime within one second, stat ============="
5068
5069 test_39i() {
5070         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5071
5072         touch $DIR1/$tfile
5073         sleep 1
5074
5075         echo hello >> $DIR1/$tfile
5076         local mtime1=`stat -c %Y $DIR1/$tfile`
5077
5078         mv $DIR1/$tfile $DIR1/$tfile-1
5079
5080         for (( i=0; i < 2; i++ )) ; do
5081                 local mtime2=`stat -c %Y $DIR1/$tfile-1`
5082
5083                 [ "$mtime1" = "$mtime2" ] || \
5084                         error "lost mtime: $mtime2, should be $mtime1"
5085
5086                 cancel_lru_locks $OSC
5087                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5088         done
5089 }
5090 run_test 39i "write, rename, stat =============================="
5091
5092 test_39j() {
5093         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5094
5095         start_full_debug_logging
5096         touch $DIR1/$tfile
5097         sleep 1
5098
5099         #define OBD_FAIL_OSC_DELAY_SETTIME       0x412
5100         lctl set_param fail_loc=0x80000412
5101         multiop_bg_pause $DIR1/$tfile oO_RDWR:w2097152_c ||
5102                 error "multiop failed"
5103         local multipid=$!
5104         local mtime1=`stat -c %Y $DIR1/$tfile`
5105
5106         mv $DIR1/$tfile $DIR1/$tfile-1
5107
5108         kill -USR1 $multipid
5109         wait $multipid || error "multiop close failed"
5110
5111         for (( i=0; i < 2; i++ )) ; do
5112                 local mtime2=`stat -c %Y $DIR1/$tfile-1`
5113                 [ "$mtime1" = "$mtime2" ] ||
5114                         error "mtime is lost on close: $mtime2, " \
5115                               "should be $mtime1"
5116
5117                 cancel_lru_locks
5118                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5119         done
5120         lctl set_param fail_loc=0
5121         stop_full_debug_logging
5122 }
5123 run_test 39j "write, rename, close, stat ======================="
5124
5125 test_39k() {
5126         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5127
5128         touch $DIR1/$tfile
5129         sleep 1
5130
5131         multiop_bg_pause $DIR1/$tfile oO_RDWR:w2097152_c || error "multiop failed"
5132         local multipid=$!
5133         local mtime1=`stat -c %Y $DIR1/$tfile`
5134
5135         touch -m -d @$TEST_39_MTIME $DIR1/$tfile
5136
5137         kill -USR1 $multipid
5138         wait $multipid || error "multiop close failed"
5139
5140         for (( i=0; i < 2; i++ )) ; do
5141                 local mtime2=`stat -c %Y $DIR1/$tfile`
5142
5143                 [ "$mtime2" = $TEST_39_MTIME ] || \
5144                         error "mtime is lost on close: $mtime2, should be $TEST_39_MTIME"
5145
5146                 cancel_lru_locks
5147                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5148         done
5149 }
5150 run_test 39k "write, utime, close, stat ========================"
5151
5152 # this should be set to future
5153 TEST_39_ATIME=`date -d "1 year" +%s`
5154
5155 test_39l() {
5156         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5157         remote_mds_nodsh && skip "remote MDS with nodsh"
5158
5159         local atime_diff=$(do_facet $SINGLEMDS \
5160                                 lctl get_param -n mdd.*MDT0000*.atime_diff)
5161         rm -rf $DIR/$tdir
5162         mkdir_on_mdt0 $DIR/$tdir
5163
5164         # test setting directory atime to future
5165         touch -a -d @$TEST_39_ATIME $DIR/$tdir
5166         local atime=$(stat -c %X $DIR/$tdir)
5167         [ "$atime" = $TEST_39_ATIME ] ||
5168                 error "atime is not set to future: $atime, $TEST_39_ATIME"
5169
5170         # test setting directory atime from future to now
5171         local now=$(date +%s)
5172         touch -a -d @$now $DIR/$tdir
5173
5174         atime=$(stat -c %X $DIR/$tdir)
5175         [ "$atime" -eq "$now"  ] ||
5176                 error "atime is not updated from future: $atime, $now"
5177
5178         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=2
5179         sleep 3
5180
5181         # test setting directory atime when now > dir atime + atime_diff
5182         local d1=$(date +%s)
5183         ls $DIR/$tdir
5184         local d2=$(date +%s)
5185         cancel_lru_locks mdc
5186         atime=$(stat -c %X $DIR/$tdir)
5187         [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
5188                 error "atime is not updated  : $atime, should be $d2"
5189
5190         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=60
5191         sleep 3
5192
5193         # test not setting directory atime when now < dir atime + atime_diff
5194         ls $DIR/$tdir
5195         cancel_lru_locks mdc
5196         atime=$(stat -c %X $DIR/$tdir)
5197         [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
5198                 error "atime is updated to $atime, should remain $d1<atime<$d2"
5199
5200         do_facet $SINGLEMDS \
5201                 lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff
5202 }
5203 run_test 39l "directory atime update ==========================="
5204
5205 test_39m() {
5206         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5207
5208         touch $DIR1/$tfile
5209         sleep 2
5210         local far_past_mtime=$(date -d "May 29 1953" +%s)
5211         local far_past_atime=$(date -d "Dec 17 1903" +%s)
5212
5213         touch -m -d @$far_past_mtime $DIR1/$tfile
5214         touch -a -d @$far_past_atime $DIR1/$tfile
5215
5216         for (( i=0; i < 2; i++ )) ; do
5217                 local timestamps=$(stat -c "%X %Y" $DIR1/$tfile)
5218                 [ "$timestamps" = "$far_past_atime $far_past_mtime" ] || \
5219                         error "atime or mtime set incorrectly"
5220
5221                 cancel_lru_locks $OSC
5222                 if [ $i = 0 ] ; then echo "repeat after cancel_lru_locks"; fi
5223         done
5224 }
5225 run_test 39m "test atime and mtime before 1970"
5226
5227 test_39n() { # LU-3832
5228         remote_mds_nodsh && skip "remote MDS with nodsh"
5229
5230         local atime_diff=$(do_facet $SINGLEMDS \
5231                 lctl get_param -n mdd.*MDT0000*.atime_diff)
5232         local atime0
5233         local atime1
5234         local atime2
5235
5236         do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=1
5237
5238         rm -rf $DIR/$tfile
5239         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer
5240         atime0=$(stat -c %X $DIR/$tfile)
5241
5242         sleep 5
5243         $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
5244         atime1=$(stat -c %X $DIR/$tfile)
5245
5246         sleep 5
5247         cancel_lru_locks mdc
5248         cancel_lru_locks osc
5249         $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
5250         atime2=$(stat -c %X $DIR/$tfile)
5251
5252         do_facet $SINGLEMDS \
5253                 lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff
5254
5255         [ "$atime0" -eq "$atime1" ] || error "atime0 $atime0 != atime1 $atime1"
5256         [ "$atime1" -eq "$atime2" ] || error "atime0 $atime0 != atime1 $atime1"
5257 }
5258 run_test 39n "check that O_NOATIME is honored"
5259
5260 test_39o() {
5261         TESTDIR=$DIR/$tdir/$tfile
5262         [ -e $TESTDIR ] && rm -rf $TESTDIR
5263         mkdir -p $TESTDIR
5264         cd $TESTDIR
5265         links1=2
5266         ls
5267         mkdir a b
5268         ls
5269         links2=$(stat -c %h .)
5270         [ $(($links1 + 2)) != $links2 ] &&
5271                 error "wrong links count $(($links1 + 2)) != $links2"
5272         rmdir b
5273         links3=$(stat -c %h .)
5274         [ $(($links1 + 1)) != $links3 ] &&
5275                 error "wrong links count $links1 != $links3"
5276         return 0
5277 }
5278 run_test 39o "directory cached attributes updated after create"
5279
5280 test_39p() {
5281         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
5282
5283         local MDTIDX=1
5284         TESTDIR=$DIR/$tdir/$tdir
5285         [ -e $TESTDIR ] && rm -rf $TESTDIR
5286         test_mkdir -p $TESTDIR
5287         cd $TESTDIR
5288         links1=2
5289         ls
5290         test_mkdir -i $MDTIDX $TESTDIR/remote_dir1
5291         test_mkdir -i $MDTIDX $TESTDIR/remote_dir2
5292         ls
5293         links2=$(stat -c %h .)
5294         [ $(($links1 + 2)) != $links2 ] &&
5295                 error "wrong links count $(($links1 + 2)) != $links2"
5296         rmdir remote_dir2
5297         links3=$(stat -c %h .)
5298         [ $(($links1 + 1)) != $links3 ] &&
5299                 error "wrong links count $links1 != $links3"
5300         return 0
5301 }
5302 run_test 39p "remote directory cached attributes updated after create ========"
5303
5304 test_39r() {
5305         [ $OST1_VERSION -ge $(version_code 2.13.52) ] ||
5306                 skip "no atime update on old OST"
5307         if [ "$ost1_FSTYPE" != ldiskfs ]; then
5308                 skip_env "ldiskfs only test"
5309         fi
5310
5311         local saved_adiff
5312         local ahost=$(facet_active_host ost1)
5313         saved_adiff=$(do_facet ost1 \
5314                 lctl get_param -n obdfilter.*OST0000.atime_diff)
5315         stack_trap "do_facet ost1 \
5316                 lctl set_param obdfilter.*.atime_diff=$saved_adiff"
5317
5318         do_facet ost1 "lctl set_param obdfilter.*.atime_diff=5"
5319
5320         $LFS setstripe -i 0 $DIR/$tfile
5321         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 ||
5322                 error "can't write initial file"
5323         cancel_lru_locks osc
5324
5325         # exceed atime_diff and access file
5326         sleep 10
5327         dd if=$DIR/$tfile of=/dev/null bs=4k count=1 ||
5328                 error "can't udpate atime"
5329
5330         # atime_cli value is in decimal
5331         local atime_cli=$(stat -c %X $DIR/$tfile)
5332         echo "client atime: $atime_cli"
5333
5334         local ostdev=$(ostdevname 1)
5335         local fid=($($LFS getstripe $DIR/$tfile | grep 0x))
5336         local seq=${fid[3]#0x}
5337         local oid=${fid[1]}
5338         local oid_hex
5339
5340         if [ $seq == 0 ]; then
5341                 oid_hex=${fid[1]}
5342         else
5343                 oid_hex=${fid[2]#0x}
5344         fi
5345         local objpath="O/$seq/d$(($oid % 32))/$oid_hex"
5346         local cmd="debugfs -c -R \\\"stat $objpath\\\" $ostdev"
5347
5348         # allow atime update to be written to device
5349         do_facet ost1 "$LCTL set_param -n osd*.*OST*.force_sync=1"
5350         echo "OST atime: $(do_facet ost1 "$cmd" |& grep atime)"
5351
5352         # Give enough time for server to get updated. Until then
5353         # the value read is defaulted to "0x00000000:00000000"
5354         # Wait until atime read via debugfs is not equal to zero.
5355         # Max limit to wait is 30 seconds.
5356         wait_update_cond $ahost                                         \
5357                 "$cmd |& awk -F'[: ]' '/atime:/ { print \\\$4 }'"       \
5358                 "-gt" "0" 30 || error "atime on ost is still 0 after 30 seconds"
5359         # atime_ost value is in hex
5360         local atime_ost=$(do_facet ost1 "$cmd" |&
5361                           awk -F'[: ]' '/atime:/ { print $4 }')
5362         # debugfs returns atime in 0xNNNNNNNN:00000000 format
5363         # convert Hex to decimal before comparing
5364         local atime_ost_dec=$((atime_ost))
5365
5366         # The test pass criteria is that the client time and server should
5367         # be same (2s gap accepted). This gap could arise due to VFS updating
5368         # the atime after the read(dd), stat and the updated time from the
5369         # inode
5370         (( $((atime_cli - atime_ost_dec)) <= 2 )) ||
5371                 error "atime on client $atime_cli != ost $atime_ost_dec"
5372 }
5373 run_test 39r "lazy atime update on OST"
5374
5375 test_39q() { # LU-8041
5376         local testdir=$DIR/$tdir
5377         mkdir -p $testdir
5378         multiop_bg_pause $testdir D_c || error "multiop failed"
5379         local multipid=$!
5380         cancel_lru_locks mdc
5381         kill -USR1 $multipid
5382         local atime=$(stat -c %X $testdir)
5383         [ "$atime" -ne 0 ] || error "atime is zero"
5384 }
5385 run_test 39q "close won't zero out atime"
5386
5387 test_39s() {
5388         local atime0
5389         local atime1
5390         local atime2
5391         local atime3
5392         local atime4
5393
5394         umount_client $MOUNT
5395         mount_client $MOUNT relatime
5396
5397         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer conv=fsync
5398         atime0=$(stat -c %X $DIR/$tfile)
5399
5400         # First read updates atime
5401         sleep 1
5402         cat $DIR/$tfile >/dev/null
5403         atime1=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
5404
5405         # Next reads do not update atime
5406         sleep 1
5407         cat $DIR/$tfile >/dev/null
5408         atime2=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
5409
5410         # If mtime is greater than atime, atime is updated
5411         sleep 1
5412         touch -m $DIR/$tfile # (mtime = now)
5413         sleep 1
5414         cat $DIR/$tfile >/dev/null # (atime is updated because atime < mtime)
5415         atime3=$(stat -c %X $DIR/$tfile) # (atime = mtime = atime0 + 3)
5416
5417         # Next reads do not update atime
5418         sleep 1
5419         cat $DIR/$tfile >/dev/null
5420         atime4=$(stat -c %X $DIR/$tfile)
5421
5422         # Remount the client to clear 'relatime' option
5423         remount_client $MOUNT
5424
5425         (( atime0 < atime1 )) ||
5426                 error "atime $atime0 should be smaller than $atime1"
5427         (( atime1 == atime2 )) ||
5428                 error "atime $atime1 was updated to $atime2"
5429         (( atime1 < atime3 )) || error "atime1 $atime1 != atime3 $atime3"
5430         (( atime3 == atime4 )) || error "atime3 $atime3 != atime4 $atime4"
5431 }
5432 run_test 39s "relatime is supported"
5433
5434 test_40() {
5435         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
5436         $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&
5437                 error "openfile O_WRONLY:O_TRUNC $tfile failed"
5438         $CHECKSTAT -t file -s 4096 $DIR/$tfile ||
5439                 error "$tfile is not 4096 bytes in size"
5440 }
5441 run_test 40 "failed open(O_TRUNC) doesn't truncate ============="
5442
5443 test_41() {
5444         # bug 1553
5445         small_write $DIR/f41 18
5446 }
5447 run_test 41 "test small file write + fstat ====================="
5448
5449 count_ost_writes() {
5450         lctl get_param -n ${OSC}.*.stats |
5451                 awk -vwrites=0 '/ost_write/ { writes += $2 } \
5452                         END { printf("%0.0f", writes) }'
5453 }
5454
5455 # decent default
5456 WRITEBACK_SAVE=500
5457 DIRTY_RATIO_SAVE=40
5458 MAX_DIRTY_RATIO=50
5459 BG_DIRTY_RATIO_SAVE=10
5460 MAX_BG_DIRTY_RATIO=25
5461
5462 start_writeback() {
5463         trap 0
5464         # in 2.6, restore /proc/sys/vm/dirty_writeback_centisecs,
5465         # dirty_ratio, dirty_background_ratio
5466         if [ -f /proc/sys/vm/dirty_writeback_centisecs ]; then
5467                 sysctl -w vm.dirty_writeback_centisecs=$WRITEBACK_SAVE
5468                 sysctl -w vm.dirty_background_ratio=$BG_DIRTY_RATIO_SAVE
5469                 sysctl -w vm.dirty_ratio=$DIRTY_RATIO_SAVE
5470         else
5471                 # if file not here, we are a 2.4 kernel
5472                 kill -CONT `pidof kupdated`
5473         fi
5474 }
5475
5476 stop_writeback() {
5477         # setup the trap first, so someone cannot exit the test at the
5478         # exact wrong time and mess up a machine
5479         trap start_writeback EXIT
5480         # in 2.6, save and 0 /proc/sys/vm/dirty_writeback_centisecs
5481         if [ -f /proc/sys/vm/dirty_writeback_centisecs ]; then
5482                 WRITEBACK_SAVE=`sysctl -n vm.dirty_writeback_centisecs`
5483                 sysctl -w vm.dirty_writeback_centisecs=0
5484                 sysctl -w vm.dirty_writeback_centisecs=0
5485                 # save and increase /proc/sys/vm/dirty_ratio
5486                 DIRTY_RATIO_SAVE=`sysctl -n vm.dirty_ratio`
5487                 sysctl -w vm.dirty_ratio=$MAX_DIRTY_RATIO
5488                 # save and increase /proc/sys/vm/dirty_background_ratio
5489                 BG_DIRTY_RATIO_SAVE=`sysctl -n vm.dirty_background_ratio`
5490                 sysctl -w vm.dirty_background_ratio=$MAX_BG_DIRTY_RATIO
5491         else
5492                 # if file not here, we are a 2.4 kernel
5493                 kill -STOP `pidof kupdated`
5494         fi
5495 }
5496
5497 # ensure that all stripes have some grant before we test client-side cache
5498 setup_test42() {
5499         for i in `seq -f $DIR/f42-%g 1 $OSTCOUNT`; do
5500                 dd if=/dev/zero of=$i bs=4k count=1
5501                 rm $i
5502         done
5503 }
5504
5505 # Tests 42* verify that our behaviour is correct WRT caching, file closure,
5506 # file truncation, and file removal.
5507 test_42a() {
5508         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5509
5510         setup_test42
5511         cancel_lru_locks $OSC
5512         stop_writeback
5513         sync; sleep 1; sync # just to be safe
5514         BEFOREWRITES=`count_ost_writes`
5515         lctl get_param -n osc.*[oO][sS][cC][_-]*.cur_grant_bytes | grep "[0-9]"
5516         dd if=/dev/zero of=$DIR/f42a bs=1024 count=100
5517         AFTERWRITES=`count_ost_writes`
5518         [ $BEFOREWRITES -eq $AFTERWRITES ] || \
5519                 error "$BEFOREWRITES < $AFTERWRITES"
5520         start_writeback
5521 }
5522 run_test 42a "ensure that we don't flush on close"
5523
5524 test_42b() {
5525         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5526
5527         setup_test42
5528         cancel_lru_locks $OSC
5529         stop_writeback
5530         sync
5531         dd if=/dev/zero of=$DIR/f42b bs=1024 count=100
5532         BEFOREWRITES=$(count_ost_writes)
5533         unlink $DIR/f42b || error "unlink $DIR/f42b: $?"
5534         AFTERWRITES=$(count_ost_writes)
5535         if [[ $BEFOREWRITES -lt $AFTERWRITES ]]; then
5536                 error "$BEFOREWRITES < $AFTERWRITES on unlink"
5537         fi
5538         BEFOREWRITES=$(count_ost_writes)
5539         sync || error "sync: $?"
5540         AFTERWRITES=$(count_ost_writes)
5541         if [[ $BEFOREWRITES -lt $AFTERWRITES ]]; then
5542                 error "$BEFOREWRITES < $AFTERWRITES on sync"
5543         fi
5544         dmesg | grep 'error from obd_brw_async' && error 'error writing back'
5545         start_writeback
5546         return 0
5547 }
5548 run_test 42b "test destroy of file with cached dirty data ======"
5549
5550 # if these tests just want to test the effect of truncation,
5551 # they have to be very careful.  consider:
5552 # - the first open gets a {0,EOF}PR lock
5553 # - the first write conflicts and gets a {0, count-1}PW
5554 # - the rest of the writes are under {count,EOF}PW
5555 # - the open for truncate tries to match a {0,EOF}PR
5556 #   for the filesize and cancels the PWs.
5557 # any number of fixes (don't get {0,EOF} on open, match
5558 # composite locks, do smarter file size management) fix
5559 # this, but for now we want these tests to verify that
5560 # the cancellation with truncate intent works, so we
5561 # start the file with a full-file pw lock to match against
5562 # until the truncate.
5563 trunc_test() {
5564         test=$1
5565         file=$DIR/$test
5566         offset=$2
5567         cancel_lru_locks $OSC
5568         stop_writeback
5569         # prime the file with 0,EOF PW to match
5570         touch $file
5571         $TRUNCATE $file 0
5572         sync; sync
5573         # now the real test..
5574         dd if=/dev/zero of=$file bs=1024 count=100
5575         BEFOREWRITES=`count_ost_writes`
5576         $TRUNCATE $file $offset
5577         cancel_lru_locks $OSC
5578         AFTERWRITES=`count_ost_writes`
5579         start_writeback
5580 }
5581
5582 test_42c() {
5583         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5584
5585         trunc_test 42c 1024
5586         [ $BEFOREWRITES -eq $AFTERWRITES ] &&
5587                 error "beforewrites $BEFOREWRITES == afterwrites $AFTERWRITES on truncate"
5588         rm $file
5589 }
5590 run_test 42c "test partial truncate of file with cached dirty data"
5591
5592 test_42d() {
5593         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5594
5595         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
5596         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
5597         $LCTL set_param debug=+cache
5598
5599         trunc_test 42d 0
5600         [ $BEFOREWRITES -eq $AFTERWRITES ] ||
5601                 error "beforewrites $BEFOREWRITES != afterwrites $AFTERWRITES on truncate"
5602         rm $file
5603 }
5604 run_test 42d "test complete truncate of file with cached dirty data"
5605
5606 test_42e() { # bug22074
5607         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5608
5609         local TDIR=$DIR/${tdir}e
5610         local pages=16 # hardcoded 16 pages, don't change it.
5611         local files=$((OSTCOUNT * 500)) # hopefully 500 files on each OST
5612         local proc_osc0="osc.${FSNAME}-OST0000-osc-[^MDT]*"
5613         local max_dirty_mb
5614         local warmup_files
5615
5616         test_mkdir $DIR/${tdir}e
5617         $LFS setstripe -c 1 $TDIR
5618         createmany -o $TDIR/f $files
5619
5620         max_dirty_mb=$($LCTL get_param -n $proc_osc0/max_dirty_mb)
5621
5622         # we assume that with $OSTCOUNT files, at least one of them will
5623         # be allocated on OST0.
5624         warmup_files=$((OSTCOUNT * max_dirty_mb))
5625         createmany -o $TDIR/w $warmup_files
5626
5627         # write a large amount of data into one file and sync, to get good
5628         # avail_grant number from OST.
5629         for ((i=0; i<$warmup_files; i++)); do
5630                 idx=$($LFS getstripe -i $TDIR/w$i)
5631                 [ $idx -ne 0 ] && continue
5632                 dd if=/dev/zero of=$TDIR/w$i bs="$max_dirty_mb"M count=1
5633                 break
5634         done
5635         [[ $i -gt $warmup_files ]] && error "OST0 is still cold"
5636         sync
5637         $LCTL get_param $proc_osc0/cur_dirty_bytes
5638         $LCTL get_param $proc_osc0/cur_grant_bytes
5639
5640         # create as much dirty pages as we can while not to trigger the actual
5641         # RPCs directly. but depends on the env, VFS may trigger flush during this
5642         # period, hopefully we are good.
5643         for ((i=0; i<$warmup_files; i++)); do
5644                 idx=$($LFS getstripe -i $TDIR/w$i)
5645                 [ $idx -ne 0 ] && continue
5646                 dd if=/dev/zero of=$TDIR/w$i bs=1M count=1 2>/dev/null
5647         done
5648         $LCTL get_param $proc_osc0/cur_dirty_bytes
5649         $LCTL get_param $proc_osc0/cur_grant_bytes
5650
5651         # perform the real test
5652         $LCTL set_param $proc_osc0/rpc_stats 0
5653         for ((;i<$files; i++)); do
5654                 [ $($LFS getstripe -i $TDIR/f$i) -eq 0 ] || continue
5655                 dd if=/dev/zero of=$TDIR/f$i bs=$PAGE_SIZE count=$pages 2>/dev/null
5656         done
5657         sync
5658         $LCTL get_param $proc_osc0/rpc_stats
5659
5660         local percent=0
5661         local have_ppr=false
5662         $LCTL get_param $proc_osc0/rpc_stats |
5663                 while read PPR RRPC RPCT RCUM BAR WRPC WPCT WCUM; do
5664                         # skip lines until we are at the RPC histogram data
5665                         [ "$PPR" == "pages" ] && have_ppr=true && continue
5666                         $have_ppr || continue
5667
5668                         # we only want the percent stat for < 16 pages
5669                         [[ $(echo $PPR | tr -d ':') -ge $pages ]] && break
5670
5671                         percent=$((percent + WPCT))
5672                         if [[ $percent -gt 15 ]]; then
5673                                 error "less than 16-pages write RPCs" \
5674                                       "$percent% > 15%"
5675                                 break
5676                         fi
5677                 done
5678         rm -rf $TDIR
5679 }
5680 run_test 42e "verify sub-RPC writes are not done synchronously"
5681
5682 test_43A() { # was test_43
5683         test_mkdir $DIR/$tdir
5684         cp -p /bin/ls $DIR/$tdir/$tfile
5685         $MULTIOP $DIR/$tdir/$tfile Ow_c &
5686         pid=$!
5687         # give multiop a chance to open
5688         sleep 1
5689
5690         $DIR/$tdir/$tfile && error "execute $DIR/$tdir/$tfile succeeded" || true
5691         kill -USR1 $pid
5692         # Wait for multiop to exit
5693         wait $pid
5694 }
5695 run_test 43A "execution of file opened for write should return -ETXTBSY"
5696
5697 test_43a() {
5698         test_mkdir $DIR/$tdir
5699         cp -p $(which sleep) $DIR/$tdir/sleep || error "can't copy"
5700         $DIR/$tdir/sleep 60 &
5701         SLEEP_PID=$!
5702         # Make sure exec of $tdir/sleep wins race with truncate
5703         sleep 1
5704         $MULTIOP $DIR/$tdir/sleep Oc && error "expected error, got success"
5705         kill $SLEEP_PID
5706 }
5707 run_test 43a "open(RDWR) of file being executed should return -ETXTBSY"
5708
5709 test_43b() {
5710         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5711
5712         test_mkdir $DIR/$tdir
5713         cp -p $(which sleep) $DIR/$tdir/sleep || error "can't copy"
5714         $DIR/$tdir/sleep 60 &
5715         SLEEP_PID=$!
5716         # Make sure exec of $tdir/sleep wins race with truncate
5717         sleep 1
5718         $TRUNCATE $DIR/$tdir/sleep 0 && error "expected error, got success"
5719         kill $SLEEP_PID
5720 }
5721 run_test 43b "truncate of file being executed should return -ETXTBSY"
5722
5723 test_43c() {
5724         local testdir="$DIR/$tdir"
5725         test_mkdir $testdir
5726         cp $SHELL $testdir/
5727         ( cd $(dirname $SHELL) && md5sum $(basename $SHELL) ) |
5728                 ( cd $testdir && md5sum -c )
5729 }
5730 run_test 43c "md5sum of copy into lustre"
5731
5732 test_44A() { # was test_44
5733         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
5734
5735         dd if=/dev/zero of=$DIR/f1 bs=4k count=1 seek=1023
5736         dd if=$DIR/f1 bs=4k count=1 > /dev/null
5737 }
5738 run_test 44A "zero length read from a sparse stripe"
5739
5740 test_44a() {
5741         local nstripe=$($LFS getstripe -c -d $DIR)
5742         [ -z "$nstripe" ] && skip "can't get stripe info"
5743         [[ $nstripe -gt $OSTCOUNT ]] &&
5744                 skip "Wrong default stripe_count: $nstripe OSTCOUNT: $OSTCOUNT"
5745
5746         local stride=$($LFS getstripe -S -d $DIR)
5747         if [[ $nstripe -eq 0 || $nstripe -eq -1 ]]; then
5748                 nstripe=$($LFS df $DIR | grep OST: | wc -l)
5749         fi
5750
5751         OFFSETS="0 $((stride/2)) $((stride-1))"
5752         for offset in $OFFSETS; do
5753                 for i in $(seq 0 $((nstripe-1))); do
5754                         local GLOBALOFFSETS=""
5755                         # size in Bytes
5756                         local size=$((((i + 2 * $nstripe )*$stride + $offset)))
5757                         local myfn=$DIR/d44a-$size
5758                         echo "--------writing $myfn at $size"
5759                         ll_sparseness_write $myfn $size ||
5760                                 error "ll_sparseness_write"
5761                         GLOBALOFFSETS="$GLOBALOFFSETS $size"
5762                         ll_sparseness_verify $myfn $GLOBALOFFSETS ||
5763                                 error "ll_sparseness_verify $GLOBALOFFSETS"
5764
5765                         for j in $(seq 0 $((nstripe-1))); do
5766                                 # size in Bytes
5767                                 size=$((((j + $nstripe )*$stride + $offset)))
5768                                 ll_sparseness_write $myfn $size ||
5769                                         error "ll_sparseness_write"
5770                                 GLOBALOFFSETS="$GLOBALOFFSETS $size"
5771                         done
5772                         ll_sparseness_verify $myfn $GLOBALOFFSETS ||
5773                                 error "ll_sparseness_verify $GLOBALOFFSETS"
5774                         rm -f $myfn
5775                 done
5776         done
5777 }
5778 run_test 44a "test sparse pwrite ==============================="
5779
5780 dirty_osc_total() {
5781         tot=0
5782         for d in `lctl get_param -n ${OSC}.*.cur_dirty_bytes`; do
5783                 tot=$(($tot + $d))
5784         done
5785         echo $tot
5786 }
5787 do_dirty_record() {
5788         before=`dirty_osc_total`
5789         echo executing "\"$*\""
5790         eval $*
5791         after=`dirty_osc_total`
5792         echo before $before, after $after
5793 }
5794 test_45() {
5795         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5796
5797         f="$DIR/f45"
5798         # Obtain grants from OST if it supports it
5799         echo blah > ${f}_grant
5800         stop_writeback
5801         sync
5802         do_dirty_record "echo blah > $f"
5803         [[ $before -eq $after ]] && error "write wasn't cached"
5804         do_dirty_record "> $f"
5805         [[ $before -gt $after ]] || error "truncate didn't lower dirty count"
5806         do_dirty_record "echo blah > $f"
5807         [[ $before -eq $after ]] && error "write wasn't cached"
5808         do_dirty_record "sync"
5809         [[ $before -gt $after ]] || error "writeback didn't lower dirty count"
5810         do_dirty_record "echo blah > $f"
5811         [[ $before -eq $after ]] && error "write wasn't cached"
5812         do_dirty_record "cancel_lru_locks osc"
5813         [[ $before -gt $after ]] ||
5814                 error "lock cancellation didn't lower dirty count"
5815         start_writeback
5816 }
5817 run_test 45 "osc io page accounting ============================"
5818
5819 # in a 2 stripe file (lov.sh), page 1023 maps to page 511 in its object.  this
5820 # test tickles a bug where re-dirtying a page was failing to be mapped to the
5821 # objects offset and an assert hit when an rpc was built with 1023's mapped
5822 # offset 511 and 511's raw 511 offset. it also found general redirtying bugs.
5823 test_46() {
5824         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5825
5826         f="$DIR/f46"
5827         stop_writeback
5828         sync
5829         dd if=/dev/zero of=$f bs=$PAGE_SIZE seek=511 count=1
5830         sync
5831         dd conv=notrunc if=/dev/zero of=$f bs=$PAGE_SIZE seek=1023 count=1
5832         dd conv=notrunc if=/dev/zero of=$f bs=$PAGE_SIZE seek=511 count=1
5833         sync
5834         start_writeback
5835 }
5836 run_test 46 "dirtying a previously written page ================"
5837
5838 # test_47 is removed "Device nodes check" is moved to test_28
5839
5840 test_48a() { # bug 2399
5841         [ "$mds1_FSTYPE" = "zfs" ] &&
5842         [ $MDS1_VERSION -lt $(version_code 2.3.63) ] &&
5843                 skip "MDS prior to 2.3.63 handle ZFS dir .. incorrectly"
5844
5845         test_mkdir $DIR/$tdir
5846         cd $DIR/$tdir
5847         mv $DIR/$tdir $DIR/$tdir.new || error "move directory failed"
5848         test_mkdir $DIR/$tdir
5849         touch foo || error "'touch foo' failed after recreating cwd"
5850         test_mkdir bar
5851         touch .foo || error "'touch .foo' failed after recreating cwd"
5852         test_mkdir .bar
5853         ls . > /dev/null || error "'ls .' failed after recreating cwd"
5854         ls .. > /dev/null || error "'ls ..' failed after removing cwd"
5855         cd . || error "'cd .' failed after recreating cwd"
5856         mkdir . && error "'mkdir .' worked after recreating cwd"
5857         rmdir . && error "'rmdir .' worked after recreating cwd"
5858         ln -s . baz || error "'ln -s .' failed after recreating cwd"
5859         cd .. || error "'cd ..' failed after recreating cwd"
5860 }
5861 run_test 48a "Access renamed working dir (should return errors)="
5862
5863 test_48b() { # bug 2399
5864         rm -rf $DIR/$tdir
5865         test_mkdir $DIR/$tdir
5866         cd $DIR/$tdir
5867         rmdir $DIR/$tdir || error "remove cwd $DIR/$tdir failed"
5868         touch foo && error "'touch foo' worked after removing cwd"
5869         mkdir foo && error "'mkdir foo' worked after removing cwd"
5870         touch .foo && error "'touch .foo' worked after removing cwd"
5871         mkdir .foo && error "'mkdir .foo' worked after removing cwd"
5872         ls . > /dev/null && error "'ls .' worked after removing cwd"
5873         ls .. > /dev/null || error "'ls ..' failed after removing cwd"
5874         mkdir . && error "'mkdir .' worked after removing cwd"
5875         rmdir . && error "'rmdir .' worked after removing cwd"
5876         ln -s . foo && error "'ln -s .' worked after removing cwd"
5877         cd .. || echo "'cd ..' failed after removing cwd `pwd`"  #bug 3517
5878 }
5879 run_test 48b "Access removed working dir (should return errors)="
5880
5881 test_48c() { # bug 2350
5882         #lctl set_param debug=-1
5883         #set -vx
5884         rm -rf $DIR/$tdir
5885         test_mkdir -p $DIR/$tdir/dir
5886         cd $DIR/$tdir/dir
5887         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
5888         $TRACE touch foo && error "touch foo worked after removing cwd"
5889         $TRACE mkdir foo && error "'mkdir foo' worked after removing cwd"
5890         touch .foo && error "touch .foo worked after removing cwd"
5891         mkdir .foo && error "mkdir .foo worked after removing cwd"
5892         $TRACE ls . && error "'ls .' worked after removing cwd"
5893         $TRACE ls .. || error "'ls ..' failed after removing cwd"
5894         $TRACE mkdir . && error "'mkdir .' worked after removing cwd"
5895         $TRACE rmdir . && error "'rmdir .' worked after removing cwd"
5896         $TRACE ln -s . foo && error "'ln -s .' worked after removing cwd"
5897         $TRACE cd .. || echo "'cd ..' failed after removing cwd `pwd`" #bug 3415
5898 }
5899 run_test 48c "Access removed working subdir (should return errors)"
5900
5901 test_48d() { # bug 2350
5902         #lctl set_param debug=-1
5903         #set -vx
5904         rm -rf $DIR/$tdir
5905         test_mkdir -p $DIR/$tdir/dir
5906         cd $DIR/$tdir/dir
5907         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
5908         $TRACE rmdir $DIR/$tdir || error "remove parent $DIR/$tdir failed"
5909         $TRACE touch foo && error "'touch foo' worked after removing parent"
5910         $TRACE mkdir foo && error "mkdir foo worked after removing parent"
5911         touch .foo && error "'touch .foo' worked after removing parent"
5912         mkdir .foo && error "mkdir .foo worked after removing parent"
5913         $TRACE ls . && error "'ls .' worked after removing parent"
5914         $TRACE ls .. && error "'ls ..' worked after removing parent"
5915         $TRACE mkdir . && error "'mkdir .' worked after removing parent"
5916         $TRACE rmdir . && error "'rmdir .' worked after removing parent"
5917         $TRACE ln -s . foo && error "'ln -s .' worked after removing parent"
5918         true
5919 }
5920 run_test 48d "Access removed parent subdir (should return errors)"
5921
5922 test_48e() { # bug 4134
5923         #lctl set_param debug=-1
5924         #set -vx
5925         rm -rf $DIR/$tdir
5926         test_mkdir -p $DIR/$tdir/dir
5927         cd $DIR/$tdir/dir
5928         $TRACE rmdir $DIR/$tdir/dir || error "remove cwd $DIR/$tdir/dir failed"
5929         $TRACE rmdir $DIR/$tdir || error "remove parent $DIR/$tdir failed"
5930         $TRACE touch $DIR/$tdir || error "'touch $DIR/$tdir' failed"
5931         $TRACE chmod +x $DIR/$tdir || error "'chmod +x $DIR/$tdir' failed"
5932         # On a buggy kernel addition of "touch foo" after cd .. will
5933         # produce kernel oops in lookup_hash_it
5934         touch ../foo && error "'cd ..' worked after recreate parent"
5935         cd $DIR
5936         $TRACE rm $DIR/$tdir || error "rm '$DIR/$tdir' failed"
5937 }
5938 run_test 48e "Access to recreated parent subdir (should return errors)"
5939
5940 test_48f() {
5941         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
5942                 skip "need MDS >= 2.13.55"
5943         [[ $MDSCOUNT -ge 2 ]] || skip "needs >= 2 MDTs"
5944         [[ "$(facet_host mds1)" != "$(facet_host mds2)" ]] ||
5945                 skip "needs different host for mdt1 mdt2"
5946         [[ $(facet_fstype mds1) == ldiskfs ]] || skip "ldiskfs only"
5947
5948         $LFS mkdir -i0 $DIR/$tdir
5949         $LFS mkdir -i 1 $DIR/$tdir/sub1 $DIR/$tdir/sub2 $DIR/$tdir/sub3
5950
5951         for d in sub1 sub2 sub3; do
5952                 #define OBD_FAIL_OSD_REF_DEL    0x19c
5953                 do_facet mds1 $LCTL set_param fail_loc=0x8000019c
5954                 rm -rf $DIR/$tdir/$d && error "rm $d should fail"
5955         done
5956
5957         rm -d --interactive=never $DIR/$tdir || error "rm $tdir fail"
5958 }
5959 run_test 48f "non-zero nlink dir unlink won't LBUG()"
5960
5961 test_49() { # LU-1030
5962         [ $PARALLEL == "yes" ] && skip "skip parallel run"
5963         remote_ost_nodsh && skip "remote OST with nodsh"
5964
5965         # get ost1 size - $FSNAME-OST0000
5966         ost1_size=$(do_facet ost1 $LFS df | grep ${ost1_svc} |
5967                 awk '{ print $4 }')
5968         # write 800M at maximum
5969         [[ $ost1_size -lt 2 ]] && ost1_size=2
5970         [[ $ost1_size -gt 819200 ]] && ost1_size=819200
5971
5972         $LFS setstripe -c 1 -i 0 $DIR/$tfile
5973         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((ost1_size >> 2)) &
5974         local dd_pid=$!
5975
5976         # change max_pages_per_rpc while writing the file
5977         local osc1_mppc=osc.$(get_osc_import_name client ost1).max_pages_per_rpc
5978         local orig_mppc=$($LCTL get_param -n $osc1_mppc)
5979         # loop until dd process exits
5980         while ps ax -opid | grep -wq $dd_pid; do
5981                 $LCTL set_param $osc1_mppc=$((RANDOM % 256 + 1))
5982                 sleep $((RANDOM % 5 + 1))
5983         done
5984         # restore original max_pages_per_rpc
5985         $LCTL set_param $osc1_mppc=$orig_mppc
5986         rm $DIR/$tfile || error "rm $DIR/$tfile failed"
5987 }
5988 run_test 49 "Change max_pages_per_rpc won't break osc extent"
5989
5990 test_50() {
5991         # bug 1485
5992         test_mkdir $DIR/$tdir
5993         cd $DIR/$tdir
5994         ls /proc/$$/cwd || error "ls /proc/$$/cwd failed"
5995 }
5996 run_test 50 "special situations: /proc symlinks  ==============="
5997
5998 test_51a() {    # was test_51
5999         # bug 1516 - create an empty entry right after ".." then split dir
6000         test_mkdir -c1 $DIR/$tdir
6001         touch $DIR/$tdir/foo
6002         $MCREATE $DIR/$tdir/bar
6003         rm $DIR/$tdir/foo
6004         createmany -m $DIR/$tdir/longfile 201
6005         FNUM=202
6006         while [[ $(ls -sd $DIR/$tdir | awk '{ print $1 }') -eq 4 ]]; do
6007                 $MCREATE $DIR/$tdir/longfile$FNUM
6008                 FNUM=$(($FNUM + 1))
6009                 echo -n "+"
6010         done
6011         echo
6012         ls -l $DIR/$tdir > /dev/null || error "ls -l $DIR/$tdir failed"
6013 }
6014 run_test 51a "special situations: split htree with empty entry =="
6015
6016 cleanup_print_lfs_df () {
6017         trap 0
6018         $LFS df
6019         $LFS df -i
6020 }
6021
6022 test_51b() {
6023         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6024
6025         local dir=$DIR/$tdir
6026         local nrdirs=$((65536 + 100))
6027
6028         # cleanup the directory
6029         rm -fr $dir
6030
6031         mkdir_on_mdt -i $((RANDOM % MDSCOUNT)) $dir
6032
6033         $LFS df
6034         $LFS df -i
6035         local mdtidx=$(printf "%04x" $($LFS getstripe -m $dir))
6036         local numfree=$(lctl get_param -n mdc.$FSNAME-MDT$mdtidx*.filesfree)
6037         [[ $numfree -lt $nrdirs ]] &&
6038                 skip "not enough free inodes ($numfree) on MDT$mdtidx"
6039
6040         # need to check free space for the directories as well
6041         local blkfree=$(lctl get_param -n mdc.$FSNAME-MDT$mdtidx*.kbytesavail)
6042         numfree=$(( blkfree / $(fs_inode_ksize) ))
6043         [[ $numfree -lt $nrdirs ]] && skip "not enough blocks ($numfree)"
6044
6045         trap cleanup_print_lfs_df EXIT
6046
6047         # create files
6048         createmany -d $dir/d $nrdirs || {
6049                 unlinkmany $dir/d $nrdirs
6050                 error "failed to create $nrdirs subdirs in MDT$mdtidx:$dir"
6051         }
6052
6053         # really created :
6054         nrdirs=$(ls -U $dir | wc -l)
6055
6056         # unlink all but 100 subdirectories, then check it still works
6057         local left=100
6058         local delete=$((nrdirs - left))
6059
6060         $LFS df
6061         $LFS df -i
6062
6063         # for ldiskfs the nlink count should be 1, but this is OSD specific
6064         # and so this is listed for informational purposes only
6065         echo "nlink before: $(stat -c %h $dir), created before: $nrdirs"
6066         unlinkmany -d $dir/d $delete ||
6067                 error "unlink of first $delete subdirs failed"
6068
6069         echo "nlink between: $(stat -c %h $dir)"
6070         local found=$(ls -U $dir | wc -l)
6071         [ $found -ne $left ] &&
6072                 error "can't find subdirs: found only $found, expected $left"
6073
6074         unlinkmany -d $dir/d $delete $left ||
6075                 error "unlink of second $left subdirs failed"
6076         # regardless of whether the backing filesystem tracks nlink accurately
6077         # or not, the nlink count shouldn't be more than "." and ".." here
6078         local after=$(stat -c %h $dir)
6079         [[ $after -gt 2 ]] && error "nlink after: $after > 2" ||
6080                 echo "nlink after: $after"
6081
6082         cleanup_print_lfs_df
6083 }
6084 run_test 51b "exceed 64k subdirectory nlink limit on create, verify unlink"
6085
6086 test_51d_sub() {
6087         local stripecount=$1
6088         local nfiles=$2
6089
6090         log "create files with stripecount=$stripecount"
6091         $LFS setstripe -C $stripecount $DIR/$tdir
6092         createmany -o $DIR/$tdir/t- $nfiles
6093         $LFS getstripe $DIR/$tdir > $TMP/$tfile
6094         for ((n = 0; n < $OSTCOUNT; n++)); do
6095                 objs[$n]=$(awk -vobjs=0 '($1 == '$n') { objs += 1 } \
6096                            END { printf("%0.0f", objs) }' $TMP/$tfile)
6097                 objs0[$n]=$(grep -A 1 idx $TMP/$tfile | awk -vobjs=0 \
6098                             '($1 == '$n') { objs += 1 } \
6099                             END { printf("%0.0f", objs) }')
6100                 log "OST$n has ${objs[$n]} objects, ${objs0[$n]} are index 0"
6101         done
6102         unlinkmany $DIR/$tdir/t- $nfiles
6103         rm  -f $TMP/$tfile
6104
6105         local nlast
6106         local min=4
6107         local max=6 # allow variance of (1 - $min/$max) = 33% by default
6108
6109         # For some combinations of stripecount and OSTCOUNT current code
6110         # is not ideal, and allocates 50% fewer *first* objects to some OSTs
6111         # than others. Rather than skipping this test entirely, check that
6112         # and keep testing to ensure imbalance does not get worse. LU-15282
6113         (( (OSTCOUNT == 6 && stripecount == 4) ||
6114            (OSTCOUNT == 10 && (stripecount == 4 || stripecount == 8)) ||
6115            (OSTCOUNT == 12 && (stripecount == 8 || stripecount == 9)))) && max=9
6116         for ((nlast=0, n = 1; n < $OSTCOUNT; nlast=n,n++)); do
6117                 (( ${objs[$n]} > ${objs[$nlast]} * 4 / 5 )) ||
6118                         { $LFS df && $LFS df -i &&
6119                         error "stripecount=$stripecount: " \
6120                               "OST $n has fewer objects vs. OST $nlast " \
6121                               "(${objs[$n]} < ${objs[$nlast]} x 4/5)"; }
6122                 (( ${objs[$n]} < ${objs[$nlast]} * 5 / 4 )) ||
6123                         { $LFS df && $LFS df -i &&
6124                         error "stripecount=$stripecount: " \
6125                               "OST $n has more objects vs. OST $nlast " \
6126                               "(${objs[$n]} > ${objs[$nlast]} x 5/4)"; }
6127
6128                 (( ${objs0[$n]} > ${objs0[$nlast]} * $min / $max )) ||
6129                         { $LFS df && $LFS df -i &&
6130                         error "stripecount=$stripecount: " \
6131                               "OST $n has fewer #0 objects vs. OST $nlast " \
6132                               "(${objs0[$n]} < ${objs0[$nlast]} x $min/$max)"; }
6133                 (( ${objs0[$n]} < ${objs0[$nlast]} * $max / $min )) ||
6134                         { $LFS df && $LFS df -i &&
6135                         error "stripecount=$stripecount: " \
6136                               "OST $n has more #0 objects vs. OST $nlast " \
6137                               "(${objs0[$n]} > ${objs0[$nlast]} x $max/$min)"; }
6138         done
6139 }
6140
6141 test_51d() {
6142         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6143         [[ $OSTCOUNT -lt 3 ]] && skip_env "needs >= 3 OSTs"
6144
6145         local stripecount
6146         local per_ost=100
6147         local nfiles=$((per_ost * OSTCOUNT))
6148         local mdts=$(comma_list $(mdts_nodes))
6149         local param="osp.*.create_count"
6150         local qos_old=$(do_facet mds1 \
6151                 "$LCTL get_param -n lod.$FSNAME-*.qos_threshold_rr" | head -n 1)
6152
6153         do_nodes $mdts \
6154                 "$LCTL set_param lod.$FSNAME-*.qos_threshold_rr=100"
6155         stack_trap "do_nodes $mdts \
6156                 '$LCTL set_param lod.$FSNAME-*.qos_threshold_rr=${qos_old%%%}'"
6157
6158         test_mkdir $DIR/$tdir
6159         local dirstripes=$(lfs getdirstripe -c $DIR/$tdir)
6160         (( dirstripes > 0 )) || dirstripes=1
6161
6162         # Ensure enough OST objects precreated for tests to pass without
6163         # running out of objects.  This is an LOV r-r OST algorithm test,
6164         # not an OST object precreation test.
6165         local old=$(do_facet mds1 "$LCTL get_param -n $param" | head -n 1)
6166         (( old >= nfiles )) ||
6167         {
6168                 local create_count=$((nfiles * OSTCOUNT / dirstripes))
6169
6170                 do_nodes $mdts "$LCTL set_param $param=$create_count"
6171                 stack_trap "do_nodes $mdts $LCTL set_param $param=$old"
6172
6173                 # trigger precreation from all MDTs for all OSTs
6174                 for ((i = 0; i < $MDSCOUNT * 2; i++ )); do
6175                         $LFS setstripe -c -1 $DIR/$tdir/wide.$i
6176                 done
6177         }
6178
6179         for ((stripecount = 3; stripecount <= $OSTCOUNT; stripecount++)); do
6180                 sleep 8  # allow object precreation to catch up
6181                 test_51d_sub $stripecount $nfiles
6182         done
6183 }
6184 run_test 51d "check LOV round-robin OST object distribution"
6185
6186 test_51e() {
6187         if [ "$mds1_FSTYPE" != ldiskfs ]; then
6188                 skip_env "ldiskfs only test"
6189         fi
6190
6191         test_mkdir -c1 $DIR/$tdir
6192         test_mkdir -c1 $DIR/$tdir/d0
6193
6194         touch $DIR/$tdir/d0/foo
6195         createmany -l $DIR/$tdir/d0/foo $DIR/$tdir/d0/f- 65001 &&
6196                 error "file exceed 65000 nlink limit!"
6197         unlinkmany $DIR/$tdir/d0/f- 65001
6198         return 0
6199 }
6200 run_test 51e "check file nlink limit"
6201
6202 test_51f() {
6203         test_mkdir $DIR/$tdir
6204
6205         local max=100000
6206         local ulimit_old=$(ulimit -n)
6207         local spare=20 # number of spare fd's for scripts/libraries, etc.
6208         local mdt=$($LFS getstripe -m $DIR/$tdir)
6209         local numfree=$($LFS df -i $DIR/$tdir | awk '/MDT:'$mdt'/ { print $4 }')
6210
6211         echo "MDT$mdt numfree=$numfree, max=$max"
6212         [[ $numfree -gt $max ]] && numfree=$max || numfree=$((numfree * 7 / 8))
6213         if [ $((numfree + spare)) -gt $ulimit_old ]; then
6214                 while ! ulimit -n $((numfree + spare)); do
6215                         numfree=$((numfree * 3 / 4))
6216                 done
6217                 echo "changed ulimit from $ulimit_old to $((numfree + spare))"
6218         else
6219                 echo "left ulimit at $ulimit_old"
6220         fi
6221
6222         createmany -o -k -t 120 $DIR/$tdir/f $numfree || {
6223                 unlinkmany $DIR/$tdir/f $numfree
6224                 error "create+open $numfree files in $DIR/$tdir failed"
6225         }
6226         ulimit -n $ulimit_old
6227
6228         # if createmany exits at 120s there will be fewer than $numfree files
6229         unlinkmany $DIR/$tdir/f $numfree || true
6230 }
6231 run_test 51f "check many open files limit"
6232
6233 test_52a() {
6234         [ -f $DIR/$tdir/foo ] && chattr -a $DIR/$tdir/foo
6235         test_mkdir $DIR/$tdir
6236         touch $DIR/$tdir/foo
6237         chattr +a $DIR/$tdir/foo || error "chattr +a failed"
6238         echo bar >> $DIR/$tdir/foo || error "append bar failed"
6239         cp /etc/hosts $DIR/$tdir/foo && error "cp worked"
6240         rm -f $DIR/$tdir/foo 2>/dev/null && error "rm worked"
6241         link $DIR/$tdir/foo $DIR/$tdir/foo_link 2>/dev/null &&
6242                                         error "link worked"
6243         echo foo >> $DIR/$tdir/foo || error "append foo failed"
6244         mrename $DIR/$tdir/foo $DIR/$tdir/foo_ren && error "rename worked"
6245         lsattr $DIR/$tdir/foo | egrep -q "^-+a[-e]+ $DIR/$tdir/foo" ||
6246                                                      error "lsattr"
6247         chattr -a $DIR/$tdir/foo || error "chattr -a failed"
6248         cp -r $DIR/$tdir $TMP/
6249         rm -fr $DIR/$tdir $TMP/$tdir || error "cleanup rm failed"
6250 }
6251 run_test 52a "append-only flag test (should return errors)"
6252
6253 test_52b() {
6254         [ -f $DIR/$tdir/foo ] && chattr -i $DIR/$tdir/foo
6255         test_mkdir $DIR/$tdir
6256         touch $DIR/$tdir/foo
6257         chattr +i $DIR/$tdir/foo || error "chattr +i failed"
6258         cat test > $DIR/$tdir/foo && error "cat test worked"
6259         cp /etc/hosts $DIR/$tdir/foo && error "cp worked"
6260         rm -f $DIR/$tdir/foo 2>/dev/null && error "rm worked"
6261         link $DIR/$tdir/foo $DIR/$tdir/foo_link 2>/dev/null &&
6262                                         error "link worked"
6263         echo foo >> $DIR/$tdir/foo && error "echo worked"
6264         mrename $DIR/$tdir/foo $DIR/$tdir/foo_ren && error "rename worked"
6265         [ -f $DIR/$tdir/foo ] || error "$tdir/foo is not a file"
6266         [ -f $DIR/$tdir/foo_ren ] && error "$tdir/foo_ren is not a file"
6267         lsattr $DIR/$tdir/foo | egrep -q "^-+i[-e]+ $DIR/$tdir/foo" ||
6268                                                         error "lsattr"
6269         chattr -i $DIR/$tdir/foo || error "chattr failed"
6270
6271         rm -fr $DIR/$tdir || error "unable to remove $DIR/$tdir"
6272 }
6273 run_test 52b "immutable flag test (should return errors) ======="
6274
6275 test_53() {
6276         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6277         remote_mds_nodsh && skip "remote MDS with nodsh"
6278         remote_ost_nodsh && skip "remote OST with nodsh"
6279
6280         local param
6281         local param_seq
6282         local ostname
6283         local mds_last
6284         local mds_last_seq
6285         local ost_last
6286         local ost_last_seq
6287         local ost_last_id
6288         local ostnum
6289         local node
6290         local found=false
6291         local support_last_seq=true
6292
6293         [[ $MDS1_VERSION -ge $(version_code 2.3.60) ]] ||
6294                 support_last_seq=false
6295
6296         # only test MDT0000
6297         local mdtosc=$(get_mdtosc_proc_path $SINGLEMDS)
6298         local value
6299         for value in $(do_facet $SINGLEMDS \
6300                        $LCTL get_param osp.$mdtosc.prealloc_last_id) ; do
6301                 param=$(echo ${value[0]} | cut -d "=" -f1)
6302                 ostname=$(echo $param | cut -d "." -f2 | cut -d - -f 1-2)
6303
6304                 if $support_last_seq; then
6305                         param_seq=$(echo $param |
6306                                 sed -e s/prealloc_last_id/prealloc_last_seq/g)
6307                         mds_last_seq=$(do_facet $SINGLEMDS \
6308                                        $LCTL get_param -n $param_seq)
6309                 fi
6310                 mds_last=$(do_facet $SINGLEMDS $LCTL get_param -n $param)
6311
6312                 ostnum=$(index_from_ostuuid ${ostname}_UUID)
6313                 node=$(facet_active_host ost$((ostnum+1)))
6314                 param="obdfilter.$ostname.last_id"
6315                 for ost_last in $(do_node $node $LCTL get_param -n $param) ; do
6316                         echo "$ostname.last_id=$ost_last; MDS.last_id=$mds_last"
6317                         ost_last_id=$ost_last
6318
6319                         if $support_last_seq; then
6320                                 ost_last_id=$(echo $ost_last |
6321                                               awk -F':' '{print $2}' |
6322                                               sed -e "s/^0x//g")
6323                                 ost_last_seq=$(echo $ost_last |
6324                                                awk -F':' '{print $1}')
6325                                 [[ $ost_last_seq = $mds_last_seq ]] || continue
6326                         fi
6327
6328                         if [[ $ost_last_id != $mds_last ]]; then
6329                                 error "$ost_last_id != $mds_last"
6330                         else
6331                                 found=true
6332                                 break
6333                         fi
6334                 done
6335         done
6336         $found || error "can not match last_seq/last_id for $mdtosc"
6337         return 0
6338 }
6339 run_test 53 "verify that MDS and OSTs agree on pre-creation ===="
6340
6341 test_54a() {
6342         LANG=C perl -MSocket -e ';' || skip "no Socket perl module installed"
6343
6344         LANG=C $SOCKETSERVER $DIR/socket ||
6345                 error "$SOCKETSERVER $DIR/socket failed: $?"
6346         LANG=C $SOCKETCLIENT $DIR/socket ||
6347                 error "$SOCKETCLIENT $DIR/socket failed: $?"
6348         unlink $DIR/socket || error "unlink $DIR/socket failed: $?"
6349 }
6350 run_test 54a "unix domain socket test =========================="
6351
6352 test_54b() {
6353         f="$DIR/f54b"
6354         mknod $f c 1 3
6355         chmod 0666 $f
6356         dd if=/dev/zero of=$f bs=$PAGE_SIZE count=1
6357 }
6358 run_test 54b "char device works in lustre ======================"
6359
6360 find_loop_dev() {
6361         [ -b /dev/loop/0 ] && LOOPBASE=/dev/loop/
6362         [ -b /dev/loop0 ] && LOOPBASE=/dev/loop
6363         [ -z "$LOOPBASE" ] && echo "/dev/loop/0 and /dev/loop0 gone?" && return
6364
6365         for i in $(seq 3 7); do
6366                 losetup $LOOPBASE$i > /dev/null 2>&1 && continue
6367                 LOOPDEV=$LOOPBASE$i
6368                 LOOPNUM=$i
6369                 break
6370         done
6371 }
6372
6373 cleanup_54c() {
6374         local rc=0
6375         loopdev="$DIR/loop54c"
6376
6377         trap 0
6378         $UMOUNT $DIR/$tdir || rc=$?
6379         losetup -d $loopdev || true
6380         losetup -d $LOOPDEV || true
6381         rm -rf $loopdev $DIR/$tfile $DIR/$tdir
6382         return $rc
6383 }
6384
6385 test_54c() {
6386         [ $PARALLEL == "yes" ] && skip "skip parallel run"
6387
6388         loopdev="$DIR/loop54c"
6389
6390         find_loop_dev
6391         [ -z "$LOOPNUM" ] && skip_env "couldn't find empty loop device"
6392         trap cleanup_54c EXIT
6393         mknod $loopdev b 7 $LOOPNUM
6394         echo "make a loop file system with $DIR/$tfile on $loopdev ($LOOPNUM)."
6395         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE seek=1024 count=1 > /dev/null
6396         losetup $loopdev $DIR/$tfile ||
6397                 error "can't set up $loopdev for $DIR/$tfile"
6398         mkfs.ext2 $loopdev || error "mke2fs on $loopdev"
6399         test_mkdir $DIR/$tdir
6400         mount -t ext2 $loopdev $DIR/$tdir ||
6401                 error "error mounting $loopdev on $DIR/$tdir"
6402         dd if=/dev/zero of=$DIR/$tdir/tmp bs=$PAGE_SIZE count=30 ||
6403                 error "dd write"
6404         df $DIR/$tdir
6405         dd if=$DIR/$tdir/tmp of=/dev/zero bs=$PAGE_SIZE count=30 ||
6406                 error "dd read"
6407         cleanup_54c
6408 }
6409 run_test 54c "block device works in lustre ====================="
6410
6411 test_54d() {
6412         local pipe="$DIR/$tfile.pipe"
6413         local string="aaaaaa"
6414
6415         mknod $pipe p
6416         echo -n "$string" > $pipe &
6417         local result=$(cat $pipe)
6418         [[ "$result" == "$string" ]] || error "$result != $string"
6419 }
6420 run_test 54d "fifo device works in lustre ======================"
6421
6422 test_54e() {
6423         f="$DIR/f54e"
6424         string="aaaaaa"
6425         cp -aL /dev/console $f
6426         echo $string > $f || error "echo $string to $f failed"
6427 }
6428 run_test 54e "console/tty device works in lustre ======================"
6429
6430 test_55a() {
6431         local dev_path="/sys/kernel/debug/lustre/devices"
6432
6433         load_module kunit/obd_test verbose=2 || error "load_module failed"
6434
6435         # This must be run in iteractive mode, since attach and setup
6436         # are stateful
6437         eval "$LCTL <<-EOF || error 'OBD device creation failed'
6438                 attach obd_test obd_name obd_uuid
6439                 setup obd_test
6440         EOF"
6441
6442         echo "Devices:"
6443         cat "$dev_path" | tail -n 10
6444
6445         $LCTL --device "obd_name" cleanup
6446         $LCTL --device "obd_name" detach
6447
6448         dmesg | tail -n 25 | grep "Lustre: OBD:.*FAIL" &&
6449                 error "OBD unit test failed"
6450
6451         rmmod -v obd_test ||
6452                 error "rmmod failed (may trigger a failure in a later test)"
6453 }
6454 run_test 55a "OBD device life cycle unit tests"
6455
6456 test_55b() {
6457         local dev_path="/sys/kernel/debug/lustre/devices"
6458         local dev_count="$(wc -l $dev_path | awk '{print $1}')"
6459
6460         # Set up a large number of devices, using the number
6461         # that can be set up in about a minute (based on prior
6462         # testing). We don't want to run this test forever.
6463         local num_dev_to_create="$(( 24000 - $dev_count))"
6464
6465         load_module kunit/obd_test || error "load_module failed"
6466
6467         local start=$SECONDS
6468
6469         # This must be run in iteractive mode, since attach and setup
6470         # are stateful
6471         for ((i = 1; i <= num_dev_to_create; i++)); do
6472                 echo "attach obd_test obd_name_$i obd_uuid_$i"
6473                 echo "setup obd_test_$i"
6474         done | $LCTL || error "OBD device creation failed"
6475
6476         echo "Load time: $((SECONDS - start))"
6477         echo "Devices:"
6478         cat "$dev_path" | tail -n 10
6479
6480         for ((i = 1; i <= num_dev_to_create; i++)); do
6481                 echo "--device obd_name_$i cleanup"
6482                 echo "--device obd_name_$i detach"
6483         done | $LCTL || error "OBD device cleanup failed"
6484
6485         echo "Unload time: $((SECONDS - start))"
6486
6487         rmmod -v obd_test ||
6488                 error "rmmod failed (may trigger a failure in a later test)"
6489 }
6490 run_test 55b "Load and unload max OBD devices"
6491
6492 test_56a() {
6493         local numfiles=3
6494         local numdirs=2
6495         local dir=$DIR/$tdir
6496
6497         rm -rf $dir
6498         test_mkdir -p $dir/dir
6499         for i in $(seq $numfiles); do
6500                 touch $dir/file$i
6501                 touch $dir/dir/file$i
6502         done
6503
6504         local numcomp=$($LFS getstripe --component-count $dir)
6505
6506         [[ $numcomp == 0 ]] && numcomp=1
6507
6508         # test lfs getstripe with --recursive
6509         local filenum=$($LFS getstripe -r $dir | egrep -c "obdidx|l_ost_idx")
6510
6511         [[ $filenum -eq $((numfiles * 2)) ]] ||
6512                 error "$LFS getstripe -r: found $filenum != $((numfiles * 2))"
6513         filenum=$($LFS getstripe $dir | egrep -c "obdidx|l_ost_idx")
6514         [[ $filenum -eq $numfiles ]] ||
6515                 error "$LFS getstripe $dir: found $filenum, not $numfiles"
6516         echo "$LFS getstripe showed obdidx or l_ost_idx"
6517
6518         # test lfs getstripe with file instead of dir
6519         filenum=$($LFS getstripe $dir/file1 | egrep -c "obdidx|l_ost_idx")
6520         [[ $filenum -eq 1 ]] ||
6521                 error "$LFS getstripe $dir/file1: found $filenum, not 1"
6522         echo "$LFS getstripe file1 passed"
6523
6524         #test lfs getstripe with --verbose
6525         filenum=$($LFS getstripe --verbose $dir | grep -c lmm_magic)
6526         [[ $filenum -eq $((numfiles * numcomp)) ]] ||
6527                 error "$LFS getstripe --verbose $dir: "\
6528                       "got $filenum want $((numfiles * numcomp)) lmm_magic"
6529         [[ $($LFS getstripe $dir | grep -c lmm_magic) -eq 0 ]] ||
6530                 error "$LFS getstripe $dir: showed lmm_magic"
6531
6532         #test lfs getstripe with -v prints lmm_fid
6533         filenum=$($LFS getstripe -v $dir | grep -c lmm_fid)
6534         local countfids=$((numdirs + numfiles * numcomp))
6535         [[ $filenum -eq $countfids ]] ||
6536                 error "$LFS getstripe -v $dir: "\
6537                       "got $filenum want $countfids lmm_fid"
6538         [[ $($LFS getstripe $dir | grep -c lmm_fid) -eq 0 ]] ||
6539                 error "$LFS getstripe $dir: showed lmm_fid by default"
6540         echo "$LFS getstripe --verbose passed"
6541
6542         #check for FID information
6543         local fid1=$($LFS getstripe --fid $dir/file1)
6544         local fid2=$($LFS getstripe --verbose $dir/file1 |
6545                      awk '/lmm_fid: / { print $2; exit; }')
6546         local fid3=$($LFS path2fid $dir/file1)
6547
6548         [ "$fid1" != "$fid2" ] &&
6549                 error "getstripe --fid '$fid1' != getstripe --verbose '$fid2'"
6550         [ "$fid1" != "$fid3" ] &&
6551                 error "getstripe --fid '$fid1' != lfs path2fid '$fid3'"
6552         echo "$LFS getstripe --fid passed"
6553
6554         #test lfs getstripe with --obd
6555         $LFS getstripe --obd wrong_uuid $dir 2>&1 | grep -q "unknown obduuid" ||
6556                 error "$LFS getstripe --obd wrong_uuid: should return error"
6557
6558         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
6559
6560         local ostidx=1
6561         local obduuid=$(ostuuid_from_index $ostidx)
6562         local found=$($LFS getstripe -r --obd $obduuid $dir |
6563                 grep 'lmm_stripe_offset:' | grep -c " $ostidx\$")
6564
6565         filenum=$($LFS getstripe -ir $dir | grep -c "^$ostidx\$")
6566         [[ $($LFS getstripe -id $dir) -ne $ostidx ]] ||
6567                 ((filenum--))
6568         [[ $($LFS getstripe -id $dir/dir) -ne $ostidx ]] ||
6569                 ((filenum--))
6570
6571         [[ $found -eq $filenum ]] ||
6572                 error "$LFS getstripe --obd: found $found expect $filenum"
6573         [[ $($LFS getstripe -r -v --obd $obduuid $dir |
6574                 sed '/^[         ]*'${ostidx}'[  ]/d' |
6575                 sed -n '/^[      ]*[0-9][0-9]*[  ]/p' | wc -l) -eq 0 ]] ||
6576                 error "$LFS getstripe --obd: should not show file on other obd"
6577         echo "$LFS getstripe --obd passed"
6578 }
6579 run_test 56a "check $LFS getstripe"
6580
6581 test_56b() {
6582         local dir=$DIR/$tdir
6583         local numdirs=3
6584
6585         test_mkdir $dir
6586         for i in $(seq $numdirs); do
6587                 test_mkdir $dir/dir$i
6588         done
6589
6590         # test lfs getdirstripe default mode is non-recursion, which is
6591         # different from lfs getstripe
6592         local dircnt=$($LFS getdirstripe $dir | grep -c lmv_stripe_count)
6593
6594         [[ $dircnt -eq 1 ]] ||
6595                 error "$LFS getdirstripe: found $dircnt, not 1"
6596         dircnt=$($LFS getdirstripe --recursive $dir |
6597                 grep -c lmv_stripe_count)
6598         [[ $dircnt -eq $((numdirs + 1)) ]] ||
6599                 error "$LFS getdirstripe -r: $dircnt, != $((numdirs + 1))"
6600 }
6601 run_test 56b "check $LFS getdirstripe"
6602
6603 test_56bb() {
6604         verify_yaml_available || skip_env "YAML verification not installed"
6605         local output_file=$DIR/$tfile.out
6606
6607         $LFS getdirstripe -v -D -y $DIR 1> $output_file
6608
6609         cat $output_file
6610         cat $output_file | verify_yaml || error "layout is not valid YAML"
6611 }
6612 run_test 56bb "check $LFS getdirstripe layout is YAML"
6613
6614 test_56c() {
6615         remote_ost_nodsh && skip "remote OST with nodsh"
6616
6617         local ost_idx=0
6618         local ost_name=$(ostname_from_index $ost_idx)
6619         local old_status=$(ost_dev_status $ost_idx)
6620         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
6621
6622         [[ -z "$old_status" ]] ||
6623                 skip_env "OST $ost_name is in $old_status status"
6624
6625         do_facet ost1 $LCTL set_param -n obdfilter.$ost_name.degraded=1
6626         [[ $OST1_VERSION -lt $(version_code 2.12.55) ]] || do_facet ost1 \
6627                 $LCTL set_param -n obdfilter.$ost_name.no_precreate=1
6628         if [[ $OST1_VERSION -ge $(version_code 2.12.57) ]]; then
6629                 save_lustre_params ost1 osd-*.$ost_name.nonrotational > $p
6630                 do_facet ost1 $LCTL set_param -n osd-*.$ost_name.nonrotational=1
6631         fi
6632
6633         [[ $($LFS df -v $MOUNT |& grep -c "inactive device") -eq 0 ]] ||
6634                 error "$LFS df -v showing inactive devices"
6635         sleep_maxage
6636
6637         local new_status=$(ost_dev_status $ost_idx $MOUNT -v)
6638
6639         [[ "$new_status" =~ "D" ]] ||
6640                 error "$ost_name status is '$new_status', missing 'D'"
6641         if [[ $OST1_VERSION -ge $(version_code 2.12.55) ]]; then
6642                 [[ "$new_status" =~ "N" ]] ||
6643                         error "$ost_name status is '$new_status', missing 'N'"
6644         fi
6645         if [[ $OST1_VERSION -ge $(version_code 2.12.57) ]]; then
6646                 [[ "$new_status" =~ "f" ]] ||
6647                         error "$ost_name status is '$new_status', missing 'f'"
6648         fi
6649
6650         do_facet ost1 $LCTL set_param -n obdfilter.$ost_name.degraded=0
6651         [[ $OST1_VERSION -lt $(version_code 2.12.55) ]] || do_facet ost1 \
6652                 $LCTL set_param -n obdfilter.$ost_name.no_precreate=0
6653         [[ -z "$p" ]] && restore_lustre_params < $p || true
6654         sleep_maxage
6655
6656         new_status=$(ost_dev_status $ost_idx)
6657         [[ ! "$new_status" =~ "D" && ! "$new_status" =~ "N" ]] ||
6658                 error "$ost_name status is '$new_status', has 'D' and/or 'N'"
6659         # can't check 'f' as devices may actually be on flash
6660 }
6661 run_test 56c "check 'lfs df' showing device status"
6662
6663 test_56d() {
6664         local mdts=$($LFS df -v $MOUNT | grep -c MDT)
6665         local osts=$($LFS df -v $MOUNT | grep -c OST)
6666
6667         $LFS df $MOUNT
6668
6669         (( mdts == MDSCOUNT )) ||
6670                 error "lfs df -v showed $mdts MDTs, not $MDSCOUNT"
6671         (( osts == OSTCOUNT )) ||
6672                 error "lfs df -v showed $osts OSTs, not $OSTCOUNT"
6673 }
6674 run_test 56d "'lfs df -v' prints only configured devices"
6675
6676 test_56e() {
6677         err_enoent=2 # No such file or directory
6678         err_eopnotsupp=95 # Operation not supported
6679
6680         enoent_mnt=/pmt1 # Invalid dentry. Path not present
6681         notsup_mnt=/tmp  # Valid dentry, but Not a lustreFS
6682
6683         # Check for handling of path not exists
6684         output=$($LFS df $enoent_mnt 2>&1)
6685         ret=$?
6686
6687         fs=$(echo $output | awk -F: '{print $2}' | awk '{print $3}' | tr -d \')
6688         [[ $fs = $enoent_mnt && $ret -eq $err_enoent ]] ||
6689                 error "expect failure $err_enoent, not $ret"
6690
6691         # Check for handling of non-Lustre FS
6692         output=$($LFS df $notsup_mnt)
6693         ret=$?
6694
6695         fs=$(echo $output | awk '{print $1}' | awk -F: '{print $2}')
6696         [[ $fs = $notsup_mnt && $ret -eq $err_eopnotsupp ]] ||
6697                 error "expect success $err_eopnotsupp, not $ret"
6698
6699         # Check for multiple LustreFS argument
6700         output=$($LFS df $MOUNT $MOUNT $MOUNT | grep -c "filesystem_summary:")
6701         ret=$?
6702
6703         [[ $output -eq 3 && $ret -eq 0 ]] ||
6704                 error "expect success 3, not $output, rc = $ret"
6705
6706         # Check for correct non-Lustre FS handling among multiple
6707         # LustreFS argument
6708         output=$($LFS df $MOUNT $notsup_mnt $MOUNT |
6709                 grep -c "filesystem_summary:"; exit ${PIPESTATUS[0]})
6710         ret=$?
6711
6712         [[ $output -eq 2 && $ret -eq $err_eopnotsupp ]] ||
6713                 error "expect success 2, not $output, rc = $ret"
6714 }
6715 run_test 56e "'lfs df' Handle non LustreFS & multiple LustreFS"
6716
6717 NUMFILES=3
6718 NUMDIRS=3
6719 setup_56() {
6720         local local_tdir="$1"
6721         local local_numfiles="$2"
6722         local local_numdirs="$3"
6723         local dir_params="$4"
6724         local dir_stripe_params="$5"
6725
6726         if [ ! -d "$local_tdir" ] ; then
6727                 test_mkdir -p $dir_stripe_params $local_tdir
6728                 [ "$dir_params" ] && $LFS setstripe $dir_params $local_tdir
6729                 for i in $(seq $local_numfiles) ; do
6730                         touch $local_tdir/file$i
6731                 done
6732                 for i in $(seq $local_numdirs) ; do
6733                         test_mkdir $dir_stripe_params $local_tdir/dir$i
6734                         for j in $(seq $local_numfiles) ; do
6735                                 touch $local_tdir/dir$i/file$j
6736                         done
6737                 done
6738         fi
6739 }
6740
6741 setup_56_special() {
6742         local local_tdir=$1
6743         local local_numfiles=$2
6744         local local_numdirs=$3
6745
6746         setup_56 $local_tdir $local_numfiles $local_numdirs
6747
6748         if [ ! -e "$local_tdir/loop${local_numfiles}b" ] ; then
6749                 for i in $(seq $local_numfiles) ; do
6750                         mknod $local_tdir/loop${i}b b 7 $i
6751                         mknod $local_tdir/null${i}c c 1 3
6752                         ln -s $local_tdir/file1 $local_tdir/link${i}
6753                 done
6754                 for i in $(seq $local_numdirs) ; do
6755                         mknod $local_tdir/dir$i/loop${i}b b 7 $i
6756                         mknod $local_tdir/dir$i/null${i}c c 1 3
6757                         ln -s $local_tdir/dir$i/file1 $local_tdir/dir$i/link${i}
6758                 done
6759         fi
6760 }
6761
6762 test_56g() {
6763         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6764         local expected=$(($NUMDIRS + 2))
6765
6766         setup_56 $dir $NUMFILES $NUMDIRS
6767
6768         # test lfs find with -name
6769         for i in $(seq $NUMFILES) ; do
6770                 local nums=$($LFS find -name "*$i" $dir | wc -l)
6771
6772                 [ $nums -eq $expected ] ||
6773                         error "lfs find -name '*$i' $dir wrong: "\
6774                               "found $nums, expected $expected"
6775         done
6776 }
6777 run_test 56g "check lfs find -name"
6778
6779 test_56h() {
6780         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6781         local expected=$(((NUMDIRS + 1) * (NUMFILES - 1) + NUMFILES))
6782
6783         setup_56 $dir $NUMFILES $NUMDIRS
6784
6785         # test lfs find with ! -name
6786         for i in $(seq $NUMFILES) ; do
6787                 local nums=$($LFS find ! -name "*$i" $dir | wc -l)
6788
6789                 [ $nums -eq $expected ] ||
6790                         error "lfs find ! -name '*$i' $dir wrong: "\
6791                               "found $nums, expected $expected"
6792         done
6793 }
6794 run_test 56h "check lfs find ! -name"
6795
6796 test_56i() {
6797         local dir=$DIR/$tdir
6798
6799         test_mkdir $dir
6800
6801         local cmd="$LFS find -ost $(ostuuid_from_index 0 $dir) $dir"
6802         local out=$($cmd)
6803
6804         [ -z "$out" ] || error "'$cmd' returned directory '$out'"
6805 }
6806 run_test 56i "check 'lfs find -ost UUID' skips directories"
6807
6808 test_56j() {
6809         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6810
6811         setup_56_special $dir $NUMFILES $NUMDIRS
6812
6813         local expected=$((NUMDIRS + 1))
6814         local cmd="$LFS find -type d $dir"
6815         local nums=$($cmd | wc -l)
6816
6817         [ $nums -eq $expected ] ||
6818                 error "'$cmd' wrong: found $nums, expected $expected"
6819 }
6820 run_test 56j "check lfs find -type d"
6821
6822 test_56k() {
6823         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6824
6825         setup_56_special $dir $NUMFILES $NUMDIRS
6826
6827         local expected=$(((NUMDIRS + 1) * NUMFILES))
6828         local cmd="$LFS find -type f $dir"
6829         local nums=$($cmd | wc -l)
6830
6831         [ $nums -eq $expected ] ||
6832                 error "'$cmd' wrong: found $nums, expected $expected"
6833 }
6834 run_test 56k "check lfs find -type f"
6835
6836 test_56l() {
6837         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6838
6839         setup_56_special $dir $NUMFILES $NUMDIRS
6840
6841         local expected=$((NUMDIRS + NUMFILES))
6842         local cmd="$LFS find -type b $dir"
6843         local nums=$($cmd | wc -l)
6844
6845         [ $nums -eq $expected ] ||
6846                 error "'$cmd' wrong: found $nums, expected $expected"
6847 }
6848 run_test 56l "check lfs find -type b"
6849
6850 test_56m() {
6851         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6852
6853         setup_56_special $dir $NUMFILES $NUMDIRS
6854
6855         local expected=$((NUMDIRS + NUMFILES))
6856         local cmd="$LFS find -type c $dir"
6857         local nums=$($cmd | wc -l)
6858         [ $nums -eq $expected ] ||
6859                 error "'$cmd' wrong: found $nums, expected $expected"
6860 }
6861 run_test 56m "check lfs find -type c"
6862
6863 test_56n() {
6864         local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
6865         setup_56_special $dir $NUMFILES $NUMDIRS
6866
6867         local expected=$((NUMDIRS + NUMFILES))
6868         local cmd="$LFS find -type l $dir"
6869         local nums=$($cmd | wc -l)
6870
6871         [ $nums -eq $expected ] ||
6872                 error "'$cmd' wrong: found $nums, expected $expected"
6873 }
6874 run_test 56n "check lfs find -type l"
6875
6876 test_56o() {
6877         local dir=$DIR/$tdir
6878
6879         setup_56 $dir $NUMFILES $NUMDIRS
6880         utime $dir/file1 > /dev/null || error "utime (1)"
6881         utime $dir/file2 > /dev/null || error "utime (2)"
6882         utime $dir/dir1 > /dev/null || error "utime (3)"
6883         utime $dir/dir2 > /dev/null || error "utime (4)"
6884         utime $dir/dir1/file1 > /dev/null || error "utime (5)"
6885         dd if=/dev/zero count=1 >> $dir/dir1/file1 && sync
6886
6887         local expected=4
6888         local nums=$($LFS find -mtime +0 $dir | wc -l)
6889
6890         [ $nums -eq $expected ] ||
6891                 error "lfs find -mtime +0 $dir: found $nums expect $expected"
6892
6893         expected=12
6894         cmd="$LFS find -mtime 0 $dir"
6895         nums=$($cmd | wc -l)
6896         [ $nums -eq $expected ] ||
6897                 error "'$cmd' wrong: found $nums, expected $expected"
6898 }
6899 run_test 56o "check lfs find -mtime for old files"
6900
6901 test_56ob() {
6902         local dir=$DIR/$tdir
6903         local expected=1
6904         local count=0
6905
6906         # just to make sure there is something that won't be found
6907         test_mkdir $dir
6908         touch $dir/$tfile.now
6909
6910         for age in year week day hour min; do
6911                 count=$((count + 1))
6912
6913                 touch $dir/$tfile-a.$age $dir/$tfile-m.$age
6914                 touch --date="$count $age ago" -a $dir/$tfile-a.$age
6915                 touch --date="$count $age ago" -m $dir/$tfile-m.$age
6916
6917                 local cmd="$LFS find $dir -mtime $count${age:0:1}"
6918                 local nums=$($cmd | wc -l)
6919                 [ $nums -eq $expected ] ||
6920                         error "'$cmd' wrong: found $nums, expected $expected"
6921
6922                 cmd="$LFS find $dir -atime $count${age:0:1}"
6923                 nums=$($cmd | wc -l)
6924                 [ $nums -eq $expected ] ||
6925                         error "'$cmd' wrong: found $nums, expected $expected"
6926         done
6927
6928         sleep 2
6929         cmd="$LFS find $dir -ctime +1s -type f"
6930         nums=$($cmd | wc -l)
6931         (( $nums == $count * 2 + 1)) ||
6932                 error "'$cmd' wrong: found $nums, expected $((count * 2 + 1))"
6933 }
6934 run_test 56ob "check lfs find -atime -mtime -ctime with units"
6935
6936 test_newerXY_base() {
6937         local x=$1
6938         local y=$2
6939         local dir=$DIR/$tdir
6940         local ref
6941         local negref
6942
6943         if [ $y == "t" ]; then
6944                 if [ $x == "b" ]; then
6945                         ref=\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\"
6946                 else
6947                         ref=\"$(date +"%Y-%m-%d %H:%M:%S")\"
6948                 fi
6949         else
6950                 ref=$DIR/$tfile.newer.$x$y
6951                 touch $ref || error "touch $ref failed"
6952         fi
6953
6954         echo "before = $ref"
6955         sleep 2
6956         setup_56 $dir $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
6957         sleep 2
6958         if [ $y == "t" ]; then
6959                 if [ $x == "b" ]; then
6960                         negref=\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\"
6961                 else
6962                         negref=\"$(date +"%Y-%m-%d %H:%M:%S")\"
6963                 fi
6964         else
6965                 negref=$DIR/$tfile.negnewer.$x$y
6966                 touch $negref || error "touch $negref failed"
6967         fi
6968
6969         echo "after = $negref"
6970         local cmd="$LFS find $dir -newer$x$y $ref"
6971         local nums=$(eval $cmd | wc -l)
6972         local expected=$(((NUMFILES + 2) * NUMDIRS + 1))
6973
6974         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
6975                 error "'$cmd' wrong: found $nums newer, expected $expected"  ; }
6976
6977         cmd="$LFS find $dir ! -newer$x$y $negref"
6978         nums=$(eval $cmd | wc -l)
6979         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
6980                 error "'$cmd' wrong: found $nums older, expected $expected"  ; }
6981
6982         cmd="$LFS find $dir -newer$x$y $ref ! -newer$x$y $negref"
6983         nums=$(eval $cmd | wc -l)
6984         [ $nums -eq $expected ] || { ls -lauR --full-time $dir ;
6985                 error "'$cmd' wrong: found $nums between, expected $expected"; }
6986
6987         rm -rf $DIR/*
6988 }
6989
6990 test_56oc() {
6991         test_newerXY_base "a" "a"
6992         test_newerXY_base "a" "m"
6993         test_newerXY_base "a" "c"
6994         test_newerXY_base "m" "a"
6995         test_newerXY_base "m" "m"
6996         test_newerXY_base "m" "c"
6997         test_newerXY_base "c" "a"
6998         test_newerXY_base "c" "m"
6999         test_newerXY_base "c" "c"
7000
7001         test_newerXY_base "a" "t"
7002         test_newerXY_base "m" "t"
7003         test_newerXY_base "c" "t"
7004
7005         (( $MDS1_VERSION >= $(version_code v2_13_53-145-g186b97e68a) &&
7006            $CLIENT_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7007                 { echo "btime needs v2_13_53-145-g186b97e68a"; return 0; }
7008
7009         test_newerXY_base "b" "b"
7010         test_newerXY_base "b" "t"
7011 }
7012 run_test 56oc "check lfs find -newerXY work"
7013
7014 test_56od() {
7015         (( $MDS1_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7016                 skip "btime unsupported on MDS < v2_13_53-145-g186b97e68a"
7017
7018         (( $CLIENT_VERSION >= $(version_code v2_13_53-145-g186b97e68a) )) ||
7019                 skip "btime unsupported on clients < v2_13_53-145-g186b97e68a"
7020
7021         local dir=$DIR/$tdir
7022         local ref=$DIR/$tfile.ref
7023         local negref=$DIR/$tfile.negref
7024
7025         mkdir $dir || error "mkdir $dir failed"
7026         touch $dir/$tfile.n1 || error "touch $dir/$tfile.n1 failed"
7027         touch $dir/$tfile.n2 || error "touch $dir/$tfile.n2 failed"
7028         mkdir $dir/$tdir.n1 || error "mkdir $dir/$tdir.n1 failed"
7029         mkdir $dir/$tdir.n2 || error "mkdir $dir/$tdir.n2 failed"
7030         touch $ref || error "touch $ref failed"
7031         # sleep 3 seconds at least
7032         sleep 3
7033
7034         local before=$(do_facet mds1 date +%s)
7035         local skew=$(($(date +%s) - before + 1))
7036
7037         if (( skew < 0 && skew > -5 )); then
7038                 sleep $((0 - skew + 1))
7039                 skew=0
7040         fi
7041
7042         # Set the dir stripe params to limit files all on MDT0,
7043         # otherwise we need to calc the max clock skew between
7044         # the client and MDTs.
7045         setup_56 $dir/d.btime $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
7046         sleep 2
7047         touch $negref || error "touch $negref failed"
7048
7049         local cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type f"
7050         local nums=$($cmd | wc -l)
7051         local expected=$(((NUMFILES + 1) * NUMDIRS))
7052
7053         [ $nums -eq $expected ] ||
7054                 error "'$cmd' wrong: found $nums, expected $expected"
7055
7056         cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type d"
7057         nums=$($cmd | wc -l)
7058         expected=$((NUMFILES + 1))
7059         [ $nums -eq $expected ] ||
7060                 error "'$cmd' wrong: found $nums, expected $expected"
7061
7062         [ $skew -lt 0 ] && return
7063
7064         local after=$(do_facet mds1 date +%s)
7065         local age=$((after - before + 1 + skew))
7066
7067         cmd="$LFS find $dir -btime -${age}s -type f"
7068         nums=$($cmd | wc -l)
7069         expected=$(((NUMFILES + 1) * NUMDIRS))
7070
7071         echo "Clock skew between client and server: $skew, age:$age"
7072         [ $nums -eq $expected ] ||
7073                 error "'$cmd' wrong: found $nums, expected $expected"
7074
7075         expected=$(($NUMDIRS + 1))
7076         cmd="$LFS find $dir -btime -${age}s -type d"
7077         nums=$($cmd | wc -l)
7078         [ $nums -eq $expected ] ||
7079                 error "'$cmd' wrong: found $nums, expected $expected"
7080         rm -f $ref $negref || error "Failed to remove $ref $negref"
7081 }
7082 run_test 56od "check lfs find -btime with units"
7083
7084 test_56p() {
7085         [ $RUNAS_ID -eq $UID ] &&
7086                 skip_env "RUNAS_ID = UID = $UID -- skipping"
7087
7088         local dir=$DIR/$tdir
7089
7090         setup_56 $dir $NUMFILES $NUMDIRS
7091         chown $RUNAS_ID $dir/file* || error "chown $DIR/${tdir}g/file$i failed"
7092
7093         local expected=$NUMFILES
7094         local cmd="$LFS find -uid $RUNAS_ID $dir"
7095         local nums=$($cmd | wc -l)
7096
7097         [ $nums -eq $expected ] ||
7098                 error "'$cmd' wrong: found $nums, expected $expected"
7099
7100         expected=$(((NUMFILES + 1) * NUMDIRS + 1))
7101         cmd="$LFS find ! -uid $RUNAS_ID $dir"
7102         nums=$($cmd | wc -l)
7103         [ $nums -eq $expected ] ||
7104                 error "'$cmd' wrong: found $nums, expected $expected"
7105 }
7106 run_test 56p "check lfs find -uid and ! -uid"
7107
7108 test_56q() {
7109         [ $RUNAS_ID -eq $UID ] &&
7110                 skip_env "RUNAS_ID = UID = $UID -- skipping"
7111
7112         local dir=$DIR/$tdir
7113
7114         setup_56 $dir $NUMFILES $NUMDIRS
7115         chgrp $RUNAS_GID $dir/file* || error "chown $dir/file$i failed"
7116
7117         local expected=$NUMFILES
7118         local cmd="$LFS find -gid $RUNAS_GID $dir"
7119         local nums=$($cmd | wc -l)
7120
7121         [ $nums -eq $expected ] ||
7122                 error "'$cmd' wrong: found $nums, expected $expected"
7123
7124         expected=$(( ($NUMFILES+1) * $NUMDIRS + 1))
7125         cmd="$LFS find ! -gid $RUNAS_GID $dir"
7126         nums=$($cmd | wc -l)
7127         [ $nums -eq $expected ] ||
7128                 error "'$cmd' wrong: found $nums, expected $expected"
7129 }
7130 run_test 56q "check lfs find -gid and ! -gid"
7131
7132 test_56r() {
7133         local dir=$DIR/$tdir
7134
7135         setup_56 $dir $NUMFILES $NUMDIRS
7136
7137         local expected=12
7138         local cmd="$LFS find -size 0 -type f -lazy $dir"
7139         local nums=$($cmd | wc -l)
7140
7141         [ $nums -eq $expected ] ||
7142                 error "'$cmd' wrong: found $nums, expected $expected"
7143         cmd="$LFS find -size 0 -type f $dir"
7144         nums=$($cmd | wc -l)
7145         [ $nums -eq $expected ] ||
7146                 error "'$cmd' wrong: found $nums, expected $expected"
7147
7148         expected=0
7149         cmd="$LFS find ! -size 0 -type f -lazy $dir"
7150         nums=$($cmd | wc -l)
7151         [ $nums -eq $expected ] ||
7152                 error "'$cmd' wrong: found $nums, expected $expected"
7153         cmd="$LFS find ! -size 0 -type f $dir"
7154         nums=$($cmd | wc -l)
7155         [ $nums -eq $expected ] ||
7156                 error "'$cmd' wrong: found $nums, expected $expected"
7157
7158         echo "test" > $dir/$tfile
7159         echo "test2" > $dir/$tfile.2 && sync
7160         expected=1
7161         cmd="$LFS find -size 5c -type f -lazy $dir"
7162         nums=$($cmd | wc -l)
7163         [ $nums -eq $expected ] ||
7164                 error "'$cmd' wrong: found $nums, expected $expected"
7165         cmd="$LFS find -size 5c -type f $dir"
7166         nums=$($cmd | wc -l)
7167         [ $nums -eq $expected ] ||
7168                 error "'$cmd' wrong: found $nums, expected $expected"
7169
7170         expected=1
7171         cmd="$LFS find -size +5c -type f -lazy $dir"
7172         nums=$($cmd | wc -l)
7173         [ $nums -eq $expected ] ||
7174                 error "'$cmd' wrong: found $nums, expected $expected"
7175         cmd="$LFS find -size +5c -type f $dir"
7176         nums=$($cmd | wc -l)
7177         [ $nums -eq $expected ] ||
7178                 error "'$cmd' wrong: found $nums, expected $expected"
7179
7180         expected=2
7181         cmd="$LFS find -size +0 -type f -lazy $dir"
7182         nums=$($cmd | wc -l)
7183         [ $nums -eq $expected ] ||
7184                 error "'$cmd' wrong: found $nums, expected $expected"
7185         cmd="$LFS find -size +0 -type f $dir"
7186         nums=$($cmd | wc -l)
7187         [ $nums -eq $expected ] ||
7188                 error "'$cmd' wrong: found $nums, expected $expected"
7189
7190         expected=2
7191         cmd="$LFS find ! -size -5c -type f -lazy $dir"
7192         nums=$($cmd | wc -l)
7193         [ $nums -eq $expected ] ||
7194                 error "'$cmd' wrong: found $nums, expected $expected"
7195         cmd="$LFS find ! -size -5c -type f $dir"
7196         nums=$($cmd | wc -l)
7197         [ $nums -eq $expected ] ||
7198                 error "'$cmd' wrong: found $nums, expected $expected"
7199
7200         expected=12
7201         cmd="$LFS find -size -5c -type f -lazy $dir"
7202         nums=$($cmd | wc -l)
7203         [ $nums -eq $expected ] ||
7204                 error "'$cmd' wrong: found $nums, expected $expected"
7205         cmd="$LFS find -size -5c -type f $dir"
7206         nums=$($cmd | wc -l)
7207         [ $nums -eq $expected ] ||
7208                 error "'$cmd' wrong: found $nums, expected $expected"
7209 }
7210 run_test 56r "check lfs find -size works"
7211
7212 test_56ra_sub() {
7213         local expected=$1
7214         local glimpses=$2
7215         local cmd="$3"
7216
7217         cancel_lru_locks $OSC
7218
7219         local rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
7220         local nums=$($cmd | wc -l)
7221
7222         [ $nums -eq $expected ] ||
7223                 error "'$cmd' wrong: found $nums, expected $expected"
7224
7225         local rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
7226
7227         if (( rpcs_before + glimpses != rpcs_after )); then
7228                 echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
7229                 $LCTL get_param osc.*.stats | grep ldlm_glimpse_enqueue
7230
7231                 if [[ $glimpses == 0 ]]; then
7232                         error "'$cmd' should not send glimpse RPCs to OST"
7233                 else
7234                         error "'$cmd' should send $glimpses glimpse RPCs to OST"
7235                 fi
7236         fi
7237 }
7238
7239 test_56ra() {
7240         [[ $MDS1_VERSION -gt $(version_code 2.12.58) ]] ||
7241                 skip "MDS < 2.12.58 doesn't return LSOM data"
7242         local dir=$DIR/$tdir
7243         local old_agl=$($LCTL get_param -n llite.*.statahead_agl)
7244
7245         [[ $OSC == "mdc" ]] && skip "statahead not needed for DoM files"
7246
7247         # statahead_agl may cause extra glimpse which confuses results. LU-13017
7248         $LCTL set_param -n llite.*.statahead_agl=0
7249         stack_trap "$LCTL set_param -n llite.*.statahead_agl=$old_agl"
7250
7251         setup_56 $dir $NUMFILES $NUMDIRS "-c 1"
7252         # open and close all files to ensure LSOM is updated
7253         cancel_lru_locks $OSC
7254         find $dir -type f | xargs cat > /dev/null
7255
7256         #   expect_found  glimpse_rpcs  command_to_run
7257         test_56ra_sub 12  0 "$LFS find -size 0 -type f -lazy $dir"
7258         test_56ra_sub 12 12 "$LFS find -size 0 -type f $dir"
7259         test_56ra_sub  0  0 "$LFS find ! -size 0 -type f -lazy $dir"
7260         test_56ra_sub  0 12 "$LFS find ! -size 0 -type f $dir"
7261
7262         echo "test" > $dir/$tfile
7263         echo "test2" > $dir/$tfile.2 && sync
7264         cancel_lru_locks $OSC
7265         cat $dir/$tfile $dir/$tfile.2 > /dev/null
7266
7267         test_56ra_sub  1  0 "$LFS find -size 5c -type f -lazy $dir"
7268         test_56ra_sub  1 14 "$LFS find -size 5c -type f $dir"
7269         test_56ra_sub  1  0 "$LFS find -size +5c -type f -lazy $dir"
7270         test_56ra_sub  1 14 "$LFS find -size +5c -type f $dir"
7271
7272         test_56ra_sub  2  0 "$LFS find -size +0 -type f -lazy $dir"
7273         test_56ra_sub  2 14 "$LFS find -size +0 -type f $dir"
7274         test_56ra_sub  2  0 "$LFS find ! -size -5c -type f -lazy $dir"
7275         test_56ra_sub  2 14 "$LFS find ! -size -5c -type f $dir"
7276         test_56ra_sub 12  0 "$LFS find -size -5c -type f -lazy $dir"
7277         test_56ra_sub 12 14 "$LFS find -size -5c -type f $dir"
7278 }
7279 run_test 56ra "check lfs find -size -lazy works for data on OSTs"
7280
7281 test_56rb() {
7282         local dir=$DIR/$tdir
7283         local tmp=$TMP/$tfile.log
7284         local mdt_idx;
7285
7286         test_mkdir -p $dir || error "failed to mkdir $dir"
7287         $LFS setstripe -c 1 -i 0 $dir/$tfile ||
7288                 error "failed to setstripe $dir/$tfile"
7289         mdt_idx=$($LFS getdirstripe -i $dir)
7290         dd if=/dev/zero of=$dir/$tfile bs=1M count=1
7291
7292         stack_trap "rm -f $tmp" EXIT
7293         $LFS find --size +100K --ost 0 $dir |& tee $tmp
7294         ! grep -q obd_uuid $tmp ||
7295                 error "failed to find --size +100K --ost 0 $dir"
7296         $LFS find --size +100K --mdt $mdt_idx $dir |& tee $tmp
7297         ! grep -q obd_uuid $tmp ||
7298                 error "failed to find --size +100K --mdt $mdt_idx $dir"
7299 }
7300 run_test 56rb "check lfs find --size --ost/--mdt works"
7301
7302 test_56rc() {
7303         (( MDSCOUNT >= 2 )) || skip "needs at least 2 MDTs"
7304         local dir=$DIR/$tdir
7305         local found
7306
7307         test_mkdir -c 2 -H all_char $dir || error "failed to mkdir $dir"
7308         $LFS mkdir -c 2 --mdt-hash all_char $dir/$tdir-all{1..10}
7309         (( $MDSCOUNT > 2 )) &&
7310                 $LFS mkdir -c 3 --mdt-hash fnv_1a_64 $dir/$tdir-fnv{1..10}
7311         mkdir $dir/$tdir-{1..10}
7312         touch $dir/$tfile-{1..10}
7313
7314         found=$($LFS find $dir --mdt-count 2 | wc -l)
7315         expect=11
7316         (( $found == $expect )) || error "found $found 2-stripe, expect $expect"
7317
7318         found=$($LFS find $dir -T +1 | wc -l)
7319         (( $MDSCOUNT > 2 )) && expect=$((expect + 10))
7320         (( $found == $expect )) || error "found $found 2+stripe, expect $expect"
7321
7322         found=$($LFS find $dir --mdt-hash all_char | wc -l)
7323         expect=11
7324         (( $found == $expect )) || error "found $found all_char, expect $expect"
7325
7326         found=$($LFS find $dir --mdt-hash fnv_1a_64 | wc -l)
7327         (( $MDSCOUNT > 2 )) && expect=10 || expect=0
7328         (( $found == $expect )) || error "found $found all_char, expect $expect"
7329 }
7330 run_test 56rc "check lfs find --mdt-count/--mdt-hash works"
7331
7332 test_56rd() {
7333         local dir=$DIR/$tdir
7334
7335         test_mkdir $dir
7336         rm -f $dir/*
7337
7338         mkfifo $dir/fifo || error "failed to create fifo file"
7339         $LFS find $dir -t p --printf "%p %y %LP\n" ||
7340                 error "should not fail even cannot get projid from pipe file"
7341         found=$($LFS find $dir -t p --printf "%y")
7342         [[ "p" == $found ]] || error "found $found, expect p"
7343
7344         mknod $dir/chardev c 1 5 ||
7345                 error "failed to create character device file"
7346         $LFS find $dir -t c --printf "%p %y %LP\n" ||
7347                 error "should not fail even cannot get projid from chardev file"
7348         found=$($LFS find $dir -t c --printf "%y")
7349         [[ "c" == $found ]] || error "found $found, expect c"
7350
7351         found=$($LFS find $dir ! -type d --printf "%p %y %LP\n" | wc -l)
7352         (( found == 2 )) || error "unable to list all files"
7353 }
7354 run_test 56rd "check lfs find --printf special files"
7355
7356 test_56s() { # LU-611 #LU-9369
7357         [[ $OSTCOUNT -lt 2 ]] && skip_env "need at least 2 OSTs"
7358
7359         local dir=$DIR/$tdir
7360         local onestripe=$(((NUMDIRS + 1) * NUMFILES))
7361
7362         setup_56 $dir $NUMFILES $NUMDIRS "-c 1"
7363         for i in $(seq $NUMDIRS); do
7364                 $LFS setstripe -c $((OSTCOUNT + 1)) $dir/dir$i/$tfile
7365         done
7366
7367         local expected=$NUMDIRS
7368         local cmd="$LFS find -c $OSTCOUNT $dir"
7369         local nums=$($cmd | wc -l)
7370
7371         [ $nums -eq $expected ] || {
7372                 $LFS getstripe -R $dir
7373                 error "'$cmd' wrong: found $nums, expected $expected"
7374         }
7375
7376         expected=$((NUMDIRS + onestripe))
7377         cmd="$LFS find -stripe-count +0 -type f $dir"
7378         nums=$($cmd | wc -l)
7379         [ $nums -eq $expected ] || {
7380                 $LFS getstripe -R $dir
7381                 error "'$cmd' wrong: found $nums, expected $expected"
7382         }
7383
7384         expected=$onestripe
7385         cmd="$LFS find -stripe-count 1 -type f $dir"
7386         nums=$($cmd | wc -l)
7387         [ $nums -eq $expected ] || {
7388                 $LFS getstripe -R $dir
7389                 error "'$cmd' wrong: found $nums, expected $expected"
7390         }
7391
7392         cmd="$LFS find -stripe-count -2 -type f $dir"
7393         nums=$($cmd | wc -l)
7394         [ $nums -eq $expected ] || {
7395                 $LFS getstripe -R $dir
7396                 error "'$cmd' wrong: found $nums, expected $expected"
7397         }
7398
7399         expected=0
7400         cmd="$LFS find -stripe-count $((OSTCOUNT + 1)) -type f $dir"
7401         nums=$($cmd | wc -l)
7402         [ $nums -eq $expected ] || {
7403                 $LFS getstripe -R $dir
7404                 error "'$cmd' wrong: found $nums, expected $expected"
7405         }
7406 }
7407 run_test 56s "check lfs find -stripe-count works"
7408
7409 test_56t() { # LU-611 #LU-9369
7410         local dir=$DIR/$tdir
7411
7412         setup_56 $dir 0 $NUMDIRS
7413         for i in $(seq $NUMDIRS); do
7414                 $LFS setstripe -S 8M $dir/dir$i/$tfile
7415         done
7416
7417         local expected=$NUMDIRS
7418         local cmd="$LFS find -S 8M $dir"
7419         local nums=$($cmd | wc -l)
7420
7421         [ $nums -eq $expected ] || {
7422                 $LFS getstripe -R $dir
7423                 error "'$cmd' wrong: found $nums, expected $expected"
7424         }
7425         rm -rf $dir
7426
7427         setup_56 $dir $NUMFILES $NUMDIRS "--stripe-size 512k"
7428
7429         $LFS setstripe -S 256k $dir/$tfile.{0,1,2,3}
7430
7431         expected=$(((NUMDIRS + 1) * NUMFILES))
7432         cmd="$LFS find -stripe-size 512k -type f $dir"
7433         nums=$($cmd | wc -l)
7434         [ $nums -eq $expected ] ||
7435                 error "'$cmd' wrong: found $nums, expected $expected"
7436
7437         cmd="$LFS find -stripe-size +320k -type f $dir"
7438         nums=$($cmd | wc -l)
7439         [ $nums -eq $expected ] ||
7440                 error "'$cmd' wrong: found $nums, expected $expected"
7441
7442         expected=$(((NUMDIRS + 1) * NUMFILES + 4))
7443         cmd="$LFS find -stripe-size +200k -type f $dir"
7444         nums=$($cmd | wc -l)
7445         [ $nums -eq $expected ] ||
7446                 error "'$cmd' wrong: found $nums, expected $expected"
7447
7448         cmd="$LFS find -stripe-size -640k -type f $dir"
7449         nums=$($cmd | wc -l)
7450         [ $nums -eq $expected ] ||
7451                 error "'$cmd' wrong: found $nums, expected $expected"
7452
7453         expected=4
7454         cmd="$LFS find -stripe-size 256k -type f $dir"
7455         nums=$($cmd | wc -l)
7456         [ $nums -eq $expected ] ||
7457                 error "'$cmd' wrong: found $nums, expected $expected"
7458
7459         cmd="$LFS find -stripe-size -320k -type f $dir"
7460         nums=$($cmd | wc -l)
7461         [ $nums -eq $expected ] ||
7462                 error "'$cmd' wrong: found $nums, expected $expected"
7463
7464         expected=0
7465         cmd="$LFS find -stripe-size 1024k -type f $dir"
7466         nums=$($cmd | wc -l)
7467         [ $nums -eq $expected ] ||
7468                 error "'$cmd' wrong: found $nums, expected $expected"
7469 }
7470 run_test 56t "check lfs find -stripe-size works"
7471
7472 test_56u() { # LU-611
7473         local dir=$DIR/$tdir
7474
7475         setup_56 $dir $NUMFILES $NUMDIRS "-i 0 -c 1"
7476
7477         if [[ $OSTCOUNT -gt 1 ]]; then
7478                 $LFS setstripe -i 1 -c 1 $dir/$tfile.{0,1,2,3}
7479                 onestripe=4
7480         else
7481                 onestripe=0
7482         fi
7483
7484         local expected=$(((NUMDIRS + 1) * NUMFILES))
7485         local cmd="$LFS find -stripe-index 0 -type f $dir"
7486         local nums=$($cmd | wc -l)
7487
7488         [ $nums -eq $expected ] ||
7489                 error "'$cmd' wrong: found $nums, expected $expected"
7490
7491         expected=$onestripe
7492         cmd="$LFS find -stripe-index 1 -type f $dir"
7493         nums=$($cmd | wc -l)
7494         [ $nums -eq $expected ] ||
7495                 error "'$cmd' wrong: found $nums, expected $expected"
7496
7497         cmd="$LFS find ! -stripe-index 0 -type f $dir"
7498         nums=$($cmd | wc -l)
7499         [ $nums -eq $expected ] ||
7500                 error "'$cmd' wrong: found $nums, expected $expected"
7501
7502         expected=0
7503         # This should produce an error and not return any files
7504         cmd="$LFS find -stripe-index $OSTCOUNT -type f $dir"
7505         nums=$($cmd 2>/dev/null | wc -l)
7506         [ $nums -eq $expected ] ||
7507                 error "'$cmd' wrong: found $nums, expected $expected"
7508
7509         if [[ $OSTCOUNT -gt 1 ]]; then
7510                 expected=$(((NUMDIRS + 1) * NUMFILES + onestripe))
7511                 cmd="$LFS find -stripe-index 0,1 -type f $dir"
7512                 nums=$($cmd | wc -l)
7513                 [ $nums -eq $expected ] ||
7514                         error "'$cmd' wrong: found $nums, expected $expected"
7515         fi
7516 }
7517 run_test 56u "check lfs find -stripe-index works"
7518
7519 test_56v() {
7520         local mdt_idx=0
7521         local dir=$DIR/$tdir
7522
7523         setup_56 $dir $NUMFILES $NUMDIRS
7524
7525         UUID=$(mdtuuid_from_index $mdt_idx $dir)
7526         [ -z "$UUID" ] && error "mdtuuid_from_index cannot find MDT $mdt_idx"
7527
7528         for file in $($LFS find -m $UUID $dir); do
7529                 file_midx=$($LFS getstripe -m $file)
7530                 [ $file_midx -eq $mdt_idx ] ||
7531                         error "lfs find -m $UUID != getstripe -m $file_midx"
7532         done
7533 }
7534 run_test 56v "check 'lfs find -m match with lfs getstripe -m'"
7535
7536 test_56wa() {
7537         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
7538         [ $PARALLEL == "yes" ] && skip "skip parallel run"
7539
7540         local dir=$DIR/$tdir
7541
7542         setup_56 $dir $NUMFILES $NUMDIRS "-c $OSTCOUNT" "-c1"
7543         stack_trap "rm -rf $dir"
7544
7545         local stripe_size=$($LFS getstripe -S -d $dir) ||
7546                 error "$LFS getstripe -S -d $dir failed"
7547         stripe_size=${stripe_size%% *}
7548
7549         local file_size=$((stripe_size * OSTCOUNT))
7550         local file_num=$((NUMDIRS * NUMFILES + NUMFILES))
7551         local required_space=$((file_num * file_size))
7552         local free_space=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
7553                            head -n1)
7554         (( free_space >= required_space / 1024 )) ||
7555                 skip_env "need $required_space, have $free_space kbytes"
7556
7557         local dd_bs=65536
7558         local dd_count=$((file_size / dd_bs))
7559
7560         # write data into the files
7561         local i
7562         local j
7563         local file
7564
7565         for ((i = 1; i <= NUMFILES; i++ )); do
7566                 file=$dir/file$i
7567                 yes | dd bs=$dd_bs count=$dd_count of=$file &>/dev/null ||
7568                         error "write data into $file failed"
7569         done
7570         for ((i = 1; i <= NUMDIRS; i++ )); do
7571                 for ((j = 1; j <= NUMFILES; j++ )); do
7572                         file=$dir/dir$i/file$j
7573                         yes|dd bs=$dd_bs count=$dd_count of=$file &>/dev/null ||
7574                                 error "write data into $file failed"
7575                 done
7576         done
7577
7578         # $LFS_MIGRATE will fail if hard link migration is unsupported
7579         if (( MDS1_VERSION > $(version_code 2.5.55) )); then
7580                 createmany -l$dir/dir1/file1 $dir/dir1/link 200 ||
7581                         error "creating links to $dir/dir1/file1 failed"
7582         fi
7583
7584         local expected=-1
7585
7586         (( OSTCOUNT <= 1 )) || expected=$((OSTCOUNT - 1))
7587
7588         # lfs_migrate file
7589         local cmd="$LFS_MIGRATE -y -c $expected $dir/file1"
7590
7591         echo "$cmd"
7592         eval $cmd || error "$cmd failed"
7593
7594         check_stripe_count $dir/file1 $expected
7595
7596         if (( $MDS1_VERSION >= $(version_code 2.6.90) )); then
7597                 # lfs_migrate file onto OST 0 if it is on OST 1, or onto
7598                 # OST 1 if it is on OST 0. This file is small enough to
7599                 # be on only one stripe.
7600                 file=$dir/migr_1_ost
7601                 dd bs=$dd_bs count=1 if=/dev/urandom of=$file >/dev/null 2>&1 ||
7602                         error "write data into $file failed"
7603                 local obdidx=$($LFS getstripe -i $file)
7604                 local oldmd5=$(md5sum $file)
7605                 local newobdidx=0
7606
7607                 (( obdidx != 0 )) || newobdidx=1
7608                 cmd="$LFS migrate -i $newobdidx $file"
7609                 echo $cmd
7610                 eval $cmd || error "$cmd failed"
7611
7612                 local realobdix=$($LFS getstripe -i $file)
7613                 local newmd5=$(md5sum $file)
7614
7615                 (( $newobdidx == $realobdix )) ||
7616                         error "new OST is different (was=$obdidx, wanted=$newobdidx, got=$realobdix)"
7617                 [[ "$oldmd5" == "$newmd5" ]] ||
7618                         error "md5sum differ: $oldmd5, $newmd5"
7619         fi
7620
7621         # lfs_migrate dir
7622         cmd="$LFS_MIGRATE -y -c $expected $dir/dir1"
7623         echo "$cmd"
7624         eval $cmd || error "$cmd failed"
7625
7626         for (( j = 1; j <= NUMFILES; j++ )); do
7627                 check_stripe_count $dir/dir1/file$j $expected
7628         done
7629
7630         # lfs_migrate works with lfs find
7631         cmd="$LFS find -stripe_count $OSTCOUNT -type f $dir |
7632              $LFS_MIGRATE -y -c $expected"
7633         echo "$cmd"
7634         eval $cmd || error "$cmd failed"
7635
7636         for (( i = 2; i <= NUMFILES; i++ )); do
7637                 check_stripe_count $dir/file$i $expected
7638         done
7639         for (( i = 2; i <= NUMDIRS; i++ )); do
7640                 for (( j = 1; j <= NUMFILES; j++ )); do
7641                         check_stripe_count $dir/dir$i/file$j $expected
7642                 done
7643         done
7644 }
7645 run_test 56wa "check lfs_migrate -c stripe_count works"
7646
7647 test_56wb() {
7648         local file1=$DIR/$tdir/file1
7649         local create_pool=false
7650         local initial_pool=$($LFS getstripe -p $DIR)
7651         local pool_list=()
7652         local pool=""
7653
7654         echo -n "Creating test dir..."
7655         test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
7656         echo "done."
7657
7658         echo -n "Creating test file..."
7659         touch $file1 || error "cannot create file"
7660         echo "done."
7661
7662         echo -n "Detecting existing pools..."
7663         pool_list=($($LFS pool_list $FSNAME | grep "$FSNAME\." | cut -d. -f2))
7664
7665         if [ ${#pool_list[@]} -gt 0 ]; then
7666                 echo "${pool_list[@]}"
7667                 for thispool in "${pool_list[@]}"; do
7668                         if [[ -z "$initial_pool" ||
7669                               "$initial_pool" != "$thispool" ]]; then
7670                                 pool="$thispool"
7671                                 echo "Using existing pool '$pool'"
7672                                 break
7673                         fi
7674                 done
7675         else
7676                 echo "none detected."
7677         fi
7678         if [ -z "$pool" ]; then
7679                 pool=${POOL:-testpool}
7680                 [ "$initial_pool" = "$pool" ] && pool="testpool2"
7681                 echo -n "Creating pool '$pool'..."
7682                 create_pool=true
7683                 pool_add $pool &> /dev/null ||
7684                         error "pool_add failed"
7685                 echo "done."
7686
7687                 echo -n "Adding target to pool..."
7688                 pool_add_targets $pool 0 0 1 &> /dev/null ||
7689                         error "pool_add_targets failed"
7690                 echo "done."
7691         fi
7692
7693         echo -n "Setting pool using -p option..."
7694         $LFS_MIGRATE -y -q --no-rsync -p $pool $file1 &> /dev/null ||
7695                 error "migrate failed rc = $?"
7696         echo "done."
7697
7698         echo -n "Verifying test file is in pool after migrating..."
7699         [ "$($LFS getstripe -p $file1)" = $pool ] ||
7700                 error "file was not migrated to pool $pool"
7701         echo "done."
7702
7703         echo -n "Removing test file from pool '$pool'..."
7704         # "lfs migrate $file" won't remove the file from the pool
7705         # until some striping information is changed.
7706         $LFS migrate -c 1 $file1 &> /dev/null ||
7707                 error "cannot remove from pool"
7708         [ "$($LFS getstripe -p $file1)" ] &&
7709                 error "pool still set"
7710         echo "done."
7711
7712         echo -n "Setting pool using --pool option..."
7713         $LFS_MIGRATE -y -q --no-rsync --pool $pool $file1 &> /dev/null ||
7714                 error "migrate failed rc = $?"
7715         echo "done."
7716
7717         # Clean up
7718         rm -f $file1
7719         if $create_pool; then
7720                 destroy_test_pools 2> /dev/null ||
7721                         error "destroy test pools failed"
7722         fi
7723 }
7724 run_test 56wb "check lfs_migrate pool support"
7725
7726 test_56wc() {
7727         local file1="$DIR/$tdir/$tfile"
7728         local md5
7729         local parent_ssize
7730         local parent_scount
7731         local cur_ssize
7732         local cur_scount
7733         local orig_ssize
7734         local new_scount
7735         local cur_comp
7736
7737         echo -n "Creating test dir..."
7738         test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
7739         $LFS setstripe -S 1M -c 1 "$DIR/$tdir" &> /dev/null ||
7740                 error "cannot set stripe by '-S 1M -c 1'"
7741         echo "done"
7742
7743         echo -n "Setting initial stripe for test file..."
7744         $LFS setstripe -S 512K -c 1 "$file1" &> /dev/null ||
7745                 error "cannot set stripe"
7746         cur_ssize=$($LFS getstripe -S "$file1")
7747         (( cur_ssize == 524288 )) || error "setstripe -S $cur_ssize != 524288"
7748         echo "done."
7749
7750         dd if=/dev/urandom of=$file1 bs=1M count=12 || error "dd $file1 failed"
7751         stack_trap "rm -f $file1"
7752         md5="$(md5sum $file1)"
7753
7754         # File currently set to -S 512K -c 1
7755
7756         # Ensure -c and -S options are rejected when -R is set
7757         echo -n "Verifying incompatible options are detected..."
7758         $LFS_MIGRATE -R -c 1 "$file1" &&
7759                 error "incompatible -R and -c options not detected"
7760         $LFS_MIGRATE -R -S 1M "$file1" &&
7761                 error "incompatible -R and -S options not detected"
7762         $LFS_MIGRATE -R -p pool "$file1" &&
7763                 error "incompatible -R and -p options not detected"
7764         $LFS_MIGRATE -R -E eof -c 1 "$file1" &&
7765                 error "incompatible -R and -E options not detected"
7766         $LFS_MIGRATE -R -A "$file1" &&
7767                 error "incompatible -R and -A options not detected"
7768         $LFS_MIGRATE -A -c 1 "$file1" &&
7769                 error "incompatible -A and -c options not detected"
7770         $LFS_MIGRATE -A -S 1M "$file1" &&
7771                 error "incompatible -A and -S options not detected"
7772         $LFS_MIGRATE -A -p pool "$file1" &&
7773                 error "incompatible -A and -p options not detected"
7774         $LFS_MIGRATE -A -E eof -c 1 "$file1" &&
7775                 error "incompatible -A and -E options not detected"
7776         echo "done."
7777
7778         # Ensure unrecognized options are passed through to 'lfs migrate'
7779         echo -n "Verifying -S option is passed through to lfs migrate..."
7780         $LFS_MIGRATE -y -S 1M "$file1" || error "migration failed"
7781         cur_ssize=$($LFS getstripe -S "$file1")
7782         (( cur_ssize == 1048576 )) || error "migrate -S $cur_ssize != 1048576"
7783         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (1)"
7784         echo "done."
7785
7786         # File currently set to -S 1M -c 1
7787
7788         # Ensure long options are supported
7789         echo -n "Verifying long options supported..."
7790         $LFS_MIGRATE --non-block "$file1" ||
7791                 error "long option without argument not supported"
7792         $LFS_MIGRATE --stripe-size 512K "$file1" ||
7793                 error "long option with argument not supported"
7794         cur_ssize=$($LFS getstripe -S "$file1")
7795         (( cur_ssize == 524288 )) ||
7796                 error "migrate --stripe-size $cur_ssize != 524288"
7797         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (2)"
7798         echo "done."
7799
7800         # File currently set to -S 512K -c 1
7801
7802         if (( OSTCOUNT > 1 )); then
7803                 echo -n "Verifying explicit stripe count can be set..."
7804                 $LFS_MIGRATE -c 2 "$file1" || error "migrate failed"
7805                 cur_scount=$($LFS getstripe -c "$file1")
7806                 (( cur_scount == 2 )) || error "migrate -c $cur_scount != 2"
7807                 [[ "$(md5sum $file1)" == "$md5" ]] ||
7808                         error "file data has changed (3)"
7809                 echo "done."
7810         fi
7811
7812         # File currently set to -S 512K -c 1 or -S 512K -c 2
7813
7814         # Ensure parent striping is used if -R is set, and no stripe
7815         # count or size is specified
7816         echo -n "Setting stripe for parent directory..."
7817         $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
7818                 error "cannot set stripe '-S 2M -c 1'"
7819         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (4)"
7820         echo "done."
7821
7822         echo -n "Verifying restripe option uses parent stripe settings..."
7823         parent_ssize=$($LFS getstripe -S $DIR/$tdir 2>/dev/null)
7824         parent_scount=$($LFS getstripe -c $DIR/$tdir 2>/dev/null)
7825         $LFS_MIGRATE -R "$file1" || error "migrate failed"
7826         cur_ssize=$($LFS getstripe -S "$file1")
7827         (( cur_ssize == parent_ssize )) ||
7828                 error "migrate -R stripe_size $cur_ssize != $parent_ssize"
7829         cur_scount=$($LFS getstripe -c "$file1")
7830         (( cur_scount == parent_scount )) ||
7831                 error "migrate -R stripe_count $cur_scount != $parent_scount"
7832         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (5)"
7833         echo "done."
7834
7835         # File currently set to -S 1M -c 1
7836
7837         # Ensure striping is preserved if -R is not set, and no stripe
7838         # count or size is specified
7839         echo -n "Verifying striping size preserved when not specified..."
7840         orig_ssize=$($LFS getstripe -S "$file1" 2>/dev/null)
7841         $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
7842                 error "cannot set stripe on parent directory"
7843         $LFS_MIGRATE "$file1" || error "migrate failed"
7844         cur_ssize=$($LFS getstripe -S "$file1")
7845         (( cur_ssize == orig_ssize )) ||
7846                 error "migrate by default $cur_ssize != $orig_ssize"
7847         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (6)"
7848         echo "done."
7849
7850         # Ensure file name properly detected when final option has no argument
7851         echo -n "Verifying file name properly detected..."
7852         $LFS_MIGRATE "$file1" ||
7853                 error "file name interpreted as option argument"
7854         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (7)"
7855         echo "done."
7856
7857         # Ensure PFL arguments are passed through properly
7858         echo -n "Verifying PFL options passed through..."
7859         new_scount=$(((OSTCOUNT + 1) / 2))
7860         $LFS_MIGRATE -E 1M -c 1 -E 16M -c $new_scount -E eof -c -1 "$file1" ||
7861                 error "migrate PFL arguments failed"
7862         cur_comp=$($LFS getstripe --comp-count $file1)
7863         (( cur_comp == 3 )) || error "component count '$cur_comp' != 3"
7864         cur_scount=$($LFS getstripe --stripe-count $file1)
7865         (( cur_scount == new_scount)) ||
7866                 error "PFL stripe count $cur_scount != $new_scount"
7867         [[ "$(md5sum $file1)" == "$md5" ]] || error "file data has changed (8)"
7868         echo "done."
7869 }
7870 run_test 56wc "check unrecognized options for lfs_migrate are passed through"
7871
7872 test_56wd() {
7873         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
7874
7875         local file1=$DIR/$tdir/$tfile
7876
7877         echo -n "Creating test dir..."
7878         test_mkdir $DIR/$tdir || error "cannot create dir"
7879         echo "done."
7880
7881         echo -n "Creating test file..."
7882         echo "$tfile" > $file1
7883         echo "done."
7884
7885         # Ensure 'lfs migrate' will fail by using a non-existent option,
7886         # and make sure rsync is not called to recover
7887         echo -n "Make sure --no-rsync option works..."
7888         $LFS_MIGRATE -y --no-rsync --invalid-opt $file1 2>&1 |
7889                 grep -q 'refusing to fall back to rsync' ||
7890                 error "rsync was called with --no-rsync set"
7891         echo "done."
7892
7893         # Ensure rsync is called without trying 'lfs migrate' first
7894         echo -n "Make sure --rsync option works..."
7895         $LFS_MIGRATE -y --rsync --invalid-opt $file1 2>&1 |
7896                 grep -q 'falling back to rsync' &&
7897                 error "lfs migrate was called with --rsync set"
7898         echo "done."
7899 }
7900 run_test 56wd "check lfs_migrate --rsync and --no-rsync work"
7901
7902 test_56we() {
7903         local td=$DIR/$tdir
7904         local tf=$td/$tfile
7905
7906         test_mkdir $td || error "cannot create $td"
7907         touch $tf || error "cannot touch $tf"
7908
7909         echo -n "Make sure --non-direct|-D works..."
7910         $LFS_MIGRATE -y --non-direct -v $tf 2>&1 |
7911                 grep -q "lfs migrate --non-direct" ||
7912                 error "--non-direct option cannot work correctly"
7913         $LFS_MIGRATE -y -D -v $tf 2>&1 |
7914                 grep -q "lfs migrate -D" ||
7915                 error "-D option cannot work correctly"
7916         echo "done."
7917 }
7918 run_test 56we "check lfs_migrate --non-direct|-D support"
7919
7920 test_56x() {
7921         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
7922         check_swap_layouts_support
7923
7924         local dir=$DIR/$tdir
7925         local ref1=/etc/passwd
7926         local file1=$dir/file1
7927
7928         test_mkdir $dir || error "creating dir $dir"
7929         $LFS setstripe -c 2 $file1
7930         cp $ref1 $file1
7931         $LFS migrate -c 1 $file1 || error "migrate failed rc = $?"
7932         stripe=$($LFS getstripe -c $file1)
7933         [[ $stripe == 1 ]] || error "stripe of $file1 is $stripe != 1"
7934         cmp $file1 $ref1 || error "content mismatch $file1 differs from $ref1"
7935
7936         # clean up
7937         rm -f $file1
7938 }
7939 run_test 56x "lfs migration support"
7940
7941 test_56xa() {
7942         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
7943         check_swap_layouts_support
7944
7945         local dir=$DIR/$tdir/$testnum
7946
7947         test_mkdir -p $dir
7948
7949         local ref1=/etc/passwd
7950         local file1=$dir/file1
7951
7952         $LFS setstripe -c 2 $file1
7953         cp $ref1 $file1
7954         $LFS migrate --block -c 1 $file1 || error "migrate failed rc = $?"
7955
7956         local stripe=$($LFS getstripe -c $file1)
7957
7958         [[ $stripe == 1 ]] || error "stripe of $file1 is $stripe != 1"
7959         cmp $file1 $ref1 || error "content mismatch $file1 differs from $ref1"
7960
7961         # clean up
7962         rm -f $file1
7963 }
7964 run_test 56xa "lfs migration --block support"
7965
7966 check_migrate_links() {
7967         [[ "$1" == "--rsync" ]] && local opts="--rsync -y" && shift
7968         local dir="$1"
7969         local file1="$dir/file1"
7970         local begin="$2"
7971         local count="$3"
7972         local runas="$4"
7973         local total_count=$(($begin + $count - 1))
7974         local symlink_count=10
7975         local uniq_count=10
7976
7977         if [ ! -f "$file1" ]; then
7978                 echo -n "creating initial file..."
7979                 $LFS setstripe -c 1 -S "512k" "$file1" ||
7980                         error "cannot setstripe initial file"
7981                 echo "done"
7982
7983                 echo -n "creating symlinks..."
7984                 for s in $(seq 1 $symlink_count); do
7985                         ln -s "$file1" "$dir/slink$s" ||
7986                                 error "cannot create symlinks"
7987                 done
7988                 echo "done"
7989
7990                 echo -n "creating nonlinked files..."
7991                 createmany -o "$dir/uniq" 1 10 &> /dev/null ||
7992                         error "cannot create nonlinked files"
7993                 echo "done"
7994         fi
7995
7996         # create hard links
7997         if [ ! -f "$dir/file$total_count" ]; then
7998                 echo -n "creating hard links $begin:$total_count..."
7999                 createmany -l"$file1" "$dir/file" "$begin" "$count" &>  \
8000                         /dev/null || error "cannot create hard links"
8001                 echo "done"
8002         fi
8003
8004         echo -n "checking number of hard links listed in xattrs..."
8005         local fid=$($LFS getstripe -F "$file1")
8006         local paths=($($LFS fid2path "$MOUNT" "$fid" 2> /dev/null))
8007
8008         echo "${#paths[*]}"
8009         if [ ${#paths[*]} -lt $total_count -a "$begin" -eq 2  ]; then
8010                         skip "hard link list has unexpected size, skipping test"
8011         fi
8012         if [ ${#paths[*]} -ge $total_count -a "$begin" -ne 2  ]; then
8013                         error "link names should exceed xattrs size"
8014         fi
8015
8016         echo -n "migrating files..."
8017         local migrate_out=$($runas $LFS_MIGRATE $opts -S '1m' $dir)
8018         local rc=$?
8019         [ $rc -eq 0 ] || error "migrate failed rc = $rc"
8020         echo "done"
8021
8022         # make sure all links have been properly migrated
8023         echo -n "verifying files..."
8024         fid=$($LFS getstripe -F "$file1") ||
8025                 error "cannot get fid for file $file1"
8026         for i in $(seq 2 $total_count); do
8027                 local fid2=$($LFS getstripe -F $dir/file$i)
8028
8029                 [ "$fid2" == "$fid" ] ||
8030                         error "migrated hard link has mismatched FID"
8031         done
8032
8033         # make sure hard links were properly detected, and migration was
8034         # performed only once for the entire link set; nonlinked files should
8035         # also be migrated
8036         local actual=$(grep -c 'done' <<< "$migrate_out")
8037         local expected=$(($uniq_count + 1))
8038
8039         [ "$actual" -eq  "$expected" ] ||
8040                 error "hard links individually migrated ($actual != $expected)"
8041
8042         # make sure the correct number of hard links are present
8043         local hardlinks=$(stat -c '%h' "$file1")
8044
8045         [ $hardlinks -eq $total_count ] ||
8046                 error "num hard links $hardlinks != $total_count"
8047         echo "done"
8048
8049         return 0
8050 }
8051
8052 test_56xb() {
8053         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
8054                 skip "Need MDS version at least 2.10.55"
8055
8056         local dir="$DIR/$tdir"
8057
8058         test_mkdir "$dir" || error "cannot create dir $dir"
8059
8060         echo "testing lfs migrate mode when all links fit within xattrs"
8061         check_migrate_links "$dir" 2 99
8062
8063         echo "testing rsync mode when all links fit within xattrs"
8064         check_migrate_links --rsync "$dir" 2 99
8065
8066         echo "testing lfs migrate mode when all links do not fit within xattrs"
8067         check_migrate_links "$dir" 101 100
8068
8069         echo "testing rsync mode when all links do not fit within xattrs"
8070         check_migrate_links --rsync "$dir" 101 100
8071
8072         chown -R $RUNAS_ID $dir
8073         echo "testing non-root lfs migrate mode when not all links are in xattr"
8074         check_migrate_links "$dir" 101 100 "$RUNAS"
8075
8076         # clean up
8077         rm -rf $dir
8078 }
8079 run_test 56xb "lfs migration hard link support"
8080
8081 test_56xc() {
8082         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8083
8084         local dir="$DIR/$tdir"
8085
8086         test_mkdir "$dir" || error "cannot create dir $dir"
8087
8088         # Test 1: ensure file < 1 GB is always migrated with 1 stripe
8089         echo -n "Setting initial stripe for 20MB test file..."
8090         $LFS setstripe -c 2 -i 0 "$dir/20mb" ||
8091                 error "cannot setstripe 20MB file"
8092         echo "done"
8093         echo -n "Sizing 20MB test file..."
8094         $TRUNCATE "$dir/20mb" 20971520 || error "cannot create 20MB test file"
8095         echo "done"
8096         echo -n "Verifying small file autostripe count is 1..."
8097         $LFS_MIGRATE -y -A -C 1 "$dir/20mb" ||
8098                 error "cannot migrate 20MB file"
8099         local stripe_count=$($LFS getstripe -c "$dir/20mb") ||
8100                 error "cannot get stripe for $dir/20mb"
8101         [ $stripe_count -eq 1 ] ||
8102                 error "unexpected stripe count $stripe_count for 20MB file"
8103         rm -f "$dir/20mb"
8104         echo "done"
8105
8106         # Test 2: File is small enough to fit within the available space on
8107         # sqrt(size_in_gb) + 1 OSTs but is larger than 1GB.  The file must
8108         # have at least an additional 1KB for each desired stripe for test 3
8109         echo -n "Setting stripe for 1GB test file..."
8110         $LFS setstripe -c 1 -i 0 "$dir/1gb" || error "cannot setstripe 1GB file"
8111         echo "done"
8112         echo -n "Sizing 1GB test file..."
8113         # File size is 1GB + 3KB
8114         $TRUNCATE "$dir/1gb" 1073744896 || error "cannot create 1GB test file"
8115         echo "done"
8116
8117         # need at least 512MB per OST for 1GB file to fit in 2 stripes
8118         local avail=$($LCTL get_param -n llite.$FSNAME*.kbytesavail)
8119         if (( avail > 524288 * OSTCOUNT )); then
8120                 echo -n "Migrating 1GB file..."
8121                 $LFS_MIGRATE -y -A -C 1 "$dir/1gb" ||
8122                         error "cannot migrate 1GB file"
8123                 echo "done"
8124                 echo -n "Verifying autostripe count is sqrt(n) + 1..."
8125                 stripe_count=$($LFS getstripe -c "$dir/1gb") ||
8126                         error "cannot getstripe for 1GB file"
8127                 [ $stripe_count -eq 2 ] ||
8128                         error "unexpected stripe count $stripe_count != 2"
8129                 echo "done"
8130         fi
8131
8132         # Test 3: File is too large to fit within the available space on
8133         # sqrt(n) + 1 OSTs.  Simulate limited available space with -X
8134         if [ $OSTCOUNT -ge 3 ]; then
8135                 # The required available space is calculated as
8136                 # file size (1GB + 3KB) / OST count (3).
8137                 local kb_per_ost=349526
8138
8139                 echo -n "Migrating 1GB file with limit..."
8140                 $LFS_MIGRATE -y -A -C 1 -X $kb_per_ost "$dir/1gb" ||
8141                         error "cannot migrate 1GB file with limit"
8142                 echo "done"
8143
8144                 stripe_count=$($LFS getstripe -c "$dir/1gb")
8145                 echo -n "Verifying 1GB autostripe count with limited space..."
8146                 [ "$stripe_count" -a $stripe_count -ge 3 ] ||
8147                         error "unexpected stripe count $stripe_count (min 3)"
8148                 echo "done"
8149         fi
8150
8151         # clean up
8152         rm -rf $dir
8153 }
8154 run_test 56xc "lfs migration autostripe"
8155
8156 test_56xd() {
8157         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8158
8159         local dir=$DIR/$tdir
8160         local f_mgrt=$dir/$tfile.mgrt
8161         local f_yaml=$dir/$tfile.yaml
8162         local f_copy=$dir/$tfile.copy
8163         local layout_yaml="-E 1M -S 512K -c 1 -E -1 -S 1M -c 2 -i 0"
8164         local layout_copy="-c 2 -S 2M -i 1"
8165         local yamlfile=$dir/yamlfile
8166         local layout_before;
8167         local layout_after;
8168
8169         test_mkdir "$dir" || error "cannot create dir $dir"
8170         stack_trap "rm -rf $dir"
8171         $LFS setstripe $layout_yaml $f_yaml ||
8172                 error "cannot setstripe $f_yaml with layout $layout_yaml"
8173         $LFS getstripe --yaml $f_yaml > $yamlfile
8174         $LFS setstripe $layout_copy $f_copy ||
8175                 error "cannot setstripe $f_copy with layout $layout_copy"
8176         touch $f_mgrt
8177         dd if=/dev/zero of=$f_mgrt bs=1M count=4
8178
8179         # 1. test option --yaml
8180         $LFS_MIGRATE -y --yaml $yamlfile $f_mgrt ||
8181                 error "cannot migrate $f_mgrt with --yaml $yamlfile"
8182         layout_before=$(get_layout_param $f_yaml)
8183         layout_after=$(get_layout_param $f_mgrt)
8184         [ "$layout_after" == "$layout_before" ] ||
8185                 error "lfs_migrate --yaml: $layout_after != $layout_before"
8186
8187         # 2. test option --copy
8188         $LFS_MIGRATE -y --copy $f_copy $f_mgrt ||
8189                 error "cannot migrate $f_mgrt with --copy $f_copy"
8190         layout_before=$(SKIP_INDEX=yes get_layout_param $f_copy)
8191         layout_after=$(SKIP_INDEX=yes get_layout_param $f_mgrt)
8192         [ "$layout_after" == "$layout_before" ] ||
8193                 error "lfs_migrate --copy: $layout_after != $layout_before"
8194 }
8195 run_test 56xd "check lfs_migrate --yaml and --copy support"
8196
8197 test_56xe() {
8198         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8199
8200         local dir=$DIR/$tdir
8201         local f_comp=$dir/$tfile
8202         local layout="-E 1M -S 512K -c 1 -E -1 -S 1M -c 2 -i 0"
8203         local layout_before=""
8204         local layout_after=""
8205
8206         test_mkdir "$dir" || error "cannot create dir $dir"
8207         stack_trap "rm -rf $dir"
8208         $LFS setstripe $layout $f_comp ||
8209                 error "cannot setstripe $f_comp with layout $layout"
8210         layout_before=$(SKIP_INDEX=yes get_layout_param $f_comp)
8211         dd if=/dev/zero of=$f_comp bs=1M count=4
8212
8213         # 1. migrate a comp layout file by lfs_migrate
8214         $LFS_MIGRATE -y $f_comp || error "cannot migrate $f_comp by lfs_migrate"
8215         layout_after=$(SKIP_INDEX=yes get_layout_param $f_comp)
8216         [ "$layout_before" == "$layout_after" ] ||
8217                 error "lfs_migrate: $layout_before != $layout_after"
8218
8219         # 2. migrate a comp layout file by lfs migrate
8220         $LFS migrate $f_comp || error "cannot migrate $f_comp by lfs migrate"
8221         layout_after=$(SKIP_INDEX=yes get_layout_param $f_comp)
8222         [ "$layout_before" == "$layout_after" ] ||
8223                 error "lfs migrate: $layout_before != $layout_after"
8224 }
8225 run_test 56xe "migrate a composite layout file"
8226
8227 test_56xf() {
8228         [[ $OSTCOUNT -ge 2 ]] || skip_env "needs >= 2 OSTs"
8229
8230         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
8231                 skip "Need server version at least 2.13.53"
8232
8233         local dir=$DIR/$tdir
8234         local f_comp=$dir/$tfile
8235         local layout="-E 1M -c1 -E -1 -c2"
8236         local fid_before=""
8237         local fid_after=""
8238
8239         test_mkdir "$dir" || error "cannot create dir $dir"
8240         stack_trap "rm -rf $dir"
8241         $LFS setstripe $layout $f_comp ||
8242                 error "cannot setstripe $f_comp with layout $layout"
8243         fid_before=$($LFS getstripe --fid $f_comp)
8244         dd if=/dev/zero of=$f_comp bs=1M count=4
8245
8246         # 1. migrate a comp layout file to a comp layout
8247         $LFS migrate $f_comp || error "cannot migrate $f_comp by lfs migrate"
8248         fid_after=$($LFS getstripe --fid $f_comp)
8249         [ "$fid_before" == "$fid_after" ] ||
8250                 error "comp-to-comp migrate: $fid_before != $fid_after"
8251
8252         # 2. migrate a comp layout file to a plain layout
8253         $LFS migrate -c2 $f_comp ||
8254                 error "cannot migrate $f_comp by lfs migrate"
8255         fid_after=$($LFS getstripe --fid $f_comp)
8256         [ "$fid_before" == "$fid_after" ] ||
8257                 error "comp-to-plain migrate: $fid_before != $fid_after"
8258
8259         # 3. migrate a plain layout file to a comp layout
8260         $LFS migrate $layout $f_comp ||
8261                 error "cannot migrate $f_comp by lfs migrate"
8262         fid_after=$($LFS getstripe --fid $f_comp)
8263         [ "$fid_before" == "$fid_after" ] ||
8264                 error "plain-to-comp migrate: $fid_before != $fid_after"
8265 }
8266 run_test 56xf "FID is not lost during migration of a composite layout file"
8267
8268 check_file_ost_range() {
8269         local file="$1"
8270         shift
8271         local range="$*"
8272         local -a file_range
8273         local idx
8274
8275         file_range=($($LFS getstripe -y "$file" |
8276                 awk '/l_ost_idx:/ { print $NF }'))
8277
8278         if [[ "${#file_range[@]}" = 0 ]]; then
8279                 echo "No osts found for $file"
8280                 return 1
8281         fi
8282
8283         for idx in "${file_range[@]}"; do
8284                 [[ " $range " =~ " $idx " ]] ||
8285                         return 1
8286         done
8287
8288         return 0
8289 }
8290
8291 sub_test_56xg() {
8292         local stripe_opt="$1"
8293         local pool="$2"
8294         shift 2
8295         local pool_ostidx="$(seq $* | tr '\n' ' ')"
8296
8297         $LFS migrate $stripe_opt -p $pool $DIR/$tfile ||
8298                 error "Fail to migrate $tfile on $pool"
8299         [[ "$($LFS getstripe -p $DIR/$tfile)" = "$pool" ]] ||
8300                 error "$tfile is not in pool $pool"
8301         check_file_ost_range "$DIR/$tfile" $pool_ostidx ||
8302                 error "$tfile osts mismatch with pool $pool (osts $pool_ostidx)"
8303 }
8304
8305 test_56xg() {
8306         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
8307         [[ $OSTCOUNT -ge 2 ]] || skip "needs >= 2 OSTs"
8308         [[ $MDS1_VERSION -gt $(version_code 2.14.52) ]] ||
8309                 skip "Need MDS version newer than 2.14.52"
8310
8311         local -a pool_names=("${TESTNAME}_0" "${TESTNAME}_1" "${TESTNAME}_2")
8312         local -a pool_ranges=("0 0" "1 1" "0 1")
8313
8314         # init pools
8315         for i in "${!pool_names[@]}"; do
8316                 pool_add ${pool_names[$i]} ||
8317                         error "pool_add failed (pool: ${pool_names[$i]})"
8318                 pool_add_targets ${pool_names[$i]} ${pool_ranges[$i]} ||
8319                         error "pool_add_targets failed (pool: ${pool_names[$i]})"
8320         done
8321
8322         # init the file to migrate
8323         $LFS setstripe -c1 -i1 $DIR/$tfile ||
8324                 error "Unable to create $tfile on OST1"
8325         stack_trap "rm -f $DIR/$tfile"
8326         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=4 status=none ||
8327                 error "Unable to write on $tfile"
8328
8329         echo "1. migrate $tfile on pool ${pool_names[0]}"
8330         sub_test_56xg "-c-1" "${pool_names[0]}" ${pool_ranges[0]}
8331
8332         echo "2. migrate $tfile on pool ${pool_names[2]}"
8333         sub_test_56xg "-c-1 -S2M" "${pool_names[2]}" ${pool_ranges[2]}
8334
8335         echo "3. migrate $tfile on pool ${pool_names[1]}"
8336         sub_test_56xg "-n -c-1" "${pool_names[1]}" ${pool_ranges[1]}
8337
8338         echo "4. migrate $tfile on pool ${pool_names[2]} with default stripe parameters"
8339         sub_test_56xg "" "${pool_names[2]}" ${pool_ranges[2]}
8340         echo
8341
8342         # Clean pools
8343         destroy_test_pools ||
8344                 error "pool_destroy failed"
8345 }
8346 run_test 56xg "lfs migrate pool support"
8347
8348 test_56xh() {
8349         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8350
8351         local size_mb=25
8352         local file1=$DIR/$tfile
8353         local tmp1=$TMP/$tfile.tmp
8354
8355         $LFS setstripe -c 2 $file1
8356
8357         stack_trap "rm -f $file1 $tmp1"
8358         dd if=/dev/urandom of=$tmp1 bs=1M count=$size_mb ||
8359                         error "error creating $tmp1"
8360         ls -lsh $tmp1
8361         cp $tmp1 $file1
8362
8363         local start=$SECONDS
8364
8365         $LFS migrate --stats --stats-interval=1 -W 1M -c 1 $file1 ||
8366                 error "migrate failed rc = $?"
8367
8368         local elapsed=$((SECONDS - start))
8369
8370         # with 1MB/s, elapsed should equal size_mb
8371         (( elapsed >= size_mb * 95 / 100 )) ||
8372                 error "'lfs migrate -W' too fast ($elapsed < 0.95 * $size_mb)?"
8373
8374         (( elapsed <= size_mb * 120 / 100 )) ||
8375                 error_not_in_vm "'lfs migrate -W' slow ($elapsed > 1.2 * $size_mb)"
8376
8377         (( elapsed <= size_mb * 350 / 100 )) ||
8378                 error "'lfs migrate -W' too slow in VM ($elapsed > 3.5 * $size_mb)"
8379
8380         stripe=$($LFS getstripe -c $file1)
8381         (( $stripe == 1 )) || error "stripe of $file1 is $stripe != 1"
8382         cmp $file1 $tmp1 || error "content mismatch $file1 differs from $tmp1"
8383
8384         # Clean up file (since it is multiple MB)
8385         rm -f $file1 $tmp1
8386 }
8387 run_test 56xh "lfs migrate bandwidth limitation support"
8388
8389 test_56xi() {
8390         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8391         verify_yaml_available || skip_env "YAML verification not installed"
8392
8393         local size_mb=5
8394         local file1=$DIR/$tfile.1
8395         local file2=$DIR/$tfile.2
8396         local file3=$DIR/$tfile.3
8397         local output_file=$DIR/$tfile.out
8398         local tmp1=$TMP/$tfile.tmp
8399
8400         $LFS setstripe -c 2 $file1
8401         $LFS setstripe -c 2 $file2
8402         $LFS setstripe -c 2 $file3
8403
8404         stack_trap "rm -f $file1 $file2 $file3 $tmp1 $output_file"
8405         dd if=/dev/urandom of=$tmp1 bs=1M count=$size_mb ||
8406                         error "error creating $tmp1"
8407         ls -lsh $tmp1
8408         cp $tmp1 $file1
8409         cp $tmp1 $file2
8410         cp $tmp1 $file3
8411
8412         $LFS migrate --stats --stats-interval=1 \
8413                 -c 1 $file1 $file2 $file3 1> $output_file ||
8414                 error "migrate failed rc = $?"
8415
8416         cat $output_file
8417         cat $output_file | verify_yaml || error "rename_stats is not valid YAML"
8418
8419         # Clean up file (since it is multiple MB)
8420         rm -f $file1 $file2 $file3 $tmp1 $output_file
8421 }
8422 run_test 56xi "lfs migrate stats support"
8423
8424 test_56xj() { # LU-16571 "lfs migrate -b" can cause thread starvation on OSS
8425         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8426
8427         local file=$DIR/$tfile
8428         local linkdir=$DIR/$tdir
8429
8430         test_mkdir $linkdir || error "fail to create $linkdir"
8431         $LFS setstripe -i 0 -c 1 -S1M $file
8432         stack_trap "rm -rf $file $linkdir"
8433         dd if=/dev/urandom of=$file bs=1M count=10 ||
8434                 error "fail to create $file"
8435
8436         # Create file links
8437         local cpts
8438         local threads_max
8439         local nlinks
8440
8441         thread_max=$(do_facet ost1 "$LCTL get_param -n ost.OSS.ost.threads_max")
8442         cpts=$(do_facet ost1 "$LCTL get_param -n cpu_partition_table | wc -l")
8443         (( nlinks = thread_max * 3 / 2 / cpts))
8444
8445         echo "create $nlinks hard links of $file"
8446         createmany -l $file $linkdir/link $nlinks
8447
8448         # Parallel migrates (should not block)
8449         local i
8450         for ((i = 0; i < nlinks; i++)); do
8451                 echo $linkdir/link$i
8452         done | xargs -n1 -P $nlinks $LFS migrate -c2
8453
8454         local stripe_count
8455         stripe_count=$($LFS getstripe -c $file) ||
8456                 error "fail to get stripe count on $file"
8457
8458         ((stripe_count == 2)) ||
8459                 error "fail to migrate $file (stripe_count = $stripe_count)"
8460 }
8461 run_test 56xj "lfs migrate -b should not cause starvation of threads on OSS"
8462
8463 test_56xk() {
8464         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8465
8466         local size_mb=5
8467         local file1=$DIR/$tfile
8468
8469         stack_trap "rm -f $file1"
8470         $LFS setstripe -c 1 $file1
8471         dd if=/dev/zero of=$file1 bs=1M count=$size_mb ||
8472                 error "error creating $file1"
8473         $LFS mirror extend -N $file1 || error "can't mirror"
8474         dd if=/dev/zero of=$file1 bs=4k count=1 conv=notrunc ||
8475                 error "can't dd"
8476         $LFS getstripe $file1 | grep stale ||
8477                 error "one component must be stale"
8478
8479         local start=$SECONDS
8480         $LFS mirror resync --stats --stats-interval=1 -W 1M $file1 ||
8481                 error "migrate failed rc = $?"
8482         local elapsed=$((SECONDS - start))
8483         $LFS getstripe $file1 | grep stale &&
8484                 error "all components must be sync"
8485
8486         # with 1MB/s, elapsed should equal size_mb
8487         (( elapsed >= size_mb * 95 / 100 )) ||
8488                 error "'lfs mirror resync -W' too fast ($elapsed < 0.95 * $size_mb)?"
8489
8490         (( elapsed <= size_mb * 120 / 100 )) ||
8491                 error_not_in_vm "'lfs mirror resync -W' slow ($elapsed > 1.2 * $size_mb)"
8492
8493         (( elapsed <= size_mb * 350 / 100 )) ||
8494                 error "'lfs mirror resync -W' too slow in VM ($elapsed > 3.5 * $size_mb)"
8495 }
8496 run_test 56xk "lfs mirror resync bandwidth limitation support"
8497
8498 test_56xl() {
8499         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
8500         verify_yaml_available || skip_env "YAML verification not installed"
8501
8502         local size_mb=5
8503         local file1=$DIR/$tfile.1
8504         local output_file=$DIR/$tfile.out
8505
8506         stack_trap "rm -f $file1"
8507         $LFS setstripe -c 1 $file1
8508         dd if=/dev/zero of=$file1 bs=1M count=$size_mb ||
8509                 error "error creating $file1"
8510         $LFS mirror extend -N $file1 || error "can't mirror"
8511         dd if=/dev/zero of=$file1 bs=4k count=1 conv=notrunc ||
8512                 error "can't dd"
8513         $LFS getstripe $file1 | grep stale ||
8514                 error "one component must be stale"
8515         $LFS getstripe $file1
8516
8517         $LFS mirror resync --stats --stats-interval=1 $file1 >$output_file ||
8518                 error "resync failed rc = $?"
8519         $LFS getstripe $file1 | grep stale &&
8520                 error "all components must be sync"
8521
8522         cat $output_file
8523         cat $output_file | verify_yaml || error "stats is not valid YAML"
8524 }
8525 run_test 56xl "lfs mirror resync stats support"
8526
8527 test_56y() {
8528         [ $MDS1_VERSION -lt $(version_code 2.4.53) ] &&
8529                 skip "No HSM $(lustre_build_version $SINGLEMDS) MDS < 2.4.53"
8530
8531         local res=""
8532         local dir=$DIR/$tdir
8533         local f1=$dir/file1
8534         local f2=$dir/file2
8535
8536         test_mkdir -p $dir || error "creating dir $dir"
8537         touch $f1 || error "creating std file $f1"
8538         $MULTIOP $f2 H2c || error "creating released file $f2"
8539
8540         # a directory can be raid0, so ask only for files
8541         res=$($LFS find $dir -L raid0 -type f | wc -l)
8542         [[ $res == 2 ]] || error "search raid0: found $res files != 2"
8543
8544         res=$($LFS find $dir \! -L raid0 -type f | wc -l)
8545         [[ $res == 0 ]] || error "search !raid0: found $res files != 0"
8546
8547         # only files can be released, so no need to force file search
8548         res=$($LFS find $dir -L released)
8549         [[ $res == $f2 ]] || error "search released: found $res != $f2"
8550
8551         res=$($LFS find $dir -type f \! -L released)
8552         [[ $res == $f1 ]] || error "search !released: found $res != $f1"
8553 }
8554 run_test 56y "lfs find -L raid0|released"
8555
8556 test_56z() { # LU-4824
8557         # This checks to make sure 'lfs find' continues after errors
8558         # There are two classes of errors that should be caught:
8559         # - If multiple paths are provided, all should be searched even if one
8560         #   errors out
8561         # - If errors are encountered during the search, it should not terminate
8562         #   early
8563         local dir=$DIR/$tdir
8564         local i
8565
8566         test_mkdir $dir
8567         for i in d{0..9}; do
8568                 test_mkdir $dir/$i
8569                 touch $dir/$i/$tfile
8570         done
8571         $LFS find $DIR/non_existent_dir $dir &&
8572                 error "$LFS find did not return an error"
8573         # Make a directory unsearchable. This should NOT be the last entry in
8574         # directory order.  Arbitrarily pick the 6th entry
8575         chmod 700 $($LFS find $dir -type d | sed '6!d')
8576
8577         $RUNAS $LFS find $DIR/non_existent $dir
8578         local count=$($RUNAS $LFS find $DIR/non_existent $dir | wc -l)
8579
8580         # The user should be able to see 10 directories and 9 files
8581         (( count == 19 )) ||
8582                 error "$LFS find found $count != 19 entries after error"
8583 }
8584 run_test 56z "lfs find should continue after an error"
8585
8586 test_56aa() { # LU-5937
8587         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
8588
8589         local dir=$DIR/$tdir
8590
8591         mkdir $dir
8592         $LFS setdirstripe -c$MDSCOUNT $dir/striped_dir
8593
8594         createmany -o $dir/striped_dir/${tfile}- 1024
8595         local dirs=$($LFS find --size +8k $dir/)
8596
8597         [ -n "$dirs" ] || error "lfs find --size wrong under striped dir"
8598 }
8599 run_test 56aa "lfs find --size under striped dir"
8600
8601 test_56ab() { # LU-10705
8602         test_mkdir $DIR/$tdir
8603         dd if=/dev/urandom of=$DIR/$tdir/$tfile.1 bs=8k count=1 seek=2k
8604         dd if=/dev/urandom of=$DIR/$tdir/$tfile.2 bs=4k count=1 seek=4k
8605         dd if=/dev/urandom of=$DIR/$tdir/$tfile.3 bs=1M count=2 seek=16
8606         # Flush writes to ensure valid blocks.  Need to be more thorough for
8607         # ZFS, since blocks are not allocated/returned to client immediately.
8608         sync_all_data
8609         wait_zfs_commit ost1 2
8610         cancel_lru_locks osc
8611         ls -ls $DIR/$tdir
8612
8613         local files=$($LFS find --size +16M $DIR/$tdir | wc -l)
8614
8615         [[ $files == 3 ]] || error ">16M size files $files isn't 3 as expected"
8616
8617         files=$($LFS find --blocks +1M $DIR/$tdir | wc -l)
8618         [[ $files == 1 ]] || error ">1M blocks files $files isn't 1 as expected"
8619
8620         rm -f $DIR/$tdir/$tfile.[123]
8621 }
8622 run_test 56ab "lfs find --blocks"
8623
8624 # LU-11188
8625 test_56aca() {
8626         local dir="$DIR/$tdir"
8627         local perms=(001 002 003 004 005 006 007
8628                      010 020 030 040 050 060 070
8629                      100 200 300 400 500 600 700
8630                      111 222 333 444 555 666 777)
8631         local perm_minus=(8 8 4 8 4 4 2
8632                           8 8 4 8 4 4 2
8633                           8 8 4 8 4 4 2
8634                           4 4 2 4 2 2 1)
8635         local perm_slash=(8  8 12  8 12 12 14
8636                           8  8 12  8 12 12 14
8637                           8  8 12  8 12 12 14
8638                          16 16 24 16 24 24 28)
8639
8640         test_mkdir "$dir"
8641         for perm in ${perms[*]}; do
8642                 touch "$dir/$tfile.$perm"
8643                 chmod $perm "$dir/$tfile.$perm"
8644         done
8645
8646         for ((i = 0; i < ${#perms[*]}; i++)); do
8647                 local num=$($LFS find $dir -perm ${perms[i]} | wc -l)
8648                 (( $num == 1 )) ||
8649                         error "lfs find -perm ${perms[i]}:"\
8650                               "$num != 1"
8651
8652                 num=$($LFS find $dir -perm -${perms[i]} -type f| wc -l)
8653                 (( $num == ${perm_minus[i]} )) ||
8654                         error "lfs find -perm -${perms[i]}:"\
8655                               "$num != ${perm_minus[i]}"
8656
8657                 num=$($LFS find $dir -perm /${perms[i]} -type f| wc -l)
8658                 (( $num == ${perm_slash[i]} )) ||
8659                         error "lfs find -perm /${perms[i]}:"\
8660                               "$num != ${perm_slash[i]}"
8661         done
8662 }
8663 run_test 56aca "check lfs find -perm with octal representation"
8664
8665 test_56acb() {
8666         local dir=$DIR/$tdir
8667         # p is the permission of write and execute for user, group and other
8668         # without the umask. It is used to test +wx.
8669         local p=$(printf "%o" "$((0333 & ~$(umask)))")
8670         local perms=(1000 000 2000 4000 $p 644 111 110 100 004)
8671         local symbolic=(+t  a+t u+t g+t o+t
8672                         g+s u+s o+s +s o+sr
8673                         o=r,ug+o,u+w
8674                         u+ g+ o+ a+ ugo+
8675                         u- g- o- a- ugo-
8676                         u= g= o= a= ugo=
8677                         o=r,ug+o,u+w u=r,a+u,u+w
8678                         g=r,ugo=g,u+w u+x,+X +X
8679                         u+x,u+X u+X u+x,g+X o+r,+X
8680                         u+x,go+X +wx +rwx)
8681
8682         test_mkdir $dir
8683         for perm in ${perms[*]}; do
8684                 touch "$dir/$tfile.$perm"
8685                 chmod $perm "$dir/$tfile.$perm"
8686         done
8687
8688         for (( i = 0; i < ${#symbolic[*]}; i++ )); do
8689                 local num=$($LFS find $dir -perm ${symbolic[i]} | wc -l)
8690
8691                 (( $num == 1 )) ||
8692                         error "lfs find $dir -perm ${symbolic[i]}: $num != 1"
8693         done
8694 }
8695 run_test 56acb "check lfs find -perm with symbolic representation"
8696
8697 test_56acc() {
8698         local dir=$DIR/$tdir
8699         local tests="17777 787 789 abcd
8700                 ug=uu ug=a ug=gu uo=ou urw
8701                 u+xg+x a=r,u+x,"
8702
8703         test_mkdir $dir
8704         for err in $tests; do
8705                 if $LFS find $dir -perm $err 2>/dev/null; then
8706                         error "lfs find -perm $err: parsing should have failed"
8707                 fi
8708         done
8709 }
8710 run_test 56acc "check parsing error for lfs find -perm"
8711
8712 test_56ba() {
8713         [ $MDS1_VERSION -lt $(version_code 2.10.50) ] &&
8714                 skip "Need MDS version at least 2.10.50"
8715
8716         # Create composite files with one component
8717         local dir=$DIR/$tdir
8718
8719         setup_56 $dir/1Mfiles 5 1 "-S 1M --component-end 1M"
8720         # Create composite files with three components
8721         setup_56 $dir/2Mfiles 5 2 "-E 2M -S 1M -E 4M -E 6M"
8722         # LU-16904 Create plain layout files
8723         lfs setstripe -c 1 $dir/$tfile-{1..10}
8724
8725         local nfiles=$($LFS find --component-end 1M --type f $dir | wc -l)
8726
8727         [[ $nfiles == 10 ]] ||
8728                 error "lfs find -E 1M found $nfiles != 10 files"
8729
8730         nfiles=$($LFS find ! -E 1M --type f $dir | wc -l)
8731         [[ $nfiles == 25 ]] ||
8732                 error "lfs find ! -E 1M found $nfiles != 25 files"
8733
8734         # All files have a component that starts at 0
8735         nfiles=$($LFS find --component-start 0 --type f $dir | wc -l)
8736         [[ $nfiles == 35 ]] ||
8737                 error "lfs find --component-start 0 - $nfiles != 35 files"
8738
8739         nfiles=$($LFS find --component-start 2M --type f $dir | wc -l)
8740         [[ $nfiles == 15 ]] ||
8741                 error "lfs find --component-start 2M - $nfiles != 15 files"
8742
8743         # All files created here have a componenet that does not starts at 2M
8744         nfiles=$($LFS find ! --component-start 2M --type f $dir | wc -l)
8745         [[ $nfiles == 35 ]] ||
8746                 error "lfs find ! --component-start 2M - $nfiles != 35 files"
8747
8748         # Find files with a specified number of components
8749         local nfiles=$($LFS find --component-count 3 --type f $dir | wc -l)
8750         [[ $nfiles == 15 ]] ||
8751                 error "lfs find --component-count 3 - $nfiles != 15 files"
8752
8753         # Remember non-composite files have a component count of zero
8754         local nfiles=$($LFS find --component-count 0 --type f $dir | wc -l)
8755         [[ $nfiles == 10 ]] ||
8756                 error "lfs find --component-count 0 - $nfiles != 10 files"
8757
8758         nfiles=$($LFS find ! --component-count 3 --type f $dir | wc -l)
8759         [[ $nfiles == 20 ]] ||
8760                 error "lfs find ! --component-count 3 - $nfiles != 20 files"
8761
8762         # All files have a flag called "init"
8763         local nfiles=$($LFS find --component-flags init --type f $dir | wc -l)
8764         [[ $nfiles == 35 ]] ||
8765                 error "lfs find --component-flags init - $nfiles != 35 files"
8766
8767         # Multi-component files will have a component not initialized
8768         local nfiles=$($LFS find ! --component-flags init --type f $dir | wc -l)
8769         [[ $nfiles == 15 ]] ||
8770                 error "lfs find !--component-flags init - $nfiles != 15 files"
8771
8772         rm -rf $dir
8773
8774 }
8775 run_test 56ba "test lfs find --component-end, -start, -count, and -flags"
8776
8777 test_56ca() {
8778         [[ $MDS1_VERSION -ge $(version_code 2.10.57) ]] ||
8779                 skip "Need MDS version at least 2.10.57"
8780
8781         local td=$DIR/$tdir
8782         local tf=$td/$tfile
8783         local dir
8784         local nfiles
8785         local cmd
8786         local i
8787         local j
8788
8789         # create mirrored directories and mirrored files
8790         mkdir $td || error "mkdir $td failed"
8791         $LFS mirror create -N3 $td || error "create mirrored dir $td failed"
8792         createmany -o $tf- 10 || error "create $tf- failed"
8793
8794         for i in $(seq 2); do
8795                 dir=$td/dir$i
8796                 mkdir $dir || error "mkdir $dir failed"
8797                 $LFS mirror create -N$((3 + i)) $dir ||
8798                         error "create mirrored dir $dir failed"
8799                 createmany -o $dir/$tfile- 10 ||
8800                         error "create $dir/$tfile- failed"
8801         done
8802
8803         # change the states of some mirrored files
8804         echo foo > $tf-6
8805         for i in $(seq 2); do
8806                 dir=$td/dir$i
8807                 for j in $(seq 4 9); do
8808                         echo foo > $dir/$tfile-$j
8809                 done
8810         done
8811
8812         # find mirrored files with specific mirror count
8813         cmd="$LFS find --mirror-count 3 --type f $td"
8814         nfiles=$($cmd | wc -l)
8815         [[ $nfiles = 10 ]] || error "$cmd: $nfiles != 10 files"
8816
8817         cmd="$LFS find ! --mirror-count 3 --type f $td"
8818         nfiles=$($cmd | wc -l)
8819         [[ $nfiles = 20 ]] || error "$cmd: $nfiles != 20 files"
8820
8821         cmd="$LFS find --mirror-count +2 --type f $td"
8822         nfiles=$($cmd | wc -l)
8823         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
8824
8825         cmd="$LFS find --mirror-count -6 --type f $td"
8826         nfiles=$($cmd | wc -l)
8827         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
8828
8829         # find mirrored files with specific file state
8830         cmd="$LFS find --maxdepth 1 --mirror-state=^ro --type f $td"
8831         [[ $($cmd) = $tf-6 ]] || error "$cmd: didn't return $tf-6"
8832
8833         cmd="$LFS find --mirror-state=ro --type f $td"
8834         nfiles=$($cmd | wc -l)
8835         [[ $nfiles = 17 ]] || error "$cmd: $nfiles != 17 files"
8836
8837         cmd="$LFS find ! --mirror-state=ro --type f $td"
8838         nfiles=$($cmd | wc -l)
8839         [[ $nfiles = 13 ]] || error "$cmd: $nfiles != 13 files"
8840
8841         cmd="$LFS find --mirror-state=wp --type f $td"
8842         nfiles=$($cmd | wc -l)
8843         [[ $nfiles = 13 ]] || error "$cmd: $nfiles != 13 files"
8844
8845         cmd="$LFS find ! --mirror-state=sp --type f $td"
8846         nfiles=$($cmd | wc -l)
8847         [[ $nfiles = 30 ]] || error "$cmd: $nfiles != 30 files"
8848 }
8849 run_test 56ca "check lfs find --mirror-count|-N and --mirror-state"
8850
8851 test_56da() { # LU-14179
8852         local path=$DIR/$tdir
8853
8854         test_mkdir $path
8855         cd $path
8856
8857         local longdir=$(str_repeat 'a' 255)
8858
8859         for i in {1..15}; do
8860                 path=$path/$longdir
8861                 test_mkdir $longdir
8862                 cd $longdir
8863         done
8864
8865         local len=${#path}
8866         local lastdir=$(str_repeat 'a' $((4096 - 1 - $len - 1)))
8867
8868         test_mkdir $lastdir
8869         cd $lastdir
8870         # PATH_MAX-1
8871         (( ${#PWD} == 4095 )) || error "bad PWD length ${#PWD}, expect 4095"
8872
8873         # NAME_MAX
8874         touch $(str_repeat 'f' 255)
8875
8876         $LFS find $DIR/$tdir --type d |& grep "lfs find: error" &&
8877                 error "lfs find reported an error"
8878
8879         rm -rf $DIR/$tdir
8880 }
8881 run_test 56da "test lfs find with long paths"
8882
8883 test_56ea() { #LU-10378
8884         local path=$DIR/$tdir
8885         local pool=$TESTNAME
8886
8887         # Create ost pool
8888         pool_add $pool || error "pool_add $pool failed"
8889         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
8890                 error "adding targets to $pool failed"
8891
8892         # Set default pool on directory before creating file
8893         mkdir $path || error "mkdir $path failed"
8894         $LFS setstripe -p $pool $path ||
8895                 error "set OST pool on $pool failed"
8896         touch $path/$tfile || error "touch $path/$tfile failed"
8897
8898         # Compare basic file attributes from -printf and stat
8899         local attr_printf=$($LFS find $path/$tfile -printf "%A@ %T@ %C@ %U %G %n")
8900         local attr_stat=$(stat -c "%X %Y %Z %u %g %h" $path/$tfile)
8901
8902         [[ "${attr_printf}" == "${attr_stat}" ]] ||
8903                 error "Attrs from lfs find and stat don't match"
8904
8905         # Compare Lustre attributes from lfs find and lfs getstripe
8906         local lattr_printf=$($LFS find $path/$tfile -printf "%Lc %LS %Li %Lp")
8907         local str_cnt=$($LFS getstripe --stripe-count $path/$tfile)
8908         local str_size=$($LFS getstripe --stripe-size $path/$tfile)
8909         local str_idx=$($LFS getstripe --stripe-index $path/$tfile)
8910         local fpool=$($LFS getstripe --pool $path/$tfile)
8911         local lattr_getstr="${str_cnt} ${str_size} ${str_idx} ${fpool}"
8912
8913         [[ "${lattr_printf}" == "${lattr_getstr}" ]] ||
8914                 error "Attrs from lfs find and lfs getstripe don't match"
8915
8916         # Verify behavior for unknown escape/format sequences
8917         local esc_printf=$($LFS find $path/$tfile -printf '\\ %% \Q %Q')
8918
8919         [[ "${esc_printf}" == '\ % \Q %Q' ]] ||
8920                 error "Escape/format codes don't match"
8921 }
8922 run_test 56ea "test lfs find -printf option"
8923
8924 test_56eb() {
8925         local dir=$DIR/$tdir
8926         local subdir_1=$dir/subdir_1
8927
8928         test_mkdir -p $subdir_1
8929         ln -s subdir_1 $dir/link_1
8930
8931         $LFS getstripe $dir | grep "^$dir/link_1$" -A1 ||
8932                 error "symlink is not followed"
8933
8934         $LFS getstripe --no-follow $dir |
8935                 grep "^$dir/link_1 has no stripe info$" ||
8936                 error "symlink should not have stripe info"
8937
8938         touch $dir/testfile
8939         ln -s testfile $dir/file_link_2
8940
8941         $LFS getstripe $dir | grep "^$dir/file_link_2$" -A1 ||
8942                 error "symlink is not followed"
8943
8944         $LFS getstripe --no-follow $dir |
8945                 grep "^$dir/file_link_2 has no stripe info$" ||
8946                 error "symlink should not have stripe info"
8947 }
8948 run_test 56eb "check lfs getstripe on symlink"
8949
8950 test_56ec() {
8951         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
8952         local dir=$DIR/$tdir
8953         local srcfile=$dir/srcfile
8954         local srcyaml=$dir/srcyaml
8955         local destfile=$dir/destfile
8956
8957         test_mkdir -p $dir
8958
8959         $LFS setstripe -i 1 $srcfile
8960         $LFS getstripe --hex-idx --yaml $srcfile > $srcyaml
8961         # if the setstripe yaml parsing fails for any reason, the command can
8962         # randomly assign the correct OST index, leading to an erroneous
8963         # success. but the chance of false success is low enough that a
8964         # regression should still be quickly caught.
8965         $LFS setstripe --yaml=$srcyaml $destfile
8966
8967         local srcindex=$($LFS getstripe -i $srcfile)
8968         local destindex=$($LFS getstripe -i $destfile)
8969
8970         if [[ ! $srcindex -eq $destindex ]]; then
8971                 error "setstripe did not set OST index correctly"
8972         fi
8973 }
8974 run_test 56ec "check lfs getstripe,setstripe --hex --yaml"
8975
8976 test_56eda() {
8977         local dir=$DIR/$tdir
8978         local subdir=$dir/subdir
8979         local file1=$dir/$tfile
8980         local file2=$dir/$tfile\2
8981         local link=$dir/$tfile-link
8982         local nfiles
8983
8984         test_mkdir -p $dir
8985         $LFS setdirstripe -c1 $subdir
8986         touch $file1
8987         touch $file2
8988         ln $file2 $link
8989
8990         nfiles=$($LFS find --links 1 $dir | wc -l)
8991         (( $nfiles == 1 )) ||
8992                 error "lfs find --links expected 1 file, got $nfiles"
8993
8994         nfiles=$($LFS find --type f --links 2 $dir | wc -l)
8995         (( $nfiles == 2 )) ||
8996                 error "lfs find --links expected 2 files, got $nfiles"
8997
8998         nfiles=$($LFS find --type d --links 2 $dir | wc -l)
8999         (( $nfiles == 1 )) ||
9000                 error "lfs find --links expected 1 directory, got $nfiles"
9001 }
9002 run_test 56eda "check lfs find --links"
9003
9004 test_56edb() {
9005         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
9006
9007         local dir=$DIR/$tdir
9008         local stripedir=$dir/stripedir
9009         local nfiles
9010
9011         test_mkdir -p $dir
9012
9013         $LFS setdirstripe -c2 $stripedir
9014
9015         $LFS getdirstripe $stripedir
9016
9017         nfiles=$($LFS find --type d --links 2 $stripedir | wc -l)
9018         (( $nfiles == 1 )) ||
9019                 error "lfs find --links expected 1 directory, got $nfiles"
9020 }
9021 run_test 56edb "check lfs find --links for directory striped on multiple MDTs"
9022
9023 test_56ef() {
9024         local dir=$DIR/$tdir
9025         local dir1=$dir/d1
9026         local dir2=$dir/d2
9027         local nfiles
9028         local err_msg
9029
9030         test_mkdir -p $dir
9031
9032         mkdir $dir1
9033         mkdir $dir2
9034
9035         touch $dir1/f
9036         touch $dir2/f
9037
9038         nfiles=$($LFS find $dir1 $dir2 ! -type d | wc -l)
9039         (( $nfiles == 2 )) ||
9040                 error "(1) lfs find expected 2 files, got $nfiles"
9041
9042         nfiles=$($LFS find $dir1 $dir2 -type f | wc -l)
9043         (( $nfiles == 2 )) ||
9044                 error "(2) lfs find expected 2 files, got $nfiles"
9045
9046         nfiles=$($LFS find -type f $dir1 $dir2 | wc -l)
9047         (( $nfiles == 2 )) ||
9048                 error "(3) lfs find expected 2 files, got $nfiles"
9049
9050         err_msg=$($LFS find $dir1/typo $dir1/f 2>&1 > /dev/null)
9051         [[ $err_msg =~ "No such file or directory" ]] ||
9052                 error "expected standard error message, got: '$err_msg'"
9053 }
9054 run_test 56ef "lfs find with multiple paths"
9055
9056 test_56eg() {
9057         local dir=$DIR/$tdir
9058         local found
9059
9060         which setfattr > /dev/null 2>&1 || skip_env "no setfattr command"
9061
9062         test_mkdir -p $dir
9063
9064         touch $dir/$tfile
9065         ln -s $dir/$tfile $dir/$tfile.symlink
9066         setfattr -n "trusted.test" -v "test_target" $dir/$tfile
9067         setfattr --no-dereference -n "trusted.test" -v "test_link" \
9068                 $dir/$tfile.symlink
9069         setfattr --no-dereference -n "trusted.common" \
9070                 $dir/{$tfile,$tfile.symlink}
9071
9072         found=$($LFS find -xattr "trusted.*=test_target" \
9073                 -xattr "trusted.common" $dir)
9074         [[ "$found" == "$dir/$tfile" ]] || {
9075                 getfattr -d -m trusted.* $dir/$tfile
9076                 error "should have found '$tfile' with xattr 'trusted.test=test_target', got '$found'"
9077         }
9078
9079         found=$($LFS find -xattr "trusted.*=test_link" \
9080                 -xattr "trusted.common" $dir)
9081         [[ "$found" == "$dir/$tfile.symlink" ]] || {
9082                 getfattr --no-dereference -d -m trusted.* $dir/$tfile.symlink
9083                 error "should have found '$tfile.symlink' with xattr 'trusted.test=test_link', got '$found'"
9084         }
9085
9086         rm -f $dir/*
9087
9088         touch $dir/$tfile.1
9089         touch $dir/$tfile.2
9090         setfattr -n "user.test" -v "1" $dir/$tfile.1
9091         setfattr -n "user.test" -v "2" $dir/$tfile.2
9092         setfattr -n "user.test2" -v "common" $dir/$tfile.{1,2}
9093
9094         found=$($LFS find -xattr "user.*=common" -xattr "user.test=1" $dir)
9095         [[ "$found" == "$dir/$tfile.1" ]] || {
9096                 getfattr -d $dir/$tfile.1
9097                 error "should have found '$tfile.1' with xattr user.test=1', got '$found'"
9098         }
9099
9100         found=$($LFS find -xattr "user.*=common" ! -xattr "user.test=1" $dir)
9101         [[ "$found" == "$dir/$tfile.2" ]] || {
9102                 getfattr -d $dir/$tfile.2
9103                 error "should have found '$tfile.2' without xattr 'user.test=1', got '$found'"
9104         }
9105
9106         setfattr -n "user.empty" $dir/$tfile.1
9107         found=$($LFS find -xattr "user.empty" $dir)
9108         [[ "$found" == "$dir/$tfile.1" ]] || {
9109                 getfattr -d $dir/$tfile.1
9110                 error "should have found '$tfile.1' with xattr 'user.empty=', got '$found'"
9111         }
9112
9113         # setfattr command normally does not store terminating null byte
9114         # when writing a string as an xattr value.
9115         #
9116         # In order to test matching a value string that includes a terminating
9117         # null, explicitly encode the string "test\0" with the null terminator.
9118         setfattr -n "user.test" -v "0x7465737400" $dir/$tfile.1
9119         found=$($LFS find -xattr "user.test=test" $dir)
9120         [[ "$found" == "$dir/$tfile.1" ]] || {
9121                 getfattr -d --encoding=hex $dir/$tfile.1
9122                 error "should have found '$tfile.1' with xattr 'user.test=0x7465737400', got '$found'"
9123         }
9124 }
9125 run_test 56eg "lfs find -xattr"
9126
9127 test_57a() {
9128         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9129         # note test will not do anything if MDS is not local
9130         if [ "$mds1_FSTYPE" != ldiskfs ]; then
9131                 skip_env "ldiskfs only test"
9132         fi
9133         remote_mds_nodsh && skip "remote MDS with nodsh"
9134
9135         local MNTDEV="osd*.*MDT*.mntdev"
9136         DEV=$(do_facet $SINGLEMDS lctl get_param -n $MNTDEV)
9137         [ -z "$DEV" ] && error "can't access $MNTDEV"
9138         for DEV in $(do_facet $SINGLEMDS lctl get_param -n $MNTDEV); do
9139                 do_facet $SINGLEMDS $DUMPE2FS -h $DEV > $TMP/t57a.dump ||
9140                         error "can't access $DEV"
9141                 DEVISIZE=$(awk '/Inode size:/ { print $3 }' $TMP/t57a.dump)
9142                 [[ $DEVISIZE -gt 128 ]] || error "inode size $DEVISIZE"
9143                 rm $TMP/t57a.dump
9144         done
9145 }
9146 run_test 57a "verify MDS filesystem created with large inodes =="
9147
9148 test_57b() {
9149         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9150         if [ "$mds1_FSTYPE" != ldiskfs ]; then
9151                 skip_env "ldiskfs only test"
9152         fi
9153         remote_mds_nodsh && skip "remote MDS with nodsh"
9154
9155         local dir=$DIR/$tdir
9156         local filecount=100
9157         local file1=$dir/f1
9158         local fileN=$dir/f$filecount
9159
9160         rm -rf $dir || error "removing $dir"
9161         test_mkdir -c1 $dir
9162         local mdtidx=$($LFS getstripe -m $dir)
9163         local mdtname=MDT$(printf %04x $mdtidx)
9164         local facet=mds$((mdtidx + 1))
9165
9166         echo "mcreating $filecount files"
9167         createmany -m $dir/f 1 $filecount || error "creating files in $dir"
9168
9169         # verify that files do not have EAs yet
9170         $LFS getstripe $file1 2>&1 | grep -q "no stripe" ||
9171                 error "$file1 has an EA"
9172         $LFS getstripe $fileN 2>&1 | grep -q "no stripe" ||
9173                 error "$fileN has an EA"
9174
9175         sync
9176         sleep 1
9177         df $dir  #make sure we get new statfs data
9178         local mdsfree=$(do_facet $facet \
9179                         lctl get_param -n osd*.*$mdtname.kbytesfree)
9180         local mdcfree=$(lctl get_param -n mdc.*$mdtname-mdc-*.kbytesfree)
9181         local file
9182
9183         echo "opening files to create objects/EAs"
9184         for file in $(seq -f $dir/f%g 1 $filecount); do
9185                 $OPENFILE -f O_RDWR $file > /dev/null 2>&1 ||
9186                         error "opening $file"
9187         done
9188
9189         # verify that files have EAs now
9190         $LFS getstripe -y $file1 | grep -q "l_ost_idx" ||
9191                 error "$file1 missing EA"
9192         $LFS getstripe -y $fileN | grep -q "l_ost_idx" ||
9193                 error "$fileN missing EA"
9194
9195         sleep 1  #make sure we get new statfs data
9196         df $dir
9197         local mdsfree2=$(do_facet $facet \
9198                          lctl get_param -n osd*.*$mdtname.kbytesfree)
9199         local mdcfree2=$(lctl get_param -n mdc.*$mdtname-mdc-*.kbytesfree)
9200
9201         if [[ $mdcfree2 -lt $((mdcfree - 16)) ]]; then
9202                 if [ "$mdsfree" != "$mdsfree2" ]; then
9203                         error "MDC before $mdcfree != after $mdcfree2"
9204                 else
9205                         echo "MDC before $mdcfree != after $mdcfree2"
9206                         echo "unable to confirm if MDS has large inodes"
9207                 fi
9208         fi
9209         rm -rf $dir
9210 }
9211 run_test 57b "default LOV EAs are stored inside large inodes ==="
9212
9213 test_58() {
9214         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9215         [ -z "$(which wiretest 2>/dev/null)" ] &&
9216                         skip_env "could not find wiretest"
9217
9218         wiretest
9219 }
9220 run_test 58 "verify cross-platform wire constants =============="
9221
9222 test_59() {
9223         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9224
9225         echo "touch 130 files"
9226         createmany -o $DIR/f59- 130
9227         echo "rm 130 files"
9228         unlinkmany $DIR/f59- 130
9229         sync
9230         # wait for commitment of removal
9231         wait_delete_completed
9232 }
9233 run_test 59 "verify cancellation of llog records async ========="
9234
9235 TEST60_HEAD="test_60 run $RANDOM"
9236 test_60a() {
9237         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9238         remote_mgs_nodsh && skip "remote MGS with nodsh"
9239         do_facet mgs "! which run-llog.sh &> /dev/null" &&
9240                 do_facet mgs "! ls run-llog.sh &> /dev/null" &&
9241                         skip_env "missing subtest run-llog.sh"
9242
9243         log "$TEST60_HEAD - from kernel mode"
9244         do_facet mgs "$LCTL dk > /dev/null"
9245         do_facet mgs "bash run-llog.sh" || error "run-llog.sh failed"
9246         do_facet mgs $LCTL dk > $TMP/$tfile
9247
9248         # LU-6388: test llog_reader
9249         local llog_reader=$(do_facet mgs "which llog_reader 2> /dev/null")
9250         llog_reader=${llog_reader:-$LUSTRE/utils/llog_reader}
9251         [ -z $(do_facet mgs ls -d $llog_reader 2> /dev/null) ] &&
9252                         skip_env "missing llog_reader"
9253         local fstype=$(facet_fstype mgs)
9254         [ $fstype != ldiskfs -a $fstype != zfs ] &&
9255                 skip_env "Only for ldiskfs or zfs type mgs"
9256
9257         local mntpt=$(facet_mntpt mgs)
9258         local mgsdev=$(mgsdevname 1)
9259         local fid_list
9260         local fid
9261         local rec_list
9262         local rec
9263         local rec_type
9264         local obj_file
9265         local path
9266         local seq
9267         local oid
9268         local pass=true
9269
9270         #get fid and record list
9271         fid_list=($(awk '/9_sub.*record/ { print $NF }' $TMP/$tfile |
9272                 tail -n 4))
9273         rec_list=($(awk '/9_sub.*record/ { print $((NF-3)) }' $TMP/$tfile |
9274                 tail -n 4))
9275         #remount mgs as ldiskfs or zfs type
9276         stop mgs || error "stop mgs failed"
9277         mount_fstype mgs || error "remount mgs failed"
9278         for ((i = 0; i < ${#fid_list[@]}; i++)); do
9279                 fid=${fid_list[i]}
9280                 rec=${rec_list[i]}
9281                 seq=$(echo $fid | awk -F ':' '{ print $1 }' | sed -e "s/^0x//g")
9282                 oid=$(echo $fid | awk -F ':' '{ print $2 }' | sed -e "s/^0x//g")
9283                 oid=$((16#$oid))
9284
9285                 case $fstype in
9286                         ldiskfs )
9287                                 obj_file=$mntpt/O/$seq/d$((oid%32))/$oid ;;
9288                         zfs )
9289                                 obj_file=$mntpt/oi.$(($((16#$seq))&127))/$fid ;;
9290                 esac
9291                 echo "obj_file is $obj_file"
9292                 do_facet mgs $llog_reader $obj_file
9293
9294                 rec_type=$(do_facet mgs $llog_reader $obj_file | grep "type=" |
9295                         awk '{ print $3 }' | sed -e "s/^type=//g")
9296                 if [ $rec_type != $rec ]; then
9297                         echo "FAILED test_60a wrong record type $rec_type," \
9298                               "should be $rec"
9299                         pass=false
9300                         break
9301                 fi
9302
9303                 #check obj path if record type is LLOG_LOGID_MAGIC
9304                 if [ "$rec" == "1064553b" ]; then
9305                         path=$(do_facet mgs $llog_reader $obj_file |
9306                                 grep "path=" | awk '{ print $NF }' |
9307                                 sed -e "s/^path=//g")
9308                         if [ $obj_file != $mntpt/$path ]; then
9309                                 echo "FAILED test_60a wrong obj path" \
9310                                       "$montpt/$path, should be $obj_file"
9311                                 pass=false
9312                                 break
9313                         fi
9314                 fi
9315         done
9316         rm -f $TMP/$tfile
9317         #restart mgs before "error", otherwise it will block the next test
9318         stop mgs || error "stop mgs failed"
9319         start mgs $(mgsdevname) $MGS_MOUNT_OPTS || error "start mgs failed"
9320         $pass || error "test failed, see FAILED test_60a messages for specifics"
9321 }
9322 run_test 60a "llog_test run from kernel module and test llog_reader"
9323
9324 test_60b() { # bug 6411
9325         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9326
9327         dmesg > $DIR/$tfile
9328         LLOG_COUNT=$(do_facet mgs dmesg |
9329                      awk "/$TEST60_HEAD/ { marker = 1; from_marker = 0; }
9330                           /llog_[a-z]*.c:[0-9]/ {
9331                                 if (marker)
9332                                         from_marker++
9333                                 from_begin++
9334                           }
9335                           END {
9336                                 if (marker)
9337                                         print from_marker
9338                                 else
9339                                         print from_begin
9340                           }")
9341
9342         [[ $LLOG_COUNT -gt 120 ]] &&
9343                 error "CDEBUG_LIMIT not limiting messages ($LLOG_COUNT)" || true
9344 }
9345 run_test 60b "limit repeated messages from CERROR/CWARN"
9346
9347 test_60c() {
9348         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9349
9350         echo "create 5000 files"
9351         createmany -o $DIR/f60c- 5000
9352 #define OBD_FAIL_MDS_LLOG_CREATE_FAILED  0x137
9353         lctl set_param fail_loc=0x80000137
9354         unlinkmany $DIR/f60c- 5000
9355         lctl set_param fail_loc=0
9356 }
9357 run_test 60c "unlink file when mds full"
9358
9359 test_60d() {
9360         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9361
9362         SAVEPRINTK=$(lctl get_param -n printk)
9363         # verify "lctl mark" is even working"
9364         MESSAGE="test message ID $RANDOM $$"
9365         $LCTL mark "$MESSAGE" || error "$LCTL mark failed"
9366         dmesg | grep -q "$MESSAGE" || error "didn't find debug marker in log"
9367
9368         lctl set_param printk=0 || error "set lnet.printk failed"
9369         lctl get_param -n printk | grep emerg || error "lnet.printk dropped emerg"
9370         MESSAGE="new test message ID $RANDOM $$"
9371         # Assume here that libcfs_debug_mark_buffer() uses D_WARNING
9372         $LCTL mark "$MESSAGE" || error "$LCTL mark failed"
9373         dmesg | grep -q "$MESSAGE" && error "D_WARNING wasn't masked" || true
9374
9375         lctl set_param -n printk="$SAVEPRINTK"
9376 }
9377 run_test 60d "test printk console message masking"
9378
9379 test_60e() {
9380         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9381         remote_mds_nodsh && skip "remote MDS with nodsh"
9382
9383         touch $DIR/$tfile
9384 #define OBD_FAIL_MDS_LLOG_CREATE_FAILED2  0x15b
9385         do_facet mds1 lctl set_param fail_loc=0x15b
9386         rm $DIR/$tfile
9387 }
9388 run_test 60e "no space while new llog is being created"
9389
9390 test_60f() {
9391         local old_path=$($LCTL get_param -n debug_path)
9392
9393         stack_trap "$LCTL set_param debug_path=$old_path"
9394         stack_trap "rm -f $TMP/$tfile*"
9395         rm -f $TMP/$tfile* 2> /dev/null
9396         #define OBD_FAIL_PTLRPC_DUMP_LOG         0x50e
9397         $LCTL set_param debug_path=$TMP/$tfile fail_loc=0x8000050e
9398         test_mkdir $DIR/$tdir
9399         # retry in case the open is cached and not released
9400         for (( i = 0; i < 100 && $(ls $TMP/$tfile* | wc -l) == 0; i++ )); do
9401                 echo $i > $DIR/$tdir/$tfile.$i && cat $DIR/$tdir/$tfile.$i
9402                 sleep 0.1
9403         done
9404         ls $TMP/$tfile*
9405         (( $(ls $TMP/$tfile* | wc -l) > 0 )) || error "$TMP/$tfile not dumped"
9406 }
9407 run_test 60f "change debug_path works"
9408
9409 test_60g() {
9410         local pid
9411         local i
9412
9413         test_mkdir -c $MDSCOUNT $DIR/$tdir
9414
9415         (
9416                 local index=0
9417                 while true; do
9418                         $LFS setdirstripe -i $(($index % $MDSCOUNT)) \
9419                                 -c $MDSCOUNT $DIR/$tdir/subdir$index \
9420                                 2>/dev/null
9421                         mkdir $DIR/$tdir/subdir$index 2>/dev/null
9422                         rmdir $DIR/$tdir/subdir$index 2>/dev/null
9423                         index=$((index + 1))
9424                 done
9425         ) &
9426
9427         pid=$!
9428
9429         for i in {0..100}; do
9430                 # define OBD_FAIL_OSD_TXN_START    0x19a
9431                 local index=$((i % MDSCOUNT + 1))
9432
9433                 do_facet mds$index $LCTL set_param fail_loc=0x8000019a \
9434                         > /dev/null
9435                 sleep 0.01
9436         done
9437
9438         kill -9 $pid
9439
9440         for i in $(seq $MDSCOUNT); do
9441                 do_facet mds$i $LCTL set_param fail_loc=0 > /dev/null
9442         done
9443
9444         mkdir $DIR/$tdir/new || error "mkdir failed"
9445         rmdir $DIR/$tdir/new || error "rmdir failed"
9446
9447         do_facet mds1 $LCTL lfsck_start -M $(facet_svc mds1) -A -C \
9448                 -t namespace
9449         for i in $(seq $MDSCOUNT); do
9450                 wait_update_facet mds$i "$LCTL get_param -n \
9451                         mdd.$(facet_svc mds$i).lfsck_namespace |
9452                         awk '/^status/ { print \\\$2 }'" "completed"
9453         done
9454
9455         ls -R $DIR/$tdir
9456         rm -rf $DIR/$tdir || error "rmdir failed"
9457 }
9458 run_test 60g "transaction abort won't cause MDT hung"
9459
9460 test_60h() {
9461         [ $MDS1_VERSION -le $(version_code 2.12.52) ] &&
9462                 skip "Need MDS version at least 2.12.52"
9463         [ $MDSCOUNT -lt 2 ] && skip "Need at least 2 MDTs"
9464
9465         local f
9466
9467         #define OBD_FAIL_MDS_STRIPE_CREATE       0x188
9468         #define OBD_FAIL_MDS_STRIPE_FID          0x189
9469         for fail_loc in 0x80000188 0x80000189; do
9470                 do_facet mds1 "$LCTL set_param fail_loc=$fail_loc"
9471                 $LFS mkdir -c $MDSCOUNT -i 0 $DIR/$tdir-$fail_loc ||
9472                         error "mkdir $dir-$fail_loc failed"
9473                 for i in {0..10}; do
9474                         # create may fail on missing stripe
9475                         echo $i > $DIR/$tdir-$fail_loc/$i
9476                 done
9477                 $LFS getdirstripe $DIR/$tdir-$fail_loc ||
9478                         error "getdirstripe $tdir-$fail_loc failed"
9479                 $LFS migrate -m 1 $DIR/$tdir-$fail_loc ||
9480                         error "migrate $tdir-$fail_loc failed"
9481                 $LFS getdirstripe $DIR/$tdir-$fail_loc ||
9482                         error "getdirstripe $tdir-$fail_loc failed"
9483                 pushd $DIR/$tdir-$fail_loc
9484                 for f in *; do
9485                         echo $f | cmp $f - || error "$f data mismatch"
9486                 done
9487                 popd
9488                 rm -rf $DIR/$tdir-$fail_loc
9489         done
9490 }
9491 run_test 60h "striped directory with missing stripes can be accessed"
9492
9493 function t60i_load() {
9494         mkdir $DIR/$tdir
9495         #define OBD_FAIL_LLOG_PAUSE_AFTER_PAD               0x131c
9496         $LCTL set_param fail_loc=0x131c fail_val=1
9497         for ((i=0; i<5000; i++)); do
9498                 touch $DIR/$tdir/f$i
9499         done
9500 }
9501
9502 test_60i() {
9503         changelog_register || error "changelog_register failed"
9504         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
9505         changelog_users $SINGLEMDS | grep -q $cl_user ||
9506                 error "User $cl_user not found in changelog_users"
9507         changelog_chmask "ALL"
9508         t60i_load &
9509         local PID=$!
9510         for((i=0; i<100; i++)); do
9511                 changelog_dump >/dev/null ||
9512                         error "can't read changelog"
9513         done
9514         kill $PID
9515         wait $PID
9516         changelog_deregister || error "changelog_deregister failed"
9517         $LCTL set_param fail_loc=0
9518 }
9519 run_test 60i "llog: new record vs reader race"
9520
9521 test_60j() {
9522         (( $MDS1_VERSION >= $(version_code 2.15.50) )) ||
9523                 skip "need MDS version at least 2.15.50"
9524         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
9525         remote_mds_nodsh && skip "remote MDS with nodsh"
9526         [[ "$mds1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
9527
9528         changelog_users $SINGLEMDS | grep "^cl" &&
9529                 skip "active changelog user"
9530
9531         local llog_reader=$(do_facet $SINGLEMDS "which llog_reader 2> /dev/null")
9532
9533         [[ -z $(do_facet $SINGLEMDS ls -d $llog_reader 2> /dev/null) ]] &&
9534                 skip_env "missing llog_reader"
9535
9536         mkdir_on_mdt0 $DIR/$tdir
9537
9538         local f=$DIR/$tdir/$tfile
9539         local mdt_dev
9540         local tmpfile
9541         local plain
9542
9543         changelog_register || error "cannot register changelog user"
9544
9545         # set changelog_mask to ALL
9546         changelog_chmask "ALL"
9547         changelog_clear
9548
9549         createmany -o ${f}- 100 || error "createmany failed as $RUNAS_ID"
9550         unlinkmany ${f}- 100 || error "unlinkmany failed"
9551
9552         tmpfile="$(mktemp --tmpdir -u $tfile.XXXXXX)"
9553         mdt_dev=$(facet_device $SINGLEMDS)
9554
9555         do_facet $SINGLEMDS sync
9556         plain=$(do_facet $SINGLEMDS "$DEBUGFS -c -R 'dump changelog_catalog \
9557                 $tmpfile' $mdt_dev; $llog_reader $tmpfile" |
9558                 awk '{match($0,"path=([^ ]+)",a)}END{print a[1]}')
9559
9560         stack_trap "do_facet $SINGLEMDS rm -f $tmpfile"
9561
9562         # if $tmpfile is not on EXT3 filesystem for some reason
9563         [[ ${plain:0:1} == 'O' ]] ||
9564                 skip "path $plain is not in 'O/1/d<n>/<n>' format"
9565
9566         size=$(do_facet $SINGLEMDS "$DEBUGFS -c -R 'dump $plain $tmpfile' \
9567                 $mdt_dev; stat -c %s $tmpfile")
9568         echo "Truncate llog from $size to $((size - size % 8192))"
9569         size=$((size - size % 8192))
9570         do_facet $SINGLEMDS $TRUNCATE $tmpfile $size
9571         errs=$(do_facet $SINGLEMDS "$llog_reader $tmpfile" |
9572                 grep -c 'in bitmap only')
9573         (( $errs > 0 )) || error "llog_reader didn't find lost records"
9574
9575         size=$((size - 9000))
9576         echo "Corrupt llog in the middle at $size"
9577         do_facet $SINGLEMDS dd if=/dev/urandom of=$tmpfile bs=1 seek=$size \
9578                 count=333 conv=notrunc
9579         errs=$(do_facet $SINGLEMDS "$llog_reader $tmpfile" |
9580                 grep -c 'next chunk')
9581         (( $errs > 0 )) || error "llog_reader didn't skip bad chunk"
9582 }
9583 run_test 60j "llog_reader reports corruptions"
9584
9585 test_61a() {
9586         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9587
9588         f="$DIR/f61"
9589         dd if=/dev/zero of=$f bs=$PAGE_SIZE count=1 || error "dd $f failed"
9590         cancel_lru_locks osc
9591         $MULTIOP $f OSMWUc || error "$MULTIOP $f failed"
9592         sync
9593 }
9594 run_test 61a "mmap() writes don't make sync hang ================"
9595
9596 test_61b() {
9597         mmap_mknod_test $DIR/$tfile || error "mmap_mknod_test failed"
9598 }
9599 run_test 61b "mmap() of unstriped file is successful"
9600
9601 # bug 2319 - oig_wait() interrupted causes crash because of invalid waitq.
9602 # Though this test is irrelevant anymore, it helped to reveal some
9603 # other grant bugs (LU-4482), let's keep it.
9604 test_63a() {   # was test_63
9605         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9606
9607         MAX_DIRTY_MB=$(lctl get_param -n osc.*.max_dirty_mb | head -n 1)
9608
9609         for i in `seq 10` ; do
9610                 dd if=/dev/zero of=$DIR/f63 bs=8k &
9611                 sleep 5
9612                 kill $!
9613                 sleep 1
9614         done
9615
9616         rm -f $DIR/f63 || true
9617 }
9618 run_test 63a "Verify oig_wait interruption does not crash ======="
9619
9620 # bug 2248 - async write errors didn't return to application on sync
9621 # bug 3677 - async write errors left page locked
9622 test_63b() {
9623         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9624
9625         debugsave
9626         lctl set_param debug=-1
9627
9628         # ensure we have a grant to do async writes
9629         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1
9630         rm $DIR/$tfile
9631
9632         sync    # sync lest earlier test intercept the fail_loc
9633
9634         #define OBD_FAIL_OSC_BRW_PREP_REQ        0x406
9635         lctl set_param fail_loc=0x80000406
9636         $MULTIOP $DIR/$tfile Owy && \
9637                 error "sync didn't return ENOMEM"
9638         sync; sleep 2; sync     # do a real sync this time to flush page
9639         lctl get_param -n llite.*.dump_page_cache | grep locked && \
9640                 error "locked page left in cache after async error" || true
9641         debugrestore
9642 }
9643 run_test 63b "async write errors should be returned to fsync ==="
9644
9645 test_64a () {
9646         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9647
9648         lfs df $DIR
9649         lctl get_param osc.*[oO][sS][cC][_-]*.cur* | grep "=[1-9]"
9650 }
9651 run_test 64a "verify filter grant calculations (in kernel) ====="
9652
9653 test_64b () {
9654         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9655
9656         bash oos.sh $MOUNT || error "oos.sh failed: $?"
9657 }
9658 run_test 64b "check out-of-space detection on client"
9659
9660 test_64c() {
9661         $LCTL set_param osc.*OST0000-osc-[^mM]*.cur_grant_bytes=0
9662 }
9663 run_test 64c "verify grant shrink"
9664
9665 import_param() {
9666         local tgt=$1
9667         local param=$2
9668
9669         $LCTL get_param osc.$tgt.import | awk "/$param/ { print \$2 }"
9670 }
9671
9672 # this does exactly what osc_request.c:osc_announce_cached() does in
9673 # order to calculate max amount of grants to ask from server
9674 want_grant() {
9675         local tgt=$1
9676
9677         local nrpages=$($LCTL get_param -n osc.$tgt.max_pages_per_rpc)
9678         local rpc_in_flight=$($LCTL get_param -n osc.$tgt.max_rpcs_in_flight)
9679
9680         ((rpc_in_flight++));
9681         nrpages=$((nrpages * rpc_in_flight))
9682
9683         local dirty_max_pages=$($LCTL get_param -n osc.$tgt.max_dirty_mb)
9684
9685         dirty_max_pages=$((dirty_max_pages * 1024 * 1024 / PAGE_SIZE))
9686
9687         [[ $dirty_max_pages -gt $nrpages ]] && nrpages=$dirty_max_pages
9688         local undirty=$((nrpages * PAGE_SIZE))
9689
9690         local max_extent_pages
9691         max_extent_pages=$(import_param $tgt grant_max_extent_size)
9692         max_extent_pages=$((max_extent_pages / PAGE_SIZE))
9693         local nrextents=$(((nrpages + max_extent_pages - 1) / max_extent_pages))
9694         local grant_extent_tax
9695         grant_extent_tax=$(import_param $tgt grant_extent_tax)
9696
9697         undirty=$((undirty + nrextents * grant_extent_tax))
9698
9699         echo $undirty
9700 }
9701
9702 # this is size of unit for grant allocation. It should be equal to
9703 # what tgt_grant.c:tgt_grant_chunk() calculates
9704 grant_chunk() {
9705         local tgt=$1
9706         local max_brw_size
9707         local grant_extent_tax
9708
9709         max_brw_size=$(import_param $tgt max_brw_size)
9710
9711         grant_extent_tax=$(import_param $tgt grant_extent_tax)
9712
9713         echo $(((max_brw_size + grant_extent_tax) * 2))
9714 }
9715
9716 test_64d() {
9717         [ $OST1_VERSION -ge $(version_code 2.10.56) ] ||
9718                 skip "OST < 2.10.55 doesn't limit grants enough"
9719
9720         local tgt=$($LCTL dl | awk '/OST0000-osc-[^mM]/ { print $4 }')
9721
9722         [[ "$($LCTL get_param osc.${tgt}.import)" =~ "grant_param" ]] ||
9723                 skip "no grant_param connect flag"
9724
9725         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
9726
9727         $LCTL set_param -n -n debug="$OLDDEBUG" || true
9728         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
9729
9730
9731         local max_cur_granted=$(($(want_grant $tgt) + $(grant_chunk $tgt)))
9732         stack_trap "rm -f $DIR/$tfile && wait_delete_completed" EXIT
9733
9734         $LFS setstripe $DIR/$tfile -i 0 -c 1
9735         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1000 &
9736         ddpid=$!
9737
9738         while kill -0 $ddpid; do
9739                 local cur_grant=$($LCTL get_param -n osc.$tgt.cur_grant_bytes)
9740
9741                 if [[ $cur_grant -gt $max_cur_granted ]]; then
9742                         kill $ddpid
9743                         error "cur_grant $cur_grant > $max_cur_granted"
9744                 fi
9745
9746                 sleep 1
9747         done
9748 }
9749 run_test 64d "check grant limit exceed"
9750
9751 check_grants() {
9752         local tgt=$1
9753         local expected=$2
9754         local msg=$3
9755         local cur_grants=$($LCTL get_param -n osc.$tgt.cur_grant_bytes)
9756
9757         ((cur_grants == expected)) ||
9758                 error "$msg: grants mismatch: $cur_grants, expected $expected"
9759 }
9760
9761 round_up_p2() {
9762         echo $((($1 + $2 - 1) & ~($2 - 1)))
9763 }
9764
9765 test_64e() {
9766         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9767         [ $OST1_VERSION -ge $(version_code 2.11.56) ] ||
9768                 skip "Need OSS version at least 2.11.56"
9769
9770         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
9771         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
9772         $LCTL set_param debug=+cache
9773
9774         # Remount client to reset grant
9775         remount_client $MOUNT || error "failed to remount client"
9776         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
9777
9778         local init_grants=$(import_param $osc_tgt initial_grant)
9779
9780         check_grants $osc_tgt $init_grants "init grants"
9781
9782         local extent_tax=$(import_param $osc_tgt grant_extent_tax)
9783         local max_brw_size=$(import_param $osc_tgt max_brw_size)
9784         local gbs=$(import_param $osc_tgt grant_block_size)
9785
9786         # write random number of bytes from max_brw_size / 4 to max_brw_size
9787         local write_bytes=$(shuf -i $((max_brw_size / 4))-$max_brw_size -n 1)
9788         # align for direct io
9789         write_bytes=$(round_up_p2 $write_bytes PAGE_SIZE)
9790         # round to grant consumption unit
9791         local wb_round_up=$(round_up_p2 $write_bytes gbs)
9792
9793         local grants=$((wb_round_up + extent_tax))
9794
9795         $LFS setstripe -c 1 -i 0 $DIR/$tfile  || error "lfs setstripe failed"
9796         stack_trap "rm -f $DIR/$tfile"
9797
9798         # define OBD_FAIL_TGT_NO_GRANT 0x725
9799         # make the server not grant more back
9800         do_facet ost1 $LCTL set_param fail_loc=0x725
9801         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 oflag=direct
9802
9803         do_facet ost1 $LCTL set_param fail_loc=0
9804
9805         check_grants $osc_tgt $((init_grants - grants)) "dio w/o grant alloc"
9806
9807         rm -f $DIR/$tfile || error "rm failed"
9808
9809         # Remount client to reset grant
9810         remount_client $MOUNT || error "failed to remount client"
9811         osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
9812
9813         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
9814
9815         # define OBD_FAIL_TGT_NO_GRANT 0x725
9816         # make the server not grant more back
9817         do_facet ost1 $LCTL set_param fail_loc=0x725
9818         $MULTIOP $DIR/$tfile "oO_WRONLY:w${write_bytes}yc"
9819         do_facet ost1 $LCTL set_param fail_loc=0
9820
9821         check_grants $osc_tgt $((init_grants - grants)) "buf io w/o grant alloc"
9822 }
9823 run_test 64e "check grant consumption (no grant allocation)"
9824
9825 test_64f() {
9826         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9827
9828         local olddebug="$($LCTL get_param -n debug 2> /dev/null)"
9829         stack_trap "$LCTL set_param -n debug='$olddebug'" EXIT
9830         $LCTL set_param debug=+cache
9831
9832         # Remount client to reset grant
9833         remount_client $MOUNT || error "failed to remount client"
9834         local osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
9835
9836         local init_grants=$(import_param $osc_tgt initial_grant)
9837         local extent_tax=$(import_param $osc_tgt grant_extent_tax)
9838         local max_brw_size=$(import_param $osc_tgt max_brw_size)
9839         local gbs=$(import_param $osc_tgt grant_block_size)
9840         local chunk=$(grant_chunk $osc_tgt)
9841
9842         # write random number of bytes from max_brw_size / 4 to max_brw_size
9843         local write_bytes=$(shuf -i $((max_brw_size / 4))-$max_brw_size -n 1)
9844         # align for direct io
9845         write_bytes=$(round_up_p2 $write_bytes PAGE_SIZE)
9846         # round to grant consumption unit
9847         local wb_round_up=$(round_up_p2 $write_bytes gbs)
9848
9849         local grants=$((wb_round_up + extent_tax))
9850
9851         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
9852         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 oflag=direct ||
9853                 error "error writing to $DIR/$tfile"
9854
9855         check_grants $osc_tgt $((init_grants - grants + chunk)) \
9856                 "direct io with grant allocation"
9857
9858         rm -f $DIR/$tfile || error "rm failed"
9859
9860         # Remount client to reset grant
9861         remount_client $MOUNT || error "failed to remount client"
9862         osc_tgt="$FSNAME-OST0000-osc-$($LFS getname -i $DIR)"
9863
9864         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "lfs setstripe failed"
9865
9866         # Testing that buffered IO consumes grant on the client
9867
9868         # Delay the RPC on the server so it's guaranteed to not complete even
9869         # if the RPC is sent from the client
9870         #define OBD_FAIL_PTLRPC_PAUSE_REQ        0x50a
9871         $LCTL set_param fail_loc=0x50a fail_val=3
9872         dd if=/dev/zero of=$DIR/$tfile bs=$write_bytes count=1 conv=notrunc ||
9873                 error "error writing to $DIR/$tfile with buffered IO"
9874
9875         check_grants $osc_tgt $((init_grants - grants)) \
9876                 "buffered io, not write rpc"
9877
9878         # Clear the fail loc and do a sync on the client
9879         $LCTL set_param fail_loc=0 fail_val=0
9880         sync
9881
9882         # RPC is now known to have sent
9883         check_grants $osc_tgt $((init_grants - grants + chunk)) \
9884                 "buffered io, one RPC"
9885 }
9886 run_test 64f "check grant consumption (with grant allocation)"
9887
9888 test_64g() {
9889         (( $MDS1_VERSION >= $(version_code 2.14.56) )) ||
9890                 skip "Need MDS version at least 2.14.56"
9891
9892         local mdts=$(comma_list $(mdts_nodes))
9893
9894         local old=$($LCTL get_param mdc.$FSNAME-*.grant_shrink_interval |
9895                         tr '\n' ' ')
9896         stack_trap "$LCTL set_param $old"
9897
9898         # generate dirty pages and increase dirty granted on MDT
9899         stack_trap "rm -f $DIR/$tfile-*"
9900         for (( i = 0; i < 10; i++)); do
9901                 $LFS setstripe -E 1M -L mdt $DIR/$tfile-$i ||
9902                         error "can't set stripe"
9903                 dd if=/dev/zero of=$DIR/$tfile-$i bs=128k count=1 ||
9904                         error "can't dd"
9905                 $LFS getstripe $DIR/$tfile-$i | grep -q pattern.*mdt || {
9906                         $LFS getstripe $DIR/$tfile-$i
9907                         error "not DoM file"
9908                 }
9909         done
9910
9911         # flush dirty pages
9912         sync
9913
9914         # wait until grant shrink reset grant dirty on MDTs
9915         for ((i = 0; i < 120; i++)); do
9916                 grant_dirty=$(do_nodes $mdts $LCTL get_param -n  mdt.*.tot_dirty |
9917                         awk '{sum=sum+$1} END {print sum}')
9918                 vm_dirty=$(awk '/Dirty:/{print $2}' /proc/meminfo)
9919                 echo "$grant_dirty grants, $vm_dirty pages"
9920                 (( grant_dirty + vm_dirty == 0 )) && break
9921                 (( i == 3 )) && sync &&
9922                         $LCTL set_param mdc.$FSNAME-*.grant_shrink_interval=5
9923                 sleep 1
9924         done
9925
9926         grant_dirty=$(do_nodes $mdts $LCTL get_param -n  mdt.*.tot_dirty |
9927                 awk '{sum=sum+$1} END {print sum}')
9928         (( grant_dirty == 0 )) || error "$grant_dirty on MDT"
9929 }
9930 run_test 64g "grant shrink on MDT"
9931
9932 test_64h() {
9933         (( $OST1_VERSION >= $(version_code 2.14.56) )) ||
9934                 skip "need OST at least 2.14.56 to avoid grant shrink on read"
9935
9936         local instance=$($LFS getname -i $DIR)
9937         local osc_tgt="$FSNAME-OST0000-osc-$instance"
9938         local num_exps=$(do_facet ost1 \
9939             $LCTL get_param -n obdfilter.*OST0000*.num_exports)
9940         local max_brw_size=$(import_param $osc_tgt max_brw_size)
9941         local avail=$($LCTL get_param -n osc.*OST0000-osc-$instance.kbytesavail)
9942         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
9943
9944         # 10MiB is for file to be written, max_brw_size * 16 *
9945         # num_exps is space reserve so that tgt_grant_shrink() decided
9946         # to not shrink
9947         local expect=$((max_brw_size * 16 * num_exps + 10 * 1048576))
9948         (( avail * 1024 < expect )) &&
9949                 skip "need $expect bytes on ost1, have $(( avail * 1024 )) only"
9950
9951         save_lustre_params client "osc.*OST0000*.grant_shrink" > $p
9952         save_lustre_params client "osc.*OST0000*.grant_shrink_interval" >> $p
9953         stack_trap "restore_lustre_params < $p; rm -f $save" EXIT
9954         $LCTL set_param osc.*OST0000*.grant_shrink=1
9955         $LCTL set_param osc.*OST0000*.grant_shrink_interval=10
9956
9957         $LFS setstripe -c 1 -i 0 $DIR/$tfile
9958         stack_trap "rm -f $DIR/$tfile"
9959         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 oflag=sync
9960
9961         # drop cache so that coming read would do rpc
9962         cancel_lru_locks osc
9963
9964         # shrink interval is set to 10, pause for 7 seconds so that
9965         # grant thread did not wake up yet but coming read entered
9966         # shrink mode for rpc (osc_should_shrink_grant())
9967         sleep 7
9968
9969         declare -a cur_grant_bytes
9970         declare -a tot_granted
9971         cur_grant_bytes[0]=$($LCTL get_param -n osc.*OST0000*.cur_grant_bytes)
9972         tot_granted[0]=$(do_facet ost1 \
9973             $LCTL get_param -n obdfilter.*OST0000*.tot_granted)
9974
9975         dd if=$DIR/$tfile bs=4K count=1 of=/dev/null
9976
9977         cur_grant_bytes[1]=$($LCTL get_param -n osc.*OST0000*.cur_grant_bytes)
9978         tot_granted[1]=$(do_facet ost1 \
9979             $LCTL get_param -n obdfilter.*OST0000*.tot_granted)
9980
9981         # grant change should be equal on both sides
9982         (( cur_grant_bytes[0] - cur_grant_bytes[1] ==
9983                 tot_granted[0] - tot_granted[1])) ||
9984                 error "grant change mismatch, "                                \
9985                         "server: ${tot_granted[0]} to ${tot_granted[1]}, "     \
9986                         "client: ${cur_grant_bytes[0]} to ${cur_grant_bytes[1]}"
9987 }
9988 run_test 64h "grant shrink on read"
9989
9990 test_64i() {
9991         (( $OST1_VERSION >= $(version_code 2.14.56) )) ||
9992                 skip "need OST at least 2.14.56 to avoid grant shrink on replay"
9993
9994         [ $PARALLEL == "yes" ] && skip "skip parallel run"
9995         remote_ost_nodsh && skip "remote OSTs with nodsh"
9996
9997         $LFS setstripe -c 1 -i 0 $DIR/$tfile
9998         stack_trap "rm -f $DIR/$tfile"
9999
10000         dd if=/dev/zero of=$DIR/$tfile bs=1M count=64
10001
10002         # lustre-ffff9fc75e850800 /mnt/lustre -> ffff9fc75e850800
10003         local instance=$($LFS getname -i $DIR)
10004
10005         local osc_tgt="$FSNAME-OST0000-osc-$instance"
10006         local cgb=$($LCTL get_param -n osc.$osc_tgt.cur_grant_bytes)
10007
10008         # shrink grants and simulate rpc loss
10009         #define OBD_FAIL_PTLRPC_DROP_REQ_OPC     0x513
10010         do_facet ost1 "$LCTL set_param fail_loc=0x80000513 fail_val=17"
10011         $LCTL set_param osc.$osc_tgt.cur_grant_bytes=$((cgb/2))B
10012
10013         fail ost1
10014
10015         dd if=/dev/zero of=$DIR/$tfile oflag=append bs=1M count=8 conv=notrunc
10016
10017         local testid=$(echo $TESTNAME | tr '_' ' ')
10018
10019         do_facet ost1 dmesg | tac | sed "/$testid/,$ d" |
10020                 grep "GRANT, real grant" &&
10021                 error "client has more grants then it owns" || true
10022 }
10023 run_test 64i "shrink on reconnect"
10024
10025 # bug 1414 - set/get directories' stripe info
10026 test_65a() {
10027         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10028
10029         test_mkdir $DIR/$tdir
10030         touch $DIR/$tdir/f1
10031         $LVERIFY $DIR/$tdir $DIR/$tdir/f1 || error "lverify failed"
10032 }
10033 run_test 65a "directory with no stripe info"
10034
10035 test_65b() {
10036         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10037
10038         test_mkdir $DIR/$tdir
10039         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
10040
10041         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
10042                                                 error "setstripe"
10043         touch $DIR/$tdir/f2
10044         $LVERIFY $DIR/$tdir $DIR/$tdir/f2 || error "lverify failed"
10045 }
10046 run_test 65b "directory setstripe -S stripe_size*2 -i 0 -c 1"
10047
10048 test_65c() {
10049         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10050         [ $OSTCOUNT -lt 2 ] && skip_env "need at least 2 OSTs"
10051
10052         test_mkdir $DIR/$tdir
10053         local stripesize=$($LFS getstripe -S $DIR/$tdir)
10054
10055         $LFS setstripe -S $((stripesize * 4)) -i 1 \
10056                 -c $((OSTCOUNT - 1)) $DIR/$tdir || error "setstripe"
10057         touch $DIR/$tdir/f3
10058         $LVERIFY $DIR/$tdir $DIR/$tdir/f3 || error "lverify failed"
10059 }
10060 run_test 65c "directory setstripe -S stripe_size*4 -i 1 -c $((OSTCOUNT-1))"
10061
10062 test_65d() {
10063         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10064
10065         test_mkdir $DIR/$tdir
10066         local STRIPECOUNT=$($LFS getstripe -c $DIR/$tdir)
10067         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
10068
10069         if [[ $STRIPECOUNT -le 0 ]]; then
10070                 sc=1
10071         elif [[ $STRIPECOUNT -gt $LOV_MAX_STRIPE_COUNT ]]; then
10072                 [[ $OSTCOUNT -gt $LOV_MAX_STRIPE_COUNT ]] &&
10073                         sc=$LOV_MAX_STRIPE_COUNT || sc=$(($OSTCOUNT - 1))
10074         else
10075                 sc=$(($STRIPECOUNT - 1))
10076         fi
10077         $LFS setstripe -S $STRIPESIZE -c $sc $DIR/$tdir || error "setstripe"
10078         touch $DIR/$tdir/f4 $DIR/$tdir/f5
10079         $LVERIFY $DIR/$tdir $DIR/$tdir/f4 $DIR/$tdir/f5 ||
10080                 error "lverify failed"
10081 }
10082 run_test 65d "directory setstripe -S stripe_size -c stripe_count"
10083
10084 test_65e() {
10085         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10086
10087         # LU-16904 delete layout when root is set as PFL layout
10088         save_layout_restore_at_exit $MOUNT
10089         $LFS setstripe -d $MOUNT || error "setstripe failed"
10090
10091         test_mkdir $DIR/$tdir
10092
10093         $LFS setstripe $DIR/$tdir || error "setstripe"
10094         $LFS getstripe -v $DIR/$tdir | grep "Default" ||
10095                                         error "no stripe info failed"
10096         touch $DIR/$tdir/f6
10097         $LVERIFY $DIR/$tdir $DIR/$tdir/f6 || error "lverify failed"
10098 }
10099 run_test 65e "directory setstripe defaults"
10100
10101 test_65f() {
10102         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10103
10104         test_mkdir $DIR/${tdir}f
10105         $RUNAS $LFS setstripe $DIR/${tdir}f &&
10106                 error "setstripe succeeded" || true
10107 }
10108 run_test 65f "dir setstripe permission (should return error) ==="
10109
10110 test_65g() {
10111         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10112
10113         # LU-16904 delete layout when root is set as PFL layout
10114         save_layout_restore_at_exit $MOUNT
10115         $LFS setstripe -d $MOUNT || error "setstripe failed"
10116
10117         test_mkdir $DIR/$tdir
10118         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
10119
10120         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
10121                 error "setstripe -S failed"
10122         $LFS setstripe -d $DIR/$tdir || error "setstripe -d failed"
10123         $LFS getstripe -v $DIR/$tdir | grep "Default" ||
10124                 error "delete default stripe failed"
10125 }
10126 run_test 65g "directory setstripe -d"
10127
10128 test_65h() {
10129         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10130
10131         test_mkdir $DIR/$tdir
10132         local STRIPESIZE=$($LFS getstripe -S $DIR/$tdir)
10133
10134         $LFS setstripe -S $((STRIPESIZE * 2)) -i 0 -c 1 $DIR/$tdir ||
10135                 error "setstripe -S failed"
10136         test_mkdir $DIR/$tdir/dd1
10137         [ $($LFS getstripe -c $DIR/$tdir) = $($LFS getstripe -c $DIR/$tdir/dd1) ] ||
10138                 error "stripe info inherit failed"
10139 }
10140 run_test 65h "directory stripe info inherit ===================="
10141
10142 test_65i() {
10143         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10144
10145         save_layout_restore_at_exit $MOUNT
10146
10147         # bug6367: set non-default striping on root directory
10148         $LFS setstripe -S 65536 -c -1 $MOUNT || error "error setting stripe"
10149
10150         # bug12836: getstripe on -1 default directory striping
10151         $LFS getstripe $MOUNT || error "getstripe $MOUNT failed"
10152
10153         # bug12836: getstripe -v on -1 default directory striping
10154         $LFS getstripe -v $MOUNT || error "getstripe -v $MOUNT failed"
10155
10156         # bug12836: new find on -1 default directory striping
10157         $LFS find -mtime -1 $MOUNT > /dev/null || error "find $MOUNT failed"
10158 }
10159 run_test 65i "various tests to set root directory striping"
10160
10161 test_65j() { # bug6367
10162         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10163
10164         sync; sleep 1
10165
10166         # if we aren't already remounting for each test, do so for this test
10167         if [ "$I_MOUNTED" = "yes" ]; then
10168                 cleanup || error "failed to unmount"
10169                 setup
10170         fi
10171
10172         save_layout_restore_at_exit $MOUNT
10173
10174         $LFS setstripe -d $MOUNT || error "setstripe failed"
10175 }
10176 run_test 65j "set default striping on root directory (bug 6367)="
10177
10178 cleanup_65k() {
10179         rm -rf $DIR/$tdir
10180         wait_delete_completed
10181         do_facet $SINGLEMDS "lctl set_param -n \
10182                 osp.$ost*MDT0000.max_create_count=$max_count"
10183         do_facet $SINGLEMDS "lctl set_param -n \
10184                 osp.$ost*MDT0000.create_count=$count"
10185         do_facet $SINGLEMDS lctl --device  %$INACTIVE_OSC activate
10186         echo $INACTIVE_OSC "is Activate"
10187
10188         wait_osc_import_state mds ost$(( ostnum + 1 )) FULL
10189 }
10190
10191 test_65k() { # bug11679
10192         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10193         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
10194         remote_mds_nodsh && skip "remote MDS with nodsh"
10195
10196         local disable_precreate=true
10197         [ $MDS1_VERSION -le $(version_code 2.8.54) ] &&
10198                 disable_precreate=false
10199
10200         echo "Check OST status: "
10201         local MDS_OSCS=$(do_facet $SINGLEMDS lctl dl |
10202                 awk '/[oO][sS][cC].*md[ts]/ { print $4 }')
10203
10204         for OSC in $MDS_OSCS; do
10205                 echo $OSC "is active"
10206                 do_facet $SINGLEMDS lctl --device %$OSC activate
10207         done
10208
10209         for INACTIVE_OSC in $MDS_OSCS; do
10210                 local ost=$(osc_to_ost $INACTIVE_OSC)
10211                 local ostnum=$(do_facet $SINGLEMDS lctl get_param -n \
10212                                lov.*md*.target_obd |
10213                                awk -F: /$ost/'{ print $1 }' | head -n 1)
10214
10215                 mkdir -p $DIR/$tdir
10216                 $LFS setstripe -i $ostnum -c 1 $DIR/$tdir
10217                 createmany -o $DIR/$tdir/$tfile.$ostnum. 1000
10218
10219                 echo "Deactivate: " $INACTIVE_OSC
10220                 do_facet $SINGLEMDS lctl --device %$INACTIVE_OSC deactivate
10221
10222                 local count=$(do_facet $SINGLEMDS "lctl get_param -n \
10223                               osp.$ost*MDT0000.create_count")
10224                 local max_count=$(do_facet $SINGLEMDS "lctl get_param -n \
10225                                   osp.$ost*MDT0000.max_create_count")
10226                 $disable_precreate &&
10227                         do_facet $SINGLEMDS "lctl set_param -n \
10228                                 osp.$ost*MDT0000.max_create_count=0"
10229
10230                 for idx in $(seq 0 $((OSTCOUNT - 1))); do
10231                         [ -f $DIR/$tdir/$idx ] && continue
10232                         echo "$LFS setstripe -i $idx -c 1 $DIR/$tdir/$idx"
10233                         $LFS setstripe -i $idx -c 1 $DIR/$tdir/$idx ||
10234                                 { cleanup_65k;
10235                                   error "setstripe $idx should succeed"; }
10236                         rm -f $DIR/$tdir/$idx || error "rm $idx failed"
10237                 done
10238                 unlinkmany $DIR/$tdir/$tfile.$ostnum. 1000
10239                 rmdir $DIR/$tdir
10240
10241                 do_facet $SINGLEMDS "lctl set_param -n \
10242                         osp.$ost*MDT0000.max_create_count=$max_count"
10243                 do_facet $SINGLEMDS "lctl set_param -n \
10244                         osp.$ost*MDT0000.create_count=$count"
10245                 do_facet $SINGLEMDS lctl --device  %$INACTIVE_OSC activate
10246                 echo $INACTIVE_OSC "is Activate"
10247
10248                 wait_osc_import_state mds ost$(( ostnum + 1 )) FULL
10249         done
10250 }
10251 run_test 65k "validate manual striping works properly with deactivated OSCs"
10252
10253 test_65l() { # bug 12836
10254         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10255
10256         test_mkdir -p $DIR/$tdir/test_dir
10257         $LFS setstripe -c -1 $DIR/$tdir/test_dir
10258         $LFS find -mtime -1 $DIR/$tdir >/dev/null
10259 }
10260 run_test 65l "lfs find on -1 stripe dir ========================"
10261
10262 test_65m() {
10263         local layout=$(save_layout $MOUNT)
10264         $RUNAS $LFS setstripe -c 2 $MOUNT && {
10265                 restore_layout $MOUNT $layout
10266                 error "setstripe should fail by non-root users"
10267         }
10268         true
10269 }
10270 run_test 65m "normal user can't set filesystem default stripe"
10271
10272 test_65n() {
10273         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
10274         [[ $MDS1_VERSION -ge $(version_code 2.12.50) ]] ||
10275                 skip "Need MDS version at least 2.12.50"
10276         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
10277
10278         [[ $OSTCOUNT -ge 2 ]] || skip_env "needs >= 2 OSTs"
10279         which getfattr > /dev/null 2>&1 || skip_env "no getfattr command"
10280         which setfattr > /dev/null 2>&1 || skip_env "no setfattr command"
10281
10282         save_layout_restore_at_exit $MOUNT
10283
10284         # new subdirectory under root directory should not inherit
10285         # the default layout from root
10286         # LU-16904 check if the root is set as PFL layout
10287         local numcomp=$($LFS getstripe --component-count $MOUNT)
10288
10289         if [[ $numcomp -eq 0 ]]; then
10290                 local dir1=$MOUNT/$tdir-1
10291                 mkdir $dir1 || error "mkdir $dir1 failed"
10292                 ! getfattr -n trusted.lov $dir1 &> /dev/null ||
10293                         error "$dir1 shouldn't have LOV EA"
10294         fi
10295
10296         # delete the default layout on root directory
10297         $LFS setstripe -d $MOUNT || error "delete root default layout failed"
10298
10299         local dir2=$MOUNT/$tdir-2
10300         mkdir $dir2 || error "mkdir $dir2 failed"
10301         ! getfattr -n trusted.lov $dir2 &> /dev/null ||
10302                 error "$dir2 shouldn't have LOV EA"
10303
10304         # set a new striping pattern on root directory
10305         local def_stripe_size=$($LFS getstripe -S $MOUNT)
10306         local new_def_stripe_size=$((def_stripe_size * 2))
10307         $LFS setstripe -S $new_def_stripe_size $MOUNT ||
10308                 error "set stripe size on $MOUNT failed"
10309
10310         # new file created in $dir2 should inherit the new stripe size from
10311         # the filesystem default
10312         local file2=$dir2/$tfile-2
10313         touch $file2 || error "touch $file2 failed"
10314
10315         local file2_stripe_size=$($LFS getstripe -S $file2)
10316         [[ $file2_stripe_size -eq $new_def_stripe_size ]] ||
10317         {
10318                 echo "file2_stripe_size: '$file2_stripe_size'"
10319                 echo "new_def_stripe_size: '$new_def_stripe_size'"
10320                 error "$file2 didn't inherit stripe size $new_def_stripe_size"
10321         }
10322
10323         local dir3=$MOUNT/$tdir-3
10324         mkdir $dir3 || error "mkdir $dir3 failed"
10325         # $dir3 shouldn't have LOV EA, but "lfs getstripe -d $dir3" should show
10326         # the root layout, which is the actual default layout that will be used
10327         # when new files are created in $dir3.
10328         local dir3_layout=$(get_layout_param $dir3)
10329         local root_dir_layout=$(get_layout_param $MOUNT)
10330         [[ "$dir3_layout" = "$root_dir_layout" ]] ||
10331         {
10332                 echo "dir3_layout: '$dir3_layout'"
10333                 echo "root_dir_layout: '$root_dir_layout'"
10334                 error "$dir3 should show the default layout from $MOUNT"
10335         }
10336
10337         # set OST pool on root directory
10338         local pool=$TESTNAME
10339         pool_add $pool || error "add $pool failed"
10340         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
10341                 error "add targets to $pool failed"
10342
10343         $LFS setstripe -p $pool $MOUNT ||
10344                 error "set OST pool on $MOUNT failed"
10345
10346         # new file created in $dir3 should inherit the pool from
10347         # the filesystem default
10348         local file3=$dir3/$tfile-3
10349         touch $file3 || error "touch $file3 failed"
10350
10351         local file3_pool=$($LFS getstripe -p $file3)
10352         [[ "$file3_pool" = "$pool" ]] ||
10353                 error "$file3 ('$file3_pool') didn't inherit OST pool '$pool'"
10354
10355         local dir4=$MOUNT/$tdir-4
10356         mkdir $dir4 || error "mkdir $dir4 failed"
10357         local dir4_layout=$(get_layout_param $dir4)
10358         root_dir_layout=$(get_layout_param $MOUNT)
10359         echo "$LFS getstripe -d $dir4"
10360         $LFS getstripe -d $dir4
10361         echo "$LFS getstripe -d $MOUNT"
10362         $LFS getstripe -d $MOUNT
10363         [[ "$dir4_layout" = "$root_dir_layout" ]] ||
10364         {
10365                 echo "dir4_layout: '$dir4_layout'"
10366                 echo "root_dir_layout: '$root_dir_layout'"
10367                 error "$dir4 should show the default layout from $MOUNT"
10368         }
10369
10370         # new file created in $dir4 should inherit the pool from
10371         # the filesystem default
10372         local file4=$dir4/$tfile-4
10373         touch $file4 || error "touch $file4 failed"
10374
10375         local file4_pool=$($LFS getstripe -p $file4)
10376         [[ "$file4_pool" = "$pool" ]] ||
10377                 error "$file4 ('$file4_pool') didn't inherit OST pool $pool"
10378
10379         # new subdirectory under non-root directory should inherit
10380         # the default layout from its parent directory
10381         $LFS setstripe -S $new_def_stripe_size -p $pool $dir4 ||
10382                 error "set directory layout on $dir4 failed"
10383
10384         local dir5=$dir4/$tdir-5
10385         mkdir $dir5 || error "mkdir $dir5 failed"
10386
10387         dir4_layout=$(get_layout_param $dir4)
10388         local dir5_layout=$(get_layout_param $dir5)
10389         [[ "$dir4_layout" = "$dir5_layout" ]] ||
10390         {
10391                 echo "dir4_layout: '$dir4_layout'"
10392                 echo "dir5_layout: '$dir5_layout'"
10393                 error "$dir5 should inherit the default layout from $dir4"
10394         }
10395
10396         # though subdir under ROOT doesn't inherit default layout, but
10397         # its sub dir/file should be created with default layout.
10398         [[ $MDSCOUNT -ge 2 ]] || skip_env "needs >= 2 MDTs"
10399         [[ $MDS1_VERSION -ge $(version_code 2.12.59) ]] ||
10400                 skip "Need MDS version at least 2.12.59"
10401
10402         local default_lmv_count=$($LFS getdirstripe -D -c $MOUNT)
10403         local default_lmv_index=$($LFS getdirstripe -D -i $MOUNT)
10404         local default_lmv_hash=$($LFS getdirstripe -D -H $MOUNT)
10405
10406         if [ $default_lmv_hash == "none" ]; then
10407                 stack_trap "$LFS setdirstripe -D -d $MOUNT" EXIT
10408         else
10409                 stack_trap "$LFS setdirstripe -D -i $default_lmv_index \
10410                         -c $default_lmv_count -H $default_lmv_hash $MOUNT" EXIT
10411         fi
10412
10413         $LFS setdirstripe -D -c 2 $MOUNT ||
10414                 error "setdirstripe -D -c 2 failed"
10415         mkdir $MOUNT/$tdir-6 || error "mkdir $tdir-6 failed"
10416         local lmv_count=$($LFS getdirstripe -c $MOUNT/$tdir-6)
10417         [ $lmv_count -eq 2 ] || error "$tdir-6 stripe count $lmv_count"
10418
10419         # $dir4 layout includes pool
10420         $LFS setstripe -S $((new_def_stripe_size * 2)) $dir4
10421         [[ "$pool" = $($LFS getstripe -p -d $dir4) ]] ||
10422                 error "pool lost on setstripe"
10423         $LFS setstripe -E -1 -S $new_def_stripe_size $dir4
10424         [[ "$pool" = $($LFS getstripe -p -d $dir4) ]] ||
10425                 error "pool lost on compound layout setstripe"
10426 }
10427 run_test 65n "don't inherit default layout from root for new subdirectories"
10428
10429 test_65o() {
10430         (( $MDS1_VERSION >= $(version_code 2.14.57) )) ||
10431                 skip "need MDS version at least 2.14.57"
10432
10433         # set OST pool on root directory
10434         local pool=$TESTNAME
10435
10436         pool_add $pool || error "add $pool failed"
10437         pool_add_targets $pool 0 $((OSTCOUNT - 1)) 1 ||
10438                 error "add targets to $pool failed"
10439
10440         local dir1=$MOUNT/$tdir
10441
10442         mkdir $dir1 || error "mkdir $dir1 failed"
10443
10444         # set a new striping pattern on root directory
10445         local def_stripe_size=$($LFS getstripe -S $MOUNT)
10446
10447         $LFS setstripe -p $pool $dir1 ||
10448                 error "set directory layout on $dir1 failed"
10449
10450         # $dir1 layout includes pool
10451         $LFS setstripe -S $((def_stripe_size * 2)) $dir1
10452         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
10453                 error "pool lost on setstripe"
10454         $LFS setstripe -E 1M -L mdt -E -1 -c 1 $dir1
10455         $LFS getstripe $dir1
10456         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
10457                 error "pool lost on compound layout setstripe"
10458
10459         $LFS setdirstripe -i 0 -c 2 $dir1/dir2 ||
10460                 error "setdirstripe failed on sub-dir with inherited pool"
10461         $LFS getstripe $dir1/dir2
10462         [[ "$pool" = $($LFS getstripe -p -d $dir1/dir2) ]] ||
10463                 error "pool lost on compound layout setdirstripe"
10464
10465         $LFS setstripe -E -1 -c 1 $dir1
10466         $LFS getstripe -d $dir1
10467         [[ "$pool" = $($LFS getstripe -p -d $dir1) ]] ||
10468                 error "pool lost on setstripe"
10469 }
10470 run_test 65o "pool inheritance for mdt component"
10471
10472 test_65p () { # LU-16152
10473         local src_dir=$DIR/$tdir/src_dir
10474         local dst_dir=$DIR/$tdir/dst_dir
10475         local yaml_file=$DIR/$tdir/layout.yaml
10476         local border
10477
10478         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) ||
10479                 skip "Need at least version 2.15.51"
10480
10481         test_mkdir -p $src_dir
10482         $LFS setstripe -E 2048M -c 4 -E EOF -c 8 $src_dir ||
10483                 error "failed to setstripe"
10484         $LFS getstripe --yaml -d $src_dir > $yaml_file ||
10485                 error "failed to getstripe"
10486
10487         test_mkdir -p $dst_dir
10488         $LFS setstripe --yaml $yaml_file $dst_dir ||
10489                 error "failed to setstripe with yaml file"
10490         border=$($LFS getstripe -d $dst_dir |
10491                 awk '/lcme_extent.e_end:/ { print $2; exit; }') ||
10492                 error "failed to getstripe"
10493
10494         # 2048M is 0x80000000, or 2147483648
10495         (( $border == 2147483648 )) ||
10496                 error "failed to handle huge number in yaml layout"
10497 }
10498 run_test 65p "setstripe with yaml file and huge number"
10499
10500 test_65p () { # LU-16194
10501         local src_dir=$DIR/$tdir/src_dir
10502
10503         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) ||
10504                 skip "Need at least version 2.15.51"
10505
10506         test_mkdir -p $src_dir
10507         # 8E is 0x8000 0000 0000 0000, which is negative as s64
10508         $LFS setstripe -E 8E -c 4 -E EOF -c 8 $src_dir &&
10509                 error "should fail if extent start/end >=8E"
10510
10511         # EOF should work as before
10512         $LFS setstripe -E 8M -c 4 -E EOF -c 8 $src_dir ||
10513                 error "failed to setstripe normally"
10514 }
10515 run_test 65p "setstripe with >=8E offset should fail"
10516
10517 # bug 2543 - update blocks count on client
10518 test_66() {
10519         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10520
10521         local COUNT=${COUNT:-8}
10522         dd if=/dev/zero of=$DIR/f66 bs=1k count=$COUNT
10523         sync; sync_all_data; sync; sync_all_data
10524         cancel_lru_locks osc
10525         local BLOCKS=$(ls -s --block-size=1k $DIR/f66 | awk '{ print $1 }')
10526         (( BLOCKS >= COUNT )) || error "$DIR/f66 blocks $BLOCKS < $COUNT"
10527 }
10528 run_test 66 "update inode blocks count on client ==============="
10529
10530 meminfo() {
10531         awk '($1 == "'$1':") { print $2 }' /proc/meminfo
10532 }
10533
10534 swap_used() {
10535         swapon -s | awk '($1 == "'$1'") { print $4 }'
10536 }
10537
10538 # bug5265, obdfilter oa2dentry return -ENOENT
10539 # #define OBD_FAIL_SRV_ENOENT 0x217
10540 test_69() {
10541         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10542         remote_ost_nodsh && skip "remote OST with nodsh"
10543
10544         f="$DIR/$tfile"
10545         $LFS setstripe -c 1 -i 0 $f
10546         stack_trap "rm -f $f ${f}.2"
10547
10548         $DIRECTIO write ${f}.2 0 1 || error "directio write error"
10549
10550         do_facet ost1 lctl set_param fail_loc=0x217
10551         $TRUNCATE $f 1 # vmtruncate() will ignore truncate() error.
10552         $DIRECTIO write $f 0 2 && error "write succeeded, expect -ENOENT"
10553
10554         do_facet ost1 lctl set_param fail_loc=0
10555         $DIRECTIO write $f 0 2 || error "write error"
10556
10557         cancel_lru_locks osc
10558         $DIRECTIO read $f 0 1 || error "read error"
10559
10560         do_facet ost1 lctl set_param fail_loc=0x217
10561         $DIRECTIO read $f 1 1 && error "read succeeded, expect -ENOENT"
10562
10563         do_facet ost1 lctl set_param fail_loc=0
10564 }
10565 run_test 69 "verify oa2dentry return -ENOENT doesn't LBUG ======"
10566
10567 test_70a() {
10568         # Perform a really simple test of health write and health check
10569         (( $OST1_VERSION >= $(version_code 2.15.59) )) ||
10570                 skip "OSTs < 2.15.59 doesn't have enable_health_write"
10571
10572         local orig_value="$(do_facet ost1 $LCTL get_param -n enable_health_write)"
10573
10574         stack_trap "do_facet ost1 $LCTL set_param enable_health_write $orig_value"
10575
10576         # Test with health write off
10577         do_facet ost1 $LCTL set_param enable_health_write off ||
10578                 error "can't set enable_health_write off"
10579         do_facet ost1 $LCTL get_param enable_health_write ||
10580                 error "can't get enable_health_write"
10581
10582         [[ "$(do_facet ost1 $LCTL get_param health_check)" =~ "healthy" ]] ||
10583                 error "not healthy (1)"
10584
10585         # Test with health write on
10586         do_facet ost1 $LCTL set_param enable_health_write on ||
10587                 error "can't set enable_health_write on"
10588         do_facet ost1 $LCTL get_param enable_health_write ||
10589                 error "can't get enable_health_write"
10590
10591         [[ "$(do_facet ost1 $LCTL get_param health_check)" =~ "healthy" ]] ||
10592                 error "not healthy (2)"
10593 }
10594 run_test 70a "verify health_check, health_write don't explode (on OST)"
10595
10596 test_71() {
10597         test_mkdir $DIR/$tdir
10598         $LFS setdirstripe -D -c$MDSCOUNT $DIR/$tdir
10599         bash rundbench -C -D $DIR/$tdir 2 || error "dbench failed!"
10600 }
10601 run_test 71 "Running dbench on lustre (don't segment fault) ===="
10602
10603 test_72a() { # bug 5695 - Test that on 2.6 remove_suid works properly
10604         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10605         [ "$RUNAS_ID" = "$UID" ] &&
10606                 skip_env "RUNAS_ID = UID = $UID -- skipping"
10607         # Check that testing environment is properly set up. Skip if not
10608         FAIL_ON_ERROR=false check_runas_id_ret $RUNAS_ID $RUNAS_GID $RUNAS ||
10609                 skip_env "User $RUNAS_ID does not exist - skipping"
10610
10611         touch $DIR/$tfile
10612         chmod 777 $DIR/$tfile
10613         chmod ug+s $DIR/$tfile
10614         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=512 count=1 ||
10615                 error "$RUNAS dd $DIR/$tfile failed"
10616         # See if we are still setuid/sgid
10617         [ -u $DIR/$tfile ] || [ -g $DIR/$tfile ] &&
10618                 error "S/gid is not dropped on write"
10619         # Now test that MDS is updated too
10620         cancel_lru_locks mdc
10621         [ -u $DIR/$tfile ] || [ -g $DIR/$tfile ] &&
10622                 error "S/gid is not dropped on MDS"
10623         rm -f $DIR/$tfile
10624 }
10625 run_test 72a "Test that remove suid works properly (bug5695) ===="
10626
10627 test_72b() { # bug 24226 -- keep mode setting when size is not changing
10628         local perm
10629
10630         [ "$RUNAS_ID" = "$UID" ] &&
10631                 skip_env "RUNAS_ID = UID = $UID -- skipping"
10632         [ "$RUNAS_ID" -eq 0 ] &&
10633                 skip_env "RUNAS_ID = 0 -- skipping"
10634         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10635         # Check that testing environment is properly set up. Skip if not
10636         FAIL_ON_ERROR=false check_runas_id_ret $RUNAS_ID $RUNAS_ID $RUNAS ||
10637                 skip_env "User $RUNAS_ID does not exist - skipping"
10638
10639         touch $DIR/${tfile}-f{g,u}
10640         test_mkdir $DIR/${tfile}-dg
10641         test_mkdir $DIR/${tfile}-du
10642         chmod 770 $DIR/${tfile}-{f,d}{g,u}
10643         chmod g+s $DIR/${tfile}-{f,d}g
10644         chmod u+s $DIR/${tfile}-{f,d}u
10645         for perm in 777 2777 4777; do
10646                 $RUNAS chmod $perm $DIR/${tfile}-fg && error "S/gid file allowed improper chmod to $perm"
10647                 $RUNAS chmod $perm $DIR/${tfile}-fu && error "S/uid file allowed improper chmod to $perm"
10648                 $RUNAS chmod $perm $DIR/${tfile}-dg && error "S/gid dir allowed improper chmod to $perm"
10649                 $RUNAS chmod $perm $DIR/${tfile}-du && error "S/uid dir allowed improper chmod to $perm"
10650         done
10651         true
10652 }
10653 run_test 72b "Test that we keep mode setting if without file data changed (bug 24226)"
10654
10655 # bug 3462 - multiple simultaneous MDC requests
10656 test_73() {
10657         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10658
10659         test_mkdir $DIR/d73-1
10660         test_mkdir $DIR/d73-2
10661         multiop_bg_pause $DIR/d73-1/f73-1 O_c || return 1
10662         pid1=$!
10663
10664         lctl set_param fail_loc=0x80000129
10665         $MULTIOP $DIR/d73-1/f73-2 Oc &
10666         sleep 1
10667         lctl set_param fail_loc=0
10668
10669         $MULTIOP $DIR/d73-2/f73-3 Oc &
10670         pid3=$!
10671
10672         kill -USR1 $pid1
10673         wait $pid1 || return 1
10674
10675         sleep 25
10676
10677         $CHECKSTAT -t file $DIR/d73-1/f73-1 || return 4
10678         $CHECKSTAT -t file $DIR/d73-1/f73-2 || return 5
10679         $CHECKSTAT -t file $DIR/d73-2/f73-3 || return 6
10680
10681         rm -rf $DIR/d73-*
10682 }
10683 run_test 73 "multiple MDC requests (should not deadlock)"
10684
10685 test_74a() { # bug 6149, 6184
10686         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10687
10688         touch $DIR/f74a
10689         #define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
10690         #
10691         # very important to OR with CFS_FAIL_ONCE (0x80000000) -- otherwise it
10692         # will spin in a tight reconnection loop
10693         $LCTL set_param fail_loc=0x8000030e
10694         # get any lock that won't be difficult - lookup works.
10695         ls $DIR/f74a
10696         $LCTL set_param fail_loc=0
10697         rm -f $DIR/f74a
10698         true
10699 }
10700 run_test 74a "ldlm_enqueue freed-export error path, ls (shouldn't LBUG)"
10701
10702 test_74b() { # bug 13310
10703         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10704
10705         #define OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT 0x30e
10706         #
10707         # very important to OR with CFS_FAIL_ONCE (0x80000000) -- otherwise it
10708         # will spin in a tight reconnection loop
10709         $LCTL set_param fail_loc=0x8000030e
10710         # get a "difficult" lock
10711         touch $DIR/f74b
10712         $LCTL set_param fail_loc=0
10713         rm -f $DIR/f74b
10714         true
10715 }
10716 run_test 74b "ldlm_enqueue freed-export error path, touch (shouldn't LBUG)"
10717
10718 test_74c() {
10719         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10720
10721         #define OBD_FAIL_LDLM_NEW_LOCK
10722         $LCTL set_param fail_loc=0x319
10723         touch $DIR/$tfile && error "touch successful"
10724         $LCTL set_param fail_loc=0
10725         true
10726 }
10727 run_test 74c "ldlm_lock_create error path, (shouldn't LBUG)"
10728
10729 slab_lic=/sys/kernel/slab/lustre_inode_cache
10730 num_objects() {
10731         [ -f $slab_lic/shrink ] && echo 1 > $slab_lic/shrink
10732         [ -f $slab_lic/objects ] && awk '{ print $1 }' $slab_lic/objects ||
10733                 awk '/lustre_inode_cache/ { print $2; exit }' /proc/slabinfo
10734 }
10735
10736 test_76a() { # Now for b=20433, added originally in b=1443
10737         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10738
10739         cancel_lru_locks osc
10740         # there may be some slab objects cached per core
10741         local cpus=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
10742         local before=$(num_objects)
10743         local count=$((512 * cpus))
10744         [ "$SLOW" = "no" ] && count=$((128 * cpus))
10745         local margin=$((count / 10))
10746         if [[ -f $slab_lic/aliases ]]; then
10747                 local aliases=$(cat $slab_lic/aliases)
10748                 (( aliases > 0 )) && margin=$((margin * aliases))
10749         fi
10750
10751         echo "before slab objects: $before"
10752         for i in $(seq $count); do
10753                 touch $DIR/$tfile
10754                 rm -f $DIR/$tfile
10755         done
10756         cancel_lru_locks osc
10757         local after=$(num_objects)
10758         echo "created: $count, after slab objects: $after"
10759         # shared slab counts are not very accurate, allow significant margin
10760         # the main goal is that the cache growth is not permanently > $count
10761         while (( after > before + margin )); do
10762                 sleep 1
10763                 after=$(num_objects)
10764                 wait=$((wait + 1))
10765                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
10766                 if (( wait > 60 )); then
10767                         error "inode slab grew from $before+$margin to $after"
10768                 fi
10769         done
10770 }
10771 run_test 76a "confirm clients recycle inodes properly ===="
10772
10773 test_76b() {
10774         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10775         [ $CLIENT_VERSION -ge $(version_code 2.13.55) ] || skip "not supported"
10776
10777         local count=512
10778         local before=$(num_objects)
10779
10780         for i in $(seq $count); do
10781                 mkdir $DIR/$tdir
10782                 rmdir $DIR/$tdir
10783         done
10784
10785         local after=$(num_objects)
10786         local wait=0
10787
10788         while (( after > before )); do
10789                 sleep 1
10790                 after=$(num_objects)
10791                 wait=$((wait + 1))
10792                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
10793                 if (( wait > 60 )); then
10794                         error "inode slab grew from $before to $after"
10795                 fi
10796         done
10797
10798         echo "slab objects before: $before, after: $after"
10799 }
10800 run_test 76b "confirm clients recycle directory inodes properly ===="
10801
10802 export ORIG_CSUM=""
10803 set_checksums()
10804 {
10805         # Note: in sptlrpc modes which enable its own bulk checksum, the
10806         # original crc32_le bulk checksum will be automatically disabled,
10807         # and the OBD_FAIL_OSC_CHECKSUM_SEND/OBD_FAIL_OSC_CHECKSUM_RECEIVE
10808         # will be checked by sptlrpc code against sptlrpc bulk checksum.
10809         # In this case set_checksums() will not be no-op, because sptlrpc
10810         # bulk checksum will be enabled all through the test.
10811
10812         [ "$ORIG_CSUM" ] || ORIG_CSUM=`lctl get_param -n osc.*.checksums | head -n1`
10813         lctl set_param -n osc.*.checksums $1
10814         return 0
10815 }
10816
10817 export ORIG_CSUM_TYPE="`lctl get_param -n osc.*osc-[^mM]*.checksum_type |
10818                         sed 's/.*\[\(.*\)\].*/\1/g' | head -n1`"
10819 CKSUM_TYPES=${CKSUM_TYPES:-$(lctl get_param -n osc.*osc-[^mM]*.checksum_type |
10820                              tr -d [] | head -n1)}
10821 set_checksum_type()
10822 {
10823         lctl set_param -n osc.*osc-[^mM]*.checksum_type $1
10824         rc=$?
10825         log "set checksum type to $1, rc = $rc"
10826         return $rc
10827 }
10828
10829 get_osc_checksum_type()
10830 {
10831         # arugment 1: OST name, like OST0000
10832         ost=$1
10833         checksum_type=$(lctl get_param -n osc.*${ost}-osc-[^mM]*.checksum_type |
10834                         sed 's/.*\[\(.*\)\].*/\1/g')
10835         rc=$?
10836         [ $rc -ne 0 ] && error "failed to get checksum type of $ost, rc = $rc, output = $checksum_type"
10837         echo $checksum_type
10838 }
10839
10840 F77_TMP=$TMP/f77-temp
10841 F77SZ=8
10842 setup_f77() {
10843         dd if=/dev/urandom of=$F77_TMP bs=1M count=$F77SZ || \
10844                 error "error writing to $F77_TMP"
10845 }
10846
10847 test_77a() { # bug 10889
10848         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10849         $GSS && skip_env "could not run with gss"
10850
10851         [ ! -f $F77_TMP ] && setup_f77
10852         set_checksums 1
10853         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ || error "dd error"
10854         set_checksums 0
10855         rm -f $DIR/$tfile
10856 }
10857 run_test 77a "normal checksum read/write operation"
10858
10859 test_77b() { # bug 10889
10860         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10861         $GSS && skip_env "could not run with gss"
10862
10863         [ ! -f $F77_TMP ] && setup_f77
10864         #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
10865         $LCTL set_param fail_loc=0x80000409
10866         set_checksums 1
10867
10868         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ conv=sync ||
10869                 error "dd error: $?"
10870         $LCTL set_param fail_loc=0
10871
10872         for algo in $CKSUM_TYPES; do
10873                 cancel_lru_locks osc
10874                 set_checksum_type $algo
10875                 #define OBD_FAIL_OSC_CHECKSUM_RECEIVE    0x408
10876                 $LCTL set_param fail_loc=0x80000408
10877                 cmp $F77_TMP $DIR/$tfile || error "file compare failed"
10878                 $LCTL set_param fail_loc=0
10879         done
10880         set_checksums 0
10881         set_checksum_type $ORIG_CSUM_TYPE
10882         rm -f $DIR/$tfile
10883 }
10884 run_test 77b "checksum error on client write, read"
10885
10886 cleanup_77c() {
10887         trap 0
10888         set_checksums 0
10889         $LCTL set_param osc.*osc-[^mM]*.checksum_dump=0
10890         $check_ost &&
10891                 do_facet ost1 $LCTL set_param obdfilter.*-OST*.checksum_dump=0
10892         [ -n "$osc_file_prefix" ] && rm -f ${osc_file_prefix}*
10893         $check_ost && [ -n "$ost_file_prefix" ] &&
10894                 do_facet ost1 rm -f ${ost_file_prefix}\*
10895 }
10896
10897 test_77c() {
10898         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10899         $GSS && skip_env "could not run with gss"
10900         remote_ost_nodsh && skip "remote OST with nodsh"
10901
10902         local bad1
10903         local osc_file_prefix
10904         local osc_file
10905         local check_ost=false
10906         local ost_file_prefix
10907         local ost_file
10908         local orig_cksum
10909         local dump_cksum
10910         local fid
10911
10912         # ensure corruption will occur on first OSS/OST
10913         $LFS setstripe -i 0 $DIR/$tfile
10914
10915         [ ! -f $F77_TMP ] && setup_f77
10916         dd if=$F77_TMP of=$DIR/$tfile bs=1M count=$F77SZ conv=sync ||
10917                 error "dd write error: $?"
10918         fid=$($LFS path2fid $DIR/$tfile)
10919
10920         if [ $OST1_VERSION -ge $(version_code 2.9.57) ]
10921         then
10922                 check_ost=true
10923                 ost_file_prefix=$(do_facet ost1 $LCTL get_param -n debug_path)
10924                 ost_file_prefix=${ost_file_prefix}-checksum_dump-ost-\\${fid}
10925         else
10926                 echo "OSS do not support bulk pages dump upon error"
10927         fi
10928
10929         osc_file_prefix=$($LCTL get_param -n debug_path)
10930         osc_file_prefix=${osc_file_prefix}-checksum_dump-osc-\\${fid}
10931
10932         trap cleanup_77c EXIT
10933
10934         set_checksums 1
10935         # enable bulk pages dump upon error on Client
10936         $LCTL set_param osc.*osc-[^mM]*.checksum_dump=1
10937         # enable bulk pages dump upon error on OSS
10938         $check_ost &&
10939                 do_facet ost1 $LCTL set_param obdfilter.*-OST*.checksum_dump=1
10940
10941         # flush Client cache to allow next read to reach OSS
10942         cancel_lru_locks osc
10943
10944         #define OBD_FAIL_OSC_CHECKSUM_RECEIVE       0x408
10945         $LCTL set_param fail_loc=0x80000408
10946         dd if=$DIR/$tfile of=/dev/null bs=1M || error "dd read error: $?"
10947         $LCTL set_param fail_loc=0
10948
10949         rm -f $DIR/$tfile
10950
10951         # check cksum dump on Client
10952         osc_file=$(ls ${osc_file_prefix}*)
10953         [ -n "$osc_file" ] || error "no checksum dump file on Client"
10954         # OBD_FAIL_OSC_CHECKSUM_RECEIVE corrupts with "bad1" at start of file
10955         bad1=$(dd if=$osc_file bs=1 count=4 2>/dev/null) || error "dd error: $?"
10956         [ $bad1 == "bad1" ] || error "unexpected corrupt pattern"
10957         orig_cksum=$(dd if=$F77_TMP bs=1 skip=4 count=1048572 2>/dev/null |
10958                      cksum)
10959         dump_cksum=$(dd if=$osc_file bs=1 skip=4 2>/dev/null | cksum)
10960         [[ "$orig_cksum" == "$dump_cksum" ]] ||
10961                 error "dump content does not match on Client"
10962
10963         $check_ost || skip "No need to check cksum dump on OSS"
10964
10965         # check cksum dump on OSS
10966         ost_file=$(do_facet ost1 ls ${ost_file_prefix}\*)
10967         [ -n "$ost_file" ] || error "no checksum dump file on OSS"
10968         orig_cksum=$(dd if=$F77_TMP bs=1048576 count=1 2>/dev/null | cksum)
10969         dump_cksum=$(do_facet ost1 dd if=$ost_file 2>/dev/null \| cksum)
10970         [[ "$orig_cksum" == "$dump_cksum" ]] ||
10971                 error "dump content does not match on OSS"
10972
10973         cleanup_77c
10974 }
10975 run_test 77c "checksum error on client read with debug"
10976
10977 test_77d() { # bug 10889
10978         [ $PARALLEL == "yes" ] && skip "skip parallel run"
10979         $GSS && skip_env "could not run with gss"
10980
10981         stack_trap "rm -f $DIR/$tfile"
10982         #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
10983         $LCTL set_param fail_loc=0x80000409
10984         set_checksums 1
10985         $DIRECTIO write $DIR/$tfile 0 $F77SZ $((1024 * 1024)) ||
10986                 error "direct write: rc=$?"
10987         $LCTL set_param fail_loc=0
10988         set_checksums 0
10989
10990         #define OBD_FAIL_OSC_CHECKSUM_RECEIVE    0x408
10991         $LCTL set_param fail_loc=0x80000408
10992         set_checksums 1
10993         cancel_lru_locks osc
10994         $DIRECTIO read $DIR/$tfile 0 $F77SZ $((1024 * 1024)) ||
10995                 error "direct read: rc=$?"
10996         $LCTL set_param fail_loc=0
10997         set_checksums 0
10998 }
10999 run_test 77d "checksum error on OST direct write, read"
11000
11001 test_77f() { # bug 10889
11002         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11003         $GSS && skip_env "could not run with gss"
11004
11005         set_checksums 1
11006         stack_trap "rm -f $DIR/$tfile"
11007         for algo in $CKSUM_TYPES; do
11008                 cancel_lru_locks osc
11009                 set_checksum_type $algo
11010                 #define OBD_FAIL_OSC_CHECKSUM_SEND       0x409
11011                 $LCTL set_param fail_loc=0x409
11012                 $DIRECTIO write $DIR/$tfile 0 $F77SZ $((1024 * 1024)) &&
11013                         error "direct write succeeded"
11014                 $LCTL set_param fail_loc=0
11015         done
11016         set_checksum_type $ORIG_CSUM_TYPE
11017         set_checksums 0
11018 }
11019 run_test 77f "repeat checksum error on write (expect error)"
11020
11021 test_77g() { # bug 10889
11022         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11023         $GSS && skip_env "could not run with gss"
11024         remote_ost_nodsh && skip "remote OST with nodsh"
11025
11026         [ ! -f $F77_TMP ] && setup_f77
11027
11028         local file=$DIR/$tfile
11029         stack_trap "rm -f $file" EXIT
11030
11031         $LFS setstripe -c 1 -i 0 $file
11032         #define OBD_FAIL_OST_CHECKSUM_RECEIVE       0x21a
11033         do_facet ost1 lctl set_param fail_loc=0x8000021a
11034         set_checksums 1
11035         dd if=$F77_TMP of=$file bs=1M count=$F77SZ ||
11036                 error "write error: rc=$?"
11037         do_facet ost1 lctl set_param fail_loc=0
11038         set_checksums 0
11039
11040         cancel_lru_locks osc
11041         #define OBD_FAIL_OST_CHECKSUM_SEND          0x21b
11042         do_facet ost1 lctl set_param fail_loc=0x8000021b
11043         set_checksums 1
11044         cmp $F77_TMP $file || error "file compare failed"
11045         do_facet ost1 lctl set_param fail_loc=0
11046         set_checksums 0
11047 }
11048 run_test 77g "checksum error on OST write, read"
11049
11050 test_77k() { # LU-10906
11051         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11052         $GSS && skip_env "could not run with gss"
11053
11054         local cksum_param="osc.$FSNAME*.checksums"
11055         local get_checksum="$LCTL get_param -n $cksum_param | head -n1"
11056         local checksum
11057         local i
11058
11059         [ "$ORIG_CSUM" ] || ORIG_CSUM=$(eval $get_checksum)
11060         stack_trap "wait_update $HOSTNAME '$get_checksum' $ORIG_CSUM || true"
11061         stack_trap "do_facet mgs $LCTL set_param -P $cksum_param=$ORIG_CSUM"
11062
11063         for i in 0 1; do
11064                 do_facet mgs $LCTL set_param -P $cksum_param=$i ||
11065                         error "failed to set checksum=$i on MGS"
11066                 wait_update $HOSTNAME "$get_checksum" $i
11067                 #remount
11068                 echo "remount client, checksum should be $i"
11069                 remount_client $MOUNT || error "failed to remount client"
11070                 checksum=$(eval $get_checksum)
11071                 [ $checksum -eq $i ] || error "checksum($checksum) != $i"
11072         done
11073         # remove persistent param to avoid races with checksum mountopt below
11074         do_facet mgs $LCTL set_param -P -d $cksum_param ||
11075                 error "failed to delete checksum on MGS"
11076
11077         for opt in "checksum" "nochecksum"; do
11078                 #remount with mount option
11079                 echo "remount client with option $opt, checksum should be $i"
11080                 umount_client $MOUNT || error "failed to umount client"
11081                 mount_client $MOUNT "$MOUNT_OPTS,$opt" ||
11082                         error "failed to mount client with option '$opt'"
11083                 checksum=$(eval $get_checksum)
11084                 [ $checksum -eq $i ] || error "checksum($checksum) != $i"
11085                 i=$((i - 1))
11086         done
11087
11088         remount_client $MOUNT || error "failed to remount client"
11089 }
11090 run_test 77k "enable/disable checksum correctly"
11091
11092 test_77l() {
11093         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11094         $GSS && skip_env "could not run with gss"
11095
11096         set_checksums 1
11097         stack_trap "set_checksums $ORIG_CSUM" EXIT
11098         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
11099
11100         set_checksum_type invalid && error "unexpected success of invalid checksum type"
11101
11102         $LFS setstripe -c 1 -i 0 $DIR/$tfile
11103         for algo in $CKSUM_TYPES; do
11104                 set_checksum_type $algo || error "fail to set checksum type $algo"
11105                 osc_algo=$(get_osc_checksum_type OST0000)
11106                 [ "$osc_algo" != "$algo" ] && error "checksum type is $osc_algo after setting it to $algo"
11107
11108                 # no locks, no reqs to let the connection idle
11109                 cancel_lru_locks osc
11110                 lru_resize_disable osc
11111                 wait_osc_import_state client ost1 IDLE
11112
11113                 # ensure ost1 is connected
11114                 stat $DIR/$tfile >/dev/null || error "can't stat"
11115                 wait_osc_import_state client ost1 FULL
11116
11117                 osc_algo=$(get_osc_checksum_type OST0000)
11118                 [ "$osc_algo" != "$algo" ] && error "checksum type changed from $algo to $osc_algo after reconnection"
11119         done
11120         return 0
11121 }
11122 run_test 77l "preferred checksum type is remembered after reconnected"
11123
11124 [ "$ORIG_CSUM" ] && set_checksums $ORIG_CSUM || true
11125 rm -f $F77_TMP
11126 unset F77_TMP
11127
11128 test_77m() {
11129         (( $CLIENT_VERSION >= $(version_code 2.14.52) )) ||
11130                 skip "Need at least version 2.14.52"
11131         local param=checksum_speed
11132
11133         $LCTL get_param $param || error "reading $param failed"
11134
11135         csum_speeds=$($LCTL get_param -n $param)
11136
11137         [[ "$csum_speeds" =~ "adler32" && "$csum_speeds" =~ "crc32" ]] ||
11138                 error "known checksum types are missing"
11139 }
11140 run_test 77m "Verify checksum_speed is correctly read"
11141
11142 check_filefrag_77n() {
11143         local nr_ext=0
11144         local starts=()
11145         local ends=()
11146
11147         while read extidx a b start end rest; do
11148                 if [[ "${extidx}" =~ ^[0-9]+: ]]; then
11149                         nr_ext=$(( $nr_ext + 1 ))
11150                         starts+=( ${start%..} )
11151                         ends+=( ${end%:} )
11152                 fi
11153         done < <( filefrag -sv $1 )
11154
11155         [[ $nr_ext -eq 2 ]] && [[ "${starts[-1]}" == $(( ${ends[0]} + 1 )) ]] && return 0
11156         return 1
11157 }
11158
11159 test_77n() {
11160         [[ "$CKSUM_TYPES" =~ t10 ]] || skip "no T10 checksum support on osc"
11161
11162         touch $DIR/$tfile
11163         $TRUNCATE $DIR/$tfile 0
11164         dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=0
11165         dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=2
11166         check_filefrag_77n $DIR/$tfile ||
11167                 skip "$tfile blocks not contiguous around hole"
11168
11169         set_checksums 1
11170         stack_trap "set_checksums $ORIG_CSUM" EXIT
11171         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
11172         stack_trap "rm -f $DIR/$tfile"
11173
11174         for algo in $CKSUM_TYPES; do
11175                 if [[ "$algo" =~ ^t10 ]]; then
11176                         set_checksum_type $algo ||
11177                                 error "fail to set checksum type $algo"
11178                         dd if=$DIR/$tfile of=/dev/null bs=12k count=1 iflag=direct ||
11179                                 error "fail to read $tfile with $algo"
11180                 fi
11181         done
11182         rm -f $DIR/$tfile
11183         return 0
11184 }
11185 run_test 77n "Verify read from a hole inside contiguous blocks with T10PI"
11186
11187 test_77o() {
11188         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
11189                 skip "Need MDS version at least 2.14.55"
11190         (( $OST1_VERSION >= $(version_code 2.14.55) )) ||
11191                 skip "Need OST version at least 2.14.55"
11192         local ofd=obdfilter
11193         local mdt=mdt
11194
11195         # print OST checksum_type
11196         echo "$ofd.$FSNAME-*.checksum_type:"
11197         do_nodes $(comma_list $(osts_nodes)) \
11198                 $LCTL get_param -n $ofd.$FSNAME-*.checksum_type
11199
11200         # print MDT checksum_type
11201         echo "$mdt.$FSNAME-*.checksum_type:"
11202         do_nodes $(comma_list $(mdts_nodes)) \
11203                 $LCTL get_param -n $mdt.$FSNAME-*.checksum_type
11204
11205         local o_count=$(do_nodes $(comma_list $(osts_nodes)) \
11206                    $LCTL get_param -n $ofd.$FSNAME-*.checksum_type | wc -l)
11207
11208         (( $o_count == $OSTCOUNT )) ||
11209                 error "found $o_count checksums, not \$MDSCOUNT=$OSTCOUNT"
11210
11211         local m_count=$(do_nodes $(comma_list $(mdts_nodes)) \
11212                    $LCTL get_param -n $mdt.$FSNAME-*.checksum_type | wc -l)
11213
11214         (( $m_count == $MDSCOUNT )) ||
11215                 error "found $m_count checksums, not \$MDSCOUNT=$MDSCOUNT"
11216 }
11217 run_test 77o "Verify checksum_type for server (mdt and ofd(obdfilter))"
11218
11219 cleanup_test_78() {
11220         trap 0
11221         rm -f $DIR/$tfile
11222 }
11223
11224 test_78() { # bug 10901
11225         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11226         remote_ost || skip_env "local OST"
11227
11228         NSEQ=5
11229         F78SIZE=$(($(awk '/MemFree:/ { print $2 }' /proc/meminfo) / 1024))
11230         echo "MemFree: $F78SIZE, Max file size: $MAXFREE"
11231         MEMTOTAL=$(($(awk '/MemTotal:/ { print $2 }' /proc/meminfo) / 1024))
11232         echo "MemTotal: $MEMTOTAL"
11233
11234         # reserve 256MB of memory for the kernel and other running processes,
11235         # and then take 1/2 of the remaining memory for the read/write buffers.
11236         if [ $MEMTOTAL -gt 512 ] ;then
11237                 MEMTOTAL=$(((MEMTOTAL - 256 ) / 2))
11238         else
11239                 # for those poor memory-starved high-end clusters...
11240                 MEMTOTAL=$((MEMTOTAL / 2))
11241         fi
11242         echo "Mem to use for directio: $MEMTOTAL"
11243
11244         [[ $F78SIZE -gt $MEMTOTAL ]] && F78SIZE=$MEMTOTAL
11245         [[ $F78SIZE -gt 512 ]] && F78SIZE=512
11246         [[ $F78SIZE -gt $((MAXFREE / 1024)) ]] && F78SIZE=$((MAXFREE / 1024))
11247         SMALLESTOST=$($LFS df $DIR | grep OST | awk '{ print $4 }' | sort -n |
11248                 head -n1)
11249         echo "Smallest OST: $SMALLESTOST"
11250         [[ $SMALLESTOST -lt 10240 ]] &&
11251                 skip "too small OSTSIZE, useless to run large O_DIRECT test"
11252
11253         trap cleanup_test_78 EXIT
11254
11255         [[ $F78SIZE -gt $((SMALLESTOST * $OSTCOUNT / 1024 - 80)) ]] &&
11256                 F78SIZE=$((SMALLESTOST * $OSTCOUNT / 1024 - 80))
11257
11258         [ "$SLOW" = "no" ] && NSEQ=1 && [ $F78SIZE -gt 32 ] && F78SIZE=32
11259         echo "File size: $F78SIZE"
11260         $LFS setstripe -c $OSTCOUNT $DIR/$tfile || error "setstripe failed"
11261         for i in $(seq 1 $NSEQ); do
11262                 FSIZE=$(($F78SIZE / ($NSEQ - $i + 1)))
11263                 echo directIO rdwr round $i of $NSEQ
11264                 $DIRECTIO rdwr $DIR/$tfile 0 $FSIZE 1048576||error "rdwr failed"
11265         done
11266
11267         cleanup_test_78
11268 }
11269 run_test 78 "handle large O_DIRECT writes correctly ============"
11270
11271 test_79() { # bug 12743
11272         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11273
11274         wait_delete_completed
11275
11276         BKTOTAL=$(calc_osc_kbytes kbytestotal)
11277         BKFREE=$(calc_osc_kbytes kbytesfree)
11278         BKAVAIL=$(calc_osc_kbytes kbytesavail)
11279
11280         STRING=`df -P $MOUNT | tail -n 1 | awk '{print $2","$3","$4}'`
11281         DFTOTAL=`echo $STRING | cut -d, -f1`
11282         DFUSED=`echo $STRING  | cut -d, -f2`
11283         DFAVAIL=`echo $STRING | cut -d, -f3`
11284         DFFREE=$(($DFTOTAL - $DFUSED))
11285
11286         ALLOWANCE=$((64 * $OSTCOUNT))
11287
11288         if [ $DFTOTAL -lt $(($BKTOTAL - $ALLOWANCE)) ] ||
11289            [ $DFTOTAL -gt $(($BKTOTAL + $ALLOWANCE)) ] ; then
11290                 error "df total($DFTOTAL) mismatch OST total($BKTOTAL)"
11291         fi
11292         if [ $DFFREE -lt $(($BKFREE - $ALLOWANCE)) ] ||
11293            [ $DFFREE -gt $(($BKFREE + $ALLOWANCE)) ] ; then
11294                 error "df free($DFFREE) mismatch OST free($BKFREE)"
11295         fi
11296         if [ $DFAVAIL -lt $(($BKAVAIL - $ALLOWANCE)) ] ||
11297            [ $DFAVAIL -gt $(($BKAVAIL + $ALLOWANCE)) ] ; then
11298                 error "df avail($DFAVAIL) mismatch OST avail($BKAVAIL)"
11299         fi
11300 }
11301 run_test 79 "df report consistency check ======================="
11302
11303 test_80() { # bug 10718
11304         remote_ost_nodsh && skip "remote OST with nodsh"
11305         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11306
11307         # relax strong synchronous semantics for slow backends like ZFS
11308         if [ "$ost1_FSTYPE" != "ldiskfs" ]; then
11309                 local soc="obdfilter.*.sync_lock_cancel"
11310                 local save=$(do_facet ost1 $LCTL get_param -n $soc | head -n1)
11311
11312                 # "sync_on_lock_cancel" was broken by v2_11_55_0-26-g7059644e9a
11313                 if [ -z "$save" ]; then
11314                         soc="obdfilter.*.sync_on_lock_cancel"
11315                         save=$(do_facet ost1 $LCTL get_param -n $soc | head -n1)
11316                 fi
11317
11318                 if [ "$save" != "never" ]; then
11319                         local hosts=$(comma_list $(osts_nodes))
11320
11321                         do_nodes $hosts $LCTL set_param $soc=never
11322                         stack_trap "do_nodes $hosts $LCTL set_param $soc=$save"
11323                 fi
11324         fi
11325
11326         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=1M
11327         sync; sleep 1; sync
11328         local before=$(date +%s)
11329         cancel_lru_locks osc
11330         local after=$(date +%s)
11331         local diff=$((after - before))
11332         [ $diff -le 1 ] || error "elapsed for 1M@1T = $diff"
11333
11334         rm -f $DIR/$tfile
11335 }
11336 run_test 80 "Page eviction is equally fast at high offsets too"
11337
11338 test_81a() { # LU-456
11339         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11340         remote_ost_nodsh && skip "remote OST with nodsh"
11341
11342         # define OBD_FAIL_OST_MAPBLK_ENOSPC    0x228
11343         # MUST OR with the CFS_FAIL_ONCE (0x80000000)
11344         do_facet ost1 lctl set_param fail_loc=0x80000228
11345
11346         # write should trigger a retry and success
11347         $LFS setstripe -i 0 -c 1 $DIR/$tfile
11348         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
11349         RC=$?
11350         if [ $RC -ne 0 ] ; then
11351                 error "write should success, but failed for $RC"
11352         fi
11353 }
11354 run_test 81a "OST should retry write when get -ENOSPC ==============="
11355
11356 test_81b() { # LU-456
11357         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11358         remote_ost_nodsh && skip "remote OST with nodsh"
11359
11360         # define OBD_FAIL_OST_MAPBLK_ENOSPC    0x228
11361         # Don't OR with the CFS_FAIL_ONCE (0x80000000)
11362         do_facet ost1 lctl set_param fail_loc=0x228
11363
11364         # write should retry several times and return -ENOSPC finally
11365         $LFS setstripe -i 0 -c 1 $DIR/$tfile
11366         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
11367         RC=$?
11368         ENOSPC=28
11369         if [ $RC -ne $ENOSPC ] ; then
11370                 error "dd should fail for -ENOSPC, but succeed."
11371         fi
11372 }
11373 run_test 81b "OST should return -ENOSPC when retry still fails ======="
11374
11375 test_99() {
11376         [ -z "$(which cvs 2>/dev/null)" ] && skip_env "could not find cvs"
11377
11378         test_mkdir $DIR/$tdir.cvsroot
11379         chown $RUNAS_ID $DIR/$tdir.cvsroot
11380
11381         cd $TMP
11382         $RUNAS cvs -d $DIR/$tdir.cvsroot init || error "cvs init failed"
11383
11384         cd /etc/init.d
11385         # some versions of cvs import exit(1) when asked to import links or
11386         # files they can't read.  ignore those files.
11387         local toignore=$(find . -type l -printf '-I %f\n' -o \
11388                          ! -perm /4 -printf '-I %f\n')
11389         $RUNAS cvs -d $DIR/$tdir.cvsroot import -m "nomesg" $toignore \
11390                 $tdir.reposname vtag rtag
11391
11392         cd $DIR
11393         test_mkdir $DIR/$tdir.reposname
11394         chown $RUNAS_ID $DIR/$tdir.reposname
11395         $RUNAS cvs -d $DIR/$tdir.cvsroot co $tdir.reposname
11396
11397         cd $DIR/$tdir.reposname
11398         $RUNAS touch foo99
11399         $RUNAS cvs add -m 'addmsg' foo99
11400         $RUNAS cvs update
11401         $RUNAS cvs commit -m 'nomsg' foo99
11402         rm -fr $DIR/$tdir.cvsroot
11403 }
11404 run_test 99 "cvs strange file/directory operations"
11405
11406 test_100() {
11407         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11408         [[ "$NETTYPE" =~ tcp ]] ||
11409                 skip_env "TCP secure port test, not useful for NETTYPE=$NETTYPE"
11410         [[ -n "$(type -p ss)" ]] || skip_env "ss not available"
11411         remote_ost_nodsh && skip "remote OST with nodsh"
11412         remote_mds_nodsh && skip "remote MDS with nodsh"
11413         remote_servers || skip "useless for local single node setup"
11414
11415         ss -tna | ( rc=1; while read STATE SND RCV LOCAL REMOTE STAT; do
11416                 [[ "${REMOTE/*:/}" == "$ACCEPTOR_PORT" ]] || continue
11417
11418                 rc=0
11419                 if (( ${LOCAL/*:/} >= 1024 )); then
11420                         echo "bad: $PROT $SND $RCV $LOCAL $REMOTE $STAT"
11421                         ss -tna
11422                         error "local: ${LOCAL/*:/} > 1024 remote: ${REMOTE/*:/}"
11423                 fi
11424         done
11425         (( $rc == 0 )) || error "privileged port not found" )
11426 }
11427 run_test 100 "check local port using privileged port"
11428
11429 function get_named_value()
11430 {
11431     local tag=$1
11432
11433     grep -w "$tag" | sed "s/^$tag  *\([0-9]*\)  *.*/\1/"
11434 }
11435
11436 test_101a() {
11437         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11438
11439         local s
11440         local discard
11441         local nreads=10000
11442         local cache_limit=32
11443
11444         $LCTL set_param -n osc.*-osc*.rpc_stats=0
11445         $LCTL set_param -n llite.*.read_ahead_stats=0
11446         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
11447                               awk '/^max_cached_mb/ { print $2 }')
11448         stack_trap "$LCTL set_param -n llite.*.max_cached_mb=$max_cached_mb"
11449         $LCTL set_param -n llite.*.max_cached_mb=$cache_limit
11450
11451         #
11452         # randomly read 10000 of 64K chunks from file 3x 32MB in size
11453         #
11454         echo "nreads: $nreads file size: $((cache_limit * 3))MB"
11455         $READS -f $DIR/$tfile -s$((cache_limit * 3192 * 1024)) -b65536 -C -n$nreads -t 180
11456
11457         discard=0
11458         for s in $($LCTL get_param -n llite.*.read_ahead_stats |
11459                    get_named_value 'read.but.discarded'); do
11460                         discard=$(($discard + $s))
11461         done
11462
11463         $LCTL get_param osc.*-osc*.rpc_stats
11464         $LCTL get_param llite.*.read_ahead_stats
11465
11466         # Discard is generally zero, but sometimes a few random reads line up
11467         # and trigger larger readahead, which is wasted & leads to discards.
11468         if [[ $(($discard)) -gt $nreads ]]; then
11469                 error "too many ($discard) discarded pages"
11470         fi
11471         rm -f $DIR/$tfile || true
11472 }
11473 run_test 101a "check read-ahead for random reads"
11474
11475 setup_test101bc() {
11476         test_mkdir $DIR/$tdir
11477         local ssize=$1
11478         local FILE_LENGTH=$2
11479         STRIPE_OFFSET=0
11480
11481         local FILE_SIZE_MB=$((FILE_LENGTH / ssize))
11482
11483         local list=$(comma_list $(osts_nodes))
11484         set_osd_param $list '' read_cache_enable 0
11485         set_osd_param $list '' writethrough_cache_enable 0
11486
11487         trap cleanup_test101bc EXIT
11488         # prepare the read-ahead file
11489         $LFS setstripe -S $ssize -i $STRIPE_OFFSET -c $OSTCOUNT $DIR/$tfile
11490
11491         dd if=/dev/zero of=$DIR/$tfile bs=$ssize \
11492                                 count=$FILE_SIZE_MB 2> /dev/null
11493
11494 }
11495
11496 cleanup_test101bc() {
11497         trap 0
11498         rm -rf $DIR/$tdir
11499         rm -f $DIR/$tfile
11500
11501         local list=$(comma_list $(osts_nodes))
11502         set_osd_param $list '' read_cache_enable 1
11503         set_osd_param $list '' writethrough_cache_enable 1
11504 }
11505
11506 ra_check_101() {
11507         local read_size=$1
11508         local stripe_size=$2
11509         local stride_length=$((stripe_size / read_size))
11510         local stride_width=$((stride_length * OSTCOUNT))
11511         local discard_limit=$(( ((stride_length - 1) * 3 / stride_width) *
11512                                 (stride_width - stride_length) ))
11513         local discard=$($LCTL get_param -n llite.*.read_ahead_stats |
11514                   get_named_value 'read.but.discarded' | calc_sum)
11515
11516         if [[ $discard -gt $discard_limit ]]; then
11517                 $LCTL get_param llite.*.read_ahead_stats
11518                 error "($discard limit ${discard_limit}) discarded pages with size (${read_size})"
11519         else
11520                 echo "Read-ahead success for size ${read_size}"
11521         fi
11522 }
11523
11524 test_101b() {
11525         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11526         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
11527
11528         local STRIPE_SIZE=1048576
11529         local STRIDE_SIZE=$((STRIPE_SIZE*OSTCOUNT))
11530
11531         if [ $SLOW == "yes" ]; then
11532                 local FILE_LENGTH=$((STRIDE_SIZE * 64))
11533         else
11534                 local FILE_LENGTH=$((STRIDE_SIZE * 8))
11535         fi
11536
11537         local ITERATION=$((FILE_LENGTH / STRIDE_SIZE))
11538
11539         # prepare the read-ahead file
11540         setup_test101bc $STRIPE_SIZE $FILE_LENGTH
11541         cancel_lru_locks osc
11542         for BIDX in 2 4 8 16 32 64 128 256
11543         do
11544                 local BSIZE=$((BIDX*4096))
11545                 local READ_COUNT=$((STRIPE_SIZE/BSIZE))
11546                 local STRIDE_LENGTH=$((STRIDE_SIZE/BSIZE))
11547                 local OFFSET=$((STRIPE_SIZE/BSIZE*(OSTCOUNT - 1)))
11548                 $LCTL set_param -n llite.*.read_ahead_stats=0
11549                 $READS -f $DIR/$tfile  -l $STRIDE_LENGTH -o $OFFSET \
11550                               -s $FILE_LENGTH -b $STRIPE_SIZE -a $READ_COUNT -n $ITERATION
11551                 cancel_lru_locks osc
11552                 ra_check_101 $BSIZE $STRIPE_SIZE $FILE_LENGTH
11553         done
11554         cleanup_test101bc
11555         true
11556 }
11557 run_test 101b "check stride-io mode read-ahead ================="
11558
11559 test_101c() {
11560         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11561
11562         local STRIPE_SIZE=1048576
11563         local FILE_LENGTH=$((STRIPE_SIZE*100))
11564         local nreads=10000
11565         local rsize=65536
11566         local osc_rpc_stats
11567
11568         setup_test101bc $STRIPE_SIZE $FILE_LENGTH
11569
11570         cancel_lru_locks osc
11571         $LCTL set_param osc.*.rpc_stats=0
11572         $READS -f $DIR/$tfile -s$FILE_LENGTH -b$rsize -n$nreads -t 180
11573         $LCTL get_param osc.*.rpc_stats
11574         for osc_rpc_stats in $($LCTL get_param -N osc.*.rpc_stats); do
11575                 local stats=$($LCTL get_param -n $osc_rpc_stats)
11576                 local lines=$(echo "$stats" | awk 'END {print NR;}')
11577                 local size
11578
11579                 if [ $lines -le 20 ]; then
11580                         echo "continue debug"
11581                         continue
11582                 fi
11583                 for size in 1 2 4 8; do
11584                         local rpc=$(echo "$stats" |
11585                                     awk '($1 == "'$size':") {print $2; exit; }')
11586                         [ $rpc != 0 ] && ((size * PAGE_SIZE < rsize)) &&
11587                                 error "Small $((size*PAGE_SIZE)) read IO $rpc!"
11588                 done
11589                 echo "$osc_rpc_stats check passed!"
11590         done
11591         cleanup_test101bc
11592         true
11593 }
11594 run_test 101c "check stripe_size aligned read-ahead"
11595
11596 test_101d() {
11597         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11598
11599         local file=$DIR/$tfile
11600         local sz_MB=${FILESIZE_101d:-80}
11601         local ra_MB=${READAHEAD_MB:-40}
11602
11603         local free_MB=$(($(df -P $DIR | tail -n 1 | awk '{ print $4 }') / 1024))
11604         [ $free_MB -lt $sz_MB ] &&
11605                 skip "Need free space ${sz_MB}M, have ${free_MB}M"
11606
11607         echo "Create test file $file size ${sz_MB}M, ${free_MB}M free"
11608         $LFS setstripe -c -1 $file || error "setstripe failed"
11609
11610         dd if=/dev/zero of=$file bs=1M count=$sz_MB || error "dd failed"
11611         echo Cancel LRU locks on lustre client to flush the client cache
11612         cancel_lru_locks osc
11613
11614         echo Disable read-ahead
11615         local old_RA=$($LCTL get_param -n llite.*.max_read_ahead_mb | head -n 1)
11616         $LCTL set_param -n llite.*.max_read_ahead_mb=0
11617         stack_trap "$LCTL set_param -n llite.*.max_read_ahead_mb=$old_RA" EXIT
11618         $LCTL get_param -n llite.*.max_read_ahead_mb
11619
11620         echo "Reading the test file $file with read-ahead disabled"
11621         local sz_KB=$((sz_MB * 1024 / 4))
11622         # 10485760 bytes transferred in 0.000938 secs (11179579337 bytes/sec)
11623         # 104857600 bytes (105 MB) copied, 0.00876352 s, 12.0 GB/s
11624         # 83886080 bytes (84 MB, 80 MiB) copied, 16 s, 5.2 MB/s
11625         local raOFF=$(LANG=C dd if=$file of=/dev/null bs=4k count=$sz_KB |&
11626                       sed -e '/records/d' -e 's/.* \([0-9][0-9\.]*\) *s.*/\1/')
11627
11628         echo "Cancel LRU locks on lustre client to flush the client cache"
11629         cancel_lru_locks osc
11630         echo Enable read-ahead with ${ra_MB}MB
11631         $LCTL set_param -n llite.*.max_read_ahead_mb=$ra_MB
11632
11633         echo "Reading the test file $file with read-ahead enabled"
11634         local raON=$(LANG=C dd if=$file of=/dev/null bs=4k count=$sz_KB |&
11635                       sed -e '/records/d' -e 's/.* \([0-9][0-9\.]*\) *s.*/\1/')
11636
11637         echo "read-ahead disabled time read '$raOFF'"
11638         echo "read-ahead enabled time read '$raON'"
11639
11640         rm -f $file
11641         wait_delete_completed
11642
11643         # use awk for this check instead of bash because it handles decimals
11644         awk "{ exit !($raOFF < 0.5 || $raOFF > $raON) }" <<<"ignore_me" ||
11645                 error "readahead ${raON}s > no-readahead ${raOFF}s (${sz_MB}M)"
11646 }
11647 run_test 101d "file read with and without read-ahead enabled"
11648
11649 test_101e() {
11650         [ $PARALLEL == "yes" ] && skip "skip parallel run"
11651
11652         local file=$DIR/$tfile
11653         local size_KB=500  #KB
11654         local count=100
11655         local bsize=1024
11656
11657         local free_KB=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
11658         local need_KB=$((count * size_KB))
11659         [[ $free_KB -le $need_KB ]] &&
11660                 skip_env "Need free space $need_KB, have $free_KB"
11661
11662         echo "Creating $count ${size_KB}K test files"
11663         for ((i = 0; i < $count; i++)); do
11664                 dd if=/dev/zero of=$file.$i bs=$bsize count=$size_KB 2>/dev/null
11665         done
11666
11667         echo "Cancel LRU locks on lustre client to flush the client cache"
11668         cancel_lru_locks $OSC
11669
11670         echo "Reset readahead stats"
11671         $LCTL set_param -n llite.*.read_ahead_stats=0
11672
11673         for ((i = 0; i < $count; i++)); do
11674                 dd if=$file.$i of=/dev/null bs=$bsize count=$size_KB 2>/dev/null
11675         done
11676
11677         $LCTL get_param llite.*.max_cached_mb
11678         $LCTL get_param llite.*.read_ahead_stats
11679         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
11680                      get_named_value 'misses' | calc_sum)
11681
11682         for ((i = 0; i < $count; i++)); do
11683                 rm -rf $file.$i 2>/dev/null
11684         done
11685
11686         #10000 means 20% reads are missing in readahead
11687         [[ $miss -lt 10000 ]] ||  error "misses too much for small reads"
11688 }
11689 run_test 101e "check read-ahead for small read(1k) for small files(500k)"
11690
11691 test_101f() {
11692         which iozone || skip_env "no iozone installed"
11693
11694         local old_debug=$($LCTL get_param debug)
11695         old_debug=${old_debug#*=}
11696         $LCTL set_param debug="reada mmap"
11697
11698         # create a test file
11699         iozone -i 0 -+n -r 1m -s 128m -w -f $DIR/$tfile > /dev/null 2>&1
11700
11701         echo Cancel LRU locks on lustre client to flush the client cache
11702         cancel_lru_locks osc
11703
11704         echo Reset readahead stats
11705         $LCTL set_param -n llite.*.read_ahead_stats=0
11706
11707         echo mmap read the file with small block size
11708         iozone -i 1 -u 1 -l 1 -+n -r 32k -s 128m -B -f $DIR/$tfile \
11709                 > /dev/null 2>&1
11710
11711         echo checking missing pages
11712         $LCTL get_param llite.*.read_ahead_stats
11713         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
11714                         get_named_value 'misses' | calc_sum)
11715
11716         $LCTL set_param debug="$old_debug"
11717         [ $miss -lt 3 ] || error "misses too much pages ('$miss')!"
11718         rm -f $DIR/$tfile
11719 }
11720 run_test 101f "check mmap read performance"
11721
11722 test_101g_brw_size_test() {
11723         local mb=$1
11724         local pages=$((mb * 1048576 / PAGE_SIZE))
11725         local file=$DIR/$tfile
11726
11727         $LCTL set_param osc.*.max_pages_per_rpc=${mb}M ||
11728                 { error "unable to set max_pages_per_rpc=${mb}M"; return 1; }
11729         for mp in $($LCTL get_param -n osc.*.max_pages_per_rpc); do
11730                 [ $mp -ne $pages ] && error "max_pages_per_rpc $mp != $pages" &&
11731                         return 2
11732         done
11733
11734         stack_trap "rm -f $file" EXIT
11735         $LCTL set_param -n osc.*.rpc_stats=0
11736
11737         # 10 RPCs should be enough for the test
11738         local count=10
11739         dd if=/dev/zero of=$file bs=${mb}M count=$count ||
11740                 { error "dd write ${mb} MB blocks failed"; return 3; }
11741         cancel_lru_locks osc
11742         dd of=/dev/null if=$file bs=${mb}M count=$count ||
11743                 { error "dd write ${mb} MB blocks failed"; return 4; }
11744
11745         # calculate number of full-sized read and write RPCs
11746         rpcs=($($LCTL get_param -n 'osc.*.rpc_stats' |
11747                 sed -n '/pages per rpc/,/^$/p' |
11748                 awk '/'$pages':/ { reads += $2; writes += $6 }; \
11749                 END { print reads,writes }'))
11750         # allow one extra full-sized read RPC for async readahead
11751         [[ ${rpcs[0]} == $count || ${rpcs[0]} == $((count + 1)) ]] ||
11752                 { error "${rpcs[0]} != $count read RPCs"; return 5; }
11753         [[ ${rpcs[1]} == $count ]] ||
11754                 { error "${rpcs[1]} != $count write RPCs"; return 6; }
11755 }
11756
11757 test_101g() {
11758         remote_ost_nodsh && skip "remote OST with nodsh"
11759
11760         local rpcs
11761         local osts=$(get_facets OST)
11762         local list=$(comma_list $(osts_nodes))
11763         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
11764         local brw_size="obdfilter.*.brw_size"
11765
11766         $LFS setstripe -i 0 -c 1 $DIR/$tfile
11767
11768         local orig_mb=$(do_facet ost1 $LCTL get_param -n $brw_size | head -n 1)
11769
11770         if { [ $OST1_VERSION -ge $(version_code 2.8.52) ] ||
11771                 { [ $OST1_VERSION -ge $(version_code 2.7.17) ] &&
11772                   [ $OST1_VERSION -lt $(version_code 2.7.50) ]; }; } &&
11773            { [ $CLIENT_VERSION -ge $(version_code 2.8.52) ] ||
11774                 { [ $CLIENT_VERSION -ge $(version_code 2.7.17) ] &&
11775                   [ $CLIENT_VERSION -lt $(version_code 2.7.50) ]; }; }; then
11776
11777                 [ $OST1_VERSION -ge $(version_code 2.9.52) ] &&
11778                         suffix="M"
11779
11780                 if [[ $orig_mb -lt 16 ]]; then
11781                         save_lustre_params $osts "$brw_size" > $p
11782                         do_nodes $list $LCTL set_param -n $brw_size=16$suffix ||
11783                                 error "set 16MB RPC size failed"
11784
11785                         echo "remount client to enable new RPC size"
11786                         remount_client $MOUNT || error "remount_client failed"
11787                 fi
11788
11789                 test_101g_brw_size_test 16 || error "16MB RPC test failed"
11790                 # should be able to set brw_size=12, but no rpc_stats for that
11791                 test_101g_brw_size_test 8 || error "8MB RPC test failed"
11792         fi
11793
11794         test_101g_brw_size_test 4 || error "4MB RPC test failed"
11795
11796         if [[ $orig_mb -lt 16 ]]; then
11797                 restore_lustre_params < $p
11798                 remount_client $MOUNT || error "remount_client restore failed"
11799         fi
11800
11801         rm -f $p $DIR/$tfile
11802 }
11803 run_test 101g "Big bulk(4/16 MiB) readahead"
11804
11805 test_101h() {
11806         $LFS setstripe -i 0 -c 1 $DIR/$tfile
11807
11808         dd if=/dev/zero of=$DIR/$tfile bs=1M count=70 ||
11809                 error "dd 70M file failed"
11810         echo Cancel LRU locks on lustre client to flush the client cache
11811         cancel_lru_locks osc
11812
11813         echo "Reset readahead stats"
11814         $LCTL set_param -n llite.*.read_ahead_stats 0
11815
11816         echo "Read 10M of data but cross 64M bundary"
11817         dd if=$DIR/$tfile of=/dev/null bs=10M skip=6 count=1
11818         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
11819                      get_named_value 'misses' | calc_sum)
11820         [ $miss -eq 1 ] || error "expected miss 1 but got $miss"
11821         rm -f $p $DIR/$tfile
11822 }
11823 run_test 101h "Readahead should cover current read window"
11824
11825 test_101i() {
11826         dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 ||
11827                 error "dd 10M file failed"
11828
11829         local max_per_file_mb=$($LCTL get_param -n \
11830                 llite.*.max_read_ahead_per_file_mb 2>/dev/null)
11831         cancel_lru_locks osc
11832         stack_trap "$LCTL set_param llite.*.max_read_ahead_per_file_mb=$max_per_file_mb"
11833         $LCTL set_param llite.*.max_read_ahead_per_file_mb=1 ||
11834                 error "set max_read_ahead_per_file_mb to 1 failed"
11835
11836         echo "Reset readahead stats"
11837         $LCTL set_param llite.*.read_ahead_stats=0
11838
11839         dd if=$DIR/$tfile of=/dev/null bs=2M
11840
11841         $LCTL get_param llite.*.read_ahead_stats
11842         local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
11843                      awk '/misses/ { print $2 }')
11844         [ $miss -eq 5 ] || error "expected misses 5 but got $miss"
11845         rm -f $DIR/$tfile
11846 }
11847 run_test 101i "allow current readahead to exceed reservation"
11848
11849 test_101j() {
11850         $LFS setstripe -i 0 -c 1 $DIR/$tfile ||
11851                 error "setstripe $DIR/$tfile failed"
11852         local file_size=$((1048576 * 16))
11853         local old_ra=$($LCTL get_param -n llite.*.max_read_ahead_mb | head -n 1)
11854         stack_trap "$LCTL set_param -n llite.*.max_read_ahead_mb $old_ra" EXIT
11855
11856         echo Disable read-ahead
11857         $LCTL set_param -n llite.*.max_read_ahead_mb=0
11858
11859         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$(($file_size / 1048576))
11860         for blk in $PAGE_SIZE 1048576 $file_size; do
11861                 cancel_lru_locks osc
11862                 echo "Reset readahead stats"
11863                 $LCTL set_param -n llite.*.read_ahead_stats=0
11864                 local count=$(($file_size / $blk))
11865                 dd if=$DIR/$tfile bs=$blk count=$count of=/dev/null
11866                 local miss=$($LCTL get_param -n llite.*.read_ahead_stats |
11867                              get_named_value 'failed.to.fast.read' | calc_sum)
11868                 $LCTL get_param -n llite.*.read_ahead_stats
11869                 [ $miss -eq $count ] || error "expected $count got $miss"
11870         done
11871
11872         rm -f $p $DIR/$tfile
11873 }
11874 run_test 101j "A complete read block should be submitted when no RA"
11875
11876 test_readahead_base() {
11877         local file=$DIR/$tfile
11878         local size=$1
11879         local iosz
11880         local ramax
11881         local ranum
11882
11883         $LCTL set_param -n llite.*.read_ahead_stats=0
11884         # The first page is not accounted into readahead
11885         ramax=$(((size + PAGE_SIZE - 1) / PAGE_SIZE - 1))
11886         iosz=$(((size + 1048575) / 1048576 * 1048576))
11887         echo "Test readahead: size=$size ramax=$ramx iosz=$iosz"
11888
11889         $LCTL mark  "Test readahead: size=$size ramax=$ramx iosz=$iosz"
11890         fallocate -l $size $file || error "failed to fallocate $file"
11891         cancel_lru_locks osc
11892         $MULTIOP $file or${iosz}c || error "failed to read $file"
11893         $LCTL get_param -n llite.*.read_ahead_stats
11894         ranum=$($LCTL get_param -n llite.*.read_ahead_stats |
11895                 awk '/readahead.pages/ { print $7 }' | calc_sum)
11896         (( $ranum <= $ramax )) ||
11897                 error "read-ahead pages is $ranum more than $ramax"
11898         rm -rf $file || error "failed to remove $file"
11899 }
11900
11901 test_101m()
11902 {
11903         local file=$DIR/$tfile
11904         local ramax
11905         local ranum
11906         local size
11907         local iosz
11908
11909         check_set_fallocate_or_skip
11910         stack_trap "rm -f $file" EXIT
11911
11912         test_readahead_base 4096
11913
11914         # file size: 16K = 16384
11915         test_readahead_base 16384
11916         test_readahead_base 16385
11917         test_readahead_base 16383
11918
11919         # file size: 1M + 1 = 1048576 + 1
11920         test_readahead_base 1048577
11921         # file size: 1M + 16K
11922         test_readahead_base $((1048576 + 16384))
11923
11924         # file size: stripe_size * (stripe_count - 1) + 16K
11925         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
11926         test_readahead_base $((1048576 * (OSTCOUNT - 1) + 16384))
11927         # file size: stripe_size * stripe_count + 16K
11928         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
11929         test_readahead_base $((1048576 * OSTCOUNT + 16384))
11930         # file size: 2 * stripe_size * stripe_count + 16K
11931         $LFS setstripe -c -1 $file || error "failed to setstripe $file"
11932         test_readahead_base $((2 * 1048576 * OSTCOUNT + 16384))
11933 }
11934 run_test 101m "read ahead for small file and last stripe of the file"
11935
11936 setup_test102() {
11937         test_mkdir $DIR/$tdir
11938         chown $RUNAS_ID $DIR/$tdir
11939         STRIPE_SIZE=65536
11940         STRIPE_OFFSET=1
11941         STRIPE_COUNT=$OSTCOUNT
11942         [[ $OSTCOUNT -gt 4 ]] && STRIPE_COUNT=4
11943
11944         trap cleanup_test102 EXIT
11945         cd $DIR
11946         $1 $LFS setstripe -S $STRIPE_SIZE -i $STRIPE_OFFSET -c $STRIPE_COUNT $tdir
11947         cd $DIR/$tdir
11948         for num in 1 2 3 4; do
11949                 for count in $(seq 1 $STRIPE_COUNT); do
11950                         for idx in $(seq 0 $[$STRIPE_COUNT - 1]); do
11951                                 local size=`expr $STRIPE_SIZE \* $num`
11952                                 local file=file"$num-$idx-$count"
11953                                 $1 $LFS setstripe -S $size -i $idx -c $count $file
11954                         done
11955                 done
11956         done
11957
11958         cd $DIR
11959         $1 tar cf $TMP/f102.tar $tdir --xattrs
11960 }
11961
11962 cleanup_test102() {
11963         trap 0
11964         rm -f $TMP/f102.tar
11965         rm -rf $DIR/d0.sanity/d102
11966 }
11967
11968 test_102a() {
11969         [ "$UID" != 0 ] && skip "must run as root"
11970         [ -z "$(lctl get_param -n mdc.*-mdc-*.connect_flags | grep xattr)" ] &&
11971                 skip_env "must have user_xattr"
11972
11973         [ -z "$(which setfattr 2>/dev/null)" ] &&
11974                 skip_env "could not find setfattr"
11975
11976         local testfile=$DIR/$tfile
11977
11978         touch $testfile
11979         echo "set/get xattr..."
11980         setfattr -n trusted.name1 -v value1 $testfile ||
11981                 error "setfattr -n trusted.name1=value1 $testfile failed"
11982         getfattr -n trusted.name1 $testfile 2> /dev/null |
11983           grep "trusted.name1=.value1" ||
11984                 error "$testfile missing trusted.name1=value1"
11985
11986         setfattr -n user.author1 -v author1 $testfile ||
11987                 error "setfattr -n user.author1=author1 $testfile failed"
11988         getfattr -n user.author1 $testfile 2> /dev/null |
11989           grep "user.author1=.author1" ||
11990                 error "$testfile missing trusted.author1=author1"
11991
11992         echo "listxattr..."
11993         setfattr -n trusted.name2 -v value2 $testfile ||
11994                 error "$testfile unable to set trusted.name2"
11995         setfattr -n trusted.name3 -v value3 $testfile ||
11996                 error "$testfile unable to set trusted.name3"
11997         [ $(getfattr -d -m "^trusted" $testfile 2> /dev/null |
11998             grep "trusted.name" | wc -l) -eq 3 ] ||
11999                 error "$testfile missing 3 trusted.name xattrs"
12000
12001         setfattr -n user.author2 -v author2 $testfile ||
12002                 error "$testfile unable to set user.author2"
12003         setfattr -n user.author3 -v author3 $testfile ||
12004                 error "$testfile unable to set user.author3"
12005         [ $(getfattr -d -m "^user" $testfile 2> /dev/null |
12006             grep "user.author" | wc -l) -eq 3 ] ||
12007                 error "$testfile missing 3 user.author xattrs"
12008
12009         echo "remove xattr..."
12010         setfattr -x trusted.name1 $testfile ||
12011                 error "$testfile error deleting trusted.name1"
12012         getfattr -d -m trusted $testfile 2> /dev/null | grep "trusted.name1" &&
12013                 error "$testfile did not delete trusted.name1 xattr"
12014
12015         setfattr -x user.author1 $testfile ||
12016                 error "$testfile error deleting user.author1"
12017         echo "set lustre special xattr ..."
12018         $LFS setstripe -c1 $testfile
12019         local lovea=$(getfattr -n "trusted.lov" -e hex $testfile |
12020                 awk -F "=" '/trusted.lov/ { print $2 }' )
12021         setfattr -n "trusted.lov" -v $lovea $testfile ||
12022                 error "$testfile doesn't ignore setting trusted.lov again"
12023         setfattr -n "trusted.lov" -v "invalid_value" $testfile &&
12024                 error "$testfile allow setting invalid trusted.lov"
12025         rm -f $testfile
12026 }
12027 run_test 102a "user xattr test =================================="
12028
12029 check_102b_layout() {
12030         local layout="$*"
12031         local testfile=$DIR/$tfile
12032
12033         echo "test layout '$layout'"
12034         $LFS setstripe $layout $testfile || error "setstripe failed"
12035         $LFS getstripe -y $testfile
12036
12037         echo "get/set/list trusted.lov xattr ..." # b=10930
12038         local value=$(getfattr -n trusted.lov -e hex $testfile | grep trusted)
12039         [[ "$value" =~ "trusted.lov" ]] ||
12040                 error "can't get trusted.lov from $testfile"
12041         local stripe_count_orig=$($LFS getstripe -c $testfile) ||
12042                 error "getstripe failed"
12043
12044         $MCREATE $testfile.2 || error "mcreate $testfile.2 failed"
12045
12046         value=$(cut -d= -f2 <<<$value)
12047         # LU-13168: truncated xattr should fail if short lov_user_md header
12048         [ $CLIENT_VERSION -lt $(version_code 2.13.53) ] &&
12049                 lens="${#value}" || lens="$(seq 4 2 ${#value})"
12050         for len in $lens; do
12051                 echo "setfattr $len $testfile.2"
12052                 setfattr -n trusted.lov -v ${value:0:$len} $testfile.2 &&
12053                         [ $len -lt 66 ] && error "short xattr len=$len worked"
12054         done
12055         local stripe_size=$($LFS getstripe -S $testfile.2)
12056         local stripe_count=$($LFS getstripe -c $testfile.2)
12057         [[ $stripe_size -eq 65536 ]] ||
12058                 error "stripe size $stripe_size != 65536"
12059         [[ $stripe_count -eq $stripe_count_orig ]] ||
12060                 error "stripe count $stripe_count != $stripe_count_orig"
12061         rm $testfile $testfile.2
12062 }
12063
12064 test_102b() {
12065         [ -z "$(which setfattr 2>/dev/null)" ] &&
12066                 skip_env "could not find setfattr"
12067         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12068
12069         # check plain layout
12070         check_102b_layout -S 65536 -i 1 -c $OSTCOUNT
12071
12072         # and also check composite layout
12073         check_102b_layout -E 1M -S 65536 -i 1 -c $OSTCOUNT -Eeof -S4M
12074
12075 }
12076 run_test 102b "getfattr/setfattr for trusted.lov EAs"
12077
12078 test_102c() {
12079         [ -z "$(which setfattr 2>/dev/null)" ] &&
12080                 skip_env "could not find setfattr"
12081         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12082
12083         # b10930: get/set/list lustre.lov xattr
12084         echo "get/set/list lustre.lov xattr ..."
12085         test_mkdir $DIR/$tdir
12086         chown $RUNAS_ID $DIR/$tdir
12087         local testfile=$DIR/$tdir/$tfile
12088         $RUNAS $LFS setstripe -S 65536 -i 1 -c $OSTCOUNT $testfile ||
12089                 error "setstripe failed"
12090         local STRIPECOUNT=$($RUNAS $LFS getstripe -c $testfile) ||
12091                 error "getstripe failed"
12092         $RUNAS getfattr -d -m "^lustre" $testfile 2> /dev/null | \
12093         grep "lustre.lov" || error "can't get lustre.lov from $testfile"
12094
12095         local testfile2=${testfile}2
12096         local value=`getfattr -n lustre.lov $testfile 2> /dev/null | \
12097                      grep "lustre.lov" |sed -e 's/[^=]\+=//'  `
12098
12099         $RUNAS $MCREATE $testfile2
12100         $RUNAS setfattr -n lustre.lov -v $value $testfile2
12101         local stripe_size=$($RUNAS $LFS getstripe -S $testfile2)
12102         local stripe_count=$($RUNAS $LFS getstripe -c $testfile2)
12103         [ $stripe_size -eq 65536 ] || error "stripe size $stripe_size != 65536"
12104         [ $stripe_count -eq $STRIPECOUNT ] ||
12105                 error "stripe count $stripe_count != $STRIPECOUNT"
12106 }
12107 run_test 102c "non-root getfattr/setfattr for lustre.lov EAs ==========="
12108
12109 compare_stripe_info1() {
12110         local stripe_index_all_zero=true
12111
12112         for num in 1 2 3 4; do
12113                 for count in $(seq 1 $STRIPE_COUNT); do
12114                         for offset in $(seq 0 $[$STRIPE_COUNT - 1]); do
12115                                 local size=$((STRIPE_SIZE * num))
12116                                 local file=file"$num-$offset-$count"
12117                                 stripe_size=$($LFS getstripe -S $PWD/$file)
12118                                 [[ $stripe_size -ne $size ]] &&
12119                                     error "$file: size $stripe_size != $size"
12120                                 stripe_count=$($LFS getstripe -c $PWD/$file)
12121                                 # allow fewer stripes to be created, ORI-601
12122                                 [[ $stripe_count -lt $(((3 * count + 3) / 4)) ]] &&
12123                                     error "$file: count $stripe_count != $count"
12124                                 stripe_index=$($LFS getstripe -i $PWD/$file)
12125                                 [[ $stripe_index -ne 0 ]] &&
12126                                         stripe_index_all_zero=false
12127                         done
12128                 done
12129         done
12130         $stripe_index_all_zero &&
12131                 error "all files are being extracted starting from OST index 0"
12132         return 0
12133 }
12134
12135 have_xattrs_include() {
12136         tar --help | grep -q xattrs-include &&
12137                 echo --xattrs-include="lustre.*"
12138 }
12139
12140 test_102d() {
12141         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12142         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12143
12144         XINC=$(have_xattrs_include)
12145         setup_test102
12146         tar xf $TMP/f102.tar -C $DIR/$tdir --xattrs $XINC
12147         cd $DIR/$tdir/$tdir
12148         compare_stripe_info1
12149 }
12150 run_test 102d "tar restore stripe info from tarfile,not keep osts"
12151
12152 test_102f() {
12153         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12154         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12155
12156         XINC=$(have_xattrs_include)
12157         setup_test102
12158         test_mkdir $DIR/$tdir.restore
12159         cd $DIR
12160         tar cf - --xattrs $tdir | tar xf - \
12161                 -C $DIR/$tdir.restore --xattrs $XINC
12162         cd $DIR/$tdir.restore/$tdir
12163         compare_stripe_info1
12164 }
12165 run_test 102f "tar copy files, not keep osts"
12166
12167 grow_xattr() {
12168         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep xattr)" ] &&
12169                 skip "must have user_xattr"
12170         [ -z "$(which setfattr 2>/dev/null)" ] &&
12171                 skip_env "could not find setfattr"
12172         [ -z "$(which getfattr 2>/dev/null)" ] &&
12173                 skip_env "could not find getfattr"
12174
12175         local xsize=${1:-1024}  # in bytes
12176         local file=$DIR/$tfile
12177         local value="$(generate_string $xsize)"
12178         local xbig=trusted.big
12179         local toobig=$2
12180
12181         touch $file
12182         log "save $xbig on $file"
12183         if [ -z "$toobig" ]
12184         then
12185                 setfattr -n $xbig -v $value $file ||
12186                         error "saving $xbig on $file failed"
12187         else
12188                 setfattr -n $xbig -v $value $file &&
12189                         error "saving $xbig on $file succeeded"
12190                 return 0
12191         fi
12192
12193         local orig=$(get_xattr_value $xbig $file)
12194         [[ "$orig" != "$value" ]] && error "$xbig different after saving $xbig"
12195
12196         local xsml=trusted.sml
12197         log "save $xsml on $file"
12198         setfattr -n $xsml -v val $file || error "saving $xsml on $file failed"
12199
12200         local new=$(get_xattr_value $xbig $file)
12201         [[ "$new" != "$orig" ]] && error "$xbig different after saving $xsml"
12202
12203         log "grow $xsml on $file"
12204         setfattr -n $xsml -v "$value" $file ||
12205                 error "growing $xsml on $file failed"
12206
12207         new=$(get_xattr_value $xbig $file)
12208         [[ "$new" != "$orig" ]] && error "$xbig different after growing $xsml"
12209         log "$xbig still valid after growing $xsml"
12210
12211         rm -f $file
12212 }
12213
12214 test_102h() { # bug 15777
12215         grow_xattr 1024
12216 }
12217 run_test 102h "grow xattr from inside inode to external block"
12218
12219 test_102ha() {
12220         large_xattr_enabled || skip_env "ea_inode feature disabled"
12221
12222         echo "setting xattr of max xattr size: $(max_xattr_size)"
12223         grow_xattr $(max_xattr_size)
12224
12225         echo "setting xattr of > max xattr size: $(max_xattr_size) + 10"
12226         echo "This should fail:"
12227         grow_xattr $(($(max_xattr_size) + 10)) 1
12228 }
12229 run_test 102ha "grow xattr from inside inode to external inode"
12230
12231 test_102i() { # bug 17038
12232         [ -z "$(which getfattr 2>/dev/null)" ] &&
12233                 skip "could not find getfattr"
12234
12235         touch $DIR/$tfile
12236         ln -s $DIR/$tfile $DIR/${tfile}link
12237         getfattr -n trusted.lov $DIR/$tfile ||
12238                 error "lgetxattr on $DIR/$tfile failed"
12239         getfattr -h -n trusted.lov $DIR/${tfile}link 2>&1 |
12240                 grep -i "no such attr" ||
12241                 error "error for lgetxattr on $DIR/${tfile}link is not ENODATA"
12242         rm -f $DIR/$tfile $DIR/${tfile}link
12243 }
12244 run_test 102i "lgetxattr test on symbolic link ============"
12245
12246 test_102j() {
12247         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12248         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
12249
12250         XINC=$(have_xattrs_include)
12251         setup_test102 "$RUNAS"
12252         chown $RUNAS_ID $DIR/$tdir
12253         $RUNAS tar xf $TMP/f102.tar -C $DIR/$tdir --xattrs $XINC
12254         cd $DIR/$tdir/$tdir
12255         compare_stripe_info1 "$RUNAS"
12256 }
12257 run_test 102j "non-root tar restore stripe info from tarfile, not keep osts ==="
12258
12259 test_102k() {
12260         [ -z "$(which setfattr 2>/dev/null)" ] &&
12261                 skip "could not find setfattr"
12262
12263         touch $DIR/$tfile
12264         # b22187 just check that does not crash for regular file.
12265         setfattr -n trusted.lov $DIR/$tfile
12266         # b22187 'setfattr -n trusted.lov' should remove LOV EA for directories
12267         local test_kdir=$DIR/$tdir
12268         test_mkdir $test_kdir
12269         local default_size=$($LFS getstripe -S $test_kdir)
12270         local default_count=$($LFS getstripe -c $test_kdir)
12271         local default_offset=$($LFS getstripe -i $test_kdir)
12272         $LFS setstripe -S 65536 -i 0 -c $OSTCOUNT $test_kdir ||
12273                 error 'dir setstripe failed'
12274         setfattr -n trusted.lov $test_kdir
12275         local stripe_size=$($LFS getstripe -S $test_kdir)
12276         local stripe_count=$($LFS getstripe -c $test_kdir)
12277         local stripe_offset=$($LFS getstripe -i $test_kdir)
12278         [ $stripe_size -eq $default_size ] ||
12279                 error "stripe size $stripe_size != $default_size"
12280         [ $stripe_count -eq $default_count ] ||
12281                 error "stripe count $stripe_count != $default_count"
12282         [ $stripe_offset -eq $default_offset ] ||
12283                 error "stripe offset $stripe_offset != $default_offset"
12284         rm -rf $DIR/$tfile $test_kdir
12285 }
12286 run_test 102k "setfattr without parameter of value shouldn't cause a crash"
12287
12288 test_102l() {
12289         [ -z "$(which getfattr 2>/dev/null)" ] &&
12290                 skip "could not find getfattr"
12291
12292         # LU-532 trusted. xattr is invisible to non-root
12293         local testfile=$DIR/$tfile
12294
12295         touch $testfile
12296
12297         echo "listxattr as user..."
12298         chown $RUNAS_ID $testfile
12299         $RUNAS getfattr -d -m '.*' $testfile 2>&1 |
12300             grep -q "trusted" &&
12301                 error "$testfile trusted xattrs are user visible"
12302
12303         return 0;
12304 }
12305 run_test 102l "listxattr size test =================================="
12306
12307 test_102m() { # LU-3403 llite: error of listxattr when buffer is small
12308         local path=$DIR/$tfile
12309         touch $path
12310
12311         listxattr_size_check $path || error "listattr_size_check $path failed"
12312 }
12313 run_test 102m "Ensure listxattr fails on small bufffer ========"
12314
12315 cleanup_test102
12316
12317 getxattr() { # getxattr path name
12318         # Return the base64 encoding of the value of xattr name on path.
12319         local path=$1
12320         local name=$2
12321
12322         # # getfattr --absolute-names --encoding=base64 --name=trusted.lov $path
12323         # file: $path
12324         # trusted.lov=0s0AvRCwEAAAAGAAAAAAAAAAAEAAACAAAAAAAQAAEAA...AAAAAAAAA=
12325         #
12326         # We print just 0s0AvRCwEAAAAGAAAAAAAAAAAEAAACAAAAAAAQAAEAA...AAAAAAAAA=
12327
12328         getfattr --absolute-names --encoding=base64 --name=$name $path |
12329                 awk -F= -v name=$name '$1 == name {
12330                         print substr($0, index($0, "=") + 1);
12331         }'
12332 }
12333
12334 test_102n() { # LU-4101 mdt: protect internal xattrs
12335         [ -z "$(which setfattr 2>/dev/null)" ] &&
12336                 skip "could not find setfattr"
12337         if [ $MDS1_VERSION -lt $(version_code 2.5.50) ]
12338         then
12339                 skip "MDT < 2.5.50 allows setxattr on internal trusted xattrs"
12340         fi
12341
12342         local file0=$DIR/$tfile.0
12343         local file1=$DIR/$tfile.1
12344         local xattr0=$TMP/$tfile.0
12345         local xattr1=$TMP/$tfile.1
12346         local namelist="lov lma lmv link fid version som hsm"
12347         local name
12348         local value
12349
12350         rm -rf $file0 $file1 $xattr0 $xattr1
12351         touch $file0 $file1
12352
12353         # Get 'before' xattrs of $file1.
12354         getfattr --absolute-names --dump --match=- $file1 > $xattr0
12355
12356         [ $MDS1_VERSION -lt $(version_code 2.8.53) ] &&
12357                 namelist+=" lfsck_namespace"
12358         for name in $namelist; do
12359                 # Try to copy xattr from $file0 to $file1.
12360                 value=$(getxattr $file0 trusted.$name 2> /dev/null)
12361
12362                 setfattr --name=trusted.$name --value="$value" $file1 ||
12363                         error "setxattr 'trusted.$name' failed"
12364
12365                 # Try to set a garbage xattr.
12366                 value=0sVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIGl0c2VsZi4=
12367
12368                 if [[ x$name == "xlov" ]]; then
12369                         setfattr --name=trusted.lov --value="$value" $file1 &&
12370                         error "setxattr invalid 'trusted.lov' success"
12371                 else
12372                         setfattr --name=trusted.$name --value="$value" $file1 ||
12373                                 error "setxattr invalid 'trusted.$name' failed"
12374                 fi
12375
12376                 # Try to remove the xattr from $file1. We don't care if this
12377                 # appears to succeed or fail, we just don't want there to be
12378                 # any changes or crashes.
12379                 setfattr --remove=$trusted.$name $file1 2> /dev/null
12380         done
12381
12382         if [ $MDS1_VERSION -gt $(version_code 2.6.50) ]
12383         then
12384                 name="lfsck_ns"
12385                 # Try to copy xattr from $file0 to $file1.
12386                 value=$(getxattr $file0 trusted.$name 2> /dev/null)
12387
12388                 setfattr --name=trusted.$name --value="$value" $file1 ||
12389                         error "setxattr 'trusted.$name' failed"
12390
12391                 # Try to set a garbage xattr.
12392                 value=0sVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIGl0c2VsZi4=
12393
12394                 setfattr --name=trusted.$name --value="$value" $file1 ||
12395                         error "setxattr 'trusted.$name' failed"
12396
12397                 # Try to remove the xattr from $file1. We don't care if this
12398                 # appears to succeed or fail, we just don't want there to be
12399                 # any changes or crashes.
12400                 setfattr --remove=$trusted.$name $file1 2> /dev/null
12401         fi
12402
12403         # Get 'after' xattrs of file1.
12404         getfattr --absolute-names --dump --match=- $file1 > $xattr1
12405
12406         if ! diff $xattr0 $xattr1; then
12407                 error "before and after xattrs of '$file1' differ"
12408         fi
12409
12410         rm -rf $file0 $file1 $xattr0 $xattr1
12411
12412         return 0
12413 }
12414 run_test 102n "silently ignore setxattr on internal trusted xattrs"
12415
12416 test_102p() { # LU-4703 setxattr did not check ownership
12417         [ $MDS1_VERSION -lt $(version_code 2.5.56) ] &&
12418                 skip "MDS needs to be at least 2.5.56"
12419
12420         local testfile=$DIR/$tfile
12421
12422         touch $testfile
12423
12424         echo "setfacl as user..."
12425         $RUNAS setfacl -m "u:$RUNAS_ID:rwx" $testfile
12426         [ $? -ne 0 ] || error "setfacl by $RUNAS_ID was allowed on $testfile"
12427
12428         echo "setfattr as user..."
12429         setfacl -m "u:$RUNAS_ID:---" $testfile
12430         $RUNAS setfattr -x system.posix_acl_access $testfile
12431         [ $? -ne 0 ] || error "setfattr by $RUNAS_ID was allowed on $testfile"
12432 }
12433 run_test 102p "check setxattr(2) correctly fails without permission"
12434
12435 test_102q() {
12436         [ $MDS1_VERSION -lt $(version_code 2.6.92) ] &&
12437                 skip "MDS needs to be at least 2.6.92"
12438
12439         orphan_linkea_check $DIR/$tfile || error "orphan_linkea_check"
12440 }
12441 run_test 102q "flistxattr should not return trusted.link EAs for orphans"
12442
12443 test_102r() {
12444         [ $MDS1_VERSION -lt $(version_code 2.6.93) ] &&
12445                 skip "MDS needs to be at least 2.6.93"
12446
12447         touch $DIR/$tfile || error "touch"
12448         setfattr -n user.$(basename $tfile) $DIR/$tfile || error "setfattr"
12449         getfattr -n user.$(basename $tfile) $DIR/$tfile || error "getfattr"
12450         rm $DIR/$tfile || error "rm"
12451
12452         #normal directory
12453         mkdir -p $DIR/$tdir || error "mkdir"
12454         setfattr -n user.$(basename $tdir) $DIR/$tdir || error "setfattr dir"
12455         getfattr -n user.$(basename $tdir) $DIR/$tdir || error "getfattr dir"
12456         setfattr -x user.$(basename $tdir) $DIR/$tdir ||
12457                 error "$testfile error deleting user.author1"
12458         getfattr -d -m user.$(basename $tdir) 2> /dev/null |
12459                 grep "user.$(basename $tdir)" &&
12460                 error "$tdir did not delete user.$(basename $tdir)"
12461         rmdir $DIR/$tdir || error "rmdir"
12462
12463         #striped directory
12464         test_mkdir $DIR/$tdir
12465         setfattr -n user.$(basename $tdir) $DIR/$tdir || error "setfattr dir"
12466         getfattr -n user.$(basename $tdir) $DIR/$tdir || error "getfattr dir"
12467         setfattr -x user.$(basename $tdir) $DIR/$tdir ||
12468                 error "$testfile error deleting user.author1"
12469         getfattr -d -m user.$(basename $tdir) 2> /dev/null |
12470                 grep "user.$(basename $tdir)" &&
12471                 error "$tdir did not delete user.$(basename $tdir)"
12472         rmdir $DIR/$tdir || error "rm striped dir"
12473 }
12474 run_test 102r "set EAs with empty values"
12475
12476 test_102s() {
12477         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
12478                 skip "MDS needs to be at least 2.11.52"
12479
12480         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
12481
12482         save_lustre_params client "llite.*.xattr_cache" > $save
12483
12484         for cache in 0 1; do
12485                 lctl set_param llite.*.xattr_cache=$cache
12486
12487                 rm -f $DIR/$tfile
12488                 touch $DIR/$tfile || error "touch"
12489                 for prefix in lustre security system trusted user; do
12490                         # Note getxattr() may fail with 'Operation not
12491                         # supported' or 'No such attribute' depending
12492                         # on prefix and cache.
12493                         getfattr -n $prefix.n102s $DIR/$tfile &&
12494                                 error "getxattr '$prefix.n102s' should fail (cache = $cache)"
12495                 done
12496         done
12497
12498         restore_lustre_params < $save
12499 }
12500 run_test 102s "getting nonexistent xattrs should fail"
12501
12502 test_102t() {
12503         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
12504                 skip "MDS needs to be at least 2.11.52"
12505
12506         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
12507
12508         save_lustre_params client "llite.*.xattr_cache" > $save
12509
12510         for cache in 0 1; do
12511                 lctl set_param llite.*.xattr_cache=$cache
12512
12513                 for buf_size in 0 256; do
12514                         rm -f $DIR/$tfile
12515                         touch $DIR/$tfile || error "touch"
12516                         setfattr -n user.multiop $DIR/$tfile
12517                         $MULTIOP $DIR/$tfile oa$buf_size ||
12518                                 error "cannot get zero length xattr value (buf_size = $buf_size)"
12519                 done
12520         done
12521
12522         restore_lustre_params < $save
12523 }
12524 run_test 102t "zero length xattr values handled correctly"
12525
12526 run_acl_subtest()
12527 {
12528         local test=$LUSTRE/tests/acl/$1.test
12529         local tmp=$(mktemp -t $1-XXXXXX).test
12530         local bin=$2
12531         local dmn=$3
12532         local grp=$4
12533         local nbd=$5
12534         export LANG=C
12535
12536
12537         local sedusers="-e s/bin/$bin/g -e s/daemon/$dmn/g"
12538         local sedgroups="-e s/:users/:$grp/g"
12539         [[ -z "$nbd" ]] || sedusers+=" -e s/nobody/$nbd/g"
12540
12541         sed $sedusers $sedgroups < $test > $tmp
12542         stack_trap "rm -f $tmp"
12543         [[ -s $tmp ]] || error "sed failed to create test script"
12544
12545         echo "performing $1 with bin='$bin' daemon='$dmn' users='$grp'..."
12546         $LUSTRE/tests/acl/run $tmp || error "run_acl_subtest '$1' failed"
12547 }
12548
12549 test_103a() {
12550         [ "$UID" != 0 ] && skip "must run as root"
12551         $GSS && skip_env "could not run under gss"
12552         [[ "$(lctl get_param -n mdc.*-mdc-*.connect_flags)" =~ "acl" ]] ||
12553                 skip_env "must have acl enabled"
12554         which setfacl || skip_env "could not find setfacl"
12555         remote_mds_nodsh && skip "remote MDS with nodsh"
12556
12557         local mdts=$(comma_list $(mdts_nodes))
12558         local saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
12559
12560         [[ -z "$saved" ]] || do_nodes $mdts $LCTL set_param mdt.*.job_xattr=NONE
12561         stack_trap "[[ -z \"$saved\" ]] || \
12562                     do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$saved" EXIT
12563
12564         ACLBIN=${ACLBIN:-"bin"}
12565         ACLDMN=${ACLDMN:-"daemon"}
12566         ACLGRP=${ACLGRP:-"users"}
12567         ACLNBD=${ACLNBD:-"nobody"}
12568
12569         if ! id $ACLBIN ||
12570            [[ "$(id -u $ACLBIN)" != "$(do_facet mds1 id -u $ACLBIN)" ]]; then
12571                 echo "bad 'bin' user '$ACLBIN', using '$USER0'"
12572                 ACLBIN=$USER0
12573                 if ! id $ACLBIN ; then
12574                         cat /etc/passwd
12575                         skip_env "can't find suitable ACL 'bin' $ACLBIN"
12576                 fi
12577         fi
12578         if ! id $ACLDMN || (( $(id -u $ACLDMN) < $(id -u $ACLBIN) )) ||
12579            [[ "$(id -u $ACLDMN)" != "$(do_facet mds1 id -u $ACLDMN)" ]]; then
12580                 echo "bad 'daemon' user '$ACLDMN', using '$USER1'"
12581                 ACLDMN=$USER1
12582                 if ! id $ACLDMN ; then
12583                         cat /etc/passwd
12584                         skip_env "can't find suitable ACL 'daemon' $ACLDMN"
12585                 fi
12586         fi
12587         if ! getent group $ACLGRP; then
12588                 echo "missing 'users' group '$ACLGRP', using '$TSTUSR'"
12589                 ACLGRP="$TSTUSR"
12590                 if ! getent group $ACLGRP; then
12591                         echo "cannot find group '$ACLGRP', adding it"
12592                         cat /etc/group
12593                         add_group 60000 $ACLGRP
12594                 fi
12595         fi
12596
12597         local bingid=$(getent group $ACLBIN | cut -d: -f 3)
12598         local dmngid=$(getent group $ACLDMN | cut -d: -f 3)
12599         local grpgid=$(getent group $ACLGRP | cut -d: -f 3)
12600
12601         if (( $bingid > $grpgid || $dmngid > $grpgid )); then
12602                 echo "group '$ACLGRP' has low gid=$grpgid, use '$TSTUSR'"
12603                 ACLGRP="$TSTUSR"
12604                 if ! getent group $ACLGRP; then
12605                         echo "cannot find group '$ACLGRP', adding it"
12606                         cat /etc/group
12607                         add_group 60000 $ACLGRP
12608                 fi
12609                 grpgid=$(getent group $ACLGRP | cut -d: -f 3)
12610                 if (( $bingid > $grpgid || $dmngid > $grpgid )); then
12611                         cat /etc/group
12612                         skip_env "$ACLGRP gid=$grpgid less than $bingid|$dmngid"
12613                 fi
12614         fi
12615
12616         gpasswd -a $ACLDMN $ACLBIN ||
12617                 error "setting client group failed"             # LU-5641
12618         do_facet mds1 gpasswd -a $ACLDMN $ACLBIN ||
12619                 error "setting MDS group failed"                # LU-5641
12620
12621         declare -a identity_old
12622
12623         for ((num = 1; num <= $MDSCOUNT; num++)); do
12624                 switch_identity $num true || identity_old[$num]=$?
12625         done
12626
12627         SAVE_UMASK=$(umask)
12628         umask 0022
12629         mkdir -p $DIR/$tdir
12630         cd $DIR/$tdir
12631
12632         run_acl_subtest cp $ACLBIN $ACLDMN $ACLGRP
12633         run_acl_subtest getfacl-noacl $ACLBIN $ACLDMN $ACLGRP
12634         run_acl_subtest misc $ACLBIN $ACLDMN $ACLGRP
12635         run_acl_subtest permissions $ACLBIN $ACLDMN $ACLGRP
12636         # LU-1482 mdd: Setting xattr are properly checked with and without ACLs
12637         # CentOS7- uses nobody=99, while newer distros use nobody=65534
12638         if ! id -u $ACLNBD ||
12639            (( $(id -u nobody) != $(do_facet mds1 id -u nobody) )); then
12640                 ACLNBD="nfsnobody"
12641                 if ! id -u $ACLNBD; then
12642                         ACLNBD=""
12643                 fi
12644         fi
12645         if [[ -n "$ACLNBD" ]] && ! getent group $ACLNBD; then
12646                 add_group $(id -u $ACLNBD) $ACLNBD
12647                 if ! getent group $ACLNBD; then
12648                         ACLNBD=""
12649                 fi
12650         fi
12651         if (( $MDS1_VERSION > $(version_code 2.8.55) )) &&
12652            [[ -n "$ACLNBD" ]] && which setfattr; then
12653                 run_acl_subtest permissions_xattr \
12654                         $ACLBIN $ACLDMN $ACLGRP $ACLNBD
12655         elif [[ -z "$ACLNBD" ]]; then
12656                 echo "skip 'permission_xattr' test - missing 'nobody' user/grp"
12657         else
12658                 echo "skip 'permission_xattr' test - missing setfattr command"
12659         fi
12660         run_acl_subtest setfacl $ACLBIN $ACLDMN $ACLGRP
12661
12662         # inheritance test got from HP
12663         cp $LUSTRE/tests/acl/make-tree . || error "cannot copy make-tree"
12664         chmod +x make-tree || error "chmod +x failed"
12665         run_acl_subtest inheritance $ACLBIN $ACLDMN $ACLGRP
12666         rm -f make-tree
12667
12668         echo "LU-974 ignore umask when acl is enabled..."
12669         run_acl_subtest 974 $ACLBIN $ACLDMN $ACLGRP
12670         if [ $MDSCOUNT -ge 2 ]; then
12671                 run_acl_subtest 974_remote $ACLBIN $ACLDMN $ACLGRP
12672         fi
12673
12674         echo "LU-2561 newly created file is same size as directory..."
12675         if [ "$mds1_FSTYPE" != "zfs" ]; then
12676                 run_acl_subtest 2561 $ACLBIN $ACLDMN $ACLGRP
12677         else
12678                 run_acl_subtest 2561_zfs $ACLBIN $ACLDMN $ACLGRP
12679         fi
12680
12681         run_acl_subtest 4924 $ACLBIN $ACLDMN $ACLGRP
12682
12683         cd $SAVE_PWD
12684         umask $SAVE_UMASK
12685
12686         for ((num = 1; num <= $MDSCOUNT; num++)); do
12687                 if [[ "${identity_old[$num]}" == 1 ]]; then
12688                         switch_identity $num false || identity_old[$num]=$?
12689                 fi
12690         done
12691 }
12692 run_test 103a "acl test"
12693
12694 test_103b() {
12695         declare -a pids
12696         local U
12697
12698         stack_trap "rm -f $DIR/$tfile.*"
12699         for U in {0..511}; do
12700                 {
12701                 local O=$(printf "%04o" $U)
12702
12703                 umask $(printf "%04o" $((511 ^ $O)))
12704                 $LFS setstripe -c 1 $DIR/$tfile.s$O
12705                 local S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.s$O))
12706
12707                 (( $S == ($O & 0666) )) ||
12708                         error "lfs setstripe $DIR/$tfile.s$O '$S' != '$O'"
12709
12710                 $LFS setstripe -E16M -c 1 -E1G -S4M $DIR/$tfile.p$O
12711                 S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.p$O))
12712                 (( $S == ($O & 0666) )) ||
12713                         error "lfs setstripe -E $DIR/$tfile.p$O '$S' != '$O'"
12714
12715                 $LFS setstripe -N2 -c 1 $DIR/$tfile.m$O
12716                 S=$(printf "%04o" 0$(stat -c%a $DIR/$tfile.m$O))
12717                 (( $S == ($O & 0666) )) ||
12718                         error "lfs setstripe -N2 $DIR/$tfile.m$O '$S' != '$O'"
12719                 rm -f $DIR/$tfile.[smp]$0
12720                 } &
12721                 local pid=$!
12722
12723                 # limit the concurrently running threads to 64. LU-11878
12724                 local idx=$((U % 64))
12725                 [ -z "${pids[idx]}" ] || wait ${pids[idx]}
12726                 pids[idx]=$pid
12727         done
12728         wait
12729 }
12730 run_test 103b "umask lfs setstripe"
12731
12732 test_103c() {
12733         mkdir -p $DIR/$tdir
12734         cp -rp $DIR/$tdir $DIR/$tdir.bak
12735
12736         [ -n "$(getfattr -d -m. $DIR/$tdir | grep posix_acl_default)" ] &&
12737                 error "$DIR/$tdir shouldn't contain default ACL"
12738         [ -n "$(getfattr -d -m. $DIR/$tdir.bak | grep posix_acl_default)" ] &&
12739                 error "$DIR/$tdir.bak shouldn't contain default ACL"
12740         true
12741 }
12742 run_test 103c "'cp -rp' won't set empty acl"
12743
12744 test_103e() {
12745         local numacl
12746         local fileacl
12747         local saved_debug=$($LCTL get_param -n debug)
12748
12749         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
12750                 skip "MDS needs to be at least 2.14.52"
12751
12752         large_xattr_enabled || skip_env "ea_inode feature disabled"
12753
12754         mkdir -p $DIR/$tdir
12755         # add big LOV EA to cause reply buffer overflow earlier
12756         $LFS setstripe -C 1000 $DIR/$tdir
12757         lctl set_param mdc.*-mdc*.stats=clear
12758
12759         $LCTL set_param debug=0
12760         stack_trap "$LCTL set_param debug=\"$saved_debug\"" EXIT
12761         stack_trap "$LCTL get_param mdc.*-mdc*.stats" EXIT
12762
12763         # add a large number of default ACLs (expect 8000+ for 2.13+)
12764         for U in {2..7000}; do
12765                 setfacl -d -m user:$U:rwx $DIR/$tdir ||
12766                         error "Able to add just $U default ACLs"
12767         done
12768         numacl=$(getfacl $DIR/$tdir |& grep -c "default:user")
12769         echo "$numacl default ACLs created"
12770
12771         stat $DIR/$tdir || error "Cannot stat directory"
12772         # check file creation
12773         touch $DIR/$tdir/$tfile ||
12774                 error "failed to create $tfile with $numacl default ACLs"
12775         stat $DIR/$tdir/$tfile  || error "Cannot stat file"
12776         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
12777         echo "$fileacl ACLs were inherited"
12778         (( $fileacl == $numacl )) ||
12779                 error "Not all default ACLs were inherited: $numacl != $fileacl"
12780         # check that new ACLs creation adds new ACLs to inherited ACLs
12781         setfacl -m user:19000:rwx $DIR/$tdir/$tfile ||
12782                 error "Cannot set new ACL"
12783         numacl=$((numacl + 1))
12784         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
12785         (( $fileacl == $numacl )) ||
12786                 error "failed to add new ACL: $fileacl != $numacl as expected"
12787         # adds more ACLs to a file to reach their maximum at 8000+
12788         numacl=0
12789         for U in {20000..25000}; do
12790                 setfacl -m user:$U:rwx $DIR/$tdir/$tfile || break
12791                 numacl=$((numacl + 1))
12792         done
12793         echo "Added $numacl more ACLs to the file"
12794         fileacl=$(getfacl $DIR/$tdir/$tfile |& grep -c "user:")
12795         echo "Total $fileacl ACLs in file"
12796         stat $DIR/$tdir/$tfile > /dev/null || error "Cannot stat file"
12797         rm -f $DIR/$tdir/$tfile || error "Cannot remove file"
12798         rmdir $DIR/$tdir || error "Cannot remove directory"
12799 }
12800 run_test 103e "inheritance of big amount of default ACLs"
12801
12802 test_103f() {
12803         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
12804                 skip "MDS needs to be at least 2.14.51"
12805
12806         large_xattr_enabled || skip_env "ea_inode feature disabled"
12807
12808         # enable changelog to consume more internal MDD buffers
12809         changelog_register
12810
12811         mkdir -p $DIR/$tdir
12812         # add big LOV EA
12813         $LFS setstripe -C 1000 $DIR/$tdir
12814         setfacl -d -m user:$U:rwx $DIR/$tdir || error "Cannot add default ACLs"
12815         mkdir $DIR/$tdir/inherited || error "failed to create subdirectory"
12816         rmdir $DIR/$tdir/inherited || error "Cannot remove subdirectory"
12817         rmdir $DIR/$tdir || error "Cannot remove directory"
12818 }
12819 run_test 103f "changelog doesn't interfere with default ACLs buffers"
12820
12821 test_104a() {
12822         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12823
12824         touch $DIR/$tfile
12825         lfs df || error "lfs df failed"
12826         lfs df -ih || error "lfs df -ih failed"
12827         lfs df -h $DIR || error "lfs df -h $DIR failed"
12828         lfs df -i $DIR || error "lfs df -i $DIR failed"
12829         lfs df $DIR/$tfile || error "lfs df $DIR/$tfile failed"
12830         lfs df -ih $DIR/$tfile || error "lfs df -ih $DIR/$tfile failed"
12831
12832         local OSC=$(lctl dl | grep OST0000-osc-[^M] | awk '{ print $4 }')
12833         lctl --device %$OSC deactivate
12834         lfs df || error "lfs df with deactivated OSC failed"
12835         lctl --device %$OSC activate
12836         # wait the osc back to normal
12837         wait_osc_import_ready client ost
12838
12839         lfs df || error "lfs df with reactivated OSC failed"
12840         rm -f $DIR/$tfile
12841 }
12842 run_test 104a "lfs df [-ih] [path] test ========================="
12843
12844 test_104b() {
12845         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12846         [ $RUNAS_ID -eq $UID ] &&
12847                 skip_env "RUNAS_ID = UID = $UID -- skipping"
12848
12849         denied_cnt=$(($($RUNAS $LFS check servers 2>&1 |
12850                         grep "Permission denied" | wc -l)))
12851         if [ $denied_cnt -ne 0 ]; then
12852                 error "lfs check servers test failed"
12853         fi
12854 }
12855 run_test 104b "$RUNAS lfs check servers test ===================="
12856
12857 #
12858 # Verify $1 is within range of $2.
12859 # Success when $1 is within range. That is, when $1 is >= 2% of $2 and
12860 # $1 is <= 2% of $2. Else Fail.
12861 #
12862 value_in_range() {
12863         # Strip all units (M, G, T)
12864         actual=$(echo $1 | tr -d A-Z)
12865         expect=$(echo $2 | tr -d A-Z)
12866
12867         expect_lo=$(($expect * 98 / 100)) # 2% below
12868         expect_hi=$(($expect * 102 / 100)) # 2% above
12869
12870         # permit 2% drift above and below
12871         (( $actual >= $expect_lo && $actual <= $expect_hi ))
12872 }
12873
12874 test_104c() {
12875         [ $PARALLEL == "yes" ] && skip "skip parallel run"
12876         [ "$ost1_FSTYPE" == "zfs" ] || skip "zfs only test"
12877
12878         local ost_param="osd-zfs.$FSNAME-OST0000."
12879         local mdt_param="osd-zfs.$FSNAME-MDT0000."
12880         local ofacets=$(get_facets OST)
12881         local mfacets=$(get_facets MDS)
12882         local saved_ost_blocks=
12883         local saved_mdt_blocks=
12884
12885         echo "Before recordsize change"
12886         lfs_df=($($LFS df -h | grep "filesystem_summary:"))
12887         df=($(df -h | grep "$MOUNT"$))
12888
12889         # For checking.
12890         echo "lfs output : ${lfs_df[*]}"
12891         echo "df  output : ${df[*]}"
12892
12893         for facet in ${ofacets//,/ }; do
12894                 if [ -z $saved_ost_blocks ]; then
12895                         saved_ost_blocks=$(do_facet $facet \
12896                                 lctl get_param -n $ost_param.blocksize)
12897                         echo "OST Blocksize: $saved_ost_blocks"
12898                 fi
12899                 ost=$(do_facet $facet lctl get_param -n $ost_param.mntdev)
12900                 do_facet $facet zfs set recordsize=32768 $ost
12901         done
12902
12903         # BS too small. Sufficient for functional testing.
12904         for facet in ${mfacets//,/ }; do
12905                 if [ -z $saved_mdt_blocks ]; then
12906                         saved_mdt_blocks=$(do_facet $facet \
12907                                 lctl get_param -n $mdt_param.blocksize)
12908                         echo "MDT Blocksize: $saved_mdt_blocks"
12909                 fi
12910                 mdt=$(do_facet $facet lctl get_param -n $mdt_param.mntdev)
12911                 do_facet $facet zfs set recordsize=32768 $mdt
12912         done
12913
12914         # Give new values chance to reflect change
12915         sleep 2
12916
12917         echo "After recordsize change"
12918         lfs_df_after=($($LFS df -h | grep "filesystem_summary:"))
12919         df_after=($(df -h | grep "$MOUNT"$))
12920
12921         # For checking.
12922         echo "lfs output : ${lfs_df_after[*]}"
12923         echo "df  output : ${df_after[*]}"
12924
12925         # Verify lfs df
12926         value_in_range ${lfs_df_after[1]%.*} ${lfs_df[1]%.*} ||
12927                 error "lfs_df bytes: ${lfs_df_after[1]%.*} != ${lfs_df[1]%.*}"
12928         value_in_range ${lfs_df_after[2]%.*} ${lfs_df[2]%.*} ||
12929                 error "lfs_df used: ${lfs_df_after[2]%.*} != ${lfs_df[2]%.*}"
12930         value_in_range ${lfs_df_after[3]%.*} ${lfs_df[3]%.*} ||
12931                 error "lfs_df avail: ${lfs_df_after[3]%.*} != ${lfs_df[3]%.*}"
12932
12933         # Verify df
12934         value_in_range ${df_after[1]%.*} ${df[1]%.*} ||
12935                 error "df bytes: ${df_after[1]%.*} != ${df[1]%.*}"
12936         value_in_range ${df_after[2]%.*} ${df[2]%.*} ||
12937                 error "df used: ${df_after[2]%.*} != ${df[2]%.*}"
12938         value_in_range ${df_after[3]%.*} ${df[3]%.*} ||
12939                 error "df avail: ${df_after[3]%.*} != ${df[3]%.*}"
12940
12941         # Restore MDT recordize back to original
12942         for facet in ${mfacets//,/ }; do
12943                 mdt=$(do_facet $facet lctl get_param -n $mdt_param.mntdev)
12944                 do_facet $facet zfs set recordsize=$saved_mdt_blocks $mdt
12945         done
12946
12947         # Restore OST recordize back to original
12948         for facet in ${ofacets//,/ }; do
12949                 ost=$(do_facet $facet lctl get_param -n $ost_param.mntdev)
12950                 do_facet $facet zfs set recordsize=$saved_ost_blocks $ost
12951         done
12952
12953         return 0
12954 }
12955 run_test 104c "Verify df vs lfs_df stays same after recordsize change"
12956
12957 test_104d() {
12958         (( $RUNAS_ID != $UID )) ||
12959                 skip_env "RUNAS_ID = UID = $UID -- skipping"
12960
12961         (( $CLIENT_VERSION >= $(version_code 2.15.51) )) ||
12962                 skip "lustre version doesn't support lctl dl with non-root"
12963
12964         # debugfs only allows root users to access files, so the
12965         # previous move of the "devices" file to debugfs broke
12966         # "lctl dl" for non-root users. The LU-9680 Netlink
12967         # interface again allows non-root users to list devices.
12968         [ "$($RUNAS $LCTL dl | wc -l)" -ge 3 ] ||
12969                 error "lctl dl doesn't work for non root"
12970
12971         ost_count="$($RUNAS $LCTL dl | grep $FSNAME-OST* | wc -l)"
12972         [ "$ost_count" -eq $OSTCOUNT ]  ||
12973                 error "lctl dl reports wrong number of OST devices"
12974
12975         mdt_count="$($RUNAS $LCTL dl | grep $FSNAME-MDT* | wc -l)"
12976         [ "$mdt_count" -eq $MDSCOUNT ]  ||
12977                 error "lctl dl reports wrong number of MDT devices"
12978 }
12979 run_test 104d "$RUNAS lctl dl test"
12980
12981 test_105a() {
12982         # doesn't work on 2.4 kernels
12983         touch $DIR/$tfile
12984         if $(flock_is_enabled); then
12985                 flocks_test 1 on -f $DIR/$tfile || error "fail flock on"
12986         else
12987                 flocks_test 1 off -f $DIR/$tfile || error "fail flock off"
12988         fi
12989         rm -f $DIR/$tfile
12990 }
12991 run_test 105a "flock when mounted without -o flock test ========"
12992
12993 test_105b() {
12994         touch $DIR/$tfile
12995         if $(flock_is_enabled); then
12996                 flocks_test 1 on -c $DIR/$tfile || error "fail flock on"
12997         else
12998                 flocks_test 1 off -c $DIR/$tfile || error "fail flock off"
12999         fi
13000         rm -f $DIR/$tfile
13001 }
13002 run_test 105b "fcntl when mounted without -o flock test ========"
13003
13004 test_105c() {
13005         touch $DIR/$tfile
13006         if $(flock_is_enabled); then
13007                 flocks_test 1 on -l $DIR/$tfile || error "fail flock on"
13008         else
13009                 flocks_test 1 off -l $DIR/$tfile || error "fail flock off"
13010         fi
13011         rm -f $DIR/$tfile
13012 }
13013 run_test 105c "lockf when mounted without -o flock test"
13014
13015 test_105d() { # bug 15924
13016         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13017
13018         test_mkdir $DIR/$tdir
13019         flock_is_enabled || skip_env "mount w/o flock enabled"
13020         #define OBD_FAIL_LDLM_CP_CB_WAIT  0x315
13021         $LCTL set_param fail_loc=0x80000315
13022         flocks_test 2 $DIR/$tdir
13023 }
13024 run_test 105d "flock race (should not freeze) ========"
13025
13026 test_105e() { # bug 22660 && 22040
13027         flock_is_enabled || skip_env "mount w/o flock enabled"
13028
13029         touch $DIR/$tfile
13030         flocks_test 3 $DIR/$tfile
13031 }
13032 run_test 105e "Two conflicting flocks from same process"
13033
13034 wait_end() {
13035         echo $*
13036         while :; do
13037                 [ -f $TMP/${tfile}_sTOP ] && return
13038                 sleep 1
13039         done
13040 }
13041
13042 test_105f() {
13043         flock_is_enabled || skip_env "mount w/o flock enabled"
13044
13045         local pmax=$(ulimit -u)
13046         local i=0
13047         touch $DIR/$tfile
13048         [ $pmax -gt 20 ] && pmax=20
13049         for((i=0; i <= $pmax; i++)) {
13050                 wait_end "R4000, 5000" | flocks_test 6 $DIR/$tfile &
13051         }
13052         for((i=0; i <= 10; i++)) {
13053                 local locks=$(do_facet $SINGLEMDS $LCTL get_param -n \
13054                         ldlm.namespaces.mdt-${FSNAME}-MDT0000*.lock_count)
13055                 [ $locks -ge $pmax ] && break
13056                 [ $i -eq 10 ] && error "The locks cannot be added after 10 secs"
13057                 sleep 1
13058         }
13059         touch $TMP/${tfile}_sTOP
13060         wait
13061         rm -r $DIR/$tfile $TMP/${tfile}_sTOP
13062 }
13063 run_test 105f "Enqueue same range flocks"
13064
13065 test_106() { #bug 10921
13066         test_mkdir $DIR/$tdir
13067         $DIR/$tdir && error "exec $DIR/$tdir succeeded"
13068         chmod 777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
13069 }
13070 run_test 106 "attempt exec of dir followed by chown of that dir"
13071
13072 test_107() {
13073         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13074
13075         CDIR=`pwd`
13076         local file=core
13077
13078         cd $DIR
13079         rm -f $file
13080
13081         local save_pattern=$(sysctl -n kernel.core_pattern)
13082         local save_uses_pid=$(sysctl -n kernel.core_uses_pid)
13083         sysctl -w kernel.core_pattern=$file
13084         sysctl -w kernel.core_uses_pid=0
13085
13086         ulimit -c unlimited
13087         sleep 60 &
13088         SLEEPPID=$!
13089
13090         sleep 1
13091
13092         kill -s 11 $SLEEPPID
13093         wait $SLEEPPID
13094         if [ -e $file ]; then
13095                 size=`stat -c%s $file`
13096                 [ $size -eq 0 ] && error "Fail to create core file $file"
13097         else
13098                 error "Fail to create core file $file"
13099         fi
13100         rm -f $file
13101         sysctl -w kernel.core_pattern=$save_pattern
13102         sysctl -w kernel.core_uses_pid=$save_uses_pid
13103         cd $CDIR
13104 }
13105 run_test 107 "Coredump on SIG"
13106
13107 test_110() {
13108         test_mkdir $DIR/$tdir
13109         test_mkdir $DIR/$tdir/$(str_repeat 'a' 255)
13110         $LFS mkdir -c $MDSCOUNT $DIR/$tdir/$(str_repeat 'b' 256) &&
13111                 error "mkdir with 256 char should fail, but did not"
13112         touch $DIR/$tdir/$(str_repeat 'x' 255) ||
13113                 error "create with 255 char failed"
13114         touch $DIR/$tdir/$(str_repeat 'y' 256) &&
13115                 error "create with 256 char should fail, but did not"
13116
13117         ls -l $DIR/$tdir
13118         rm -rf $DIR/$tdir
13119 }
13120 run_test 110 "filename length checking"
13121
13122 test_116a() { # was previously test_116()
13123         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13124         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13125         remote_mds_nodsh && skip "remote MDS with nodsh"
13126
13127         echo -n "Free space priority "
13128         do_facet $SINGLEMDS lctl get_param -n lo[vd].*-mdtlov.qos_prio_free |
13129                 head -n1
13130         declare -a AVAIL
13131         free_min_max
13132
13133         [ $MINV -eq 0 ] && skip "no free space in OST$MINI, skip"
13134         [ $MINV -gt 10000000 ] && skip "too much free space in OST$MINI, skip"
13135         stack_trap simple_cleanup_common
13136
13137         # Check if we need to generate uneven OSTs
13138         test_mkdir -p $DIR/$tdir/OST${MINI}
13139         local FILL=$((MINV / 4))
13140         local DIFF=$((MAXV - MINV))
13141         local DIFF2=$((DIFF * 100 / MINV))
13142
13143         local threshold=$(do_facet $SINGLEMDS \
13144                 lctl get_param -n *.*MDT0000-mdtlov.qos_threshold_rr | head -n1)
13145         threshold=${threshold%%%}
13146         echo -n "Check for uneven OSTs: "
13147         echo -n "diff=${DIFF}KB (${DIFF2}%) must be > ${threshold}% ..."
13148
13149         if [[ $DIFF2 -gt $threshold ]]; then
13150                 echo "ok"
13151                 echo "Don't need to fill OST$MINI"
13152         else
13153                 # generate uneven OSTs. Write 2% over the QOS threshold value
13154                 echo "no"
13155                 DIFF=$((threshold - DIFF2 + 2))
13156                 DIFF2=$((MINV * DIFF / 100))
13157                 echo "Fill $DIFF% remaining space in OST$MINI with ${DIFF2}KB"
13158                 $LFS setstripe -i $MINI -c 1 $DIR/$tdir/OST${MINI} ||
13159                         error "setstripe failed"
13160                 DIFF=$((DIFF2 / 2048))
13161                 i=0
13162                 while [ $i -lt $DIFF ]; do
13163                         i=$((i + 1))
13164                         dd if=/dev/zero of=$DIR/$tdir/OST${MINI}/$tfile-$i \
13165                                 bs=2M count=1 2>/dev/null
13166                         echo -n .
13167                 done
13168                 echo .
13169                 sync
13170                 sleep_maxage
13171                 free_min_max
13172         fi
13173
13174         DIFF=$((MAXV - MINV))
13175         DIFF2=$((DIFF * 100 / MINV))
13176         echo -n "diff=$DIFF=$DIFF2% must be > $threshold% for QOS mode..."
13177         if [ $DIFF2 -gt $threshold ]; then
13178                 echo "ok"
13179         else
13180                 skip "QOS imbalance criteria not met"
13181         fi
13182
13183         MINI1=$MINI
13184         MINV1=$MINV
13185         MAXI1=$MAXI
13186         MAXV1=$MAXV
13187
13188         # now fill using QOS
13189         $LFS setstripe -c 1 $DIR/$tdir
13190         FILL=$((FILL / 200))
13191         if [ $FILL -gt 600 ]; then
13192                 FILL=600
13193         fi
13194         echo "writing $FILL files to QOS-assigned OSTs"
13195         i=0
13196         while [ $i -lt $FILL ]; do
13197                 i=$((i + 1))
13198                 dd if=/dev/zero of=$DIR/$tdir/$tfile-$i bs=200k \
13199                         count=1 2>/dev/null
13200                 echo -n .
13201         done
13202         echo "wrote $i 200k files"
13203         sync
13204         sleep_maxage
13205
13206         echo "Note: free space may not be updated, so measurements might be off"
13207         free_min_max
13208         DIFF2=$((MAXV - MINV))
13209         echo "free space delta: orig $DIFF final $DIFF2"
13210         [ $DIFF2 -gt $DIFF ] && echo "delta got worse!"
13211         DIFF=$((MINV1 - ${AVAIL[$MINI1]}))
13212         echo "Wrote ${DIFF}KB to smaller OST $MINI1"
13213         DIFF2=$((MAXV1 - ${AVAIL[$MAXI1]}))
13214         echo "Wrote ${DIFF2}KB to larger OST $MAXI1"
13215         if [[ $DIFF -gt 0 ]]; then
13216                 FILL=$((DIFF2 * 100 / DIFF - 100))
13217                 echo "Wrote ${FILL}% more data to larger OST $MAXI1"
13218         fi
13219
13220         # Figure out which files were written where
13221         UUID=$(lctl get_param -n lov.${FSNAME}-clilov-*.target_obd |
13222                awk '/'$MINI1': / {print $2; exit}')
13223         echo $UUID
13224         MINC=$($LFS getstripe --ost $UUID $DIR/$tdir | grep $DIR | wc -l)
13225         echo "$MINC files created on smaller OST $MINI1"
13226         UUID=$(lctl get_param -n lov.${FSNAME}-clilov-*.target_obd |
13227                awk '/'$MAXI1': / {print $2; exit}')
13228         echo $UUID
13229         MAXC=$($LFS getstripe --ost $UUID $DIR/$tdir | grep $DIR | wc -l)
13230         echo "$MAXC files created on larger OST $MAXI1"
13231         if [[ $MINC -gt 0 ]]; then
13232                 FILL=$((MAXC * 100 / MINC - 100))
13233                 echo "Wrote ${FILL}% more files to larger OST $MAXI1"
13234         fi
13235         [[ $MAXC -gt $MINC ]] ||
13236                 error_ignore LU-9 "stripe QOS didn't balance free space"
13237 }
13238 run_test 116a "stripe QOS: free space balance ==================="
13239
13240 test_116b() { # LU-2093
13241         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13242         remote_mds_nodsh && skip "remote MDS with nodsh"
13243
13244 #define OBD_FAIL_MDS_OSC_CREATE_FAIL     0x147
13245         local old_rr=$(do_facet $SINGLEMDS lctl get_param -n \
13246                        lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr | head -1)
13247         [ -z "$old_rr" ] && skip "no QOS"
13248         do_facet $SINGLEMDS lctl set_param \
13249                 lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr=0
13250         mkdir -p $DIR/$tdir
13251         do_facet $SINGLEMDS lctl set_param fail_loc=0x147
13252         createmany -o $DIR/$tdir/f- 20 || error "can't create"
13253         do_facet $SINGLEMDS lctl set_param fail_loc=0
13254         rm -rf $DIR/$tdir
13255         do_facet $SINGLEMDS lctl set_param \
13256                 lo[vd].$FSNAME-MDT0000-mdtlov.qos_threshold_rr=$old_rr
13257 }
13258 run_test 116b "QoS shouldn't LBUG if not enough OSTs found on the 2nd pass"
13259
13260 test_117() # bug 10891
13261 {
13262         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13263
13264         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
13265         #define OBD_FAIL_OST_SETATTR_CREDITS 0x21e
13266         lctl set_param fail_loc=0x21e
13267         > $DIR/$tfile || error "truncate failed"
13268         lctl set_param fail_loc=0
13269         echo "Truncate succeeded."
13270         rm -f $DIR/$tfile
13271 }
13272 run_test 117 "verify osd extend =========="
13273
13274 NO_SLOW_RESENDCOUNT=4
13275 export OLD_RESENDCOUNT=""
13276 set_resend_count () {
13277         local PROC_RESENDCOUNT="osc.${FSNAME}-OST*-osc-*.resend_count"
13278         OLD_RESENDCOUNT=$(lctl get_param -n $PROC_RESENDCOUNT | head -n1)
13279         lctl set_param -n $PROC_RESENDCOUNT $1
13280         echo resend_count is set to $(lctl get_param -n $PROC_RESENDCOUNT)
13281 }
13282
13283 # for reduce test_118* time (b=14842)
13284 [ "$SLOW" = "no" ] && set_resend_count $NO_SLOW_RESENDCOUNT
13285
13286 # Reset async IO behavior after error case
13287 reset_async() {
13288         FILE=$DIR/reset_async
13289
13290         # Ensure all OSCs are cleared
13291         $LFS setstripe -c -1 $FILE
13292         dd if=/dev/zero of=$FILE bs=64k count=$OSTCOUNT
13293         sync
13294         rm $FILE
13295 }
13296
13297 test_118a() #bug 11710
13298 {
13299         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13300
13301         reset_async
13302
13303         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13304         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13305         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
13306
13307         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13308                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13309                 return 1;
13310         fi
13311         rm -f $DIR/$tfile
13312 }
13313 run_test 118a "verify O_SYNC works =========="
13314
13315 test_118b()
13316 {
13317         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13318         remote_ost_nodsh && skip "remote OST with nodsh"
13319
13320         reset_async
13321
13322         #define OBD_FAIL_SRV_ENOENT 0x217
13323         set_nodes_failloc "$(osts_nodes)" 0x217
13324         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13325         RC=$?
13326         set_nodes_failloc "$(osts_nodes)" 0
13327         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13328         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13329                     grep -c writeback)
13330
13331         if [[ $RC -eq 0 ]]; then
13332                 error "Must return error due to dropped pages, rc=$RC"
13333                 return 1;
13334         fi
13335
13336         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13337                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13338                 return 1;
13339         fi
13340
13341         echo "Dirty pages not leaked on ENOENT"
13342
13343         # Due to the above error the OSC will issue all RPCs syncronously
13344         # until a subsequent RPC completes successfully without error.
13345         $MULTIOP $DIR/$tfile Ow4096yc
13346         rm -f $DIR/$tfile
13347
13348         return 0
13349 }
13350 run_test 118b "Reclaim dirty pages on fatal error =========="
13351
13352 test_118c()
13353 {
13354         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13355
13356         # for 118c, restore the original resend count, LU-1940
13357         [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] &&
13358                                 set_resend_count $OLD_RESENDCOUNT
13359         remote_ost_nodsh && skip "remote OST with nodsh"
13360
13361         reset_async
13362
13363         #define OBD_FAIL_OST_EROFS               0x216
13364         set_nodes_failloc "$(osts_nodes)" 0x216
13365
13366         # multiop should block due to fsync until pages are written
13367         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
13368         MULTIPID=$!
13369         sleep 1
13370
13371         if [[ `ps h -o comm -p $MULTIPID` != "multiop" ]]; then
13372                 error "Multiop failed to block on fsync, pid=$MULTIPID"
13373         fi
13374
13375         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13376                     grep -c writeback)
13377         if [[ $WRITEBACK -eq 0 ]]; then
13378                 error "No page in writeback, writeback=$WRITEBACK"
13379         fi
13380
13381         set_nodes_failloc "$(osts_nodes)" 0
13382         wait $MULTIPID
13383         RC=$?
13384         if [[ $RC -ne 0 ]]; then
13385                 error "Multiop fsync failed, rc=$RC"
13386         fi
13387
13388         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13389         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13390                     grep -c writeback)
13391         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13392                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13393         fi
13394
13395         rm -f $DIR/$tfile
13396         echo "Dirty pages flushed via fsync on EROFS"
13397         return 0
13398 }
13399 run_test 118c "Fsync blocks on EROFS until dirty pages are flushed =========="
13400
13401 # continue to use small resend count to reduce test_118* time (b=14842)
13402 [ "$SLOW" = "no" ] && set_resend_count $NO_SLOW_RESENDCOUNT
13403
13404 test_118d()
13405 {
13406         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13407         remote_ost_nodsh && skip "remote OST with nodsh"
13408
13409         reset_async
13410
13411         #define OBD_FAIL_OST_BRW_PAUSE_BULK
13412         set_nodes_failloc "$(osts_nodes)" 0x214
13413         # multiop should block due to fsync until pages are written
13414         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
13415         MULTIPID=$!
13416         sleep 1
13417
13418         if [[ `ps h -o comm -p $MULTIPID` != "multiop" ]]; then
13419                 error "Multiop failed to block on fsync, pid=$MULTIPID"
13420         fi
13421
13422         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13423                     grep -c writeback)
13424         if [[ $WRITEBACK -eq 0 ]]; then
13425                 error "No page in writeback, writeback=$WRITEBACK"
13426         fi
13427
13428         wait $MULTIPID || error "Multiop fsync failed, rc=$?"
13429         set_nodes_failloc "$(osts_nodes)" 0
13430
13431         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13432         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13433                     grep -c writeback)
13434         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13435                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13436         fi
13437
13438         rm -f $DIR/$tfile
13439         echo "Dirty pages gaurenteed flushed via fsync"
13440         return 0
13441 }
13442 run_test 118d "Fsync validation inject a delay of the bulk =========="
13443
13444 test_118f() {
13445         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13446
13447         reset_async
13448
13449         #define OBD_FAIL_OSC_BRW_PREP_REQ2        0x40a
13450         lctl set_param fail_loc=0x8000040a
13451
13452         # Should simulate EINVAL error which is fatal
13453         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13454         RC=$?
13455         if [[ $RC -eq 0 ]]; then
13456                 error "Must return error due to dropped pages, rc=$RC"
13457         fi
13458
13459         lctl set_param fail_loc=0x0
13460
13461         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
13462         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13463         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13464                     grep -c writeback)
13465         if [[ $LOCKED -ne 0 ]]; then
13466                 error "Locked pages remain in cache, locked=$LOCKED"
13467         fi
13468
13469         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13470                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13471         fi
13472
13473         rm -f $DIR/$tfile
13474         echo "No pages locked after fsync"
13475
13476         reset_async
13477         return 0
13478 }
13479 run_test 118f "Simulate unrecoverable OSC side error =========="
13480
13481 test_118g() {
13482         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13483
13484         reset_async
13485
13486         #define OBD_FAIL_OSC_BRW_PREP_REQ        0x406
13487         lctl set_param fail_loc=0x406
13488
13489         # simulate local -ENOMEM
13490         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13491         RC=$?
13492
13493         lctl set_param fail_loc=0
13494         if [[ $RC -eq 0 ]]; then
13495                 error "Must return error due to dropped pages, rc=$RC"
13496         fi
13497
13498         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
13499         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13500         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13501                         grep -c writeback)
13502         if [[ $LOCKED -ne 0 ]]; then
13503                 error "Locked pages remain in cache, locked=$LOCKED"
13504         fi
13505
13506         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13507                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13508         fi
13509
13510         rm -f $DIR/$tfile
13511         echo "No pages locked after fsync"
13512
13513         reset_async
13514         return 0
13515 }
13516 run_test 118g "Don't stay in wait if we got local -ENOMEM  =========="
13517
13518 test_118h() {
13519         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13520         remote_ost_nodsh && skip "remote OST with nodsh"
13521
13522         reset_async
13523
13524         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
13525         set_nodes_failloc "$(osts_nodes)" 0x20e
13526         # Should simulate ENOMEM error which is recoverable and should be handled by timeout
13527         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13528         RC=$?
13529
13530         set_nodes_failloc "$(osts_nodes)" 0
13531         if [[ $RC -eq 0 ]]; then
13532                 error "Must return error due to dropped pages, rc=$RC"
13533         fi
13534
13535         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
13536         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13537         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache |
13538                     grep -c writeback)
13539         if [[ $LOCKED -ne 0 ]]; then
13540                 error "Locked pages remain in cache, locked=$LOCKED"
13541         fi
13542
13543         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13544                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13545         fi
13546
13547         rm -f $DIR/$tfile
13548         echo "No pages locked after fsync"
13549
13550         return 0
13551 }
13552 run_test 118h "Verify timeout in handling recoverables errors  =========="
13553
13554 [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] && set_resend_count $OLD_RESENDCOUNT
13555
13556 test_118i() {
13557         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13558         remote_ost_nodsh && skip "remote OST with nodsh"
13559
13560         reset_async
13561
13562         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
13563         set_nodes_failloc "$(osts_nodes)" 0x20e
13564
13565         # Should simulate ENOMEM error which is recoverable and should be handled by timeout
13566         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c &
13567         PID=$!
13568         sleep 5
13569         set_nodes_failloc "$(osts_nodes)" 0
13570
13571         wait $PID
13572         RC=$?
13573         if [[ $RC -ne 0 ]]; then
13574                 error "got error, but should be not, rc=$RC"
13575         fi
13576
13577         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
13578         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13579         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
13580         if [[ $LOCKED -ne 0 ]]; then
13581                 error "Locked pages remain in cache, locked=$LOCKED"
13582         fi
13583
13584         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13585                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13586         fi
13587
13588         rm -f $DIR/$tfile
13589         echo "No pages locked after fsync"
13590
13591         return 0
13592 }
13593 run_test 118i "Fix error before timeout in recoverable error  =========="
13594
13595 [ "$SLOW" = "no" ] && set_resend_count 4
13596
13597 test_118j() {
13598         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13599         remote_ost_nodsh && skip "remote OST with nodsh"
13600
13601         reset_async
13602
13603         #define OBD_FAIL_OST_BRW_WRITE_BULK2     0x220
13604         set_nodes_failloc "$(osts_nodes)" 0x220
13605
13606         # return -EIO from OST
13607         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:O_SYNC:w4096c
13608         RC=$?
13609         set_nodes_failloc "$(osts_nodes)" 0x0
13610         if [[ $RC -eq 0 ]]; then
13611                 error "Must return error due to dropped pages, rc=$RC"
13612         fi
13613
13614         LOCKED=$(lctl get_param -n llite.*.dump_page_cache | grep -c locked)
13615         DIRTY=$(lctl get_param -n llite.*.dump_page_cache | grep -c dirty)
13616         WRITEBACK=$(lctl get_param -n llite.*.dump_page_cache | grep -c writeback)
13617         if [[ $LOCKED -ne 0 ]]; then
13618                 error "Locked pages remain in cache, locked=$LOCKED"
13619         fi
13620
13621         # in recoverable error on OST we want resend and stay until it finished
13622         if [[ $DIRTY -ne 0 || $WRITEBACK -ne 0 ]]; then
13623                 error "Dirty pages not flushed to disk, dirty=$DIRTY, writeback=$WRITEBACK"
13624         fi
13625
13626         rm -f $DIR/$tfile
13627         echo "No pages locked after fsync"
13628
13629         return 0
13630 }
13631 run_test 118j "Simulate unrecoverable OST side error =========="
13632
13633 test_118k()
13634 {
13635         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13636         remote_ost_nodsh && skip "remote OSTs with nodsh"
13637
13638         #define OBD_FAIL_OST_BRW_WRITE_BULK      0x20e
13639         set_nodes_failloc "$(osts_nodes)" 0x20e
13640         test_mkdir $DIR/$tdir
13641
13642         for ((i=0;i<10;i++)); do
13643                 (dd if=/dev/zero of=$DIR/$tdir/$tfile-$i bs=1M count=10 || \
13644                         error "dd to $DIR/$tdir/$tfile-$i failed" )&
13645                 SLEEPPID=$!
13646                 sleep 0.500s
13647                 kill $SLEEPPID
13648                 wait $SLEEPPID
13649         done
13650
13651         set_nodes_failloc "$(osts_nodes)" 0
13652         rm -rf $DIR/$tdir
13653 }
13654 run_test 118k "bio alloc -ENOMEM and IO TERM handling ========="
13655
13656 test_118l() # LU-646
13657 {
13658         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13659
13660         test_mkdir $DIR/$tdir
13661         $MULTIOP $DIR/$tdir Dy || error "fsync dir failed"
13662         rm -rf $DIR/$tdir
13663 }
13664 run_test 118l "fsync dir"
13665
13666 test_118m() # LU-3066
13667 {
13668         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13669
13670         test_mkdir $DIR/$tdir
13671         $MULTIOP $DIR/$tdir DY || error "fdatasync dir failed"
13672         rm -rf $DIR/$tdir
13673 }
13674 run_test 118m "fdatasync dir ========="
13675
13676 [ "$SLOW" = "no" ] && [ -n "$OLD_RESENDCOUNT" ] && set_resend_count $OLD_RESENDCOUNT
13677
13678 test_118n()
13679 {
13680         local begin
13681         local end
13682
13683         [ $PARALLEL == "yes" ] && skip "skip parallel run"
13684         remote_ost_nodsh && skip "remote OSTs with nodsh"
13685
13686         # Sleep to avoid a cached response.
13687         #define OBD_STATFS_CACHE_SECONDS 1
13688         sleep 2
13689
13690         # Inject a 10 second delay in the OST_STATFS handler.
13691         #define OBD_FAIL_OST_STATFS_DELAY 0x242
13692         set_nodes_failloc "$(osts_nodes)" 0x242
13693
13694         begin=$SECONDS
13695         stat --file-system $MOUNT > /dev/null
13696         end=$SECONDS
13697
13698         set_nodes_failloc "$(osts_nodes)" 0
13699
13700         if ((end - begin > 20)); then
13701             error "statfs took $((end - begin)) seconds, expected 10"
13702         fi
13703 }
13704 run_test 118n "statfs() sends OST_STATFS requests in parallel"
13705
13706 test_119a() # bug 11737
13707 {
13708         BSIZE=$((512 * 1024))
13709         directio write $DIR/$tfile 0 1 $BSIZE
13710         # We ask to read two blocks, which is more than a file size.
13711         # directio will indicate an error when requested and actual
13712         # sizes aren't equeal (a normal situation in this case) and
13713         # print actual read amount.
13714         NOB=`directio read $DIR/$tfile 0 2 $BSIZE | awk '/error/ {print $6}'`
13715         if [ "$NOB" != "$BSIZE" ]; then
13716                 error "read $NOB bytes instead of $BSIZE"
13717         fi
13718         rm -f $DIR/$tfile
13719 }
13720 run_test 119a "Short directIO read must return actual read amount"
13721
13722 test_119b() # bug 11737
13723 {
13724         [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
13725
13726         $LFS setstripe -c 2 $DIR/$tfile || error "setstripe failed"
13727         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=1 || error "dd failed"
13728         sync
13729         $MULTIOP $DIR/$tfile oO_RDONLY:O_DIRECT:r$((2048 * 1024)) ||
13730                 error "direct read failed"
13731         rm -f $DIR/$tfile
13732 }
13733 run_test 119b "Sparse directIO read must return actual read amount"
13734
13735 test_119c() # bug 13099
13736 {
13737         BSIZE=1048576
13738         directio write $DIR/$tfile 3 1 $BSIZE || error "direct write failed"
13739         directio readhole $DIR/$tfile 0 2 $BSIZE || error "reading hole failed"
13740         rm -f $DIR/$tfile
13741 }
13742 run_test 119c "Testing for direct read hitting hole"
13743
13744 # Note: test 119d was removed, skipping 119d for new tests to avoid polluting
13745 # Maloo test history
13746
13747 test_119e()
13748 {
13749         (( $MDS1_VERSION >= $(version_code 2.15.58) )) ||
13750                 skip "Need server version at least 2.15.58"
13751         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
13752
13753         local stripe_size=$((1024 * 1024)) #1 MiB
13754         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
13755         local file_size=$((25 * stripe_size))
13756         local bsizes
13757
13758         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
13759         stack_trap "rm -f $DIR/$tfile*"
13760
13761         # Just a bit bigger than the largest size in the test set below
13762         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
13763                 error "buffered i/o to create file failed"
13764
13765         # trivial test of unaligned DIO
13766         dd if=$DIR/$tfile.1 bs=4095 of=$DIR/$tfile.2 count=4 \
13767                 iflag=direct oflag=direct ||
13768                 error "trivial unaligned dio failed"
13769
13770         # Test of disabling unaligned DIO support
13771         $LCTL set_param llite.*.unaligned_dio=0
13772         stack_trap "$LCTL set_param llite.*.unaligned_dio=1"
13773         echo "testing disabling unaligned DIO - 'invalid argument' expected:"
13774         dd if=$DIR/$tfile.1 bs=1024 of=$DIR/$tfile.2 count=4 \
13775                 iflag=direct oflag=direct &&
13776                 error "unaligned dio succeeded when disabled"
13777         $LCTL set_param llite.*.unaligned_dio=1
13778
13779         # Clean up before next part of test
13780         rm -f $DIR/$tfile.2
13781
13782         if zfs_or_rotational; then
13783                 # DIO on ZFS can take up to 2 seconds per IO
13784                 # rotational is better, but still slow.
13785                 # Limit testing on those media to larger sizes
13786                 bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
13787                         $((stripe_size + 1024))"
13788         else
13789                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
13790                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
13791                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
13792                         $((stripe_size - 1)) $stripe_size \
13793                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
13794                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
13795         fi
13796
13797         for bs in $bsizes; do
13798                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
13799                 echo "Read/write with DIO at size $bs"
13800                 # Read and write with DIO from source to dest
13801                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 \
13802                         iflag=direct oflag=direct ||
13803                         error "dio failed"
13804
13805                 ls -la $DIR/$tfile.1 $DIR/$tfile.2
13806                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
13807                         error "size incorrect, file copy read/write bsize: $bs"
13808                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
13809                         error "files differ, bsize $bs"
13810                 rm -f $DIR/$tfile.2
13811         done
13812 }
13813 run_test 119e "Basic tests of dio read and write at various sizes"
13814
13815 test_119f()
13816 {
13817         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
13818
13819         local stripe_size=$((1024 * 1024)) #1 MiB
13820         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
13821         local file_size=$((25 * stripe_size))
13822         local bsizes
13823
13824         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
13825         stack_trap "rm -f $DIR/$tfile*"
13826
13827         # Just a bit bigger than the largest size in the test set below
13828         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
13829                 error "buffered i/o to create file failed"
13830
13831         if zfs_or_rotational; then
13832                 # DIO on ZFS can take up to 2 seconds per IO
13833                 # rotational is better, but still slow.
13834                 # Limit testing on those media to larger sizes
13835                 bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
13836                         $((stripe_size + 1024))"
13837         else
13838                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
13839                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
13840                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
13841                         $((stripe_size - 1)) $stripe_size \
13842                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
13843                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
13844         fi
13845
13846         for bs in $bsizes; do
13847                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
13848                 # Read and write with DIO from source to dest in two
13849                 # threads - should give correct copy of file
13850
13851                 echo "bs: $bs"
13852                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 iflag=direct \
13853                         oflag=direct conv=notrunc &
13854                 pid_dio1=$!
13855                 # Note block size is different here for a more interesting race
13856                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
13857                         iflag=direct oflag=direct conv=notrunc &
13858                 pid_dio2=$!
13859                 wait $pid_dio1
13860                 rc1=$?
13861                 wait $pid_dio2
13862                 rc2=$?
13863                 if (( rc1 != 0 )); then
13864                         error "dio copy 1 w/bsize $bs failed: $rc1"
13865                 fi
13866                 if (( rc2 != 0 )); then
13867                         error "dio copy 2 w/bsize $bs failed: $rc2"
13868                 fi
13869
13870
13871                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
13872                         error "size incorrect, file copy read/write bsize: $bs"
13873                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
13874                         error "files differ, bsize $bs"
13875                 rm -f $DIR/$tfile.2
13876         done
13877 }
13878 run_test 119f "dio vs dio race"
13879
13880 test_119g()
13881 {
13882         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
13883
13884         local stripe_size=$((1024 * 1024)) #1 MiB
13885         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
13886         local file_size=$((25 * stripe_size))
13887         local bsizes
13888
13889         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
13890         stack_trap "rm -f $DIR/$tfile*"
13891
13892         # Just a bit bigger than the largest size in the test set below
13893         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
13894                 error "buffered i/o to create file failed"
13895
13896         if zfs_or_rotational; then
13897                 # DIO on ZFS can take up to 2 seconds per IO
13898                 # rotational is better, but still slow.
13899                 # Limit testing on those media to larger sizes
13900                 bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
13901                         $((stripe_size + 1024))"
13902         else
13903                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
13904                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
13905                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
13906                         $((stripe_size - 1)) $stripe_size \
13907                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
13908                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
13909         fi
13910
13911         for bs in $bsizes; do
13912                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
13913                 echo "bs: $bs"
13914                 dd if=$DIR/$tfile.1 bs=$bs of=$DIR/$tfile.2 iflag=direct \
13915                         oflag=direct conv=notrunc &
13916                 pid_dio1=$!
13917                 # Buffered I/O with similar but not the same block size
13918                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 &
13919                 pid_bio2=$!
13920                 wait $pid_dio1
13921                 rc1=$?
13922                 wait $pid_bio2
13923                 rc2=$?
13924                 if (( rc1 != 0 )); then
13925                         error "dio copy 1 w/bsize $bs failed: $rc1"
13926                 fi
13927                 if (( rc2 != 0 )); then
13928                         error "buffered copy 2 w/bsize $bs failed: $rc2"
13929                 fi
13930
13931                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
13932                         error "size incorrect"
13933                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
13934                         error "files differ, bsize $bs"
13935                 rm -f $DIR/$tfile.2
13936         done
13937 }
13938 run_test 119g "dio vs buffered I/O race"
13939
13940 test_119h()
13941 {
13942         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
13943
13944         local stripe_size=$((1024 * 1024)) #1 MiB
13945         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
13946         local file_size=$((25 * stripe_size))
13947         local bsizes
13948
13949         stack_trap "rm -f $DIR/$tfile.*"
13950
13951         if zfs_or_rotational; then
13952                 # DIO on ZFS can take up to 2 seconds per IO
13953                 # rotational is better, but still slow.
13954                 # Limit testing on those media to larger sizes
13955                 bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
13956                         $((stripe_size + 1024))"
13957         else
13958                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
13959                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
13960                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
13961                         $((stripe_size - 1)) $stripe_size \
13962                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
13963                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
13964         fi
13965
13966         for bs in $bsizes; do
13967                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
13968                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
13969                 echo "unaligned writes of blocksize: $bs"
13970                 # Write a file with unaligned DIO and regular DIO, and compare
13971                 # them
13972                 # with 'u', multiop randomly unaligns the io from the buffer
13973                 $MULTIOP $DIR/$tfile.1 \
13974                 oO_CREAT:O_RDWR:O_DIRECT:wu${bs}wu${bs}wu${bs}wu${bs}wu${bs} ||
13975                         error "multiop memory unaligned write failed, $bs"
13976                 $MULTIOP $DIR/$tfile.2 \
13977                 oO_CREAT:O_RDWR:O_DIRECT:w${bs}w${bs}w${bs}w${bs}w${bs} ||
13978                         error "multiop memory aligned write failed, $bs"
13979
13980                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
13981                         error "files differ, bsize $bs"
13982                 rm -f $DIR/$tfile.*
13983         done
13984
13985         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
13986         dd if=/dev/zero bs=$((stripe_size * 5)) of=$DIR/$tfile.1 count=5 ||
13987                 error "dd to create source file for read failed"
13988
13989         # Just a few quick tests to make sure unaligned DIO reads don't crash
13990         for bs in $bsizes; do
13991
13992                 echo "unaligned reads of blocksize: $bs"
13993                 # with 'u', multiop randomly unaligns the io from the buffer
13994                 $MULTIOP $DIR/$tfile.1 \
13995                 oO_CREAT:O_RDWR:O_DIRECT:ru${bs}ru${bs}ru${bs}ru${bs}ru${bs} ||
13996                         error "multiop memory unaligned read failed, $bs"
13997
13998         done
13999         rm -f $DIR/$tfile*
14000 }
14001 run_test 119h "basic tests of memory unaligned dio"
14002
14003 # aiocp with the '-a' option makes testing memory unaligned aio trivial
14004 test_119i()
14005 {
14006         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
14007         which aiocp || skip_env "no aiocp installed"
14008
14009         local stripe_size=$((1024 * 1024)) #1 MiB
14010         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
14011         local file_size=$((25 * stripe_size))
14012         local bsizes
14013
14014         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
14015         stack_trap "rm -f $DIR/$tfile.*"
14016
14017         # Just a bit bigger than the largest size in the test set below
14018         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
14019                 error "buffered i/o to create file failed"
14020
14021         if zfs_or_rotational; then
14022                 # DIO on ZFS can take up to 2 seconds per IO
14023                 # rotational is better, but still slow.
14024                 # Limit testing on those media to larger sizes
14025                 bsizes="$((stripe_size - PAGE_SIZE)) $stripe_size \
14026                         $((stripe_size + 1024))"
14027         else
14028                 bsizes="$((PAGE_SIZE / 4)) $((PAGE_SIZE - 1024)) \
14029                         $((PAGE_SIZE - 1)) $PAGE_SIZE $((PAGE_SIZE + 1024)) \
14030                         $((PAGE_SIZE * 3/2)) $((PAGE_SIZE * 4)) \
14031                         $((stripe_size - 1)) $stripe_size \
14032                         $((stripe_size + 1)) $((stripe_size * 3/2)) \
14033                         $((stripe_size * 4)) $((stripe_size * 4 + 1))"
14034         fi
14035
14036         # Do page aligned and NOT page aligned AIO
14037         for align in 8 512 $((PAGE_SIZE)); do
14038         # Deliberately includes a few aligned sizes
14039         for bs in $bsizes; do
14040                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
14041
14042                 echo "bs: $bs, align: $align, file_size $file_size"
14043                 aiocp -a $align -b $bs -s $file_size -f O_DIRECT \
14044                         $DIR/$tfile.1 $DIR/$tfile.2 ||
14045                         error "unaligned aio failed, bs: $bs, align: $align"
14046
14047                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
14048                         error "size incorrect"
14049                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
14050                         error "files differ"
14051                 rm -f $DIR/$tfile.2
14052         done
14053         done
14054 }
14055 run_test 119i "test unaligned aio at varying sizes"
14056
14057 test_120a() {
14058         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14059         remote_mds_nodsh && skip "remote MDS with nodsh"
14060         test_mkdir -i0 -c1 $DIR/$tdir
14061         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14062                 skip_env "no early lock cancel on server"
14063
14064         lru_resize_disable mdc
14065         lru_resize_disable osc
14066         cancel_lru_locks mdc
14067         # asynchronous object destroy at MDT could cause bl ast to client
14068         cancel_lru_locks osc
14069
14070         stat $DIR/$tdir > /dev/null
14071         can1=$(do_facet mds1 \
14072                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14073                awk '/ldlm_cancel/ {print $2}')
14074         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14075                awk '/ldlm_bl_callback/ {print $2}')
14076         test_mkdir -i0 -c1 $DIR/$tdir/d1
14077         can2=$(do_facet mds1 \
14078                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14079                awk '/ldlm_cancel/ {print $2}')
14080         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14081                awk '/ldlm_bl_callback/ {print $2}')
14082         [ $can1 -eq $can2 ] || error $((can2-can1)) "cancel RPC occured."
14083         [ $blk1 -eq $blk2 ] || error $((blk2-blk1)) "blocking RPC occured."
14084         lru_resize_enable mdc
14085         lru_resize_enable osc
14086 }
14087 run_test 120a "Early Lock Cancel: mkdir test"
14088
14089 test_120b() {
14090         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14091         remote_mds_nodsh && skip "remote MDS with nodsh"
14092         test_mkdir $DIR/$tdir
14093         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14094                 skip_env "no early lock cancel on server"
14095
14096         lru_resize_disable mdc
14097         lru_resize_disable osc
14098         cancel_lru_locks mdc
14099         stat $DIR/$tdir > /dev/null
14100         can1=$(do_facet $SINGLEMDS \
14101                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14102                awk '/ldlm_cancel/ {print $2}')
14103         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14104                awk '/ldlm_bl_callback/ {print $2}')
14105         touch $DIR/$tdir/f1
14106         can2=$(do_facet $SINGLEMDS \
14107                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14108                awk '/ldlm_cancel/ {print $2}')
14109         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14110                awk '/ldlm_bl_callback/ {print $2}')
14111         [ $can1 -eq $can2 ] || error $((can2-can1)) "cancel RPC occured."
14112         [ $blk1 -eq $blk2 ] || error $((blk2-blk1)) "blocking RPC occured."
14113         lru_resize_enable mdc
14114         lru_resize_enable osc
14115 }
14116 run_test 120b "Early Lock Cancel: create test"
14117
14118 test_120c() {
14119         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14120         remote_mds_nodsh && skip "remote MDS with nodsh"
14121         test_mkdir -i0 -c1 $DIR/$tdir
14122         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14123                 skip "no early lock cancel on server"
14124
14125         lru_resize_disable mdc
14126         lru_resize_disable osc
14127         test_mkdir -i0 -c1 $DIR/$tdir/d1
14128         test_mkdir -i0 -c1 $DIR/$tdir/d2
14129         touch $DIR/$tdir/d1/f1
14130         cancel_lru_locks mdc
14131         stat $DIR/$tdir/d1 $DIR/$tdir/d2 $DIR/$tdir/d1/f1 > /dev/null
14132         can1=$(do_facet mds1 \
14133                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14134                awk '/ldlm_cancel/ {print $2}')
14135         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14136                awk '/ldlm_bl_callback/ {print $2}')
14137         ln $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2
14138         can2=$(do_facet mds1 \
14139                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14140                awk '/ldlm_cancel/ {print $2}')
14141         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14142                awk '/ldlm_bl_callback/ {print $2}')
14143         [ $can1 -eq $can2 ] || error $((can2-can1)) "cancel RPC occured."
14144         [ $blk1 -eq $blk2 ] || error $((blk2-blk1)) "blocking RPC occured."
14145         lru_resize_enable mdc
14146         lru_resize_enable osc
14147 }
14148 run_test 120c "Early Lock Cancel: link test"
14149
14150 test_120d() {
14151         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14152         remote_mds_nodsh && skip "remote MDS with nodsh"
14153         test_mkdir -i0 -c1 $DIR/$tdir
14154         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14155                 skip_env "no early lock cancel on server"
14156
14157         lru_resize_disable mdc
14158         lru_resize_disable osc
14159         touch $DIR/$tdir
14160         cancel_lru_locks mdc
14161         stat $DIR/$tdir > /dev/null
14162         can1=$(do_facet mds1 \
14163                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14164                awk '/ldlm_cancel/ {print $2}')
14165         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14166                awk '/ldlm_bl_callback/ {print $2}')
14167         chmod a+x $DIR/$tdir
14168         can2=$(do_facet mds1 \
14169                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14170                awk '/ldlm_cancel/ {print $2}')
14171         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14172                awk '/ldlm_bl_callback/ {print $2}')
14173         [ $can1 -eq $can2 ] || error $((can2-can1)) "cancel RPC occured."
14174         [ $blk1 -eq $blk2 ] || error $((blk2-blk1)) "blocking RPC occured."
14175         lru_resize_enable mdc
14176         lru_resize_enable osc
14177 }
14178 run_test 120d "Early Lock Cancel: setattr test"
14179
14180 test_120e() {
14181         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14182         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14183                 skip_env "no early lock cancel on server"
14184         remote_mds_nodsh && skip "remote MDS with nodsh"
14185
14186         local dlmtrace_set=false
14187
14188         test_mkdir -i0 -c1 $DIR/$tdir
14189         lru_resize_disable mdc
14190         lru_resize_disable osc
14191         ! $LCTL get_param debug | grep -q dlmtrace &&
14192                 $LCTL set_param debug=+dlmtrace && dlmtrace_set=true
14193         dd if=/dev/zero of=$DIR/$tdir/f1 count=1
14194         cancel_lru_locks mdc
14195         cancel_lru_locks osc
14196         dd if=$DIR/$tdir/f1 of=/dev/null
14197         stat $DIR/$tdir $DIR/$tdir/f1 > /dev/null
14198         # XXX client can not do early lock cancel of OST lock
14199         # during unlink (LU-4206), so cancel osc lock now.
14200         sleep 2
14201         cancel_lru_locks osc
14202         can1=$(do_facet mds1 \
14203                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14204                awk '/ldlm_cancel/ {print $2}')
14205         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14206                awk '/ldlm_bl_callback/ {print $2}')
14207         unlink $DIR/$tdir/f1
14208         sleep 5
14209         can2=$(do_facet mds1 \
14210                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14211                awk '/ldlm_cancel/ {print $2}')
14212         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14213                awk '/ldlm_bl_callback/ {print $2}')
14214         [ $can1 -ne $can2 ] && error "$((can2 - can1)) cancel RPC occured" &&
14215                 $LCTL dk $TMP/cancel.debug.txt
14216         [ $blk1 -ne $blk2 ] && error "$((blk2 - blk1)) blocking RPC occured" &&
14217                 $LCTL dk $TMP/blocking.debug.txt
14218         $dlmtrace_set && $LCTL set_param debug=-dlmtrace
14219         lru_resize_enable mdc
14220         lru_resize_enable osc
14221 }
14222 run_test 120e "Early Lock Cancel: unlink test"
14223
14224 test_120f() {
14225         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14226         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14227                 skip_env "no early lock cancel on server"
14228         remote_mds_nodsh && skip "remote MDS with nodsh"
14229
14230         test_mkdir -i0 -c1 $DIR/$tdir
14231         lru_resize_disable mdc
14232         lru_resize_disable osc
14233         test_mkdir -i0 -c1 $DIR/$tdir/d1
14234         test_mkdir -i0 -c1 $DIR/$tdir/d2
14235         dd if=/dev/zero of=$DIR/$tdir/d1/f1 count=1
14236         dd if=/dev/zero of=$DIR/$tdir/d2/f2 count=1
14237         cancel_lru_locks mdc
14238         cancel_lru_locks osc
14239         dd if=$DIR/$tdir/d1/f1 of=/dev/null
14240         dd if=$DIR/$tdir/d2/f2 of=/dev/null
14241         stat $DIR/$tdir/d1 $DIR/$tdir/d2 $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2 > /dev/null
14242         # XXX client can not do early lock cancel of OST lock
14243         # during rename (LU-4206), so cancel osc lock now.
14244         sleep 2
14245         cancel_lru_locks osc
14246         can1=$(do_facet mds1 \
14247                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14248                awk '/ldlm_cancel/ {print $2}')
14249         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14250                awk '/ldlm_bl_callback/ {print $2}')
14251         mrename $DIR/$tdir/d1/f1 $DIR/$tdir/d2/f2
14252         sleep 5
14253         can2=$(do_facet mds1 \
14254                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14255                awk '/ldlm_cancel/ {print $2}')
14256         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14257                awk '/ldlm_bl_callback/ {print $2}')
14258         [ $can1 -eq $can2 ] || error $((can2-can1)) "cancel RPC occured."
14259         [ $blk1 -eq $blk2 ] || error $((blk2-blk1)) "blocking RPC occured."
14260         lru_resize_enable mdc
14261         lru_resize_enable osc
14262 }
14263 run_test 120f "Early Lock Cancel: rename test"
14264
14265 test_120g() {
14266         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14267         $LCTL get_param -n mdc.*.connect_flags | grep -q early_lock_cancel ||
14268                 skip_env "no early lock cancel on server"
14269         remote_mds_nodsh && skip "remote MDS with nodsh"
14270
14271         lru_resize_disable mdc
14272         lru_resize_disable osc
14273         count=10000
14274         echo create $count files
14275         test_mkdir $DIR/$tdir
14276         cancel_lru_locks mdc
14277         cancel_lru_locks osc
14278         t0=$(date +%s)
14279
14280         can0=$(do_facet $SINGLEMDS \
14281                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14282                awk '/ldlm_cancel/ {print $2}')
14283         blk0=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14284                awk '/ldlm_bl_callback/ {print $2}')
14285         createmany -o $DIR/$tdir/f $count
14286         sync
14287         can1=$(do_facet $SINGLEMDS \
14288                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14289                awk '/ldlm_cancel/ {print $2}')
14290         blk1=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14291                awk '/ldlm_bl_callback/ {print $2}')
14292         t1=$(date +%s)
14293         echo total: $((can1-can0)) cancels, $((blk1-blk0)) blockings
14294         echo rm $count files
14295         rm -r $DIR/$tdir
14296         sync
14297         can2=$(do_facet $SINGLEMDS \
14298                "$LCTL get_param -n ldlm.services.ldlm_canceld.stats" |
14299                awk '/ldlm_cancel/ {print $2}')
14300         blk2=$($LCTL get_param -n ldlm.services.ldlm_cbd.stats |
14301                awk '/ldlm_bl_callback/ {print $2}')
14302         t2=$(date +%s)
14303         echo total: $count removes in $((t2-t1))
14304         echo total: $((can2-can1)) cancels, $((blk2-blk1)) blockings
14305         sleep 2
14306         # wait for commitment of removal
14307         lru_resize_enable mdc
14308         lru_resize_enable osc
14309 }
14310 run_test 120g "Early Lock Cancel: performance test"
14311
14312 test_121() { #bug #10589
14313         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14314
14315         rm -rf $DIR/$tfile
14316         writes=$(LANG=C dd if=/dev/zero of=$DIR/$tfile count=1 2>&1 | awk -F '+' '/out$/ {print $1}')
14317 #define OBD_FAIL_LDLM_CANCEL_RACE        0x310
14318         lctl set_param fail_loc=0x310
14319         cancel_lru_locks osc > /dev/null
14320         reads=$(LANG=C dd if=$DIR/$tfile of=/dev/null 2>&1 | awk -F '+' '/in$/ {print $1}')
14321         lctl set_param fail_loc=0
14322         [[ $reads -eq $writes ]] ||
14323                 error "read $reads blocks, must be $writes blocks"
14324 }
14325 run_test 121 "read cancel race ========="
14326
14327 test_123a_base() { # was test 123, statahead(bug 11401)
14328         local lsx="$1"
14329
14330         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
14331
14332         SLOWOK=0
14333         if ! grep -q "processor.*: 1" /proc/cpuinfo; then
14334                 log "testing UP system. Performance may be lower than expected."
14335                 SLOWOK=1
14336         fi
14337         running_in_vm && SLOWOK=1
14338
14339         $LCTL set_param mdc.*.batch_stats=0
14340
14341         rm -rf $DIR/$tdir
14342         test_mkdir $DIR/$tdir
14343         NUMFREE=$(df -i -P $DIR | tail -n 1 | awk '{ print $4 }')
14344         [[ $NUMFREE -gt 100000 ]] && NUMFREE=100000 || NUMFREE=$((NUMFREE-1000))
14345         MULT=10
14346         for ((i=100, j=0; i<=$NUMFREE; j=$i, i=$((i * MULT)) )); do
14347                 createmany -o $DIR/$tdir/$tfile $j $((i - j))
14348
14349                 max=$(lctl get_param -n llite.*.statahead_max | head -n 1)
14350                 lctl set_param -n llite.*.statahead_max 0
14351                 lctl get_param llite.*.statahead_max
14352                 cancel_lru_locks mdc
14353                 cancel_lru_locks osc
14354                 stime=$(date +%s)
14355                 time $lsx $DIR/$tdir | wc -l
14356                 etime=$(date +%s)
14357                 delta=$((etime - stime))
14358                 log "$lsx $i files without statahead: $delta sec"
14359                 lctl set_param llite.*.statahead_max=$max
14360
14361                 swrong=$(lctl get_param -n llite.*.statahead_stats |
14362                          awk '/statahead.wrong:/ { print $NF }')
14363                 lctl get_param -n llite.*.statahead_max | grep '[0-9]'
14364                 cancel_lru_locks mdc
14365                 cancel_lru_locks osc
14366                 stime=$(date +%s)
14367                 time $lsx $DIR/$tdir | wc -l
14368                 etime=$(date +%s)
14369                 delta_sa=$((etime - stime))
14370                 log "$lsx $i files with statahead: $delta_sa sec"
14371                 lctl get_param -n llite.*.statahead_stats
14372                 ewrong=$(lctl get_param -n llite.*.statahead_stats |
14373                          awk '/statahead.wrong:/ { print $NF }')
14374
14375                 [[ $swrong -lt $ewrong ]] &&
14376                         log "statahead was stopped, maybe too many locks held!"
14377                 [[ $delta -eq 0 || $delta_sa -eq 0 ]] && continue
14378
14379                 if (( $delta_sa*100 > $delta*105 && $delta_sa > $delta+2)); then
14380                         max=$(lctl get_param -n llite.*.statahead_max |
14381                                 head -n 1)
14382                         lctl set_param -n llite.*.statahead_max 0
14383                         lctl get_param llite.*.statahead_max
14384                         cancel_lru_locks mdc
14385                         cancel_lru_locks osc
14386                         stime=$(date +%s)
14387                         time $lsx $DIR/$tdir | wc -l
14388                         etime=$(date +%s)
14389                         delta=$((etime - stime))
14390                         log "$lsx $i files again without statahead: $delta sec"
14391                         lctl set_param llite.*.statahead_max=$max
14392                         if (( $delta_sa*100 > delta*105 && delta_sa > delta+2 )); then
14393                                 if [ $SLOWOK -eq 0 ]; then
14394                                         error "$lsx $i files is slower with statahead!"
14395                                 else
14396                                         log "$lsx $i files is slower with statahead!"
14397                                 fi
14398                                 break
14399                         fi
14400                 fi
14401
14402                 [ $delta -gt 20 ] && break
14403                 [ $delta -gt 8 ] && MULT=$((50 / delta))
14404                 [ "$SLOW" = "no" -a $delta -gt 5 ] && break
14405         done
14406         log "$lsx done"
14407
14408         stime=$(date +%s)
14409         rm -r $DIR/$tdir
14410         sync
14411         etime=$(date +%s)
14412         delta=$((etime - stime))
14413         log "rm -r $DIR/$tdir/: $delta seconds"
14414         log "rm done"
14415         lctl get_param -n llite.*.statahead_stats
14416         $LCTL get_param mdc.*.batch_stats
14417 }
14418
14419 test_123aa() {
14420         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14421
14422         test_123a_base "ls -l"
14423 }
14424 run_test 123aa "verify statahead work"
14425
14426 test_123ab() {
14427         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14428
14429         statx_supported || skip_env "Test must be statx() syscall supported"
14430
14431         test_123a_base "$STATX -l"
14432 }
14433 run_test 123ab "verify statahead work by using statx"
14434
14435 test_123ac() {
14436         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14437
14438         statx_supported || skip_env "Test must be statx() syscall supported"
14439
14440         local rpcs_before
14441         local rpcs_after
14442         local agl_before
14443         local agl_after
14444
14445         cancel_lru_locks $OSC
14446         rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
14447         agl_before=$($LCTL get_param -n llite.*.statahead_stats |
14448                      awk '/agl.total:/ { print $NF }')
14449         test_123a_base "$STATX -c \"%n %i %A %h %u %g %W %X %Z\" -D"
14450         test_123a_base "$STATX --cached=always -D"
14451         agl_after=$($LCTL get_param -n llite.*.statahead_stats |
14452                     awk '/agl.total:/ { print $NF }')
14453         [ $agl_before -eq $agl_after ] ||
14454                 error "Should not trigger AGL thread - $agl_before:$agl_after"
14455         rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
14456         [ $rpcs_after -eq $rpcs_before ] ||
14457                 error "$STATX should not send glimpse RPCs to $OSC"
14458 }
14459 run_test 123ac "verify statahead work by using statx without glimpse RPCs"
14460
14461 test_batch_statahead() {
14462         local max=$1
14463         local batch_max=$2
14464         local num=10000
14465         local batch_rpcs
14466         local unbatch_rpcs
14467         local hit_total
14468
14469         echo -e "\nbatching: statahead_max=$max statahead_batch_max=$batch_max"
14470         $LCTL set_param mdc.*.batch_stats=0
14471         $LCTL set_param llite.*.statahead_max=$max
14472         $LCTL set_param llite.*.statahead_batch_max=$batch_max
14473         # Verify that batched statahead is faster than one without statahead
14474         test_123a_base "ls -l"
14475
14476         stack_trap "rm -rf $DIR/$tdir" EXIT
14477         mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
14478         createmany -o $DIR/$tdir/$tfile $num || error "failed to create files"
14479
14480         # unbatched statahead
14481         $LCTL set_param llite.*.statahead_batch_max=0
14482         $LCTL set_param llite.*.statahead_stats=clear
14483         $LCTL set_param mdc.*.stats=clear
14484         cancel_lru_locks mdc
14485         cancel_lru_locks osc
14486         time ls -l $DIR/$tdir | wc -l
14487         unbatch_rpcs=$(calc_stats mdc.*.stats ldlm_ibits_enqueue)
14488         wait_update_facet client "pgrep ll_sa" "" 35 ||
14489                 error "ll_sa thread is still running"
14490         hit_total=$($LCTL get_param -n llite.*.statahead_stats |
14491                     awk '/hit.total:/ { print $NF }')
14492         # hit ratio should be larger than 75% (7500).
14493         (( $hit_total > 7500 )) ||
14494                 error "unbatched statahead hit count ($hit_total) is too low"
14495
14496         # batched statahead
14497         $LCTL set_param llite.*.statahead_batch_max=$batch_max
14498         $LCTL set_param llite.*.statahead_stats=clear
14499         $LCTL set_param mdc.*.batch_stats=clear
14500         $LCTL set_param mdc.*.stats=clear
14501         cancel_lru_locks mdc
14502         cancel_lru_locks osc
14503         time ls -l $DIR/$tdir | wc -l
14504         batch_rpcs=$(calc_stats mdc.*.stats mds_batch)
14505         # wait for statahead thread to quit and update statahead stats
14506         wait_update_facet client "pgrep ll_sa" "" 35 ||
14507                 error "ll_sa thread is still running"
14508         hit_total=$($LCTL get_param -n llite.*.statahead_stats |
14509                     awk '/hit.total:/ { print $NF }')
14510         # hit ratio should be larger than 75% (7500).
14511         (( $hit_total > 7500 )) ||
14512                 error "batched statahead hit count ($hit_total) is too low"
14513
14514         echo "unbatched RPCs: $unbatch_rpcs, batched RPCs: $batch_rpcs"
14515         (( $unbatch_rpcs > $batch_rpcs )) ||
14516                 error "batched statahead does not reduce RPC count"
14517         $LCTL get_param mdc.*.batch_stats
14518 }
14519
14520 test_123ad() {
14521         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14522
14523         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
14524                 skip "Need server version at least 2.15.53"
14525
14526         local max
14527         local batch_max
14528
14529         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
14530         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
14531
14532         stack_trap "$LCTL set_param llite.*.statahead_max=$max" EXIT
14533         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max" EXIT
14534
14535         test_batch_statahead 32 32
14536         test_batch_statahead 2048 256
14537 }
14538 run_test 123ad "Verify batching statahead works correctly"
14539
14540 test_123b () { # statahead(bug 15027)
14541         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14542
14543         test_mkdir $DIR/$tdir
14544         createmany -o $DIR/$tdir/$tfile-%d 1000
14545
14546         cancel_lru_locks mdc
14547         cancel_lru_locks osc
14548
14549 #define OBD_FAIL_MDC_GETATTR_ENQUEUE     0x803
14550         lctl set_param fail_loc=0x80000803
14551         ls -lR $DIR/$tdir > /dev/null
14552         log "ls done"
14553         lctl set_param fail_loc=0x0
14554         lctl get_param -n llite.*.statahead_stats
14555         rm -r $DIR/$tdir
14556         sync
14557
14558 }
14559 run_test 123b "not panic with network error in statahead enqueue (bug 15027)"
14560
14561 test_123c() {
14562         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
14563
14564         test_mkdir -i 0 -c 1 $DIR/$tdir.0
14565         test_mkdir -i 1 -c 1 $DIR/$tdir.1
14566         touch $DIR/$tdir.1/{1..3}
14567         mv $DIR/$tdir.1/{1..3} $DIR/$tdir.0
14568
14569         remount_client $MOUNT
14570
14571         $MULTIOP $DIR/$tdir.0 Q
14572
14573         # let statahead to complete
14574         ls -l $DIR/$tdir.0 > /dev/null
14575
14576         testid=$(echo $TESTNAME | tr '_' ' ')
14577         dmesg | tac | sed "/$testid/,$ d" | grep "Can not initialize inode" &&
14578                 error "statahead warning" || true
14579 }
14580 run_test 123c "Can not initialize inode warning on DNE statahead"
14581
14582 test_123d() {
14583         local num=100
14584         local swrong
14585         local ewrong
14586
14587         test_mkdir -c -1 $DIR/$tdir || error "test_mkdir $DIR/$tdir failed"
14588         $LFS setdirstripe -D -c $MDSCOUNT $DIR/$tdir ||
14589                 error "setdirstripe $DIR/$tdir failed"
14590         createmany -d $DIR/$tdir/$tfile $num || error "createmany $num failed"
14591         remount_client $MOUNT
14592         $LCTL get_param llite.*.statahead_max
14593         $LCTL set_param llite.*.statahead_stats=0 ||
14594                 error "clear statahead_stats failed"
14595         swrong=$(lctl get_param -n llite.*.statahead_stats |
14596                  awk '/statahead.wrong:/ { print $NF }')
14597         ls -l $DIR/$tdir || error "ls -l $DIR/$tdir failed"
14598         # wait for statahead thread finished to update hit/miss stats.
14599         sleep 1
14600         $LCTL get_param -n llite.*.statahead_stats
14601         ewrong=$(lctl get_param -n llite.*.statahead_stats |
14602                  awk '/statahead.wrong:/ { print $NF }')
14603         (( $swrong == $ewrong )) ||
14604                 log "statahead was stopped, maybe too many locks held!"
14605 }
14606 run_test 123d "Statahead on striped directories works correctly"
14607
14608 test_123e() {
14609         local max
14610         local batch_max
14611         local dir=$DIR/$tdir
14612
14613         mkdir $dir || error "mkdir $dir failed"
14614         $LFS setstripe -C 32 $dir || error "setstripe $dir failed"
14615         stack_trap "rm -rf $dir"
14616
14617         touch $dir/$tfile.{0..1000} || error "touch 1000 files failed"
14618
14619         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
14620         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
14621         stack_trap "$LCTL set_param llite.*.statahead_max=$max" EXIT
14622         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max" EXIT
14623
14624         $LCTL set_param llite.*.statahead_max=2048
14625         $LCTL set_param llite.*.statahead_batch_max=1024
14626
14627         ls -l $dir
14628         $LCTL get_param mdc.*.batch_stats
14629         $LCTL get_param llite.*.statahead_*
14630 }
14631 run_test 123e "statahead with large wide striping"
14632
14633 test_123f() {
14634         local max
14635         local batch_max
14636         local dir=$DIR/$tdir
14637
14638         mkdir $dir || error "mkdir $dir failed"
14639         $LFS setstripe -C 1000 $dir || error "setstripe $dir failed"
14640         stack_trap "rm -rf $dir"
14641
14642         touch $dir/$tfile.{0..200} || error "touch 200 files failed"
14643
14644         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
14645         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
14646
14647         $LCTL set_param llite.*.statahead_max=64
14648         $LCTL set_param llite.*.statahead_batch_max=64
14649
14650         ls -l $dir
14651         lctl get_param mdc.*.batch_stats
14652         lctl get_param llite.*.statahead_*
14653
14654         $LCTL set_param llite.*.statahead_max=$max
14655         $LCTL set_param llite.*.statahead_batch_max=$batch_max
14656 }
14657 run_test 123f "Retry mechanism with large wide striping files"
14658
14659 test_123g() {
14660         local dir=$DIR/$tdir
14661         local num=1000
14662
14663         mkdir $dir || error "failed to mkdir $dir"
14664         createmany -o $dir/$tfile $num || error "failed creatmany files"
14665         cancel_lru_locks mdc
14666         cancel_lru_locks osc
14667
14668         $LCTL set_param llite.*.statahead_stats=clear
14669         $LCTL set_param mdc.*.batch_stats=clear
14670         aheadmany -c stat -s 0 -e $num -b $tfile -d $dir ||
14671                 error "aheadmany $dir with $tfile failed"
14672         wait_update_facet client "pgrep ll_sa" "" 35 ||
14673                 error "ll_sa thread is still running"
14674         $LCTL get_param -n llite.*.statahead_stats
14675         $LCTL get_param -n mdc.*.batch_stats
14676
14677         local count
14678
14679         count=$($LCTL get_param -n llite.*.statahead_stats |
14680                 awk '/hit.total:/ {print $2}')
14681         echo "Hit total: $count"
14682         # Hit ratio should be >= 75%
14683         (( $count > num * 75 / 100 )) ||
14684                 error "hit total $count is be > 75% of $num"
14685 }
14686 run_test 123g "Test for stat-ahead advise"
14687
14688 test_123h_base() {
14689         local dir=$DIR/$tdir
14690         local cmd="touch $dir/$tfile.{$1}"
14691         local fcnt=$2
14692
14693         stack_trap "rm -rf $dir"
14694         mkdir -p $dir || error "failed to mkdir $dir"
14695         eval $cmd
14696
14697         cancel_lru_locks mdc
14698         $LCTL set_param llite.*.statahead_stats=clear
14699         $LCTL set_param mdc.*.batch_stats=0
14700         $LCTL set_param llite.*.statahead_max=1024
14701         $LCTL set_param llite.*.statahead_batch_max=1024
14702         lctl get_param -n llite.*.statahead_stats
14703         du -a $dir > /dev/null
14704         echo "Wait statahead thread (ll_sa_xxx) to exit..."
14705         wait_update_facet client "pgrep ll_sa" "" 35 ||
14706                 error "ll_sa statahead thread does not quit in 35s"
14707         $LCTL get_param -n llite.*.statahead_stats
14708         $LCTL get_param -n mdc.*.batch_stats
14709
14710         local count=$($LCTL get_param -n llite.*.statahead_stats |
14711                         awk '/fname.total:/ {print $2}')
14712
14713         [ $count == 1 ] || error "File name pattern statahead not trigger"
14714         count=$($LCTL get_param -n llite.*.statahead_stats |
14715                 awk '/hit.total:/ {print $2}')
14716         # Hit ratio should be >= 75%
14717         (( $count > fcnt * 75 / 100 )) ||
14718                 error "hit total is too low: $count"
14719         rm -rf $dir || error "rm -rf $dir failed"
14720 }
14721
14722 test_123h() {
14723         local max
14724         local batch_max
14725         local enabled
14726
14727         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
14728         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
14729         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
14730         stack_trap "$LCTL set_param llite.*.statahead_max=$max"
14731         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max"
14732         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
14733
14734         $LCTL set_param llite.*.enable_statahead_fname=1
14735
14736         echo "Scan a directory with number regularized fname"
14737         test_123h_base "0..10000" 10000
14738
14739         echo "Scan a directory with zeroed padding number regularized fname"
14740         test_123h_base "000000..010000" 10000
14741 }
14742 run_test 123h "Verify statahead work with the fname pattern via du"
14743
14744 test_123i_base() {
14745         local fmt=$1
14746         local iocmd=$2
14747         local dir=$DIR/$tdir
14748         local cmd="createmany -m $fmt"
14749
14750         echo "Command:"
14751         echo "- $cmd"
14752         echo "- $iocmd"
14753         stack_trap "unlinkmany $fmt"
14754         mkdir -p $dir || error "failed to mkdir $dir"
14755         eval $cmd
14756
14757         cancel_lru_locks mdc
14758         $LCTL set_param llite.*.statahead_stats=clear
14759         $LCTL set_param mdc.*.batch_stats=0
14760
14761         echo "statahead_stats (Pre):"
14762         lctl get_param -n llite.*.statahead_stats
14763         eval $iocmd || error "$iocmd failed"
14764         echo "statahead_stats (Post):"
14765         $LCTL get_param -n llite.*.statahead_stats
14766         $LCTL get_param -n mdc.*.batch_stats
14767
14768         echo "Wait the statahead thread (ll_sa_xxx) to exit ..."
14769         wait_update_facet client "pgrep ll_sa" "" 35 ||
14770                 error "ll_sa statahead thread does not quit in 35s"
14771         $LCTL get_param -n llite.*.statahead_stats
14772         $LCTL get_param -n mdc.*.batch_stats
14773
14774         local count=$($LCTL get_param -n llite.*.statahead_stats |
14775                         awk '/fname.total:/ {print $2}')
14776
14777         [ $count == 1 ] || error "File name pattern statahead not trigger"
14778         count=$($LCTL get_param -n llite.*.statahead_stats |
14779                 awk '/hit.total:/ {print $2}')
14780         # Hit ratio should be >= 75%
14781         (( $count > 750 )) || error "hit total is too low: $count"
14782 }
14783
14784 test_123i() {
14785         local dir=$DIR/$tdir
14786         local cnt=1000
14787         local max
14788         local batch_max
14789         local enabled
14790         local min
14791
14792         max=$($LCTL get_param -n llite.*.statahead_max | head -n 1)
14793         batch_max=$($LCTL get_param -n llite.*.statahead_batch_max | head -n 1)
14794         min=$($LCTL get_param -n llite.*.statahead_min | head -n 1)
14795         enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1)
14796         stack_trap "$LCTL set_param llite.*.statahead_max=$max"
14797         stack_trap "$LCTL set_param llite.*.statahead_batch_max=$batch_max"
14798         stack_trap "$LCTL set_param llite.*.statahead_min=$min"
14799         stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled"
14800         $LCTL set_param llite.*.statahead_max=1024
14801         $LCTL set_param llite.*.statahead_batch_max=32
14802         $LCTL set_param llite.*.statahead_min=64
14803         $LCTL set_param llite.*.enable_statahead_fname=1
14804
14805         test_123i_base "$dir/$tfile.%06d $cnt" "ls $dir/* > /dev/null"
14806         test_123i_base "$dir/$tfile $cnt" \
14807                 "aheadmany -c stat -N -s 0 -e $cnt -b $tfile -d $dir"
14808 }
14809 run_test 123i "Verify statahead work with the fname indexing pattern"
14810
14811 test_124a() {
14812         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14813         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
14814                 skip_env "no lru resize on server"
14815
14816         local NR=2000
14817
14818         test_mkdir $DIR/$tdir
14819
14820         log "create $NR files at $DIR/$tdir"
14821         createmany -o $DIR/$tdir/f $NR ||
14822                 error "failed to create $NR files in $DIR/$tdir"
14823
14824         cancel_lru_locks mdc
14825         ls -l $DIR/$tdir > /dev/null
14826
14827         local NSDIR=""
14828         local LRU_SIZE=0
14829         for VALUE in $($LCTL get_param ldlm.namespaces.*mdc-*.lru_size); do
14830                 local PARAM=$(echo ${VALUE[0]} | cut -d "=" -f1)
14831                 LRU_SIZE=$($LCTL get_param -n $PARAM)
14832                 if [[ $LRU_SIZE -gt $(default_lru_size) ]]; then
14833                         NSDIR=$(echo $PARAM | cut -d "." -f1-3)
14834                         log "NSDIR=$NSDIR"
14835                         log "NS=$(basename $NSDIR)"
14836                         break
14837                 fi
14838         done
14839
14840         if [[ -z "$NSDIR" || $LRU_SIZE -lt $(default_lru_size) ]]; then
14841                 skip "Not enough cached locks created!"
14842         fi
14843         log "LRU=$LRU_SIZE"
14844
14845         local SLEEP=30
14846
14847         # We know that lru resize allows one client to hold $LIMIT locks
14848         # for 10h. After that locks begin to be killed by client.
14849         local MAX_HRS=10
14850         local LIMIT=$($LCTL get_param -n $NSDIR.pool.limit)
14851         log "LIMIT=$LIMIT"
14852         if [ $LIMIT -lt $LRU_SIZE ]; then
14853                 skip "Limit is too small $LIMIT"
14854         fi
14855
14856         # Make LVF so higher that sleeping for $SLEEP is enough to _start_
14857         # killing locks. Some time was spent for creating locks. This means
14858         # that up to the moment of sleep finish we must have killed some of
14859         # them (10-100 locks). This depends on how fast ther were created.
14860         # Many of them were touched in almost the same moment and thus will
14861         # be killed in groups.
14862         local LVF=$(($MAX_HRS * 60 * 60 / $SLEEP * $LIMIT / $LRU_SIZE * 100))
14863
14864         # Use $LRU_SIZE_B here to take into account real number of locks
14865         # created in the case of CMD, LRU_SIZE_B != $NR in most of cases
14866         local LRU_SIZE_B=$LRU_SIZE
14867         log "LVF=$LVF"
14868         local OLD_LVF=$($LCTL get_param -n $NSDIR.pool.lock_volume_factor)
14869         log "OLD_LVF=$OLD_LVF"
14870         $LCTL set_param -n $NSDIR.pool.lock_volume_factor $LVF
14871
14872         # Let's make sure that we really have some margin. Client checks
14873         # cached locks every 10 sec.
14874         SLEEP=$((SLEEP+20))
14875         log "Sleep ${SLEEP} sec"
14876         local SEC=0
14877         while ((SEC<$SLEEP)); do
14878                 echo -n "..."
14879                 sleep 5
14880                 SEC=$((SEC+5))
14881                 LRU_SIZE=$($LCTL get_param -n $NSDIR/lru_size)
14882                 echo -n "$LRU_SIZE"
14883         done
14884         echo ""
14885         $LCTL set_param -n $NSDIR.pool.lock_volume_factor $OLD_LVF
14886         local LRU_SIZE_A=$($LCTL get_param -n $NSDIR.lru_size)
14887
14888         [[ $LRU_SIZE_B -gt $LRU_SIZE_A ]] || {
14889                 error "No locks dropped in ${SLEEP}s. LRU size: $LRU_SIZE_A"
14890                 unlinkmany $DIR/$tdir/f $NR
14891                 return
14892         }
14893
14894         log "Dropped "$((LRU_SIZE_B-LRU_SIZE_A))" locks in ${SLEEP}s"
14895         log "unlink $NR files at $DIR/$tdir"
14896         unlinkmany $DIR/$tdir/f $NR
14897 }
14898 run_test 124a "lru resize ======================================="
14899
14900 get_max_pool_limit()
14901 {
14902         local limit=$($LCTL get_param \
14903                       -n ldlm.namespaces.*-MDT0000-mdc-*.pool.limit)
14904         local max=0
14905         for l in $limit; do
14906                 if [[ $l -gt $max ]]; then
14907                         max=$l
14908                 fi
14909         done
14910         echo $max
14911 }
14912
14913 test_124b() {
14914         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14915         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
14916                 skip_env "no lru resize on server"
14917
14918         LIMIT=$(get_max_pool_limit)
14919
14920         NR=$(($(default_lru_size)*20))
14921         if [[ $NR -gt $LIMIT ]]; then
14922                 log "Limit lock number by $LIMIT locks"
14923                 NR=$LIMIT
14924         fi
14925
14926         IFree=$(mdsrate_inodes_available)
14927         if [ $IFree -lt $NR ]; then
14928                 log "Limit lock number by $IFree inodes"
14929                 NR=$IFree
14930         fi
14931
14932         lru_resize_disable mdc
14933         test_mkdir -p $DIR/$tdir/disable_lru_resize
14934
14935         createmany -o $DIR/$tdir/disable_lru_resize/f $NR
14936         log "doing ls -la $DIR/$tdir/disable_lru_resize 3 times"
14937         cancel_lru_locks mdc
14938         stime=`date +%s`
14939         PID=""
14940         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
14941         PID="$PID $!"
14942         sleep 2
14943         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
14944         PID="$PID $!"
14945         sleep 2
14946         ls -la $DIR/$tdir/disable_lru_resize > /dev/null &
14947         PID="$PID $!"
14948         wait $PID
14949         etime=`date +%s`
14950         nolruresize_delta=$((etime-stime))
14951         log "ls -la time: $nolruresize_delta seconds"
14952         log "lru_size = $(lctl get_param -n ldlm.namespaces.*mdc*.lru_size)"
14953         unlinkmany $DIR/$tdir/disable_lru_resize/f $NR
14954
14955         lru_resize_enable mdc
14956         test_mkdir -p $DIR/$tdir/enable_lru_resize
14957
14958         createmany -o $DIR/$tdir/enable_lru_resize/f $NR
14959         log "doing ls -la $DIR/$tdir/enable_lru_resize 3 times"
14960         cancel_lru_locks mdc
14961         stime=`date +%s`
14962         PID=""
14963         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
14964         PID="$PID $!"
14965         sleep 2
14966         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
14967         PID="$PID $!"
14968         sleep 2
14969         ls -la $DIR/$tdir/enable_lru_resize > /dev/null &
14970         PID="$PID $!"
14971         wait $PID
14972         etime=`date +%s`
14973         lruresize_delta=$((etime-stime))
14974         log "ls -la time: $lruresize_delta seconds"
14975         log "lru_size = $(lctl get_param -n ldlm.namespaces.*mdc*.lru_size)"
14976
14977         if [ $lruresize_delta -gt $nolruresize_delta ]; then
14978                 log "ls -la is $(((lruresize_delta - $nolruresize_delta) * 100 / $nolruresize_delta))% slower with lru resize enabled"
14979         elif [ $nolruresize_delta -gt $lruresize_delta ]; then
14980                 log "ls -la is $(((nolruresize_delta - $lruresize_delta) * 100 / $nolruresize_delta))% faster with lru resize enabled"
14981         else
14982                 log "lru resize performs the same with no lru resize"
14983         fi
14984         unlinkmany $DIR/$tdir/enable_lru_resize/f $NR
14985 }
14986 run_test 124b "lru resize (performance test) ======================="
14987
14988 test_124c() {
14989         [ $PARALLEL == "yes" ] && skip "skip parallel run"
14990         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
14991                 skip_env "no lru resize on server"
14992
14993         # cache ununsed locks on client
14994         local nr=100
14995         cancel_lru_locks mdc
14996         test_mkdir $DIR/$tdir
14997         createmany -o $DIR/$tdir/f $nr ||
14998                 error "failed to create $nr files in $DIR/$tdir"
14999         ls -l $DIR/$tdir > /dev/null
15000
15001         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
15002         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
15003         local max_age=$($LCTL get_param -n $nsdir.lru_max_age)
15004         local recalc_p=$($LCTL get_param -n $nsdir.pool.recalc_period)
15005         echo "unused=$unused, max_age=$max_age, recalc_p=$recalc_p"
15006
15007         # set lru_max_age to 1 sec
15008         $LCTL set_param $nsdir.lru_max_age=1000 # milliseconds
15009         echo "sleep $((recalc_p * 2)) seconds..."
15010         sleep $((recalc_p * 2))
15011
15012         local remaining=$($LCTL get_param -n $nsdir.lock_unused_count)
15013         # restore lru_max_age
15014         $LCTL set_param -n $nsdir.lru_max_age $max_age
15015         [ $remaining -eq 0 ] || error "$remaining locks are not canceled"
15016         unlinkmany $DIR/$tdir/f $nr
15017 }
15018 run_test 124c "LRUR cancel very aged locks"
15019
15020 test_124d() {
15021         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15022         $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize ||
15023                 skip_env "no lru resize on server"
15024
15025         # cache ununsed locks on client
15026         local nr=100
15027
15028         lru_resize_disable mdc
15029         stack_trap "lru_resize_enable mdc" EXIT
15030
15031         cancel_lru_locks mdc
15032
15033         # asynchronous object destroy at MDT could cause bl ast to client
15034         test_mkdir $DIR/$tdir
15035         createmany -o $DIR/$tdir/f $nr ||
15036                 error "failed to create $nr files in $DIR/$tdir"
15037         stack_trap "unlinkmany $DIR/$tdir/f $nr" EXIT
15038
15039         ls -l $DIR/$tdir > /dev/null
15040
15041         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
15042         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
15043         local max_age=$($LCTL get_param -n $nsdir.lru_max_age)
15044         local recalc_p=$($LCTL get_param -n $nsdir.pool.recalc_period)
15045
15046         echo "unused=$unused, max_age=$max_age, recalc_p=$recalc_p"
15047
15048         # set lru_max_age to 1 sec
15049         $LCTL set_param $nsdir.lru_max_age=1000 # milliseconds
15050         stack_trap "$LCTL set_param -n $nsdir.lru_max_age $max_age" EXIT
15051
15052         echo "sleep $((recalc_p * 2)) seconds..."
15053         sleep $((recalc_p * 2))
15054
15055         local remaining=$($LCTL get_param -n $nsdir.lock_unused_count)
15056
15057         [ $remaining -eq 0 ] || error "$remaining locks are not canceled"
15058 }
15059 run_test 124d "cancel very aged locks if lru-resize disabled"
15060
15061 test_125() { # 13358
15062         $LCTL get_param -n llite.*.client_type | grep -q local ||
15063                 skip "must run as local client"
15064         $LCTL get_param -n mdc.*-mdc-*.connect_flags | grep -q acl ||
15065                 skip_env "must have acl enabled"
15066         [ -z "$(which setfacl)" ] && skip_env "must have setfacl tool"
15067         id $USER0 || skip_env "missing user $USER0"
15068
15069         test_mkdir $DIR/$tdir
15070         $LFS setstripe -S 65536 -c -1 $DIR/$tdir || error "setstripe failed"
15071         setfacl -R -m u:$USER0:rwx $DIR/$tdir ||
15072                 error "setfacl $DIR/$tdir failed"
15073         ls -ld $DIR/$tdir || error "cannot access $DIR/$tdir"
15074 }
15075 run_test 125 "don't return EPROTO when a dir has a non-default striping and ACLs"
15076
15077 test_126() { # bug 12829/13455
15078         $GSS && skip_env "must run as gss disabled"
15079         $LCTL get_param -n llite.*.client_type | grep -q local ||
15080                 skip "must run as local client"
15081         [ "$UID" != 0 ] && skip "must run as root, not UID $UID"
15082
15083         $RUNAS -u 0 -g 1 touch $DIR/$tfile || error "touch failed"
15084         gid=`ls -n $DIR/$tfile | awk '{print $4}'`
15085         rm -f $DIR/$tfile
15086         [ $gid -eq "1" ] || error "gid is set to" $gid "instead of 1"
15087 }
15088 run_test 126 "check that the fsgid provided by the client is taken into account"
15089
15090 test_127a() { # bug 15521
15091         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15092         local name count samp unit min max sum sumsq
15093         local tmpfile=$TMP/$tfile.tmp
15094
15095         # enable stats header if it is disabled
15096         $LCTL set_param enable_stats_header=1
15097
15098         $LFS setstripe -i 0 -c 1 $DIR/$tfile || error "setstripe failed"
15099         echo "stats before reset"
15100         stack_trap "rm -f $tmpfile"
15101         local now=$(date +%s)
15102
15103         $LCTL get_param osc.*.stats | tee $tmpfile
15104
15105         local snapshot_time=$(awk '/snapshot_time/ { print $2; exit }' $tmpfile)
15106         local start_time=$(awk '/start_time/ { print $2; exit }' $tmpfile)
15107         local elapsed=$(awk '/elapsed_time/ { print $2; exit }' $tmpfile)
15108         local uptime=$(awk '{ print $1 }' /proc/uptime)
15109
15110         # snapshot_time should match POSIX epoch time, allow some delta for VMs
15111         (( ${snapshot_time%\.*} >= $now - 5 &&
15112            ${snapshot_time%\.*} <= $now + 5 )) ||
15113                 error "snapshot_time=$snapshot_time != now=$now"
15114         # elapsed _should_ be from mount, but at least less than uptime
15115         (( ${elapsed%\.*} < ${uptime%\.*} )) ||
15116                 error "elapsed=$elapsed > uptime=$uptime"
15117         (( ${snapshot_time%\.*} - ${start_time%\.*} >= ${elapsed%\.*} - 2 &&
15118            ${snapshot_time%\.*} - ${start_time%\.*} <= ${elapsed%\.*} + 2 )) ||
15119                 error "elapsed=$elapsed != $snapshot_time - $start_time"
15120
15121         $LCTL set_param osc.*.stats=0
15122         local reset=$(date +%s)
15123         local fsize=$((2048 * 1024))
15124
15125         dd if=/dev/zero of=$DIR/$tfile bs=$fsize count=1
15126         cancel_lru_locks osc
15127         dd if=$DIR/$tfile of=/dev/null bs=$fsize
15128
15129         now=$(date +%s)
15130         $LCTL get_param osc.*0000-osc-*.stats > $tmpfile
15131         while read name count samp unit min max sum sumsq; do
15132                 [[ "$samp" == "samples" ]] || continue
15133
15134                 echo "got name=$name count=$count unit=$unit min=$min max=$max"
15135                 [ ! $min ] && error "Missing min value for $name proc entry"
15136                 eval $name=$count || error "Wrong proc format"
15137
15138                 case $name in
15139                 read_bytes|write_bytes)
15140                         [[ "$unit" =~ "bytes" ]] ||
15141                                 error "unit is not 'bytes': $unit"
15142                         (( $min >= 4096 )) || error "min is too small: $min"
15143                         (( $min <= $fsize )) || error "min is too big: $min"
15144                         (( $max >= 4096 )) || error "max is too small: $max"
15145                         (( $max <= $fsize )) || error "max is too big: $max"
15146                         (( $sum == $fsize )) || error "sum is wrong: $sum"
15147                         (( $sumsq >= ($fsize / 4096) * (4096 * 4096) )) ||
15148                                 error "sumsquare is too small: $sumsq"
15149                         (( $sumsq <= $fsize * $fsize )) ||
15150                                 error "sumsquare is too big: $sumsq"
15151                         ;;
15152                 ost_read|ost_write)
15153                         [[ "$unit" =~ "usec" ]] ||
15154                                 error "unit is not 'usec': $unit"
15155                         ;;
15156                 *)      ;;
15157                 esac
15158         done < $tmpfile
15159
15160         #check that we actually got some stats
15161         [ "$read_bytes" ] || error "Missing read_bytes stats"
15162         [ "$write_bytes" ] || error "Missing write_bytes stats"
15163         [ "$read_bytes" != 0 ] || error "no read done"
15164         [ "$write_bytes" != 0 ] || error "no write done"
15165
15166         snapshot_time=$(awk '/snapshot_time/ { print $2; exit }' $tmpfile)
15167         start_time=$(awk '/start_time/ { print $2; exit }' $tmpfile)
15168         elapsed=$(awk '/elapsed_time/ { print $2; exit }' $tmpfile)
15169
15170         # snapshot_time should match POSIX epoch time, allow some delta for VMs
15171         (( ${snapshot_time%\.*} >= $now - 5 &&
15172            ${snapshot_time%\.*} <= $now + 5 )) ||
15173                 error "reset snapshot_time=$snapshot_time != now=$now"
15174         # elapsed should be from time of stats reset
15175         (( ${elapsed%\.*} >= $now - $reset - 2 &&
15176            ${elapsed%\.*} <= $now - $reset + 2 )) ||
15177                 error "reset elapsed=$elapsed > $now - $reset"
15178         (( ${snapshot_time%\.*} - ${start_time%\.*} >= ${elapsed%\.*} - 2 &&
15179            ${snapshot_time%\.*} - ${start_time%\.*} <= ${elapsed%\.*} + 2 )) ||
15180                 error "reset elapsed=$elapsed != $snapshot_time - $start_time"
15181 }
15182 run_test 127a "verify the client stats are sane"
15183
15184 test_127b() { # bug LU-333
15185         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15186         local name count samp unit min max sum sumsq
15187
15188         echo "stats before reset"
15189         $LCTL get_param llite.*.stats
15190         $LCTL set_param llite.*.stats=0
15191
15192         # perform 2 reads and writes so MAX is different from SUM.
15193         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1
15194         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1
15195         cancel_lru_locks osc
15196         dd if=$DIR/$tfile of=/dev/null bs=$PAGE_SIZE count=1
15197         dd if=$DIR/$tfile of=/dev/null bs=$PAGE_SIZE count=1
15198
15199         $LCTL get_param llite.*.stats | grep samples > $TMP/$tfile.tmp
15200         stack_trap "rm -f $TMP/$tfile.tmp"
15201         while read name count samp unit min max sum sumsq; do
15202                 echo "got name=$name count=$count unit=$unit min=$min max=$max"
15203                 eval $name=$count || error "Wrong proc format"
15204
15205                 case $name in
15206                 read_bytes|write_bytes)
15207                         [[ "$unit" =~ "bytes" ]] ||
15208                                 error "unit is not 'bytes': $unit"
15209                         (( $count == 2 )) || error "count is not 2: $count"
15210                         (( $min == $PAGE_SIZE )) ||
15211                                 error "min is not $PAGE_SIZE: $min"
15212                         (( $max == $PAGE_SIZE )) ||
15213                                 error "max is not $PAGE_SIZE: $max"
15214                         (( $sum == $PAGE_SIZE * 2 )) ||
15215                                 error "sum is not $((PAGE_SIZE * 2)): $sum"
15216                         ;;
15217                 read|write)
15218                         [[ "$unit" =~ "usec" ]] ||
15219                                 error "unit is not 'usec': $unit"
15220                         ;;
15221                 *)      ;;
15222                 esac
15223         done < $TMP/$tfile.tmp
15224
15225         #check that we actually got some stats
15226         [ "$read_bytes" ] || error "Missing read_bytes stats"
15227         [ "$write_bytes" ] || error "Missing write_bytes stats"
15228         [ "$read_bytes" != 0 ] || error "no read done"
15229         [ "$write_bytes" != 0 ] || error "no write done"
15230 }
15231 run_test 127b "verify the llite client stats are sane"
15232
15233 test_127c() { # LU-12394
15234         [ "$OSTCOUNT" -lt "2" ] && skip_env "needs >= 2 OSTs"
15235         local size
15236         local bsize
15237         local reads
15238         local writes
15239         local count
15240
15241         $LCTL set_param llite.*.extents_stats=1
15242         stack_trap "$LCTL set_param llite.*.extents_stats=0" EXIT
15243
15244         # Use two stripes so there is enough space in default config
15245         $LFS setstripe -c 2 $DIR/$tfile
15246
15247         # Extent stats start at 0-4K and go in power of two buckets
15248         # LL_HIST_START = 12 --> 2^12 = 4K
15249         # We do 3K*2^i, so 3K, 6K, 12K, 24K... hitting each bucket.
15250         # We do not do buckets larger than 64 MiB to avoid ENOSPC issues on
15251         # small configs
15252         for size in 3K 6K 12K 24K 48K 96K 192K 384K 768K 1536K 3M 6M 12M 24M 48M;
15253                 do
15254                 # Write and read, 2x each, second time at a non-zero offset
15255                 dd if=/dev/zero of=$DIR/$tfile bs=$size count=1
15256                 dd if=/dev/zero of=$DIR/$tfile bs=$size count=1 seek=10
15257                 dd if=$DIR/$tfile of=/dev/null bs=$size count=1
15258                 dd if=$DIR/$tfile of=/dev/null bs=$size count=1 seek=10
15259                 rm -f $DIR/$tfile
15260         done
15261
15262         $LCTL get_param llite.*.extents_stats
15263
15264         count=2
15265         for bsize in 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M;
15266                 do
15267                 local bucket=$($LCTL get_param -n llite.*.extents_stats |
15268                                 grep -m 1 $bsize)
15269                 reads=$(echo $bucket | awk '{print $5}')
15270                 writes=$(echo $bucket | awk '{print $9}')
15271                 [ "$reads" -eq $count ] ||
15272                         error "$reads reads in < $bsize bucket, expect $count"
15273                 [ "$writes" -eq $count ] ||
15274                         error "$writes writes in < $bsize bucket, expect $count"
15275         done
15276
15277         # Test mmap write and read
15278         $LCTL set_param llite.*.extents_stats=c
15279         size=512
15280         dd if=/dev/zero of=$DIR/$tfile bs=${size}K count=1
15281         $MULTIOP $DIR/$tfile OSMRUc || error "$MULTIOP $DIR/$tfile failed"
15282         $MULTIOP $DIR/$tfile OSMWUc || error "$MULTIOP $DIR/$tfile failed"
15283
15284         $LCTL get_param llite.*.extents_stats
15285
15286         count=$(((size*1024) / PAGE_SIZE))
15287
15288         bsize=$((2 * PAGE_SIZE / 1024))K
15289
15290         bucket=$($LCTL get_param -n llite.*.extents_stats |
15291                         grep -m 1 $bsize)
15292         reads=$(echo $bucket | awk '{print $5}')
15293         writes=$(echo $bucket | awk '{print $9}')
15294         # mmap writes fault in the page first, creating an additonal read
15295         [ "$reads" -eq $((2 * count)) ] ||
15296                 error "$reads reads in < $bsize bucket, expect $count"
15297         [ "$writes" -eq $count ] ||
15298                 error "$writes writes in < $bsize bucket, expect $count"
15299 }
15300 run_test 127c "test llite extent stats with regular & mmap i/o"
15301
15302 test_128() { # bug 15212
15303         touch $DIR/$tfile
15304         $LFS 2>&1 <<-EOF | tee $TMP/$tfile.log
15305                 find $DIR/$tfile
15306                 find $DIR/$tfile
15307         EOF
15308
15309         result=$(grep error $TMP/$tfile.log)
15310         rm -f $DIR/$tfile $TMP/$tfile.log
15311         [ -z "$result" ] ||
15312                 error "consecutive find's under interactive lfs failed"
15313 }
15314 run_test 128 "interactive lfs for 2 consecutive find's"
15315
15316 set_dir_limits () {
15317         local mntdev
15318         local canondev
15319         local node
15320
15321         local ldproc=/proc/fs/ldiskfs
15322         local facets=$(get_facets MDS)
15323
15324         for facet in ${facets//,/ }; do
15325                 canondev=$(ldiskfs_canon \
15326                            *.$(convert_facet2label $facet).mntdev $facet)
15327                 do_facet $facet "test -e $ldproc/$canondev/max_dir_size" ||
15328                         ldproc=/sys/fs/ldiskfs
15329                 do_facet $facet "echo $1 >$ldproc/$canondev/max_dir_size"
15330                 do_facet $facet "echo $2 >$ldproc/$canondev/warning_dir_size"
15331         done
15332 }
15333
15334 check_mds_dmesg() {
15335         local facets=$(get_facets MDS)
15336         for facet in ${facets//,/ }; do
15337                 do_facet $facet "dmesg | tail -3 | grep $1" && return 0
15338         done
15339         return 1
15340 }
15341
15342 test_129() {
15343         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15344         [[ $MDS1_VERSION -ge $(version_code 2.5.56) ]] ||
15345                 skip "Need MDS version with at least 2.5.56"
15346         if [ "$mds1_FSTYPE" != ldiskfs ]; then
15347                 skip_env "ldiskfs only test"
15348         fi
15349         remote_mds_nodsh && skip "remote MDS with nodsh"
15350
15351         local ENOSPC=28
15352         local has_warning=false
15353
15354         rm -rf $DIR/$tdir
15355         mkdir -p $DIR/$tdir
15356
15357         # block size of mds1
15358         local maxsize=$(($($LCTL get_param -n mdc.*MDT0000*.blocksize) * 8))
15359         set_dir_limits $maxsize $((maxsize * 6 / 8))
15360         stack_trap "set_dir_limits 0 0"
15361         stack_trap "unlinkmany $DIR/$tdir/file_base_ 2000 || true"
15362         local dirsize=$(stat -c%s "$DIR/$tdir")
15363         local nfiles=0
15364         while (( $dirsize <= $maxsize )); do
15365                 $MCREATE $DIR/$tdir/file_base_$nfiles
15366                 rc=$?
15367                 # check two errors:
15368                 # ENOSPC for ext4 max_dir_size, which has been used since
15369                 # kernel v3.6-rc1-8-gdf981d03ee, lustre v2_4_50_0-79-gaed82035c0
15370                 if (( rc == ENOSPC )); then
15371                         set_dir_limits 0 0
15372                         echo "rc=$rc returned as expected after $nfiles files"
15373
15374                         createmany -o $DIR/$tdir/file_extra_$nfiles. 5 ||
15375                                 error "create failed w/o dir size limit"
15376
15377                         # messages may be rate limited if test is run repeatedly
15378                         check_mds_dmesg '"is approaching max"' ||
15379                                 echo "warning message should be output"
15380                         check_mds_dmesg '"has reached max"' ||
15381                                 echo "reached message should be output"
15382
15383                         dirsize=$(stat -c%s "$DIR/$tdir")
15384
15385                         [[ $dirsize -ge $maxsize ]] && return 0
15386                         error "dirsize $dirsize < $maxsize after $nfiles files"
15387                 elif (( rc != 0 )); then
15388                         break
15389                 fi
15390                 nfiles=$((nfiles + 1))
15391                 dirsize=$(stat -c%s "$DIR/$tdir")
15392         done
15393
15394         error "rc=$rc, size=$dirsize/$maxsize, mdt=$MDSCOUNT, nfiles=$nfiles"
15395 }
15396 run_test 129 "test directory size limit ========================"
15397
15398 OLDIFS="$IFS"
15399 cleanup_130() {
15400         trap 0
15401         IFS="$OLDIFS"
15402         rm -f $DIR/$tfile
15403 }
15404
15405 test_130a() {
15406         local filefrag_op=$(filefrag -e 2>&1 | grep "invalid option")
15407         [[ -z "$filefrag_op" ]] || skip_env "filefrag does not support FIEMAP"
15408
15409         trap cleanup_130 EXIT RETURN
15410
15411         local fm_file=$DIR/$tfile
15412         $LFS setstripe -S 65536 -c 1 $fm_file || error "setstripe on $fm_file"
15413         dd if=/dev/zero of=$fm_file bs=65536 count=1 ||
15414                 error "dd failed for $fm_file"
15415
15416         # LU-1795: test filefrag/FIEMAP once, even if unsupported on ZFS
15417         filefrag -ves $fm_file
15418         local rc=$?
15419         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15420                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15421         (( $rc == 0 )) || error "filefrag $fm_file failed"
15422
15423         filefrag_op=$(filefrag -ve -k $fm_file |
15424                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
15425         local lun=$($LFS getstripe -i $fm_file)
15426
15427         local start_blk=$(echo $filefrag_op | cut -d: -f2 | cut -d. -f1)
15428         IFS=$'\n'
15429         local tot_len=0
15430         for line in $filefrag_op; do
15431                 local frag_lun=$(echo $line | cut -d: -f5)
15432                 local ext_len=$(echo $line | cut -d: -f4)
15433
15434                 if (( $frag_lun != $lun )); then
15435                         error "FIEMAP on 1-stripe file($fm_file) failed"
15436                         return
15437                 fi
15438                 (( tot_len += ext_len ))
15439         done
15440
15441         if (( lun != frag_lun || start_blk != 0 || tot_len != 64 )); then
15442                 error "FIEMAP on 1-stripe file($fm_file) failed"
15443                 return
15444         fi
15445
15446         echo "FIEMAP on single striped file succeeded"
15447 }
15448 run_test 130a "FIEMAP (1-stripe file)"
15449
15450 test_130b() {
15451         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15452
15453         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15454         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15455         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15456                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15457
15458         trap cleanup_130 EXIT RETURN
15459
15460         local fm_file=$DIR/$tfile
15461         $LFS setstripe -S 65536 -c $OSTCOUNT $fm_file ||
15462                 error "setstripe on $fm_file"
15463
15464         dd if=/dev/zero of=$fm_file bs=1M count=$OSTCOUNT ||
15465                 error "dd failed on $fm_file"
15466
15467         filefrag -ves $fm_file || error "filefrag $fm_file failed"
15468         filefrag_op=$(filefrag -ve -k $fm_file |
15469                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
15470
15471         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
15472                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15473
15474         IFS=$'\n'
15475         local tot_len=0
15476         local num_luns=1
15477
15478         for line in $filefrag_op; do
15479                 local frag_lun=$(echo $line | cut -d: -f5 |
15480                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15481                 local ext_len=$(echo $line | cut -d: -f4)
15482                 if (( $frag_lun != $last_lun )); then
15483                         if (( tot_len != 1024 )); then
15484                                 error "FIEMAP on $fm_file failed; returned len $tot_len for OST $last_lun instead of 1024"
15485                                 return
15486                         else
15487                                 (( num_luns += 1 ))
15488                                 tot_len=0
15489                         fi
15490                 fi
15491                 (( tot_len += ext_len ))
15492                 last_lun=$frag_lun
15493         done
15494         if (( num_luns != $OSTCOUNT || tot_len != 1024 )); then
15495                 error "FIEMAP on $fm_file failed; returned wrong number of luns or wrong len for OST $last_lun"
15496                 return
15497         fi
15498
15499         echo "FIEMAP on $OSTCOUNT-stripe file succeeded"
15500 }
15501 run_test 130b "FIEMAP ($OSTCOUNT-stripe file)"
15502
15503 test_130c() {
15504         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15505
15506         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15507         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15508         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15509                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15510
15511         trap cleanup_130 EXIT RETURN
15512
15513         local fm_file=$DIR/$tfile
15514         $LFS setstripe -S 65536 -c 2 $fm_file || error "setstripe on $fm_file"
15515
15516         dd if=/dev/zero of=$fm_file seek=1 bs=1M count=1 ||
15517                 error "dd failed on $fm_file"
15518
15519         filefrag -ves $fm_file || error "filefrag $fm_file failed"
15520         filefrag_op=$(filefrag -ve -k $fm_file |
15521                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
15522
15523         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
15524                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15525
15526         IFS=$'\n'
15527         local tot_len=0
15528         local num_luns=1
15529         for line in $filefrag_op; do
15530                 local frag_lun=$(echo $line | cut -d: -f5 |
15531                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15532                 local ext_len=$(echo $line | cut -d: -f4)
15533                 if (( $frag_lun != $last_lun )); then
15534                         local logical=$(echo $line | cut -d: -f2 | cut -d. -f1)
15535                         if (( logical != 512 )); then
15536                                 error "FIEMAP on $fm_file failed; returned logical start for lun $logical instead of 512"
15537                                 return
15538                         fi
15539                         if (( tot_len != 512 )); then
15540                                 error "FIEMAP on $fm_file failed; returned len $tot_len for OST $last_lun instead of 1024"
15541                                 return
15542                         else
15543                                 (( num_luns += 1 ))
15544                                 tot_len=0
15545                         fi
15546                 fi
15547                 (( tot_len += ext_len ))
15548                 last_lun=$frag_lun
15549         done
15550         if (( num_luns != 2 || tot_len != 512 )); then
15551                 error "FIEMAP on $fm_file failed; returned wrong number of luns or wrong len for OST $last_lun"
15552                 return
15553         fi
15554
15555         echo "FIEMAP on 2-stripe file with hole succeeded"
15556 }
15557 run_test 130c "FIEMAP (2-stripe file with hole)"
15558
15559 test_130d() {
15560         (( $OSTCOUNT >= 3 )) || skip "needs >= 3 OSTs"
15561
15562         filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15563         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15564         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15565                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15566
15567         trap cleanup_130 EXIT RETURN
15568
15569         local fm_file=$DIR/$tfile
15570         $LFS setstripe -S 65536 -c $OSTCOUNT $fm_file ||
15571                         error "setstripe on $fm_file"
15572
15573         local actual_stripe_count=$($LFS getstripe -c $fm_file)
15574         dd if=/dev/zero of=$fm_file bs=1M count=$actual_stripe_count ||
15575                 error "dd failed on $fm_file"
15576
15577         filefrag -ves $fm_file || error "filefrag $fm_file failed"
15578         filefrag_op=$(filefrag -ve -k $fm_file |
15579                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
15580
15581         local last_lun=$(echo $filefrag_op | cut -d: -f5 |
15582                          sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15583
15584         IFS=$'\n'
15585         local tot_len=0
15586         local num_luns=1
15587         for line in $filefrag_op; do
15588                 local frag_lun=$(echo $line | cut -d: -f5 |
15589                                  sed -e 's/^[ \t]*/0x/' | sed -e 's/0x0x/0x/')
15590                 local ext_len=$(echo $line | cut -d: -f4)
15591                 if (( $frag_lun != $last_lun )); then
15592                         if (( tot_len != 1024 )); then
15593                                 error "FIEMAP on $fm_file failed; returned len $tot_len for OST $last_lun instead of 1024"
15594                                 return
15595                         else
15596                                 (( num_luns += 1 ))
15597                                 local tot_len=0
15598                         fi
15599                 fi
15600                 (( tot_len += ext_len ))
15601                 last_lun=$frag_lun
15602         done
15603         if (( num_luns != actual_stripe_count || tot_len != 1024 )); then
15604                 error "FIEMAP on $fm_file failed; returned wrong number of luns or wrong len for OST $last_lun"
15605                 return
15606         fi
15607
15608         echo "FIEMAP on N-stripe file succeeded"
15609 }
15610 run_test 130d "FIEMAP (N-stripe file)"
15611
15612 test_130e() {
15613         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
15614
15615         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15616         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15617         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15618                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15619
15620         trap cleanup_130 EXIT RETURN
15621
15622         local fm_file=$DIR/$tfile
15623         $LFS setstripe -S 131072 -c 2 $fm_file || error "setstripe on $fm_file"
15624         stack_trap "rm -f $fm_file"
15625
15626         local num_blks=512
15627         local expected_len=$(( (num_blks / 2) * 64 ))
15628         for ((i = 0; i < $num_blks; i++)); do
15629                 dd if=/dev/zero of=$fm_file count=1 bs=64k seek=$((2*$i)) \
15630                         conv=notrunc > /dev/null 2>&1
15631         done
15632
15633         filefrag -ves $fm_file || error "filefrag $fm_file failed"
15634         filefrag_op=$(filefrag -ve -k $fm_file |
15635                       sed -n '/ext:/,/found/{/ext:/d; /found/d; p}')
15636
15637         local last_lun=$(echo $filefrag_op | cut -d: -f5)
15638
15639         IFS=$'\n'
15640         local tot_len=0
15641         local num_luns=1
15642         for line in $filefrag_op; do
15643                 local frag_lun=$(echo $line | cut -d: -f5)
15644                 local ext_len=$(echo $line | cut -d: -f4)
15645                 if (( $frag_lun != $last_lun )); then
15646                         if (( tot_len != $expected_len )); then
15647                                 error "OST$last_lun $tot_len != $expected_len"
15648                         else
15649                                 (( num_luns += 1 ))
15650                                 tot_len=0
15651                         fi
15652                 fi
15653                 (( tot_len += ext_len ))
15654                 last_lun=$frag_lun
15655         done
15656         if (( num_luns != 2 || tot_len != $expected_len )); then
15657                 error "OST$last_lun $num_luns != 2, $tot_len != $expected_len"
15658         fi
15659
15660         echo "FIEMAP with continuation calls succeeded"
15661 }
15662 run_test 130e "FIEMAP (test continuation FIEMAP calls)"
15663
15664 test_130f() {
15665         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15666         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15667         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15668                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15669
15670         local fm_file=$DIR/$tfile
15671         $MULTIOP $fm_file oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:T33554432c ||
15672                 error "multiop create with lov_delay_create on $fm_file"
15673
15674         filefrag -ves $fm_file || error "filefrag $fm_file failed"
15675         filefrag_extents=$(filefrag -vek $fm_file |
15676                            awk '/extents? found/ { print $2 }')
15677         if (( $filefrag_extents != 0 )); then
15678                 error "$fm_file: filefrag_extents=$filefrag_extents != 0"
15679         fi
15680
15681         rm -f $fm_file
15682 }
15683 run_test 130f "FIEMAP (unstriped file)"
15684
15685 test_130g() {
15686         (( $MDS1_VERSION >= $(version_code 2.12.53) )) ||
15687                 skip "Need MDS version with at least 2.12.53 for overstriping"
15688         local filefrag_op=$(filefrag -l 2>&1 | grep "invalid option")
15689         [[ -z "$filefrag_op" ]] || skip_env "filefrag missing logical ordering"
15690         [[ "$ost1_FSTYPE" != "zfs" ]] ||
15691                 skip "LU-1941: FIEMAP unimplemented on ZFS"
15692
15693         local file=$DIR/$tfile
15694         local nr=$((OSTCOUNT * 100))
15695
15696         $LFS setstripe -C $nr -S1M $file ||
15697                 error "failed to setstripe -C $nr $file"
15698
15699         stack_trap "rm -f $file"
15700         dd if=/dev/zero of=$file count=$nr bs=1M
15701         sync
15702         nr=$($LFS getstripe -c $file)
15703
15704         local extents=$(filefrag -v $file |
15705                         sed -n '/ext:/,/found/{/ext:/d; /found/d; p}' | wc -l)
15706
15707         echo "filefrag list $extents extents in file with stripecount $nr"
15708         if (( extents < nr )); then
15709                 $LFS getstripe $file
15710                 filefrag -v $file
15711                 error "filefrag printed $extents < $nr extents"
15712         fi
15713 }
15714 run_test 130g "FIEMAP (overstripe file)"
15715
15716 # Test for writev/readv
15717 test_131a() {
15718         rwv -f $DIR/$tfile -w -n 3 524288 1048576 1572864 ||
15719                 error "writev test failed"
15720         rwv -f $DIR/$tfile -r -v -n 2 1572864 1048576 ||
15721                 error "readv failed"
15722         rm -f $DIR/$tfile
15723 }
15724 run_test 131a "test iov's crossing stripe boundary for writev/readv"
15725
15726 test_131b() {
15727         local fsize=$((524288 + 1048576 + 1572864))
15728         rwv -f $DIR/$tfile -w -a -n 3 524288 1048576 1572864 &&
15729                 $CHECKSTAT -t file $DIR/$tfile -s $fsize ||
15730                         error "append writev test failed"
15731
15732         ((fsize += 1572864 + 1048576))
15733         rwv -f $DIR/$tfile -w -a -n 2 1572864 1048576 &&
15734                 $CHECKSTAT -t file $DIR/$tfile -s $fsize ||
15735                         error "append writev test failed"
15736         rm -f $DIR/$tfile
15737 }
15738 run_test 131b "test append writev"
15739
15740 test_131c() {
15741         rwv -f $DIR/$tfile -w -d -n 1 1048576 || return 0
15742         error "NOT PASS"
15743 }
15744 run_test 131c "test read/write on file w/o objects"
15745
15746 test_131d() {
15747         rwv -f $DIR/$tfile -w -n 1 1572864
15748         NOB=`rwv -f $DIR/$tfile -r -n 3 524288 524288 1048576 | awk '/error/ {print $6}'`
15749         if [ "$NOB" != 1572864 ]; then
15750                 error "Short read filed: read $NOB bytes instead of 1572864"
15751         fi
15752         rm -f $DIR/$tfile
15753 }
15754 run_test 131d "test short read"
15755
15756 test_131e() {
15757         rwv -f $DIR/$tfile -w -s 1048576 -n 1 1048576
15758         rwv -f $DIR/$tfile -r -z -s 0 -n 1 524288 || \
15759         error "read hitting hole failed"
15760         rm -f $DIR/$tfile
15761 }
15762 run_test 131e "test read hitting hole"
15763
15764 check_stats() {
15765         local facet=$1
15766         local op=$2
15767         local want=${3:-0}
15768         local res
15769
15770         # open             11 samples [usecs] 468 4793 13658 35791898
15771         case $facet in
15772         mds*) res=($(do_facet $facet \
15773                    $LCTL get_param mdt.$FSNAME-MDT0000.md_stats | grep "$op"))
15774                  ;;
15775         ost*) res=($(do_facet $facet \
15776                   $LCTL get_param obdfilter.$FSNAME-OST0000.stats | grep "$op"))
15777                  ;;
15778         *) error "Wrong facet '$facet'" ;;
15779         esac
15780         [[ -n "$res" ]] || error "counter for $op on $facet not incremented"
15781         # if $want is zero, it means any stat increment is ok.
15782         if (( $want > 0 )); then
15783                 local count=${res[1]}
15784
15785                 if (( $count != $want )); then
15786                         if [[ $facet =~ "mds" ]]; then
15787                                 do_nodes $(comma_list $(mdts_nodes)) \
15788                                         $LCTL get_param mdt.*.md_stats
15789                         else
15790                                 do_nodes $(comma_list $(osts-nodes)) \
15791                                         $LCTL get_param obdfilter.*.stats
15792                         fi
15793                         error "The $op counter on $facet is $count, not $want"
15794                 fi
15795         fi
15796 }
15797
15798 test_133a() {
15799         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15800         remote_ost_nodsh && skip "remote OST with nodsh"
15801         remote_mds_nodsh && skip "remote MDS with nodsh"
15802         do_facet $SINGLEMDS $LCTL list_param mdt.*.rename_stats ||
15803                 skip_env "MDS doesn't support rename stats"
15804
15805         local testdir=$DIR/${tdir}/stats_testdir
15806
15807         mkdir_on_mdt0 $DIR/${tdir}
15808
15809         # clear stats.
15810         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15811         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
15812
15813         # verify mdt stats first.
15814         mkdir_on_mdt0 ${testdir} || error "mkdir_on_mdt0 failed"
15815         check_stats $SINGLEMDS "mkdir" 1
15816
15817         # clear "open" from "lfs mkdir" above
15818         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15819         touch ${testdir}/${tfile} || error "touch failed"
15820         check_stats $SINGLEMDS "open" 1
15821         check_stats $SINGLEMDS "close" 1
15822         # open should match close
15823         ls -lR ${testdir}
15824         check_stats $SINGLEMDS "open" 2
15825         check_stats $SINGLEMDS "close" 2
15826         [ $MDS1_VERSION -ge $(version_code 2.8.54) ] && {
15827                 mknod ${testdir}/${tfile}-pipe p || error "mknod failed"
15828                 check_stats $SINGLEMDS "mknod" 2
15829         }
15830         rm -f ${testdir}/${tfile}-pipe || error "pipe remove failed"
15831         check_stats $SINGLEMDS "unlink" 1
15832         rm -f ${testdir}/${tfile} || error "file remove failed"
15833         check_stats $SINGLEMDS "unlink" 2
15834
15835         # remove working dir and check mdt stats again.
15836         rmdir ${testdir} || error "rmdir failed"
15837         check_stats $SINGLEMDS "rmdir" 1
15838
15839         local testdir1=$DIR/${tdir}/stats_testdir1
15840         mkdir_on_mdt0 ${testdir}
15841         mkdir_on_mdt0 ${testdir1}
15842         touch ${testdir1}/test1
15843         mv ${testdir1}/test1 ${testdir} || error "file crossdir rename"
15844         check_stats $SINGLEMDS "crossdir_rename" 1
15845
15846         mv ${testdir}/test1 ${testdir}/test0 || error "file samedir rename"
15847         check_stats $SINGLEMDS "samedir_rename" 1
15848
15849         rm -rf $DIR/${tdir}
15850 }
15851 run_test 133a "Verifying MDT stats ========================================"
15852
15853 test_133b() {
15854         local res
15855
15856         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15857         remote_ost_nodsh && skip "remote OST with nodsh"
15858         remote_mds_nodsh && skip "remote MDS with nodsh"
15859
15860         local testdir=$DIR/${tdir}/stats_testdir
15861
15862         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
15863         mkdir_on_mdt0 ${testdir} || error "mkdir_on_mdt0 failed"
15864         touch ${testdir}/${tfile} || error "touch failed"
15865         cancel_lru_locks mdc
15866
15867         # clear stats.
15868         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15869         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
15870
15871         # extra mdt stats verification.
15872         chmod 444 ${testdir}/${tfile} || error "chmod failed"
15873         check_stats $SINGLEMDS "setattr" 1
15874         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15875         if [ $MDS1_VERSION -ne $(version_code 2.2.0) ]
15876         then            # LU-1740
15877                 ls -l ${testdir}/${tfile} > /dev/null|| error "ls failed"
15878                 check_stats $SINGLEMDS "getattr" 1
15879         fi
15880         rm -rf $DIR/${tdir}
15881
15882         # when DNE is enabled, MDT uses STATFS RPC to ping other targets
15883         # so the check below is not reliable
15884         [ $MDSCOUNT -eq 1 ] || return 0
15885
15886         # Sleep to avoid a cached response.
15887         #define OBD_STATFS_CACHE_SECONDS 1
15888         sleep 2
15889         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15890         do_facet ost1 $LCTL set_param obdfilter.*.exports.*.stats=clear
15891         $LFS df || error "lfs failed"
15892         check_stats $SINGLEMDS "statfs" 1
15893
15894         # check aggregated statfs (LU-10018)
15895         [ $MDS1_VERSION -lt $(version_code 2.11.54) ] &&
15896                 return 0
15897         [ $CLIENT_VERSION -lt $(version_code 2.11.54) ] &&
15898                 return 0
15899         sleep 2
15900         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15901         do_facet ost1 $LCTL set_param obdfilter.*.exports.*.stats=clear
15902         df $DIR
15903         check_stats $SINGLEMDS "statfs" 1
15904
15905         # We want to check that the client didn't send OST_STATFS to
15906         # ost1 but the MDT also uses OST_STATFS for precreate. So some
15907         # extra care is needed here.
15908         if remote_mds; then
15909                 local nid=$($LCTL list_nids | head -1 | sed  "s/\./\\\./g")
15910                 local param="obdfilter.$FSNAME-OST0000.exports.'$nid'.stats"
15911
15912                 res=$(do_facet ost1 $LCTL get_param $param | grep statfs)
15913                 [ "$res" ] && error "OST got STATFS"
15914         fi
15915
15916         return 0
15917 }
15918 run_test 133b "Verifying extra MDT stats =================================="
15919
15920 test_133c() {
15921         [ $PARALLEL == "yes" ] && skip "skip parallel run"
15922         remote_ost_nodsh && skip "remote OST with nodsh"
15923         remote_mds_nodsh && skip "remote MDS with nodsh"
15924
15925         local testdir=$DIR/$tdir/stats_testdir
15926
15927         test_mkdir -p $testdir
15928
15929         # verify obdfilter stats.
15930         $LFS setstripe -c 1 -i 0 $testdir/$tfile
15931         sync
15932         cancel_lru_locks osc
15933         wait_delete_completed
15934
15935         # clear stats.
15936         do_facet $SINGLEMDS $LCTL set_param mdt.*.md_stats=clear
15937         do_facet ost1 $LCTL set_param obdfilter.*.stats=clear
15938
15939         dd if=/dev/zero of=$testdir/$tfile conv=notrunc bs=512k count=1 ||
15940                 error "dd failed"
15941         sync
15942         cancel_lru_locks osc
15943         check_stats ost1 "write" 1
15944
15945         dd if=$testdir/$tfile of=/dev/null bs=1k count=1 || error "dd failed"
15946         check_stats ost1 "read" 1
15947
15948         > $testdir/$tfile || error "truncate failed"
15949         check_stats ost1 "punch" 1
15950
15951         rm -f $testdir/$tfile || error "file remove failed"
15952         wait_delete_completed
15953         check_stats ost1 "destroy" 1
15954
15955         rm -rf $DIR/$tdir
15956 }
15957 run_test 133c "Verifying OST stats ========================================"
15958
15959 order_2() {
15960         local value=$1
15961         local orig=$value
15962         local order=1
15963
15964         while [ $value -ge 2 ]; do
15965                 order=$((order*2))
15966                 value=$((value/2))
15967         done
15968
15969         if [ $orig -gt $order ]; then
15970                 order=$((order*2))
15971         fi
15972         echo $order
15973 }
15974
15975 size_in_KMGT() {
15976     local value=$1
15977     local size=('K' 'M' 'G' 'T');
15978     local i=0
15979     local size_string=$value
15980
15981     while [ $value -ge 1024 ]; do
15982         if [ $i -gt 3 ]; then
15983             #T is the biggest unit we get here, if that is bigger,
15984             #just return XXXT
15985             size_string=${value}T
15986             break
15987         fi
15988         value=$((value >> 10))
15989         if [ $value -lt 1024 ]; then
15990             size_string=${value}${size[$i]}
15991             break
15992         fi
15993         i=$((i + 1))
15994     done
15995
15996     echo $size_string
15997 }
15998
15999 get_rename_size() {
16000         local size=$1
16001         local context=${2:-.}
16002         local sample=$(do_facet $SINGLEMDS $LCTL \
16003                 get_param mdt.$FSNAME-MDT0000.rename_stats |
16004                 grep -A1 $context |
16005                 awk '/ '${size}'/ {print $4}' | sed -e "s/,//g")
16006         echo $sample
16007 }
16008
16009 test_133d() {
16010         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16011         remote_ost_nodsh && skip "remote OST with nodsh"
16012         remote_mds_nodsh && skip "remote MDS with nodsh"
16013         do_facet $SINGLEMDS $LCTL list_param mdt.*.rename_stats ||
16014                 skip_env "MDS doesn't support rename stats"
16015
16016         local testdir1=$DIR/${tdir}/stats_testdir1
16017         local testdir2=$DIR/${tdir}/stats_testdir2
16018         mkdir -p $DIR/${tdir} || error "mkdir $tdir failed"
16019
16020         do_facet $SINGLEMDS $LCTL set_param mdt.*.rename_stats=clear
16021
16022         mkdir_on_mdt0 ${testdir1} || error "mkdir $testdir1 failed"
16023         mkdir_on_mdt0 ${testdir2} || error "mkdir $testdir2 failed"
16024
16025         createmany -o $testdir1/test 512 || error "createmany failed"
16026
16027         # check samedir rename size
16028         mv ${testdir1}/test0 ${testdir1}/test_0
16029
16030         local testdir1_size=$(ls -l $DIR/${tdir} |
16031                 awk '/stats_testdir1/ {print $5}')
16032         local testdir2_size=$(ls -l $DIR/${tdir} |
16033                 awk '/stats_testdir2/ {print $5}')
16034
16035         testdir1_size=$(order_2 $testdir1_size)
16036         testdir2_size=$(order_2 $testdir2_size)
16037
16038         testdir1_size=$(size_in_KMGT $testdir1_size)
16039         testdir2_size=$(size_in_KMGT $testdir2_size)
16040
16041         echo "source rename dir size: ${testdir1_size}"
16042         echo "target rename dir size: ${testdir2_size}"
16043
16044         local cmd="do_facet $SINGLEMDS $LCTL "
16045         cmd+="get_param mdt.$FSNAME-MDT0000.rename_stats"
16046
16047         eval $cmd || error "$cmd failed"
16048         local samedir=$($cmd | grep 'same_dir')
16049         local same_sample=$(get_rename_size $testdir1_size)
16050         [ -z "$samedir" ] && error "samedir_rename_size count error"
16051         [[ $same_sample -eq 1 ]] ||
16052                 error "samedir_rename_size error $same_sample"
16053         echo "Check same dir rename stats success"
16054
16055         do_facet $SINGLEMDS $LCTL set_param mdt.*.rename_stats=clear
16056
16057         # check crossdir rename size
16058         mv ${testdir1}/test_0 ${testdir2}/test_0
16059
16060         testdir1_size=$(ls -l $DIR/${tdir} |
16061                 awk '/stats_testdir1/ {print $5}')
16062         testdir2_size=$(ls -l $DIR/${tdir} |
16063                 awk '/stats_testdir2/ {print $5}')
16064
16065         testdir1_size=$(order_2 $testdir1_size)
16066         testdir2_size=$(order_2 $testdir2_size)
16067
16068         testdir1_size=$(size_in_KMGT $testdir1_size)
16069         testdir2_size=$(size_in_KMGT $testdir2_size)
16070
16071         echo "source rename dir size: ${testdir1_size}"
16072         echo "target rename dir size: ${testdir2_size}"
16073
16074         eval $cmd || error "$cmd failed"
16075         local crossdir=$($cmd | grep 'crossdir')
16076         local src_sample=$(get_rename_size $testdir1_size crossdir_src)
16077         local tgt_sample=$(get_rename_size $testdir2_size crossdir_tgt)
16078         [ -z "$crossdir" ] && error "crossdir_rename_size count error"
16079         [[ $src_sample -eq 1 ]] ||
16080                 error "crossdir_rename_size error $src_sample"
16081         [[ $tgt_sample -eq 1 ]] ||
16082                 error "crossdir_rename_size error $tgt_sample"
16083         echo "Check cross dir rename stats success"
16084         rm -rf $DIR/${tdir}
16085 }
16086 run_test 133d "Verifying rename_stats ========================================"
16087
16088 test_133e() {
16089         remote_mds_nodsh && skip "remote MDS with nodsh"
16090         remote_ost_nodsh && skip "remote OST with nodsh"
16091         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16092
16093         local testdir=$DIR/${tdir}/stats_testdir
16094         local ctr f0 f1 bs=32768 count=42 sum
16095
16096         mkdir -p ${testdir} || error "mkdir failed"
16097
16098         $LFS setstripe -c 1 -i 0 ${testdir}/${tfile}
16099
16100         for ctr in {write,read}_bytes; do
16101                 sync
16102                 cancel_lru_locks osc
16103
16104                 do_facet ost1 $LCTL set_param -n \
16105                         "obdfilter.*.exports.clear=clear"
16106
16107                 if [ $ctr = write_bytes ]; then
16108                         f0=/dev/zero
16109                         f1=${testdir}/${tfile}
16110                 else
16111                         f0=${testdir}/${tfile}
16112                         f1=/dev/null
16113                 fi
16114
16115                 dd if=$f0 of=$f1 conv=notrunc bs=$bs count=$count || \
16116                         error "dd failed"
16117                 sync
16118                 cancel_lru_locks osc
16119
16120                 sum=$(do_facet ost1 $LCTL get_param \
16121                         "obdfilter.*.exports.*.stats" |
16122                         awk -v ctr=$ctr 'BEGIN { sum = 0 }
16123                                 $1 == ctr { sum += $7 }
16124                                 END { printf("%0.0f", sum) }')
16125
16126                 if ((sum != bs * count)); then
16127                         error "Bad $ctr sum, expected $((bs * count)), got $sum"
16128                 fi
16129         done
16130
16131         rm -rf $DIR/${tdir}
16132 }
16133 run_test 133e "Verifying OST {read,write}_bytes nid stats ================="
16134
16135 test_133f() {
16136         [[ $(lustre_version_code $facet) -ge $(version_code 2.7.65) ]] ||
16137                 skip "too old lustre for get_param -R ($facet_ver)"
16138
16139         # verifying readability.
16140         $LCTL get_param -R '*' &> /dev/null
16141
16142         # Verifing writability with badarea_io.
16143         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
16144         local skipped_params='force_lbug|changelog_mask|daemon_file'
16145         $LCTL list_param -FR '*' | grep '=' | tr -d = |
16146                 egrep -v "$skipped_params" |
16147                 xargs -n 1 find $proc_dirs -name |
16148                 xargs -n 1 badarea_io ||
16149                 error "client badarea_io failed"
16150
16151         # remount the FS in case writes/reads /proc break the FS
16152         cleanup || error "failed to unmount"
16153         setup || error "failed to setup"
16154 }
16155 run_test 133f "Check reads/writes of client lustre proc files with bad area io"
16156
16157 test_133g() {
16158         remote_mds_nodsh && skip "remote MDS with nodsh"
16159         remote_ost_nodsh && skip "remote OST with nodsh"
16160
16161         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
16162         local proc_dirs_str=$(eval echo $proc_dirs)
16163         local skipped_params="'force_lbug|changelog_mask|daemon_file'"
16164         local facet
16165         for facet in mds1 ost1; do
16166                 local facet_ver=$(lustre_version_code $facet)
16167                 if [ $facet_ver -ge $(version_code 2.7.65) ]; then
16168                         do_facet $facet "$LCTL get_param -R '*'" &> /dev/null
16169                 else
16170                         log "$facet: too old lustre for get_param -R"
16171                 fi
16172                 if [ $facet_ver -ge $(version_code 2.5.54) ]; then
16173                         do_facet $facet "$LCTL list_param -FR '*' | grep '=' |
16174                                 tr -d = | egrep -v $skipped_params |
16175                                 xargs -n 1 find $proc_dirs_str -name |
16176                                 xargs -n 1 badarea_io" ||
16177                                         error "$facet badarea_io failed"
16178                 else
16179                         skip_noexit "$facet: too old lustre for get_param -R"
16180                 fi
16181         done
16182
16183         # remount the FS in case writes/reads /proc break the FS
16184         cleanup || error "failed to unmount"
16185         setup || error "failed to setup"
16186 }
16187 run_test 133g "Check reads/writes of server lustre proc files with bad area io"
16188
16189 test_133h() {
16190         remote_mds_nodsh && skip "remote MDS with nodsh"
16191         remote_ost_nodsh && skip "remote OST with nodsh"
16192         [[ $MDS1_VERSION -lt $(version_code 2.9.54) ]] &&
16193                 skip "Need MDS version at least 2.9.54"
16194
16195         local facet
16196         for facet in client mds1 ost1; do
16197                 # Get the list of files that are missing the terminating newline
16198                 local plist=$(do_facet $facet
16199                         $LCTL list_param -FR '*' | grep '=' | tr -d =)
16200                 local ent
16201                 for ent in $plist; do
16202                         local missing=$(do_facet $facet $LCTL get_param $ent \|\
16203                                 awk -v FS='\v' -v RS='\v\v' \
16204                                 "'END { if(NR>0 && \\\$NF !~ /.*\\\n\$/) \
16205                                         print FILENAME}'" 2>/dev/null)
16206                         [ -z $missing ] || {
16207                                 do_facet $facet $LCTL get_param $ent | od -An -tx1
16208                                 error "file does not end with newline: $facet-$ent"
16209                         }
16210                 done
16211         done
16212 }
16213 run_test 133h "Proc files should end with newlines"
16214
16215 test_134a() {
16216         remote_mds_nodsh && skip "remote MDS with nodsh"
16217         [[ $MDS1_VERSION -lt $(version_code 2.7.54) ]] &&
16218                 skip "Need MDS version at least 2.7.54"
16219
16220         mkdir_on_mdt0 $DIR/$tdir || error "failed to create $DIR/$tdir"
16221         cancel_lru_locks mdc
16222
16223         local nsdir="ldlm.namespaces.*-MDT0000-mdc-*"
16224         local unused=$($LCTL get_param -n $nsdir.lock_unused_count)
16225         [ $unused -eq 0 ] || error "$unused locks are not cleared"
16226
16227         local nr=1000
16228         createmany -o $DIR/$tdir/f $nr ||
16229                 error "failed to create $nr files in $DIR/$tdir"
16230         unused=$($LCTL get_param -n $nsdir.lock_unused_count)
16231
16232         #define OBD_FAIL_LDLM_WATERMARK_LOW     0x327
16233         do_facet mds1 $LCTL set_param fail_loc=0x327
16234         do_facet mds1 $LCTL set_param fail_val=500
16235         touch $DIR/$tdir/m
16236
16237         echo "sleep 10 seconds ..."
16238         sleep 10
16239         local lck_cnt=$($LCTL get_param -n $nsdir.lock_unused_count)
16240
16241         do_facet mds1 $LCTL set_param fail_loc=0
16242         do_facet mds1 $LCTL set_param fail_val=0
16243         [ $lck_cnt -lt $unused ] ||
16244                 error "No locks reclaimed, before:$unused, after:$lck_cnt"
16245
16246         rm $DIR/$tdir/m
16247         unlinkmany $DIR/$tdir/f $nr
16248 }
16249 run_test 134a "Server reclaims locks when reaching lock_reclaim_threshold"
16250
16251 test_134b() {
16252         remote_mds_nodsh && skip "remote MDS with nodsh"
16253         [[ $MDS1_VERSION -lt $(version_code 2.7.54) ]] &&
16254                 skip "Need MDS version at least 2.7.54"
16255
16256         mkdir_on_mdt0 $DIR/$tdir || error "failed to create $DIR/$tdir"
16257         cancel_lru_locks mdc
16258
16259         local low_wm=$(do_facet mds1 $LCTL get_param -n \
16260                         ldlm.lock_reclaim_threshold_mb)
16261         # disable reclaim temporarily
16262         do_facet mds1 $LCTL set_param ldlm.lock_reclaim_threshold_mb=0
16263
16264         #define OBD_FAIL_LDLM_WATERMARK_HIGH     0x328
16265         do_facet mds1 $LCTL set_param fail_loc=0x328
16266         do_facet mds1 $LCTL set_param fail_val=500
16267
16268         $LCTL set_param debug=+trace
16269
16270         local nr=600
16271         createmany -o $DIR/$tdir/f $nr &
16272         local create_pid=$!
16273
16274         echo "Sleep $TIMEOUT seconds ..."
16275         sleep $TIMEOUT
16276         if ! ps -p $create_pid  > /dev/null 2>&1; then
16277                 do_facet mds1 $LCTL set_param fail_loc=0
16278                 do_facet mds1 $LCTL set_param fail_val=0
16279                 do_facet mds1 $LCTL set_param \
16280                         ldlm.lock_reclaim_threshold_mb=${low_wm}m
16281                 error "createmany finished incorrectly!"
16282         fi
16283         do_facet mds1 $LCTL set_param fail_loc=0
16284         do_facet mds1 $LCTL set_param fail_val=0
16285         do_facet mds1 $LCTL set_param ldlm.lock_reclaim_threshold_mb=${low_wm}m
16286         wait $create_pid || return 1
16287
16288         unlinkmany $DIR/$tdir/f $nr
16289 }
16290 run_test 134b "Server rejects lock request when reaching lock_limit_mb"
16291
16292 test_135() {
16293         remote_mds_nodsh && skip "remote MDS with nodsh"
16294         [[ $MDS1_VERSION -lt $(version_code 2.13.50) ]] &&
16295                 skip "Need MDS version at least 2.13.50"
16296         local fname
16297
16298         mkdir -p $DIR/$tdir || error "failed to create $DIR/$tdir"
16299
16300 #define OBD_FAIL_PLAIN_RECORDS 0x1319
16301         #set only one record at plain llog
16302         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1319 fail_val=1
16303
16304         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
16305
16306         #fill already existed plain llog each 64767
16307         #wrapping whole catalog
16308         createmany -o -u $DIR/$tdir/$tfile- $((64767 * 1))
16309
16310         createmany -o $DIR/$tdir/$tfile_ 64700
16311         for (( i = 0; i < 64700; i = i + 2 ))
16312         do
16313                 rm $DIR/$tdir/$tfile_$i &
16314                 rm $DIR/$tdir/$tfile_$((i + 1)) &
16315                 local pid=$!
16316                 wait $pid
16317         done
16318
16319         #waiting osp synchronization
16320         wait_delete_completed
16321 }
16322 run_test 135 "Race catalog processing"
16323
16324 test_136() {
16325         remote_mds_nodsh && skip "remote MDS with nodsh"
16326         [[ $MDS1_VERSION -lt $(version_code 2.13.50) ]] &&
16327                 skip "Need MDS version at least 2.13.50"
16328         local fname
16329
16330         mkdir -p $DIR/$tdir || error "failed to create $DIR/$tdir"
16331         $LFS setstripe -c 1 -i 0 $DIR/$tdir || error "failed to set striping"
16332         #set only one record at plain llog
16333 #define OBD_FAIL_CATALOG_FULL_CHECK                0x131a
16334         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x131a fail_val=1
16335
16336         ost_set_temp_seq_width_all $DATA_SEQ_MAX_WIDTH
16337
16338         #fill already existed 2 plain llogs each 64767
16339         #wrapping whole catalog
16340         createmany -o -u $DIR/$tdir/$tfile- $((64767 * 1))
16341         createmany -o -u $DIR/$tdir/$tfile- $((64767 * 3 / 2))
16342         wait_delete_completed
16343
16344         createmany -o $DIR/$tdir/$tfile_ 10
16345         sleep 25
16346
16347         do_facet $SINGLEMDS $LCTL set_param fail_val=3
16348         for (( i = 0; i < 10; i = i + 3 ))
16349         do
16350                 rm $DIR/$tdir/$tfile_$i &
16351                 rm $DIR/$tdir/$tfile_$((i + 1)) &
16352                 local pid=$!
16353                 wait $pid
16354                 sleep 7
16355                 rm $DIR/$tdir/$tfile_$((i + 2)) &
16356         done
16357
16358         #waiting osp synchronization
16359         wait_delete_completed
16360 }
16361 run_test 136 "Race catalog processing 2"
16362
16363 test_140() { #bug-17379
16364         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16365
16366         test_mkdir $DIR/$tdir
16367         cd $DIR/$tdir || error "Changing to $DIR/$tdir"
16368         cp $(which stat) . || error "Copying stat to $DIR/$tdir"
16369
16370         # VFS limits max symlink depth to 5(4KSTACK) or 7(8KSTACK) or 8
16371         # For kernel > 3.5, bellow only tests consecutive symlink (MAX 40)
16372         local i=0
16373         while i=$((i + 1)); do
16374                 test_mkdir $i
16375                 cd $i || error "Changing to $i"
16376                 ln -s ../stat stat || error "Creating stat symlink"
16377                 # Read the symlink until ELOOP present,
16378                 # not LBUGing the system is considered success,
16379                 # we didn't overrun the stack.
16380                 $OPENFILE -f O_RDONLY stat >/dev/null 2>&1; ret=$?
16381                 if [ $ret -ne 0 ]; then
16382                         if [ $ret -eq 40 ]; then
16383                                 break  # -ELOOP
16384                         else
16385                                 error "Open stat symlink"
16386                                         return
16387                         fi
16388                 fi
16389         done
16390         i=$((i - 1))
16391         echo "The symlink depth = $i"
16392         [ $i -eq 5 ] || [ $i -eq 7 ] || [ $i -eq 8 ] || [ $i -eq 40 ] ||
16393                 error "Invalid symlink depth"
16394
16395         # Test recursive symlink
16396         ln -s symlink_self symlink_self
16397         $OPENFILE -f O_RDONLY symlink_self >/dev/null 2>&1; ret=$?
16398         echo "open symlink_self returns $ret"
16399         [ $ret -eq 40 ] || error "recursive symlink doesn't return -ELOOP"
16400 }
16401 run_test 140 "Check reasonable stack depth (shouldn't LBUG) ===="
16402
16403 test_150a() {
16404         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16405
16406         local TF="$TMP/$tfile"
16407
16408         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16409         dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
16410         cp $TF $DIR/$tfile
16411         cancel_lru_locks $OSC
16412         cmp $TF $DIR/$tfile || error "$TMP/$tfile $DIR/$tfile differ"
16413         remount_client $MOUNT
16414         df -P $MOUNT
16415         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (remount)"
16416
16417         $TRUNCATE $TF 6000
16418         $TRUNCATE $DIR/$tfile 6000
16419         cancel_lru_locks $OSC
16420         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (truncate1)"
16421
16422         echo "12345" >>$TF
16423         echo "12345" >>$DIR/$tfile
16424         cancel_lru_locks $OSC
16425         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append1)"
16426
16427         echo "12345" >>$TF
16428         echo "12345" >>$DIR/$tfile
16429         cancel_lru_locks $OSC
16430         cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append2)"
16431 }
16432 run_test 150a "truncate/append tests"
16433
16434 test_150b() {
16435         check_set_fallocate_or_skip
16436         local out
16437
16438         touch $DIR/$tfile
16439         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16440         out=$(check_fallocate $DIR/$tfile 2>&1) ||
16441                 skip_eopnotsupp "$out|check_fallocate failed"
16442 }
16443 run_test 150b "Verify fallocate (prealloc) functionality"
16444
16445 test_150bb() {
16446         check_set_fallocate_or_skip
16447
16448         touch $DIR/$tfile
16449         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16450         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=20 || error "dd failed"
16451         > $DIR/$tfile
16452         fallocate -l $((1048576 * 20)) $DIR/$tfile || error "fallocate failed"
16453         # precomputed md5sum for 20MB of zeroes
16454         local expect="8f4e33f3dc3e414ff94e5fb6905cba8c"
16455         local sum=($(md5sum $DIR/$tfile))
16456
16457         [[ "${sum[0]}" == "$expect" ]] || error "fallocate unwritten is not zero"
16458
16459         check_set_fallocate 1
16460
16461         > $DIR/$tfile
16462         fallocate -l $((1048576 * 20)) $DIR/$tfile || error "fallocate failed"
16463         sum=($(md5sum $DIR/$tfile))
16464
16465         [[ "${sum[0]}" == "$expect" ]] || error "fallocate zero is not zero"
16466 }
16467 run_test 150bb "Verify fallocate modes both zero space"
16468
16469 test_150c() {
16470         check_set_fallocate_or_skip
16471         local striping="-c2"
16472
16473         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16474         $LFS setstripe -c $OSTCOUNT -S1M $DIR/$tfile || error "setstripe failed"
16475         fallocate -l ${OSTCOUNT}m $DIR/$tfile || error "fallocate failed"
16476         local bytes=$(($(stat -c '%b * %B' $DIR/$tfile)))
16477         local want=$((OSTCOUNT * 1048576))
16478
16479         # Must allocate all requested space, not more than 5% extra
16480         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
16481                 error "bytes $bytes is not $want"
16482
16483         rm -f $DIR/$tfile
16484
16485         echo "verify fallocate on PFL file"
16486
16487         [[ "x$DOM" == "xyes" ]] && striping="-L mdt"
16488
16489         $LFS setstripe -E1M $striping -E16M -c3 -Eeof -c 4 $DIR/$tfile ||
16490                 error "Create $DIR/$tfile failed"
16491         fallocate -l $((1048576 * 512)) $DIR/$tfile || error "fallocate failed"
16492         bytes=$(($(stat -c '%b * %B' $DIR/$tfile)))
16493         want=$((512 * 1048576))
16494
16495         # Must allocate all requested space, not more than 5% extra
16496         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
16497                 error "bytes $bytes is not $want"
16498 }
16499 run_test 150c "Verify fallocate Size and Blocks"
16500
16501 test_150d() {
16502         check_set_fallocate_or_skip
16503         local striping="-c2"
16504
16505         [[ "x$DOM" == "xyes" ]] && striping="-L mdt"
16506
16507         stack_trap "rm -f $DIR/$tdir; wait_delete_completed"
16508         $LFS setstripe -E1M $striping -E eof -c $OSTCOUNT -S1M $DIR/$tdir ||
16509                 error "setstripe failed"
16510         fallocate -o 1G -l ${OSTCOUNT}m $DIR/$tdir || error "fallocate failed"
16511         local bytes=$(($(stat -c '%b * %B' $DIR/$tdir)))
16512         local want=$((OSTCOUNT * 1048576))
16513
16514         # Must allocate all requested space, not more than 5% extra
16515         (( $bytes >= $want && $bytes < $want * 105 / 100 )) ||
16516                 error "bytes $bytes is not $want"
16517 }
16518 run_test 150d "Verify fallocate Size and Blocks - Non zero start"
16519
16520 test_150e() {
16521         check_set_fallocate_or_skip
16522
16523         echo "df before:"
16524         $LFS df
16525         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16526         $LFS setstripe -c${OSTCOUNT} $DIR/$tfile ||
16527                 error "$LFS setstripe -c${OSTCOUNT} $DIR/$tfile failed"
16528
16529         # Find OST with Minimum Size
16530         min_size_ost=$($LFS df | awk "/$FSNAME-OST/ { print \$4 }" |
16531                        sort -un | head -1)
16532
16533         # Get 100MB per OST of the available space to reduce run time
16534         # else 60% of the available space if we are running SLOW tests
16535         if [ $SLOW == "no" ]; then
16536                 local space=$((1024 * 100 * OSTCOUNT))
16537         else
16538                 local space=$(((min_size_ost * 60)/100 * OSTCOUNT))
16539         fi
16540
16541         fallocate -l${space}k $DIR/$tfile ||
16542                 error "fallocate ${space}k $DIR/$tfile failed"
16543         echo "'fallocate -l ${space}k $DIR/$tfile' succeeded"
16544
16545         # get size immediately after fallocate. This should be correctly
16546         # updated
16547         local size=$(stat -c '%s' $DIR/$tfile)
16548         local used=$(( $(stat -c '%b * %B' $DIR/$tfile) / 1024))
16549
16550         # Sleep for a while for statfs to get updated. And not pull from cache.
16551         sleep 2
16552
16553         echo "df after fallocate:"
16554         $LFS df
16555
16556         (( size / 1024 == space )) || error "size $size != requested $space"
16557         [ "$ost1_FSTYPE" != ldiskfs ] || (( used >= space )) ||
16558                 error "used $used < space $space"
16559
16560         rm $DIR/$tfile || error "rm failed"
16561         sync
16562         wait_delete_completed
16563
16564         echo "df after unlink:"
16565         $LFS df
16566 }
16567 run_test 150e "Verify 60% of available OST space consumed by fallocate"
16568
16569 test_150f() {
16570         local size
16571         local blocks
16572         local want_size_before=20480 # in bytes
16573         local want_blocks_before=40 # 512 sized blocks
16574         local want_blocks_after=24  # 512 sized blocks
16575         local length=$(((want_blocks_before - want_blocks_after) * 512))
16576
16577         [[ $OST1_VERSION -ge $(version_code 2.14.0) ]] ||
16578                 skip "need at least 2.14.0 for fallocate punch"
16579
16580         if [ "$ost1_FSTYPE" = "zfs" ] || [ "$mds1_FSTYPE" = "zfs" ]; then
16581                 skip "LU-14160: punch mode is not implemented on OSD ZFS"
16582         fi
16583
16584         check_set_fallocate_or_skip
16585         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16586
16587         [[ "x$DOM" == "xyes" ]] &&
16588                 $LFS setstripe -E1M -L mdt -E eof $DIR/$tfile
16589
16590         echo "Verify fallocate punch: Range within the file range"
16591         yes 'A' | dd of=$DIR/$tfile bs=4096 count=5 ||
16592                 error "dd failed for bs 4096 and count 5"
16593
16594         # Call fallocate with punch range which is within the file range
16595         out=$(fallocate -p --offset 4096 -l $length $DIR/$tfile 2>&1) ||
16596                 skip_eopnotsupp "$out|fallocate: offset 4096 and length $length"
16597         # client must see changes immediately after fallocate
16598         size=$(stat -c '%s' $DIR/$tfile)
16599         blocks=$(stat -c '%b' $DIR/$tfile)
16600
16601         # Verify punch worked.
16602         (( blocks == want_blocks_after )) ||
16603                 error "punch failed: blocks $blocks != $want_blocks_after"
16604
16605         (( size == want_size_before )) ||
16606                 error "punch failed: size $size != $want_size_before"
16607
16608         # Verify there is hole in file
16609         local data_off=$(lseek_test -d 4096 $DIR/$tfile)
16610         # precomputed md5sum
16611         local expect="4a9a834a2db02452929c0a348273b4aa"
16612
16613         cksum=($(md5sum $DIR/$tfile))
16614         [[ "${cksum[0]}" == "$expect" ]] ||
16615                 error "unexpected MD5SUM after punch: ${cksum[0]}"
16616
16617         # Start second sub-case for fallocate punch.
16618         echo "Verify fallocate punch: Range overlapping and less than blocksize"
16619         yes 'A' | dd of=$DIR/$tfile bs=4096 count=5 ||
16620                 error "dd failed for bs 4096 and count 5"
16621
16622         # Punch range less than block size will have no change in block count
16623         want_blocks_after=40  # 512 sized blocks
16624
16625         # Punch overlaps two blocks and less than blocksize
16626         out=$(fallocate -p --offset 4000 -l 3000 $DIR/$tfile 2>&1) ||
16627                 skip_eopnotsupp "$out|fallocate: offset 4000 length 3000"
16628         size=$(stat -c '%s' $DIR/$tfile)
16629         blocks=$(stat -c '%b' $DIR/$tfile)
16630
16631         # Verify punch worked.
16632         (( blocks == want_blocks_after )) ||
16633                 error "punch failed: blocks $blocks != $want_blocks_after"
16634
16635         (( size == want_size_before )) ||
16636                 error "punch failed: size $size != $want_size_before"
16637
16638         # Verify if range is really zero'ed out. We expect Zeros.
16639         # precomputed md5sum
16640         expect="c57ec5d769c3dbe3426edc3f7d7e11d3"
16641         cksum=($(md5sum $DIR/$tfile))
16642         [[ "${cksum[0]}" == "$expect" ]] ||
16643                 error "unexpected MD5SUM after punch: ${cksum[0]}"
16644 }
16645 run_test 150f "Verify fallocate punch functionality"
16646
16647 test_150g() {
16648         local space
16649         local size
16650         local blocks
16651         local blocks_after
16652         local size_after
16653         local BS=4096 # Block size in bytes
16654
16655         [[ $OST1_VERSION -ge $(version_code 2.14.0) ]] ||
16656                 skip "need at least 2.14.0 for fallocate punch"
16657
16658         if [ "$ost1_FSTYPE" = "zfs" ] || [ "$mds1_FSTYPE" = "zfs" ]; then
16659                 skip "LU-14160: punch mode is not implemented on OSD ZFS"
16660         fi
16661
16662         check_set_fallocate_or_skip
16663         stack_trap "rm -f $DIR/$tfile; wait_delete_completed"
16664
16665         if [[ "x$DOM" == "xyes" ]]; then
16666                 $LFS setstripe -E2M -L mdt -E eof -c${OSTCOUNT} $DIR/$tfile ||
16667                         error "$LFS setstripe DoM + ${OSTCOUNT} OST failed"
16668         else
16669                 $LFS setstripe -c${OSTCOUNT} $DIR/$tfile ||
16670                         error "$LFS setstripe -c${OSTCOUNT} $DIR/$tfile failed"
16671         fi
16672
16673         # Get 100MB per OST of the available space to reduce run time
16674         # else 60% of the available space if we are running SLOW tests
16675         if [ $SLOW == "no" ]; then
16676                 space=$((1024 * 100 * OSTCOUNT))
16677         else
16678                 # Find OST with Minimum Size
16679                 space=$($LFS df | awk "/$FSNAME-OST/ { print \$4 }" |
16680                         sort -un | head -1)
16681                 echo "min size OST: $space"
16682                 space=$(((space * 60)/100 * OSTCOUNT))
16683         fi
16684         # space in 1k units, round to 4k blocks
16685         local blkcount=$((space * 1024 / $BS))
16686
16687         echo "Verify fallocate punch: Very large Range"
16688         fallocate -l${space}k $DIR/$tfile ||
16689                 error "fallocate ${space}k $DIR/$tfile failed"
16690         # write 1M at the end, start and in the middle
16691         yes 'A' | dd of=$DIR/$tfile bs=$BS count=256 ||
16692                 error "dd failed: bs $BS count 256"
16693         yes 'A' | dd of=$DIR/$tfile bs=$BS seek=$((blkcount - 256)) count=256 ||
16694                 error "dd failed: bs $BS count 256 seek $((blkcount - 256))"
16695         yes 'A' | dd of=$DIR/$tfile bs=$BS seek=$((blkcount / 2)) count=1024 ||
16696                 error "dd failed: bs $BS count 256 seek $((blkcount / 2))"
16697
16698         # Gather stats.
16699         size=$(stat -c '%s' $DIR/$tfile)
16700
16701         # gather punch length.
16702         local punch_size=$((size - (BS * 2)))
16703
16704         echo "punch_size = $punch_size"
16705         echo "size - punch_size: $((size - punch_size))"
16706         echo "size - punch_size in blocks: $(((size - punch_size)/BS))"
16707
16708         # Call fallocate to punch all except 2 blocks. We leave the
16709         # first and the last block
16710         echo "fallocate -p --offset $BS -l $punch_size $DIR/$tfile"
16711         out=$(fallocate -p --offset $BS -l $punch_size $DIR/$tfile 2>&1) ||
16712                 skip_eopnotsupp "$out|fallocate: offset $BS length $punch_size"
16713
16714         size_after=$(stat -c '%s' $DIR/$tfile)
16715         blocks_after=$(stat -c '%b' $DIR/$tfile)
16716
16717         # Verify punch worked.
16718         # Size should be kept
16719         (( size == size_after )) ||
16720                 error "punch failed: size $size != $size_after"
16721
16722         # two 4k data blocks to remain plus possible 1 extra extent block
16723         (( blocks_after <= ((BS / 512) * 3) )) ||
16724                 error "too many blocks remains: $blocks_after"
16725
16726         # Verify that file has hole between the first and the last blocks
16727         local hole_start=$(lseek_test -l 0 $DIR/$tfile)
16728         local hole_end=$(lseek_test -d $BS $DIR/$tfile)
16729
16730         echo "Hole at [$hole_start, $hole_end)"
16731         (( hole_start == BS )) ||
16732                 error "no hole at offset $BS after punch"
16733
16734         (( hole_end == BS + punch_size )) ||
16735                 error "data at offset $hole_end < $((BS + punch_size))"
16736 }
16737 run_test 150g "Verify fallocate punch on large range"
16738
16739 test_150h() {
16740         local file=$DIR/$tfile
16741         local size
16742
16743         check_set_fallocate_or_skip
16744         statx_supported || skip_env "Test must be statx() syscall supported"
16745
16746         # fallocate() does not update the size information on the MDT
16747         fallocate -l 16K $file || error "failed to fallocate $file"
16748         cancel_lru_locks $OSC
16749         # STATX with cached-always mode will not send glimpse RPCs to OST,
16750         # it uses the caching attrs on the client side as much as possible.
16751         size=$($STATX --cached=always -c %s $file)
16752         [ $size == 16384 ] ||
16753                 error "size after fallocate() is $size, expected 16384"
16754 }
16755 run_test 150h "Verify extend fallocate updates the file size"
16756
16757 #LU-2902 roc_hit was not able to read all values from lproc
16758 function roc_hit_init() {
16759         local list=$(comma_list $(osts_nodes))
16760         local dir=$DIR/$tdir-check
16761         local file=$dir/$tfile
16762         local BEFORE
16763         local AFTER
16764         local idx
16765
16766         test_mkdir $dir
16767         #use setstripe to do a write to every ost
16768         for i in $(seq 0 $((OSTCOUNT-1))); do
16769                 $LFS setstripe -c 1 -i $i $dir || error "$LFS setstripe $file failed"
16770                 dd if=/dev/urandom of=$file bs=4k count=4 2>&1 > /dev/null
16771                 idx=$(printf %04x $i)
16772                 BEFORE=$(get_osd_param $list *OST*$idx stats |
16773                         awk '$1 == "cache_access" {sum += $7}
16774                                 END { printf("%0.0f", sum) }')
16775
16776                 cancel_lru_locks osc
16777                 cat $file >/dev/null
16778
16779                 AFTER=$(get_osd_param $list *OST*$idx stats |
16780                         awk '$1 == "cache_access" {sum += $7}
16781                                 END { printf("%0.0f", sum) }')
16782
16783                 echo BEFORE:$BEFORE AFTER:$AFTER
16784                 if ! let "AFTER - BEFORE == 4"; then
16785                         rm -rf $dir
16786                         error "roc_hit is not safe to use"
16787                 fi
16788                 rm $file
16789         done
16790
16791         rm -rf $dir
16792 }
16793
16794 function roc_hit() {
16795         local list=$(comma_list $(osts_nodes))
16796         echo $(get_osd_param $list '' stats |
16797                 awk '$1 == "cache_hit" {sum += $7}
16798                         END { printf("%0.0f", sum) }')
16799 }
16800
16801 function set_cache() {
16802         local on=1
16803
16804         if [ "$2" == "off" ]; then
16805                 on=0;
16806         fi
16807         local list=$(comma_list $(osts_nodes))
16808         set_osd_param $list '' $1_cache_enable $on
16809
16810         cancel_lru_locks osc
16811 }
16812
16813 test_151() {
16814         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16815         remote_ost_nodsh && skip "remote OST with nodsh"
16816         (( CLIENT_VERSION == OST1_VERSION )) ||
16817                 skip "LU-13081: no interop testing for OSS cache"
16818
16819         local CPAGES=3
16820         local list=$(comma_list $(osts_nodes))
16821
16822         # check whether obdfilter is cache capable at all
16823         if ! get_osd_param $list '' read_cache_enable >/dev/null; then
16824                 skip "not cache-capable obdfilter"
16825         fi
16826
16827         # check cache is enabled on all obdfilters
16828         if get_osd_param $list '' read_cache_enable | grep 0; then
16829                 skip "oss cache is disabled"
16830         fi
16831
16832         set_osd_param $list '' writethrough_cache_enable 1
16833
16834         # check write cache is enabled on all obdfilters
16835         if get_osd_param $list '' writethrough_cache_enable | grep 0; then
16836                 skip "oss write cache is NOT enabled"
16837         fi
16838
16839         roc_hit_init
16840
16841         #define OBD_FAIL_OBD_NO_LRU  0x609
16842         do_nodes $list $LCTL set_param fail_loc=0x609
16843
16844         # pages should be in the case right after write
16845         dd if=/dev/urandom of=$DIR/$tfile bs=4k count=$CPAGES ||
16846                 error "dd failed"
16847
16848         local BEFORE=$(roc_hit)
16849         cancel_lru_locks osc
16850         cat $DIR/$tfile >/dev/null
16851         local AFTER=$(roc_hit)
16852
16853         do_nodes $list $LCTL set_param fail_loc=0
16854
16855         if ! let "AFTER - BEFORE == CPAGES"; then
16856                 error "NOT IN CACHE: before: $BEFORE, after: $AFTER"
16857         fi
16858
16859         cancel_lru_locks osc
16860         # invalidates OST cache
16861         do_nodes $list "echo 1 > /proc/sys/vm/drop_caches"
16862         set_osd_param $list '' read_cache_enable 0
16863         cat $DIR/$tfile >/dev/null
16864
16865         # now data shouldn't be found in the cache
16866         BEFORE=$(roc_hit)
16867         cancel_lru_locks osc
16868         cat $DIR/$tfile >/dev/null
16869         AFTER=$(roc_hit)
16870         if let "AFTER - BEFORE != 0"; then
16871                 error "IN CACHE: before: $BEFORE, after: $AFTER"
16872         fi
16873
16874         set_osd_param $list '' read_cache_enable 1
16875         rm -f $DIR/$tfile
16876 }
16877 run_test 151 "test cache on oss and controls ==============================="
16878
16879 test_152() {
16880         [ $PARALLEL == "yes" ] && skip "skip parallel run"
16881
16882         local TF="$TMP/$tfile"
16883
16884         # simulate ENOMEM during write
16885 #define OBD_FAIL_OST_NOMEM      0x226
16886         lctl set_param fail_loc=0x80000226
16887         dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
16888         cp $TF $DIR/$tfile
16889         sync || error "sync failed"
16890         lctl set_param fail_loc=0
16891
16892         # discard client's cache
16893         cancel_lru_locks osc
16894
16895         # simulate ENOMEM during read
16896         lctl set_param fail_loc=0x80000226
16897         cmp $TF $DIR/$tfile || error "cmp failed"
16898         lctl set_param fail_loc=0
16899
16900         rm -f $TF
16901 }
16902 run_test 152 "test read/write with enomem ============================"
16903
16904 test_153() {
16905         $MULTIOP $DIR/$tfile Ow4096Ycu || error "multiop failed"
16906 }
16907 run_test 153 "test if fdatasync does not crash ======================="
16908
16909 dot_lustre_fid_permission_check() {
16910         local fid=$1
16911         local ffid=$MOUNT/.lustre/fid/$fid
16912         local test_dir=$2
16913
16914         echo "stat fid $fid"
16915         stat $ffid || error "stat $ffid failed."
16916         echo "touch fid $fid"
16917         touch $ffid || error "touch $ffid failed."
16918         echo "write to fid $fid"
16919         cat /etc/hosts > $ffid || error "write $ffid failed."
16920         echo "read fid $fid"
16921         diff /etc/hosts $ffid || error "read $ffid failed."
16922         echo "append write to fid $fid"
16923         cat /etc/hosts >> $ffid || error "append write $ffid failed."
16924         echo "rename fid $fid"
16925         mv $ffid $test_dir/$tfile.1 &&
16926                 error "rename $ffid to $tfile.1 should fail."
16927         touch $test_dir/$tfile.1
16928         mv $test_dir/$tfile.1 $ffid &&
16929                 error "rename $tfile.1 to $ffid should fail."
16930         rm -f $test_dir/$tfile.1
16931         echo "truncate fid $fid"
16932         $TRUNCATE $ffid 777 || error "truncate $ffid failed."
16933         echo "link fid $fid"
16934         ln -f $ffid $test_dir/tfile.lnk || error "link $ffid failed."
16935         if [[ $($LCTL get_param -n mdc.*-mdc-*.connect_flags) =~ acl ]]; then
16936                 id $USER0 || skip_env "missing user $USER0"
16937                 echo "setfacl fid $fid"
16938                 setfacl -R -m u:$USER0:rwx $ffid ||
16939                         error "setfacl $ffid failed"
16940                 echo "getfacl fid $fid"
16941                 getfacl $ffid || error "getfacl $ffid failed."
16942         fi
16943         echo "unlink fid $fid"
16944         unlink $MOUNT/.lustre/fid/$fid && error "unlink $ffid should fail."
16945         echo "mknod fid $fid"
16946         mknod $ffid c 1 3 && error "mknod $ffid should fail."
16947
16948         fid=[0xf00000400:0x1:0x0]
16949         ffid=$MOUNT/.lustre/fid/$fid
16950
16951         echo "stat non-exist fid $fid"
16952         stat $ffid > /dev/null && error "stat non-exist $ffid should fail."
16953         echo "write to non-exist fid $fid"
16954         cat /etc/hosts > $ffid && error "write non-exist $ffid should fail."
16955         echo "link new fid $fid"
16956         ln $test_dir/$tfile $ffid && error "link $ffid should fail."
16957
16958         mkdir -p $test_dir/$tdir
16959         touch $test_dir/$tdir/$tfile
16960         fid=$($LFS path2fid $test_dir/$tdir)
16961         rc=$?
16962         [ $rc -ne 0 ] &&
16963                 error "error: could not get fid for $test_dir/$dir/$tfile."
16964
16965         ffid=$MOUNT/.lustre/fid/$fid
16966
16967         echo "ls $fid"
16968         ls $ffid || error "ls $ffid failed."
16969         echo "touch $fid/$tfile.1"
16970         touch $ffid/$tfile.1 || error "touch $ffid/$tfile.1 failed."
16971
16972         echo "touch $MOUNT/.lustre/fid/$tfile"
16973         touch $MOUNT/.lustre/fid/$tfile && \
16974                 error "touch $MOUNT/.lustre/fid/$tfile should fail."
16975
16976         echo "setxattr to $MOUNT/.lustre/fid"
16977         setfattr -n trusted.name1 -v value1 $MOUNT/.lustre/fid
16978
16979         echo "listxattr for $MOUNT/.lustre/fid"
16980         getfattr -d -m "^trusted" $MOUNT/.lustre/fid
16981
16982         echo "delxattr from $MOUNT/.lustre/fid"
16983         setfattr -x trusted.name1 $MOUNT/.lustre/fid
16984
16985         echo "touch invalid fid: $MOUNT/.lustre/fid/[0x200000400:0x2:0x3]"
16986         touch $MOUNT/.lustre/fid/[0x200000400:0x2:0x3] &&
16987                 error "touch invalid fid should fail."
16988
16989         echo "touch non-normal fid: $MOUNT/.lustre/fid/[0x1:0x2:0x0]"
16990         touch $MOUNT/.lustre/fid/[0x1:0x2:0x0] &&
16991                 error "touch non-normal fid should fail."
16992
16993         echo "rename $tdir to $MOUNT/.lustre/fid"
16994         mrename $test_dir/$tdir $MOUNT/.lustre/fid &&
16995                 error "rename to $MOUNT/.lustre/fid should fail."
16996
16997         if [ $MDS1_VERSION -ge $(version_code 2.3.51) ]
16998         then            # LU-3547
16999                 local old_obf_mode=$(stat --format="%a" $DIR/.lustre/fid)
17000                 local new_obf_mode=777
17001
17002                 echo "change mode of $DIR/.lustre/fid to $new_obf_mode"
17003                 chmod $new_obf_mode $DIR/.lustre/fid ||
17004                         error "chmod $new_obf_mode $DIR/.lustre/fid failed"
17005
17006                 local obf_mode=$(stat --format=%a $DIR/.lustre/fid)
17007                 [ $obf_mode -eq $new_obf_mode ] ||
17008                         error "stat $DIR/.lustre/fid returned wrong mode $obf_mode"
17009
17010                 echo "restore mode of $DIR/.lustre/fid to $old_obf_mode"
17011                 chmod $old_obf_mode $DIR/.lustre/fid ||
17012                         error "chmod $old_obf_mode $DIR/.lustre/fid failed"
17013         fi
17014
17015         $OPENFILE -f O_LOV_DELAY_CREATE:O_CREAT $test_dir/$tfile-2
17016         fid=$($LFS path2fid $test_dir/$tfile-2)
17017
17018         if [ $MDS1_VERSION -ge $(version_code 2.6.50) ]
17019         then # LU-5424
17020                 echo "cp /etc/passwd $MOUNT/.lustre/fid/$fid"
17021                 cp /etc/passwd $MOUNT/.lustre/fid/$fid ||
17022                         error "create lov data thru .lustre failed"
17023         fi
17024         echo "cp /etc/passwd $test_dir/$tfile-2"
17025         cp /etc/passwd $test_dir/$tfile-2 ||
17026                 error "copy to $test_dir/$tfile-2 failed."
17027         echo "diff /etc/passwd $MOUNT/.lustre/fid/$fid"
17028         diff /etc/passwd $MOUNT/.lustre/fid/$fid ||
17029                 error "diff /etc/passwd $MOUNT/.lustre/fid/$fid failed."
17030
17031         rm -rf $test_dir/tfile.lnk
17032         rm -rf $test_dir/$tfile-2
17033 }
17034
17035 test_154A() {
17036         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
17037                 skip "Need MDS version at least 2.4.1"
17038
17039         local tf=$DIR/$tfile
17040         touch $tf
17041
17042         local fid=$($LFS path2fid $tf)
17043         [ -z "$fid" ] && error "path2fid unable to get $tf FID"
17044
17045         # check that we get the same pathname back
17046         local rootpath
17047         local found
17048         for rootpath in "$MOUNT" "$MOUNT///" "$MOUNT/$tfile"; do
17049                 echo "$rootpath $fid"
17050                 found=$($LFS fid2path $rootpath "$fid")
17051                 [ -z "$found" ] && error "fid2path unable to get '$fid' path"
17052                 [ "$found" == "$tf" ] || error "fid2path $found != $tf"
17053         done
17054
17055         # check wrong root path format
17056         rootpath=$MOUNT"_wrong"
17057         found=$($LFS fid2path $rootpath "$fid")
17058         [ -z "$found" ] || error "should fail ($rootpath != $MOUNT)"
17059 }
17060 run_test 154A "lfs path2fid and fid2path basic checks"
17061
17062 test_154B() {
17063         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
17064                 skip "Need MDS version at least 2.4.1"
17065
17066         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
17067         touch $DIR/$tdir/$tfile || error "touch $DIR/$tdir/$tfile failed"
17068         local linkea=$($LL_DECODE_LINKEA $DIR/$tdir/$tfile | grep 'pfid')
17069         [ -z "$linkea" ] && error "decode linkea $DIR/$tdir/$tfile failed"
17070
17071         local name=$(echo $linkea | awk '/pfid/ {print $5}' | sed -e "s/'//g")
17072         local PFID=$(echo $linkea | awk '/pfid/ {print $3}' | sed -e "s/,//g")
17073
17074         # check that we get the same pathname
17075         echo "PFID: $PFID, name: $name"
17076         local FOUND=$($LFS fid2path $MOUNT "$PFID")
17077         [ -z "$FOUND" ] && error "fid2path unable to get $PFID path"
17078         [ "$FOUND/$name" != "$DIR/$tdir/$tfile" ] &&
17079                 error "ll_decode_linkea has $FOUND/$name != $DIR/$tdir/$tfile"
17080
17081         rm -rf $DIR/$tdir || error "Can not delete directory $DIR/$tdir"
17082 }
17083 run_test 154B "verify the ll_decode_linkea tool"
17084
17085 test_154a() {
17086         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17087         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
17088         (( $MDS1_VERSION >= $(version_code 2.2.51) )) ||
17089                 skip "Need MDS version at least 2.2.51"
17090         [ -z "$(which setfacl)" ] && skip_env "must have setfacl tool"
17091
17092         cp /etc/hosts $DIR/$tfile
17093
17094         fid=$($LFS path2fid $DIR/$tfile)
17095         rc=$?
17096         [ $rc -ne 0 ] && error "error: could not get fid for $DIR/$tfile."
17097
17098         dot_lustre_fid_permission_check "$fid" $DIR ||
17099                 error "dot lustre permission check $fid failed"
17100
17101         ls -a $MOUNT | grep "\.lustre" && error ".lustre should not be listed"
17102
17103         rm -rf $MOUNT/.lustre && error ".lustre is not allowed to be unlinked"
17104
17105         touch $MOUNT/.lustre/file &&
17106                 error "creation is not allowed under .lustre"
17107
17108         mkdir $MOUNT/.lustre/dir &&
17109                 error "mkdir is not allowed under .lustre"
17110
17111         rm -rf $DIR/$tfile
17112 }
17113 run_test 154a "Open-by-FID"
17114
17115 test_154b() {
17116         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17117         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
17118         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
17119         [[ $MDS1_VERSION -ge $(version_code 2.2.51) ]] ||
17120                 skip "Need MDS version at least 2.2.51"
17121
17122         local remote_dir=$DIR/$tdir/remote_dir
17123         local MDTIDX=1
17124         local rc=0
17125
17126         mkdir -p $DIR/$tdir
17127         $LFS mkdir -i $MDTIDX $remote_dir ||
17128                 error "create remote directory failed"
17129
17130         cp /etc/hosts $remote_dir/$tfile
17131
17132         fid=$($LFS path2fid $remote_dir/$tfile)
17133         rc=$?
17134         [ $rc -ne 0 ] && error "error: could not get fid for $remote_dir/$tfile"
17135
17136         dot_lustre_fid_permission_check "$fid" $remote_dir ||
17137                 error "dot lustre permission check $fid failed"
17138         rm -rf $DIR/$tdir
17139 }
17140 run_test 154b "Open-by-FID for remote directory"
17141
17142 test_154c() {
17143         [[ $MDS1_VERSION -lt $(version_code 2.4.1) ]] &&
17144                 skip "Need MDS version at least 2.4.1"
17145
17146         touch $DIR/$tfile.1 $DIR/$tfile.2 $DIR/$tfile.3
17147         local FID1=$($LFS path2fid $DIR/$tfile.1)
17148         local FID2=$($LFS path2fid $DIR/$tfile.2)
17149         local FID3=$($LFS path2fid $DIR/$tfile.3)
17150
17151         local N=1
17152         $LFS path2fid $DIR/$tfile.[123] | while read PATHNAME FID; do
17153                 [ "$PATHNAME" = "$DIR/$tfile.$N:" ] ||
17154                         error "path2fid pathname $PATHNAME != $DIR/$tfile.$N:"
17155                 local want=FID$N
17156                 [ "$FID" = "${!want}" ] ||
17157                         error "path2fid $PATHNAME FID $FID != FID$N ${!want}"
17158                 N=$((N + 1))
17159         done
17160
17161         $LFS fid2path $MOUNT "$FID1" "$FID2" "$FID3" | while read PATHNAME;
17162         do
17163                 [ "$PATHNAME" = "$DIR/$tfile.$N" ] ||
17164                         error "fid2path pathname $PATHNAME != $DIR/$tfile.$N:"
17165                 N=$((N + 1))
17166         done
17167 }
17168 run_test 154c "lfs path2fid and fid2path multiple arguments"
17169
17170 test_154d() {
17171         remote_mds_nodsh && skip "remote MDS with nodsh"
17172         [[ $MDS1_VERSION -lt $(version_code 2.5.53) ]] &&
17173                 skip "Need MDS version at least 2.5.53"
17174
17175         if remote_mds; then
17176                 nid=$($LCTL list_nids | sed  "s/\./\\\./g")
17177         else
17178                 nid="0@lo"
17179         fi
17180         local proc_ofile="mdt.*.exports.'$nid'.open_files"
17181         local fd
17182         local cmd
17183
17184         rm -f $DIR/$tfile
17185         touch $DIR/$tfile
17186
17187         local fid=$($LFS path2fid $DIR/$tfile)
17188         # Open the file
17189         fd=$(free_fd)
17190         cmd="exec $fd<$DIR/$tfile"
17191         eval $cmd
17192         local fid_list=$(do_facet $SINGLEMDS $LCTL get_param $proc_ofile)
17193         echo "$fid_list" | grep "$fid"
17194         rc=$?
17195
17196         cmd="exec $fd>/dev/null"
17197         eval $cmd
17198         if [ $rc -ne 0 ]; then
17199                 error "FID $fid not found in open files list $fid_list"
17200         fi
17201 }
17202 run_test 154d "Verify open file fid"
17203
17204 test_154e()
17205 {
17206         [[ $MDS1_VERSION -lt $(version_code 2.6.50) ]] &&
17207                 skip "Need MDS version at least 2.6.50"
17208
17209         if ls -a $MOUNT | grep -q '^\.lustre$'; then
17210                 error ".lustre returned by readdir"
17211         fi
17212 }
17213 run_test 154e ".lustre is not returned by readdir"
17214
17215 test_154f() {
17216         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
17217
17218         # create parent directory on a single MDT to avoid cross-MDT hardlinks
17219         mkdir_on_mdt0 $DIR/$tdir
17220         # test dirs inherit from its stripe
17221         mkdir -p $DIR/$tdir/foo1 || error "mkdir error"
17222         mkdir -p $DIR/$tdir/foo2 || error "mkdir error"
17223         cp /etc/hosts $DIR/$tdir/foo1/$tfile
17224         ln $DIR/$tdir/foo1/$tfile $DIR/$tdir/foo2/link
17225         touch $DIR/f
17226
17227         # get fid of parents
17228         local FID0=$($LFS path2fid $DIR/$tdir)
17229         local FID1=$($LFS path2fid $DIR/$tdir/foo1)
17230         local FID2=$($LFS path2fid $DIR/$tdir/foo2)
17231         local FID3=$($LFS path2fid $DIR)
17232
17233         # check that path2fid --parents returns expected <parent_fid>/name
17234         # 1) test for a directory (single parent)
17235         local parent=$($LFS path2fid --parents $DIR/$tdir/foo1)
17236         [ "$parent" == "$FID0/foo1" ] ||
17237                 error "expected parent: $FID0/foo1, got: $parent"
17238
17239         # 2) test for a file with nlink > 1 (multiple parents)
17240         parent=$($LFS path2fid --parents $DIR/$tdir/foo1/$tfile)
17241         echo "$parent" | grep -F "$FID1/$tfile" ||
17242                 error "$FID1/$tfile not returned in parent list"
17243         echo "$parent" | grep -F "$FID2/link" ||
17244                 error "$FID2/link not returned in parent list"
17245
17246         # 3) get parent by fid
17247         local file_fid=$($LFS path2fid $DIR/$tdir/foo1/$tfile)
17248         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
17249         echo "$parent" | grep -F "$FID1/$tfile" ||
17250                 error "$FID1/$tfile not returned in parent list (by fid)"
17251         echo "$parent" | grep -F "$FID2/link" ||
17252                 error "$FID2/link not returned in parent list (by fid)"
17253
17254         # 4) test for entry in root directory
17255         parent=$($LFS path2fid --parents $DIR/f)
17256         echo "$parent" | grep -F "$FID3/f" ||
17257                 error "$FID3/f not returned in parent list"
17258
17259         # 5) test it on root directory
17260         [ -z "$($LFS path2fid --parents $MOUNT 2>/dev/null)" ] ||
17261                 error "$MOUNT should not have parents"
17262
17263         # enable xattr caching and check that linkea is correctly updated
17264         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
17265         save_lustre_params client "llite.*.xattr_cache" > $save
17266         lctl set_param llite.*.xattr_cache 1
17267
17268         # 6.1) linkea update on rename
17269         mv $DIR/$tdir/foo1/$tfile $DIR/$tdir/foo2/$tfile.moved
17270
17271         # get parents by fid
17272         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
17273         # foo1 should no longer be returned in parent list
17274         echo "$parent" | grep -F "$FID1" &&
17275                 error "$FID1 should no longer be in parent list"
17276         # the new path should appear
17277         echo "$parent" | grep -F "$FID2/$tfile.moved" ||
17278                 error "$FID2/$tfile.moved is not in parent list"
17279
17280         # 6.2) linkea update on unlink
17281         rm -f $DIR/$tdir/foo2/link
17282         parent=$($LFS path2fid --parents $MOUNT/.lustre/fid/$file_fid)
17283         # foo2/link should no longer be returned in parent list
17284         echo "$parent" | grep -F "$FID2/link" &&
17285                 error "$FID2/link should no longer be in parent list"
17286         true
17287
17288         rm -f $DIR/f
17289         restore_lustre_params < $save
17290         rm -f $save
17291 }
17292 run_test 154f "get parent fids by reading link ea"
17293
17294 test_154g()
17295 {
17296         [[ $MDS1_VERSION -ge $(version_code 2.6.92) &&
17297            $CLIENT_VERSION -gt $(version_code 2.6.99) ]] ||
17298                 skip "Need MDS version at least 2.6.92"
17299
17300         mkdir_on_mdt0 $DIR/$tdir
17301         llapi_fid_test -d $DIR/$tdir
17302 }
17303 run_test 154g "various llapi FID tests"
17304
17305 test_154h()
17306 {
17307         (( $CLIENT_VERSION >= $(version_code 2.15.55.1) )) ||
17308                 skip "Need client at least version 2.15.55.1"
17309
17310         # Create an empty file
17311         touch $DIR/$tfile
17312
17313         # Get FID (interactive mode) and save under $TMP/$tfile.log
17314         $LFS 2>&1 <<-EOF | tee $TMP/$tfile.log
17315                 path2fid $DIR/$tfile
17316         EOF
17317
17318         fid=$(cat $TMP/$tfile.log)
17319         # $fid should not be empty
17320         [[ ! -z $fid ]] || error "FID is empty"
17321         $LFS rmfid $DIR "$fid" || error "rmfid failed for $fid"
17322 }
17323 run_test 154h "Verify interactive path2fid"
17324
17325 test_155_small_load() {
17326     local temp=$TMP/$tfile
17327     local file=$DIR/$tfile
17328
17329     dd if=/dev/urandom of=$temp bs=6096 count=1 || \
17330         error "dd of=$temp bs=6096 count=1 failed"
17331     cp $temp $file
17332     cancel_lru_locks $OSC
17333     cmp $temp $file || error "$temp $file differ"
17334
17335     $TRUNCATE $temp 6000
17336     $TRUNCATE $file 6000
17337     cmp $temp $file || error "$temp $file differ (truncate1)"
17338
17339     echo "12345" >>$temp
17340     echo "12345" >>$file
17341     cmp $temp $file || error "$temp $file differ (append1)"
17342
17343     echo "12345" >>$temp
17344     echo "12345" >>$file
17345     cmp $temp $file || error "$temp $file differ (append2)"
17346
17347     rm -f $temp $file
17348     true
17349 }
17350
17351 test_155_big_load() {
17352         remote_ost_nodsh && skip "remote OST with nodsh"
17353
17354         local temp=$TMP/$tfile
17355         local file=$DIR/$tfile
17356
17357         free_min_max
17358         local cache_size=$(do_facet ost$((MAXI+1)) \
17359                 "awk '/cache/ {sum+=\\\$4} END {print sum}' /proc/cpuinfo")
17360
17361         # LU-16042: can not get the cache size on Arm64 VM here, fallback to a
17362         # pre-set value
17363         if [ -z "$cache_size" ]; then
17364                 cache_size=256
17365         fi
17366         local large_file_size=$((cache_size * 2))
17367
17368         echo "OSS cache size: $cache_size KB"
17369         echo "Large file size: $large_file_size KB"
17370
17371         [ $MAXV -le $large_file_size ] &&
17372                 skip_env "max available OST size needs > $large_file_size KB"
17373
17374         $LFS setstripe $file -c 1 -i $MAXI || error "$LFS setstripe $file failed"
17375
17376         dd if=/dev/urandom of=$temp bs=$large_file_size count=1k ||
17377                 error "dd of=$temp bs=$large_file_size count=1k failed"
17378         cp $temp $file
17379         ls -lh $temp $file
17380         cancel_lru_locks osc
17381         cmp $temp $file || error "$temp $file differ"
17382
17383         rm -f $temp $file
17384         true
17385 }
17386
17387 save_writethrough() {
17388         local facets=$(get_facets OST)
17389
17390         save_lustre_params $facets "osd-*.*.writethrough_cache_enable" > $1
17391 }
17392
17393 test_155a() {
17394         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17395
17396         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17397
17398         save_writethrough $p
17399
17400         set_cache read on
17401         set_cache writethrough on
17402         test_155_small_load
17403         restore_lustre_params < $p
17404         rm -f $p
17405 }
17406 run_test 155a "Verify small file correctness: read cache:on write_cache:on"
17407
17408 test_155b() {
17409         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17410
17411         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17412
17413         save_writethrough $p
17414
17415         set_cache read on
17416         set_cache writethrough off
17417         test_155_small_load
17418         restore_lustre_params < $p
17419         rm -f $p
17420 }
17421 run_test 155b "Verify small file correctness: read cache:on write_cache:off"
17422
17423 test_155c() {
17424         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17425
17426         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17427
17428         save_writethrough $p
17429
17430         set_cache read off
17431         set_cache writethrough on
17432         test_155_small_load
17433         restore_lustre_params < $p
17434         rm -f $p
17435 }
17436 run_test 155c "Verify small file correctness: read cache:off write_cache:on"
17437
17438 test_155d() {
17439         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17440
17441         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17442
17443         save_writethrough $p
17444
17445         set_cache read off
17446         set_cache writethrough off
17447         test_155_small_load
17448         restore_lustre_params < $p
17449         rm -f $p
17450 }
17451 run_test 155d "Verify small file correctness: read cache:off write_cache:off"
17452
17453 test_155e() {
17454         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17455
17456         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17457
17458         save_writethrough $p
17459
17460         set_cache read on
17461         set_cache writethrough on
17462         test_155_big_load
17463         restore_lustre_params < $p
17464         rm -f $p
17465 }
17466 run_test 155e "Verify big file correctness: read cache:on write_cache:on"
17467
17468 test_155f() {
17469         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17470
17471         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17472
17473         save_writethrough $p
17474
17475         set_cache read on
17476         set_cache writethrough off
17477         test_155_big_load
17478         restore_lustre_params < $p
17479         rm -f $p
17480 }
17481 run_test 155f "Verify big file correctness: read cache:on write_cache:off"
17482
17483 test_155g() {
17484         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17485
17486         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17487
17488         save_writethrough $p
17489
17490         set_cache read off
17491         set_cache writethrough on
17492         test_155_big_load
17493         restore_lustre_params < $p
17494         rm -f $p
17495 }
17496 run_test 155g "Verify big file correctness: read cache:off write_cache:on"
17497
17498 test_155h() {
17499         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17500
17501         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17502
17503         save_writethrough $p
17504
17505         set_cache read off
17506         set_cache writethrough off
17507         test_155_big_load
17508         restore_lustre_params < $p
17509         rm -f $p
17510 }
17511 run_test 155h "Verify big file correctness: read cache:off write_cache:off"
17512
17513 test_156() {
17514         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17515         remote_ost_nodsh && skip "remote OST with nodsh"
17516         [ $OST1_VERSION -lt $(version_code 2.6.93) ] &&
17517                 skip "stats not implemented on old servers"
17518         [ "$ost1_FSTYPE" = "zfs" ] &&
17519                 skip "LU-1956/LU-2261: stats not implemented on OSD ZFS"
17520         (( CLIENT_VERSION == OST1_VERSION )) ||
17521                 skip "LU-13081: no interop testing for OSS cache"
17522
17523         local CPAGES=3
17524         local BEFORE
17525         local AFTER
17526         local file="$DIR/$tfile"
17527         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
17528
17529         save_writethrough $p
17530         roc_hit_init
17531
17532         log "Turn on read and write cache"
17533         set_cache read on
17534         set_cache writethrough on
17535
17536         log "Write data and read it back."
17537         log "Read should be satisfied from the cache."
17538         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
17539         BEFORE=$(roc_hit)
17540         cancel_lru_locks osc
17541         cat $file >/dev/null
17542         AFTER=$(roc_hit)
17543         if ! let "AFTER - BEFORE == CPAGES"; then
17544                 error "NOT IN CACHE (2): before: $BEFORE, after: $AFTER"
17545         else
17546                 log "cache hits: before: $BEFORE, after: $AFTER"
17547         fi
17548
17549         log "Read again; it should be satisfied from the cache."
17550         BEFORE=$AFTER
17551         cancel_lru_locks osc
17552         cat $file >/dev/null
17553         AFTER=$(roc_hit)
17554         if ! let "AFTER - BEFORE == CPAGES"; then
17555                 error "NOT IN CACHE (3): before: $BEFORE, after: $AFTER"
17556         else
17557                 log "cache hits:: before: $BEFORE, after: $AFTER"
17558         fi
17559
17560         log "Turn off the read cache and turn on the write cache"
17561         set_cache read off
17562         set_cache writethrough on
17563
17564         log "Read again; it should be satisfied from the cache."
17565         BEFORE=$(roc_hit)
17566         cancel_lru_locks osc
17567         cat $file >/dev/null
17568         AFTER=$(roc_hit)
17569         if ! let "AFTER - BEFORE == CPAGES"; then
17570                 error "NOT IN CACHE (4): before: $BEFORE, after: $AFTER"
17571         else
17572                 log "cache hits:: before: $BEFORE, after: $AFTER"
17573         fi
17574
17575         if [ $OST1_VERSION -lt $(version_code 2.12.55) ]; then
17576                 # > 2.12.56 uses pagecache if cached
17577                 log "Read again; it should not be satisfied from the cache."
17578                 BEFORE=$AFTER
17579                 cancel_lru_locks osc
17580                 cat $file >/dev/null
17581                 AFTER=$(roc_hit)
17582                 if ! let "AFTER - BEFORE == 0"; then
17583                         error "IN CACHE (5): before: $BEFORE, after: $AFTER"
17584                 else
17585                         log "cache hits:: before: $BEFORE, after: $AFTER"
17586                 fi
17587         fi
17588
17589         log "Write data and read it back."
17590         log "Read should be satisfied from the cache."
17591         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
17592         BEFORE=$(roc_hit)
17593         cancel_lru_locks osc
17594         cat $file >/dev/null
17595         AFTER=$(roc_hit)
17596         if ! let "AFTER - BEFORE == CPAGES"; then
17597                 error "NOT IN CACHE (6): before: $BEFORE, after: $AFTER"
17598         else
17599                 log "cache hits:: before: $BEFORE, after: $AFTER"
17600         fi
17601
17602         if [ $OST1_VERSION -lt $(version_code 2.12.55) ]; then
17603                 # > 2.12.56 uses pagecache if cached
17604                 log "Read again; it should not be satisfied from the cache."
17605                 BEFORE=$AFTER
17606                 cancel_lru_locks osc
17607                 cat $file >/dev/null
17608                 AFTER=$(roc_hit)
17609                 if ! let "AFTER - BEFORE == 0"; then
17610                         error "IN CACHE (7): before: $BEFORE, after: $AFTER"
17611                 else
17612                         log "cache hits:: before: $BEFORE, after: $AFTER"
17613                 fi
17614         fi
17615
17616         log "Turn off read and write cache"
17617         set_cache read off
17618         set_cache writethrough off
17619
17620         log "Write data and read it back"
17621         log "It should not be satisfied from the cache."
17622         rm -f $file
17623         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
17624         cancel_lru_locks osc
17625         BEFORE=$(roc_hit)
17626         cat $file >/dev/null
17627         AFTER=$(roc_hit)
17628         if ! let "AFTER - BEFORE == 0"; then
17629                 error_ignore bz20762 "IN CACHE (8):before:$BEFORE,after:$AFTER"
17630         else
17631                 log "cache hits:: before: $BEFORE, after: $AFTER"
17632         fi
17633
17634         log "Turn on the read cache and turn off the write cache"
17635         set_cache read on
17636         set_cache writethrough off
17637
17638         log "Write data and read it back"
17639         log "It should not be satisfied from the cache."
17640         rm -f $file
17641         dd if=/dev/urandom of=$file bs=4k count=$CPAGES || error "dd failed"
17642         BEFORE=$(roc_hit)
17643         cancel_lru_locks osc
17644         cat $file >/dev/null
17645         AFTER=$(roc_hit)
17646         if ! let "AFTER - BEFORE == 0"; then
17647                 error_ignore bz20762 "IN CACHE (9):before:$BEFORE,after:$AFTER"
17648         else
17649                 log "cache hits:: before: $BEFORE, after: $AFTER"
17650         fi
17651
17652         log "Read again; it should be satisfied from the cache."
17653         BEFORE=$(roc_hit)
17654         cancel_lru_locks osc
17655         cat $file >/dev/null
17656         AFTER=$(roc_hit)
17657         if ! let "AFTER - BEFORE == CPAGES"; then
17658                 error "NOT IN CACHE (1): before: $BEFORE, after: $AFTER"
17659         else
17660                 log "cache hits:: before: $BEFORE, after: $AFTER"
17661         fi
17662
17663         restore_lustre_params < $p
17664         rm -f $p $file
17665 }
17666 run_test 156 "Verification of tunables"
17667
17668 test_160a() {
17669         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17670         remote_mds_nodsh && skip "remote MDS with nodsh"
17671         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
17672                 skip "Need MDS version at least 2.2.0"
17673
17674         changelog_register || error "changelog_register failed"
17675         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
17676         changelog_users $SINGLEMDS | grep -q $cl_user ||
17677                 error "User $cl_user not found in changelog_users"
17678
17679         mkdir_on_mdt0 $DIR/$tdir
17680
17681         # change something
17682         test_mkdir -p $DIR/$tdir/pics/2008/zachy
17683         changelog_clear 0 || error "changelog_clear failed"
17684         touch $DIR/$tdir/pics/2008/zachy/$tfile                 # open 1
17685         cp /etc/hosts $DIR/$tdir/pics/2008/zachy/pic1.jpg       # open 2
17686         mv $DIR/$tdir/pics/2008/zachy $DIR/$tdir/pics/zach
17687         ln $DIR/$tdir/pics/zach/pic1.jpg $DIR/$tdir/pics/2008/portland.jpg
17688         ln -s $DIR/$tdir/pics/2008/portland.jpg $DIR/$tdir/pics/desktop.jpg
17689         rm $DIR/$tdir/pics/desktop.jpg
17690
17691         echo "verifying changelog mask"
17692         changelog_chmask "-MKDIR"
17693         changelog_chmask "-CLOSE"
17694
17695         test_mkdir -p $DIR/$tdir/pics/zach/sofia                # not logged
17696         echo "zzzzzz" > $DIR/$tdir/pics/zach/file               # not logged
17697
17698         changelog_chmask "+MKDIR"
17699         changelog_chmask "+CLOSE"
17700
17701         test_mkdir -p $DIR/$tdir/pics/2008/sofia                # mkdir 1
17702         echo "zzzzzz" > $DIR/$tdir/pics/zach/file               # open 3
17703
17704         MKDIRS=$(changelog_dump | grep -c "MKDIR")
17705         CLOSES=$(changelog_dump | grep -c "CLOSE")
17706         [ $MKDIRS -eq 1 ] || error "MKDIR changelog mask count $MKDIRS != 1"
17707         [ $CLOSES -eq 3 ] || error "CLOSE changelog mask count $CLOSES != 3"
17708
17709         # verify contents
17710         echo "verifying target fid"
17711         local fidc=$(changelog_extract_field "CREAT" "$tfile" "t=")
17712         local fidf=$($LFS path2fid $DIR/$tdir/pics/zach/$tfile)
17713         [ "$fidc" == "$fidf" ] ||
17714                 error "changelog '$tfile' fid $fidc != file fid $fidf"
17715         echo "verifying parent fid"
17716         # The FID returned from the Changelog may be the directory shard on
17717         # a different MDT, and not the FID returned by path2fid on the parent.
17718         # Instead of comparing FIDs, verify that fid2path(fidp) is correct,
17719         # since this is what will matter when recreating this file in the tree.
17720         local fidp=$(changelog_extract_field "CREAT" "$tfile" "p=")
17721         local pathp=$($LFS fid2path $MOUNT "$fidp")
17722         [ "${pathp%/}" == "$DIR/$tdir/pics/zach" ] ||
17723                 error "changelog fid2path($fidc) $pathp != $DIR/$tdir/pics/zach"
17724
17725         echo "getting records for $cl_user"
17726         changelog_users $SINGLEMDS
17727         local user_rec1=$(changelog_user_rec $SINGLEMDS $cl_user)
17728         local nclr=3
17729         __changelog_clear $SINGLEMDS $cl_user +$nclr ||
17730                 error "changelog_clear failed"
17731         local user_rec2=$(changelog_user_rec $SINGLEMDS $cl_user)
17732         echo "verifying user clear: $user_rec1 + $nclr == $user_rec2"
17733         [ $user_rec2 == $((user_rec1 + nclr)) ] ||
17734                 error "user index expect $user_rec1 + $nclr != $user_rec2"
17735
17736         local min0_rec=$(changelog_users $SINGLEMDS |
17737                 awk 'min == "" || $2 < min { min = $2 }; END { print min }')
17738         local first_rec=$($LFS changelog $(facet_svc $SINGLEMDS) |
17739                           awk '{ print $1; exit; }')
17740
17741         changelog_dump | tail -n 5
17742         echo "verifying user min purge: $min0_rec + 1 == $first_rec"
17743         [ $first_rec == $((min0_rec + 1)) ] ||
17744                 error "first index should be $min0_rec + 1 not $first_rec"
17745
17746         # LU-3446 changelog index reset on MDT restart
17747         local cur_rec1=$(changelog_users $SINGLEMDS |
17748                          awk '/^current.index:/ { print $NF }')
17749         changelog_clear 0 ||
17750                 error "clear all changelog records for $cl_user failed"
17751         stop $SINGLEMDS || error "Fail to stop $SINGLEMDS"
17752         start $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) $MDS_MOUNT_OPTS ||
17753                 error "Fail to start $SINGLEMDS"
17754         local cur_rec2=$(changelog_users $SINGLEMDS |
17755                          awk '/^current.index:/ { print $NF }')
17756         echo "verifying index survives MDT restart: $cur_rec1 == $cur_rec2"
17757         [ $cur_rec1 == $cur_rec2 ] ||
17758                 error "current index should be $cur_rec1 not $cur_rec2"
17759
17760         echo "verifying users from this test are deregistered"
17761         changelog_deregister || error "changelog_deregister failed"
17762         changelog_users $SINGLEMDS | grep -q $cl_user &&
17763                 error "User '$cl_user' still in changelog_users"
17764
17765         # lctl get_param -n mdd.*.changelog_users
17766         # current_index: 144
17767         # ID    index (idle seconds)
17768         # cl3   144   (2) mask=<list>
17769         if [ -z "$(changelog_users $SINGLEMDS | grep -v current.index)" ]; then
17770                 # this is the normal case where all users were deregistered
17771                 # make sure no new records are added when no users are present
17772                 local last_rec1=$(changelog_users $SINGLEMDS |
17773                                   awk '/^current.index:/ { print $NF }')
17774                 touch $DIR/$tdir/chloe
17775                 local last_rec2=$(changelog_users $SINGLEMDS |
17776                                   awk '/^current.index:/ { print $NF }')
17777                 echo "verify changelogs are off: $last_rec1 == $last_rec2"
17778                 [ $last_rec1 == $last_rec2 ] || error "changelogs not off"
17779         else
17780                 # any changelog users must be leftovers from a previous test
17781                 changelog_users $SINGLEMDS
17782                 echo "other changelog users; can't verify off"
17783         fi
17784 }
17785 run_test 160a "changelog sanity"
17786
17787 test_160b() { # LU-3587
17788         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17789         remote_mds_nodsh && skip "remote MDS with nodsh"
17790         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
17791                 skip "Need MDS version at least 2.2.0"
17792
17793         changelog_register || error "changelog_register failed"
17794         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
17795         changelog_users $SINGLEMDS | grep -q $cl_user ||
17796                 error "User '$cl_user' not found in changelog_users"
17797
17798         local longname1=$(str_repeat a 255)
17799         local longname2=$(str_repeat b 255)
17800
17801         cd $DIR
17802         echo "creating very long named file"
17803         touch $longname1 || error "create of '$longname1' failed"
17804         echo "renaming very long named file"
17805         mv $longname1 $longname2
17806
17807         changelog_dump | grep RENME | tail -n 5
17808         rm -f $longname2
17809 }
17810 run_test 160b "Verify that very long rename doesn't crash in changelog"
17811
17812 test_160c() {
17813         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17814         remote_mds_nodsh && skip "remote MDS with nodsh"
17815
17816         [[ $MDS1_VERSION -gt $(version_code 2.5.57) ]] ||
17817                 [[ $MDS1_VERSION -gt $(version_code 2.5.1) &&
17818                    $MDS1_VERSION -lt $(version_code 2.5.50) ]] ||
17819                 skip "Need MDS version at least 2.5.58 or 2.5.2+"
17820
17821         local rc=0
17822
17823         # Registration step
17824         changelog_register || error "changelog_register failed"
17825
17826         rm -rf $DIR/$tdir
17827         mkdir -p $DIR/$tdir
17828         $MCREATE $DIR/$tdir/foo_160c
17829         changelog_chmask "-TRUNC"
17830         $TRUNCATE $DIR/$tdir/foo_160c 200
17831         changelog_chmask "+TRUNC"
17832         $TRUNCATE $DIR/$tdir/foo_160c 199
17833         changelog_dump | tail -n 5
17834         local truncs=$(changelog_dump | tail -n 5 | grep -c TRUNC)
17835         [ $truncs -eq 1 ] || error "TRUNC changelog mask count $truncs != 1"
17836 }
17837 run_test 160c "verify that changelog log catch the truncate event"
17838
17839 test_160d() {
17840         remote_mds_nodsh && skip "remote MDS with nodsh"
17841         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
17842         [ $PARALLEL == "yes" ] && skip "skip parallel run"
17843         [[ $MDS1_VERSION -ge $(version_code 2.7.60) ]] ||
17844                 skip "Need MDS version at least 2.7.60"
17845
17846         # Registration step
17847         changelog_register || error "changelog_register failed"
17848
17849         mkdir -p $DIR/$tdir/migrate_dir
17850         changelog_clear 0 || error "changelog_clear failed"
17851
17852         $LFS migrate -m 1 $DIR/$tdir/migrate_dir || error "migrate fails"
17853         changelog_dump | tail -n 5
17854         local migrates=$(changelog_dump | grep -c "MIGRT")
17855         [ $migrates -eq 1 ] || error "MIGRATE changelog count $migrates != 1"
17856 }
17857 run_test 160d "verify that changelog log catch the migrate event"
17858
17859 test_160e() {
17860         remote_mds_nodsh && skip "remote MDS with nodsh"
17861
17862         # Create a user
17863         changelog_register || error "changelog_register failed"
17864
17865         local MDT0=$(facet_svc $SINGLEMDS)
17866         local rc
17867
17868         # No user (expect fail)
17869         do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister
17870         rc=$?
17871         if [ $rc -eq 0 ]; then
17872                 error "Should fail without user"
17873         elif [ $rc -ne 4 ]; then
17874                 error "changelog_deregister failed with $rc, expect 4(CMD_HELP)"
17875         fi
17876
17877         # Delete a future user (expect fail)
17878         do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister "cl77"
17879         rc=$?
17880         if [ $rc -eq 0 ]; then
17881                 error "Deleted non-existant user cl77"
17882         elif [ $rc -ne 2 ]; then
17883                 error "changelog_deregister failed with $rc, expect 2 (ENOENT)"
17884         fi
17885
17886         # Clear to a bad index (1 billion should be safe)
17887         $LFS changelog_clear $MDT0 "${CL_USERS[$SINGLEMDS]%% *}" 1000000000
17888         rc=$?
17889
17890         if [ $rc -eq 0 ]; then
17891                 error "Successfully cleared to invalid CL index"
17892         elif [ $rc -ne 22 ]; then
17893                 error "changelog_clear failed with $rc, expected 22 (EINVAL)"
17894         fi
17895 }
17896 run_test 160e "changelog negative testing (should return errors)"
17897
17898 test_160f() {
17899         remote_mds_nodsh && skip "remote MDS with nodsh" && return
17900         [[ $MDS1_VERSION -ge $(version_code 2.10.56) ]] ||
17901                 skip "Need MDS version at least 2.10.56"
17902
17903         local mdts=$(comma_list $(mdts_nodes))
17904
17905         # Create a user
17906         changelog_register || error "first changelog_register failed"
17907         changelog_register || error "second changelog_register failed"
17908         local cl_users
17909         declare -A cl_user1
17910         declare -A cl_user2
17911         local user_rec1
17912         local user_rec2
17913         local i
17914
17915         # generate some changelog records to accumulate on each MDT
17916         # use all_char because created files should be evenly distributed
17917         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
17918                 error "test_mkdir $tdir failed"
17919         log "$(date +%s): creating first files"
17920         for ((i = 0; i < MDSCOUNT * 2; i++)); do
17921                 $LFS mkdir -i $((i%MDSCOUNT)) $DIR/$tdir/d$i.$((i/MDSCOUNT)) ||
17922                         error "create $DIR/$tdir/d$i.$((i/MDSCOUNT)) failed"
17923         done
17924
17925         # check changelogs have been generated
17926         local start=$SECONDS
17927         local idle_time=$((MDSCOUNT * 5 + 5))
17928         local nbcl=$(changelog_dump | wc -l)
17929         [[ $nbcl -eq 0 ]] && error "no changelogs found"
17930
17931         for param in "changelog_max_idle_time=$idle_time" \
17932                      "changelog_gc=1" \
17933                      "changelog_min_gc_interval=2" \
17934                      "changelog_min_free_cat_entries=3"; do
17935                 local MDT0=$(facet_svc $SINGLEMDS)
17936                 local var="${param%=*}"
17937                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
17938
17939                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
17940                 do_nodes $mdts $LCTL set_param mdd.*.$param
17941         done
17942
17943         # force cl_user2 to be idle (1st part), but also cancel the
17944         # cl_user1 records so that it is not evicted later in the test.
17945         local sleep1=$((idle_time / 2))
17946         echo "$(date +%s): sleep1 $sleep1/${idle_time}s"
17947         sleep $sleep1
17948
17949         # simulate changelog catalog almost full
17950         #define OBD_FAIL_CAT_FREE_RECORDS       0x1313
17951         do_nodes $mdts "$LCTL set_param fail_loc=0x1313 fail_val=3"
17952
17953         for i in $(seq $MDSCOUNT); do
17954                 cl_users=(${CL_USERS[mds$i]})
17955                 cl_user1[mds$i]="${cl_users[0]}"
17956                 cl_user2[mds$i]="${cl_users[1]}"
17957
17958                 [ -n "${cl_user1[mds$i]}" ] ||
17959                         error "mds$i: no user registered"
17960                 [ -n "${cl_user2[mds$i]}" ] ||
17961                         error "mds$i: only ${cl_user2[mds$i]} is registered"
17962
17963                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
17964                 [ -n "$user_rec1" ] ||
17965                         error "mds$i: User ${cl_user1[mds$i]} not registered"
17966                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
17967                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
17968                 [ -n "$user_rec2" ] ||
17969                         error "mds$i: User ${cl_user1[mds$i]} not registered"
17970                 echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
17971                      "$user_rec1 + 2 == $user_rec2"
17972                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
17973                         error "mds$i: user ${cl_user1[mds$i]} index expected " \
17974                               "$user_rec1 + 2, but is $user_rec2"
17975                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
17976                 [ -n "$user_rec2" ] ||
17977                         error "mds$i: User ${cl_user2[mds$i]} not registered"
17978                 [ $user_rec1 == $user_rec2 ] ||
17979                         error "mds$i: user ${cl_user2[mds$i]} index expected " \
17980                               "$user_rec1, but is $user_rec2"
17981         done
17982
17983         # force cl_user2 idle (2nd part) to just exceed changelog_max_idle_time
17984         local sleep2=$((idle_time - (SECONDS - start) + 1))
17985         echo "$(date +%s): sleep2 $sleep2/${idle_time}s"
17986         sleep $sleep2
17987
17988         # Generate one more changelog to trigger GC at fail_loc for cl_user2.
17989         # cl_user1 should be OK because it recently processed records.
17990         echo "$(date +%s): creating $((MDSCOUNT * 2)) files"
17991         for ((i = 0; i < MDSCOUNT * 2; i++)); do
17992                 $LFS mkdir -i $((i%MDSCOUNT)) $DIR/$tdir/d$i.$((i/MDSCOUNT+2))||
17993                         error "create $DIR/$tdir/d$i.$((i/MDSCOUNT+2)) failed"
17994         done
17995
17996         # ensure gc thread is done
17997         for i in $(mdts_nodes); do
17998                 wait_update $i "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
17999                         error "$i: GC-thread not done"
18000         done
18001
18002         local first_rec
18003         for (( i = 1; i <= MDSCOUNT; i++ )); do
18004                 # check cl_user1 still registered
18005                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
18006                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18007                 # check cl_user2 unregistered
18008                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
18009                         error "mds$i: User ${cl_user2[mds$i]} still registered"
18010
18011                 # check changelogs are present and starting at $user_rec1 + 1
18012                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18013                 [ -n "$user_rec1" ] ||
18014                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18015                 first_rec=$($LFS changelog $(facet_svc mds$i) |
18016                             awk '{ print $1; exit; }')
18017
18018                 echo "mds$i: $(date +%s) verify rec $user_rec1+1 == $first_rec"
18019                 [ $((user_rec1 + 1)) == $first_rec ] ||
18020                         error "mds$i: rec $first_rec != $user_rec1 + 1"
18021         done
18022 }
18023 run_test 160f "changelog garbage collect (timestamped users)"
18024
18025 test_160g() {
18026         remote_mds_nodsh && skip "remote MDS with nodsh"
18027         [[ $MDS1_VERSION -ge $(version_code 2.14.55) ]] ||
18028                 skip "Need MDS version at least 2.14.55"
18029
18030         local mdts=$(comma_list $(mdts_nodes))
18031
18032         # Create a user
18033         changelog_register || error "first changelog_register failed"
18034         changelog_register || error "second changelog_register failed"
18035         local cl_users
18036         declare -A cl_user1
18037         declare -A cl_user2
18038         local user_rec1
18039         local user_rec2
18040         local i
18041
18042         # generate some changelog records to accumulate on each MDT
18043         # use all_char because created files should be evenly distributed
18044         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
18045                 error "test_mkdir $tdir failed"
18046         for ((i = 0; i < MDSCOUNT; i++)); do
18047                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
18048                         error "create $DIR/$tdir/d$i.1 failed"
18049         done
18050
18051         # check changelogs have been generated
18052         local nbcl=$(changelog_dump | wc -l)
18053         (( $nbcl > 0 )) || error "no changelogs found"
18054
18055         # reduce the max_idle_indexes value to make sure we exceed it
18056         for param in "changelog_max_idle_indexes=2" \
18057                      "changelog_gc=1" \
18058                      "changelog_min_gc_interval=2"; do
18059                 local MDT0=$(facet_svc $SINGLEMDS)
18060                 local var="${param%=*}"
18061                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
18062
18063                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
18064                 do_nodes $mdts $LCTL set_param mdd.*.$param ||
18065                         error "unable to set mdd.*.$param"
18066         done
18067
18068         local start=$SECONDS
18069         for i in $(seq $MDSCOUNT); do
18070                 cl_users=(${CL_USERS[mds$i]})
18071                 cl_user1[mds$i]="${cl_users[0]}"
18072                 cl_user2[mds$i]="${cl_users[1]}"
18073
18074                 [ -n "${cl_user1[mds$i]}" ] ||
18075                         error "mds$i: user1 is not registered"
18076                 [ -n "${cl_user2[mds$i]}" ] ||
18077                         error "mds$i: only ${cl_user1[mds$i]} is registered"
18078
18079                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18080                 [ -n "$user_rec1" ] ||
18081                         error "mds$i: user1 ${cl_user1[mds$i]} not found"
18082                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
18083                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18084                 [ -n "$user_rec2" ] ||
18085                         error "mds$i: user1 ${cl_user1[mds$i]} not found (2)"
18086                 echo "mds$i: verifying user1 ${cl_user1[mds$i]} clear: " \
18087                      "$user_rec1 + 2 == $user_rec2"
18088                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
18089                         error "mds$i: user1 ${cl_user1[mds$i]} index " \
18090                               "expected $user_rec1 + 2, but is $user_rec2"
18091                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
18092                 [ -n "$user_rec2" ] ||
18093                         error "mds$i: user2 ${cl_user2[mds$i]} not found"
18094                 [ $user_rec1 == $user_rec2 ] ||
18095                         error "mds$i: user2 ${cl_user2[mds$i]} index " \
18096                               "expected $user_rec1, but is $user_rec2"
18097         done
18098
18099         # ensure we are past the previous changelog_min_gc_interval set above
18100         local sleep2=$((start + 2 - SECONDS))
18101         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
18102         # Generate one more changelog to trigger GC at fail_loc for cl_user2.
18103         # cl_user1 should be OK because it recently processed records.
18104         for ((i = 0; i < MDSCOUNT; i++)); do
18105                 $LFS mkdir -i $i $DIR/$tdir/d$i.3 ||
18106                         error "create $DIR/$tdir/d$i.3 failed"
18107         done
18108
18109         # ensure gc thread is done
18110         for i in $(mdts_nodes); do
18111                 wait_update $i "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
18112                         error "$i: GC-thread not done"
18113         done
18114
18115         local first_rec
18116         for (( i = 1; i <= MDSCOUNT; i++ )); do
18117                 # check cl_user1 still registered
18118                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
18119                         error "mds$i: user1 ${cl_user1[mds$i]} not found (3)"
18120                 # check cl_user2 unregistered
18121                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
18122                         error "mds$i: user2 ${cl_user2[mds$i]} is registered"
18123
18124                 # check changelogs are present and starting at $user_rec1 + 1
18125                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18126                 [ -n "$user_rec1" ] ||
18127                         error "mds$i: user1 ${cl_user1[mds$i]} not found (4)"
18128                 first_rec=$($LFS changelog $(facet_svc mds$i) |
18129                             awk '{ print $1; exit; }')
18130
18131                 echo "mds$i: $(date +%s) verify rec $user_rec1+1 == $first_rec"
18132                 [ $((user_rec1 + 1)) == $first_rec ] ||
18133                         error "mds$i: rec $first_rec != $user_rec1 + 1"
18134         done
18135 }
18136 run_test 160g "changelog garbage collect on idle records"
18137
18138 test_160h() {
18139         remote_mds_nodsh && skip "remote MDS with nodsh" && return
18140         [[ $MDS1_VERSION -ge $(version_code 2.10.56) ]] ||
18141                 skip "Need MDS version at least 2.10.56"
18142
18143         local mdts=$(comma_list $(mdts_nodes))
18144
18145         # Create a user
18146         changelog_register || error "first changelog_register failed"
18147         changelog_register || error "second changelog_register failed"
18148         local cl_users
18149         declare -A cl_user1
18150         declare -A cl_user2
18151         local user_rec1
18152         local user_rec2
18153         local i
18154
18155         # generate some changelog records to accumulate on each MDT
18156         # use all_char because created files should be evenly distributed
18157         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
18158                 error "test_mkdir $tdir failed"
18159         for ((i = 0; i < MDSCOUNT; i++)); do
18160                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
18161                         error "create $DIR/$tdir/d$i.1 failed"
18162         done
18163
18164         # check changelogs have been generated
18165         local nbcl=$(changelog_dump | wc -l)
18166         [[ $nbcl -eq 0 ]] && error "no changelogs found"
18167
18168         for param in "changelog_max_idle_time=10" \
18169                      "changelog_gc=1" \
18170                      "changelog_min_gc_interval=2"; do
18171                 local MDT0=$(facet_svc $SINGLEMDS)
18172                 local var="${param%=*}"
18173                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
18174
18175                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
18176                 do_nodes $mdts $LCTL set_param mdd.*.$param
18177         done
18178
18179         # force cl_user2 to be idle (1st part)
18180         sleep 9
18181
18182         for i in $(seq $MDSCOUNT); do
18183                 cl_users=(${CL_USERS[mds$i]})
18184                 cl_user1[mds$i]="${cl_users[0]}"
18185                 cl_user2[mds$i]="${cl_users[1]}"
18186
18187                 [ -n "${cl_user1[mds$i]}" ] ||
18188                         error "mds$i: no user registered"
18189                 [ -n "${cl_user2[mds$i]}" ] ||
18190                         error "mds$i: only ${cl_user2[mds$i]} is registered"
18191
18192                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18193                 [ -n "$user_rec1" ] ||
18194                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18195                 __changelog_clear mds$i ${cl_user1[mds$i]} +2
18196                 user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18197                 [ -n "$user_rec2" ] ||
18198                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18199                 echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
18200                      "$user_rec1 + 2 == $user_rec2"
18201                 [ $((user_rec1 + 2)) == $user_rec2 ] ||
18202                         error "mds$i: user ${cl_user1[mds$i]} index expected " \
18203                               "$user_rec1 + 2, but is $user_rec2"
18204                 user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
18205                 [ -n "$user_rec2" ] ||
18206                         error "mds$i: User ${cl_user2[mds$i]} not registered"
18207                 [ $user_rec1 == $user_rec2 ] ||
18208                         error "mds$i: user ${cl_user2[mds$i]} index expected " \
18209                               "$user_rec1, but is $user_rec2"
18210         done
18211
18212         # force cl_user2 to be idle (2nd part) and to reach
18213         # changelog_max_idle_time
18214         sleep 2
18215
18216         # force each GC-thread start and block then
18217         # one per MDT/MDD, set fail_val accordingly
18218         #define OBD_FAIL_FORCE_GC_THREAD 0x1316
18219         do_nodes $mdts $LCTL set_param fail_loc=0x1316
18220
18221         # generate more changelogs to trigger fail_loc
18222         createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
18223                 error "create $DIR/$tdir/${tfile}bis failed"
18224
18225         # stop MDT to stop GC-thread, should be done in back-ground as it will
18226         # block waiting for the thread to be released and exit
18227         declare -A stop_pids
18228         for i in $(seq $MDSCOUNT); do
18229                 stop mds$i &
18230                 stop_pids[mds$i]=$!
18231         done
18232
18233         for i in $(mdts_nodes); do
18234                 local facet
18235                 local nb=0
18236                 local facets=$(facets_up_on_host $i)
18237
18238                 for facet in ${facets//,/ }; do
18239                         if [[ $facet == mds* ]]; then
18240                                 nb=$((nb + 1))
18241                         fi
18242                 done
18243                 # ensure each MDS's gc threads are still present and all in "R"
18244                 # state (OBD_FAIL_FORCE_GC_THREAD effect!)
18245                 [[ $(do_node $i pgrep chlg_gc_thread | wc -l) -eq $nb ]] ||
18246                         error "$i: expected $nb GC-thread"
18247                 wait_update $i \
18248                         "ps -C chlg_gc_thread -o state --no-headers | uniq" \
18249                         "R" 20 ||
18250                         error "$i: GC-thread not found in R-state"
18251                 # check umounts of each MDT on MDS have reached kthread_stop()
18252                 [[ $(do_node $i pgrep umount | wc -l) -eq $nb ]] ||
18253                         error "$i: expected $nb umount"
18254                 wait_update $i \
18255                         "ps -C umount -o state --no-headers | uniq" "D" 20 ||
18256                         error "$i: umount not found in D-state"
18257         done
18258
18259         # release all GC-threads
18260         do_nodes $mdts $LCTL set_param fail_loc=0
18261
18262         # wait for MDT stop to complete
18263         for i in $(seq $MDSCOUNT); do
18264                 wait ${stop_pids[mds$i]} || error "mds$i: stop failed"
18265         done
18266
18267         # XXX
18268         # may try to check if any orphan changelog records are present
18269         # via ldiskfs/zfs and llog_reader...
18270
18271         # re-start/mount MDTs
18272         for i in $(seq $MDSCOUNT); do
18273                 start mds$i $(mdsdevname $i) $MDS_MOUNT_OPTS ||
18274                         error "Fail to start mds$i"
18275         done
18276
18277         local first_rec
18278         for i in $(seq $MDSCOUNT); do
18279                 # check cl_user1 still registered
18280                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
18281                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18282                 # check cl_user2 unregistered
18283                 changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
18284                         error "mds$i: User ${cl_user2[mds$i]} still registered"
18285
18286                 # check changelogs are present and starting at $user_rec1 + 1
18287                 user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
18288                 [ -n "$user_rec1" ] ||
18289                         error "mds$i: User ${cl_user1[mds$i]} not registered"
18290                 first_rec=$($LFS changelog $(facet_svc mds$i) |
18291                             awk '{ print $1; exit; }')
18292
18293                 echo "mds$i: verifying first index $user_rec1 + 1 == $first_rec"
18294                 [ $((user_rec1 + 1)) == $first_rec ] ||
18295                         error "mds$i: first index should be $user_rec1 + 1, " \
18296                               "but is $first_rec"
18297         done
18298 }
18299 run_test 160h "changelog gc thread stop upon umount, orphan records delete " \
18300               "during mount"
18301
18302 test_160i() {
18303
18304         local mdts=$(comma_list $(mdts_nodes))
18305
18306         changelog_register || error "first changelog_register failed"
18307
18308         # generate some changelog records to accumulate on each MDT
18309         # use all_char because created files should be evenly distributed
18310         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
18311                 error "test_mkdir $tdir failed"
18312         for ((i = 0; i < MDSCOUNT; i++)); do
18313                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
18314                         error "create $DIR/$tdir/d$i.1 failed"
18315         done
18316
18317         # check changelogs have been generated
18318         local nbcl=$(changelog_dump | wc -l)
18319         [[ $nbcl -eq 0 ]] && error "no changelogs found"
18320
18321         # simulate race between register and unregister
18322         # XXX as fail_loc is set per-MDS, with DNE configs the race
18323         # simulation will only occur for one MDT per MDS and for the
18324         # others the normal race scenario will take place
18325         #define CFS_FAIL_CHLOG_USER_REG_UNREG_RACE          0x1315
18326         do_nodes $mdts $LCTL set_param fail_loc=0x10001315
18327         do_nodes $mdts $LCTL set_param fail_val=1
18328
18329         # unregister 1st user
18330         changelog_deregister &
18331         local pid1=$!
18332         # wait some time for deregister work to reach race rdv
18333         sleep 2
18334         # register 2nd user
18335         changelog_register || error "2nd user register failed"
18336
18337         wait $pid1 || error "1st user deregister failed"
18338
18339         local i
18340         local last_rec
18341         declare -A LAST_REC
18342         for i in $(seq $MDSCOUNT); do
18343                 if changelog_users mds$i | grep "^cl"; then
18344                         # make sure new records are added with one user present
18345                         LAST_REC[mds$i]=$(changelog_users $SINGLEMDS |
18346                                           awk '/^current.index:/ { print $NF }')
18347                 else
18348                         error "mds$i has no user registered"
18349                 fi
18350         done
18351
18352         # generate more changelog records to accumulate on each MDT
18353         createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
18354                 error "create $DIR/$tdir/${tfile}bis failed"
18355
18356         for i in $(seq $MDSCOUNT); do
18357                 last_rec=$(changelog_users $SINGLEMDS |
18358                            awk '/^current.index:/ { print $NF }')
18359                 echo "verify changelogs are on: $last_rec != ${LAST_REC[mds$i]}"
18360                 [ $last_rec != ${LAST_REC[mds$i]} ] ||
18361                         error "changelogs are off on mds$i"
18362         done
18363 }
18364 run_test 160i "changelog user register/unregister race"
18365
18366 test_160j() {
18367         remote_mds_nodsh && skip "remote MDS with nodsh"
18368         [[ $MDS1_VERSION -lt $(version_code 2.12.56) ]] &&
18369                 skip "Need MDS version at least 2.12.56"
18370
18371         mount_client $MOUNT2 || error "mount_client on $MOUNT2 failed"
18372         stack_trap "umount $MOUNT2" EXIT
18373
18374         changelog_register || error "first changelog_register failed"
18375         stack_trap "changelog_deregister" EXIT
18376
18377         # generate some changelog
18378         # use all_char because created files should be evenly distributed
18379         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
18380                 error "mkdir $tdir failed"
18381         for ((i = 0; i < MDSCOUNT; i++)); do
18382                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
18383                         error "create $DIR/$tdir/d$i.1 failed"
18384         done
18385
18386         # open the changelog device
18387         exec 3>/dev/changelog-$FSNAME-MDT0000
18388         stack_trap "exec 3>&-" EXIT
18389         exec 4</dev/changelog-$FSNAME-MDT0000
18390         stack_trap "exec 4<&-" EXIT
18391
18392         # umount the first lustre mount
18393         umount $MOUNT
18394         stack_trap "mount_client $MOUNT" EXIT
18395
18396         # read changelog, which may or may not fail, but should not crash
18397         cat <&4 >/dev/null
18398
18399         # clear changelog
18400         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
18401         changelog_users $SINGLEMDS | grep -q $cl_user ||
18402                 error "User $cl_user not found in changelog_users"
18403
18404         printf 'clear:'$cl_user':0' >&3
18405 }
18406 run_test 160j "client can be umounted while its chanangelog is being used"
18407
18408 test_160k() {
18409         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18410         remote_mds_nodsh && skip "remote MDS with nodsh"
18411
18412         mkdir -p $DIR/$tdir/1/1
18413
18414         changelog_register || error "changelog_register failed"
18415         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
18416
18417         changelog_users $SINGLEMDS | grep -q $cl_user ||
18418                 error "User '$cl_user' not found in changelog_users"
18419 #define OBD_FAIL_MDS_CHANGELOG_REORDER 0x15d
18420         do_facet mds1 $LCTL set_param fail_loc=0x8000015d fail_val=3
18421         rmdir $DIR/$tdir/1/1 & sleep 1
18422         mkdir $DIR/$tdir/2
18423         touch $DIR/$tdir/2/2
18424         rm -rf $DIR/$tdir/2
18425
18426         wait
18427         sleep 4
18428
18429         changelog_dump | grep rmdir || error "rmdir not recorded"
18430 }
18431 run_test 160k "Verify that changelog records are not lost"
18432
18433 # Verifies that a file passed as a parameter has recently had an operation
18434 # performed on it that has generated an MTIME changelog which contains the
18435 # correct parent FID. As files might reside on a different MDT from the
18436 # parent directory in DNE configurations, the FIDs are translated to paths
18437 # before being compared, which should be identical
18438 compare_mtime_changelog() {
18439         local file="${1}"
18440         local mdtidx
18441         local mtime
18442         local cl_fid
18443         local pdir
18444         local dir
18445
18446         mdtidx=$($LFS getstripe --mdt-index $file)
18447         mdtidx=$(printf "%04x" $mdtidx)
18448
18449         # Obtain the parent FID from the MTIME changelog
18450         mtime=$($LFS changelog $FSNAME-MDT$mdtidx | tail -n 1 | grep MTIME)
18451         [ -z "$mtime" ] && error "MTIME changelog not recorded"
18452
18453         cl_fid=$(sed -e 's/.* p=//' -e 's/ .*//' <<<$mtime)
18454         [ -z "$cl_fid" ] && error "parent FID not present"
18455
18456         # Verify that the path for the parent FID is the same as the path for
18457         # the test directory
18458         pdir=$($LFS fid2path $MOUNT "$cl_fid")
18459
18460         dir=$(dirname $1)
18461
18462         [[ "${pdir%/}" == "$dir" ]] ||
18463                 error "MTIME changelog parent FID is wrong, expected $dir, got $pdir"
18464 }
18465
18466 test_160l() {
18467         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18468
18469         remote_mds_nodsh && skip "remote MDS with nodsh"
18470         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
18471                 skip "Need MDS version at least 2.13.55"
18472
18473         local cl_user
18474
18475         changelog_register || error "changelog_register failed"
18476         cl_user="${CL_USERS[$SINGLEMDS]%% *}"
18477
18478         changelog_users $SINGLEMDS | grep -q $cl_user ||
18479                 error "User '$cl_user' not found in changelog_users"
18480
18481         # Clear some types so that MTIME changelogs are generated
18482         changelog_chmask "-CREAT"
18483         changelog_chmask "-CLOSE"
18484
18485         test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
18486
18487         # Test CL_MTIME during setattr
18488         touch $DIR/$tdir/$tfile
18489         compare_mtime_changelog $DIR/$tdir/$tfile
18490
18491         # Test CL_MTIME during close
18492         $MULTIOP $DIR/$tdir/${tfile}_2 O_2w4096c || error "multiop failed"
18493         compare_mtime_changelog $DIR/$tdir/${tfile}_2
18494 }
18495 run_test 160l "Verify that MTIME changelog records contain the parent FID"
18496
18497 test_160m() {
18498         remote_mds_nodsh && skip "remote MDS with nodsh" && return
18499         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
18500                 skip "Need MDS version at least 2.14.51"
18501         local cl_users
18502         local cl_user1
18503         local cl_user2
18504         local pid1
18505
18506         # Create a user
18507         changelog_register || error "first changelog_register failed"
18508         changelog_register || error "second changelog_register failed"
18509
18510         cl_users=(${CL_USERS[mds1]})
18511         cl_user1="${cl_users[0]}"
18512         cl_user2="${cl_users[1]}"
18513         # generate some changelog records to accumulate on MDT0
18514         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
18515         createmany -m $DIR/$tdir/$tfile 50 ||
18516                 error "create $DIR/$tdir/$tfile failed"
18517         unlinkmany $DIR/$tdir/$tfile 50 || error "unlinkmany failed"
18518         rm -f $DIR/$tdir
18519
18520         # check changelogs have been generated
18521         local nbcl=$(changelog_dump | wc -l)
18522         [[ $nbcl -eq 0 ]] && error "no changelogs found"
18523
18524 #define OBD_FAIL_MDS_CHANGELOG_RACE      0x15f
18525         do_facet mds1 $LCTL set_param fail_loc=0x8000015f fail_val=0
18526
18527         __changelog_clear mds1 $cl_user1 +10
18528         __changelog_clear mds1 $cl_user2 0 &
18529         pid1=$!
18530         sleep 2
18531         __changelog_clear mds1 $cl_user1 0 ||
18532                 error "fail to cancel record for $cl_user1"
18533         wait $pid1
18534         [[ $? -eq 0 ]] || error "fail to cancel record for $cl_user2"
18535 }
18536 run_test 160m "Changelog clear race"
18537
18538 test_160n() {
18539         remote_mds_nodsh && skip "remote MDS with nodsh" && return
18540         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
18541                 skip "Need MDS version at least 2.14.51"
18542         local cl_users
18543         local cl_user1
18544         local cl_user2
18545         local pid1
18546         local first_rec
18547         local last_rec=0
18548
18549         # Create a user
18550         changelog_register || error "first changelog_register failed"
18551
18552         cl_users=(${CL_USERS[mds1]})
18553         cl_user1="${cl_users[0]}"
18554
18555         # generate some changelog records to accumulate on MDT0
18556         test_mkdir -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
18557         first_rec=$(changelog_users $SINGLEMDS |
18558                         awk '/^current.index:/ { print $NF }')
18559         while (( last_rec < (( first_rec + 65000)) )); do
18560                 createmany -m $DIR/$tdir/$tfile 10000 ||
18561                         error "create $DIR/$tdir/$tfile failed"
18562
18563                 for i in $(seq 0 10000); do
18564                         mrename $DIR/$tdir/$tfile$i $DIR/$tdir/$tfile-new$i \
18565                                 > /dev/null
18566                 done
18567
18568                 unlinkmany $DIR/$tdir/$tfile-new 10000 ||
18569                         error "unlinkmany failed unlink"
18570                 last_rec=$(changelog_users $SINGLEMDS |
18571                         awk '/^current.index:/ { print $NF }')
18572                 echo last record $last_rec
18573                 (( last_rec == 0 )) && error "no changelog found"
18574         done
18575
18576 #define OBD_FAIL_MDS_CHANGELOG_DEL       0x16c
18577         do_facet mds1 $LCTL set_param fail_loc=0x8000016c fail_val=0
18578
18579         __changelog_clear mds1 $cl_user1 0 &
18580         pid1=$!
18581         sleep 2
18582         __changelog_clear mds1 $cl_user1 0 ||
18583                 error "fail to cancel record for $cl_user1"
18584         wait $pid1
18585         [[ $? -eq 0 ]] || error "fail to cancel record for $cl_user2"
18586 }
18587 run_test 160n "Changelog destroy race"
18588
18589 test_160o() {
18590         local mdt="$(facet_svc $SINGLEMDS)"
18591
18592         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
18593         remote_mds_nodsh && skip "remote MDS with nodsh"
18594         [ $MDS1_VERSION -ge $(version_code 2.14.52) ] ||
18595                 skip "Need MDS version at least 2.14.52"
18596
18597         changelog_register --user test_160o -m unlnk+close+open ||
18598                 error "changelog_register failed"
18599
18600         do_facet $SINGLEMDS $LCTL --device $mdt \
18601                                 changelog_register -u "Tt3_-#" &&
18602                 error "bad symbols in name should fail"
18603
18604         do_facet $SINGLEMDS $LCTL --device $mdt \
18605                                 changelog_register -u test_160o &&
18606                 error "the same name registration should fail"
18607
18608         do_facet $SINGLEMDS $LCTL --device $mdt \
18609                         changelog_register -u test_160toolongname &&
18610                 error "too long name registration should fail"
18611
18612         changelog_chmask "MARK+HSM"
18613         lctl get_param mdd.*.changelog*mask
18614         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
18615         changelog_users $SINGLEMDS | grep -q $cl_user ||
18616                 error "User $cl_user not found in changelog_users"
18617         #verify username
18618         echo $cl_user | grep -q test_160o ||
18619                 error "User $cl_user has no specific name 'test160o'"
18620
18621         # change something
18622         changelog_clear 0 || error "changelog_clear failed"
18623         # generate some changelog records to accumulate on MDT0
18624         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
18625         touch $DIR/$tdir/$tfile                 # open 1
18626
18627         OPENS=$(changelog_dump | grep -c "OPEN")
18628         [[ $OPENS -eq 1 ]] || error "OPEN changelog mask count $OPENS != 1"
18629
18630         # must be no MKDIR it wasn't set as user mask
18631         MKDIR=$(changelog_dump | grep -c "MKDIR")
18632         [[ $MKDIR -eq 0 ]] || error "MKDIR changelog mask found $MKDIR > 0"
18633
18634         oldmask=$(do_facet $SINGLEMDS $LCTL get_param \
18635                                 mdd.$mdt.changelog_current_mask -n)
18636         # register maskless user
18637         changelog_register || error "changelog_register failed"
18638         # effective mask should be not changed because it is not minimal
18639         mask=$(do_facet $SINGLEMDS $LCTL get_param \
18640                                 mdd.$mdt.changelog_current_mask -n)
18641         [[ $mask == $oldmask ]] || error "mask was changed: $mask vs $oldmask"
18642         # set server mask to minimal value
18643         changelog_chmask "MARK"
18644         # check effective mask again, should be treated as DEFMASK now
18645         mask=$(do_facet $SINGLEMDS $LCTL get_param \
18646                                 mdd.$mdt.changelog_current_mask -n)
18647         [[ $mask == *"HLINK"* ]] || error "mask is not DEFMASK as expected"
18648
18649         if (( $MDS1_VERSION >= $(version_code 2.15.52) )) ; then
18650                 # set server mask back to some value
18651                 changelog_chmask "CLOSE,UNLNK"
18652                 # check effective mask again, should not remain as DEFMASK
18653                 mask=$(do_facet $SINGLEMDS $LCTL get_param \
18654                                 mdd.$mdt.changelog_current_mask -n)
18655                 [[ $mask != *"HLINK"* ]] || error "mask is still DEFMASK"
18656         fi
18657
18658         do_facet $SINGLEMDS $LCTL --device $mdt \
18659                                 changelog_deregister -u test_160o ||
18660                 error "cannot deregister by name"
18661 }
18662 run_test 160o "changelog user name and mask"
18663
18664 test_160p() {
18665         remote_mds_nodsh && skip "remote MDS with nodsh" && return
18666         [[ $MDS1_VERSION -ge $(version_code 2.14.51) ]] ||
18667                 skip "Need MDS version at least 2.14.51"
18668         [[ "$mds1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
18669         local cl_users
18670         local cl_user1
18671         local entry_count
18672
18673         # Create a user
18674         changelog_register || error "first changelog_register failed"
18675
18676         cl_users=(${CL_USERS[mds1]})
18677         cl_user1="${cl_users[0]}"
18678
18679         test_mkdir -p -i0 -c1 $DIR/$tdir || error "test_mkdir $tdir failed"
18680         createmany -m $DIR/$tdir/$tfile 50 ||
18681                 error "create $DIR/$tdir/$tfile failed"
18682         unlinkmany $DIR/$tdir/$tfile 50 || error "unlinkmany failed"
18683         rm -rf $DIR/$tdir
18684
18685         # check changelogs have been generated
18686         entry_count=$(changelog_dump | wc -l)
18687         ((entry_count != 0)) || error "no changelog entries found"
18688
18689         # remove changelog_users and check that orphan entries are removed
18690         stop mds1
18691         local dev=$(mdsdevname 1)
18692         do_facet mds1 "$DEBUGFS -w -R 'rm changelog_users' $dev"
18693         start mds1 $dev $MDS_MOUNT_OPTS || error "cannot start mds1"
18694         entry_count=$(changelog_dump | wc -l)
18695         ((entry_count == 0)) ||
18696                 error "found $entry_count changelog entries, expected none"
18697 }
18698 run_test 160p "Changelog orphan cleanup with no users"
18699
18700 test_160q() {
18701         local mdt="$(facet_svc $SINGLEMDS)"
18702         local clu
18703
18704         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
18705         remote_mds_nodsh && skip "remote MDS with nodsh"
18706         [ $MDS1_VERSION -ge $(version_code 2.14.54) ] ||
18707                 skip "Need MDS version at least 2.14.54"
18708
18709         # set server mask to minimal value like server init does
18710         changelog_chmask "MARK"
18711         clu=$(do_facet $SINGLEMDS $LCTL --device $mdt changelog_register -n) ||
18712                 error "changelog_register failed"
18713         # check effective mask again, should be treated as DEFMASK now
18714         mask=$(do_facet $SINGLEMDS $LCTL get_param \
18715                                 mdd.$mdt.changelog_current_mask -n)
18716         do_facet $SINGLEMDS $LCTL --device $mdt changelog_deregister $clu ||
18717                 error "changelog_deregister failed"
18718         [[ $mask == *"HLINK"* ]] || error "mask is not DEFMASK as expected"
18719 }
18720 run_test 160q "changelog effective mask is DEFMASK if not set"
18721
18722 test_160s() {
18723         remote_mds_nodsh && skip "remote MDS with nodsh"
18724         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
18725                 skip "Need MDS version at least 2.14.55"
18726
18727         local mdts=$(comma_list $(mdts_nodes))
18728
18729         #define OBD_FAIL_TIME_IN_CHLOG_USER     0x1314
18730         do_nodes $mdts $LCTL set_param fail_loc=0x1314 \
18731                                        fail_val=$((24 * 3600 * 10))
18732
18733         # Create a user which is 10 days old
18734         changelog_register || error "first changelog_register failed"
18735         local cl_users
18736         declare -A cl_user1
18737         local i
18738
18739         # generate some changelog records to accumulate on each MDT
18740         # use all_char because created files should be evenly distributed
18741         test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
18742                 error "test_mkdir $tdir failed"
18743         for ((i = 0; i < MDSCOUNT; i++)); do
18744                 $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
18745                         error "create $DIR/$tdir/d$i.1 failed"
18746         done
18747
18748         # check changelogs have been generated
18749         local nbcl=$(changelog_dump | wc -l)
18750         (( nbcl > 0 )) || error "no changelogs found"
18751
18752         # reduce the max_idle_indexes value to make sure we exceed it
18753         for param in "changelog_max_idle_indexes=2097446912" \
18754                      "changelog_max_idle_time=2592000" \
18755                      "changelog_gc=1" \
18756                      "changelog_min_gc_interval=2"; do
18757                 local MDT0=$(facet_svc $SINGLEMDS)
18758                 local var="${param%=*}"
18759                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
18760
18761                 stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
18762                 do_nodes $mdts $LCTL set_param mdd.*.$param ||
18763                         error "unable to set mdd.*.$param"
18764         done
18765
18766         local start=$SECONDS
18767         for i in $(seq $MDSCOUNT); do
18768                 cl_users=(${CL_USERS[mds$i]})
18769                 cl_user1[mds$i]="${cl_users[0]}"
18770
18771                 [[ -n "${cl_user1[mds$i]}" ]] ||
18772                         error "mds$i: no user registered"
18773         done
18774
18775         #define OBD_FAIL_MDS_CHANGELOG_IDX_PUMP   0x16d
18776         do_nodes $mdts $LCTL set_param fail_loc=0x16d fail_val=500000000
18777
18778         # ensure we are past the previous changelog_min_gc_interval set above
18779         local sleep2=$((start + 2 - SECONDS))
18780         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
18781
18782         # Generate one more changelog to trigger GC
18783         for ((i = 0; i < MDSCOUNT; i++)); do
18784                 $LFS mkdir -i $i $DIR/$tdir/d$i.3 $DIR/$tdir/d$i.4 ||
18785                         error "create $DIR/$tdir/d$i.3 failed"
18786         done
18787
18788         # ensure gc thread is done
18789         for node in $(mdts_nodes); do
18790                 wait_update $node "pgrep chlg_gc_thread" "" 20 ||
18791                         error "$node: GC-thread not done"
18792         done
18793
18794         do_nodes $mdts $LCTL set_param fail_loc=0
18795
18796         for (( i = 1; i <= MDSCOUNT; i++ )); do
18797                 # check cl_user1 is purged
18798                 changelog_users mds$i | grep -q "${cl_user1[mds$i]}" &&
18799                         error "mds$i: User ${cl_user1[mds$i]} is registered"
18800         done
18801         return 0
18802 }
18803 run_test 160s "changelog garbage collect on idle records * time"
18804
18805 test_160t() {
18806         remote_mds_nodsh && skip "remote MDS with nodsh"
18807         (( $MDS1_VERSION >= $(version_code 2.15.50) )) ||
18808                 skip "Need MDS version at least 2.15.50"
18809
18810         local MDT0=$(facet_svc $SINGLEMDS)
18811         local cl_users
18812         local cl_user1
18813         local cl_user2
18814         local start
18815
18816         changelog_register --user user1 -m all ||
18817                 error "user1 failed to register"
18818
18819         mkdir_on_mdt0 $DIR/$tdir
18820         # create default overstripe to maximize changelog size
18821         $LFS setstripe  -C 8 $DIR/$tdir || error "setstripe failed"
18822         createmany -o $DIR/$tdir/u1_ 2000 || error "createmany for user1 failed"
18823         llog_size1=$(do_facet mds1 $LCTL get_param -n mdd.$MDT0.changelog_size)
18824
18825         # user2 consumes less records so less space
18826         changelog_register --user user2 || error "user2 failed to register"
18827         createmany -o $DIR/$tdir/u2_ 500 || error "createmany for user2 failed"
18828         llog_size2=$(do_facet mds1 $LCTL get_param -n mdd.$MDT0.changelog_size)
18829
18830         # check changelogs have been generated
18831         local nbcl=$(changelog_dump | wc -l)
18832         (( nbcl > 0 )) || error "no changelogs found"
18833
18834         # reduce the changelog_min_gc_interval to force check
18835         for param in "changelog_gc=1" "changelog_min_gc_interval=2"; do
18836                 local var="${param%=*}"
18837                 local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
18838
18839                 stack_trap "do_facet mds1 $LCTL set_param mdd.$MDT0.$var=$old"
18840                 do_facet mds1 $LCTL set_param mdd.$MDT0.$param ||
18841                         error "unable to set mdd.*.$param"
18842         done
18843
18844         start=$SECONDS
18845         cl_users=(${CL_USERS[mds1]})
18846         cl_user1="${cl_users[0]}"
18847         cl_user2="${cl_users[1]}"
18848
18849         [[ -n $cl_user1 ]] ||
18850                 error "mds1: user #1 isn't registered"
18851         [[ -n $cl_user2 ]] ||
18852                 error "mds1: user #2 isn't registered"
18853
18854         # ensure we are past the previous changelog_min_gc_interval set above
18855         local sleep2=$((start + 2 - SECONDS))
18856         (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
18857
18858         #define OBD_FAIL_MDS_CHANGELOG_ENOSPC 0x018c
18859         do_facet mds1 $LCTL set_param fail_loc=0x018c \
18860                         fail_val=$(((llog_size1 + llog_size2) / 2))
18861
18862         # Generate more changelog to trigger GC
18863         createmany -o $DIR/$tdir/u3_ 4 ||
18864                 error "create failed for more files"
18865
18866         # ensure gc thread is done
18867         wait_update_facet mds1 "pgrep chlg_gc_thread" "" 20 ||
18868                 error "mds1: GC-thread not done"
18869
18870         do_facet mds1 $LCTL set_param fail_loc=0
18871
18872         # check cl_user1 is purged
18873         changelog_users mds1 | grep -q "$cl_user1" &&
18874                 error "User $cl_user1 is registered"
18875         # check cl_user2 is not purged
18876         changelog_users mds1 | grep -q "$cl_user2" ||
18877                 error "User $cl_user2 is not registered"
18878 }
18879 run_test 160t "changelog garbage collect on lack of space"
18880
18881 test_160u() { # LU-17400
18882         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18883         remote_mds_nodsh && skip "remote MDS with nodsh"
18884         [ $MDS1_VERSION -ge $(version_code 2.2.0) ] ||
18885                 skip "Need MDS version at least 2.2.0"
18886
18887         cd $DIR || error "cd $DIR failed"
18888
18889         # ensure changelog has a clean view if tests are run multiple times
18890         [ -d rename ] && rm -rf rename
18891
18892         changelog_register || error "changelog_register failed"
18893         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
18894
18895         changelog_users $SINGLEMDS | grep -q $cl_user ||
18896                 error "User '$cl_user' not found in changelog_users"
18897
18898         local longname1=$(str_repeat a 255)
18899
18900         echo "creating simple directory tree"
18901         mkdir -p rename/a || error "create of simple directory tree failed"
18902         echo "creating rename/hw file"
18903         echo "hello world" > rename/hw || error "create of rename/hw failed"
18904         echo "creating very long named file"
18905         touch rename/$longname1 || error "create of 'rename/$longname1' failed"
18906         echo "move rename/hw to rename/a/a.hw"
18907         mv rename/hw rename/a/a.hw || error "mv failed"
18908
18909         RENME=($(changelog_dump | grep "RENME"))
18910         #declare -p RENME # for debugging captured value with indexes
18911
18912         [[ "${RENME[11]}" == "a.hw" && "${RENME[14]}" == "hw" ]] ||
18913                 error "changelog rename record type name/sname error"
18914 }
18915 run_test 160u "changelog rename record type name and sname strings are correct"
18916
18917 test_161a() {
18918         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18919
18920         test_mkdir -c1 $DIR/$tdir
18921         cp /etc/hosts $DIR/$tdir/$tfile
18922         test_mkdir -c1 $DIR/$tdir/foo1
18923         test_mkdir -c1 $DIR/$tdir/foo2
18924         ln $DIR/$tdir/$tfile $DIR/$tdir/foo1/sofia
18925         ln $DIR/$tdir/$tfile $DIR/$tdir/foo2/zachary
18926         ln $DIR/$tdir/$tfile $DIR/$tdir/foo1/luna
18927         ln $DIR/$tdir/$tfile $DIR/$tdir/foo2/thor
18928         local FID=$($LFS path2fid $DIR/$tdir/$tfile | tr -d '[]')
18929         if [ "$($LFS fid2path $DIR $FID | wc -l)" != "5" ]; then
18930                 $LFS fid2path $DIR $FID
18931                 error "bad link ea"
18932         fi
18933         # middle
18934         rm $DIR/$tdir/foo2/zachary
18935         # last
18936         rm $DIR/$tdir/foo2/thor
18937         # first
18938         rm $DIR/$tdir/$tfile
18939         # rename
18940         mv $DIR/$tdir/foo1/sofia $DIR/$tdir/foo2/maggie
18941         [ "$($LFS fid2path $FSNAME --link 1 $FID)" != "$tdir/foo2/maggie" ] &&
18942                 { $LFS fid2path $DIR $FID; error "bad link rename"; }
18943         rm $DIR/$tdir/foo2/maggie
18944
18945         # overflow the EA
18946         local longname=$tfile.avg_len_is_thirty_two_
18947         stack_trap "unlinkmany $DIR/$tdir/foo2/$longname 1000 || \
18948                 error_noexit 'failed to unlink many hardlinks'" EXIT
18949         createmany -l$DIR/$tdir/foo1/luna $DIR/$tdir/foo2/$longname 1000 ||
18950                 error "failed to hardlink many files"
18951         links=$($LFS fid2path $DIR $FID | wc -l)
18952         echo -n "${links}/1000 links in link EA"
18953         [[ $links -gt 60 ]] || error "expected at least 60 links in link EA"
18954 }
18955 run_test 161a "link ea sanity"
18956
18957 test_161b() {
18958         [ $PARALLEL == "yes" ] && skip "skip parallel run"
18959         [ $MDSCOUNT -lt 2 ] && skip_env "skipping remote directory test"
18960
18961         local MDTIDX=1
18962         local remote_dir=$DIR/$tdir/remote_dir
18963
18964         mkdir -p $DIR/$tdir
18965         $LFS mkdir -i $MDTIDX $remote_dir ||
18966                 error "create remote directory failed"
18967
18968         cp /etc/hosts $remote_dir/$tfile
18969         mkdir -p $remote_dir/foo1
18970         mkdir -p $remote_dir/foo2
18971         ln $remote_dir/$tfile $remote_dir/foo1/sofia
18972         ln $remote_dir/$tfile $remote_dir/foo2/zachary
18973         ln $remote_dir/$tfile $remote_dir/foo1/luna
18974         ln $remote_dir/$tfile $remote_dir/foo2/thor
18975
18976         local FID=$($LFS path2fid $remote_dir/$tfile | tr -d '[' |
18977                      tr -d ']')
18978         if [ "$($LFS fid2path $DIR $FID | wc -l)" != "5" ]; then
18979                 $LFS fid2path $DIR $FID
18980                 error "bad link ea"
18981         fi
18982         # middle
18983         rm $remote_dir/foo2/zachary
18984         # last
18985         rm $remote_dir/foo2/thor
18986         # first
18987         rm $remote_dir/$tfile
18988         # rename
18989         mv $remote_dir/foo1/sofia $remote_dir/foo2/maggie
18990         local link_path=$($LFS fid2path $FSNAME --link 1 $FID)
18991         if [ "$DIR/$link_path" != "$remote_dir/foo2/maggie" ]; then
18992                 $LFS fid2path $DIR $FID
18993                 error "bad link rename"
18994         fi
18995         rm $remote_dir/foo2/maggie
18996
18997         # overflow the EA
18998         local longname=filename_avg_len_is_thirty_two_
18999         createmany -l$remote_dir/foo1/luna $remote_dir/foo2/$longname 1000 ||
19000                 error "failed to hardlink many files"
19001         links=$($LFS fid2path $DIR $FID | wc -l)
19002         echo -n "${links}/1000 links in link EA"
19003         [[ ${links} -gt 60 ]] ||
19004                 error "expected at least 60 links in link EA"
19005         unlinkmany $remote_dir/foo2/$longname 1000 ||
19006         error "failed to unlink many hardlinks"
19007 }
19008 run_test 161b "link ea sanity under remote directory"
19009
19010 test_161c() {
19011         remote_mds_nodsh && skip "remote MDS with nodsh"
19012         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19013         [[ $MDS1_VERSION -lt $(version_code 2.1.5) ]] &&
19014                 skip "Need MDS version at least 2.1.5"
19015
19016         # define CLF_RENAME_LAST 0x0001
19017         # rename overwrite a target having nlink = 1 (changelog flag 0x1)
19018         changelog_register || error "changelog_register failed"
19019
19020         rm -rf $DIR/$tdir
19021         test_mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir
19022         touch $DIR/$tdir/foo_161c
19023         touch $DIR/$tdir/bar_161c
19024         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/bar_161c
19025         changelog_dump | grep RENME | tail -n 5
19026         local flags=$(changelog_dump | grep "RENME.*bar_161c" | cut -f5 -d' ')
19027         changelog_clear 0 || error "changelog_clear failed"
19028         if [ x$flags != "x0x1" ]; then
19029                 error "flag $flags is not 0x1"
19030         fi
19031
19032         echo "rename overwrite target with nlink = 1, changelog flags=$flags"
19033         # rename overwrite a target having nlink > 1 (changelog flag 0x0)
19034         touch $DIR/$tdir/foo_161c
19035         touch $DIR/$tdir/bar_161c
19036         ln $DIR/$tdir/bar_161c $DIR/$tdir/foobar_161c
19037         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/bar_161c
19038         changelog_dump | grep RENME | tail -n 5
19039         flags=$(changelog_dump | grep "RENME.*bar_161c" | cut -f5 -d' ')
19040         changelog_clear 0 || error "changelog_clear failed"
19041         if [ x$flags != "x0x0" ]; then
19042                 error "flag $flags is not 0x0"
19043         fi
19044         echo "rename overwrite a target having nlink > 1," \
19045                 "changelog record has flags of $flags"
19046
19047         # rename doesn't overwrite a target (changelog flag 0x0)
19048         touch $DIR/$tdir/foo_161c
19049         mv -f $DIR/$tdir/foo_161c $DIR/$tdir/foo2_161c
19050         changelog_dump | grep RENME | tail -n 5
19051         flags=$(changelog_dump | grep RENME | tail -1 | cut -f5 -d' ')
19052         changelog_clear 0 || error "changelog_clear failed"
19053         if [ x$flags != "x0x0" ]; then
19054                 error "flag $flags is not 0x0"
19055         fi
19056         echo "rename doesn't overwrite a target," \
19057                 "changelog record has flags of $flags"
19058
19059         # define CLF_UNLINK_LAST 0x0001
19060         # unlink a file having nlink = 1 (changelog flag 0x1)
19061         rm -f $DIR/$tdir/foo2_161c
19062         changelog_dump | grep UNLNK | tail -n 5
19063         flags=$(changelog_dump | grep UNLNK | tail -1 | cut -f5 -d' ')
19064         changelog_clear 0 || error "changelog_clear failed"
19065         if [ x$flags != "x0x1" ]; then
19066                 error "flag $flags is not 0x1"
19067         fi
19068         echo "unlink a file having nlink = 1," \
19069                 "changelog record has flags of $flags"
19070
19071         # unlink a file having nlink > 1 (changelog flag 0x0)
19072         ln -f $DIR/$tdir/bar_161c $DIR/$tdir/foobar_161c
19073         rm -f $DIR/$tdir/foobar_161c
19074         changelog_dump | grep UNLNK | tail -n 5
19075         flags=$(changelog_dump | grep UNLNK | tail -1 | cut -f5 -d' ')
19076         changelog_clear 0 || error "changelog_clear failed"
19077         if [ x$flags != "x0x0" ]; then
19078                 error "flag $flags is not 0x0"
19079         fi
19080         echo "unlink a file having nlink > 1, changelog record flags '$flags'"
19081 }
19082 run_test 161c "check CL_RENME[UNLINK] changelog record flags"
19083
19084 test_161d() {
19085         remote_mds_nodsh && skip "remote MDS with nodsh"
19086         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
19087
19088         local pid
19089         local fid
19090
19091         changelog_register || error "changelog_register failed"
19092
19093         # work in a standalone dir to avoid locking on $DIR/$MOUNT to
19094         # interfer with $MOUNT/.lustre/fid/ access
19095         mkdir $DIR/$tdir
19096         [[ $? -eq 0 ]] || error "mkdir failed"
19097
19098         #define OBD_FAIL_LLITE_CREATE_NODE_PAUSE 0x140c | CFS_FAIL_ONCE
19099         $LCTL set_param fail_loc=0x8000140c
19100         # 5s pause
19101         $LCTL set_param fail_val=5
19102
19103         # create file
19104         echo foofoo > $DIR/$tdir/$tfile &
19105         pid=$!
19106
19107         # wait for create to be delayed
19108         sleep 2
19109
19110         ps -p $pid
19111         [[ $? -eq 0 ]] || error "create should be blocked"
19112
19113         local tempfile="$(mktemp --tmpdir $tfile.XXXXXX)"
19114         stack_trap "rm -f $tempfile"
19115         fid=$(changelog_extract_field "CREAT" "$tfile" "t=")
19116         cat $MOUNT/.lustre/fid/$fid 2>/dev/null >$tempfile || error "cat failed"
19117         # some delay may occur during ChangeLog publishing and file read just
19118         # above, that could allow file write to happen finally
19119         [[ -s $tempfile ]] && echo "file should be empty"
19120
19121         $LCTL set_param fail_loc=0
19122
19123         wait $pid
19124         [[ $? -eq 0 ]] || error "create failed"
19125 }
19126 run_test 161d "create with concurrent .lustre/fid access"
19127
19128 check_path() {
19129         local expected="$1"
19130         shift
19131         local fid="$2"
19132
19133         local path
19134         path=$($LFS fid2path "$@")
19135         local rc=$?
19136
19137         if [ $rc -ne 0 ]; then
19138                 error "path looked up of '$expected' failed: rc=$rc"
19139         elif [ "$path" != "$expected" ]; then
19140                 error "path looked up '$path' instead of '$expected'"
19141         else
19142                 echo "FID '$fid' resolves to path '$path' as expected"
19143         fi
19144 }
19145
19146 test_162a() { # was test_162
19147         test_mkdir -p -c1 $DIR/$tdir/d2
19148         touch $DIR/$tdir/d2/$tfile
19149         touch $DIR/$tdir/d2/x1
19150         touch $DIR/$tdir/d2/x2
19151         test_mkdir -p -c1 $DIR/$tdir/d2/a/b/c
19152         test_mkdir -p -c1 $DIR/$tdir/d2/p/q/r
19153         # regular file
19154         local fid=$($LFS path2fid $DIR/$tdir/d2/$tfile | tr -d '[]')
19155         check_path "$tdir/d2/$tfile" $FSNAME "$fid" --link 0
19156
19157         # softlink
19158         ln -s $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/p/q/r/slink
19159         fid=$($LFS path2fid $DIR/$tdir/d2/p/q/r/slink | tr -d '[]')
19160         check_path "$tdir/d2/p/q/r/slink" $FSNAME "$fid" --link 0
19161
19162         # softlink to wrong file
19163         ln -s /this/is/garbage $DIR/$tdir/d2/p/q/r/slink.wrong
19164         fid=$($LFS path2fid $DIR/$tdir/d2/p/q/r/slink.wrong | tr -d '[]')
19165         check_path "$tdir/d2/p/q/r/slink.wrong" $FSNAME "$fid" --link 0
19166
19167         # hardlink
19168         ln $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/p/q/r/hlink
19169         mv $DIR/$tdir/d2/$tfile $DIR/$tdir/d2/a/b/c/new_file
19170         fid=$($LFS path2fid $DIR/$tdir/d2/a/b/c/new_file | tr -d '[]')
19171         # fid2path dir/fsname should both work
19172         check_path "$tdir/d2/a/b/c/new_file" $FSNAME "$fid" --link 1
19173         check_path "$DIR/$tdir/d2/p/q/r/hlink" $DIR "$fid" --link 0
19174
19175         # hardlink count: check that there are 2 links
19176         local nlinks=$($LFS fid2path $DIR "$fid" | wc -l)
19177         [ $nlinks -eq 2 ] || error "expect 2 links, found $nlinks"
19178
19179         # hardlink indexing: remove the first link
19180         rm $DIR/$tdir/d2/p/q/r/hlink
19181         check_path "$tdir/d2/a/b/c/new_file" $FSNAME $fid --link 0
19182 }
19183 run_test 162a "path lookup sanity"
19184
19185 test_162b() {
19186         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19187         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
19188
19189         mkdir $DIR/$tdir
19190         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
19191                                 error "create striped dir failed"
19192
19193         local FID=$($LFS getdirstripe $DIR/$tdir/striped_dir |
19194                                         tail -n 1 | awk '{print $2}')
19195         stat $MOUNT/.lustre/fid/$FID && error "sub_stripe can be accessed"
19196
19197         touch $DIR/$tdir/striped_dir/f{0..4} || error "touch f0..4 failed"
19198         mkdir $DIR/$tdir/striped_dir/d{0..4} || error "mkdir d0..4 failed"
19199
19200         # regular file
19201         for ((i=0;i<5;i++)); do
19202                 FID=$($LFS path2fid $DIR/$tdir/striped_dir/f$i | tr -d '[]') ||
19203                         error "get fid for f$i failed"
19204                 check_path "$tdir/striped_dir/f$i" $FSNAME $FID --link 0
19205
19206                 FID=$($LFS path2fid $DIR/$tdir/striped_dir/d$i | tr -d '[]') ||
19207                         error "get fid for d$i failed"
19208                 check_path "$tdir/striped_dir/d$i" $FSNAME $FID --link 0
19209         done
19210
19211         return 0
19212 }
19213 run_test 162b "striped directory path lookup sanity"
19214
19215 # LU-4239: Verify fid2path works with paths 100 or more directories deep
19216 test_162c() {
19217         [[ $MDS1_VERSION -lt $(version_code 2.7.51) ]] &&
19218                 skip "Need MDS version at least 2.7.51"
19219
19220         local lpath=$tdir.local
19221         local rpath=$tdir.remote
19222
19223         test_mkdir $DIR/$lpath
19224         test_mkdir $DIR/$rpath
19225
19226         for ((i = 0; i <= 101; i++)); do
19227                 lpath="$lpath/$i"
19228                 mkdir $DIR/$lpath
19229                 FID=$($LFS path2fid $DIR/$lpath | tr -d '[]') ||
19230                         error "get fid for local directory $DIR/$lpath failed"
19231                 check_path "$DIR/$lpath" $MOUNT $FID --link 0
19232
19233                 rpath="$rpath/$i"
19234                 test_mkdir $DIR/$rpath
19235                 FID=$($LFS path2fid $DIR/$rpath | tr -d '[]') ||
19236                         error "get fid for remote directory $DIR/$rpath failed"
19237                 check_path "$DIR/$rpath" $MOUNT $FID --link 0
19238         done
19239
19240         return 0
19241 }
19242 run_test 162c "fid2path works with paths 100 or more directories deep"
19243
19244 oalr_event_count() {
19245         local event="${1}"
19246         local trace="${2}"
19247
19248         awk -v name="${FSNAME}-OST0000" \
19249             -v event="${event}" \
19250             '$1 == "TRACE" && $2 == event && $3 == name' \
19251             "${trace}" |
19252         wc -l
19253 }
19254
19255 oalr_expect_event_count() {
19256         local event="${1}"
19257         local trace="${2}"
19258         local expect="${3}"
19259         local count
19260
19261         count=$(oalr_event_count "${event}" "${trace}")
19262         if ((count == expect)); then
19263                 return 0
19264         fi
19265
19266         error_noexit "${event} event count was '${count}', expected ${expect}"
19267         cat "${trace}" >&2
19268         exit 1
19269 }
19270
19271 cleanup_165() {
19272         do_facet ost1 killall --quiet -KILL ofd_access_log_reader || true
19273         stop ost1
19274         start ost1 "$(ostdevname 1)" $OST_MOUNT_OPTS
19275 }
19276
19277 setup_165() {
19278         sync # Flush previous IOs so we can count log entries.
19279         do_facet ost1 $LCTL set_param "obdfilter.${FSNAME}-OST0000.access_log_size=4096"
19280         stack_trap cleanup_165 EXIT
19281 }
19282
19283 test_165a() {
19284         local trace="/tmp/${tfile}.trace"
19285         local rc
19286         local count
19287
19288         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
19289                 skip "OFD access log unsupported"
19290
19291         setup_165
19292         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
19293         sleep 5
19294
19295         do_facet ost1 ofd_access_log_reader --list
19296         stop ost1
19297
19298         do_facet ost1 killall -TERM ofd_access_log_reader
19299         wait
19300         rc=$?
19301
19302         if ((rc != 0)); then
19303                 error "ofd_access_log_reader exited with rc = '${rc}'"
19304         fi
19305
19306         # Parse trace file for discovery events:
19307         oalr_expect_event_count alr_log_add "${trace}" 1
19308         oalr_expect_event_count alr_log_eof "${trace}" 1
19309         oalr_expect_event_count alr_log_free "${trace}" 1
19310 }
19311 run_test 165a "ofd access log discovery"
19312
19313 test_165b() {
19314         local trace="/tmp/${tfile}.trace"
19315         local file="${DIR}/${tfile}"
19316         local pfid1
19317         local pfid2
19318         local -a entry
19319         local rc
19320         local count
19321         local size
19322         local flags
19323
19324         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
19325                 skip "OFD access log unsupported"
19326
19327         setup_165
19328         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
19329         sleep 5
19330
19331         do_facet ost1 ofd_access_log_reader --list
19332
19333         lfs setstripe -c 1 -i 0 "${file}"
19334         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
19335                 error "cannot create '${file}'"
19336
19337         sleep 5
19338         do_facet ost1 killall -TERM ofd_access_log_reader
19339         wait
19340         rc=$?
19341
19342         if ((rc != 0)); then
19343                 error "ofd_access_log_reader exited with rc = '${rc}'"
19344         fi
19345
19346         oalr_expect_event_count alr_log_entry "${trace}" 1
19347
19348         pfid1=$($LFS path2fid "${file}")
19349
19350         # 1     2             3   4    5     6   7    8    9     10
19351         # TRACE alr_log_entry OST PFID BEGIN END TIME SIZE COUNT FLAGS
19352         entry=( - $(awk -v pfid="${pfid}" '$1 == "TRACE" && $2 == "alr_log_entry"' "${trace}" ) )
19353
19354         echo "entry = '${entry[*]}'" >&2
19355
19356         pfid2=${entry[4]}
19357         if [[ "${pfid1}" != "${pfid2}" ]]; then
19358                 error "entry '${entry[*]}' has invalid PFID '${pfid2}', expected ${pfid1}"
19359         fi
19360
19361         size=${entry[8]}
19362         if ((size != 1048576)); then
19363                 error "entry '${entry[*]}' has invalid io size '${size}', expected 1048576"
19364         fi
19365
19366         flags=${entry[10]}
19367         if [[ "${flags}" != "w" ]]; then
19368                 error "entry '${entry[*]}' has invalid io flags '${flags}', expected 'w'"
19369         fi
19370
19371         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
19372         sleep 5
19373
19374         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r524288c ||
19375                 error "cannot read '${file}'"
19376         sleep 5
19377
19378         do_facet ost1 killall -TERM ofd_access_log_reader
19379         wait
19380         rc=$?
19381
19382         if ((rc != 0)); then
19383                 error "ofd_access_log_reader exited with rc = '${rc}'"
19384         fi
19385
19386         oalr_expect_event_count alr_log_entry "${trace}" 1
19387
19388         entry=( - $(awk -v pfid="${pfid}" '$1 == "TRACE" && $2 == "alr_log_entry"' "${trace}" ) )
19389         echo "entry = '${entry[*]}'" >&2
19390
19391         pfid2=${entry[4]}
19392         if [[ "${pfid1}" != "${pfid2}" ]]; then
19393                 error "entry '${entry[*]}' has invalid PFID '${pfid2}', expected ${pfid1}"
19394         fi
19395
19396         size=${entry[8]}
19397         if ((size != 524288)); then
19398                 error "entry '${entry[*]}' has invalid io size '${size}', 524288"
19399         fi
19400
19401         flags=${entry[10]}
19402         if [[ "${flags}" != "r" ]]; then
19403                 error "entry '${entry[*]}' has invalid io flags '${flags}', expected 'r'"
19404         fi
19405 }
19406 run_test 165b "ofd access log entries are produced and consumed"
19407
19408 test_165c() {
19409         local trace="/tmp/${tfile}.trace"
19410         local file="${DIR}/${tdir}/${tfile}"
19411
19412         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
19413                 skip "OFD access log unsupported"
19414
19415         test_mkdir "${DIR}/${tdir}"
19416
19417         setup_165
19418         do_facet ost1 ofd_access_log_reader --debug=- --trace=- > "${trace}" &
19419         sleep 5
19420
19421         lfs setstripe -c 1 -i 0 "${DIR}/${tdir}"
19422
19423         # 4096 / 64 = 64. Create twice as many entries.
19424         for ((i = 0; i < 128; i++)); do
19425                 $MULTIOP "${file}-${i}" oO_CREAT:O_WRONLY:w512c ||
19426                         error "cannot create file"
19427         done
19428
19429         sync
19430
19431         do_facet ost1 killall -TERM ofd_access_log_reader
19432         wait
19433         rc=$?
19434         if ((rc != 0)); then
19435                 error "ofd_access_log_reader exited with rc = '${rc}'"
19436         fi
19437
19438         unlinkmany  "${file}-%d" 128
19439 }
19440 run_test 165c "full ofd access logs do not block IOs"
19441
19442 oal_get_read_count() {
19443         local stats="$1"
19444
19445         # STATS lustre-OST0001 alr_read_count 1
19446
19447         do_facet ost1 cat "${stats}" |
19448         awk '$1 == "STATS" && $3 == "alr_read_count" { count = $4; }
19449              END { print count; }'
19450 }
19451
19452 oal_expect_read_count() {
19453         local stats="$1"
19454         local count
19455         local expect="$2"
19456
19457         # Ask ofd_access_log_reader to write stats.
19458         do_facet ost1 killall -USR1 ofd_access_log_reader
19459
19460         # Allow some time for things to happen.
19461         sleep 1
19462
19463         count=$(oal_get_read_count "${stats}")
19464         if ((count == expect)); then
19465                 return 0
19466         fi
19467
19468         error_noexit "bad read count, got ${count}, expected ${expect}"
19469         do_facet ost1 cat "${stats}" >&2
19470         exit 1
19471 }
19472
19473 test_165d() {
19474         local stats="/tmp/${tfile}.stats"
19475         local file="${DIR}/${tdir}/${tfile}"
19476         local param="obdfilter.${FSNAME}-OST0000.access_log_mask"
19477
19478         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
19479                 skip "OFD access log unsupported"
19480
19481         test_mkdir "${DIR}/${tdir}"
19482
19483         setup_165
19484         do_facet ost1 ofd_access_log_reader --stats="${stats}" &
19485         sleep 5
19486
19487         lfs setstripe -c 1 -i 0 "${file}"
19488
19489         do_facet ost1 lctl set_param "${param}=rw"
19490         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
19491                 error "cannot create '${file}'"
19492         oal_expect_read_count "${stats}" 1
19493
19494         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
19495                 error "cannot read '${file}'"
19496         oal_expect_read_count "${stats}" 2
19497
19498         do_facet ost1 lctl set_param "${param}=r"
19499         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
19500                 error "cannot create '${file}'"
19501         oal_expect_read_count "${stats}" 2
19502
19503         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
19504                 error "cannot read '${file}'"
19505         oal_expect_read_count "${stats}" 3
19506
19507         do_facet ost1 lctl set_param "${param}=w"
19508         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
19509                 error "cannot create '${file}'"
19510         oal_expect_read_count "${stats}" 4
19511
19512         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
19513                 error "cannot read '${file}'"
19514         oal_expect_read_count "${stats}" 4
19515
19516         do_facet ost1 lctl set_param "${param}=0"
19517         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_WRONLY:w1048576c ||
19518                 error "cannot create '${file}'"
19519         oal_expect_read_count "${stats}" 4
19520
19521         $MULTIOP "${file}" oO_CREAT:O_DIRECT:O_RDONLY:r1048576c ||
19522                 error "cannot read '${file}'"
19523         oal_expect_read_count "${stats}" 4
19524
19525         do_facet ost1 killall -TERM ofd_access_log_reader
19526         wait
19527         rc=$?
19528         if ((rc != 0)); then
19529                 error "ofd_access_log_reader exited with rc = '${rc}'"
19530         fi
19531 }
19532 run_test 165d "ofd_access_log mask works"
19533
19534 test_165e() {
19535         local stats="/tmp/${tfile}.stats"
19536         local file0="${DIR}/${tdir}-0/${tfile}"
19537         local file1="${DIR}/${tdir}-1/${tfile}"
19538
19539         (( $OST1_VERSION >= $(version_code 2.13.54) )) ||
19540                 skip "OFD access log unsupported"
19541
19542         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
19543
19544         test_mkdir -c 1 -i 0 "${DIR}/${tdir}-0"
19545         test_mkdir -c 1 -i 1 "${DIR}/${tdir}-1"
19546
19547         lfs setstripe -c 1 -i 0 "${file0}"
19548         lfs setstripe -c 1 -i 0 "${file1}"
19549
19550         setup_165
19551         do_facet ost1 ofd_access_log_reader -I 1 --stats="${stats}" &
19552         sleep 5
19553
19554         $MULTIOP "${file0}" oO_CREAT:O_WRONLY:w512c ||
19555                 error "cannot create '${file0}'"
19556         sync
19557         oal_expect_read_count "${stats}" 0
19558
19559         $MULTIOP "${file1}" oO_CREAT:O_WRONLY:w512c ||
19560                 error "cannot create '${file1}'"
19561         sync
19562         oal_expect_read_count "${stats}" 1
19563
19564         do_facet ost1 killall -TERM ofd_access_log_reader
19565         wait
19566         rc=$?
19567         if ((rc != 0)); then
19568                 error "ofd_access_log_reader exited with rc = '${rc}'"
19569         fi
19570 }
19571 run_test 165e "ofd_access_log MDT index filter works"
19572
19573 test_165f() {
19574         local trace="/tmp/${tfile}.trace"
19575         local rc
19576         local count
19577
19578         setup_165
19579         do_facet ost1 timeout 60 ofd_access_log_reader \
19580                 --exit-on-close --debug=- --trace=- > "${trace}" &
19581         sleep 5
19582         stop ost1
19583
19584         wait
19585         rc=$?
19586
19587         if ((rc != 0)); then
19588                 error_noexit "ofd_access_log_reader exited with rc = '${rc}'"
19589                 cat "${trace}"
19590                 exit 1
19591         fi
19592 }
19593 run_test 165f "ofd_access_log_reader --exit-on-close works"
19594
19595 test_169() {
19596         # do directio so as not to populate the page cache
19597         log "creating a 10 Mb file"
19598         $MULTIOP $DIR/$tfile oO_CREAT:O_DIRECT:O_RDWR:w$((10*1048576))c ||
19599                 error "multiop failed while creating a file"
19600         log "starting reads"
19601         dd if=$DIR/$tfile of=/dev/null bs=4096 &
19602         log "truncating the file"
19603         $MULTIOP $DIR/$tfile oO_TRUNC:c ||
19604                 error "multiop failed while truncating the file"
19605         log "killing dd"
19606         kill %+ || true # reads might have finished
19607         echo "wait until dd is finished"
19608         wait
19609         log "removing the temporary file"
19610         rm -rf $DIR/$tfile || error "tmp file removal failed"
19611 }
19612 run_test 169 "parallel read and truncate should not deadlock"
19613
19614 test_170() {
19615         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19616
19617         $LCTL clear     # bug 18514
19618         $LCTL debug_daemon start $TMP/${tfile}_log_good
19619         touch $DIR/$tfile
19620         $LCTL debug_daemon stop
19621         sed -e "s/^...../a/g" $TMP/${tfile}_log_good > $TMP/${tfile}_log_bad ||
19622                 error "sed failed to read log_good"
19623
19624         $LCTL debug_daemon start $TMP/${tfile}_log_good
19625         rm -rf $DIR/$tfile
19626         $LCTL debug_daemon stop
19627
19628         $LCTL df $TMP/${tfile}_log_bad > $TMP/${tfile}_log_bad.out 2>&1 ||
19629                error "lctl df log_bad failed"
19630
19631         local bad_line=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $9}')
19632         local good_line1=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $5}')
19633
19634         $LCTL df $TMP/${tfile}_log_good > $TMP/${tfile}_log_good.out 2>&1
19635         local good_line2=$(tail -n 1 $TMP/${tfile}_log_good.out | awk '{print $5}')
19636
19637         [ "$bad_line" ] && [ "$good_line1" ] && [ "$good_line2" ] ||
19638                 error "bad_line good_line1 good_line2 are empty"
19639
19640         cat $TMP/${tfile}_log_good >> $TMP/${tfile}_logs_corrupt
19641         cat $TMP/${tfile}_log_bad >> $TMP/${tfile}_logs_corrupt
19642         cat $TMP/${tfile}_log_good >> $TMP/${tfile}_logs_corrupt
19643
19644         $LCTL df $TMP/${tfile}_logs_corrupt > $TMP/${tfile}_log_bad.out 2>&1
19645         local bad_line_new=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $9}')
19646         local good_line_new=$(tail -n 1 $TMP/${tfile}_log_bad.out | awk '{print $5}')
19647
19648         [ "$bad_line_new" ] && [ "$good_line_new" ] ||
19649                 error "bad_line_new good_line_new are empty"
19650
19651         local expected_good=$((good_line1 + good_line2*2))
19652
19653         rm -f $TMP/${tfile}*
19654         # LU-231, short malformed line may not be counted into bad lines
19655         if [ $bad_line -ne $bad_line_new ] &&
19656                    [ $bad_line -ne $((bad_line_new - 1)) ]; then
19657                 error "expected $bad_line bad lines, but got $bad_line_new"
19658                 return 1
19659         fi
19660
19661         if [ $expected_good -ne $good_line_new ]; then
19662                 error "expected $expected_good good lines, but got $good_line_new"
19663                 return 2
19664         fi
19665         true
19666 }
19667 run_test 170 "test lctl df to handle corrupted log ====================="
19668
19669 test_171() { # bug20592
19670         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19671
19672         #define OBD_FAIL_PTLRPC_DUMP_LOG         0x50e
19673         $LCTL set_param fail_loc=0x50e
19674         $LCTL set_param fail_val=3000
19675         multiop_bg_pause $DIR/$tfile O_s || true
19676         local MULTIPID=$!
19677         kill -USR1 $MULTIPID
19678         # cause log dump
19679         sleep 3
19680         wait $MULTIPID
19681         if dmesg | grep "recursive fault"; then
19682                 error "caught a recursive fault"
19683         fi
19684         $LCTL set_param fail_loc=0
19685         true
19686 }
19687 run_test 171 "test libcfs_debug_dumplog_thread stuck in do_exit() ======"
19688
19689 test_172() {
19690
19691         #define OBD_FAIL_OBD_CLEANUP  0x60e
19692         $LCTL set_param fail_loc=0x60e
19693         umount $MOUNT || error "umount $MOUNT failed"
19694         stack_trap "mount_client $MOUNT"
19695
19696         (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )) ||
19697                 error "no client OBDs are remained"
19698
19699         $LCTL dl | while read devno state type name foo; do
19700                 case $type in
19701                 lov|osc|lmv|mdc)
19702                         $LCTL --device $name cleanup
19703                         $LCTL --device $name detach
19704                         ;;
19705                 *)
19706                         # skip server devices
19707                         ;;
19708                 esac
19709         done
19710
19711         if (( $($LCTL dl | egrep -c " osc | lov | lmv | mdc ") > 0 )); then
19712                 $LCTL dl | egrep " osc | lov | lmv | mdc "
19713                 error "some client OBDs are still remained"
19714         fi
19715
19716 }
19717 run_test 172 "manual device removal with lctl cleanup/detach ======"
19718
19719 # it would be good to share it with obdfilter-survey/iokit-libecho code
19720 setup_obdecho_osc () {
19721         local rc=0
19722         local ost_nid=$1
19723         local obdfilter_name=$2
19724         echo "Creating new osc for $obdfilter_name on $ost_nid"
19725         # make sure we can find loopback nid
19726         $LCTL add_uuid $ost_nid $ost_nid >/dev/null 2>&1
19727
19728         [ $rc -eq 0 ] && { $LCTL attach osc ${obdfilter_name}_osc     \
19729                            ${obdfilter_name}_osc_UUID || rc=2; }
19730         [ $rc -eq 0 ] && { $LCTL --device ${obdfilter_name}_osc setup \
19731                            ${obdfilter_name}_UUID  $ost_nid || rc=3; }
19732         return $rc
19733 }
19734
19735 cleanup_obdecho_osc () {
19736         local obdfilter_name=$1
19737         $LCTL --device ${obdfilter_name}_osc cleanup >/dev/null
19738         $LCTL --device ${obdfilter_name}_osc detach  >/dev/null
19739         return 0
19740 }
19741
19742 obdecho_test() {
19743         local OBD=$1
19744         local node=$2
19745         local pages=${3:-64}
19746         local rc=0
19747         local id
19748
19749         local count=10
19750         local obd_size=$(get_obd_size $node $OBD)
19751         local page_size=$(get_page_size $node)
19752         if [[ -n "$obd_size" ]]; then
19753                 local new_count=$((obd_size / (pages * page_size / 1024)))
19754                 [[ $new_count -ge $count ]] || count=$new_count
19755         fi
19756
19757         do_facet $node "$LCTL attach echo_client ec ec_uuid" || rc=1
19758         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec setup $OBD" ||
19759                            rc=2; }
19760         if [ $rc -eq 0 ]; then
19761             id=$(do_facet $node "$LCTL --device ec create 1"  | awk '/object id/ {print $6}')
19762             [ ${PIPESTATUS[0]} -eq 0 -a -n "$id" ] || rc=3
19763         fi
19764         echo "New object id is $id"
19765         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec getattr $id" ||
19766                            rc=4; }
19767         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec "                 \
19768                            "test_brw $count w v $pages $id" || rc=4; }
19769         [ $rc -eq 0 ] && { do_facet $node "$LCTL --device ec destroy $id 1" ||
19770                            rc=4; }
19771         [ $rc -eq 0 ] || [ $rc -gt 2 ] &&
19772                 { do_facet $node "$LCTL --device ec cleanup" || rc=5; }
19773         [ $rc -eq 0 ] || [ $rc -gt 1 ] &&
19774                 { do_facet $node "$LCTL --device ec detach" || rc=6; }
19775         [ $rc -ne 0 ] && echo "obecho_create_test failed: $rc"
19776         return $rc
19777 }
19778
19779 test_180a() {
19780         skip "obdecho on osc is no longer supported"
19781 }
19782 run_test 180a "test obdecho on osc"
19783
19784 test_180b() {
19785         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19786         remote_ost_nodsh && skip "remote OST with nodsh"
19787
19788         do_rpc_nodes $(facet_active_host ost1) load_module obdecho/obdecho &&
19789                 stack_trap "do_facet ost1 rmmod obdecho" EXIT ||
19790                 error "failed to load module obdecho"
19791
19792         local target=$(do_facet ost1 $LCTL dl |
19793                        awk '/obdfilter/ { print $4; exit; }')
19794
19795         if [ -n "$target" ]; then
19796                 obdecho_test $target ost1 || error "obdecho_test failed with $?"
19797         else
19798                 do_facet ost1 $LCTL dl
19799                 error "there is no obdfilter target on ost1"
19800         fi
19801 }
19802 run_test 180b "test obdecho directly on obdfilter"
19803
19804 test_180c() { # LU-2598
19805         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19806         remote_ost_nodsh && skip "remote OST with nodsh"
19807         [[ $MDS1_VERSION -lt $(version_code 2.4.0) ]] &&
19808                 skip "Need MDS version at least 2.4.0"
19809
19810         do_rpc_nodes $(facet_active_host ost1) load_module obdecho/obdecho &&
19811                 stack_trap "do_facet ost1 rmmod obdecho" EXIT ||
19812                 error "failed to load module obdecho"
19813
19814         local target=$(do_facet ost1 $LCTL dl |
19815                        awk '/obdfilter/ { print $4; exit; }')
19816
19817         if [ -n "$target" ]; then
19818                 local pages=16384 # 64MB bulk I/O RPC size
19819
19820                 obdecho_test "$target" ost1 "$pages" ||
19821                         error "obdecho_test with pages=$pages failed with $?"
19822         else
19823                 do_facet ost1 $LCTL dl
19824                 error "there is no obdfilter target on ost1"
19825         fi
19826 }
19827 run_test 180c "test huge bulk I/O size on obdfilter, don't LASSERT"
19828
19829 test_181() { # bug 22177
19830         test_mkdir $DIR/$tdir
19831         # create enough files to index the directory
19832         createmany -o $DIR/$tdir/foobar 4000
19833         # print attributes for debug purpose
19834         lsattr -d .
19835         # open dir
19836         multiop_bg_pause $DIR/$tdir D_Sc || return 1
19837         MULTIPID=$!
19838         # remove the files & current working dir
19839         unlinkmany $DIR/$tdir/foobar 4000
19840         rmdir $DIR/$tdir
19841         kill -USR1 $MULTIPID
19842         wait $MULTIPID
19843         stat $DIR/$tdir && error "open-unlinked dir was not removed!"
19844         return 0
19845 }
19846 run_test 181 "Test open-unlinked dir ========================"
19847
19848 test_182a() {
19849         local fcount=1000
19850         local tcount=10
19851
19852         mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir"
19853
19854         $LCTL set_param mdc.*.rpc_stats=clear
19855
19856         for (( i = 0; i < $tcount; i++ )) ; do
19857                 mkdir $DIR/$tdir/$i
19858         done
19859
19860         for (( i = 0; i < $tcount; i++ )) ; do
19861                 createmany -o $DIR/$tdir/$i/f- $fcount &
19862         done
19863         wait
19864
19865         for (( i = 0; i < $tcount; i++ )) ; do
19866                 unlinkmany $DIR/$tdir/$i/f- $fcount &
19867         done
19868         wait
19869
19870         $LCTL get_param mdc.*.rpc_stats
19871
19872         rm -rf $DIR/$tdir
19873 }
19874 run_test 182a "Test parallel modify metadata operations from mdc"
19875
19876 test_182b() {
19877         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
19878         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
19879         local dcount=1000
19880         local tcount=10
19881         local stime
19882         local etime
19883         local delta
19884
19885         do_facet mds1 $LCTL list_param \
19886                 osp.$FSNAME-MDT*-osp-MDT*.rpc_stats ||
19887                 skip "MDS lacks parallel RPC handling"
19888
19889         $LFS mkdir -i 0 $DIR/$tdir || error "creating dir $DIR/$tdir"
19890
19891         rpc_count=$(do_facet mds1 $LCTL get_param -n \
19892                     osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight)
19893
19894         stime=$(date +%s)
19895         createmany -i 0 -d $DIR/$tdir/t- $tcount
19896
19897         for (( i = 0; i < $tcount; i++ )) ; do
19898                 createmany -i 0 -d $DIR/$tdir/t-$i/d- 0 $dcount &
19899         done
19900         wait
19901         etime=$(date +%s)
19902         delta=$((etime - stime))
19903         echo "Time for file creation $delta sec for $rpc_count parallel RPCs"
19904
19905         stime=$(date +%s)
19906         for (( i = 0; i < $tcount; i++ )) ; do
19907                 unlinkmany -d $DIR/$tdir/$i/d- $dcount &
19908         done
19909         wait
19910         etime=$(date +%s)
19911         delta=$((etime - stime))
19912         echo "Time for file removal $delta sec for $rpc_count parallel RPCs"
19913
19914         rm -rf $DIR/$tdir
19915
19916         $LFS mkdir -i 0 $DIR/$tdir || error "creating dir $DIR/$tdir"
19917
19918         do_facet mds1 $LCTL set_param osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight=1
19919
19920         stime=$(date +%s)
19921         createmany -i 0 -d $DIR/$tdir/t- $tcount
19922
19923         for (( i = 0; i < $tcount; i++ )) ; do
19924                 createmany -i 0 -d $DIR/$tdir/t-$i/d- 0 $dcount &
19925         done
19926         wait
19927         etime=$(date +%s)
19928         delta=$((etime - stime))
19929         echo "Time for file creation $delta sec for 1 RPC sent at a time"
19930
19931         stime=$(date +%s)
19932         for (( i = 0; i < $tcount; i++ )) ; do
19933                 unlinkmany -d $DIR/$tdir/t-$i/d- $dcount &
19934         done
19935         wait
19936         etime=$(date +%s)
19937         delta=$((etime - stime))
19938         echo "Time for file removal $delta sec for 1 RPC sent at a time"
19939
19940         do_facet mds1 $LCTL set_param osp.$FSNAME-MDT0001-osp-MDT0000.max_mod_rpcs_in_flight=$rpc_count
19941 }
19942 run_test 182b "Test parallel modify metadata operations from osp"
19943
19944 test_183() { # LU-2275
19945         [ $PARALLEL == "yes" ] && skip "skip parallel run"
19946         remote_mds_nodsh && skip "remote MDS with nodsh"
19947         [[ $MDS1_VERSION -lt $(version_code 2.3.56) ]] &&
19948                 skip "Need MDS version at least 2.3.56"
19949
19950         mkdir_on_mdt0 $DIR/$tdir || error "creating dir $DIR/$tdir"
19951         echo aaa > $DIR/$tdir/$tfile
19952
19953 #define OBD_FAIL_MDS_NEGATIVE_POSITIVE  0x148
19954         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x148
19955
19956         ls -l $DIR/$tdir && error "ls succeeded, should have failed"
19957         cat $DIR/$tdir/$tfile && error "cat succeeded, should have failed"
19958
19959         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
19960
19961         # Flush negative dentry cache
19962         touch $DIR/$tdir/$tfile
19963
19964         # We are not checking for any leaked references here, they'll
19965         # become evident next time we do cleanup with module unload.
19966         rm -rf $DIR/$tdir
19967 }
19968 run_test 183 "No crash or request leak in case of strange dispositions ========"
19969
19970 # test suite 184 is for LU-2016, LU-2017
19971 test_184a() {
19972         check_swap_layouts_support
19973
19974         dir0=$DIR/$tdir/$testnum
19975         test_mkdir -p -c1 $dir0
19976         ref1=/etc/passwd
19977         ref2=/etc/group
19978         file1=$dir0/f1
19979         file2=$dir0/f2
19980         $LFS setstripe -c1 $file1
19981         cp $ref1 $file1
19982         $LFS setstripe -c2 $file2
19983         cp $ref2 $file2
19984         gen1=$($LFS getstripe -g $file1)
19985         gen2=$($LFS getstripe -g $file2)
19986
19987         $LFS swap_layouts $file1 $file2 || error "swap of file layout failed"
19988         gen=$($LFS getstripe -g $file1)
19989         [[ $gen1 != $gen ]] ||
19990                 error "Layout generation on $file1 does not change"
19991         gen=$($LFS getstripe -g $file2)
19992         [[ $gen2 != $gen ]] ||
19993                 error "Layout generation on $file2 does not change"
19994
19995         cmp $ref1 $file2 || error "content compare failed ($ref1 != $file2)"
19996         cmp $ref2 $file1 || error "content compare failed ($ref2 != $file1)"
19997
19998         lfsck_verify_pfid $file1 $file2 || error "PFID are not transferred"
19999 }
20000 run_test 184a "Basic layout swap"
20001
20002 test_184b() {
20003         check_swap_layouts_support
20004
20005         dir0=$DIR/$tdir/$testnum
20006         mkdir -p $dir0 || error "creating dir $dir0"
20007         file1=$dir0/f1
20008         file2=$dir0/f2
20009         file3=$dir0/f3
20010         dir1=$dir0/d1
20011         dir2=$dir0/d2
20012         mkdir $dir1 $dir2
20013         $LFS setstripe -c1 $file1
20014         $LFS setstripe -c2 $file2
20015         $LFS setstripe -c1 $file3
20016         chown $RUNAS_ID $file3
20017         gen1=$($LFS getstripe -g $file1)
20018         gen2=$($LFS getstripe -g $file2)
20019
20020         $LFS swap_layouts $dir1 $dir2 &&
20021                 error "swap of directories layouts should fail"
20022         $LFS swap_layouts $dir1 $file1 &&
20023                 error "swap of directory and file layouts should fail"
20024         $RUNAS $LFS swap_layouts $file1 $file2 &&
20025                 error "swap of file we cannot write should fail"
20026         $LFS swap_layouts $file1 $file3 &&
20027                 error "swap of file with different owner should fail"
20028         /bin/true # to clear error code
20029 }
20030 run_test 184b "Forbidden layout swap (will generate errors)"
20031
20032 test_184c() {
20033         local cmpn_arg=$(cmp -n 2>&1 | grep "invalid option")
20034         [ -n "$cmpn_arg" ] && skip_env "cmp does not support -n"
20035         check_swap_layouts_support
20036         check_swap_layout_no_dom $DIR
20037
20038         local dir0=$DIR/$tdir/$testnum
20039         mkdir -p $dir0 || error "creating dir $dir0"
20040
20041         local ref1=$dir0/ref1
20042         local ref2=$dir0/ref2
20043         local file1=$dir0/file1
20044         local file2=$dir0/file2
20045         # create a file large enough for the concurrent test
20046         dd if=/dev/urandom of=$ref1 bs=1M count=$((RANDOM % 50 + 20))
20047         dd if=/dev/urandom of=$ref2 bs=1M count=$((RANDOM % 50 + 20))
20048         echo "ref file size: ref1($(stat -c %s $ref1))," \
20049              "ref2($(stat -c %s $ref2))"
20050
20051         cp $ref2 $file2
20052         dd if=$ref1 of=$file1 bs=16k &
20053         local DD_PID=$!
20054
20055         # Make sure dd starts to copy file, but wait at most 5 seconds
20056         local loops=0
20057         while [ ! -s $file1 -a $((loops++)) -lt 50 ]; do sleep 0.1; done
20058
20059         $LFS swap_layouts $file1 $file2
20060         local rc=$?
20061         wait $DD_PID
20062         [[ $? == 0 ]] || error "concurrent write on $file1 failed"
20063         [[ $rc == 0 ]] || error "swap of $file1 and $file2 failed"
20064
20065         # how many bytes copied before swapping layout
20066         local copied=$(stat -c %s $file2)
20067         local remaining=$(stat -c %s $ref1)
20068         remaining=$((remaining - copied))
20069         echo "Copied $copied bytes before swapping layout..."
20070
20071         cmp -n $copied $file1 $ref2 | grep differ &&
20072                 error "Content mismatch [0, $copied) of ref2 and file1"
20073         cmp -n $copied $file2 $ref1 ||
20074                 error "Content mismatch [0, $copied) of ref1 and file2"
20075         cmp -i $copied:$copied -n $remaining $file1 $ref1 ||
20076                 error "Content mismatch [$copied, EOF) of ref1 and file1"
20077
20078         # clean up
20079         rm -f $ref1 $ref2 $file1 $file2
20080 }
20081 run_test 184c "Concurrent write and layout swap"
20082
20083 test_184d() {
20084         check_swap_layouts_support
20085         check_swap_layout_no_dom $DIR
20086         [ -z "$(which getfattr 2>/dev/null)" ] &&
20087                 skip_env "no getfattr command"
20088
20089         local file1=$DIR/$tdir/$tfile-1
20090         local file2=$DIR/$tdir/$tfile-2
20091         local file3=$DIR/$tdir/$tfile-3
20092         local lovea1
20093         local lovea2
20094
20095         mkdir -p $DIR/$tdir
20096         touch $file1 || error "create $file1 failed"
20097         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file2 ||
20098                 error "create $file2 failed"
20099         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file3 ||
20100                 error "create $file3 failed"
20101         lovea1=$(get_layout_param $file1)
20102
20103         $LFS swap_layouts $file2 $file3 ||
20104                 error "swap $file2 $file3 layouts failed"
20105         $LFS swap_layouts $file1 $file2 ||
20106                 error "swap $file1 $file2 layouts failed"
20107
20108         lovea2=$(get_layout_param $file2)
20109         echo "$lovea1"
20110         echo "$lovea2"
20111         [ "$lovea1" == "$lovea2" ] || error "lovea $lovea1 != $lovea2"
20112
20113         lovea1=$(getfattr -n trusted.lov $file1 | grep ^trusted)
20114         [[ -z "$lovea1" ]] || error "$file1 shouldn't have lovea"
20115 }
20116 run_test 184d "allow stripeless layouts swap"
20117
20118 test_184e() {
20119         [[ $MDS1_VERSION -ge $(version_code 2.6.94) ]] ||
20120                 skip "Need MDS version at least 2.6.94"
20121         check_swap_layouts_support
20122         check_swap_layout_no_dom $DIR
20123         [ -z "$(which getfattr 2>/dev/null)" ] &&
20124                 skip_env "no getfattr command"
20125
20126         local file1=$DIR/$tdir/$tfile-1
20127         local file2=$DIR/$tdir/$tfile-2
20128         local file3=$DIR/$tdir/$tfile-3
20129         local lovea
20130
20131         mkdir -p $DIR/$tdir
20132         touch $file1 || error "create $file1 failed"
20133         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file2 ||
20134                 error "create $file2 failed"
20135         $OPENFILE -f O_CREAT:O_LOV_DELAY_CREATE $file3 ||
20136                 error "create $file3 failed"
20137
20138         $LFS swap_layouts $file1 $file2 ||
20139                 error "swap $file1 $file2 layouts failed"
20140
20141         lovea=$(getfattr -n trusted.lov $file1 | grep ^trusted)
20142         [[ -z "$lovea" ]] || error "$file1 shouldn't have lovea"
20143
20144         echo 123 > $file1 || error "Should be able to write into $file1"
20145
20146         $LFS swap_layouts $file1 $file3 ||
20147                 error "swap $file1 $file3 layouts failed"
20148
20149         echo 123 > $file1 || error "Should be able to write into $file1"
20150
20151         rm -rf $file1 $file2 $file3
20152 }
20153 run_test 184e "Recreate layout after stripeless layout swaps"
20154
20155 test_184f() {
20156         # Create a file with name longer than sizeof(struct stat) ==
20157         # 144 to see if we can get chars from the file name to appear
20158         # in the returned striping. Note that 'f' == 0x66.
20159         local file=$(for ((i = 0; i < 200; i++)); do echo -n f; done)
20160
20161         mkdir -p $DIR/$tdir
20162         mcreate $DIR/$tdir/$file
20163         if lfs find --stripe-count 0x6666 $DIR/$tdir | grep $file; then
20164                 error "IOC_MDC_GETFILEINFO returned garbage striping"
20165         fi
20166 }
20167 run_test 184f "IOC_MDC_GETFILEINFO for files with long names but no striping"
20168
20169 test_185() { # LU-2441
20170         # LU-3553 - no volatile file support in old servers
20171         [[ $MDS1_VERSION -ge $(version_code 2.3.60) ]] ||
20172                 skip "Need MDS version at least 2.3.60"
20173
20174         mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir"
20175         touch $DIR/$tdir/spoo
20176         local mtime1=$(stat -c "%Y" $DIR/$tdir)
20177         local fid=$($MULTIOP $DIR/$tdir VFw4096c) ||
20178                 error "cannot create/write a volatile file"
20179         [ "$FILESET" == "" ] &&
20180         $CHECKSTAT -t file $MOUNT/.lustre/fid/$fid 2>/dev/null &&
20181                 error "FID is still valid after close"
20182
20183         multiop_bg_pause $DIR/$tdir Vw4096_c
20184         local multi_pid=$!
20185
20186         local OLD_IFS=$IFS
20187         IFS=":"
20188         local fidv=($fid)
20189         IFS=$OLD_IFS
20190         # assume that the next FID for this client is sequential, since stdout
20191         # is unfortunately eaten by multiop_bg_pause
20192         local n=$((${fidv[1]} + 1))
20193         local next_fid="${fidv[0]}:$(printf "0x%x" $n):${fidv[2]}"
20194         if [ "$FILESET" == "" ]; then
20195                 $CHECKSTAT -t file $MOUNT/.lustre/fid/$next_fid ||
20196                         error "FID is missing before close"
20197         fi
20198         kill -USR1 $multi_pid
20199         # 1 second delay, so if mtime change we will see it
20200         sleep 1
20201         local mtime2=$(stat -c "%Y" $DIR/$tdir)
20202         [[ $mtime1 == $mtime2 ]] || error "mtime has changed"
20203 }
20204 run_test 185 "Volatile file support"
20205
20206 function create_check_volatile() {
20207         local idx=$1
20208         local tgt
20209
20210         $MULTIOP $MOUNT/.lustre/fid V${idx}Fw4096_c >&/tmp/${tfile}.fid &
20211         local PID=$!
20212         sleep 1
20213         local FID=$(cat /tmp/${tfile}.fid)
20214         [ "$FID" == "" ] && error "can't get FID for volatile"
20215         $CHECKSTAT -t file $MOUNT/.lustre/fid/$FID || error "can't stat $FID"
20216         tgt=$($LFS getstripe -m $MOUNT/.lustre/fid/$FID)
20217         [ "$tgt" != "$idx" ] && error "wrong MDS $tgt, expected $idx"
20218         kill -USR1 $PID
20219         wait
20220         sleep 1
20221         cancel_lru_locks mdc # flush opencache
20222         $CHECKSTAT -t file $MOUNT/.lustre/fid/$FID && error "can stat $FID"
20223         return 0
20224 }
20225
20226 test_185a(){
20227         # LU-12516 - volatile creation via .lustre
20228         [[ $MDS1_VERSION -ge $(version_code 2.12.55) ]] ||
20229                 skip "Need MDS version at least 2.3.55"
20230
20231         create_check_volatile 0
20232         [ $MDSCOUNT -lt 2 ] && return 0
20233
20234         # DNE case
20235         create_check_volatile 1
20236
20237         return 0
20238 }
20239 run_test 185a "Volatile file creation in .lustre/fid/"
20240
20241 test_187a() {
20242         remote_mds_nodsh && skip "remote MDS with nodsh"
20243         [ $MDS1_VERSION -lt $(version_code 2.3.0) ] &&
20244                 skip "Need MDS version at least 2.3.0"
20245
20246         local dir0=$DIR/$tdir/$testnum
20247         mkdir -p $dir0 || error "creating dir $dir0"
20248
20249         local file=$dir0/file1
20250         dd if=/dev/urandom of=$file count=10 bs=1M conv=fsync
20251         stack_trap "rm -f $file"
20252         local dv1=$($LFS data_version $file)
20253         dd if=/dev/urandom of=$file seek=10 count=1 bs=1M conv=fsync
20254         local dv2=$($LFS data_version $file)
20255         [[ $dv1 != $dv2 ]] ||
20256                 error "data version did not change on write $dv1 == $dv2"
20257 }
20258 run_test 187a "Test data version change"
20259
20260 test_187b() {
20261         remote_mds_nodsh && skip "remote MDS with nodsh"
20262         [ $MDS1_VERSION -lt $(version_code 2.3.0) ] &&
20263                 skip "Need MDS version at least 2.3.0"
20264
20265         local dir0=$DIR/$tdir/$testnum
20266         mkdir -p $dir0 || error "creating dir $dir0"
20267
20268         declare -a DV=$($MULTIOP $dir0 Vw1000xYw1000xY | cut -f3 -d" ")
20269         [[ ${DV[0]} != ${DV[1]} ]] ||
20270                 error "data version did not change on write"\
20271                       " ${DV[0]} == ${DV[1]}"
20272
20273         # clean up
20274         rm -f $file1
20275 }
20276 run_test 187b "Test data version change on volatile file"
20277
20278 test_200() {
20279         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20280         remote_mgs_nodsh && skip "remote MGS with nodsh"
20281         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
20282
20283         local POOL=${POOL:-cea1}
20284         local POOL_ROOT=${POOL_ROOT:-$DIR/d200.pools}
20285         local POOL_DIR_NAME=${POOL_DIR_NAME:-dir_tst}
20286         # Pool OST targets
20287         local first_ost=0
20288         local last_ost=$(($OSTCOUNT - 1))
20289         local ost_step=2
20290         local ost_list=$(seq $first_ost $ost_step $last_ost)
20291         local ost_range="$first_ost $last_ost $ost_step"
20292         local test_path=$POOL_ROOT/$POOL_DIR_NAME
20293         local file_dir=$POOL_ROOT/file_tst
20294         local subdir=$test_path/subdir
20295         local rc=0
20296
20297         while : ; do
20298                 # former test_200a test_200b
20299                 pool_add $POOL                          || { rc=$? ; break; }
20300                 pool_add_targets  $POOL $ost_range      || { rc=$? ; break; }
20301                 # former test_200c test_200d
20302                 mkdir -p $test_path
20303                 pool_set_dir      $POOL $test_path      || { rc=$? ; break; }
20304                 pool_check_dir    $POOL $test_path      || { rc=$? ; break; }
20305                 mkdir -p $subdir
20306                 pool_check_dir    $POOL $subdir         || { rc=$? ; break; }
20307                 pool_dir_rel_path $POOL $POOL_DIR_NAME $POOL_ROOT \
20308                                                         || { rc=$? ; break; }
20309                 # former test_200e test_200f
20310                 local files=$((OSTCOUNT*3))
20311                 pool_alloc_files  $POOL $test_path $files "$ost_list" \
20312                                                         || { rc=$? ; break; }
20313                 pool_create_files $POOL $file_dir $files "$ost_list" \
20314                                                         || { rc=$? ; break; }
20315                 # former test_200g test_200h
20316                 pool_lfs_df $POOL                       || { rc=$? ; break; }
20317                 pool_file_rel_path $POOL $test_path     || { rc=$? ; break; }
20318
20319                 # former test_201a test_201b test_201c
20320                 pool_remove_first_target $POOL          || { rc=$? ; break; }
20321
20322                 local f=$test_path/$tfile
20323                 pool_remove_all_targets $POOL $f        || { rc=$? ; break; }
20324                 pool_remove $POOL $f                    || { rc=$? ; break; }
20325                 break
20326         done
20327
20328         destroy_test_pools
20329
20330         return $rc
20331 }
20332 run_test 200 "OST pools"
20333
20334 # usage: default_attr <count | size | offset>
20335 default_attr() {
20336         $LCTL get_param -n lov.$FSNAME-clilov-\*.stripe${1}
20337 }
20338
20339 # usage: check_default_stripe_attr
20340 check_default_stripe_attr() {
20341         ACTUAL=$($LFS getstripe $* $DIR/$tdir)
20342         case $1 in
20343         --stripe-count|-c)
20344                 [ -n "$2" ] && EXPECTED=0 || EXPECTED=$(default_attr count);;
20345         --stripe-size|-S)
20346                 [ -n "$2" ] && EXPECTED=0 || EXPECTED=$(default_attr size);;
20347         --stripe-index|-i)
20348                 EXPECTED=-1;;
20349         *)
20350                 error "unknown getstripe attr '$1'"
20351         esac
20352
20353         [ $ACTUAL == $EXPECTED ] ||
20354                 error "$DIR/$tdir has $1 '$ACTUAL', not '$EXPECTED'"
20355 }
20356
20357 test_204a() {
20358         test_mkdir $DIR/$tdir
20359         $LFS setstripe --stripe-count 0 --stripe-size 0 --stripe-index -1 $DIR/$tdir
20360
20361         check_default_stripe_attr --stripe-count
20362         check_default_stripe_attr --stripe-size
20363         check_default_stripe_attr --stripe-index
20364 }
20365 run_test 204a "Print default stripe attributes"
20366
20367 test_204b() {
20368         test_mkdir $DIR/$tdir
20369         $LFS setstripe --stripe-count 1 $DIR/$tdir
20370
20371         check_default_stripe_attr --stripe-size
20372         check_default_stripe_attr --stripe-index
20373 }
20374 run_test 204b "Print default stripe size and offset"
20375
20376 test_204c() {
20377         test_mkdir $DIR/$tdir
20378         $LFS setstripe --stripe-size 65536 $DIR/$tdir
20379
20380         check_default_stripe_attr --stripe-count
20381         check_default_stripe_attr --stripe-index
20382 }
20383 run_test 204c "Print default stripe count and offset"
20384
20385 test_204d() {
20386         test_mkdir $DIR/$tdir
20387         $LFS setstripe --stripe-index 0 $DIR/$tdir
20388
20389         check_default_stripe_attr --stripe-count
20390         check_default_stripe_attr --stripe-size
20391 }
20392 run_test 204d "Print default stripe count and size"
20393
20394 test_204e() {
20395         test_mkdir $DIR/$tdir
20396         $LFS setstripe -d $DIR/$tdir
20397
20398         # LU-16904 check if root is set as PFL layout
20399         local numcomp=$($LFS getstripe --component-count $MOUNT)
20400
20401         if [[ $numcomp -gt 0 ]]; then
20402                 check_default_stripe_attr --stripe-count
20403         else
20404                 check_default_stripe_attr --stripe-count --raw
20405         fi
20406         check_default_stripe_attr --stripe-size --raw
20407         check_default_stripe_attr --stripe-index --raw
20408 }
20409 run_test 204e "Print raw stripe attributes"
20410
20411 test_204f() {
20412         test_mkdir $DIR/$tdir
20413         $LFS setstripe --stripe-count 1 $DIR/$tdir
20414
20415         check_default_stripe_attr --stripe-size --raw
20416         check_default_stripe_attr --stripe-index --raw
20417 }
20418 run_test 204f "Print raw stripe size and offset"
20419
20420 test_204g() {
20421         test_mkdir $DIR/$tdir
20422         $LFS setstripe --stripe-size 65536 $DIR/$tdir
20423
20424         check_default_stripe_attr --stripe-count --raw
20425         check_default_stripe_attr --stripe-index --raw
20426 }
20427 run_test 204g "Print raw stripe count and offset"
20428
20429 test_204h() {
20430         test_mkdir $DIR/$tdir
20431         $LFS setstripe --stripe-index 0 $DIR/$tdir
20432
20433         check_default_stripe_attr --stripe-count --raw
20434         check_default_stripe_attr --stripe-size --raw
20435 }
20436 run_test 204h "Print raw stripe count and size"
20437
20438 # Figure out which job scheduler is being used, if any,
20439 # or use a fake one
20440 if [ -n "$SLURM_JOB_ID" ]; then # SLURM
20441         JOBENV=SLURM_JOB_ID
20442 elif [ -n "$LSB_JOBID" ]; then # Load Sharing Facility
20443         JOBENV=LSB_JOBID
20444 elif [ -n "$PBS_JOBID" ]; then # PBS/Maui/Moab
20445         JOBENV=PBS_JOBID
20446 elif [ -n "$LOADL_STEPID" ]; then # LoadLeveller
20447         JOBENV=LOADL_STEP_ID
20448 elif [ -n "$JOB_ID" ]; then # Sun Grid Engine
20449         JOBENV=JOB_ID
20450 else
20451         $LCTL list_param jobid_name > /dev/null 2>&1
20452         if [ $? -eq 0 ]; then
20453                 JOBENV=nodelocal
20454         else
20455                 JOBENV=FAKE_JOBID
20456         fi
20457 fi
20458 LUSTRE_JOBID_SIZE=31 # plus NUL terminator
20459
20460 verify_jobstats() {
20461         local cmd=($1)
20462         shift
20463         local facets="$@"
20464
20465 # we don't really need to clear the stats for this test to work, since each
20466 # command has a unique jobid, but it makes debugging easier if needed.
20467 #       for facet in $facets; do
20468 #               local dev=$(convert_facet2label $facet)
20469 #               # clear old jobstats
20470 #               do_facet $facet lctl set_param *.$dev.job_stats="clear"
20471 #       done
20472
20473         # use a new JobID for each test, or we might see an old one
20474         [ "$JOBENV" = "FAKE_JOBID" ] &&
20475                 FAKE_JOBID=id.$testnum.$(basename ${cmd[0]}).$RANDOM
20476
20477         JOBVAL=${!JOBENV:0:$LUSTRE_JOBID_SIZE}
20478
20479         [ "$JOBENV" = "nodelocal" ] && {
20480                 FAKE_JOBID=id.$testnum.%e.$RANDOM
20481                 $LCTL set_param jobid_name=$FAKE_JOBID
20482                 JOBVAL=${FAKE_JOBID/\%e/$(basename ${cmd[0]})}
20483         }
20484
20485         log "Test: ${cmd[*]}"
20486         log "Using JobID environment $($LCTL get_param -n jobid_var)=$JOBVAL"
20487
20488         if [ $JOBENV = "FAKE_JOBID" ]; then
20489                 FAKE_JOBID=$JOBVAL ${cmd[*]}
20490         else
20491                 ${cmd[*]}
20492         fi
20493
20494         # all files are created on OST0000
20495         for facet in $facets; do
20496                 local stats="*.$(convert_facet2label $facet).job_stats"
20497
20498                 # strip out libtool wrappers for in-tree executables
20499                 if (( $(do_facet $facet lctl get_param $stats |
20500                         sed -e 's/\.lt-/./' | grep -cw $JOBVAL) != 1 )); then
20501                         do_facet $facet lctl get_param $stats
20502                         error "No jobstats for $JOBVAL found on $facet::$stats"
20503                 fi
20504         done
20505 }
20506
20507 jobstats_set() {
20508         local new_jobenv=$1
20509
20510         set_persistent_param_and_check client "jobid_var" \
20511                 "$FSNAME.sys.jobid_var" $new_jobenv
20512 }
20513
20514 test_205a() { # Job stats
20515         [ $PARALLEL == "yes" ] && skip "skip parallel run"
20516         [[ $MDS1_VERSION -ge $(version_code 2.7.1) ]] ||
20517                 skip "Need MDS version with at least 2.7.1"
20518         remote_mgs_nodsh && skip "remote MGS with nodsh"
20519         remote_mds_nodsh && skip "remote MDS with nodsh"
20520         remote_ost_nodsh && skip "remote OST with nodsh"
20521         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep jobstats)" ] &&
20522                 skip "Server doesn't support jobstats"
20523         [[ $JOBID_VAR = disable ]] && skip_env "jobstats is disabled"
20524
20525         local old_jobenv=$($LCTL get_param -n jobid_var)
20526         [ $old_jobenv != $JOBENV ] && jobstats_set $JOBENV
20527         stack_trap "jobstats_set $old_jobenv" EXIT
20528
20529         changelog_register
20530
20531         local old_jobid_name=$($LCTL get_param jobid_name)
20532         stack_trap "$LCTL set_param $old_jobid_name" EXIT
20533
20534         local old_interval=$(do_facet $SINGLEMDS lctl get_param -n \
20535                                 mdt.*.job_cleanup_interval | head -n 1)
20536         local new_interval=5
20537         do_facet $SINGLEMDS \
20538                 $LCTL set_param mdt.*.job_cleanup_interval=$new_interval
20539         stack_trap "do_facet $SINGLEMDS \
20540                 $LCTL set_param mdt.*.job_cleanup_interval=$old_interval" EXIT
20541         local start=$SECONDS
20542
20543         local cmd
20544         # mkdir
20545         cmd="$LFS mkdir -i 0 -c 1 $DIR/$tdir"
20546         verify_jobstats "$cmd" "$SINGLEMDS"
20547         # rmdir
20548         cmd="rmdir $DIR/$tdir"
20549         verify_jobstats "$cmd" "$SINGLEMDS"
20550         # mkdir on secondary MDT
20551         if [ $MDSCOUNT -gt 1 ]; then
20552                 cmd="lfs mkdir -i 1 $DIR/$tdir.remote"
20553                 verify_jobstats "$cmd" "mds2"
20554         fi
20555         # mknod
20556         cmd="mknod $DIR/$tfile c 1 3"
20557         verify_jobstats "$cmd" "$SINGLEMDS"
20558         # unlink
20559         cmd="rm -f $DIR/$tfile"
20560         verify_jobstats "$cmd" "$SINGLEMDS"
20561         # create all files on OST0000 so verify_jobstats can find OST stats
20562         # open & close
20563         cmd="$LFS setstripe -i 0 -c 1 $DIR/$tfile"
20564         verify_jobstats "$cmd" "$SINGLEMDS"
20565         # setattr
20566         cmd="touch $DIR/$tfile"
20567         verify_jobstats "$cmd" "$SINGLEMDS ost1"
20568         # write
20569         cmd="dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=sync"
20570         verify_jobstats "$cmd" "ost1"
20571         # read
20572         cancel_lru_locks osc
20573         cmd="dd if=$DIR/$tfile of=/dev/null bs=1M count=1 iflag=direct"
20574         verify_jobstats "$cmd" "ost1"
20575         # truncate
20576         cmd="$TRUNCATE $DIR/$tfile 0"
20577         verify_jobstats "$cmd" "$SINGLEMDS ost1"
20578         # rename
20579         cmd="mv -f $DIR/$tfile $DIR/$tdir.rename"
20580         verify_jobstats "$cmd" "$SINGLEMDS"
20581         # jobstats expiry - sleep until old stats should be expired
20582         local left=$((new_interval + 5 - (SECONDS - start)))
20583         [ $left -ge 0 ] && wait_update_facet $SINGLEMDS \
20584                 "lctl get_param *.*.job_stats | grep -c 'job_id.*mkdir'" \
20585                         "0" $left
20586         cmd="$LFS mkdir -i 0 -c 1 $DIR/$tdir.expire"
20587         verify_jobstats "$cmd" "$SINGLEMDS"
20588         [ $(do_facet $SINGLEMDS lctl get_param *.*.job_stats |
20589             grep -c "job_id.*mkdir") -gt 1 ] && error "old jobstats not expired"
20590
20591         # Ensure that jobid are present in changelog (if supported by MDS)
20592         if [ $MDS1_VERSION -ge $(version_code 2.6.52) ];then
20593                 changelog_dump | tail -10
20594                 jobids=$(changelog_dump | tail -9 | grep -c "j=")
20595                 [ $jobids -eq 9 ] ||
20596                         error "Wrong changelog jobid count $jobids != 9"
20597
20598                 # LU-5862
20599                 JOBENV="disable"
20600                 jobstats_set $JOBENV
20601                 touch $DIR/$tfile
20602                 changelog_dump | grep $tfile
20603                 jobids=$(changelog_dump | grep $tfile | tail -1 | grep -c "j=")
20604                 [ $jobids -eq 0 ] ||
20605                         error "Unexpected jobids when jobid_var=$JOBENV"
20606         fi
20607
20608         # test '%j' access to environment variable - if supported
20609         if lctl set_param jobid_var=USER jobid_name="S.%j.%e.%u.%h.E"; then
20610                 JOBENV="JOBCOMPLEX"
20611                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname).E"
20612
20613                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
20614         fi
20615
20616         if lctl set_param jobid_var=USER jobid_name="S.%j.%e.%u.%H.E"; then
20617                 JOBENV="JOBCOMPLEX"
20618                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname -s).E"
20619
20620                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
20621         fi
20622
20623         # test '%j' access to per-session jobid - if supported
20624         if lctl list_param jobid_this_session > /dev/null 2>&1
20625         then
20626                 lctl set_param jobid_var=session jobid_name="S.%j.%e.%u.%h.E"
20627                 lctl set_param jobid_this_session=$USER
20628
20629                 JOBENV="JOBCOMPLEX"
20630                 JOBCOMPLEX="S.$USER.touch.$(id -u).$(hostname).E"
20631
20632                 verify_jobstats "touch $DIR/$tfile" $SINGLEMDS
20633         fi
20634 }
20635 run_test 205a "Verify job stats"
20636
20637 # LU-13117, LU-13597, LU-16599
20638 test_205b() {
20639         (( $MDS1_VERSION >= $(version_code 2.13.54.91) )) ||
20640                 skip "Need MDS version at least 2.13.54.91"
20641
20642         local job_stats="mdt.*.job_stats"
20643         local old_jobid=$(do_facet mds1 $LCTL get_param jobid_var)
20644
20645         do_facet mds1 $LCTL set_param $job_stats=clear
20646
20647         # Setting jobid_var to USER might not be supported
20648         [[ -n "$old_jobid" ]] && stack_trap "$LCTL set_param $old_jobid"
20649         $LCTL set_param jobid_var=USER || true
20650         stack_trap "$LCTL set_param $($LCTL get_param jobid_name)"
20651         $LCTL set_param jobid_name="%j.%e.%u"
20652
20653         env -i USERTESTJOBSTATS=foolish touch $DIR/$tfile.1
20654         do_facet mds1 $LCTL get_param $job_stats | grep "job_id:.*foolish" &&
20655                 { do_facet mds1 $LCTL get_param $job_stats;
20656                   error "Unexpected jobid found"; }
20657         do_facet mds1 $LCTL get_param $job_stats | grep "open:.*min.*max.*sum"||
20658                 { do_facet mds1 $LCTL get_param $job_stats;
20659                   error "wrong job_stats format found"; }
20660
20661         (( $MDS1_VERSION <= $(version_code 2.15.0) )) &&
20662                 echo "MDS does not yet escape jobid" && return 0
20663
20664         mkdir_on_mdt0 $DIR/$tdir
20665         $LCTL set_param jobid_var=TEST205b
20666         env -i TEST205b="has sp" touch $DIR/$tdir/$tfile.2
20667         local jobid=$(do_facet mds1 $LCTL get_param $job_stats |
20668                       awk '/has\\x20sp/ {print $3}')
20669         [[ -n "$jobid" ]] || { do_facet mds1 $LCTL get_param $job_stats;
20670                   error "jobid not escaped"; }
20671
20672         if (( $MDS1_VERSION >= $(version_code 2.15.53.139) )); then
20673                 # need to run such a command on mds1:
20674                 # lctl set_param mdt.$FSNAME-MDT0000.job_stats='"has\x20sp.touch.0"'
20675                 #
20676                 # there might be multiple MDTs on single mds server, so need to
20677                 # specifiy MDT0000. Or the command will fail due to other MDTs
20678                 do_facet_vp mds1 $LCTL set_param mdt.$FSNAME-MDT0000.job_stats=$jobid ||
20679                         error "cannot clear escaped jobid in job_stats";
20680         else
20681                 echo "MDS does not support clearing escaped jobid"
20682         fi
20683 }
20684 run_test 205b "Verify job stats jobid and output format"
20685
20686 # LU-13733
20687 test_205c() {
20688         $LCTL set_param llite.*.stats=0
20689         dd if=/dev/zero of=$DIR/$tfile.1 bs=4k count=1
20690         $LCTL get_param llite.*.stats
20691         $LCTL get_param llite.*.stats | grep \
20692                 "write_bytes *1 samples \[bytes\] 4096 4096 4096 16777216" ||
20693                         error "wrong client stats format found"
20694 }
20695 run_test 205c "Verify client stats format"
20696
20697 test_205d() {
20698         local file=$DIR/$tdir/$tfile
20699
20700         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
20701                 skip "need lustre >= 2.15.53 for lljobstat"
20702         (( $OST1_VERSION >= $(version_code 2.15.53) )) ||
20703                 skip "need lustre >= 2.15.53 for lljobstat"
20704         verify_yaml_available || skip_env "YAML verification not installed"
20705
20706         test_mkdir -i 0 $DIR/$tdir
20707         $LFS setstripe -E 1M -L mdt -E -1 $file || error "create file failed"
20708         stack_trap "rm -rf $DIR/$tdir"
20709
20710         dd if=/dev/zero of=$file bs=1M count=10 conv=sync ||
20711                 error "failed to write data to $file"
20712         mv $file $file.2
20713
20714         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.rename_stats"
20715         echo -n 'verify rename_stats...'
20716         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.rename_stats" |
20717                 verify_yaml || error "rename_stats is not valid YAML"
20718         echo " OK"
20719
20720         echo -n 'verify mdt job_stats...'
20721         do_facet mds1 "$LCTL get_param -n mdt.$FSNAME-MDT0000.job_stats" |
20722                 verify_yaml || error "job_stats on mds1 is not valid YAML"
20723         echo " OK"
20724
20725         echo -n 'verify ost job_stats...'
20726         do_facet ost1 "$LCTL get_param -n obdfilter.$FSNAME-OST0000.job_stats" |
20727                 verify_yaml || error "job_stats on ost1 is not valid YAML"
20728         echo " OK"
20729 }
20730 run_test 205d "verify the format of some stats files"
20731
20732 test_205e() {
20733         local ops_comma
20734         local file=$DIR/$tdir/$tfile
20735         local -a cli_params
20736
20737         (( $MDS1_VERSION >= $(version_code 2.15.53) )) ||
20738                 skip "need lustre >= 2.15.53 for lljobstat"
20739         (( $OST1_VERSION >= $(version_code 2.15.53) )) ||
20740                 skip "need lustre >= 2.15.53 for lljobstat"
20741         verify_yaml_available || skip_env "YAML verification not installed"
20742
20743         cli_params=( $($LCTL get_param jobid_name jobid_var) )
20744         $LCTL set_param jobid_var=nodelocal jobid_name=205e.%e.%u
20745         stack_trap "$LCTL set_param ${cli_params[*]}" EXIT
20746
20747         mkdir_on_mdt0 $DIR/$tdir || error "failed to create dir"
20748         stack_trap "rm -rf $DIR/$tdir"
20749
20750         $LFS setstripe -E EOF -i 0 -c 1 $file ||
20751                 error "failed to create $file on ost1"
20752         dd if=/dev/zero of=$file bs=1M count=10 oflag=sync ||
20753                 error "failed to write data to $file"
20754
20755         do_facet mds1 "$LCTL get_param *.*.job_stats"
20756         do_facet ost1 "$LCTL get_param *.*.job_stats"
20757
20758         do_facet ost1 "lljobstat -n 1 -i 0 -c 1000"
20759         do_facet ost1 "lljobstat -n 1 -i 0 -c 1000" | verify_yaml ||
20760                 error "The output of lljobstat is not an valid YAML"
20761
20762         # verify that job dd.0 does exist and has some ops on ost1
20763         # typically this line is like:
20764         # - 205e.dd.0:            {ops: 20, ...}
20765         ops_comma=$(do_facet ost1 "lljobstat -n 1 -i 0 -c 1000" |
20766                     awk '$2=="205e.dd.0:" {print $4}')
20767
20768         (( ${ops_comma%,} >= 10 )) ||
20769                 error "cannot find job 205e.dd.0 with ops >= 10"
20770 }
20771 run_test 205e "verify the output of lljobstat"
20772
20773 test_205f() {
20774         verify_yaml_available || skip_env "YAML verification not installed"
20775
20776         # check both qos_ost_weights and qos_mdt_weights
20777         do_facet mds1 $LCTL get_param -n lod.*.qos*weights
20778         do_facet mds1 $LCTL get_param -n lod.*.qos*weights | verify_yaml ||
20779                 error "qos_ost_weights is not valid YAML"
20780 }
20781 run_test 205f "verify qos_ost_weights YAML format "
20782
20783 __test_205_jobstats_dump() {
20784         local -a pids
20785         local nbr_instance=$1
20786
20787         while true; do
20788                 if (( ${#pids[@]} >= nbr_instance )); then
20789                         wait ${pids[@]}
20790                         pids=()
20791                 fi
20792
20793                 do_facet mds1 "$LCTL get_param mdt.*.job_stats > /dev/null" &
20794                 pids+=( $! )
20795         done
20796 }
20797
20798 __test_205_cleanup() {
20799         kill $@
20800         # Clear all job entries
20801         do_facet mds1 "$LCTL set_param mdt.*.job_stats=clear"
20802 }
20803
20804 test_205g() {
20805         local -a mds1_params
20806         local -a cli_params
20807         local pids
20808         local interval=5
20809
20810         mds1_params=( $(do_facet mds1 $LCTL get_param mdt.*.job_cleanup_interval) )
20811         do_facet mds1 $LCTL set_param mdt.*.job_cleanup_interval=$interval
20812         stack_trap "do_facet mds1 $LCTL set_param ${mds1_params[*]}" EXIT
20813
20814         cli_params=( $($LCTL get_param jobid_name jobid_var) )
20815         $LCTL set_param jobid_var=TEST205G_ID jobid_name=%j.%p
20816         stack_trap "$LCTL set_param ${cli_params[*]}" EXIT
20817
20818         # start jobs loop
20819         export TEST205G_ID=205g
20820         stack_trap "unset TEST205G_ID" EXIT
20821         while true; do
20822                 printf $DIR/$tfile.{0001..1000} | xargs -P10 -n1 touch
20823         done & pids="$! "
20824
20825         __test_205_jobstats_dump 4 & pids+="$! "
20826         stack_trap "__test_205_cleanup $pids" EXIT INT
20827
20828         [[ $SLOW == "no" ]] && sleep 90 || sleep 240
20829 }
20830 run_test 205g "stress test for job_stats procfile"
20831
20832 test_205h() {
20833         (( $MDS1_VERSION >= $(version_code 2.15.57.7) )) ||
20834                 skip "Need MDS >= v2_15_57-7-g23a2db28dc for jobid xattr"
20835         which getfattr > /dev/null 2>&1 || skip_env "no getfattr command"
20836
20837         local dir=$DIR/$tdir
20838         local f=$dir/$tfile
20839         local f2=$dir/$tfile-2
20840         local f3=$dir/$tfile-3
20841         local subdir=$DIR/dir
20842         local val
20843
20844         local mdts=$(comma_list $(mdts_nodes))
20845         local mds_saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
20846         local client_saved=$($LCTL get_param -n jobid_var)
20847
20848         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$mds_saved" EXIT
20849         stack_trap "$LCTL set_param jobid_var=$client_saved" EXIT
20850
20851         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.job ||
20852                 error "failed to set job_xattr parameter to user.job"
20853         $LCTL set_param jobid_var=procname.uid ||
20854                 error "failed to set jobid_var parameter"
20855
20856         test_mkdir $dir
20857
20858         touch $f
20859         val=$(getfattr -n user.job $f | grep user.job)
20860         [[ $val = user.job=\"touch.0\" ]] ||
20861                 error "expected user.job=\"touch.0\", got '$val'"
20862
20863         mkdir $subdir
20864         val=$(getfattr -n user.job $subdir | grep user.job)
20865         [[ $val = user.job=\"mkdir.0\" ]] ||
20866                 error "expected user.job=\"mkdir.0\", got '$val'"
20867
20868         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=NONE ||
20869                 error "failed to set job_xattr parameter to NONE"
20870
20871         touch $f2
20872         val=$(getfattr -d $f2)
20873         [[ -z $val ]] ||
20874                 error "expected no user xattr, got '$val'"
20875
20876         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=trusted.job ||
20877                 error "failed to set job_xattr parameter to trusted.job"
20878
20879         touch $f3
20880         val=$(getfattr -n trusted.job $f3 | grep trusted.job)
20881         [[ $val = trusted.job=\"touch.0\" ]] ||
20882                 error "expected trusted.job=\"touch.0\", got '$val'"
20883 }
20884 run_test 205h "check jobid xattr is stored correctly"
20885
20886 test_205i() {
20887         (( $MDS1_VERSION >= $(version_code 2.15.57.7) )) ||
20888                 skip "Need MDS >= v2_15_57-7-g23a2db28dc for jobid xattr"
20889
20890         local mdts=$(comma_list $(mdts_nodes))
20891         local mds_saved=$(do_facet mds1 $LCTL get_param -n mdt.$FSNAME-MDT0000.job_xattr)
20892
20893         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.job_xattr=$mds_saved" EXIT
20894
20895         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.1234567 ||
20896                 error "failed to set mdt.*.job_xattr to user.1234567"
20897
20898         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.12345678 &&
20899                 error "failed to reject too long job_xattr name"
20900
20901         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=userjob &&
20902                 error "failed to reject job_xattr name in bad format"
20903
20904         do_nodes $mdts $LCTL set_param mdt.*.job_xattr=user.job/ &&
20905                 error "failed to reject job_xattr name with invalid character"
20906
20907         do_nodes $mdts "printf 'mdt.*.job_xattr=user.job\x80' |
20908                         xargs $LCTL set_param" &&
20909                 error "failed to reject job_xattr name with non-ascii character"
20910
20911         return 0
20912 }
20913 run_test 205i "check job_xattr parameter accepts and rejects values correctly"
20914
20915 # LU-1480, LU-1773 and LU-1657
20916 test_206() {
20917         mkdir -p $DIR/$tdir
20918         $LFS setstripe -c -1 $DIR/$tdir
20919 #define OBD_FAIL_LOV_INIT 0x1403
20920         $LCTL set_param fail_loc=0xa0001403
20921         $LCTL set_param fail_val=1
20922         touch $DIR/$tdir/$tfile || true
20923 }
20924 run_test 206 "fail lov_init_raid0() doesn't lbug"
20925
20926 test_207a() {
20927         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((RANDOM%10+1))
20928         local fsz=`stat -c %s $DIR/$tfile`
20929         cancel_lru_locks mdc
20930
20931         # do not return layout in getattr intent
20932 #define OBD_FAIL_MDS_NO_LL_GETATTR 0x170
20933         $LCTL set_param fail_loc=0x170
20934         local sz=`stat -c %s $DIR/$tfile`
20935
20936         [ $fsz -eq $sz ] || error "file size expected $fsz, actual $sz"
20937
20938         rm -rf $DIR/$tfile
20939 }
20940 run_test 207a "can refresh layout at glimpse"
20941
20942 test_207b() {
20943         dd if=/dev/zero of=$DIR/$tfile bs=4k count=$((RANDOM%10+1))
20944         local cksum=`md5sum $DIR/$tfile`
20945         local fsz=`stat -c %s $DIR/$tfile`
20946         cancel_lru_locks mdc
20947         cancel_lru_locks osc
20948
20949         # do not return layout in getattr intent
20950 #define OBD_FAIL_MDS_NO_LL_OPEN 0x171
20951         $LCTL set_param fail_loc=0x171
20952
20953         # it will refresh layout after the file is opened but before read issues
20954         echo checksum is "$cksum"
20955         echo "$cksum" |md5sum -c --quiet || error "file differs"
20956
20957         rm -rf $DIR/$tfile
20958 }
20959 run_test 207b "can refresh layout at open"
20960
20961 test_208() {
20962         # FIXME: in this test suite, only RD lease is used. This is okay
20963         # for now as only exclusive open is supported. After generic lease
20964         # is done, this test suite should be revised. - Jinshan
20965
20966         remote_mds_nodsh && skip "remote MDS with nodsh"
20967         [[ $MDS1_VERSION -ge $(version_code 2.4.52) ]] ||
20968                 skip "Need MDS version at least 2.4.52"
20969
20970         echo "==== test 1: verify get lease work"
20971         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:eRE+eU || error "get lease error"
20972
20973         echo "==== test 2: verify lease can be broken by upcoming open"
20974         $MULTIOP $DIR/$tfile oO_RDWR:eR_E-eUc &
20975         local PID=$!
20976         sleep 2
20977
20978         $MULTIOP $DIR/$tfile oO_RDWR:c
20979         kill -USR1 $PID && wait $PID || error "break lease error"
20980
20981         echo "==== test 3: verify lease can't be granted if an open already exists"
20982         $MULTIOP $DIR/$tfile oO_RDWR:_c &
20983         local PID=$!
20984         sleep 2
20985
20986         $MULTIOP $DIR/$tfile oO_RDWR:eReUc && error "apply lease should fail"
20987         kill -USR1 $PID && wait $PID || error "open file error"
20988
20989         echo "==== test 4: lease can sustain over recovery"
20990         $MULTIOP $DIR/$tfile oO_RDWR:eR_E+eUc &
20991         PID=$!
20992         sleep 2
20993
20994         fail mds1
20995
20996         kill -USR1 $PID && wait $PID || error "lease broken over recovery"
20997
20998         echo "==== test 5: lease broken can't be regained by replay"
20999         $MULTIOP $DIR/$tfile oO_RDWR:eR_E-eUc &
21000         PID=$!
21001         sleep 2
21002
21003         # open file to break lease and then recovery
21004         $MULTIOP $DIR/$tfile oO_RDWR:c || error "open file error"
21005         fail mds1
21006
21007         kill -USR1 $PID && wait $PID || error "lease not broken over recovery"
21008
21009         rm -f $DIR/$tfile
21010 }
21011 run_test 208 "Exclusive open"
21012
21013 test_209() {
21014         [ -z "$(lctl get_param -n mdc.*.connect_flags | grep disp_stripe)" ] &&
21015                 skip_env "must have disp_stripe"
21016
21017         touch $DIR/$tfile
21018         sync; sleep 5; sync;
21019
21020         echo 3 > /proc/sys/vm/drop_caches
21021         [ -f /sys/kernel/slab/ptlrpc_cache/shrink ] &&
21022                 echo 1 > /sys/kernel/slab/ptlrpc_cache/shrink
21023         req_before=$(awk '/ptlrpc_cache / { print $2 }' /proc/slabinfo)
21024
21025         # open/close 500 times
21026         for i in $(seq 500); do
21027                 cat $DIR/$tfile
21028         done
21029
21030         echo 3 > /proc/sys/vm/drop_caches
21031         [ -f /sys/kernel/slab/ptlrpc_cache/shrink ] &&
21032                 echo 1 > /sys/kernel/slab/ptlrpc_cache/shrink
21033         req_after=$(awk '/ptlrpc_cache / { print $2 }' /proc/slabinfo)
21034
21035         echo "before: $req_before, after: $req_after"
21036         [ $((req_after - req_before)) -ge 300 ] &&
21037                 error "open/close requests are not freed"
21038         return 0
21039 }
21040 run_test 209 "read-only open/close requests should be freed promptly"
21041
21042 test_210() {
21043         local pid
21044
21045         $MULTIOP $DIR/$tfile oO_CREAT:O_RDWR:eW_E+eUc &
21046         pid=$!
21047         sleep 1
21048
21049         $LFS getstripe $DIR/$tfile
21050         kill -USR1 $pid
21051         wait $pid || error "multiop failed"
21052
21053         $MULTIOP $DIR/$tfile oO_RDONLY:eR_E+eUc &
21054         pid=$!
21055         sleep 1
21056
21057         $LFS getstripe $DIR/$tfile
21058         kill -USR1 $pid
21059         wait $pid || error "multiop failed"
21060 }
21061 run_test 210 "lfs getstripe does not break leases"
21062
21063 function test_211() {
21064         local PID
21065         local id
21066         local rc
21067
21068         stack_trap "rm -f $DIR/$tfile" EXIT
21069         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=10 oflag=direct ||
21070                 error "can't create file"
21071         $LFS mirror extend -N $DIR/$tfile ||
21072                 error "can't create a replica"
21073         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1 oflag=direct
21074         $LFS getstripe $DIR/$tfile
21075         stale=$($LFS getstripe $DIR/$tfile | grep stale | wc -l)
21076         (( $stale != 1 )) && error "expected 1 stale, found $stale"
21077
21078         $MULTIOP $DIR/$tfile OeW_E+eUc &
21079         PID=$!
21080         sleep 0.3
21081
21082         id=$($LFS getstripe $DIR/$tfile |
21083                 awk '/lcme_mirror_id:/{id=$2}/lcme_flags.*init$/{print id}')
21084         $LFS mirror split -d --mirror-id $id $DIR/$tfile &&
21085                 error "removed last in-sync replica?"
21086
21087         kill -USR1 $PID
21088         wait $PID
21089         (( $? == 0 )) || error "failed split broke the lease"
21090 }
21091 run_test 211 "failed mirror split doesn't break write lease"
21092
21093 test_212() {
21094         size=`date +%s`
21095         size=$((size % 8192 + 1))
21096         dd if=/dev/urandom of=$DIR/f212 bs=1k count=$size
21097         sendfile $DIR/f212 $DIR/f212.xyz || error "sendfile wrong"
21098         rm -f $DIR/f212 $DIR/f212.xyz
21099 }
21100 run_test 212 "Sendfile test ============================================"
21101
21102 test_213() {
21103         dd if=/dev/zero of=$DIR/$tfile bs=4k count=4
21104         cancel_lru_locks osc
21105         lctl set_param fail_loc=0x8000040f
21106         # generate a read lock
21107         cat $DIR/$tfile > /dev/null
21108         # write to the file, it will try to cancel the above read lock.
21109         cat /etc/hosts >> $DIR/$tfile
21110 }
21111 run_test 213 "OSC lock completion and cancel race don't crash - bug 18829"
21112
21113 test_214() { # for bug 20133
21114         mkdir -p $DIR/$tdir/d214c || error "mkdir $DIR/$tdir/d214c failed"
21115         for (( i=0; i < 340; i++ )) ; do
21116                 touch $DIR/$tdir/d214c/a$i
21117         done
21118
21119         ls -l $DIR/$tdir || error "ls -l $DIR/d214p failed"
21120         mv $DIR/$tdir/d214c $DIR/ || error "mv $DIR/d214p/d214c $DIR/ failed"
21121         ls $DIR/d214c || error "ls $DIR/d214c failed"
21122         rm -rf $DIR/$tdir || error "rm -rf $DIR/d214* failed"
21123         rm -rf $DIR/d214* || error "rm -rf $DIR/d214* failed"
21124 }
21125 run_test 214 "hash-indexed directory test - bug 20133"
21126
21127 # having "abc" as 1st arg, creates $TMP/lnet_abc.out and $TMP/lnet_abc.sys
21128 create_lnet_proc_files() {
21129         lctl get_param -n $1 >$TMP/lnet_$1.sys || error "cannot read lnet.$1"
21130 }
21131
21132 # counterpart of create_lnet_proc_files
21133 remove_lnet_proc_files() {
21134         rm -f $TMP/lnet_$1.sys
21135 }
21136
21137 # uses 1st arg as trailing part of filename, 2nd arg as description for reports,
21138 # 3rd arg as regexp for body
21139 check_lnet_proc_stats() {
21140         local l=$(cat "$TMP/lnet_$1" |wc -l)
21141         [ $l = 1 ] || (cat "$TMP/lnet_$1" && error "$2 is not of 1 line: $l")
21142
21143         grep -E "$3" "$TMP/lnet_$1" || (cat "$TMP/lnet_$1" && error "$2 misformatted")
21144 }
21145
21146 # uses 1st arg as trailing part of filename, 2nd arg as description for reports,
21147 # 3rd arg as regexp for body, 4th arg as regexp for 1st line, 5th arg is
21148 # optional and can be regexp for 2nd line (lnet.routes case)
21149 check_lnet_proc_entry() {
21150         local blp=2          # blp stands for 'position of 1st line of body'
21151         [ -z "$5" ] || blp=3 # lnet.routes case
21152
21153         local l=$(cat "$TMP/lnet_$1" |wc -l)
21154         # subtracting one from $blp because the body can be empty
21155         [ "$l" -ge "$(($blp - 1))" ] || (cat "$TMP/lnet_$1" && error "$2 is too short: $l")
21156
21157         sed -n '1 p' "$TMP/lnet_$1" |grep -E "$4" >/dev/null ||
21158                 (cat "$TMP/lnet_$1" && error "1st line of $2 misformatted")
21159
21160         [ "$5" = "" ] || sed -n '2 p' "$TMP/lnet_$1" |grep -E "$5" >/dev/null ||
21161                 (cat "$TMP/lnet_$1" && error "2nd line of $2 misformatted")
21162
21163         # bail out if any unexpected line happened
21164         sed -n "$blp p" "$TMP/lnet_$1" | grep -Ev "$3"
21165         [ "$?" != 0 ] || error "$2 misformatted"
21166 }
21167
21168 test_215() { # for bugs 18102, 21079, 21517
21169         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21170
21171         local N='(0|[1-9][0-9]*)'       # non-negative numeric
21172         local P='[1-9][0-9]*'           # positive numeric
21173         local I='(0|-?[1-9][0-9]*|NA)'  # any numeric (0 | >0 | <0) or NA if no value
21174         local NET='[a-z][a-z0-9]*'      # LNet net like o2ib2
21175         local ADDR='[0-9.]+'            # LNet addr like 10.0.0.1
21176         local ADDR6='([0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}' # IPv6 LNet addr
21177         local NID="$ADDR@$NET"          # LNet nid like 10.0.0.1@o2ib2
21178         local NID6="$ADDR6@$NET"        # LNet nid like 2601:8c1:c180::cbdd@tcp
21179
21180         local L1 # regexp for 1st line
21181         local L2 # regexp for 2nd line (optional)
21182         local BR # regexp for the rest (body)
21183
21184         # lnet.stats should look as 11 space-separated non-negative numerics
21185         BR="^$N $N $N $N $N $N $N $N $N $N $N$"
21186         create_lnet_proc_files "stats"
21187         check_lnet_proc_stats "stats.sys" "lnet.stats" "$BR"
21188         remove_lnet_proc_files "stats"
21189
21190         # lnet.routes should look like this:
21191         # Routing disabled/enabled
21192         # net hops priority state router
21193         # where net is a string like tcp0, hops > 0, priority >= 0,
21194         # state is up/down,
21195         # router is a string like 192.168.1.1@tcp2
21196         L1="^Routing (disabled|enabled)$"
21197         L2="^net +hops +priority +state +router$"
21198         BR="^$NET +$N +(0|1) +(up|down) +($NID|$NID6)$"
21199         create_lnet_proc_files "routes"
21200         check_lnet_proc_entry "routes.sys" "lnet.routes" "$BR" "$L1" "$L2"
21201         remove_lnet_proc_files "routes"
21202
21203         # lnet.routers should look like this:
21204         # ref rtr_ref alive_cnt state last_ping ping_sent deadline down_ni router
21205         # where ref > 0, rtr_ref > 0, alive_cnt >= 0, state is up/down,
21206         # last_ping >= 0, ping_sent is boolean (0/1), deadline and down_ni are
21207         # numeric (0 or >0 or <0), router is a string like 192.168.1.1@tcp2
21208         L1="^ref +rtr_ref +alive +router$"
21209         BR="^$P +$P +(up|down) +($NID|$NID6)$"
21210         create_lnet_proc_files "routers"
21211         check_lnet_proc_entry "routers.sys" "lnet.routers" "$BR" "$L1"
21212         remove_lnet_proc_files "routers"
21213
21214         # lnet.peers should look like this:
21215         # nid refs state last max rtr min tx min queue
21216         # where nid is a string like 192.168.1.1@tcp2, refs > 0,
21217         # state is up/down/NA, max >= 0. last, rtr, min, tx, min are
21218         # numeric (0 or >0 or <0), queue >= 0.
21219         L1="^nid +refs +state +last +max +rtr +min +tx +min +queue$"
21220         BR="^($NID|$NID6) +$P +(up|down|NA) +$I +$N +$I +$I +$I +$I +$N$"
21221         create_lnet_proc_files "peers"
21222         check_lnet_proc_entry "peers.sys" "lnet.peers" "$BR" "$L1"
21223         remove_lnet_proc_files "peers"
21224
21225         # lnet.buffers  should look like this:
21226         # pages count credits min
21227         # where pages >=0, count >=0, credits and min are numeric (0 or >0 or <0)
21228         L1="^pages +count +credits +min$"
21229         BR="^ +$N +$N +$I +$I$"
21230         create_lnet_proc_files "buffers"
21231         check_lnet_proc_entry "buffers.sys" "lnet.buffers" "$BR" "$L1"
21232         remove_lnet_proc_files "buffers"
21233
21234         # lnet.nis should look like this:
21235         # nid status alive refs peer rtr max tx min
21236         # where nid is a string like 192.168.1.1@tcp2, status is up/down,
21237         # alive is numeric (0 or >0 or <0), refs >= 0, peer >= 0,
21238         # rtr >= 0, max >=0, tx and min are numeric (0 or >0 or <0).
21239         L1="^nid +status +alive +refs +peer +rtr +max +tx +min$"
21240         BR="^($NID|$NID6) +(up|down) +$I +$N +$N +$N +$N +$I +$I$"
21241         create_lnet_proc_files "nis"
21242         check_lnet_proc_entry "nis.sys" "lnet.nis" "$BR" "$L1"
21243         remove_lnet_proc_files "nis"
21244
21245         # can we successfully write to lnet.stats?
21246         lctl set_param -n stats=0 || error "cannot write to lnet.stats"
21247 }
21248 run_test 215 "lnet exists and has proper content - bugs 18102, 21079, 21517"
21249
21250 test_216() { # bug 20317
21251         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21252         remote_ost_nodsh && skip "remote OST with nodsh"
21253
21254         local node
21255         local facets=$(get_facets OST)
21256         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
21257
21258         save_lustre_params client "osc.*.contention_seconds" > $p
21259         save_lustre_params $facets \
21260                 "ldlm.namespaces.filter-*.max_nolock_bytes" >> $p
21261         save_lustre_params $facets \
21262                 "ldlm.namespaces.filter-*.contended_locks" >> $p
21263         save_lustre_params $facets \
21264                 "ldlm.namespaces.filter-*.contention_seconds" >> $p
21265         clear_stats osc.*.osc_stats
21266
21267         # agressive lockless i/o settings
21268         do_nodes $(comma_list $(osts_nodes)) \
21269                 "lctl set_param -n ldlm.namespaces.*.max_nolock_bytes=2000000 \
21270                         ldlm.namespaces.filter-*.contended_locks=0 \
21271                         ldlm.namespaces.filter-*.contention_seconds=60"
21272         lctl set_param -n osc.*.contention_seconds=60
21273
21274         $DIRECTIO write $DIR/$tfile 0 10 4096
21275         $CHECKSTAT -s 40960 $DIR/$tfile
21276
21277         # disable lockless i/o
21278         do_nodes $(comma_list $(osts_nodes)) \
21279                 "lctl set_param -n ldlm.namespaces.filter-*.max_nolock_bytes=0 \
21280                         ldlm.namespaces.filter-*.contended_locks=32 \
21281                         ldlm.namespaces.filter-*.contention_seconds=0"
21282         lctl set_param -n osc.*.contention_seconds=0
21283         clear_stats osc.*.osc_stats
21284
21285         dd if=/dev/zero of=$DIR/$tfile count=0
21286         $CHECKSTAT -s 0 $DIR/$tfile
21287
21288         restore_lustre_params <$p
21289         rm -f $p
21290         rm $DIR/$tfile
21291 }
21292 run_test 216 "check lockless direct write updates file size and kms correctly"
21293
21294 test_217() { # bug 22430
21295         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21296
21297         local node
21298
21299         for node in $(nodes_list); do
21300                 local nid=$(host_nids_address $node $NETTYPE)
21301                 local node_ip=$(do_node $node getent ahostsv4 $node |
21302                                 awk '{ print $1; exit; }')
21303
21304                 echo "node: '$node', nid: '$nid', node_ip='$node_ip'"
21305                 # if hostname matches any NID, use hostname for better testing
21306                 if [[ -z "$nid" || "$nid" =~ "$node_ip" ]]; then
21307                         echo "lctl ping node $node@$NETTYPE"
21308                         lctl ping $node@$NETTYPE ||
21309                                 error "ping $node@$NETTYPE failed rc=$?"
21310                 else # otherwise, at least test 'lctl ping' is working
21311                         echo "lctl ping nid $(h2nettype $nid)"
21312                         lctl ping $(h2nettype $nid) ||
21313                                 error "ping $(h2nettype $nid) failed rc=$?"
21314                         echo "skipping $node (no hyphen detected)"
21315                 fi
21316         done
21317
21318         return 0
21319 }
21320 run_test 217 "check lctl ping for hostnames with embedded hyphen ('-')"
21321
21322 test_218() {
21323         # do directio so as not to populate the page cache
21324         log "creating a 10 Mb file"
21325         $MULTIOP $DIR/$tfile oO_CREAT:O_DIRECT:O_RDWR:w$((10*1048576))c ||
21326                 error "multiop failed while creating a file"
21327         log "starting reads"
21328         dd if=$DIR/$tfile of=/dev/null bs=4096 &
21329         log "truncating the file"
21330         $MULTIOP $DIR/$tfile oO_TRUNC:c ||
21331                 error "multiop failed while truncating the file"
21332         log "killing dd"
21333         kill %+ || true # reads might have finished
21334         echo "wait until dd is finished"
21335         wait
21336         log "removing the temporary file"
21337         rm -rf $DIR/$tfile || error "tmp file removal failed"
21338 }
21339 run_test 218 "parallel read and truncate should not deadlock"
21340
21341 test_219() {
21342         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21343
21344         # write one partial page
21345         dd if=/dev/zero of=$DIR/$tfile bs=1024 count=1
21346         # set no grant so vvp_io_commit_write will do sync write
21347         $LCTL set_param fail_loc=0x411
21348         # write a full page at the end of file
21349         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 seek=1 conv=notrunc
21350
21351         $LCTL set_param fail_loc=0
21352         dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 seek=3
21353         $LCTL set_param fail_loc=0x411
21354         dd if=/dev/zero of=$DIR/$tfile bs=1024 count=1 seek=2 conv=notrunc
21355
21356         # LU-4201
21357         dd if=/dev/zero of=$DIR/$tfile-2 bs=1024 count=1
21358         $CHECKSTAT -s 1024 $DIR/$tfile-2 || error "checkstat wrong size"
21359 }
21360 run_test 219 "LU-394: Write partial won't cause uncontiguous pages vec at LND"
21361
21362 test_220() { #LU-325
21363         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21364         remote_ost_nodsh && skip "remote OST with nodsh"
21365         remote_mds_nodsh && skip "remote MDS with nodsh"
21366         remote_mgs_nodsh && skip "remote MGS with nodsh"
21367
21368         local OSTIDX=0
21369
21370         # create on MDT0000 so the last_id and next_id are correct
21371         mkdir_on_mdt0 $DIR/$tdir
21372         local OST=$($LFS df $DIR | awk '/OST:'$OSTIDX'/ { print $1 }')
21373         OST=${OST%_UUID}
21374
21375         # on the mdt's osc
21376         local mdtosc_proc1=$(get_mdtosc_proc_path $SINGLEMDS $OST)
21377         local last_id=$(do_facet $SINGLEMDS lctl get_param -n \
21378                         osp.$mdtosc_proc1.prealloc_last_id)
21379         local next_id=$(do_facet $SINGLEMDS lctl get_param -n \
21380                         osp.$mdtosc_proc1.prealloc_next_id)
21381
21382         $LFS df -i
21383
21384         do_facet ost$((OSTIDX + 1)) lctl set_param fail_val=-1
21385         #define OBD_FAIL_OST_ENOINO              0x229
21386         do_facet ost$((OSTIDX + 1)) lctl set_param fail_loc=0x229
21387         create_pool $FSNAME.$TESTNAME || return 1
21388         do_facet mgs $LCTL pool_add $FSNAME.$TESTNAME $OST || return 2
21389
21390         $LFS setstripe $DIR/$tdir -i $OSTIDX -c 1 -p $FSNAME.$TESTNAME
21391
21392         MDSOBJS=$((last_id - next_id))
21393         echo "preallocated objects on MDS is $MDSOBJS" "($last_id - $next_id)"
21394
21395         blocks=$($LFS df $MOUNT | awk '($1 == '$OSTIDX') { print $4 }')
21396         echo "OST still has $count kbytes free"
21397
21398         echo "create $MDSOBJS files @next_id..."
21399         createmany -o $DIR/$tdir/f $MDSOBJS || return 3
21400
21401         local last_id2=$(do_facet mds${MDSIDX} lctl get_param -n \
21402                         osp.$mdtosc_proc1.prealloc_last_id)
21403         local next_id2=$(do_facet mds${MDSIDX} lctl get_param -n \
21404                         osp.$mdtosc_proc1.prealloc_next_id)
21405
21406         echo "after creation, last_id=$last_id2, next_id=$next_id2"
21407         $LFS df -i
21408
21409         echo "cleanup..."
21410
21411         do_facet ost$((OSTIDX + 1)) lctl set_param fail_val=0
21412         do_facet ost$((OSTIDX + 1)) lctl set_param fail_loc=0
21413
21414         do_facet mgs $LCTL pool_remove $FSNAME.$TESTNAME $OST ||
21415                 error "$LCTL pool_remove $FSNAME.$TESTNAME $OST failed"
21416         do_facet mgs $LCTL pool_destroy $FSNAME.$TESTNAME ||
21417                 error "$LCTL pool_destroy $FSNAME.$TESTNAME failed"
21418         echo "unlink $MDSOBJS files @$next_id..."
21419         unlinkmany $DIR/$tdir/f $MDSOBJS || error "unlinkmany failed"
21420 }
21421 run_test 220 "preallocated MDS objects still used if ENOSPC from OST"
21422
21423 test_221() {
21424         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21425
21426         dd if=`which date` of=$MOUNT/date oflag=sync
21427         chmod +x $MOUNT/date
21428
21429         #define OBD_FAIL_LLITE_FAULT_TRUNC_RACE  0x1401
21430         $LCTL set_param fail_loc=0x80001401
21431
21432         $MOUNT/date > /dev/null
21433         rm -f $MOUNT/date
21434 }
21435 run_test 221 "make sure fault and truncate race to not cause OOM"
21436
21437 test_222a () {
21438         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21439
21440         rm -rf $DIR/$tdir
21441         test_mkdir $DIR/$tdir
21442         $LFS setstripe -c 1 -i 0 $DIR/$tdir
21443         createmany -o $DIR/$tdir/$tfile 10
21444         cancel_lru_locks mdc
21445         cancel_lru_locks osc
21446         #define OBD_FAIL_LDLM_AGL_DELAY           0x31a
21447         $LCTL set_param fail_loc=0x31a
21448         ls -l $DIR/$tdir > /dev/null || error "AGL for ls failed"
21449         $LCTL set_param fail_loc=0
21450         rm -r $DIR/$tdir
21451 }
21452 run_test 222a "AGL for ls should not trigger CLIO lock failure"
21453
21454 test_222b () {
21455         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21456
21457         rm -rf $DIR/$tdir
21458         test_mkdir $DIR/$tdir
21459         $LFS setstripe -c 1 -i 0 $DIR/$tdir
21460         createmany -o $DIR/$tdir/$tfile 10
21461         cancel_lru_locks mdc
21462         cancel_lru_locks osc
21463         #define OBD_FAIL_LDLM_AGL_DELAY           0x31a
21464         $LCTL set_param fail_loc=0x31a
21465         rm -r $DIR/$tdir || error "AGL for rmdir failed"
21466         $LCTL set_param fail_loc=0
21467 }
21468 run_test 222b "AGL for rmdir should not trigger CLIO lock failure"
21469
21470 test_223 () {
21471         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21472
21473         rm -rf $DIR/$tdir
21474         test_mkdir $DIR/$tdir
21475         $LFS setstripe -c 1 -i 0 $DIR/$tdir
21476         createmany -o $DIR/$tdir/$tfile 10
21477         cancel_lru_locks mdc
21478         cancel_lru_locks osc
21479         #define OBD_FAIL_LDLM_AGL_NOLOCK          0x31b
21480         $LCTL set_param fail_loc=0x31b
21481         ls -l $DIR/$tdir > /dev/null || error "reenqueue failed"
21482         $LCTL set_param fail_loc=0
21483         rm -r $DIR/$tdir
21484 }
21485 run_test 223 "osc reenqueue if without AGL lock granted ======================="
21486
21487 test_224a() { # LU-1039, MRP-303
21488         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21489         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB   0x508
21490         $LCTL set_param fail_loc=0x508
21491         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 conv=fsync
21492         $LCTL set_param fail_loc=0
21493         df $DIR
21494 }
21495 run_test 224a "Don't panic on bulk IO failure"
21496
21497 test_224bd_sub() { # LU-1039, MRP-303
21498         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21499         local timeout=$1
21500
21501         shift
21502         dd if=/dev/urandom of=$TMP/$tfile bs=1M count=1
21503
21504         $LFS setstripe -c 1 -i 0 $DIR/$tfile
21505
21506         dd if=$TMP/$tfile of=$DIR/$tfile bs=1M count=1
21507         cancel_lru_locks osc
21508         set_checksums 0
21509         stack_trap "set_checksums $ORIG_CSUM" EXIT
21510         local at_max_saved=0
21511
21512         # adaptive timeouts may prevent seeing the issue
21513         if at_is_enabled; then
21514                 at_max_saved=$(at_max_get mds)
21515                 at_max_set 0 mds client
21516                 stack_trap "at_max_set $at_max_saved mds client" EXIT
21517         fi
21518
21519         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB2   0x515
21520         do_facet ost1 $LCTL set_param fail_val=$timeout fail_loc=0x80000515
21521         dd of=$TMP/$tfile.new if=$DIR/$tfile bs=1M count=1 || "$@"
21522
21523         do_facet ost1 $LCTL set_param fail_loc=0
21524         cmp $TMP/$tfile $TMP/$tfile.new || error "file contents wrong"
21525         df $DIR
21526 }
21527
21528 test_224b() {
21529         test_224bd_sub 3 error "dd failed"
21530 }
21531 run_test 224b "Don't panic on bulk IO failure"
21532
21533 test_224c() { # LU-6441
21534         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21535         remote_mds_nodsh && skip "remote MDS with nodsh"
21536
21537         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
21538         save_writethrough $p
21539         set_cache writethrough on
21540
21541         local pages_per_rpc=$($LCTL get_param osc.*.max_pages_per_rpc)
21542         local at_max=$($LCTL get_param -n at_max)
21543         local timeout=$($LCTL get_param -n timeout)
21544         local test_at="at_max"
21545         local param_at="$FSNAME.sys.at_max"
21546         local test_timeout="timeout"
21547         local param_timeout="$FSNAME.sys.timeout"
21548
21549         $LCTL set_param -n osc.*.max_pages_per_rpc=1024
21550
21551         set_persistent_param_and_check client "$test_at" "$param_at" 0
21552         set_persistent_param_and_check client "$test_timeout" "$param_timeout" 5
21553
21554         #define OBD_FAIL_PTLRPC_CLIENT_BULK_CB3 0x520
21555         do_facet ost1 "$LCTL set_param fail_loc=0x520"
21556         $LFS setstripe -c 1 -i 0 $DIR/$tfile
21557         stack_trap "rm -f $DIR/$tfile"
21558         dd if=/dev/zero of=$DIR/$tfile bs=8MB count=1
21559         sync
21560         do_facet ost1 "$LCTL set_param fail_loc=0"
21561
21562         set_persistent_param_and_check client "$test_at" "$param_at" $at_max
21563         set_persistent_param_and_check client "$test_timeout" "$param_timeout" \
21564                 $timeout
21565
21566         $LCTL set_param -n $pages_per_rpc
21567         restore_lustre_params < $p
21568         rm -f $p
21569 }
21570 run_test 224c "Don't hang if one of md lost during large bulk RPC"
21571
21572 test_224d() { # LU-11169
21573         test_224bd_sub $((TIMEOUT + 2)) error "dd failed"
21574 }
21575 run_test 224d "Don't corrupt data on bulk IO timeout"
21576
21577 MDSSURVEY=${MDSSURVEY:-$(which mds-survey 2>/dev/null || true)}
21578 test_225a () {
21579         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21580         if [ -z ${MDSSURVEY} ]; then
21581                 skip_env "mds-survey not found"
21582         fi
21583         [ $MDS1_VERSION -ge $(version_code 2.2.51) ] ||
21584                 skip "Need MDS version at least 2.2.51"
21585
21586         local mds=$(facet_host $SINGLEMDS)
21587         local target=$(do_nodes $mds 'lctl dl' |
21588                        awk '{ if ($2 == "UP" && $3 == "mdt") { print $4 }}')
21589
21590         local cmd1="file_count=1000 thrhi=4"
21591         local cmd2="dir_count=2 layer=mdd stripe_count=0"
21592         local cmd3="rslt_loc=${TMP} targets=\"$mds:$target\" $MDSSURVEY"
21593         local cmd="$cmd1 $cmd2 $cmd3"
21594
21595         rm -f ${TMP}/mds_survey*
21596         echo + $cmd
21597         eval $cmd || error "mds-survey with zero-stripe failed"
21598         cat ${TMP}/mds_survey*
21599         rm -f ${TMP}/mds_survey*
21600 }
21601 run_test 225a "Metadata survey sanity with zero-stripe"
21602
21603 test_225b () {
21604         if [ -z ${MDSSURVEY} ]; then
21605                 skip_env "mds-survey not found"
21606         fi
21607         [ $MDS1_VERSION -ge $(version_code 2.2.51) ] ||
21608                 skip "Need MDS version at least 2.2.51"
21609         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21610         remote_mds_nodsh && skip "remote MDS with nodsh"
21611         if [ $($LCTL dl | grep -c osc) -eq 0 ]; then
21612                 skip_env "Need to mount OST to test"
21613         fi
21614
21615         local mds=$(facet_host $SINGLEMDS)
21616         local target=$(do_nodes $mds 'lctl dl' |
21617                        awk '{ if ($2 == "UP" && $3 == "mdt") { print $4 }}')
21618
21619         local cmd1="file_count=1000 thrhi=4"
21620         local cmd2="dir_count=2 layer=mdd stripe_count=1"
21621         local cmd3="rslt_loc=${TMP} targets=\"$mds:$target\" $MDSSURVEY"
21622         local cmd="$cmd1 $cmd2 $cmd3"
21623
21624         rm -f ${TMP}/mds_survey*
21625         echo + $cmd
21626         eval $cmd || error "mds-survey with stripe_count failed"
21627         cat ${TMP}/mds_survey*
21628         rm -f ${TMP}/mds_survey*
21629 }
21630 run_test 225b "Metadata survey sanity with stripe_count = 1"
21631
21632 mcreate_path2fid () {
21633         local mode=$1
21634         local major=$2
21635         local minor=$3
21636         local name=$4
21637         local desc=$5
21638         local path=$DIR/$tdir/$name
21639         local fid
21640         local rc
21641         local fid_path
21642
21643         $MCREATE --mode=$1 --major=$2 --minor=$3 $path ||
21644                 error "cannot create $desc"
21645
21646         fid=$($LFS path2fid $path | tr -d '[' | tr -d ']')
21647         rc=$?
21648         [ $rc -ne 0 ] && error "cannot get fid of a $desc"
21649
21650         fid_path=$($LFS fid2path $MOUNT $fid)
21651         rc=$?
21652         [ $rc -ne 0 ] && error "cannot get path of $desc by $DIR $path $fid"
21653
21654         [ "$path" == "$fid_path" ] ||
21655                 error "fid2path returned $fid_path, expected $path"
21656
21657         echo "pass with $path and $fid"
21658 }
21659
21660 test_226a () {
21661         rm -rf $DIR/$tdir
21662         mkdir -p $DIR/$tdir
21663
21664         mcreate_path2fid 0010666 0 0 fifo "FIFO"
21665         mcreate_path2fid 0020666 1 3 null "character special file (null)"
21666         mcreate_path2fid 0020666 1 255 none "character special file (no device)"
21667         mcreate_path2fid 0040666 0 0 dir "directory"
21668         mcreate_path2fid 0060666 7 0 loop0 "block special file (loop)"
21669         mcreate_path2fid 0100666 0 0 file "regular file"
21670         mcreate_path2fid 0120666 0 0 link "symbolic link"
21671         mcreate_path2fid 0140666 0 0 sock "socket"
21672 }
21673 run_test 226a "call path2fid and fid2path on files of all type"
21674
21675 test_226b () {
21676         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
21677
21678         local MDTIDX=1
21679
21680         rm -rf $DIR/$tdir
21681         mkdir -p $DIR/$tdir
21682         $LFS setdirstripe -i $MDTIDX $DIR/$tdir/remote_dir ||
21683                 error "create remote directory failed"
21684         mcreate_path2fid 0010666 0 0 "remote_dir/fifo" "FIFO"
21685         mcreate_path2fid 0020666 1 3 "remote_dir/null" \
21686                                 "character special file (null)"
21687         mcreate_path2fid 0020666 1 255 "remote_dir/none" \
21688                                 "character special file (no device)"
21689         mcreate_path2fid 0040666 0 0 "remote_dir/dir" "directory"
21690         mcreate_path2fid 0060666 7 0 "remote_dir/loop0" \
21691                                 "block special file (loop)"
21692         mcreate_path2fid 0100666 0 0 "remote_dir/file" "regular file"
21693         mcreate_path2fid 0120666 0 0 "remote_dir/link" "symbolic link"
21694         mcreate_path2fid 0140666 0 0 "remote_dir/sock" "socket"
21695 }
21696 run_test 226b "call path2fid and fid2path on files of all type under remote dir"
21697
21698 test_226c () {
21699         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
21700         [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
21701                 skip "Need MDS version at least 2.13.55"
21702
21703         local submnt=/mnt/submnt
21704         local srcfile=/etc/passwd
21705         local dstfile=$submnt/passwd
21706         local path
21707         local fid
21708
21709         rm -rf $DIR/$tdir
21710         rm -rf $submnt
21711         $LFS setdirstripe -c -1 -i 1 $DIR/$tdir ||
21712                 error "create remote directory failed"
21713         mkdir -p $submnt || error "create $submnt failed"
21714         $MOUNT_CMD $MGSNID:/$FSNAME/$tdir $submnt ||
21715                 error "mount $submnt failed"
21716         stack_trap "umount $submnt" EXIT
21717
21718         cp $srcfile $dstfile
21719         fid=$($LFS path2fid $dstfile)
21720         path=$($LFS fid2path $submnt "$fid")
21721         [ "$path" = "$dstfile" ] ||
21722                 error "fid2path $submnt $fid failed ($path != $dstfile)"
21723 }
21724 run_test 226c "call path2fid and fid2path under remote dir with subdir mount"
21725
21726 test_226d () {
21727         (( $CLIENT_VERSION >= $(version_code 2.15.57) )) ||
21728                 skip "Need client at least version 2.15.57"
21729
21730         # Define First test dataset
21731         local testdirs_01=$DIR/$tdir
21732         local testdata_01=$testdirs_01/${tdir}_01
21733         local testresult_01=${tdir}_01
21734         # Define Second test dataset
21735         local testdirs_02=$DIR/$tdir/$tdir
21736         local testdata_02=$testdirs_02/${tdir}_02
21737         local testresult_02=${tdir}_02
21738         # Define third test dataset (top level)
21739         local testdata_03=$DIR/${tdir}_03
21740         local testresult_03=${tdir}_03
21741
21742         # Create first test dataset
21743         mkdir -p $testdirs_01 || error "cannot create dir $testdirs_01"
21744         touch $testdata_01 || error "cannot create file $testdata_01"
21745
21746         # Create second test dataset
21747         mkdir -p $testdirs_02 || error "cannot create dir $testdirs_02"
21748         touch $testdata_02 || error "cannot create file $testdata_02"
21749
21750         # Create third test dataset
21751         touch $testdata_03 || error "cannot create file $testdata_03"
21752
21753         local fid01=$($LFS getstripe -F "$testdata_01") ||
21754                 error "getstripe failed on $testdata_01"
21755         local fid02=$($LFS getstripe -F "$testdata_02") ||
21756                 error "getstripe failed on $testdata_01"
21757         local fid03=$($LFS getstripe -F "$testdata_03") ||
21758                 error "getstripe failed on $testdata_03"
21759
21760         # Verify only -n option
21761         local out1=$($LFS fid2path -n $DIR $fid01) ||
21762                 error "fid2path failed on $fid01"
21763         local out2=$($LFS fid2path -n $DIR $fid02) ||
21764                 error "fid2path failed on $fid02"
21765         local out3=$($LFS fid2path -n $DIR $fid03) ||
21766                 error "fid2path failed on $fid03"
21767
21768         [[ "$out1" == "$testresult_01" ]] ||
21769                 error "fid2path failed: Expected $testresult_01 got $out1"
21770         [[ "$out2" == "$testresult_02" ]] ||
21771                 error "fid2path failed: Expected $testresult_02 got $out2"
21772         [[ "$out3" == "$testresult_03" ]] ||
21773                 error "fid2path failed: Expected $testresult_03 got $out3"
21774
21775         # Verify with option -fn together
21776         out1=$($LFS fid2path -fn $DIR $fid01) ||
21777                 error "fid2path -fn failed on $fid01"
21778         out2=$($LFS fid2path -fn $DIR $fid02) ||
21779                 error "fid2path -fn failed on $fid02"
21780         out3=$($LFS fid2path -fn $DIR $fid03) ||
21781                 error "fid2path -fn failed on $fid03"
21782
21783         local tmpout=$(echo $out1 | cut -d" " -f2)
21784         [[ "$tmpout" == "$testresult_01" ]] ||
21785                 error "fid2path -fn failed: Expected $testresult_01 got $out1"
21786
21787         tmpout=$(echo $out2 | cut -d" " -f2)
21788         [[ "$tmpout" == "$testresult_02" ]] ||
21789                 error "fid2path -fn failed: Expected $testresult_02 got $out2"
21790
21791         tmpout=$(echo $out3 | cut -d" " -f2)
21792         [[ "$tmpout" == "$testresult_03" ]] ||
21793                 error "fid2path -fn failed: Expected $testresult_03 got $out3"
21794 }
21795 run_test 226d "verify fid2path with -n and -fn option"
21796
21797 test_226e () {
21798         (( $CLIENT_VERSION >= $(version_code 2.15.56) )) ||
21799                 skip "Need client at least version 2.15.56"
21800
21801         # Define filename with 'newline' and a space
21802         local testfile="Test"$'\n'"file 01"
21803         # Define link name with multiple 'newline' and a space
21804         local linkfile="Link"$'\n'"file "$'\n'"01"
21805         # Remove prior hard link
21806         rm -f $DIR/"$linkfile"
21807
21808         # Create file
21809         touch $DIR/"$testfile"
21810         # Create link
21811         ln $DIR/"$testfile" $DIR/"$linkfile"
21812
21813         local fid=$($LFS getstripe -F "$DIR/$testfile") ||
21814                 error "getstripe failed on $DIR/$testfile"
21815
21816         # Call with -0 option
21817         local out1=$($LFS fid2path -0 $DIR $fid | xargs --null -n1 \
21818                 echo "FILE:" | grep -c "FILE:")
21819
21820         # With -0 option the output should be exactly 2 lines.
21821         (( $out1 == 2 )) || error "fid2path -0 failed on $fid, $out1"
21822 }
21823 run_test 226e "Verify path2fid -0 option with newline and space"
21824
21825 # LU-1299 Executing or running ldd on a truncated executable does not
21826 # cause an out-of-memory condition.
21827 test_227() {
21828         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21829         [ -z "$(which ldd)" ] && skip_env "should have ldd tool"
21830
21831         dd if=$(which date) of=$MOUNT/date bs=1k count=1
21832         chmod +x $MOUNT/date
21833
21834         $MOUNT/date > /dev/null
21835         ldd $MOUNT/date > /dev/null
21836         rm -f $MOUNT/date
21837 }
21838 run_test 227 "running truncated executable does not cause OOM"
21839
21840 # LU-1512 try to reuse idle OI blocks
21841 test_228a() {
21842         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21843         remote_mds_nodsh && skip "remote MDS with nodsh"
21844         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
21845
21846         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
21847         local myDIR=$DIR/$tdir
21848
21849         mkdir -p $myDIR
21850         #define OBD_FAIL_SEQ_EXHAUST             0x1002
21851         $LCTL set_param fail_loc=0x80001002
21852         createmany -o $myDIR/t- 10000
21853         $LCTL set_param fail_loc=0
21854         # The guard is current the largest FID holder
21855         touch $myDIR/guard
21856         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
21857                     tr -d '[')
21858         local IDX=$(($SEQ % 64))
21859
21860         do_facet $SINGLEMDS sync
21861         # Make sure journal flushed.
21862         sleep 6
21863         local blk1=$(do_facet $SINGLEMDS \
21864                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21865                      grep Blockcount | awk '{print $4}')
21866
21867         # Remove old files, some OI blocks will become idle.
21868         unlinkmany $myDIR/t- 10000
21869         # Create new files, idle OI blocks should be reused.
21870         createmany -o $myDIR/t- 2000
21871         do_facet $SINGLEMDS sync
21872         # Make sure journal flushed.
21873         sleep 6
21874         local blk2=$(do_facet $SINGLEMDS \
21875                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21876                      grep Blockcount | awk '{print $4}')
21877
21878         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
21879 }
21880 run_test 228a "try to reuse idle OI blocks"
21881
21882 test_228b() {
21883         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21884         remote_mds_nodsh && skip "remote MDS with nodsh"
21885         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
21886
21887         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
21888         local myDIR=$DIR/$tdir
21889
21890         mkdir -p $myDIR
21891         #define OBD_FAIL_SEQ_EXHAUST             0x1002
21892         $LCTL set_param fail_loc=0x80001002
21893         createmany -o $myDIR/t- 10000
21894         $LCTL set_param fail_loc=0
21895         # The guard is current the largest FID holder
21896         touch $myDIR/guard
21897         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
21898                     tr -d '[')
21899         local IDX=$(($SEQ % 64))
21900
21901         do_facet $SINGLEMDS sync
21902         # Make sure journal flushed.
21903         sleep 6
21904         local blk1=$(do_facet $SINGLEMDS \
21905                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21906                      grep Blockcount | awk '{print $4}')
21907
21908         # Remove old files, some OI blocks will become idle.
21909         unlinkmany $myDIR/t- 10000
21910
21911         # stop the MDT
21912         stop $SINGLEMDS || error "Fail to stop MDT."
21913         # remount the MDT
21914         start $SINGLEMDS $(facet_device $SINGLEMDS) $MDS_MOUNT_OPTS ||
21915                 error "Fail to start MDT."
21916
21917         client_up || error "Fail to df."
21918         # Create new files, idle OI blocks should be reused.
21919         createmany -o $myDIR/t- 2000
21920         do_facet $SINGLEMDS sync
21921         # Make sure journal flushed.
21922         sleep 6
21923         local blk2=$(do_facet $SINGLEMDS \
21924                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21925                      grep Blockcount | awk '{print $4}')
21926
21927         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
21928 }
21929 run_test 228b "idle OI blocks can be reused after MDT restart"
21930
21931 #LU-1881
21932 test_228c() {
21933         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21934         remote_mds_nodsh && skip "remote MDS with nodsh"
21935         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
21936
21937         local MDT_DEV=$(mdsdevname ${SINGLEMDS//mds/})
21938         local myDIR=$DIR/$tdir
21939
21940         mkdir -p $myDIR
21941         #define OBD_FAIL_SEQ_EXHAUST             0x1002
21942         $LCTL set_param fail_loc=0x80001002
21943         # 20000 files can guarantee there are index nodes in the OI file
21944         createmany -o $myDIR/t- 20000
21945         $LCTL set_param fail_loc=0
21946         # The guard is current the largest FID holder
21947         touch $myDIR/guard
21948         local SEQ=$($LFS path2fid $myDIR/guard | awk -F ':' '{print $1}' |
21949                     tr -d '[')
21950         local IDX=$(($SEQ % 64))
21951
21952         do_facet $SINGLEMDS sync
21953         # Make sure journal flushed.
21954         sleep 6
21955         local blk1=$(do_facet $SINGLEMDS \
21956                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21957                      grep Blockcount | awk '{print $4}')
21958
21959         # Remove old files, some OI blocks will become idle.
21960         unlinkmany $myDIR/t- 20000
21961         rm -f $myDIR/guard
21962         # The OI file should become empty now
21963
21964         # Create new files, idle OI blocks should be reused.
21965         createmany -o $myDIR/t- 2000
21966         do_facet $SINGLEMDS sync
21967         # Make sure journal flushed.
21968         sleep 6
21969         local blk2=$(do_facet $SINGLEMDS \
21970                      "$DEBUGFS -c -R \\\"stat oi.16.${IDX}\\\" $MDT_DEV" |
21971                      grep Blockcount | awk '{print $4}')
21972
21973         [ $blk1 == $blk2 ] || error "old blk1=$blk1, new blk2=$blk2, unmatched!"
21974 }
21975 run_test 228c "NOT shrink the last entry in OI index node to recycle idle leaf"
21976
21977 test_229() { # LU-2482, LU-3448
21978         [ $PARALLEL == "yes" ] && skip "skip parallel run"
21979         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
21980         [ $MDS1_VERSION -lt $(version_code 2.4.53) ] &&
21981                 skip "No HSM $(lustre_build_version $SINGLEMDS) MDS < 2.4.53"
21982
21983         rm -f $DIR/$tfile
21984
21985         # Create a file with a released layout and stripe count 2.
21986         $MULTIOP $DIR/$tfile H2c ||
21987                 error "failed to create file with released layout"
21988
21989         $LFS getstripe -v $DIR/$tfile
21990
21991         local pattern=$($LFS getstripe -L $DIR/$tfile)
21992         [ X"$pattern" = X"released" ] || error "pattern error ($pattern)"
21993
21994         local stripe_count=$($LFS getstripe -c $DIR/$tfile) ||
21995                 error "getstripe"
21996         [ $stripe_count -eq 2 ] || error "stripe count not 2 ($stripe_count)"
21997         stat $DIR/$tfile || error "failed to stat released file"
21998
21999         chown $RUNAS_ID $DIR/$tfile ||
22000                 error "chown $RUNAS_ID $DIR/$tfile failed"
22001
22002         chgrp $RUNAS_ID $DIR/$tfile ||
22003                 error "chgrp $RUNAS_ID $DIR/$tfile failed"
22004
22005         touch $DIR/$tfile || error "touch $DIR/$tfile failed"
22006         rm $DIR/$tfile || error "failed to remove released file"
22007 }
22008 run_test 229 "getstripe/stat/rm/attr changes work on released files"
22009
22010 test_230a() {
22011         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22012         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22013         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22014                 skip "Need MDS version at least 2.11.52"
22015
22016         local MDTIDX=1
22017
22018         test_mkdir $DIR/$tdir
22019         test_mkdir -i0 -c1 $DIR/$tdir/test_230_local
22020         local mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230_local)
22021         [ $mdt_idx -ne 0 ] &&
22022                 error "create local directory on wrong MDT $mdt_idx"
22023
22024         $LFS mkdir -i $MDTIDX $DIR/$tdir/test_230 ||
22025                         error "create remote directory failed"
22026         local mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230)
22027         [ $mdt_idx -ne $MDTIDX ] &&
22028                 error "create remote directory on wrong MDT $mdt_idx"
22029
22030         createmany -o $DIR/$tdir/test_230/t- 10 ||
22031                 error "create files on remote directory failed"
22032         mdt_idx=$($LFS getstripe -m $DIR/$tdir/test_230/t-0)
22033         [ $mdt_idx -ne $MDTIDX ] && error "create files on wrong MDT $mdt_idx"
22034         rm -r $DIR/$tdir || error "unlink remote directory failed"
22035 }
22036 run_test 230a "Create remote directory and files under the remote directory"
22037
22038 test_230b() {
22039         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22040         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22041         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22042                 skip "Need MDS version at least 2.11.52"
22043
22044         local MDTIDX=1
22045         local mdt_index
22046         local i
22047         local file
22048         local pid
22049         local stripe_count
22050         local migrate_dir=$DIR/$tdir/migrate_dir
22051         local other_dir=$DIR/$tdir/other_dir
22052
22053         test_mkdir $DIR/$tdir
22054         test_mkdir -i0 -c1 $migrate_dir
22055         test_mkdir -i0 -c1 $other_dir
22056         for ((i=0; i<10; i++)); do
22057                 mkdir -p $migrate_dir/dir_${i}
22058                 createmany -o $migrate_dir/dir_${i}/f 10 ||
22059                         error "create files under remote dir failed $i"
22060         done
22061
22062         cp /etc/passwd $migrate_dir/$tfile
22063         cp /etc/passwd $other_dir/$tfile
22064         chattr +SAD $migrate_dir
22065         chattr +SAD $migrate_dir/$tfile
22066
22067         local old_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
22068         local old_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
22069         local old_dir_mode=$(stat -c%f $migrate_dir)
22070         local old_file_mode=$(stat -c%f $migrate_dir/$tfile)
22071
22072         mkdir -p $migrate_dir/dir_default_stripe2
22073         $LFS setstripe -c 2 $migrate_dir/dir_default_stripe2
22074         $LFS setstripe -c 2 $migrate_dir/${tfile}_stripe2
22075
22076         mkdir -p $other_dir
22077         ln $migrate_dir/$tfile $other_dir/luna
22078         ln $migrate_dir/$tfile $migrate_dir/sofia
22079         ln $other_dir/$tfile $migrate_dir/david
22080         ln -s $migrate_dir/$tfile $other_dir/zachary
22081         ln -s $migrate_dir/$tfile $migrate_dir/${tfile}_ln
22082         ln -s $other_dir/$tfile $migrate_dir/${tfile}_ln_other
22083
22084         local len
22085         local lnktgt
22086
22087         # inline symlink
22088         for len in 58 59 60; do
22089                 lnktgt=$(str_repeat 'l' $len)
22090                 touch $migrate_dir/$lnktgt
22091                 ln -s $lnktgt $migrate_dir/${len}char_ln
22092         done
22093
22094         # PATH_MAX
22095         for len in 4094 4095; do
22096                 lnktgt=$(str_repeat 'l' $len)
22097                 ln -s $lnktgt $migrate_dir/${len}char_ln
22098         done
22099
22100         # NAME_MAX
22101         for len in 254 255; do
22102                 touch $migrate_dir/$(str_repeat 'l' $len)
22103         done
22104
22105         $LFS migrate -m $MDTIDX $migrate_dir ||
22106                 error "fails on migrating remote dir to MDT1"
22107
22108         echo "migratate to MDT1, then checking.."
22109         for ((i = 0; i < 10; i++)); do
22110                 for file in $(find $migrate_dir/dir_${i}); do
22111                         mdt_index=$($LFS getstripe -m $file)
22112                         # broken symlink getstripe will fail
22113                         [ $mdt_index -ne $MDTIDX ] && stat -L $file &&
22114                                 error "$file is not on MDT${MDTIDX}"
22115                 done
22116         done
22117
22118         # the multiple link file should still in MDT0
22119         mdt_index=$($LFS getstripe -m $migrate_dir/$tfile)
22120         [ $mdt_index == 0 ] ||
22121                 error "$file is not on MDT${MDTIDX}"
22122
22123         local new_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
22124         [ "$old_dir_flag" = "$new_dir_flag" ] ||
22125                 error " expect $old_dir_flag get $new_dir_flag"
22126
22127         local new_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
22128         [ "$old_file_flag" = "$new_file_flag" ] ||
22129                 error " expect $old_file_flag get $new_file_flag"
22130
22131         local new_dir_mode=$(stat -c%f $migrate_dir)
22132         [ "$old_dir_mode" = "$new_dir_mode" ] ||
22133                 error "expect mode $old_dir_mode get $new_dir_mode"
22134
22135         local new_file_mode=$(stat -c%f $migrate_dir/$tfile)
22136         [ "$old_file_mode" = "$new_file_mode" ] ||
22137                 error "expect mode $old_file_mode get $new_file_mode"
22138
22139         diff /etc/passwd $migrate_dir/$tfile ||
22140                 error "$tfile different after migration"
22141
22142         diff /etc/passwd $other_dir/luna ||
22143                 error "luna different after migration"
22144
22145         diff /etc/passwd $migrate_dir/sofia ||
22146                 error "sofia different after migration"
22147
22148         diff /etc/passwd $migrate_dir/david ||
22149                 error "david different after migration"
22150
22151         diff /etc/passwd $other_dir/zachary ||
22152                 error "zachary different after migration"
22153
22154         diff /etc/passwd $migrate_dir/${tfile}_ln ||
22155                 error "${tfile}_ln different after migration"
22156
22157         diff /etc/passwd $migrate_dir/${tfile}_ln_other ||
22158                 error "${tfile}_ln_other different after migration"
22159
22160         stripe_count=$($LFS getstripe -c $migrate_dir/dir_default_stripe2)
22161         [ $stripe_count = 2 ] ||
22162                 error "dir strpe_count $d != 2 after migration."
22163
22164         stripe_count=$($LFS getstripe -c $migrate_dir/${tfile}_stripe2)
22165         [ $stripe_count = 2 ] ||
22166                 error "file strpe_count $d != 2 after migration."
22167
22168         #migrate back to MDT0
22169         MDTIDX=0
22170
22171         $LFS migrate -m $MDTIDX $migrate_dir ||
22172                 error "fails on migrating remote dir to MDT0"
22173
22174         echo "migrate back to MDT0, checking.."
22175         for file in $(find $migrate_dir); do
22176                 mdt_index=$($LFS getstripe -m $file)
22177                 [ $mdt_index -ne $MDTIDX ] && stat -L $file &&
22178                         error "$file is not on MDT${MDTIDX}"
22179         done
22180
22181         local new_dir_flag=$(lsattr -a $migrate_dir | awk '/\/\.$/ {print $1}')
22182         [ "$old_dir_flag" = "$new_dir_flag" ] ||
22183                 error " expect $old_dir_flag get $new_dir_flag"
22184
22185         local new_file_flag=$(lsattr $migrate_dir/$tfile | awk '{print $1}')
22186         [ "$old_file_flag" = "$new_file_flag" ] ||
22187                 error " expect $old_file_flag get $new_file_flag"
22188
22189         local new_dir_mode=$(stat -c%f $migrate_dir)
22190         [ "$old_dir_mode" = "$new_dir_mode" ] ||
22191                 error "expect mode $old_dir_mode get $new_dir_mode"
22192
22193         local new_file_mode=$(stat -c%f $migrate_dir/$tfile)
22194         [ "$old_file_mode" = "$new_file_mode" ] ||
22195                 error "expect mode $old_file_mode get $new_file_mode"
22196
22197         diff /etc/passwd ${migrate_dir}/$tfile ||
22198                 error "$tfile different after migration"
22199
22200         diff /etc/passwd ${other_dir}/luna ||
22201                 error "luna different after migration"
22202
22203         diff /etc/passwd ${migrate_dir}/sofia ||
22204                 error "sofia different after migration"
22205
22206         diff /etc/passwd ${other_dir}/zachary ||
22207                 error "zachary different after migration"
22208
22209         diff /etc/passwd $migrate_dir/${tfile}_ln ||
22210                 error "${tfile}_ln different after migration"
22211
22212         diff /etc/passwd $migrate_dir/${tfile}_ln_other ||
22213                 error "${tfile}_ln_other different after migration"
22214
22215         stripe_count=$($LFS getstripe -c ${migrate_dir}/dir_default_stripe2)
22216         [ $stripe_count = 2 ] ||
22217                 error "dir strpe_count $d != 2 after migration."
22218
22219         stripe_count=$($LFS getstripe -c ${migrate_dir}/${tfile}_stripe2)
22220         [ $stripe_count = 2 ] ||
22221                 error "file strpe_count $d != 2 after migration."
22222
22223         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22224 }
22225 run_test 230b "migrate directory"
22226
22227 test_230c() {
22228         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22229         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22230         remote_mds_nodsh && skip "remote MDS with nodsh"
22231         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22232                 skip "Need MDS version at least 2.11.52"
22233
22234         local MDTIDX=1
22235         local total=3
22236         local mdt_index
22237         local file
22238         local migrate_dir=$DIR/$tdir/migrate_dir
22239
22240         #If migrating directory fails in the middle, all entries of
22241         #the directory is still accessiable.
22242         test_mkdir $DIR/$tdir
22243         test_mkdir -i0 -c1 $migrate_dir
22244         test_mkdir -i1 -c1 $DIR/$tdir/remote_dir
22245         stat $migrate_dir
22246         createmany -o $migrate_dir/f $total ||
22247                 error "create files under ${migrate_dir} failed"
22248
22249         # fail after migrating top dir, and this will fail only once, so the
22250         # first sub file migration will fail (currently f3), others succeed.
22251         #OBD_FAIL_MIGRATE_ENTRIES       0x1801
22252         do_facet mds1 lctl set_param fail_loc=0x1801
22253         local t=$(ls $migrate_dir | wc -l)
22254         $LFS migrate --mdt-index $MDTIDX $migrate_dir &&
22255                 error "migrate should fail"
22256         local u=$(ls $migrate_dir | wc -l)
22257         [ "$u" == "$t" ] || error "$u != $t during migration"
22258
22259         # add new dir/file should succeed
22260         mkdir $migrate_dir/dir ||
22261                 error "mkdir failed under migrating directory"
22262         touch $migrate_dir/file ||
22263                 error "create file failed under migrating directory"
22264
22265         # add file with existing name should fail
22266         for file in $migrate_dir/f*; do
22267                 stat $file > /dev/null || error "stat $file failed"
22268                 $OPENFILE -f O_CREAT:O_EXCL $file &&
22269                         error "open(O_CREAT|O_EXCL) $file should fail"
22270                 $MULTIOP $file m && error "create $file should fail"
22271                 touch $DIR/$tdir/remote_dir/$tfile ||
22272                         error "touch $tfile failed"
22273                 ln $DIR/$tdir/remote_dir/$tfile $file &&
22274                         error "link $file should fail"
22275                 mdt_index=$($LFS getstripe -m $file)
22276                 if [ $mdt_index == 0 ]; then
22277                         # file failed to migrate is not allowed to rename to
22278                         mv $DIR/$tdir/remote_dir/$tfile $file &&
22279                                 error "rename to $file should fail"
22280                 else
22281                         mv $DIR/$tdir/remote_dir/$tfile $file ||
22282                                 error "rename to $file failed"
22283                 fi
22284                 echo hello >> $file || error "write $file failed"
22285         done
22286
22287         # resume migration with different options should fail
22288         $LFS migrate -m 0 $migrate_dir &&
22289                 error "migrate -m 0 $migrate_dir should fail"
22290
22291         $LFS migrate -m $MDTIDX -c 2 $migrate_dir &&
22292                 error "migrate -c 2 $migrate_dir should fail"
22293
22294         # resume migration should succeed
22295         $LFS migrate -m $MDTIDX $migrate_dir ||
22296                 error "migrate $migrate_dir failed"
22297
22298         echo "Finish migration, then checking.."
22299         for file in $(find $migrate_dir); do
22300                 mdt_index=$($LFS getstripe -m $file)
22301                 [ $mdt_index == $MDTIDX ] ||
22302                         error "$file is not on MDT${MDTIDX}"
22303         done
22304
22305         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22306 }
22307 run_test 230c "check directory accessiblity if migration failed"
22308
22309 test_230d() {
22310         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22311         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22312         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22313                 skip "Need MDS version at least 2.11.52"
22314         # LU-11235
22315         [ "$mds1_FSTYPE" == "zfs" ] && skip "skip ZFS backend"
22316
22317         local migrate_dir=$DIR/$tdir/migrate_dir
22318         local old_index
22319         local new_index
22320         local old_count
22321         local new_count
22322         local new_hash
22323         local mdt_index
22324         local i
22325         local j
22326
22327         old_index=$((RANDOM % MDSCOUNT))
22328         old_count=$((MDSCOUNT - old_index))
22329         new_index=$((RANDOM % MDSCOUNT))
22330         new_count=$((MDSCOUNT - new_index))
22331         new_hash=1 # for all_char
22332
22333         [ $old_count -gt 1 ] && old_count=$((old_count - RANDOM % old_count))
22334         [ $new_count -gt 1 ] && new_count=$((new_count - RANDOM % new_count))
22335
22336         test_mkdir $DIR/$tdir
22337         test_mkdir -i $old_index -c $old_count $migrate_dir
22338
22339         for ((i=0; i<100; i++)); do
22340                 test_mkdir -i0 -c1 $migrate_dir/dir_${i}
22341                 createmany -o $migrate_dir/dir_${i}/f 100 ||
22342                         error "create files under remote dir failed $i"
22343         done
22344
22345         echo -n "Migrate from MDT$old_index "
22346         [ $old_count -gt 1 ] && echo -n "... MDT$((old_index + old_count - 1)) "
22347         echo -n "to MDT$new_index"
22348         [ $new_count -gt 1 ] && echo -n " ... MDT$((new_index + new_count - 1))"
22349         echo
22350
22351         echo "$LFS migrate -m$new_index -c$new_count -H $new_hash $migrate_dir"
22352         $LFS migrate -m $new_index -c $new_count -H $new_hash $migrate_dir ||
22353                 error "migrate remote dir error"
22354
22355         echo "Finish migration, then checking.."
22356         for file in $(find $migrate_dir -maxdepth 1); do
22357                 mdt_index=$($LFS getstripe -m $file)
22358                 if [ $mdt_index -lt $new_index ] ||
22359                    [ $mdt_index -gt $((new_index + new_count - 1)) ]; then
22360                         error "$file is on MDT$mdt_index"
22361                 fi
22362         done
22363
22364         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22365 }
22366 run_test 230d "check migrate big directory"
22367
22368 test_230e() {
22369         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22370         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22371         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22372                 skip "Need MDS version at least 2.11.52"
22373
22374         local i
22375         local j
22376         local a_fid
22377         local b_fid
22378
22379         mkdir_on_mdt0 $DIR/$tdir
22380         mkdir $DIR/$tdir/migrate_dir
22381         mkdir $DIR/$tdir/other_dir
22382         touch $DIR/$tdir/migrate_dir/a
22383         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/b
22384         ls $DIR/$tdir/other_dir
22385
22386         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
22387                 error "migrate dir fails"
22388
22389         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir)
22390         [ $mdt_index == 1 ] || error "migrate_dir is not on MDT1"
22391
22392         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
22393         [ $mdt_index == 0 ] || error "a is not on MDT0"
22394
22395         $LFS migrate -m 1 $DIR/$tdir/other_dir ||
22396                 error "migrate dir fails"
22397
22398         mdt_index=$($LFS getstripe -m $DIR/$tdir/other_dir)
22399         [ $mdt_index == 1 ] || error "other_dir is not on MDT1"
22400
22401         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
22402         [ $mdt_index == 1 ] || error "a is not on MDT1"
22403
22404         mdt_index=$($LFS getstripe -m $DIR/$tdir/other_dir/b)
22405         [ $mdt_index == 1 ] || error "b is not on MDT1"
22406
22407         a_fid=$($LFS path2fid $DIR/$tdir/migrate_dir/a)
22408         b_fid=$($LFS path2fid $DIR/$tdir/other_dir/b)
22409
22410         [ "$a_fid" = "$b_fid" ] || error "different fid after migration"
22411
22412         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22413 }
22414 run_test 230e "migrate mulitple local link files"
22415
22416 test_230f() {
22417         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22418         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22419         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22420                 skip "Need MDS version at least 2.11.52"
22421
22422         local a_fid
22423         local ln_fid
22424
22425         mkdir -p $DIR/$tdir
22426         mkdir $DIR/$tdir/migrate_dir
22427         $LFS mkdir -i1 $DIR/$tdir/other_dir
22428         touch $DIR/$tdir/migrate_dir/a
22429         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln1
22430         ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln2
22431         ls $DIR/$tdir/other_dir
22432
22433         # a should be migrated to MDT1, since no other links on MDT0
22434         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
22435                 error "#1 migrate dir fails"
22436         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir)
22437         [ $mdt_index == 1 ] || error "migrate_dir is not on MDT1"
22438         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
22439         [ $mdt_index == 1 ] || error "a is not on MDT1"
22440
22441         # a should stay on MDT1, because it is a mulitple link file
22442         $LFS migrate -m 0 $DIR/$tdir/migrate_dir ||
22443                 error "#2 migrate dir fails"
22444         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
22445         [ $mdt_index == 1 ] || error "a is not on MDT1"
22446
22447         $LFS migrate -m 1 $DIR/$tdir/migrate_dir ||
22448                 error "#3 migrate dir fails"
22449
22450         a_fid=$($LFS path2fid $DIR/$tdir/migrate_dir/a)
22451         ln_fid=$($LFS path2fid $DIR/$tdir/other_dir/ln1)
22452         [ "$a_fid" = "$ln_fid" ] || error "different fid after migrate to MDT1"
22453
22454         rm -rf $DIR/$tdir/other_dir/ln1 || error "unlink ln1 fails"
22455         rm -rf $DIR/$tdir/other_dir/ln2 || error "unlink ln2 fails"
22456
22457         # a should be migrated to MDT0, since no other links on MDT1
22458         $LFS migrate -m 0 $DIR/$tdir/migrate_dir ||
22459                 error "#4 migrate dir fails"
22460         mdt_index=$($LFS getstripe -m $DIR/$tdir/migrate_dir/a)
22461         [ $mdt_index == 0 ] || error "a is not on MDT0"
22462
22463         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22464 }
22465 run_test 230f "migrate mulitple remote link files"
22466
22467 test_230g() {
22468         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22469         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22470         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22471                 skip "Need MDS version at least 2.11.52"
22472
22473         mkdir -p $DIR/$tdir/migrate_dir
22474
22475         $LFS migrate -m 1000 $DIR/$tdir/migrate_dir &&
22476                 error "migrating dir to non-exist MDT succeeds"
22477         true
22478 }
22479 run_test 230g "migrate dir to non-exist MDT"
22480
22481 test_230h() {
22482         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22483         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22484         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22485                 skip "Need MDS version at least 2.11.52"
22486
22487         local mdt_index
22488
22489         mkdir -p $DIR/$tdir/migrate_dir
22490
22491         $LFS migrate -m1 $DIR &&
22492                 error "migrating mountpoint1 should fail"
22493
22494         $LFS migrate -m1 $DIR/$tdir/.. &&
22495                 error "migrating mountpoint2 should fail"
22496
22497         # same as mv
22498         $LFS migrate -m1 $DIR/$tdir/migrate_dir/.. &&
22499                 error "migrating $tdir/migrate_dir/.. should fail"
22500
22501         true
22502 }
22503 run_test 230h "migrate .. and root"
22504
22505 test_230i() {
22506         [ $PARALLEL == "yes" ] && skip "skip parallel run"
22507         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
22508         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
22509                 skip "Need MDS version at least 2.11.52"
22510
22511         mkdir -p $DIR/$tdir/migrate_dir
22512
22513         $LFS migrate -m 1 $DIR/$tdir/migrate_dir/ ||
22514                 error "migration fails with a tailing slash"
22515
22516         $LFS migrate -m 0 $DIR/$tdir/migrate_dir// ||
22517                 error "migration fails with two tailing slashes"
22518 }
22519 run_test 230i "lfs migrate -m tolerates trailing slashes"
22520
22521 test_230j() {
22522         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
22523         [ $MDS1_VERSION -lt $(version_code 2.13.52) ] &&
22524                 skip "Need MDS version at least 2.11.52"
22525
22526         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $tdir failed"
22527         $LFS setstripe -E 1M -L mdt $DIR/$tdir/$tfile ||
22528                 error "create $tfile failed"
22529         cat /etc/passwd > $DIR/$tdir/$tfile
22530
22531         $LFS migrate -m 1 $DIR/$tdir || error "migrate failed"
22532
22533         cmp /etc/passwd $DIR/$tdir/$tfile ||
22534                 error "DoM file mismatch after migration"
22535 }
22536 run_test 230j "DoM file data not changed after dir migration"
22537
22538 test_230k() {
22539         [ $MDSCOUNT -lt 4 ] && skip "needs >= 4 MDTs"
22540         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
22541                 skip "Need MDS version at least 2.11.56"
22542
22543         local total=20
22544         local files_on_starting_mdt=0
22545
22546         $LFS mkdir -i -1 -c 2 $DIR/$tdir || error "mkdir failed"
22547         $LFS getdirstripe $DIR/$tdir
22548         for i in $(seq $total); do
22549                 echo $((i*i - i)) > $DIR/$tdir/$tfile.$i || error "write failed"
22550                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 0 ]] &&
22551                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
22552         done
22553
22554         echo "$files_on_starting_mdt files on MDT0"
22555
22556         $LFS migrate -m 1,3 $DIR/$tdir || error "migrate -m 1,3 failed"
22557         $LFS getdirstripe $DIR/$tdir
22558
22559         files_on_starting_mdt=0
22560         for i in $(seq $total); do
22561                 $(echo $((i*i - i)) | cmp $DIR/$tdir/$tfile.$i -) ||
22562                         error "file $tfile.$i mismatch after migration"
22563                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 1 ]] &&
22564                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
22565         done
22566
22567         echo "$files_on_starting_mdt files on MDT1 after migration"
22568         [[ $files_on_starting_mdt -eq $total ]] && error "all files on MDT1"
22569
22570         $LFS migrate -m 0 -c 2 $DIR/$tdir || error "migrate -m 0 -c 2 failed"
22571         $LFS getdirstripe $DIR/$tdir
22572
22573         files_on_starting_mdt=0
22574         for i in $(seq $total); do
22575                 $(echo $((i*i - i)) | cmp $DIR/$tdir/$tfile.$i -) ||
22576                         error "file $tfile.$i mismatch after 2nd migration"
22577                 [[ $($LFS getstripe -m $DIR/$tdir/$tfile.$i) -eq 0 ]] &&
22578                         files_on_starting_mdt=$((files_on_starting_mdt + 1))
22579         done
22580
22581         echo "$files_on_starting_mdt files on MDT0 after 2nd migration"
22582         [[ $files_on_starting_mdt -eq $total ]] && error "all files on MDT0"
22583
22584         true
22585 }
22586 run_test 230k "file data not changed after dir migration"
22587
22588 test_230l() {
22589         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
22590         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
22591                 skip "Need MDS version at least 2.11.56"
22592
22593         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir failed"
22594         createmany -o $DIR/$tdir/f___________________________________ 1000 ||
22595                 error "create files under remote dir failed $i"
22596         $LFS migrate -m 1 $DIR/$tdir || error "migrate failed"
22597 }
22598 run_test 230l "readdir between MDTs won't crash"
22599
22600 test_230m() {
22601         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
22602         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
22603                 skip "Need MDS version at least 2.11.56"
22604
22605         local MDTIDX=1
22606         local mig_dir=$DIR/$tdir/migrate_dir
22607         local longstr="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
22608         local shortstr="b"
22609         local val
22610
22611         echo "Creating files and dirs with xattrs"
22612         test_mkdir $DIR/$tdir
22613         test_mkdir -i0 -c1 $mig_dir
22614         mkdir $mig_dir/dir
22615         setfattr -n user.attr1 -v $longstr $mig_dir/dir ||
22616                 error "cannot set xattr attr1 on dir"
22617         setfattr -n user.attr2 -v $shortstr $mig_dir/dir ||
22618                 error "cannot set xattr attr2 on dir"
22619         touch $mig_dir/dir/f0
22620         setfattr -n user.attr1 -v $longstr $mig_dir/dir/f0 ||
22621                 error "cannot set xattr attr1 on file"
22622         setfattr -n user.attr2 -v $shortstr $mig_dir/dir/f0 ||
22623                 error "cannot set xattr attr2 on file"
22624         sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
22625         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir 2>/dev/null)
22626         [ "$val" = $longstr ] || error "xattr attr1 not set properly on dir"
22627         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir 2>/dev/null)
22628         [ "$val" = $shortstr ] || error "xattr attr2 not set properly on dir"
22629         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir/f0 2>/dev/null)
22630         [ "$val" = $longstr ] || error "xattr attr1 not set properly on file"
22631         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir/f0 2>/dev/null)
22632         [ "$val" = $shortstr ] || error "xattr attr2 not set properly on file"
22633
22634         echo "Migrating to MDT1"
22635         $LFS migrate -m $MDTIDX $mig_dir ||
22636                 error "fails on migrating dir to MDT1"
22637
22638         sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
22639         echo "Checking xattrs"
22640         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir 2>/dev/null)
22641         [ "$val" = $longstr ] ||
22642                 error "expecting xattr1 $longstr on dir, found $val"
22643         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir 2>/dev/null)
22644         [ "$val" = $shortstr ] ||
22645                 error "expecting xattr2 $shortstr on dir, found $val"
22646         val=$(getfattr --only-values -n user.attr1 $mig_dir/dir/f0 2>/dev/null)
22647         [ "$val" = $longstr ] ||
22648                 error "expecting xattr1 $longstr on file, found $val"
22649         val=$(getfattr --only-values -n user.attr2 $mig_dir/dir/f0 2>/dev/null)
22650         [ "$val" = $shortstr ] ||
22651                 error "expecting xattr2 $shortstr on file, found $val"
22652 }
22653 run_test 230m "xattrs not changed after dir migration"
22654
22655 test_230n() {
22656         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
22657         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
22658                 skip "Need MDS version at least 2.13.53"
22659
22660         $LFS mkdir -i 0 $DIR/$tdir || error "mkdir $tdir failed"
22661         cat /etc/hosts > $DIR/$tdir/$tfile
22662         $LFS mirror extend -N1 $DIR/$tdir/$tfile || error "Mirroring failed"
22663         $LFS migrate -m 1 $DIR/$tdir || error "Migration failed"
22664
22665         cmp /etc/hosts $DIR/$tdir/$tfile ||
22666                 error "File data mismatch after migration"
22667 }
22668 run_test 230n "Dir migration with mirrored file"
22669
22670 test_230o() {
22671         [ $MDSCOUNT -ge 2 ] || skip "needs >= 2 MDTs"
22672         [ $MDS1_VERSION -ge $(version_code 2.13.52) ] ||
22673                 skip "Need MDS version at least 2.13.52"
22674
22675         local mdts=$(comma_list $(mdts_nodes))
22676         local timeout=100
22677         local restripe_status
22678         local delta
22679         local i
22680
22681         [[ $mds1_FSTYPE == zfs ]] && timeout=300
22682
22683         # in case "crush" hash type is not set
22684         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
22685
22686         restripe_status=$(do_facet mds1 $LCTL get_param -n \
22687                            mdt.*MDT0000.enable_dir_restripe)
22688         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
22689         stack_trap "do_nodes $mdts $LCTL set_param \
22690                     mdt.*.enable_dir_restripe=$restripe_status"
22691
22692         mkdir $DIR/$tdir
22693         createmany -m $DIR/$tdir/f 100 ||
22694                 error "create files under remote dir failed $i"
22695         createmany -d $DIR/$tdir/d 100 ||
22696                 error "create dirs under remote dir failed $i"
22697
22698         for i in $(seq 2 $MDSCOUNT); do
22699                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
22700                 $LFS setdirstripe -c $i $DIR/$tdir ||
22701                         error "split -c $i $tdir failed"
22702                 wait_update $HOSTNAME \
22703                         "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
22704                         error "dir split not finished"
22705                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
22706                         awk '/migrate/ {sum += $2} END { print sum }')
22707                 echo "$delta migrated when dir split $((i - 1)) to $i stripes"
22708                 # delta is around total_files/stripe_count
22709                 (( $delta < 200 / (i - 1) + 4 )) ||
22710                         error "$delta files migrated >= $((200 / (i - 1) + 4))"
22711         done
22712 }
22713 run_test 230o "dir split"
22714
22715 test_230p() {
22716         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
22717         (( MDS1_VERSION >= $(version_code 2.13.52) )) ||
22718                 skip "Need MDS version at least 2.13.52"
22719
22720         local mdts=$(comma_list $(mdts_nodes))
22721         local timeout=100
22722         local restripe_status
22723         local delta
22724         local c
22725
22726         [[ $mds1_FSTYPE == zfs ]] && timeout=300
22727
22728         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
22729
22730         restripe_status=$(do_facet mds1 $LCTL get_param -n \
22731                            mdt.*MDT0000.enable_dir_restripe)
22732         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
22733         stack_trap "do_nodes $mdts $LCTL set_param \
22734                     mdt.*.enable_dir_restripe=$restripe_status"
22735
22736         test_mkdir -c $MDSCOUNT -H crush $DIR/$tdir
22737         createmany -m $DIR/$tdir/f 100 ||
22738                 error "create files under remote dir failed"
22739         createmany -d $DIR/$tdir/d 100 ||
22740                 error "create dirs under remote dir failed"
22741
22742         for c in $(seq $((MDSCOUNT - 1)) -1 1); do
22743                 local mdt_hash="crush"
22744
22745                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
22746                 $LFS setdirstripe -c $c $DIR/$tdir ||
22747                         error "split -c $c $tdir failed"
22748                 if (( MDS1_VERSION >= $(version_code 2.14.51) )); then
22749                         mdt_hash="$mdt_hash,fixed"
22750                 elif [ $c -eq 1 ]; then
22751                         mdt_hash="none"
22752                 fi
22753                 wait_update $HOSTNAME \
22754                         "$LFS getdirstripe -H $DIR/$tdir" $mdt_hash $timeout ||
22755                         error "dir merge not finished"
22756                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
22757                         awk '/migrate/ {sum += $2} END { print sum }')
22758                 echo "$delta migrated when dir merge $((c + 1)) to $c stripes"
22759                 # delta is around total_files/stripe_count
22760                 (( delta < 200 / c + 4 )) ||
22761                         error "$delta files migrated >= $((200 / c + 4))"
22762         done
22763 }
22764 run_test 230p "dir merge"
22765
22766 test_230q() {
22767         (( MDSCOUNT > 1)) || skip "needs >= 2 MDTs"
22768         (( MDS1_VERSION >= $(version_code 2.13.52) )) ||
22769                 skip "Need MDS version at least 2.13.52"
22770
22771         local mdts=$(comma_list $(mdts_nodes))
22772         local saved_threshold=$(do_facet mds1 \
22773                         $LCTL get_param -n mdt.*-MDT0000.dir_split_count)
22774         local saved_delta=$(do_facet mds1 \
22775                         $LCTL get_param -n mdt.*-MDT0000.dir_split_delta)
22776         local threshold=100
22777         local delta=2
22778         local total=0
22779         local stripe_count=0
22780         local stripe_index
22781         local nr_files
22782         local create
22783
22784         # test with fewer files on ZFS
22785         [ "$mds1_FSTYPE" == "zfs" ] && threshold=40
22786
22787         stack_trap "do_nodes $mdts $LCTL set_param \
22788                     mdt.*.dir_split_count=$saved_threshold"
22789         stack_trap "do_nodes $mdts $LCTL set_param \
22790                     mdt.*.dir_split_delta=$saved_delta"
22791         stack_trap "do_nodes $mdts $LCTL set_param mdt.*.dir_restripe_nsonly=1"
22792         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_auto_split=1"
22793         do_nodes $mdts "$LCTL set_param mdt.*.dir_split_count=$threshold"
22794         do_nodes $mdts "$LCTL set_param mdt.*.dir_split_delta=$delta"
22795         do_nodes $mdts "$LCTL set_param mdt.*.dir_restripe_nsonly=0"
22796         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
22797
22798         $LFS mkdir -i -1 -c 1 $DIR/$tdir || error "mkdir $tdir failed"
22799         stripe_index=$($LFS getdirstripe -i $DIR/$tdir)
22800
22801         create=$((threshold * 3 / 2))
22802         while [ $stripe_count -lt $MDSCOUNT ]; do
22803                 createmany -m $DIR/$tdir/f $total $create ||
22804                         error "create sub files failed"
22805                 stat $DIR/$tdir > /dev/null
22806                 total=$((total + create))
22807                 stripe_count=$((stripe_count + delta))
22808                 [ $stripe_count -gt $MDSCOUNT ] && stripe_count=$MDSCOUNT
22809
22810                 wait_update $HOSTNAME \
22811                         "$LFS getdirstripe -c $DIR/$tdir" "$stripe_count" 40 ||
22812                         error "stripe count $($LFS getdirstripe -c $DIR/$tdir) != $stripe_count"
22813
22814                 wait_update $HOSTNAME \
22815                         "$LFS getdirstripe -H $DIR/$tdir" "crush" 200 ||
22816                         error "stripe hash $($LFS getdirstripe -H $DIR/$tdir) != crush"
22817
22818                 nr_files=$($LFS find -m 1 $DIR/$tdir | grep -c -w $stripe_index)
22819                 echo "$nr_files/$total files on MDT$stripe_index after split"
22820                 # allow 10% margin of imbalance with crush hash
22821                 (( $nr_files <= $total / $stripe_count + $create / 10)) ||
22822                         error "$nr_files files on MDT$stripe_index after split"
22823
22824                 nr_files=$($LFS find -type f $DIR/$tdir | wc -l)
22825                 [ $nr_files -eq $total ] ||
22826                         error "total sub files $nr_files != $total"
22827         done
22828
22829         (( MDS1_VERSION >= $(version_code 2.14.51) )) || return 0
22830
22831         echo "fixed layout directory won't auto split"
22832         $LFS migrate -m 0 $DIR/$tdir || error "migrate $tdir failed"
22833         wait_update $HOSTNAME "$LFS getdirstripe -H $DIR/$tdir" "crush,fixed" \
22834                 10 || error "stripe hash $($LFS getdirstripe -H $DIR/$tdir)"
22835         wait_update $HOSTNAME "$LFS getdirstripe -c $DIR/$tdir" 1 10 ||
22836                 error "stripe count $($LFS getdirstripe -c $DIR/$tdir)"
22837 }
22838 run_test 230q "dir auto split"
22839
22840 test_230r() {
22841         [[ $PARALLEL != "yes" ]] || skip "skip parallel run"
22842         [[ $MDSCOUNT -ge 2 ]] || skip_env "needs >= 2 MDTs"
22843         [[ $MDS1_VERSION -ge $(version_code 2.13.54) ]] ||
22844                 skip "Need MDS version at least 2.13.54"
22845
22846         # maximum amount of local locks:
22847         # parent striped dir - 2 locks
22848         # new stripe in parent to migrate to - 1 lock
22849         # source and target - 2 locks
22850         # Total 5 locks for regular file
22851         mkdir -p $DIR/$tdir
22852         $LFS mkdir -i1 -c2 $DIR/$tdir/dir1
22853         touch $DIR/$tdir/dir1/eee
22854
22855         # create 4 hardlink for 4 more locks
22856         # Total: 9 locks > RS_MAX_LOCKS (8)
22857         $LFS mkdir -i1 -c1 $DIR/$tdir/dir2
22858         $LFS mkdir -i1 -c1 $DIR/$tdir/dir3
22859         $LFS mkdir -i1 -c1 $DIR/$tdir/dir4
22860         $LFS mkdir -i1 -c1 $DIR/$tdir/dir5
22861         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir2/eee
22862         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir3/eee
22863         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir4/eee
22864         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir5/eee
22865
22866         cancel_lru_locks mdc
22867
22868         $LFS migrate -m1 -c1 $DIR/$tdir/dir1 ||
22869                 error "migrate dir fails"
22870
22871         rm -rf $DIR/$tdir || error "rm dir failed after migration"
22872 }
22873 run_test 230r "migrate with too many local locks"
22874
22875 test_230s() {
22876         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
22877                 skip "Need MDS version at least 2.14.52"
22878
22879         local mdts=$(comma_list $(mdts_nodes))
22880         local restripe_status=$(do_facet mds1 $LCTL get_param -n \
22881                                 mdt.*MDT0000.enable_dir_restripe)
22882
22883         stack_trap "do_nodes $mdts $LCTL set_param \
22884                     mdt.*.enable_dir_restripe=$restripe_status"
22885
22886         local st
22887         for st in 0 1; do
22888                 do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=$st"
22889                 test_mkdir $DIR/$tdir
22890                 $LFS mkdir $DIR/$tdir |& grep "File exists" ||
22891                         error "$LFS mkdir should return EEXIST if target exists"
22892                 rmdir $DIR/$tdir
22893         done
22894 }
22895 run_test 230s "lfs mkdir should return -EEXIST if target exists"
22896
22897 test_230t()
22898 {
22899         (( $MDSCOUNT >= 2 )) || skip_env "needs >= 2 MDTs"
22900         (( $MDS1_VERSION >= $(version_code 2.14.50) )) ||
22901                 skip "Need MDS version at least 2.14.50"
22902
22903         test_mkdir $DIR/$tdir || error "mkdir $tdir failed"
22904         test_mkdir $DIR/$tdir/subdir || error "mkdir subdir failed"
22905         $LFS project -p 1 -s $DIR/$tdir ||
22906                 error "set $tdir project id failed"
22907         $LFS project -p 2 -s $DIR/$tdir/subdir ||
22908                 error "set subdir project id failed"
22909         local pbefore="$($LFS project -d $DIR/$tdir)"
22910         local sbefore="$($LFS project -d $DIR/$tdir/subdir)"
22911         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir || error "migrate failed"
22912
22913         local pafter="$($LFS project -d $DIR/$tdir)"
22914         local safter="$($LFS project -d $DIR/$tdir/subdir)"
22915         [[ "$pbefore" == "$pafter" ]] || error "projid '$pbefore' != '$pafter'"
22916         [[ "$sbefore" == "$safter" ]] || error "projid '$sbefore' != '$safter'"
22917
22918         (( $MDS1_VERSION >= $(version_code 2.15.59.107) )) ||
22919                 { echo "Need MDS >= 2.15.59.107 for projid rename"; return 0; }
22920
22921         # check rename works, even if source parent projid differs (LU-17016)
22922         test_mkdir $DIR/$tdir.2 || error "mkdir $tdir.2 failed"
22923         local fid_before=$($LFS path2fid $DIR/$tdir/subdir)
22924
22925         $LFS project -p 2 -s $DIR/$tdir.2 || error "set $tdir.2 projid failed"
22926         mrename $DIR/$tdir/subdir $DIR/$tdir.2/subdir ||
22927                 error "subdir failed rename for different source parent projid"
22928         local fid_after=$($LFS path2fid $DIR/$tdir.2/subdir)
22929
22930         [[ "$fid_before" == "$fid_after" ]] ||
22931                 error "fid before '$fid_before' != after '$fid_after'"
22932 }
22933 run_test 230t "migrate directory with project ID set"
22934
22935 test_230u()
22936 {
22937         (( MDSCOUNT > 3 )) || skip_env "needs >= 4 MDTs"
22938         (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
22939                 skip "Need MDS version at least 2.14.53"
22940
22941         local count
22942
22943         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
22944         mkdir $DIR/$tdir/sub{0..99} || error "mkdir sub failed"
22945         $LFS migrate -m -1 $DIR/$tdir/sub{0..99} || error "migrate sub failed"
22946         for i in $(seq 0 $((MDSCOUNT - 1))); do
22947                 count=$($LFS getstripe -m $DIR/$tdir/sub* | grep -c ^$i)
22948                 echo "$count dirs migrated to MDT$i"
22949         done
22950         count=$($LFS getstripe -m $DIR/$tdir/sub* | sort -u | wc -l)
22951         (( count >= MDSCOUNT - 1 )) || error "dirs migrated to $count MDTs"
22952 }
22953 run_test 230u "migrate directory by QOS"
22954
22955 test_230v()
22956 {
22957         (( MDSCOUNT > 3 )) || skip_env "needs >= 4 MDTs"
22958         (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
22959                 skip "Need MDS version at least 2.14.53"
22960
22961         local count
22962
22963         mkdir $DIR/$tdir || error "mkdir $tdir failed"
22964         mkdir $DIR/$tdir/sub{0..99} || error "mkdir sub failed"
22965         $LFS migrate -m 0,2,1 $DIR/$tdir || error "migrate $tdir failed"
22966         for i in $(seq 0 $((MDSCOUNT - 1))); do
22967                 count=$($LFS getstripe -m $DIR/$tdir/sub* | grep -c ^$i)
22968                 echo "$count subdirs migrated to MDT$i"
22969                 (( i == 3 )) && (( count > 0 )) &&
22970                         error "subdir shouldn't be migrated to MDT3"
22971         done
22972         count=$($LFS getstripe -m $DIR/$tdir/sub* | sort -u | wc -l)
22973         (( count == 3 )) || error "dirs migrated to $count MDTs"
22974 }
22975 run_test 230v "subdir migrated to the MDT where its parent is located"
22976
22977 test_230w() {
22978         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
22979         (( MDS1_VERSION >= $(version_code 2.15.0) )) ||
22980                 skip "Need MDS version at least 2.15.0"
22981
22982         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
22983         createmany -o $DIR/$tdir/f 10 || error "create files failed"
22984         createmany -d $DIR/$tdir/d 10 || error "create dirs failed"
22985
22986         $LFS migrate -m 1 -c $MDSCOUNT -d $DIR/$tdir ||
22987                 error "migrate failed"
22988
22989         (( $($LFS getdirstripe -c $DIR/$tdir) == MDSCOUNT )) ||
22990                 error "$tdir stripe count mismatch"
22991
22992         for i in $(seq 0 9); do
22993                 (( $($LFS getdirstripe -c $DIR/$tdir/d$i) == 0 )) ||
22994                         error "d$i is striped"
22995         done
22996 }
22997 run_test 230w "non-recursive mode dir migration"
22998
22999 test_230x() {
23000         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
23001         (( MDS1_VERSION >= $(version_code 2.15.0) )) ||
23002                 skip "Need MDS version at least 2.15.0"
23003
23004         mkdir -p $DIR/$tdir || error "mkdir failed"
23005         createmany -d $DIR/$tdir/sub 100 || error "createmany failed"
23006
23007         local mdt_name=$(mdtname_from_index 0)
23008         local low=$(do_facet mds2 $LCTL get_param -n \
23009                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low)
23010         local high=$(do_facet mds2 $LCTL get_param -n \
23011                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high)
23012         local ffree=$($LFS df -i $MOUNT | awk "/$mdt_name/ { print \$4 }")
23013         local maxage=$(do_facet mds2 $LCTL get_param -n \
23014                 osp.*$mdt_name-osp-MDT0001.maxage)
23015
23016         stack_trap "do_facet mds2 $LCTL set_param -n \
23017                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$low \
23018                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high=$high" EXIT
23019         stack_trap "do_facet mds2 $LCTL set_param -n \
23020                 osp.*$mdt_name-osp-MDT0001.maxage=$maxage" EXIT
23021
23022         do_facet mds2 $LCTL set_param -n \
23023                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$((ffree + 1))
23024         do_facet mds2 $LCTL set_param -n osp.*$mdt_name-osp-MDT0001.maxage=1
23025         sleep 4
23026         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir &&
23027                 error "migrate $tdir should fail"
23028
23029         do_facet mds2 $LCTL set_param -n \
23030                 osp.*$mdt_name-osp-MDT0001.reserved_ino_low=$low
23031         do_facet mds2 $LCTL set_param -n \
23032                 osp.*$mdt_name-osp-MDT0001.reserved_ino_high=$high
23033         sleep 4
23034         $LFS migrate -m 1 -c $MDSCOUNT $DIR/$tdir ||
23035                 error "migrate failed"
23036         (( $($LFS getdirstripe -c $DIR/$tdir) == $MDSCOUNT )) ||
23037                 error "$tdir stripe count mismatch"
23038 }
23039 run_test 230x "dir migration check space"
23040
23041 test_230y() {
23042         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
23043         (( MDS1_VERSION >= $(version_code 2.15.55.45) )) ||
23044                 skip "Need MDS version at least 2.15.55.45"
23045
23046         local pid
23047
23048         test_mkdir -c -1 $DIR/$tdir || error "mkdir $tdir failed"
23049         $LFS getdirstripe $DIR/$tdir
23050         createmany -d $DIR/$tdir/d 100 || error "createmany failed"
23051         $LFS migrate -m 1 -c 2 $DIR/$tdir &
23052         pid=$!
23053         sleep 1
23054
23055         #OBD_FAIL_MIGRATE_BAD_HASH      0x1802
23056         do_facet mds2 lctl set_param fail_loc=0x1802
23057
23058         wait $pid
23059         do_facet mds2 lctl set_param fail_loc=0
23060         $LFS getdirstripe $DIR/$tdir
23061         unlinkmany -d $DIR/$tdir/d 100 || error "unlinkmany failed"
23062         rmdir $DIR/$tdir || error "rmdir $tdir failed"
23063 }
23064 run_test 230y "unlink dir with bad hash type"
23065
23066 test_230z() {
23067         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
23068         (( MDS1_VERSION >= $(version_code 2.15.55.45) )) ||
23069                 skip "Need MDS version at least 2.15.55.45"
23070
23071         local pid
23072
23073         test_mkdir -c -1 $DIR/$tdir || error "mkdir $tdir failed"
23074         $LFS getdirstripe $DIR/$tdir
23075         createmany -d $DIR/$tdir/d 100 || error "createmany failed"
23076         $LFS migrate -m 1 -c 2 -H fnv_1a_64 $DIR/$tdir &
23077         pid=$!
23078         sleep 1
23079
23080         #OBD_FAIL_MIGRATE_BAD_HASH      0x1802
23081         do_facet mds2 lctl set_param fail_loc=0x1802
23082
23083         wait $pid
23084         do_facet mds2 lctl set_param fail_loc=0
23085         $LFS getdirstripe $DIR/$tdir
23086
23087         # resume migration
23088         $LFS migrate -m 1 -c 2 -H fnv_1a_64 $DIR/$tdir ||
23089                 error "resume migration failed"
23090         $LFS getdirstripe $DIR/$tdir
23091         [ $($LFS getdirstripe -H $DIR/$tdir) == "fnv_1a_64,fixed" ] ||
23092                 error "migration is not finished"
23093 }
23094 run_test 230z "resume dir migration with bad hash type"
23095
23096 test_231a()
23097 {
23098         # For simplicity this test assumes that max_pages_per_rpc
23099         # is the same across all OSCs
23100         local max_pages=$($LCTL get_param -n osc.*.max_pages_per_rpc | head -n1)
23101         local bulk_size=$((max_pages * PAGE_SIZE))
23102         local brw_size=$(do_facet ost1 $LCTL get_param -n obdfilter.*.brw_size |
23103                                        head -n 1)
23104
23105         mkdir -p $DIR/$tdir
23106         $LFS setstripe -S ${brw_size}M $DIR/$tdir ||
23107                 error "failed to set stripe with -S ${brw_size}M option"
23108         stack_trap "rm -rf $DIR/$tdir"
23109
23110         # clear the OSC stats
23111         $LCTL set_param osc.*.stats=0 &>/dev/null
23112         stop_writeback
23113
23114         # Client writes $bulk_size - there must be 1 rpc for $max_pages.
23115         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=$bulk_size count=1 \
23116                 oflag=direct &>/dev/null || error "dd failed"
23117
23118         sync; sleep 1; sync # just to be safe
23119         local nrpcs=$($LCTL get_param osc.*.stats |awk '/ost_write/ {print $2}')
23120         if [ x$nrpcs != "x1" ]; then
23121                 $LCTL get_param osc.*.stats
23122                 error "found $nrpcs ost_write RPCs, not 1 as expected"
23123         fi
23124
23125         start_writeback
23126         # Drop the OSC cache, otherwise we will read from it
23127         cancel_lru_locks osc
23128
23129         # clear the OSC stats
23130         $LCTL set_param osc.*.stats=0 &>/dev/null
23131
23132         # Client reads $bulk_size.
23133         dd if=$DIR/$tdir/$tfile of=/dev/null bs=$bulk_size count=1 \
23134                 iflag=direct &>/dev/null || error "dd failed"
23135
23136         nrpcs=$($LCTL get_param osc.*.stats | awk '/ost_read/ { print $2 }')
23137         if [ x$nrpcs != "x1" ]; then
23138                 $LCTL get_param osc.*.stats
23139                 error "found $nrpcs ost_read RPCs, not 1 as expected"
23140         fi
23141 }
23142 run_test 231a "checking that reading/writing of BRW RPC size results in one RPC"
23143
23144 test_231b() {
23145         mkdir -p $DIR/$tdir
23146         stack_trap "rm -rf $DIR/$tdir"
23147         local i
23148         for i in {0..1023}; do
23149                 dd if=/dev/zero of=$DIR/$tdir/$tfile conv=notrunc \
23150                         seek=$((2 * i)) bs=4096 count=1 &>/dev/null ||
23151                         error "dd of=$DIR/$tdir/$tfile seek=$((2 * i)) failed"
23152         done
23153         sync
23154 }
23155 run_test 231b "must not assert on fully utilized OST request buffer"
23156
23157 test_232a() {
23158         mkdir -p $DIR/$tdir
23159         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
23160
23161         #define OBD_FAIL_LDLM_OST_LVB            0x31c
23162         do_facet ost1 $LCTL set_param fail_loc=0x31c
23163
23164         # ignore dd failure
23165         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 || true
23166         stack_trap "rm -f $DIR/$tdir/$tfile"
23167
23168         do_facet ost1 $LCTL set_param fail_loc=0
23169         umount_client $MOUNT || error "umount failed"
23170         mount_client $MOUNT || error "mount failed"
23171         stop ost1 || error "cannot stop ost1"
23172         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
23173 }
23174 run_test 232a "failed lock should not block umount"
23175
23176 test_232b() {
23177         [ $MDS1_VERSION -ge $(version_code 2.10.58) ] ||
23178                 skip "Need MDS version at least 2.10.58"
23179
23180         mkdir -p $DIR/$tdir
23181         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
23182         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1
23183         stack_trap "rm -f $DIR/$tdir/$tfile"
23184         sync
23185         cancel_lru_locks osc
23186
23187         #define OBD_FAIL_LDLM_OST_LVB            0x31c
23188         do_facet ost1 $LCTL set_param fail_loc=0x31c
23189
23190         # ignore failure
23191         $LFS data_version $DIR/$tdir/$tfile || true
23192
23193         do_facet ost1 $LCTL set_param fail_loc=0
23194         umount_client $MOUNT || error "umount failed"
23195         mount_client $MOUNT || error "mount failed"
23196         stop ost1 || error "cannot stop ost1"
23197         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
23198 }
23199 run_test 232b "failed data version lock should not block umount"
23200
23201 test_233a() {
23202         [ $MDS1_VERSION -ge $(version_code 2.3.64) ] ||
23203                 skip "Need MDS version at least 2.3.64"
23204         [ -n "$FILESET" ] && skip_env "SKIP due to FILESET set"
23205
23206         local fid=$($LFS path2fid $MOUNT)
23207
23208         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
23209                 error "cannot access $MOUNT using its FID '$fid'"
23210 }
23211 run_test 233a "checking that OBF of the FS root succeeds"
23212
23213 test_233b() {
23214         [ $MDS1_VERSION -ge $(version_code 2.5.90) ] ||
23215                 skip "Need MDS version at least 2.5.90"
23216         [ -n "$FILESET" ] && skip_env "SKIP due to FILESET set"
23217
23218         local fid=$($LFS path2fid $MOUNT/.lustre)
23219
23220         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
23221                 error "cannot access $MOUNT/.lustre using its FID '$fid'"
23222
23223         fid=$($LFS path2fid $MOUNT/.lustre/fid)
23224         stat $MOUNT/.lustre/fid/$fid > /dev/null ||
23225                 error "cannot access $MOUNT/.lustre/fid using its FID '$fid'"
23226 }
23227 run_test 233b "checking that OBF of the FS .lustre succeeds"
23228
23229 test_234() {
23230         local p="$TMP/sanityN-$TESTNAME.parameters"
23231         save_lustre_params client "llite.*.xattr_cache" > $p
23232         lctl set_param llite.*.xattr_cache 1 ||
23233                 skip_env "xattr cache is not supported"
23234
23235         mkdir -p $DIR/$tdir || error "mkdir failed"
23236         touch $DIR/$tdir/$tfile || error "touch failed"
23237         # OBD_FAIL_LLITE_XATTR_ENOMEM
23238         $LCTL set_param fail_loc=0x1405
23239         getfattr -n user.attr $DIR/$tdir/$tfile &&
23240                 error "getfattr should have failed with ENOMEM"
23241         $LCTL set_param fail_loc=0x0
23242         rm -rf $DIR/$tdir
23243
23244         restore_lustre_params < $p
23245         rm -f $p
23246 }
23247 run_test 234 "xattr cache should not crash on ENOMEM"
23248
23249 test_235() {
23250         [ $MDS1_VERSION -lt $(version_code 2.4.52) ] &&
23251                 skip "Need MDS version at least 2.4.52"
23252
23253         flock_deadlock $DIR/$tfile
23254         local RC=$?
23255         case $RC in
23256                 0)
23257                 ;;
23258                 124) error "process hangs on a deadlock"
23259                 ;;
23260                 *) error "error executing flock_deadlock $DIR/$tfile"
23261                 ;;
23262         esac
23263 }
23264 run_test 235 "LU-1715: flock deadlock detection does not work properly"
23265
23266 #LU-2935
23267 test_236() {
23268         check_swap_layouts_support
23269
23270         local ref1=/etc/passwd
23271         local ref2=/etc/group
23272         local file1=$DIR/$tdir/f1
23273         local file2=$DIR/$tdir/f2
23274
23275         test_mkdir -c1 $DIR/$tdir
23276         $LFS setstripe -c 1 $file1 || error "cannot setstripe on '$file1': rc = $?"
23277         cp $ref1 $file1 || error "cp $ref1 $file1 failed: rc = $?"
23278         $LFS setstripe -c 2 $file2 || error "cannot setstripe on '$file2': rc = $?"
23279         cp $ref2 $file2 || error "cp $ref2 $file2 failed: rc = $?"
23280         local fd=$(free_fd)
23281         local cmd="exec $fd<>$file2"
23282         eval $cmd
23283         rm $file2
23284         $LFS swap_layouts $file1 /proc/self/fd/${fd} ||
23285                 error "cannot swap layouts of '$file1' and /proc/self/fd/${fd}"
23286         cmd="exec $fd>&-"
23287         eval $cmd
23288         cmp $ref2 $file1 || error "content compare failed ($ref2 != $file1)"
23289
23290         #cleanup
23291         rm -rf $DIR/$tdir
23292 }
23293 run_test 236 "Layout swap on open unlinked file"
23294
23295 # LU-4659 linkea consistency
23296 test_238() {
23297         [[ $MDS1_VERSION -gt $(version_code 2.5.57) ]] ||
23298                 [[ $MDS1_VERSION -gt $(version_code 2.5.1) &&
23299                    $MDS1_VERSION -lt $(version_code 2.5.50) ]] ||
23300                 skip "Need MDS version at least 2.5.58 or 2.5.2+"
23301
23302         touch $DIR/$tfile
23303         ln $DIR/$tfile $DIR/$tfile.lnk
23304         touch $DIR/$tfile.new
23305         mv $DIR/$tfile.new $DIR/$tfile
23306         local fid1=$($LFS path2fid $DIR/$tfile)
23307         local fid2=$($LFS path2fid $DIR/$tfile.lnk)
23308         local path1=$($LFS fid2path $FSNAME "$fid1")
23309         [ $tfile == $path1 ] || error "linkea inconsistent: $tfile $fid1 $path1"
23310         local path2=$($LFS fid2path $FSNAME "$fid2")
23311         [ $tfile.lnk == $path2 ] ||
23312                 error "linkea inconsistent: $tfile.lnk $fid2 $path2!"
23313         rm -f $DIR/$tfile*
23314 }
23315 run_test 238 "Verify linkea consistency"
23316
23317 test_239A() { # was test_239
23318         [ $MDS1_VERSION -lt $(version_code 2.5.60) ] &&
23319                 skip "Need MDS version at least 2.5.60"
23320
23321         local list=$(comma_list $(mdts_nodes))
23322
23323         mkdir -p $DIR/$tdir
23324         createmany -o $DIR/$tdir/f- 5000
23325         unlinkmany $DIR/$tdir/f- 5000
23326         [ $MDS1_VERSION -gt $(version_code 2.10.4) ] &&
23327                 do_nodes $list "lctl set_param -n osp.*.force_sync=1"
23328         changes=$(do_nodes $list "lctl get_param -n osp.*MDT*.sync_changes \
23329                         osp.*MDT*.sync_in_flight" | calc_sum)
23330         [ "$changes" -eq 0 ] || error "$changes not synced"
23331 }
23332 run_test 239A "osp_sync test"
23333
23334 test_239a() { #LU-5297
23335         remote_mds_nodsh && skip "remote MDS with nodsh"
23336
23337         touch $DIR/$tfile
23338         #define OBD_FAIL_OSP_CHECK_INVALID_REC     0x2100
23339         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2100
23340         chgrp $RUNAS_GID $DIR/$tfile
23341         wait_delete_completed
23342 }
23343 run_test 239a "process invalid osp sync record correctly"
23344
23345 test_239b() { #LU-5297
23346         remote_mds_nodsh && skip "remote MDS with nodsh"
23347
23348         touch $DIR/$tfile1
23349         #define OBD_FAIL_OSP_CHECK_ENOMEM     0x2101
23350         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2101
23351         chgrp $RUNAS_GID $DIR/$tfile1
23352         wait_delete_completed
23353         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
23354         touch $DIR/$tfile2
23355         chgrp $RUNAS_GID $DIR/$tfile2
23356         wait_delete_completed
23357 }
23358 run_test 239b "process osp sync record with ENOMEM error correctly"
23359
23360 test_240() {
23361         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
23362         remote_mds_nodsh && skip "remote MDS with nodsh"
23363
23364         mkdir -p $DIR/$tdir
23365
23366         $LFS mkdir -i 0 $DIR/$tdir/d0 ||
23367                 error "failed to mkdir $DIR/$tdir/d0 on MDT0"
23368         $LFS mkdir -i 1 $DIR/$tdir/d0/d1 ||
23369                 error "failed to mkdir $DIR/$tdir/d0/d1 on MDT1"
23370
23371         umount_client $MOUNT || error "umount failed"
23372         #define OBD_FAIL_TGT_DELAY_CONDITIONAL   0x713
23373         do_facet mds2 lctl set_param fail_loc=0x713 fail_val=1
23374         mount_client $MOUNT || error "failed to mount client"
23375
23376         echo "stat $DIR/$tdir/d0/d1, should not fail/ASSERT"
23377         stat $DIR/$tdir/d0/d1 || error "fail to stat $DIR/$tdir/d0/d1"
23378 }
23379 run_test 240 "race between ldlm enqueue and the connection RPC (no ASSERT)"
23380
23381 test_241_bio() {
23382         local count=$1
23383         local bsize=$2
23384
23385         for LOOP in $(seq $count); do
23386                 dd if=$DIR/$tfile of=/dev/null bs=$bsize count=1 2>/dev/null
23387                 cancel_lru_locks $OSC || true
23388         done
23389 }
23390
23391 test_241_dio() {
23392         local count=$1
23393         local bsize=$2
23394
23395         for LOOP in $(seq $1); do
23396                 dd if=$DIR/$tfile of=/dev/null bs=$bsize count=1 iflag=direct \
23397                         2>/dev/null
23398         done
23399 }
23400
23401 test_241a() { # was test_241
23402         local bsize=$PAGE_SIZE
23403
23404         (( bsize < 40960 )) && bsize=40960
23405         dd if=/dev/zero of=$DIR/$tfile count=1 bs=$bsize
23406         ls -la $DIR/$tfile
23407         cancel_lru_locks $OSC
23408         test_241_bio 1000 $bsize &
23409         PID=$!
23410         test_241_dio 1000 $bsize
23411         wait $PID
23412 }
23413 run_test 241a "bio vs dio"
23414
23415 test_241b() {
23416         local bsize=$PAGE_SIZE
23417
23418         (( bsize < 40960 )) && bsize=40960
23419         dd if=/dev/zero of=$DIR/$tfile count=1 bs=$bsize
23420         ls -la $DIR/$tfile
23421         test_241_dio 1000 $bsize &
23422         PID=$!
23423         test_241_dio 1000 $bsize
23424         wait $PID
23425 }
23426 run_test 241b "dio vs dio"
23427
23428 test_242() {
23429         remote_mds_nodsh && skip "remote MDS with nodsh"
23430
23431         mkdir_on_mdt0 $DIR/$tdir
23432         touch $DIR/$tdir/$tfile
23433
23434         #define OBD_FAIL_MDS_READPAGE_PACK      0x105
23435         do_facet mds1 lctl set_param fail_loc=0x105
23436         /bin/ls $DIR/$tdir && error "ls $DIR/$tdir should fail"
23437
23438         do_facet mds1 lctl set_param fail_loc=0
23439         /bin/ls $DIR/$tdir || error "ls $DIR/$tdir failed"
23440 }
23441 run_test 242 "mdt_readpage failure should not cause directory unreadable"
23442
23443 test_243()
23444 {
23445         test_mkdir $DIR/$tdir
23446         group_lock_test -d $DIR/$tdir || error "A group lock test failed"
23447 }
23448 run_test 243 "various group lock tests"
23449
23450 test_244a()
23451 {
23452         test_mkdir $DIR/$tdir
23453         dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=35
23454         sendfile_grouplock $DIR/$tdir/$tfile || \
23455                 error "sendfile+grouplock failed"
23456         rm -rf $DIR/$tdir
23457 }
23458 run_test 244a "sendfile with group lock tests"
23459
23460 test_244b()
23461 {
23462         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
23463
23464         local threads=50
23465         local size=$((1024*1024))
23466
23467         test_mkdir $DIR/$tdir
23468         for i in $(seq 1 $threads); do
23469                 local file=$DIR/$tdir/file_$((i / 10))
23470                 $MULTIOP $file OG1234w$size_$((i % 3))w$size_$((i % 4))g1234c &
23471                 local pids[$i]=$!
23472         done
23473         for i in $(seq 1 $threads); do
23474                 wait ${pids[$i]}
23475         done
23476 }
23477 run_test 244b "multi-threaded write with group lock"
23478
23479 test_245a() {
23480         local flagname="multi_mod_rpcs"
23481         local connect_data_name="max_mod_rpcs"
23482         local out
23483
23484         # check if multiple modify RPCs flag is set
23485         out=$($LCTL get_param mdc.$FSNAME-MDT0000-*.import |
23486                 grep "connect_flags:")
23487         echo "$out"
23488
23489         echo "$out" | grep -qw $flagname
23490         if [ $? -ne 0 ]; then
23491                 echo "connect flag $flagname is not set"
23492                 return
23493         fi
23494
23495         # check if multiple modify RPCs data is set
23496         out=$($LCTL get_param mdc.$FSNAME-MDT0000-*.import)
23497         echo "$out"
23498
23499         echo "$out" | grep -qw $connect_data_name ||
23500                 error "import should have connect data $connect_data_name"
23501 }
23502 run_test 245a "check mdc connection flag/data: multiple modify RPCs"
23503
23504 test_245b() {
23505         local flagname="multi_mod_rpcs"
23506         local connect_data_name="max_mod_rpcs"
23507         local out
23508
23509         remote_mds_nodsh && skip "remote MDS with nodsh"
23510         [[ $MDSCOUNT -ge 2 ]] || skip "needs >= 2 MDTs"
23511
23512         # check if multiple modify RPCs flag is set
23513         out=$(do_facet mds1 \
23514               $LCTL get_param osp.$FSNAME-MDT0001-osp-MDT0000.import |
23515               grep "connect_flags:")
23516         echo "$out"
23517
23518         [[ "$out" =~ $flagname ]] || skip "connect flag $flagname is not set"
23519
23520         # check if multiple modify RPCs data is set
23521         out=$(do_facet mds1 \
23522               $LCTL get_param osp.$FSNAME-MDT0001-osp-MDT0000.import)
23523
23524         [[ "$out" =~ $connect_data_name ]] ||
23525                 {
23526                         echo "$out"
23527                         error "missing connect data $connect_data_name"
23528                 }
23529 }
23530 run_test 245b "check osp connection flag/data: multiple modify RPCs"
23531
23532 cleanup_247() {
23533         local submount=$1
23534
23535         trap 0
23536         umount_client $submount
23537         rmdir $submount
23538 }
23539
23540 test_247a() {
23541         lctl get_param -n mdc.$FSNAME-MDT0000*.import |
23542                 grep -q subtree ||
23543                 skip_env "Fileset feature is not supported"
23544
23545         local submount=${MOUNT}_$tdir
23546
23547         mkdir $MOUNT/$tdir
23548         mkdir -p $submount || error "mkdir $submount failed"
23549         FILESET="$FILESET/$tdir" mount_client $submount ||
23550                 error "mount $submount failed"
23551         trap "cleanup_247 $submount" EXIT
23552         echo foo > $submount/$tfile || error "write $submount/$tfile failed"
23553         [ $(cat $MOUNT/$tdir/$tfile) = "foo" ] ||
23554                 error "read $MOUNT/$tdir/$tfile failed"
23555         cleanup_247 $submount
23556 }
23557 run_test 247a "mount subdir as fileset"
23558
23559 test_247b() {
23560         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
23561                 skip_env "Fileset feature is not supported"
23562
23563         local submount=${MOUNT}_$tdir
23564
23565         rm -rf $MOUNT/$tdir
23566         mkdir -p $submount || error "mkdir $submount failed"
23567         SKIP_FILESET=1
23568         FILESET="$FILESET/$tdir" mount_client $submount &&
23569                 error "mount $submount should fail"
23570         rmdir $submount
23571 }
23572 run_test 247b "mount subdir that dose not exist"
23573
23574 test_247c() {
23575         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
23576                 skip_env "Fileset feature is not supported"
23577
23578         local submount=${MOUNT}_$tdir
23579
23580         mkdir -p $MOUNT/$tdir/dir1
23581         mkdir -p $submount || error "mkdir $submount failed"
23582         trap "cleanup_247 $submount" EXIT
23583         FILESET="$FILESET/$tdir" mount_client $submount ||
23584                 error "mount $submount failed"
23585         local fid=$($LFS path2fid $MOUNT/)
23586         $LFS fid2path $submount $fid && error "fid2path should fail"
23587         cleanup_247 $submount
23588 }
23589 run_test 247c "running fid2path outside subdirectory root"
23590
23591 test_247d() {
23592         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
23593                 skip "Fileset feature is not supported"
23594
23595         local submount=${MOUNT}_$tdir
23596
23597         mkdir -p $MOUNT/$tdir/dir1
23598         mkdir -p $submount || error "mkdir $submount failed"
23599         FILESET="$FILESET/$tdir" mount_client $submount ||
23600                 error "mount $submount failed"
23601         trap "cleanup_247 $submount" EXIT
23602
23603         local td=$submount/dir1
23604         local fid=$($LFS path2fid $td)
23605         [ -z "$fid" ] && error "path2fid unable to get $td FID"
23606
23607         # check that we get the same pathname back
23608         local rootpath
23609         local found
23610         for rootpath in "$submount" "$submount///" "$submount/dir1"; do
23611                 echo "$rootpath $fid"
23612                 found=$($LFS fid2path $rootpath "$fid")
23613                 [ -n "$found" ] || error "fid2path should succeed"
23614                 [ "$found" == "$td" ] || error "fid2path $found != $td"
23615         done
23616         # check wrong root path format
23617         rootpath=$submount"_wrong"
23618         found=$($LFS fid2path $rootpath "$fid")
23619         [ -z "$found" ] || error "fid2path should fail ($rootpath != $submount)"
23620
23621         cleanup_247 $submount
23622 }
23623 run_test 247d "running fid2path inside subdirectory root"
23624
23625 # LU-8037
23626 test_247e() {
23627         lctl get_param -n mdc.$FSNAME-MDT0000*.import |
23628                 grep -q subtree ||
23629                 skip "Fileset feature is not supported"
23630
23631         local submount=${MOUNT}_$tdir
23632
23633         mkdir $MOUNT/$tdir
23634         mkdir -p $submount || error "mkdir $submount failed"
23635         FILESET="$FILESET/.." mount_client $submount &&
23636                 error "mount $submount should fail"
23637         rmdir $submount
23638 }
23639 run_test 247e "mount .. as fileset"
23640
23641 test_247f() {
23642         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
23643         (( $MDS1_VERSION >= $(version_code 2.14.50.162) )) ||
23644                 skip "Need at least version 2.14.50.162"
23645         lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
23646                 skip "Fileset feature is not supported"
23647
23648         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
23649         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/remote ||
23650                 error "mkdir remote failed"
23651         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/remote/subdir ||
23652                 error "mkdir remote/subdir failed"
23653         $LFS mkdir -i 0 -c $MDSCOUNT $DIR/$tdir/striped ||
23654                 error "mkdir striped failed"
23655         mkdir $DIR/$tdir/striped/subdir || error "mkdir striped/subdir failed"
23656
23657         local submount=${MOUNT}_$tdir
23658
23659         mkdir -p $submount || error "mkdir $submount failed"
23660         stack_trap "rmdir $submount"
23661
23662         local dir
23663         local fileset=$FILESET
23664         local mdts=$(comma_list $(mdts_nodes))
23665
23666         do_nodes $mdts "$LCTL set_param mdt.*.enable_remote_subdir_mount=1"
23667         for dir in $tdir/remote $tdir/remote/subdir $tdir/striped \
23668                 $tdir/striped/subdir $tdir/striped/.; do
23669                 FILESET="$fileset/$dir" mount_client $submount ||
23670                         error "mount $dir failed"
23671                 umount_client $submount
23672         done
23673 }
23674 run_test 247f "mount striped or remote directory as fileset"
23675
23676 test_subdir_mount_lock()
23677 {
23678         local testdir=$1
23679         local submount=${MOUNT}_$(basename $testdir)
23680
23681         touch $DIR/$testdir/$tfile || error "touch $tfile failed"
23682
23683         mkdir -p $submount || error "mkdir $submount failed"
23684         stack_trap "rmdir $submount"
23685
23686         FILESET="$fileset/$testdir" mount_client $submount ||
23687                 error "mount $FILESET failed"
23688         stack_trap "umount $submount"
23689
23690         local mdts=$(comma_list $(mdts_nodes))
23691
23692         local nrpcs
23693
23694         stat $submount > /dev/null || error "stat $submount failed"
23695         cancel_lru_locks $MDC
23696         stat $submount > /dev/null || error "stat $submount failed"
23697         stat $submount/$tfile > /dev/null || error "stat $tfile failed"
23698         do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear > /dev/null"
23699         stat $submount/$tfile > /dev/null || error "stat $tfile failed"
23700         nrpcs=$(do_nodes $mdts "lctl get_param -n mdt.*.md_stats" |
23701                 awk '/getattr/ {sum += $2} END {print sum}')
23702
23703         [ -z "$nrpcs" ] || error "$nrpcs extra getattr sent"
23704 }
23705
23706 test_247g() {
23707         (( $MDSCOUNT > 1 )) || skip_env "needs > 1 MDTs"
23708
23709         $LFS mkdir -i 0 -c 4 -H fnv_1a_64 $DIR/$tdir ||
23710                 error "mkdir $tdir failed"
23711         test_subdir_mount_lock $tdir
23712 }
23713 run_test 247g "striped directory submount revalidate ROOT from cache"
23714
23715 test_247h() {
23716         (( $MDSCOUNT > 1 )) || skip_env "needs > 1 MDTs"
23717         (( $MDS1_VERSION >= $(version_code 2.15.51) )) ||
23718                 skip "Need MDS version at least 2.15.51"
23719
23720         $LFS mkdir -i 1 -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
23721         test_subdir_mount_lock $tdir
23722         mkdir_on_mdt -i 0 $DIR/$tdir/$tdir.0 || error "mkdir $tdir.0 failed"
23723         mkdir_on_mdt -i 1 $DIR/$tdir/$tdir.0/$tdir.1 ||
23724                 error "mkdir $tdir.1 failed"
23725         test_subdir_mount_lock $tdir/$tdir.0/$tdir.1
23726 }
23727 run_test 247h "remote directory submount revalidate ROOT from cache"
23728
23729 test_248a() {
23730         local fast_read_sav=$($LCTL get_param -n llite.*.fast_read 2>/dev/null)
23731         [ -z "$fast_read_sav" ] && skip "no fast read support"
23732
23733         # create a large file for fast read verification
23734         dd if=/dev/zero of=$DIR/$tfile bs=1M count=128 > /dev/null 2>&1
23735
23736         # make sure the file is created correctly
23737         $CHECKSTAT -s $((128*1024*1024)) $DIR/$tfile ||
23738                 { rm -f $DIR/$tfile; skip "file creation error"; }
23739
23740         echo "Test 1: verify that fast read is 4 times faster on cache read"
23741
23742         # small read with fast read enabled
23743         $LCTL set_param -n llite.*.fast_read=1
23744         local t_fast=$(dd if=$DIR/$tfile of=/dev/null bs=4k 2>&1 |
23745                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
23746                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
23747         # small read with fast read disabled
23748         $LCTL set_param -n llite.*.fast_read=0
23749         local t_slow=$(dd if=$DIR/$tfile of=/dev/null bs=4k 2>&1 |
23750                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
23751                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
23752
23753         # verify that fast read is 4 times faster for cache read
23754         [ $(bc <<< "4 * $t_fast < $t_slow") -eq 1 ] ||
23755                 error_not_in_vm "fast read was not 4 times faster: " \
23756                            "$t_fast vs $t_slow"
23757
23758         echo "Test 2: verify the performance between big and small read"
23759         $LCTL set_param -n llite.*.fast_read=1
23760
23761         # 1k non-cache read
23762         cancel_lru_locks osc
23763         local t_1k=$(dd if=$DIR/$tfile of=/dev/null bs=1k 2>&1 |
23764                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
23765                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
23766
23767         # 1M non-cache read
23768         cancel_lru_locks osc
23769         local t_1m=$(dd if=$DIR/$tfile of=/dev/null bs=1k 2>&1 |
23770                 egrep -o '([[:digit:]\.\,e-]+) s' | cut -d's' -f1 |
23771                 sed -e 's/,/./' -e 's/[eE]+*/\*10\^/')
23772
23773         # verify that big IO is not 4 times faster than small IO
23774         [ $(bc <<< "4 * $t_1k >= $t_1m") -eq 1 ] ||
23775                 error_not_in_vm "bigger IO is way too fast: $t_1k vs $t_1m"
23776
23777         $LCTL set_param -n llite.*.fast_read=$fast_read_sav
23778         rm -f $DIR/$tfile
23779 }
23780 run_test 248a "fast read verification"
23781
23782 test_248b() {
23783         # Default short_io_bytes=16384, try both smaller and larger sizes.
23784         # Lustre O_DIRECT read and write needs to be a multiple of PAGE_SIZE.
23785         # 6017024 = 2^12*13*113 = 47008*128 = 11752*512 = 4096*1469 = 53248*113
23786         echo "bs=53248 count=113 normal buffered write"
23787         dd if=/dev/urandom of=$TMP/$tfile.0 bs=53248 count=113 ||
23788                 error "dd of initial data file failed"
23789         stack_trap "rm -f $DIR/$tfile.[0-3] $TMP/$tfile.[0-3]" EXIT
23790
23791         echo "bs=47008 count=128 oflag=dsync normal write $tfile.0"
23792         dd if=$TMP/$tfile.0 of=$DIR/$tfile.0 bs=47008 count=128 oflag=dsync ||
23793                 error "dd with sync normal writes failed"
23794         cmp $TMP/$tfile.0 $DIR/$tfile.0 || error "compare $DIR/$tfile.0 failed"
23795
23796         echo "bs=11752 count=512 oflag=dsync small write $tfile.1"
23797         dd if=$TMP/$tfile.0 of=$DIR/$tfile.1 bs=11752 count=512 oflag=dsync ||
23798                 error "dd with sync small writes failed"
23799         cmp $TMP/$tfile.0 $DIR/$tfile.1 || error "compare $DIR/$tfile.1 failed"
23800
23801         cancel_lru_locks osc
23802
23803         # calculate the small O_DIRECT size and count for the client PAGE_SIZE
23804         local num=$((13 * 113 / (PAGE_SIZE / 4096)))
23805         echo "bs=$PAGE_SIZE count=$num iflag=direct small read $tfile.1"
23806         dd if=$DIR/$tfile.1 of=$TMP/$tfile.1 bs=$PAGE_SIZE count=$num \
23807                 iflag=direct || error "dd with O_DIRECT small read failed"
23808         # adjust bytes checked to handle larger PAGE_SIZE for ARM/PPC
23809         cmp --bytes=$((PAGE_SIZE * num)) $TMP/$tfile.0 $TMP/$tfile.1 ||
23810                 error "compare $TMP/$tfile.1 failed"
23811
23812         local save=$($LCTL get_param -n osc.*OST000*.short_io_bytes | head -n 1)
23813         stack_trap "$LCTL set_param osc.$FSNAME-*.short_io_bytes=$save" EXIT
23814
23815         # just to see what the maximum tunable value is, and test parsing
23816         echo "test invalid parameter 2MB"
23817         $LCTL set_param osc.$FSNAME-OST0000*.short_io_bytes=2M &&
23818                 error "too-large short_io_bytes allowed"
23819         echo "test maximum parameter 512KB"
23820         # if we can set a larger short_io_bytes, run test regardless of version
23821         if ! $LCTL set_param osc.$FSNAME-OST0000*.short_io_bytes=512K; then
23822                 # older clients may not allow setting it this large, that's OK
23823                 [ $CLIENT_VERSION -ge $(version_code 2.13.50) ] ||
23824                         skip "Need at least client version 2.13.50"
23825                 error "medium short_io_bytes failed"
23826         fi
23827         $LCTL get_param osc.$FSNAME-OST0000*.short_io_bytes
23828         size=$($LCTL get_param -n osc.$FSNAME-OST0000*.short_io_bytes)
23829
23830         echo "test large parameter 64KB"
23831         $LCTL set_param osc.$FSNAME-*.short_io_bytes=65536
23832         $LCTL get_param osc.$FSNAME-OST0000*.short_io_bytes
23833
23834         echo "bs=47008 count=128 oflag=dsync large write $tfile.2"
23835         dd if=$TMP/$tfile.0 of=$DIR/$tfile.2 bs=47008 count=128 oflag=dsync ||
23836                 error "dd with sync large writes failed"
23837         cmp $TMP/$tfile.0 $DIR/$tfile.2 || error "compare $DIR/$tfile.2 failed"
23838
23839         # calculate the large O_DIRECT size and count for the client PAGE_SIZE
23840         local size=$(((4096 * 13 + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE))
23841         num=$((113 * 4096 / PAGE_SIZE))
23842         echo "bs=$size count=$num oflag=direct large write $tfile.3"
23843         dd if=$TMP/$tfile.0 of=$DIR/$tfile.3 bs=$size count=$num oflag=direct ||
23844                 error "dd with O_DIRECT large writes failed"
23845         cmp --bytes=$((size * num)) $TMP/$tfile.0 $DIR/$tfile.3 ||
23846                 error "compare $DIR/$tfile.3 failed"
23847
23848         cancel_lru_locks osc
23849
23850         echo "bs=$size count=$num iflag=direct large read $tfile.2"
23851         dd if=$DIR/$tfile.2 of=$TMP/$tfile.2 bs=$size count=$num iflag=direct ||
23852                 error "dd with O_DIRECT large read failed"
23853         cmp --bytes=$((size * num)) $TMP/$tfile.0 $TMP/$tfile.2 ||
23854                 error "compare $TMP/$tfile.2 failed"
23855
23856         echo "bs=$size count=$num iflag=direct large read $tfile.3"
23857         dd if=$DIR/$tfile.3 of=$TMP/$tfile.3 bs=$size count=$num iflag=direct ||
23858                 error "dd with O_DIRECT large read failed"
23859         cmp --bytes=$((size * num)) $TMP/$tfile.0 $TMP/$tfile.3 ||
23860                 error "compare $TMP/$tfile.3 failed"
23861 }
23862 run_test 248b "test short_io read and write for both small and large sizes"
23863
23864 test_248c() {
23865         $LCTL set_param llite.*.read_ahead_stats=c
23866         # This test compares whole file readahead to non-whole file readahead
23867         # The performance should be consistently slightly faster for whole file,
23868         # and the bug caused whole file readahead to be 80-100x slower, but to
23869         # account for possible test system lag, we require whole file to be
23870         # <= 1.5xnon-whole file, and require 3 failures in a row to fail the
23871         # test
23872         local time1
23873         local time2
23874         local whole_mb=$($LCTL get_param -n llite.*.max_read_ahead_whole_mb)
23875         stack_trap "$LCTL set_param llite.*.max_read_ahead_whole_mb=$whole_mb" EXIT
23876         counter=0
23877
23878         while [ $counter -lt 3 ]; do
23879                 # Increment the counter
23880                 ((counter++))
23881
23882                 $LCTL set_param llite.*.max_read_ahead_whole_mb=64
23883                 rm -f $DIR/$tfile
23884                 touch $DIR/$tfile || error "(0) failed to create file"
23885                 # 64 MiB
23886                 $TRUNCATE $DIR/$tfile 67108864 || error "(1) failed to truncate file"
23887                 time1=$(dd if=$DIR/$tfile bs=4K of=/dev/null 2>&1 | awk '/bytes/ {print $8}')
23888                 echo "whole file readahead of 64 MiB took $time1 seconds"
23889                 $LCTL get_param llite.*.read_ahead_stats
23890
23891                 $LCTL set_param llite.*.read_ahead_stats=c
23892                 $LCTL set_param llite.*.max_read_ahead_whole_mb=8
23893                 rm -f $DIR/$tfile
23894                 touch $DIR/$tfile || error "(2) failed to create file"
23895                 # 64 MiB
23896                 $TRUNCATE $DIR/$tfile 67108864 || error "(3) failed to create file"
23897                 time2=$(dd if=$DIR/$tfile bs=4K of=/dev/null 2>&1 | awk '/bytes/ {print $8}')
23898                 echo "non-whole file readahead of 64 MiB took $time2 seconds"
23899                 $LCTL get_param llite.*.read_ahead_stats
23900
23901                 # Check if time1 is not more than 1.5 times2
23902                 timecheck=$(echo "$time1 <= (1.5 * $time2)" | bc -l)
23903
23904                 if [[ $timecheck -eq 1 ]]; then
23905                         echo "Test passed on attempt $counter"
23906                         # Exit the loop
23907                         counter=4
23908                 else
23909                         echo "Attempt $counter failed: whole file readahead took: $time1, greater than non: $time2"
23910                 fi
23911         done
23912         if [ $counter -eq 3 ]; then
23913                 error "whole file readahead check failed 3 times in a row, probably not just VM lag"
23914         fi
23915
23916 }
23917 run_test 248c "verify whole file read behavior"
23918
23919 test_249() { # LU-7890
23920         [ $MDS1_VERSION -lt $(version_code 2.8.53) ] &&
23921                 skip "Need at least version 2.8.54"
23922
23923         rm -f $DIR/$tfile
23924         $LFS setstripe -c 1 $DIR/$tfile
23925         # Offset 2T == 4k * 512M
23926         dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 seek=512M ||
23927                 error "dd to 2T offset failed"
23928 }
23929 run_test 249 "Write above 2T file size"
23930
23931 test_250() {
23932         [ "$(facet_fstype ost$(($($LFS getstripe -i $DIR/$tfile) + 1)))" = "zfs" ] \
23933          && skip "no 16TB file size limit on ZFS"
23934
23935         $LFS setstripe -c 1 $DIR/$tfile
23936         # ldiskfs extent file size limit is (16TB - 4KB - 1) bytes
23937         local size=$((16 * 1024 * 1024 * 1024 * 1024 - 4096 - 1))
23938         $TRUNCATE $DIR/$tfile $size || error "truncate $tfile to $size failed"
23939         dd if=/dev/zero of=$DIR/$tfile bs=10 count=1 oflag=append \
23940                 conv=notrunc,fsync && error "append succeeded"
23941         return 0
23942 }
23943 run_test 250 "Write above 16T limit"
23944
23945 test_251a() {
23946         $LFS setstripe -c -1 -S 1048576 $DIR/$tfile
23947
23948         #define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407
23949         #Skip once - writing the first stripe will succeed
23950         $LCTL set_param fail_loc=0xa0001407 fail_val=1
23951         $MULTIOP $DIR/$tfile o:O_RDWR:w2097152c 2>&1 | grep -q "short write" &&
23952                 error "short write happened"
23953
23954         $LCTL set_param fail_loc=0xa0001407 fail_val=1
23955         $MULTIOP $DIR/$tfile or2097152c 2>&1 | grep -q "short read" &&
23956                 error "short read happened"
23957
23958         rm -f $DIR/$tfile
23959 }
23960 run_test 251a "Handling short read and write correctly"
23961
23962 test_251b() {
23963         dd if=/dev/zero of=$DIR/$tfile bs=1k count=4 ||
23964                 error "write $tfile failed"
23965
23966         sleep 2 && echo 12345 >> $DIR/$tfile &
23967
23968         #define OBD_FAIL_LLITE_READ_PAUSE 0x1431
23969         $LCTL set_param fail_loc=0x1431 fail_val=5
23970         # seek to 4096, 2 seconds later, file size expand to 4102, and after
23971         # 5 seconds, read 10 bytes, the short read should
23972         # report:
23973         #                start ->+ read_len -> offset_after_read read_count
23974         #     short read: 4096 ->+ 10 -> 4096 0
23975         # not:
23976         #     short read: 4096 ->+ 10 -> 4102 0
23977         local off=$($MULTIOP $DIR/$tfile oO_RDONLY:z4096r10c 2>&1 | \
23978                         awk '/short read/ { print $7 }')
23979         (( off == 4096 )) ||
23980                 error "short read should set offset at 4096, not $off"
23981 }
23982 run_test 251b "short read restore offset correctly"
23983
23984 test_252() {
23985         remote_mds_nodsh && skip "remote MDS with nodsh"
23986         remote_ost_nodsh && skip "remote OST with nodsh"
23987         if [ "$ost1_FSTYPE" != ldiskfs ] || [ "$mds1_FSTYPE" != ldiskfs ]; then
23988                 skip_env "ldiskfs only test"
23989         fi
23990
23991         local tgt
23992         local dev
23993         local out
23994         local uuid
23995         local num
23996         local gen
23997
23998         # check lr_reader on OST0000
23999         tgt=ost1
24000         dev=$(facet_device $tgt)
24001         out=$(do_facet $tgt $LR_READER $dev)
24002         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
24003         echo "$out"
24004         uuid=$(echo "$out" | grep -i uuid | awk '{ print $2 }')
24005         [ "$uuid" == "$(ostuuid_from_index 0)" ] ||
24006                 error "Invalid uuid returned by $LR_READER on target $tgt"
24007         echo -e "uuid returned by $LR_READER is '$uuid'\n"
24008
24009         # check lr_reader -c on MDT0000
24010         tgt=mds1
24011         dev=$(facet_device $tgt)
24012         if ! do_facet $tgt $LR_READER -h | grep -q OPTIONS; then
24013                 skip "$LR_READER does not support additional options"
24014         fi
24015         out=$(do_facet $tgt $LR_READER -c $dev)
24016         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
24017         echo "$out"
24018         num=$(echo "$out" | grep -c "mdtlov")
24019         [ "$num" -eq $((MDSCOUNT - 1)) ] ||
24020                 error "Invalid number of mdtlov clients returned by $LR_READER"
24021         echo -e "Number of mdtlov clients returned by $LR_READER is '$num'\n"
24022
24023         # check lr_reader -cr on MDT0000
24024         out=$(do_facet $tgt $LR_READER -cr $dev)
24025         [ $? -eq 0 ] || error "$LR_READER failed on target $tgt device $dev"
24026         echo "$out"
24027         echo "$out" | grep -q "^reply_data:$" ||
24028                 error "$LR_READER should have returned 'reply_data' section"
24029         num=$(echo "$out" | grep -c "client_generation")
24030         echo -e "Number of reply data returned by $LR_READER is '$num'\n"
24031 }
24032 run_test 252 "check lr_reader tool"
24033
24034 test_253() {
24035         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24036         remote_mds_nodsh && skip "remote MDS with nodsh"
24037         remote_mgs_nodsh && skip "remote MGS with nodsh"
24038         check_set_fallocate_or_skip
24039
24040         local ostidx=0
24041         local rc=0
24042         local ost_name=$(ostname_from_index $ostidx)
24043
24044         # on the mdt's osc
24045         local mdtosc_proc1=$(get_mdtosc_proc_path $SINGLEMDS $ost_name)
24046         do_facet $SINGLEMDS $LCTL get_param -n \
24047                 osp.$mdtosc_proc1.reserved_mb_high ||
24048                 skip  "remote MDS does not support reserved_mb_high"
24049
24050         rm -rf $DIR/$tdir
24051         wait_mds_ost_sync
24052         wait_delete_completed
24053         mkdir $DIR/$tdir
24054         stack_trap "rm -rf $DIR/$tdir"
24055
24056         pool_add $TESTNAME || error "Pool creation failed"
24057         pool_add_targets $TESTNAME 0 || error "Pool add targets failed"
24058
24059         $LFS setstripe $DIR/$tdir -i $ostidx -c 1 -p $FSNAME.$TESTNAME ||
24060                 error "Setstripe failed"
24061
24062         dd if=/dev/zero of=$DIR/$tdir/$tfile.0 bs=1M count=10
24063
24064         local wms=$(ost_watermarks_get $ostidx)
24065
24066         ost_watermarks_set $ostidx 60 50
24067         stack_trap "ost_watermarks_set $ostidx $wms"
24068
24069         local free_kb=$($LFS df $MOUNT | awk "/$ost_name/ { print \$4 }")
24070         local size=$((free_kb * 1024))
24071
24072         fallocate -l $size $DIR/$tdir/fill_ost$ostidx ||
24073                 error "fallocate failed"
24074         sleep_maxage
24075
24076         local oa_status=$(do_facet $SINGLEMDS $LCTL get_param -n \
24077                         osp.$mdtosc_proc1.prealloc_status)
24078         echo "prealloc_status $oa_status"
24079
24080         dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=1M count=1 &&
24081                 error "File creation should fail"
24082
24083         #object allocation was stopped, but we still able to append files
24084         dd if=/dev/zero of=$DIR/$tdir/$tfile.0 bs=1M seek=6 count=5 \
24085                 oflag=append || error "Append failed"
24086
24087         rm -f $DIR/$tdir/$tfile.0
24088         rm -f $DIR/$tdir/fill_ost$ostidx
24089
24090         wait_delete_completed
24091         sleep_maxage
24092
24093         for i in $(seq 10 12); do
24094                 dd if=/dev/zero of=$DIR/$tdir/$tfile.$i bs=1M count=1 \
24095                         2>/dev/null || error "File creation failed after rm"
24096         done
24097
24098         oa_status=$(do_facet $SINGLEMDS $LCTL get_param -n \
24099                         osp.$mdtosc_proc1.prealloc_status)
24100         echo "prealloc_status $oa_status"
24101
24102         if (( oa_status != 0 )); then
24103                 error "Object allocation still disable after rm"
24104         fi
24105 }
24106 run_test 253 "Check object allocation limit"
24107
24108 test_254() {
24109         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24110         remote_mds_nodsh && skip "remote MDS with nodsh"
24111
24112         local mdt=$(facet_svc $SINGLEMDS)
24113
24114         do_facet $SINGLEMDS $LCTL get_param -n mdd.$mdt.changelog_size ||
24115                 skip "MDS does not support changelog_size"
24116
24117         local cl_user
24118
24119         changelog_register || error "changelog_register failed"
24120
24121         changelog_clear 0 || error "changelog_clear failed"
24122
24123         local size1=$(do_facet $SINGLEMDS \
24124                       $LCTL get_param -n mdd.$mdt.changelog_size)
24125         echo "Changelog size $size1"
24126
24127         rm -rf $DIR/$tdir
24128         $LFS mkdir -i 0 $DIR/$tdir
24129         # change something
24130         mkdir -p $DIR/$tdir/pics/2008/zachy
24131         touch $DIR/$tdir/pics/2008/zachy/timestamp
24132         cp /etc/hosts $DIR/$tdir/pics/2008/zachy/pic1.jpg
24133         mv $DIR/$tdir/pics/2008/zachy $DIR/$tdir/pics/zach
24134         ln $DIR/$tdir/pics/zach/pic1.jpg $DIR/$tdir/pics/2008/portland.jpg
24135         ln -s $DIR/$tdir/pics/2008/portland.jpg $DIR/$tdir/pics/desktop.jpg
24136         rm $DIR/$tdir/pics/desktop.jpg
24137
24138         local size2=$(do_facet $SINGLEMDS \
24139                       $LCTL get_param -n mdd.$mdt.changelog_size)
24140         echo "Changelog size after work $size2"
24141
24142         (( $size2 > $size1 )) ||
24143                 error "new Changelog size=$size2 less than old size=$size1"
24144 }
24145 run_test 254 "Check changelog size"
24146
24147 ladvise_no_type()
24148 {
24149         local type=$1
24150         local file=$2
24151
24152         lfs ladvise -a invalid $file 2>&1 | grep "Valid types" |
24153                 awk -F: '{print $2}' | grep $type > /dev/null
24154         if [ $? -ne 0 ]; then
24155                 return 0
24156         fi
24157         return 1
24158 }
24159
24160 ladvise_no_ioctl()
24161 {
24162         local file=$1
24163
24164         lfs ladvise -a willread $file > /dev/null 2>&1
24165         if [ $? -eq 0 ]; then
24166                 return 1
24167         fi
24168
24169         lfs ladvise -a willread $file 2>&1 |
24170                 grep "Inappropriate ioctl for device" > /dev/null
24171         if [ $? -eq 0 ]; then
24172                 return 0
24173         fi
24174         return 1
24175 }
24176
24177 percent() {
24178         bc <<<"scale=2; ($1 - $2) * 100 / $2"
24179 }
24180
24181 # run a random read IO workload
24182 # usage: random_read_iops <filename> <filesize> <iosize>
24183 random_read_iops() {
24184         local file=$1
24185         local fsize=$2
24186         local iosize=${3:-4096}
24187
24188         $READS -f $file -s $fsize -b $iosize -n $((fsize / iosize)) -t 60 |
24189                 sed -e '/^$/d' -e 's#.*s, ##' -e 's#MB/s##'
24190 }
24191
24192 drop_file_oss_cache() {
24193         local file="$1"
24194         local nodes="$2"
24195
24196         $LFS ladvise -a dontneed $file 2>/dev/null ||
24197                 do_nodes $nodes "echo 3 > /proc/sys/vm/drop_caches"
24198 }
24199
24200 ladvise_willread_performance()
24201 {
24202         local repeat=10
24203         local average_origin=0
24204         local average_cache=0
24205         local average_ladvise=0
24206
24207         for ((i = 1; i <= $repeat; i++)); do
24208                 echo "Iter $i/$repeat: reading without willread hint"
24209                 cancel_lru_locks osc
24210                 drop_file_oss_cache $DIR/$tfile $(comma_list $(osts_nodes))
24211                 local speed_origin=$(random_read_iops $DIR/$tfile $size)
24212                 echo "Iter $i/$repeat: uncached speed: $speed_origin"
24213                 average_origin=$(bc <<<"$average_origin + $speed_origin")
24214
24215                 cancel_lru_locks osc
24216                 local speed_cache=$(random_read_iops $DIR/$tfile $size)
24217                 echo "Iter $i/$repeat: OSS cache speed: $speed_cache"
24218                 average_cache=$(bc <<<"$average_cache + $speed_cache")
24219
24220                 cancel_lru_locks osc
24221                 drop_file_oss_cache $DIR/$tfile $(comma_list $(osts_nodes))
24222                 $LFS ladvise -a willread $DIR/$tfile || error "ladvise failed"
24223                 local speed_ladvise=$(random_read_iops $DIR/$tfile $size)
24224                 echo "Iter $i/$repeat: ladvise speed: $speed_ladvise"
24225                 average_ladvise=$(bc <<<"$average_ladvise + $speed_ladvise")
24226         done
24227         average_origin=$(bc <<<"scale=2; $average_origin / $repeat")
24228         average_cache=$(bc <<<"scale=2; $average_cache / $repeat")
24229         average_ladvise=$(bc <<<"scale=2; $average_ladvise / $repeat")
24230
24231         speedup_cache=$(percent $average_cache $average_origin)
24232         speedup_ladvise=$(percent $average_ladvise $average_origin)
24233
24234         echo "Average uncached read: $average_origin"
24235         echo "Average speedup with OSS cached read:" \
24236                 "$average_cache = +$speedup_cache%"
24237         echo "Average speedup with ladvise willread:" \
24238                 "$average_ladvise = +$speedup_ladvise%"
24239
24240         local lowest_speedup=20
24241         if (( ${speedup_cache%.*} < $lowest_speedup )); then
24242                 echo "Speedup with OSS cached read less than $lowest_speedup%,"\
24243                      "got $speedup_cache%. Skipping ladvise willread check."
24244                 return 0
24245         fi
24246
24247         # the test won't work on ZFS until it supports 'ladvise dontneed', but
24248         # it is still good to run until then to exercise 'ladvise willread'
24249         ! $LFS ladvise -a dontneed $DIR/$tfile &&
24250                 [ "$ost1_FSTYPE" = "zfs" ] &&
24251                 echo "osd-zfs does not support dontneed or drop_caches" &&
24252                 return 0
24253
24254         lowest_speedup=$(bc <<<"scale=2; $speedup_cache / 2")
24255         (( ${speedup_ladvise%.*} > ${lowest_speedup%.*} )) ||
24256                 error_not_in_vm "Speedup with willread is less than " \
24257                         "$lowest_speedup%, got $speedup_ladvise%"
24258 }
24259
24260 test_255a() {
24261         [ $OST1_VERSION -lt $(version_code 2.8.54) ] &&
24262                 skip "lustre < 2.8.54 does not support ladvise "
24263         remote_ost_nodsh && skip "remote OST with nodsh"
24264
24265         stack_trap "rm -f $DIR/$tfile"
24266         lfs setstripe -c -1 -i 0 $DIR/$tfile || error "$tfile failed"
24267
24268         ladvise_no_type willread $DIR/$tfile &&
24269                 skip "willread ladvise is not supported"
24270
24271         ladvise_no_ioctl $DIR/$tfile &&
24272                 skip "ladvise ioctl is not supported"
24273
24274         local size_mb=100
24275         local size=$((size_mb * 1048576))
24276         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=$size_mb ||
24277                 error "dd to $DIR/$tfile failed"
24278
24279         lfs ladvise -a willread $DIR/$tfile ||
24280                 error "Ladvise failed with no range argument"
24281
24282         lfs ladvise -a willread -s 0 $DIR/$tfile ||
24283                 error "Ladvise failed with no -l or -e argument"
24284
24285         lfs ladvise -a willread -e 1 $DIR/$tfile ||
24286                 error "Ladvise failed with only -e argument"
24287
24288         lfs ladvise -a willread -l 1 $DIR/$tfile ||
24289                 error "Ladvise failed with only -l argument"
24290
24291         lfs ladvise -a willread -s 2 -e 1 $DIR/$tfile &&
24292                 error "End offset should not be smaller than start offset"
24293
24294         lfs ladvise -a willread -s 2 -e 2 $DIR/$tfile &&
24295                 error "End offset should not be equal to start offset"
24296
24297         lfs ladvise -a willread -s $size -l 1 $DIR/$tfile ||
24298                 error "Ladvise failed with overflowing -s argument"
24299
24300         lfs ladvise -a willread -s 1 -e $((size + 1)) $DIR/$tfile ||
24301                 error "Ladvise failed with overflowing -e argument"
24302
24303         lfs ladvise -a willread -s 1 -l $size $DIR/$tfile ||
24304                 error "Ladvise failed with overflowing -l argument"
24305
24306         lfs ladvise -a willread -l 1 -e 2 $DIR/$tfile &&
24307                 error "Ladvise succeeded with conflicting -l and -e arguments"
24308
24309         echo "Synchronous ladvise should wait"
24310         local delay=8
24311 #define OBD_FAIL_OST_LADVISE_PAUSE       0x237
24312         do_nodes $(comma_list $(osts_nodes)) \
24313                 $LCTL set_param fail_val=$delay fail_loc=0x237
24314         stack_trap "do_nodes $(comma_list $(osts_nodes)) \
24315                 $LCTL set_param fail_loc=0"
24316
24317         local start_ts=$SECONDS
24318         lfs ladvise -a willread $DIR/$tfile ||
24319                 error "Ladvise failed with no range argument"
24320         local end_ts=$SECONDS
24321         local inteval_ts=$((end_ts - start_ts))
24322
24323         if [ $inteval_ts -lt $(($delay - 1)) ]; then
24324                 error "Synchronous advice didn't wait reply"
24325         fi
24326
24327         echo "Asynchronous ladvise shouldn't wait"
24328         local start_ts=$SECONDS
24329         lfs ladvise -a willread -b $DIR/$tfile ||
24330                 error "Ladvise failed with no range argument"
24331         local end_ts=$SECONDS
24332         local inteval_ts=$((end_ts - start_ts))
24333
24334         if [ $inteval_ts -gt $(($delay / 2)) ]; then
24335                 error "Asynchronous advice blocked"
24336         fi
24337
24338         ladvise_willread_performance
24339 }
24340 run_test 255a "check 'lfs ladvise -a willread'"
24341
24342 facet_meminfo() {
24343         local facet=$1
24344         local info=$2
24345
24346         do_facet $facet "cat /proc/meminfo | grep ^${info}:" | awk '{print $2}'
24347 }
24348
24349 test_255b() {
24350         [ $OST1_VERSION -lt $(version_code 2.8.54) ] &&
24351                 skip "lustre < 2.8.54 does not support ladvise "
24352         remote_ost_nodsh && skip "remote OST with nodsh"
24353
24354         stack_trap "rm -f $DIR/$tfile"
24355         lfs setstripe -c 1 -i 0 $DIR/$tfile
24356
24357         ladvise_no_type dontneed $DIR/$tfile &&
24358                 skip "dontneed ladvise is not supported"
24359
24360         ladvise_no_ioctl $DIR/$tfile &&
24361                 skip "ladvise ioctl is not supported"
24362
24363         ! $LFS ladvise -a dontneed $DIR/$tfile &&
24364                 [ "$ost1_FSTYPE" = "zfs" ] &&
24365                 skip "zfs-osd does not support 'ladvise dontneed'"
24366
24367         local size_mb=100
24368         local size=$((size_mb * 1048576))
24369         # In order to prevent disturbance of other processes, only check 3/4
24370         # of the memory usage
24371         local kibibytes=$((size_mb * 1024 * 3 / 4))
24372
24373         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=$size_mb ||
24374                 error "dd to $DIR/$tfile failed"
24375
24376         #force write to complete before dropping OST cache & checking memory
24377         sync
24378
24379         local total=$(facet_meminfo ost1 MemTotal)
24380         echo "Total memory: $total KiB"
24381
24382         do_facet ost1 "sync && echo 3 > /proc/sys/vm/drop_caches"
24383         local before_read=$(facet_meminfo ost1 Cached)
24384         echo "Cache used before read: $before_read KiB"
24385
24386         lfs ladvise -a willread $DIR/$tfile ||
24387                 error "Ladvise willread failed"
24388         local after_read=$(facet_meminfo ost1 Cached)
24389         echo "Cache used after read: $after_read KiB"
24390
24391         lfs ladvise -a dontneed $DIR/$tfile ||
24392                 error "Ladvise dontneed again failed"
24393         local no_read=$(facet_meminfo ost1 Cached)
24394         echo "Cache used after dontneed ladvise: $no_read KiB"
24395
24396         if [ $total -lt $((before_read + kibibytes)) ]; then
24397                 echo "Memory is too small, abort checking"
24398                 return 0
24399         fi
24400
24401         if [ $((before_read + kibibytes)) -gt $after_read ]; then
24402                 error "Ladvise willread should use more memory" \
24403                         "than $kibibytes KiB"
24404         fi
24405
24406         if [ $((no_read + kibibytes)) -gt $after_read ]; then
24407                 error "Ladvise dontneed should release more memory" \
24408                         "than $kibibytes KiB"
24409         fi
24410 }
24411 run_test 255b "check 'lfs ladvise -a dontneed'"
24412
24413 test_255c() {
24414         [ $OST1_VERSION -lt $(version_code 2.10.50) ] &&
24415                 skip "lustre < 2.10.50 does not support lockahead"
24416
24417         local ost1_imp=$(get_osc_import_name client ost1)
24418         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
24419                          cut -d'.' -f2)
24420         local count
24421         local new_count
24422         local difference
24423         local i
24424         local rc
24425
24426         test_mkdir -p $DIR/$tdir
24427         $LFS setstripe -i 0 -c 1 $DIR/$tdir
24428
24429         #test 10 returns only success/failure
24430         i=10
24431         lockahead_test -d $DIR/$tdir -t $i -f $tfile
24432         rc=$?
24433         if [ $rc -eq 255 ]; then
24434                 error "Ladvise test${i} failed, ${rc}"
24435         fi
24436
24437         #test 11 counts lock enqueue requests, all others count new locks
24438         i=11
24439         count=$(do_facet ost1 \
24440                 $LCTL get_param -n ost.OSS.ost.stats)
24441         count=$(echo "$count" | grep ldlm_extent_enqueue | awk '{ print $2 }')
24442
24443         lockahead_test -d $DIR/$tdir -t $i -f $tfile
24444         rc=$?
24445         if [ $rc -eq 255 ]; then
24446                 error "Ladvise test${i} failed, ${rc}"
24447         fi
24448
24449         new_count=$(do_facet ost1 \
24450                 $LCTL get_param -n ost.OSS.ost.stats)
24451         new_count=$(echo "$new_count" | grep ldlm_extent_enqueue | \
24452                    awk '{ print $2 }')
24453
24454         difference="$((new_count - count))"
24455         if [ $difference -ne $rc ]; then
24456                 error "Ladvise test${i}, bad enqueue count, returned " \
24457                       "${rc}, actual ${difference}"
24458         fi
24459
24460         for i in $(seq 12 21); do
24461                 # If we do not do this, we run the risk of having too many
24462                 # locks and starting lock cancellation while we are checking
24463                 # lock counts.
24464                 cancel_lru_locks osc
24465
24466                 count=$($LCTL get_param -n \
24467                        ldlm.namespaces.$imp_name.lock_unused_count)
24468
24469                 lockahead_test -d $DIR/$tdir -t $i -f $tfile
24470                 rc=$?
24471                 if [ $rc -eq 255 ]; then
24472                         error "Ladvise test ${i} failed, ${rc}"
24473                 fi
24474
24475                 new_count=$($LCTL get_param -n \
24476                        ldlm.namespaces.$imp_name.lock_unused_count)
24477                 difference="$((new_count - count))"
24478
24479                 # Test 15 output is divided by 100 to map down to valid return
24480                 if [ $i -eq 15 ]; then
24481                         rc="$((rc * 100))"
24482                 fi
24483
24484                 if [ $difference -ne $rc ]; then
24485                         error "Ladvise test ${i}, bad lock count, returned " \
24486                               "${rc}, actual ${difference}"
24487                 fi
24488         done
24489
24490         #test 22 returns only success/failure
24491         i=22
24492         lockahead_test -d $DIR/$tdir -t $i -f $tfile
24493         rc=$?
24494         if [ $rc -eq 255 ]; then
24495                 error "Ladvise test${i} failed, ${rc}"
24496         fi
24497 }
24498 run_test 255c "suite of ladvise lockahead tests"
24499
24500 test_256() {
24501         [ $PARALLEL == "yes" ] && skip "skip parallel run"
24502         remote_mds_nodsh && skip "remote MDS with nodsh"
24503         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
24504         changelog_users $SINGLEMDS | grep "^cl" &&
24505                 skip "active changelog user"
24506
24507         local cl_user
24508         local cat_sl
24509         local mdt_dev
24510
24511         mdt_dev=$(facet_device $SINGLEMDS)
24512         echo $mdt_dev
24513
24514         changelog_register || error "changelog_register failed"
24515
24516         rm -rf $DIR/$tdir
24517         mkdir_on_mdt -i$(($(facet_number $SINGLEMDS) - 1)) $DIR/$tdir
24518
24519         changelog_clear 0 || error "changelog_clear failed"
24520
24521         # change something
24522         touch $DIR/$tdir/{1..10}
24523
24524         # stop the MDT
24525         stop $SINGLEMDS || error "Fail to stop MDT"
24526
24527         # remount the MDT
24528         start $SINGLEMDS $(facet_device $SINGLEMDS) $MDS_MOUNT_OPTS ||
24529                 error "Fail to start MDT"
24530
24531         #after mount new plainllog is used
24532         touch $DIR/$tdir/{11..19}
24533         local tmpfile="$(mktemp --tmpdir -u $tfile.XXXXXX)"
24534         stack_trap "rm -f $tmpfile"
24535         cat_sl=$(do_facet $SINGLEMDS "sync; \
24536                  $DEBUGFS -c -R 'dump changelog_catalog $tmpfile' $mdt_dev; \
24537                  llog_reader $tmpfile | grep -c type=1064553b")
24538         do_facet $SINGLEMDS llog_reader $tmpfile
24539
24540         [ $cat_sl != 2 ] && error "Changelog catalog has $cat_sl != 2 slots"
24541
24542         changelog_clear 0 || error "changelog_clear failed"
24543
24544         cat_sl=$(do_facet $SINGLEMDS "sync; \
24545                  $DEBUGFS -c -R 'dump changelog_catalog $tmpfile' $mdt_dev; \
24546                  llog_reader $tmpfile | grep -c type=1064553b")
24547
24548         if (( cat_sl == 2 )); then
24549                 error "Empty plain llog was not deleted from changelog catalog"
24550         elif (( cat_sl != 1 )); then
24551                 error "Active plain llog shouldn't be deleted from catalog"
24552         fi
24553 }
24554 run_test 256 "Check llog delete for empty and not full state"
24555
24556 test_257() {
24557         remote_mds_nodsh && skip "remote MDS with nodsh"
24558         [[ $MDS1_VERSION -lt $(version_code 2.8.55) ]] &&
24559                 skip "Need MDS version at least 2.8.55"
24560
24561         test_mkdir $DIR/$tdir
24562
24563         setfattr -n trusted.name1 -v value1 $DIR/$tdir ||
24564                 error "setfattr -n trusted.name1=value1 $DIR/$tdir failed"
24565         stat $DIR/$tdir
24566
24567 #define OBD_FAIL_MDS_XATTR_REP                  0x161
24568         local mdtidx=$($LFS getstripe -m $DIR/$tdir)
24569         local facet=mds$((mdtidx + 1))
24570         set_nodes_failloc $(facet_active_host $facet) 0x80000161
24571         getfattr -n trusted.name1 $DIR/$tdir 2> /dev/null
24572
24573         stop $facet || error "stop MDS failed"
24574         start $facet $(mdsdevname $((mdtidx + 1))) $MDS_MOUNT_OPTS ||
24575                 error "start MDS fail"
24576         wait_recovery_complete $facet
24577 }
24578 run_test 257 "xattr locks are not lost"
24579
24580 # Verify we take the i_mutex when security requires it
24581 test_258a() {
24582 #define OBD_FAIL_IMUTEX_SEC 0x141c
24583         $LCTL set_param fail_loc=0x141c
24584         touch $DIR/$tfile
24585         chmod u+s $DIR/$tfile
24586         chmod a+rwx $DIR/$tfile
24587         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 oflag=append
24588         RC=$?
24589         if [ $RC -ne 0 ]; then
24590                 error "error, failed to take i_mutex, rc=$?"
24591         fi
24592         rm -f $DIR/$tfile
24593 }
24594 run_test 258a "verify i_mutex security behavior when suid attributes is set"
24595
24596 # Verify we do NOT take the i_mutex in the normal case
24597 test_258b() {
24598 #define OBD_FAIL_IMUTEX_NOSEC 0x141d
24599         $LCTL set_param fail_loc=0x141d
24600         touch $DIR/$tfile
24601         chmod a+rwx $DIR
24602         chmod a+rw $DIR/$tfile
24603         $RUNAS dd if=/dev/zero of=$DIR/$tfile bs=4k count=1 oflag=append
24604         RC=$?
24605         if [ $RC -ne 0 ]; then
24606                 error "error, took i_mutex unnecessarily, rc=$?"
24607         fi
24608         rm -f $DIR/$tfile
24609
24610 }
24611 run_test 258b "verify i_mutex security behavior"
24612
24613 test_259() {
24614         local file=$DIR/$tfile
24615         local before
24616         local after
24617
24618         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
24619
24620         stack_trap "rm -f $file" EXIT
24621
24622         wait_delete_completed
24623         before=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
24624         echo "before: $before"
24625
24626         $LFS setstripe -i 0 -c 1 $file
24627         dd if=/dev/zero of=$file bs=1M count=10 || error "couldn't write"
24628         sync_all_data
24629         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
24630         echo "after write: $after"
24631
24632 #define OBD_FAIL_OSD_FAIL_AT_TRUNCATE          0x2301
24633         do_facet ost1 $LCTL set_param fail_loc=0x2301
24634         $TRUNCATE $file 0
24635         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
24636         echo "after truncate: $after"
24637
24638         stop ost1
24639         do_facet ost1 $LCTL set_param fail_loc=0
24640         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "cannot start ost1"
24641         sleep 2
24642         after=$(do_facet ost1 "$LCTL get_param -n osd-*.*OST0000.kbytesfree")
24643         echo "after restart: $after"
24644         [ $((after - before)) -ge $(fs_log_size ost1) ] &&
24645                 error "missing truncate?"
24646
24647         return 0
24648 }
24649 run_test 259 "crash at delayed truncate"
24650
24651 test_260() {
24652 #define OBD_FAIL_MDC_CLOSE               0x806
24653         $LCTL set_param fail_loc=0x80000806
24654         touch $DIR/$tfile
24655
24656 }
24657 run_test 260 "Check mdc_close fail"
24658
24659 ### Data-on-MDT sanity tests ###
24660 test_270a() {
24661         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24662                 skip "Need MDS version at least 2.10.55 for DoM"
24663
24664         # create DoM file
24665         local dom=$DIR/$tdir/dom_file
24666         local tmp=$DIR/$tdir/tmp_file
24667
24668         mkdir_on_mdt0 $DIR/$tdir
24669
24670         # basic checks for DoM component creation
24671         $LFS setstripe -E 1024K -E 2048K -L mdt $dom 2>/dev/null &&
24672                 error "Can set MDT layout to non-first entry"
24673
24674         $LFS setstripe -E 1024K -L mdt -E 2048K -L mdt $dom 2>/dev/null &&
24675                 error "Can define multiple entries as MDT layout"
24676
24677         $LFS setstripe -E 1M -L mdt $dom || error "Can't create DoM layout"
24678
24679         [ $($LFS getstripe -L $dom) == "mdt" ] || error "bad pattern"
24680         [ $($LFS getstripe -c $dom) == 0 ] || error "bad stripe count"
24681         [ $($LFS getstripe -S $dom) == 1048576 ] || error "bad stripe size"
24682
24683         local mdtidx=$($LFS getstripe -m $dom)
24684         local mdtname=MDT$(printf %04x $mdtidx)
24685         local facet=mds$((mdtidx + 1))
24686         local space_check=1
24687
24688         # Skip free space checks with ZFS
24689         [ "$(facet_fstype $facet)" == "zfs" ] && space_check=0
24690
24691         # write
24692         sync
24693         local size_tmp=$((65536 * 3))
24694         local mdtfree1=$(do_facet $facet \
24695                          lctl get_param -n osd*.*$mdtname.kbytesfree)
24696
24697         dd if=/dev/urandom of=$tmp bs=1024 count=$((size_tmp / 1024))
24698         # check also direct IO along write
24699         # IO size must be a multiple of PAGE_SIZE on all platforms (ARM=64KB)
24700         dd if=$tmp of=$dom bs=65536 count=$((size_tmp / 65536)) oflag=direct
24701         sync
24702         cmp $tmp $dom || error "file data is different"
24703         [ $(stat -c%s $dom) == $size_tmp ] ||
24704                 error "bad size after write: $(stat -c%s $dom) != $size_tmp"
24705         if [ $space_check == 1 ]; then
24706                 local mdtfree2=$(do_facet $facet \
24707                                  lctl get_param -n osd*.*$mdtname.kbytesfree)
24708
24709                 # increase in usage from by $size_tmp
24710                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_tmp / 1024)) ] ||
24711                         error "MDT free space wrong after write: " \
24712                               "$mdtfree1 >= $mdtfree2 + $size_tmp/1024"
24713         fi
24714
24715         # truncate
24716         local size_dom=10000
24717
24718         $TRUNCATE $dom $size_dom
24719         [ $(stat -c%s $dom) == $size_dom ] ||
24720                 error "bad size after truncate: $(stat -c%s $dom) != $size_dom"
24721         if [ $space_check == 1 ]; then
24722                 mdtfree1=$(do_facet $facet \
24723                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
24724                 # decrease in usage from $size_tmp to new $size_dom
24725                 [ $(($mdtfree1 - $mdtfree2)) -ge \
24726                   $(((size_tmp - size_dom) / 1024)) ] ||
24727                         error "MDT free space is wrong after truncate: " \
24728                               "$mdtfree1 >= $mdtfree2 + ($size_tmp - $size_dom) / 1024"
24729         fi
24730
24731         # append
24732         cat $tmp >> $dom
24733         sync
24734         size_dom=$((size_dom + size_tmp))
24735         [ $(stat -c%s $dom) == $size_dom ] ||
24736                 error "bad size after append: $(stat -c%s $dom) != $size_dom"
24737         if [ $space_check == 1 ]; then
24738                 mdtfree2=$(do_facet $facet \
24739                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
24740                 # increase in usage by $size_tmp from previous
24741                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_tmp / 1024)) ] ||
24742                         error "MDT free space is wrong after append: " \
24743                               "$mdtfree1 >= $mdtfree2 + $size_tmp/1024"
24744         fi
24745
24746         # delete
24747         rm $dom
24748         if [ $space_check == 1 ]; then
24749                 mdtfree1=$(do_facet $facet \
24750                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
24751                 # decrease in usage by $size_dom from previous
24752                 [ $(($mdtfree1 - $mdtfree2)) -ge $((size_dom / 1024)) ] ||
24753                         error "MDT free space is wrong after removal: " \
24754                               "$mdtfree1 >= $mdtfree2 + $size_dom/1024"
24755         fi
24756
24757         # combined striping
24758         $LFS setstripe -E 1024K -L mdt -E EOF $dom ||
24759                 error "Can't create DoM + OST striping"
24760
24761         size_tmp=2031616 # must be a multiple of PAGE_SIZE=65536 on ARM
24762         dd if=/dev/urandom of=$tmp bs=1024 count=$((size_tmp / 1024))
24763         # check also direct IO along write
24764         dd if=$tmp of=$dom bs=65536 count=$((size_tmp / 65536)) oflag=direct
24765         sync
24766         cmp $tmp $dom || error "file data is different"
24767         [ $(stat -c%s $dom) == $size_tmp ] ||
24768                 error "bad size after write: $(stat -c%s $dom) != $size_tmp"
24769         rm $dom $tmp
24770
24771         return 0
24772 }
24773 run_test 270a "DoM: basic functionality tests"
24774
24775 test_270b() {
24776         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24777                 skip "Need MDS version at least 2.10.55"
24778
24779         local dom=$DIR/$tdir/dom_file
24780         local max_size=1048576
24781
24782         mkdir -p $DIR/$tdir
24783         $LFS setstripe -E $max_size -L mdt $dom
24784
24785         # truncate over the limit
24786         $TRUNCATE $dom $(($max_size + 1)) &&
24787                 error "successful truncate over the maximum size"
24788         # write over the limit
24789         dd if=/dev/zero of=$dom bs=$max_size seek=1 count=1 &&
24790                 error "successful write over the maximum size"
24791         # append over the limit
24792         dd if=/dev/zero of=$dom bs=$(($max_size - 3)) count=1
24793         echo "12345" >> $dom && error "successful append over the maximum size"
24794         rm $dom
24795
24796         return 0
24797 }
24798 run_test 270b "DoM: maximum size overflow checks for DoM-only file"
24799
24800 test_270c() {
24801         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24802                 skip "Need MDS version at least 2.10.55"
24803
24804         mkdir -p $DIR/$tdir
24805         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
24806
24807         # check files inherit DoM EA
24808         touch $DIR/$tdir/first
24809         [ $($LFS getstripe -L $DIR/$tdir/first) == "mdt" ] ||
24810                 error "bad pattern"
24811         [ $($LFS getstripe -c $DIR/$tdir/first) == 0 ] ||
24812                 error "bad stripe count"
24813         [ $($LFS getstripe -S $DIR/$tdir/first) == 1048576 ] ||
24814                 error "bad stripe size"
24815
24816         # check directory inherits DoM EA and uses it as default
24817         mkdir $DIR/$tdir/subdir
24818         touch $DIR/$tdir/subdir/second
24819         [ $($LFS getstripe -L $DIR/$tdir/subdir/second) == "mdt" ] ||
24820                 error "bad pattern in sub-directory"
24821         [ $($LFS getstripe -c $DIR/$tdir/subdir/second) == 0 ] ||
24822                 error "bad stripe count in sub-directory"
24823         [ $($LFS getstripe -S $DIR/$tdir/subdir/second) == 1048576 ] ||
24824                 error "bad stripe size in sub-directory"
24825         return 0
24826 }
24827 run_test 270c "DoM: DoM EA inheritance tests"
24828
24829 test_270d() {
24830         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24831                 skip "Need MDS version at least 2.10.55"
24832
24833         mkdir -p $DIR/$tdir
24834         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
24835
24836         # inherit default DoM striping
24837         mkdir $DIR/$tdir/subdir
24838         touch $DIR/$tdir/subdir/f1
24839
24840         # change default directory striping
24841         $LFS setstripe -c 1 $DIR/$tdir/subdir
24842         touch $DIR/$tdir/subdir/f2
24843         [ $($LFS getstripe -c $DIR/$tdir/subdir/f2) == 1 ] ||
24844                 error "wrong default striping in file 2"
24845         [ $($LFS getstripe -L $DIR/$tdir/subdir/f2) == "raid0" ] ||
24846                 error "bad pattern in file 2"
24847         return 0
24848 }
24849 run_test 270d "DoM: change striping from DoM to RAID0"
24850
24851 test_270e() {
24852         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24853                 skip "Need MDS version at least 2.10.55"
24854
24855         mkdir -p $DIR/$tdir/dom
24856         mkdir -p $DIR/$tdir/norm
24857         DOMFILES=20
24858         NORMFILES=10
24859         $LFS setstripe -E 1M -L mdt $DIR/$tdir/dom
24860         $LFS setstripe -i 0 -S 2M $DIR/$tdir/norm
24861
24862         createmany -o $DIR/$tdir/dom/dom- $DOMFILES
24863         createmany -o $DIR/$tdir/norm/norm- $NORMFILES
24864
24865         # find DoM files by layout
24866         NUM=$($LFS find -L mdt -type f $DIR/$tdir 2>/dev/null | wc -l)
24867         [ $NUM -eq  $DOMFILES ] ||
24868                 error "lfs find -L: found $NUM, expected $DOMFILES"
24869         echo "Test 1: lfs find 20 DOM files by layout: OK"
24870
24871         # there should be 1 dir with default DOM striping
24872         NUM=$($LFS find -L mdt -type d $DIR/$tdir 2>/dev/null | wc -l)
24873         [ $NUM -eq  1 ] ||
24874                 error "lfs find -L: found $NUM, expected 1 dir"
24875         echo "Test 2: lfs find 1 DOM dir by layout: OK"
24876
24877         # find DoM files by stripe size
24878         NUM=$($LFS find -S -1200K -type f $DIR/$tdir 2>/dev/null | wc -l)
24879         [ $NUM -eq  $DOMFILES ] ||
24880                 error "lfs find -S: found $NUM, expected $DOMFILES"
24881         echo "Test 4: lfs find 20 DOM files by stripe size: OK"
24882
24883         # find files by stripe offset except DoM files
24884         NUM=$($LFS find -i 0 -type f $DIR/$tdir 2>/dev/null | wc -l)
24885         [ $NUM -eq  $NORMFILES ] ||
24886                 error "lfs find -i: found $NUM, expected $NORMFILES"
24887         echo "Test 5: lfs find no DOM files by stripe index: OK"
24888         return 0
24889 }
24890 run_test 270e "DoM: lfs find with DoM files test"
24891
24892 test_270f() {
24893         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
24894                 skip "Need MDS version at least 2.10.55"
24895
24896         local mdtname=${FSNAME}-MDT0000-mdtlov
24897         local dom=$DIR/$tdir/dom_file
24898         local dom_limit_saved=$(do_facet mds1 $LCTL get_param -n \
24899                                                 lod.$mdtname.dom_stripesize)
24900         local dom_limit=131072
24901
24902         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=$dom_limit
24903         local dom_current=$(do_facet mds1 $LCTL get_param -n \
24904                                                 lod.$mdtname.dom_stripesize)
24905         [ ${dom_limit} -eq ${dom_current} ] ||
24906                 error "Cannot change per-MDT DoM stripe limit to $dom_limit"
24907
24908         $LFS mkdir -i 0 -c 1 $DIR/$tdir
24909         $LFS setstripe -d $DIR/$tdir
24910         $LFS setstripe -E $dom_limit -L mdt $DIR/$tdir ||
24911                 error "Can't set directory default striping"
24912
24913         # exceed maximum stripe size
24914         $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom ||
24915                 error "Can't create file with $((dom_limit * 2)) DoM stripe"
24916         [ $($LFS getstripe -S $dom) -eq $((dom_limit * 2)) ] &&
24917                 error "Able to create DoM component size more than LOD limit"
24918
24919         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=0
24920         dom_current=$(do_facet mds1 $LCTL get_param -n \
24921                                                 lod.$mdtname.dom_stripesize)
24922         [ 0 -eq ${dom_current} ] ||
24923                 error "Can't set zero DoM stripe limit"
24924         rm $dom
24925
24926         # attempt to create DoM file on server with disabled DoM should
24927         # remove DoM entry from layout and be succeed
24928         $LFS setstripe -E $dom_limit -L mdt -E -1 $dom ||
24929                 error "Can't create DoM file (DoM is disabled)"
24930         [ $($LFS getstripe -L $dom) == "mdt" ] &&
24931                 error "File has DoM component while DoM is disabled"
24932         rm $dom
24933
24934         # attempt to create DoM file with only DoM stripe should return error
24935         $LFS setstripe -E $dom_limit -L mdt $dom &&
24936                 error "Able to create DoM-only file while DoM is disabled"
24937
24938         # too low values to be aligned with smallest stripe size 64K
24939         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=30000
24940         dom_current=$(do_facet mds1 $LCTL get_param -n \
24941                                                 lod.$mdtname.dom_stripesize)
24942         [ 30000 -eq ${dom_current} ] &&
24943                 error "Can set too small DoM stripe limit"
24944
24945         # 64K is a minimal stripe size in Lustre, expect limit of that size
24946         [ 65536 -eq ${dom_current} ] ||
24947                 error "Limit is not set to 64K but ${dom_current}"
24948
24949         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=2147483648
24950         dom_current=$(do_facet mds1 $LCTL get_param -n \
24951                                                 lod.$mdtname.dom_stripesize)
24952         echo $dom_current
24953         [ 2147483648 -eq ${dom_current} ] &&
24954                 error "Can set too large DoM stripe limit"
24955
24956         do_facet mds1 $LCTL set_param -n \
24957                                 lod.$mdtname.dom_stripesize=$((dom_limit * 2))
24958         $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom ||
24959                 error "Can't create DoM component size after limit change"
24960         do_facet mds1 $LCTL set_param -n \
24961                                 lod.$mdtname.dom_stripesize=$((dom_limit / 2))
24962         $LFS setstripe -E $dom_limit -L mdt ${dom}_big ||
24963                 error "Can't create DoM file after limit decrease"
24964         [ $($LFS getstripe -S ${dom}_big) -eq $((dom_limit / 2)) ] ||
24965                 error "Can create big DoM component after limit decrease"
24966         touch ${dom}_def ||
24967                 error "Can't create file with old default layout"
24968
24969         do_facet mds1 $LCTL set_param -n lod.*.dom_stripesize=$dom_limit_saved
24970         return 0
24971 }
24972 run_test 270f "DoM: maximum DoM stripe size checks"
24973
24974 test_270g() {
24975         [ $MDS1_VERSION -ge $(version_code 2.13.52) ] ||
24976                 skip "Need MDS version at least 2.13.52"
24977         local dom=$DIR/$tdir/$tfile
24978
24979         $LFS mkdir -i 0 -c 1 $DIR/$tdir
24980         local lodname=${FSNAME}-MDT0000-mdtlov
24981
24982         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
24983         save_lustre_params mds1 "lod.${lodname}.dom_stripesize_max_kb" > $save
24984         save_lustre_params mds1 "lod.${lodname}.dom_threshold_free_mb" >> $save
24985         stack_trap "restore_lustre_params < $save; rm -f $save" EXIT
24986
24987         local dom_limit=1024
24988         local dom_threshold="50%"
24989
24990         $LFS setstripe -d $DIR/$tdir
24991         $LFS setstripe -E ${dom_limit}K -L mdt $DIR/$tdir ||
24992                 error "Can't set directory default striping"
24993
24994         do_facet mds1 $LCTL set_param -n \
24995                                 lod.${lodname}.dom_stripesize_max_kb=$dom_limit
24996         # set 0 threshold and create DOM file to change tunable stripesize
24997         do_facet mds1 $LCTL set_param -n lod.${lodname}.dom_threshold_free_mb=0
24998         $LFS setstripe -E ${dom_limit}K -L mdt -E -1 $dom ||
24999                 error "Failed to create $dom file"
25000         # now tunable dom_cur_stripesize should reach maximum
25001         local dom_current=$(do_facet mds1 $LCTL get_param -n \
25002                                         lod.${lodname}.dom_stripesize_cur_kb)
25003         [[ $dom_current == $dom_limit ]] ||
25004                 error "Current DOM stripesize is not maximum"
25005         rm $dom
25006
25007         # set threshold for further tests
25008         do_facet mds1 $LCTL set_param -n \
25009                         lod.${lodname}.dom_threshold_free_mb=$dom_threshold
25010         echo "DOM threshold is $dom_threshold free space"
25011         local dom_def
25012         local dom_set
25013         # Spoof bfree to exceed threshold
25014         #define OBD_FAIL_MDS_STATFS_SPOOF   0x168
25015         do_facet mds1 $LCTL set_param -n fail_loc=0x0168
25016         for spfree in 40 20 0 15 30 55; do
25017                 do_facet mds1 $LCTL set_param -n fail_val=$spfree
25018                 $LFS setstripe -E ${dom_limit}K -L mdt -E -1 $dom ||
25019                         error "Failed to create $dom file"
25020                 dom_def=$(do_facet mds1 $LCTL get_param -n \
25021                                         lod.${lodname}.dom_stripesize_cur_kb)
25022                 echo "Free space: ${spfree}%, default DOM stripe: ${dom_def}K"
25023                 [[ $dom_def != $dom_current ]] ||
25024                         error "Default stripe size was not changed"
25025                 if (( spfree > 0 )) ; then
25026                         dom_set=$($LFS getstripe -S $dom)
25027                         (( dom_set == dom_def * 1024 )) ||
25028                                 error "DOM component size is still old"
25029                 else
25030                         [[ $($LFS getstripe -L $dom) != "mdt" ]] ||
25031                                 error "DoM component is set with no free space"
25032                 fi
25033                 rm $dom
25034                 dom_current=$dom_def
25035         done
25036 }
25037 run_test 270g "DoM: default DoM stripe size depends on free space"
25038
25039 test_270h() {
25040         [[ $MDS1_VERSION -ge $(version_code 2.13.53) ]] ||
25041                 skip "Need MDS version at least 2.13.53"
25042
25043         local mdtname=${FSNAME}-MDT0000-mdtlov
25044         local dom=$DIR/$tdir/$tfile
25045         local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
25046
25047         save_lustre_params mds1 "lod.*.dom_stripesize" > $save
25048         stack_trap "restore_lustre_params < $save; rm -f $save" EXIT
25049
25050         $LFS mkdir -i 0 -c 1 $DIR/$tdir
25051         $LFS setstripe -E 1M -c1  -E -1 -c2 ${dom}_1 ||
25052                 error "can't create OST file"
25053         # mirrored file with DOM entry in the second mirror
25054         $LFS mirror extend -N -E 1M -L mdt -E eof -c2 ${dom}_1 ||
25055                 error "can't create mirror with DoM component"
25056
25057         do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=0
25058
25059         # DOM component in the middle and has other enries in the same mirror,
25060         # should succeed but lost DoM component
25061         $LFS setstripe --copy=${dom}_1 $dom ||
25062                 error "Can't create file from OST|DOM mirror layout"
25063         # check new file has no DoM layout after all
25064         [[ $($LFS getstripe -L $dom) != "mdt" ]] ||
25065                 error "File has DoM component while DoM is disabled"
25066 }
25067 run_test 270h "DoM: DoM stripe removal when disabled on server"
25068
25069 test_270i() {
25070         (( $MDS1_VERSION >= $(version_code 2.14.54) )) ||
25071                 skip "Need MDS version at least 2.14.54"
25072
25073         mkdir $DIR/$tdir
25074         # DoM with plain layout
25075         $LFS setstripe -L mdt -S 128k -c -1 $DIR/$tdir &&
25076                 error "default plain layout with DoM must fail"
25077         $LFS setstripe -L mdt -S 128k -c -1 $DIR/$tdir/$tfile &&
25078                 error "setstripe plain file layout with DoM must fail"
25079         $LFS setstripe -E 1M -L mdt -S 128k -c -1 -E eof $DIR/$tdir &&
25080                 error "default DoM layout with bad striping must fail"
25081         $LFS setstripe -E 1M -L mdt -S 128k -c -1 -E eof $DIR/$tdir/$tfile &&
25082                 error "setstripe to DoM layout with bad striping must fail"
25083         return 0
25084 }
25085 run_test 270i "DoM: setting invalid DoM striping should fail"
25086
25087 test_270j() {
25088         (( $MDS1_VERSION >= $(version_code 2.15.55.203) )) ||
25089                 skip "Need MDS version at least 2.15.55.203"
25090
25091         local dom=$DIR/$tdir/$tfile
25092         local odv
25093         local ndv
25094
25095         mkdir -p $DIR/$tdir
25096
25097         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
25098
25099         odv=$($LFS data_version $dom)
25100         chmod 666 $dom
25101         mv $dom ${dom}_moved
25102         link ${dom}_moved $dom
25103         setfattr -n user.attrx -v "some_attr" $dom
25104         ndv=$($LFS data_version $dom)
25105         (( $ndv == $odv )) ||
25106                 error "data version was changed by metadata operations"
25107
25108         dd if=/dev/urandom of=$dom bs=1M count=1 ||
25109                 error "failed to write data into $dom"
25110         cancel_lru_locks mdc
25111         ndv=$($LFS data_version $dom)
25112         (( $ndv != $odv )) ||
25113                 error "data version wasn't changed on write"
25114
25115         odv=$ndv
25116         $TRUNCATE $dom 1000 || error "failed to truncate $dom"
25117         ndv=$($LFS data_version $dom)
25118         (( $ndv != $odv )) ||
25119                 error "data version wasn't changed on truncate down"
25120
25121         odv=$ndv
25122         $TRUNCATE $dom 25000
25123         ndv=$($LFS data_version $dom)
25124         (( $ndv != $odv )) ||
25125                 error "data version wasn't changed on truncate up"
25126
25127         # check also fallocate for ldiskfs
25128         if [[ "$mds1_FSTYPE" == ldiskfs ]]; then
25129                 odv=$ndv
25130                 fallocate -l 1048576 $dom
25131                 ndv=$($LFS data_version $dom)
25132                 (( $ndv != $odv )) ||
25133                         error "data version wasn't changed on fallocate"
25134
25135                 odv=$ndv
25136                 fallocate -p --offset 4096 -l 4096 $dom
25137                 ndv=$($LFS data_version $dom)
25138                 (( $ndv != $odv )) ||
25139                         error "data version wasn't changed on fallocate punch"
25140         fi
25141 }
25142 run_test 270j "DoM migration: DOM file to the OST-striped file (plain)"
25143
25144 test_271a() {
25145         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
25146                 skip "Need MDS version at least 2.10.55"
25147
25148         local dom=$DIR/$tdir/dom
25149
25150         mkdir -p $DIR/$tdir
25151
25152         $LFS setstripe -E 1024K -L mdt $dom
25153
25154         lctl set_param -n mdc.*.stats=clear
25155         dd if=/dev/zero of=$dom bs=4096 count=1 || return 1
25156         cat $dom > /dev/null
25157         local reads=$(lctl get_param -n mdc.*.stats | grep -c ost_read)
25158         [ $reads -eq 0 ] || error "Unexpected $reads READ RPCs"
25159         ls $dom
25160         rm -f $dom
25161 }
25162 run_test 271a "DoM: data is cached for read after write"
25163
25164 test_271b() {
25165         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
25166                 skip "Need MDS version at least 2.10.55"
25167
25168         local dom=$DIR/$tdir/dom
25169
25170         mkdir -p $DIR/$tdir
25171
25172         $LFS setstripe -E 1024K -L mdt -E EOF $dom
25173
25174         lctl set_param -n mdc.*.stats=clear
25175         dd if=/dev/zero of=$dom bs=4096 count=1 || return 1
25176         cancel_lru_locks mdc
25177         $CHECKSTAT -t file -s 4096 $dom || error "stat #1 fails"
25178         # second stat to check size is cached on client
25179         $CHECKSTAT -t file -s 4096 $dom || error "stat #2 fails"
25180         local gls=$(lctl get_param -n mdc.*.stats | grep -c ldlm_glimpse)
25181         [ $gls -eq 0 ] || error "Unexpected $gls glimpse RPCs"
25182         rm -f $dom
25183 }
25184 run_test 271b "DoM: no glimpse RPC for stat (DoM only file)"
25185
25186 test_271ba() {
25187         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
25188                 skip "Need MDS version at least 2.10.55"
25189
25190         local dom=$DIR/$tdir/dom
25191
25192         mkdir -p $DIR/$tdir
25193
25194         $LFS setstripe -E 1024K -L mdt -E EOF $dom
25195
25196         lctl set_param -n mdc.*.stats=clear
25197         lctl set_param -n osc.*.stats=clear
25198         dd if=/dev/zero of=$dom bs=2048K count=1 || return 1
25199         cancel_lru_locks mdc
25200         $CHECKSTAT -t file -s 2097152 $dom || error "stat"
25201         # second stat to check size is cached on client
25202         $CHECKSTAT -t file -s 2097152 $dom || error "stat"
25203         local gls=$(lctl get_param -n mdc.*.stats | grep -c ldlm_glimpse)
25204         [ $gls == 0 ] || error "Unexpected $gls glimpse RPCs"
25205         local gls=$(lctl get_param -n osc.*.stats | grep -c ldlm_glimpse)
25206         [ $gls == 0 ] || error "Unexpected $gls OSC glimpse RPCs"
25207         rm -f $dom
25208 }
25209 run_test 271ba "DoM: no glimpse RPC for stat (combined file)"
25210
25211
25212 get_mdc_stats() {
25213         local mdtidx=$1
25214         local param=$2
25215         local mdt=MDT$(printf %04x $mdtidx)
25216
25217         if [ -z $param ]; then
25218                 lctl get_param -n mdc.*$mdt*.stats
25219         else
25220                 lctl get_param -n mdc.*$mdt*.stats | awk "/$param/"'{print $2}'
25221         fi
25222 }
25223
25224 test_271c() {
25225         [ $MDS1_VERSION -lt $(version_code 2.10.55) ] &&
25226                 skip "Need MDS version at least 2.10.55"
25227
25228         local dom=$DIR/$tdir/dom
25229
25230         mkdir -p $DIR/$tdir
25231
25232         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
25233
25234         local mdtidx=$($LFS getstripe -m $DIR/$tdir)
25235         local facet=mds$((mdtidx + 1))
25236
25237         cancel_lru_locks mdc
25238         do_facet $facet lctl set_param -n mdt.*.dom_lock=0
25239         createmany -o $dom 1000
25240         lctl set_param -n mdc.*.stats=clear
25241         smalliomany -w $dom 1000 200
25242         get_mdc_stats $mdtidx
25243         local enq=$(get_mdc_stats $mdtidx ldlm_ibits_enqueue)
25244         # Each file has 1 open, 1 IO enqueues, total 2000
25245         # but now we have also +1 getxattr for security.capability, total 3000
25246         [ $enq -ge 2000 ] || error "Too few enqueues $enq, expected > 2000"
25247         unlinkmany $dom 1000
25248
25249         cancel_lru_locks mdc
25250         do_facet $facet lctl set_param -n mdt.*.dom_lock=1
25251         createmany -o $dom 1000
25252         lctl set_param -n mdc.*.stats=clear
25253         smalliomany -w $dom 1000 200
25254         local enq_2=$(get_mdc_stats $mdtidx ldlm_ibits_enqueue)
25255         # Expect to see reduced amount of RPCs by 1000 due to single enqueue
25256         # for OPEN and IO lock.
25257         [ $((enq - enq_2)) -ge 1000 ] ||
25258                 error "Too many enqueues $enq_2, expected about $((enq - 1000))"
25259         unlinkmany $dom 1000
25260         return 0
25261 }
25262 run_test 271c "DoM: IO lock at open saves enqueue RPCs"
25263
25264 cleanup_271def_tests() {
25265         trap 0
25266         rm -f $1
25267 }
25268
25269 test_271d() {
25270         [ $MDS1_VERSION -lt $(version_code 2.10.57) ] &&
25271                 skip "Need MDS version at least 2.10.57"
25272
25273         local dom=$DIR/$tdir/dom
25274         local tmp=$TMP/$tfile
25275         trap "cleanup_271def_tests $tmp" EXIT
25276
25277         mkdir -p $DIR/$tdir
25278
25279         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
25280
25281         local mdtidx=$($LFS getstripe --mdt-index $DIR/$tdir)
25282
25283         cancel_lru_locks mdc
25284         dd if=/dev/urandom of=$tmp bs=1000 count=1
25285         dd if=$tmp of=$dom bs=1000 count=1
25286         cancel_lru_locks mdc
25287
25288         cat /etc/hosts >> $tmp
25289         lctl set_param -n mdc.*.stats=clear
25290
25291         # append data to the same file it should update local page
25292         echo "Append to the same page"
25293         cat /etc/hosts >> $dom
25294         local num=$(get_mdc_stats $mdtidx ost_read)
25295         local ra=$(get_mdc_stats $mdtidx req_active)
25296         local rw=$(get_mdc_stats $mdtidx req_waittime)
25297
25298         [ -z $num ] || error "$num READ RPC occured"
25299         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
25300         echo "... DONE"
25301
25302         # compare content
25303         cmp $tmp $dom || error "file miscompare"
25304
25305         cancel_lru_locks mdc
25306         lctl set_param -n mdc.*.stats=clear
25307
25308         echo "Open and read file"
25309         cat $dom > /dev/null
25310         local num=$(get_mdc_stats $mdtidx ost_read)
25311         local ra=$(get_mdc_stats $mdtidx req_active)
25312         local rw=$(get_mdc_stats $mdtidx req_waittime)
25313
25314         [ -z $num ] || error "$num READ RPC occured"
25315         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
25316         echo "... DONE"
25317
25318         # compare content
25319         cmp $tmp $dom || error "file miscompare"
25320
25321         return 0
25322 }
25323 run_test 271d "DoM: read on open (1K file in reply buffer)"
25324
25325 test_271f() {
25326         [ $MDS1_VERSION -lt $(version_code 2.10.57) ] &&
25327                 skip "Need MDS version at least 2.10.57"
25328
25329         local dom=$DIR/$tdir/dom
25330         local tmp=$TMP/$tfile
25331         trap "cleanup_271def_tests $tmp" EXIT
25332
25333         mkdir -p $DIR/$tdir
25334
25335         $LFS setstripe -E 1024K -L mdt $DIR/$tdir
25336
25337         local mdtidx=$($LFS getstripe --mdt-index $DIR/$tdir)
25338
25339         cancel_lru_locks mdc
25340         dd if=/dev/urandom of=$tmp bs=265000 count=1
25341         dd if=$tmp of=$dom bs=265000 count=1
25342         cancel_lru_locks mdc
25343         cat /etc/hosts >> $tmp
25344         lctl set_param -n mdc.*.stats=clear
25345
25346         echo "Append to the same page"
25347         cat /etc/hosts >> $dom
25348         local num=$(get_mdc_stats $mdtidx ost_read)
25349         local ra=$(get_mdc_stats $mdtidx req_active)
25350         local rw=$(get_mdc_stats $mdtidx req_waittime)
25351
25352         [ -z $num ] || error "$num READ RPC occured"
25353         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
25354         echo "... DONE"
25355
25356         # compare content
25357         cmp $tmp $dom || error "file miscompare"
25358
25359         cancel_lru_locks mdc
25360         lctl set_param -n mdc.*.stats=clear
25361
25362         echo "Open and read file"
25363         cat $dom > /dev/null
25364         local num=$(get_mdc_stats $mdtidx ost_read)
25365         local ra=$(get_mdc_stats $mdtidx req_active)
25366         local rw=$(get_mdc_stats $mdtidx req_waittime)
25367
25368         [ -z $num ] && num=0
25369         [ $num -eq 1 ] || error "expect 1 READ RPC, $num occured"
25370         [ $ra == $rw ] || error "$((ra - rw)) resend occured"
25371         echo "... DONE"
25372
25373         # compare content
25374         cmp $tmp $dom || error "file miscompare"
25375
25376         return 0
25377 }
25378 run_test 271f "DoM: read on open (200K file and read tail)"
25379
25380 test_271g() {
25381         [[ $($LCTL get_param mdc.*.import) =~ async_discard ]] ||
25382                 skip "Skipping due to old client or server version"
25383
25384         $LFS setstripe -E 1024K -L mdt -E EOF $DIR1/$tfile
25385         # to get layout
25386         $CHECKSTAT -t file $DIR1/$tfile
25387
25388         $MULTIOP $DIR1/$tfile Ow40960_w4096c &
25389         MULTIOP_PID=$!
25390         sleep 1
25391         #define OBD_FAIL_LDLM_CANCEL_BL_CB_RACE
25392         $LCTL set_param fail_loc=0x80000314
25393         rm $DIR1/$tfile || error "Unlink fails"
25394         RC=$?
25395         kill -USR1 $MULTIOP_PID && wait $MULTIOP_PID || error "multiop failure"
25396         [ $RC -eq 0 ] || error "Failed write to stale object"
25397 }
25398 run_test 271g "Discard DoM data vs client flush race"
25399
25400 test_272a() {
25401         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
25402                 skip "Need MDS version at least 2.11.50"
25403
25404         local dom=$DIR/$tdir/dom
25405         mkdir -p $DIR/$tdir
25406
25407         $LFS setstripe -E 256K -L mdt -E -1 -c1 $dom
25408         dd if=/dev/urandom of=$dom bs=512K count=1 ||
25409                 error "failed to write data into $dom"
25410         local old_md5=$(md5sum $dom)
25411
25412         $LFS migrate -E 256K -L mdt -E -1 -c2 $dom ||
25413                 error "failed to migrate to the same DoM component"
25414
25415         local new_md5=$(md5sum $dom)
25416
25417         [ "$old_md5" == "$new_md5" ] ||
25418                 error "md5sum differ: $old_md5, $new_md5"
25419
25420         [ $($LFS getstripe -c $dom) -eq 2 ] ||
25421                 error "bad final stripe count: $($LFS getstripe -c $dom) != 2"
25422 }
25423 run_test 272a "DoM migration: new layout with the same DOM component"
25424
25425 test_272b() {
25426         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
25427                 skip "Need MDS version at least 2.11.50"
25428
25429         local dom=$DIR/$tdir/dom
25430         mkdir -p $DIR/$tdir
25431         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
25432         stack_trap "rm -rf $DIR/$tdir"
25433
25434         local mdtidx=$($LFS getstripe -m $dom)
25435         local mdtname=MDT$(printf %04x $mdtidx)
25436         local facet=mds$((mdtidx + 1))
25437
25438         local mdtfree1=$(do_facet $facet \
25439                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25440         dd if=/dev/urandom of=$dom bs=2M count=1 ||
25441                 error "failed to write data into $dom"
25442         local old_md5=$(md5sum $dom)
25443         cancel_lru_locks mdc
25444         local mdtfree1=$(do_facet $facet \
25445                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25446
25447         $LFS migrate -c2 $dom ||
25448                 error "failed to migrate to the new composite layout"
25449         [[ $($LFS getstripe --component-start=0 -L $dom) != 'mdt' ]] ||
25450                 error "MDT stripe was not removed"
25451         ! getfattr -n trusted.dataver $dom &> /dev/null ||
25452                 error "$dir1 shouldn't have DATAVER EA"
25453
25454         cancel_lru_locks mdc
25455         local new_md5=$(md5sum $dom)
25456         [ "$old_md5" == "$new_md5" ] ||
25457                 error "$old_md5 != $new_md5"
25458
25459         # Skip free space checks with ZFS
25460         if [ "$(facet_fstype $facet)" != "zfs" ]; then
25461                 local mdtfree2=$(do_facet $facet \
25462                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25463                 [ $mdtfree2 -gt $mdtfree1 ] ||
25464                         error "MDT space is not freed after migration"
25465         fi
25466         return 0
25467 }
25468 run_test 272b "DoM migration: DOM file to the OST-striped file (plain)"
25469
25470 test_272c() {
25471         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
25472                 skip "Need MDS version at least 2.11.50"
25473
25474         local dom=$DIR/$tdir/$tfile
25475         mkdir -p $DIR/$tdir
25476         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
25477         stack_trap "rm -rf $DIR/$tdir"
25478
25479         local mdtidx=$($LFS getstripe -m $dom)
25480         local mdtname=MDT$(printf %04x $mdtidx)
25481         local facet=mds$((mdtidx + 1))
25482
25483         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
25484                 error "failed to write data into $dom"
25485         local old_md5=$(md5sum $dom)
25486         cancel_lru_locks mdc
25487         local mdtfree1=$(do_facet $facet \
25488                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25489
25490         $LFS migrate -E 2M -c1 -E -1 -c2 $dom ||
25491                 error "failed to migrate to the new composite layout"
25492         [[ $($LFS getstripe --component-start=0 -L $dom) != 'mdt' ]] ||
25493                 error "MDT stripe was not removed"
25494
25495         cancel_lru_locks mdc
25496         local new_md5=$(md5sum $dom)
25497         [ "$old_md5" == "$new_md5" ] ||
25498                 error "$old_md5 != $new_md5"
25499
25500         # Skip free space checks with ZFS
25501         if [ "$(facet_fstype $facet)" != "zfs" ]; then
25502                 local mdtfree2=$(do_facet $facet \
25503                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25504                 [ $mdtfree2 -gt $mdtfree1 ] ||
25505                         error "MDS space is not freed after migration"
25506         fi
25507         return 0
25508 }
25509 run_test 272c "DoM migration: DOM file to the OST-striped file (composite)"
25510
25511 test_272d() {
25512         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
25513                 skip "Need MDS version at least 2.12.55"
25514
25515         local dom=$DIR/$tdir/$tfile
25516         mkdir -p $DIR/$tdir
25517         $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
25518
25519         local mdtidx=$($LFS getstripe -m $dom)
25520         local mdtname=MDT$(printf %04x $mdtidx)
25521         local facet=mds$((mdtidx + 1))
25522
25523         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
25524                 error "failed to write data into $dom"
25525         local old_md5=$(md5sum $dom)
25526         cancel_lru_locks mdc
25527         local mdtfree1=$(do_facet $facet \
25528                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25529
25530         $LFS mirror extend -N -E 2M -c1 -E -1 -c2 $dom ||
25531                 error "failed mirroring to the new composite layout"
25532         $LFS mirror resync $dom ||
25533                 error "failed mirror resync"
25534         $LFS mirror split --mirror-id 1 -d $dom ||
25535                 error "failed mirror split"
25536
25537         [ $($LFS getstripe -L $dom) != 'mdt' ] ||
25538                 error "MDT stripe was not removed"
25539
25540         cancel_lru_locks mdc
25541         local new_md5=$(md5sum $dom)
25542         [ "$old_md5" == "$new_md5" ] ||
25543                 error "$old_md5 != $new_md5"
25544
25545         # Skip free space checks with ZFS
25546         if [ "$(facet_fstype $facet)" != "zfs" ]; then
25547                 local mdtfree2=$(do_facet $facet \
25548                                 lctl get_param -n osd*.*$mdtname.kbytesfree)
25549                 [ $mdtfree2 -gt $mdtfree1 ] ||
25550                         error "MDS space is not freed after DOM mirror deletion"
25551         fi
25552         return 0
25553 }
25554 run_test 272d "DoM mirroring: OST-striped mirror to DOM file"
25555
25556 test_272e() {
25557         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
25558                 skip "Need MDS version at least 2.12.55"
25559
25560         local dom=$DIR/$tdir/$tfile
25561         mkdir -p $DIR/$tdir
25562         $LFS setstripe -c 2 $dom
25563
25564         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
25565                 error "failed to write data into $dom"
25566         local old_md5=$(md5sum $dom)
25567         cancel_lru_locks
25568
25569         $LFS mirror extend -N -E 1M -L mdt -E eof -c2 $dom ||
25570                 error "failed mirroring to the DOM layout"
25571         $LFS mirror resync $dom ||
25572                 error "failed mirror resync"
25573         $LFS mirror split --mirror-id 1 -d $dom ||
25574                 error "failed mirror split"
25575
25576         [[ $($LFS getstripe -L --component-start=0 $dom) == 'mdt' ]] ||
25577                 error "MDT stripe wasn't set"
25578
25579         cancel_lru_locks
25580         local new_md5=$(md5sum $dom)
25581         [ "$old_md5" == "$new_md5" ] ||
25582                 error "$old_md5 != $new_md5"
25583
25584         return 0
25585 }
25586 run_test 272e "DoM mirroring: DOM mirror to the OST-striped file"
25587
25588 test_272f() {
25589         [ $MDS1_VERSION -lt $(version_code 2.12.55) ] &&
25590                 skip "Need MDS version at least 2.12.55"
25591
25592         local dom=$DIR/$tdir/$tfile
25593         mkdir -p $DIR/$tdir
25594         $LFS setstripe -c 2 $dom
25595
25596         dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
25597                 error "failed to write data into $dom"
25598         local old_md5=$(md5sum $dom)
25599         cancel_lru_locks
25600
25601         $LFS migrate -E 1M -L mdt -E eof -c2 -v $dom ||
25602                 error "failed migrating to the DOM file"
25603
25604         [[ $($LFS getstripe -L --component-start=0 $dom) == 'mdt' ]] ||
25605                 error "MDT stripe wasn't set"
25606
25607         cancel_lru_locks
25608         local new_md5=$(md5sum $dom)
25609         [ "$old_md5" != "$new_md5" ] &&
25610                 error "$old_md5 != $new_md5"
25611
25612         return 0
25613 }
25614 run_test 272f "DoM migration: OST-striped file to DOM file"
25615
25616 test_273a() {
25617         [ $MDS1_VERSION -lt $(version_code 2.11.50) ] &&
25618                 skip "Need MDS version at least 2.11.50"
25619
25620         # Layout swap cannot be done if either file has DOM component,
25621         # this will never be supported, migration should be used instead
25622
25623         local dom=$DIR/$tdir/$tfile
25624         mkdir -p $DIR/$tdir
25625
25626         $LFS setstripe -c2 ${dom}_plain
25627         $LFS setstripe -E 1M -L mdt -E -1 -c2 ${dom}_dom
25628         $LFS swap_layouts ${dom}_plain ${dom}_dom &&
25629                 error "can swap layout with DoM component"
25630         $LFS swap_layouts ${dom}_dom ${dom}_plain &&
25631                 error "can swap layout with DoM component"
25632
25633         $LFS setstripe -E 1M -c1 -E -1 -c2 ${dom}_comp
25634         $LFS swap_layouts ${dom}_comp ${dom}_dom &&
25635                 error "can swap layout with DoM component"
25636         $LFS swap_layouts ${dom}_dom ${dom}_comp &&
25637                 error "can swap layout with DoM component"
25638         return 0
25639 }
25640 run_test 273a "DoM: layout swapping should fail with DOM"
25641
25642 test_273b() {
25643         mkdir -p $DIR/$tdir
25644         $LFS setstripe -E 1M -L mdt -E -1 -c -1 $DIR/$tdir
25645
25646 #define OBD_FAIL_MDS_COMMITRW_DELAY      0x16b
25647         do_facet mds1 $LCTL set_param fail_loc=0x8000016b fail_val=2
25648
25649         $MULTIOP $DIR/$tdir/$tfile Ouw2097152c
25650 }
25651 run_test 273b "DoM: race writeback and object destroy"
25652
25653 test_273c() {
25654         mkdir -p $DIR/$tdir
25655         $LFS setstripe -E 1M -E-1 -c-1 $DIR/$tdir
25656
25657         #define OBD_FAIL_OFD_COMMITRW_DELAY      0x1e1
25658         do_facet ost1 $LCTL set_param fail_loc=0x800001e1 fail_val=2
25659
25660         $MULTIOP $DIR/$tdir/$tfile Ouw2097152c
25661 }
25662 run_test 273c "race writeback and object destroy"
25663
25664 test_275() {
25665         remote_ost_nodsh && skip "remote OST with nodsh"
25666         [ $OST1_VERSION -lt $(version_code 2.10.57) ] &&
25667                 skip "Need OST version >= 2.10.57"
25668
25669         local file=$DIR/$tfile
25670         local oss
25671
25672         oss=$(comma_list $(osts_nodes))
25673
25674         dd if=/dev/urandom of=$file bs=1M count=2 ||
25675                 error "failed to create a file"
25676         stack_trap "rm -f $file"
25677         cancel_lru_locks osc
25678
25679         #lock 1
25680         dd if=$file of=/dev/null bs=1M count=1 iflag=direct ||
25681                 error "failed to read a file"
25682
25683 #define OBD_FAIL_LDLM_PAUSE_CANCEL2      0x31f
25684         $LCTL set_param fail_loc=0x8000031f
25685
25686         cancel_lru_locks osc &
25687         sleep 1
25688
25689 #define OBD_FAIL_LDLM_PROLONG_PAUSE      0x32b
25690         do_nodes $oss $LCTL set_param fail_loc=0x8000032b
25691         #IO takes another lock, but matches the PENDING one
25692         #and places it to the IO RPC
25693         dd if=$file of=/dev/null bs=1M count=1 iflag=direct ||
25694                 error "failed to read a file with PENDING lock"
25695 }
25696 run_test 275 "Read on a canceled duplicate lock"
25697
25698 test_276() {
25699         remote_ost_nodsh && skip "remote OST with nodsh"
25700         local pid
25701
25702         do_facet ost1 "(while true; do \
25703                 $LCTL get_param obdfilter.*.filesfree > /dev/null 2>&1; \
25704                 done) & pid=\\\$!; echo \\\$pid > $TMP/sanity_276_pid" &
25705         pid=$!
25706
25707         for LOOP in $(seq 20); do
25708                 stop ost1
25709                 start ost1 $(ostdevname 1) $OST_MOUNT_OPTS
25710         done
25711         kill -9 $pid
25712         do_facet ost1 "pid=\\\$(cat $TMP/sanity_276_pid); kill -9 \\\$pid; \
25713                 rm $TMP/sanity_276_pid"
25714 }
25715 run_test 276 "Race between mount and obd_statfs"
25716
25717 test_277() {
25718         $LCTL set_param ldlm.namespaces.*.lru_size=0
25719         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
25720         local cached_mb=$($LCTL get_param llite.*.max_cached_mb |
25721                           awk '/^used_mb/ { print $2 }')
25722         [ $cached_mb -eq 1 ] || error "expected mb 1 got $cached_mb"
25723         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 \
25724                 oflag=direct conv=notrunc
25725         cached_mb=$($LCTL get_param llite.*.max_cached_mb |
25726                     awk '/^used_mb/ { print $2 }')
25727         [ $cached_mb -eq 0 ] || error "expected mb 0 got $cached_mb"
25728 }
25729 run_test 277 "Direct IO shall drop page cache"
25730
25731 test_278() {
25732         [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
25733         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
25734         [[ "$(facet_host mds1)" != "$(facet_host mds2)" ]] &&
25735                 skip "needs the same host for mdt1 mdt2" && return
25736
25737         local pid1
25738         local pid2
25739
25740 #define OBD_FAIL_OBD_STOP_MDS_RACE     0x60b
25741         do_facet mds2 $LCTL set_param fail_loc=0x8000060c
25742         stop mds2 &
25743         pid2=$!
25744
25745         stop mds1
25746
25747         echo "Starting MDTs"
25748         start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
25749         wait $pid2
25750 #For the error assertion will happen. lu_env_get_key(..., &mdt_thread_key)
25751 #will return NULL
25752         do_facet mds2 $LCTL set_param fail_loc=0
25753
25754         start mds2 $(mdsdevname 2) $MDS_MOUNT_OPTS
25755         wait_recovery_complete mds2
25756 }
25757 run_test 278 "Race starting MDS between MDTs stop/start"
25758
25759 test_280() {
25760         [ $MGS_VERSION -lt $(version_code 2.13.52) ] &&
25761                 skip "Need MGS version at least 2.13.52"
25762         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25763         combined_mgs_mds || skip "needs combined MGS/MDT"
25764
25765         umount_client $MOUNT
25766 #define OBD_FAIL_MDS_LLOG_UMOUNT_RACE   0x15e
25767         do_facet mgs $LCTL set_param fail_loc=0x8000015e fail_val=0
25768
25769         mount_client $MOUNT &
25770         sleep 1
25771         stop mgs || error "stop mgs failed"
25772         #for a race mgs would crash
25773         start mgs $(mgsdevname) $MGS_MOUNT_OPTS || error "start mgs failed"
25774         # make sure we unmount client before remounting
25775         wait
25776         umount_client $MOUNT
25777         mount_client $MOUNT || error "mount client failed"
25778 }
25779 run_test 280 "Race between MGS umount and client llog processing"
25780
25781 cleanup_test_300() {
25782         trap 0
25783         umask $SAVE_UMASK
25784 }
25785
25786 test_striped_dir() {
25787         local mdt_index=$1
25788         local stripe_count=$2
25789         local overstriping=$3
25790         local stripe_index
25791         local getstripe_count
25792
25793         mkdir -p $DIR/$tdir
25794
25795         SAVE_UMASK=$(umask)
25796         trap cleanup_test_300 RETURN EXIT
25797
25798         if [ -z $overstriping ]; then
25799                 $LFS setdirstripe -i $mdt_index -c $stripe_count -H all_char \
25800                                         -o 755 $DIR/$tdir/striped_dir ||
25801                         error "set striped dir error"
25802         else
25803                 $LFS setdirstripe -i $mdt_index -C $stripe_count -H all_char \
25804                                         -o 755 $DIR/$tdir/striped_dir ||
25805                         error "set striped dir error"
25806         fi
25807
25808         local mode=$(stat -c%a $DIR/$tdir/striped_dir)
25809         [ "$mode" = "755" ] || error "expect 755 got $mode"
25810
25811         $LFS getdirstripe $DIR/$tdir/striped_dir > /dev/null 2>&1 ||
25812                 error "getdirstripe failed"
25813         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir)
25814         if [ "$getstripe_count" != "$stripe_count" ]; then
25815                 error "1:stripe_count is $getstripe_count, expect $stripe_count"
25816         fi
25817         getstripe_count=$($LFS getdirstripe -T $DIR/$tdir/striped_dir)
25818         if [ "$getstripe_count" != "$stripe_count" ]; then
25819                 error "2:stripe_count is $getstripe_count, expect $stripe_count"
25820         fi
25821
25822         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir)
25823         if [ "$stripe_index" != "$mdt_index" ]; then
25824                 error "stripe_index is $stripe_index, expect $mdt_index"
25825         fi
25826
25827         [ $(stat -c%h $DIR/$tdir/striped_dir) == '2' ] ||
25828                 error "nlink error after create striped dir"
25829
25830         mkdir $DIR/$tdir/striped_dir/a
25831         mkdir $DIR/$tdir/striped_dir/b
25832
25833         stat $DIR/$tdir/striped_dir/a ||
25834                 error "create dir under striped dir failed"
25835         stat $DIR/$tdir/striped_dir/b ||
25836                 error "create dir under striped dir failed"
25837
25838         [ $(stat -c%h $DIR/$tdir/striped_dir) == '4' ] ||
25839                 error "nlink error after mkdir"
25840
25841         rmdir $DIR/$tdir/striped_dir/a
25842         [ $(stat -c%h $DIR/$tdir/striped_dir) == '3' ] ||
25843                 error "nlink error after rmdir"
25844
25845         rmdir $DIR/$tdir/striped_dir/b
25846         [ $(stat -c%h $DIR/$tdir/striped_dir) == '2' ] ||
25847                 error "nlink error after rmdir"
25848
25849         chattr +i $DIR/$tdir/striped_dir
25850         createmany -o $DIR/$tdir/striped_dir/f 10 &&
25851                 error "immutable flags not working under striped dir!"
25852         chattr -i $DIR/$tdir/striped_dir
25853
25854         rmdir $DIR/$tdir/striped_dir ||
25855                 error "rmdir striped dir error"
25856
25857         cleanup_test_300
25858
25859         true
25860 }
25861
25862 test_300a() {
25863         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
25864                 skip "skipped for lustre < 2.7.0"
25865         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25866         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25867
25868         test_striped_dir 0 2 || error "failed on striped dir on MDT0"
25869         test_striped_dir 1 2 || error "failed on striped dir on MDT0"
25870 }
25871 run_test 300a "basic striped dir sanity test"
25872
25873 test_300b() {
25874         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
25875                 skip "skipped for lustre < 2.7.0"
25876         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25877         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25878
25879         local i
25880         local mtime1
25881         local mtime2
25882         local mtime3
25883
25884         test_mkdir $DIR/$tdir || error "mkdir fail"
25885         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
25886                 error "set striped dir error"
25887         for i in {0..9}; do
25888                 mtime1=$(stat -c %Y $DIR/$tdir/striped_dir)
25889                 sleep 1
25890                 touch $DIR/$tdir/striped_dir/file_$i || error "touch error $i"
25891                 mtime2=$(stat -c %Y $DIR/$tdir/striped_dir)
25892                 [ $mtime1 -eq $mtime2 ] && error "mtime unchanged after create"
25893                 sleep 1
25894                 rm -f $DIR/$tdir/striped_dir/file_$i || error "unlink error $i"
25895                 mtime3=$(stat -c %Y $DIR/$tdir/striped_dir)
25896                 [ $mtime2 -eq $mtime3 ] && error "mtime unchanged after unlink"
25897         done
25898         true
25899 }
25900 run_test 300b "check ctime/mtime for striped dir"
25901
25902 test_300c() {
25903         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
25904                 skip "skipped for lustre < 2.7.0"
25905         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25906         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25907
25908         local file_count
25909
25910         mkdir_on_mdt0 $DIR/$tdir
25911         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir ||
25912                 error "set striped dir error"
25913
25914         chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/striped_dir ||
25915                 error "chown striped dir failed"
25916
25917         $RUNAS createmany -o $DIR/$tdir/striped_dir/f 5000 ||
25918                 error "create 5k files failed"
25919
25920         file_count=$(ls $DIR/$tdir/striped_dir | wc -l)
25921
25922         [ "$file_count" = 5000 ] || error "file count $file_count != 5000"
25923
25924         rm -rf $DIR/$tdir
25925 }
25926 run_test 300c "chown && check ls under striped directory"
25927
25928 test_300d() {
25929         [ $MDS1_VERSION -lt $(version_code 2.7.0) ] &&
25930                 skip "skipped for lustre < 2.7.0"
25931         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25932         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25933
25934         local stripe_count
25935         local file
25936
25937         mkdir -p $DIR/$tdir
25938         $LFS setstripe -c 2 $DIR/$tdir
25939
25940         #local striped directory
25941         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
25942                 error "set striped dir error"
25943         #look at the directories for debug purposes
25944         ls -l $DIR/$tdir
25945         $LFS getdirstripe $DIR/$tdir
25946         ls -l $DIR/$tdir/striped_dir
25947         $LFS getdirstripe $DIR/$tdir/striped_dir
25948         createmany -o $DIR/$tdir/striped_dir/f 10 ||
25949                 error "create 10 files failed"
25950
25951         #remote striped directory
25952         $LFS setdirstripe -i 1 -c 2 $DIR/$tdir/remote_striped_dir ||
25953                 error "set striped dir error"
25954         #look at the directories for debug purposes
25955         ls -l $DIR/$tdir
25956         $LFS getdirstripe $DIR/$tdir
25957         ls -l $DIR/$tdir/remote_striped_dir
25958         $LFS getdirstripe $DIR/$tdir/remote_striped_dir
25959         createmany -o $DIR/$tdir/remote_striped_dir/f 10 ||
25960                 error "create 10 files failed"
25961
25962         for file in $(find $DIR/$tdir); do
25963                 stripe_count=$($LFS getstripe -c $file)
25964                 [ $stripe_count -eq 2 ] ||
25965                         error "wrong stripe $stripe_count for $file"
25966         done
25967
25968         rm -rf $DIR/$tdir
25969 }
25970 run_test 300d "check default stripe under striped directory"
25971
25972 test_300e() {
25973         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
25974                 skip "Need MDS version at least 2.7.55"
25975         [ $PARALLEL == "yes" ] && skip "skip parallel run"
25976         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
25977
25978         local stripe_count
25979         local file
25980
25981         mkdir -p $DIR/$tdir
25982
25983         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
25984                 error "set striped dir error"
25985
25986         touch $DIR/$tdir/striped_dir/a
25987         touch $DIR/$tdir/striped_dir/b
25988         touch $DIR/$tdir/striped_dir/c
25989
25990         mkdir $DIR/$tdir/striped_dir/dir_a
25991         mkdir $DIR/$tdir/striped_dir/dir_b
25992         mkdir $DIR/$tdir/striped_dir/dir_c
25993
25994         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_a ||
25995                 error "set striped adir under striped dir error"
25996
25997         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_b ||
25998                 error "set striped bdir under striped dir error"
25999
26000         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_c ||
26001                 error "set striped cdir under striped dir error"
26002
26003         mrename $DIR/$tdir/striped_dir/dir_a $DIR/$tdir/striped_dir/dir_b ||
26004                 error "rename dir under striped dir fails"
26005
26006         mrename $DIR/$tdir/striped_dir/stp_a $DIR/$tdir/striped_dir/stp_b ||
26007                 error "rename dir under different stripes fails"
26008
26009         mrename $DIR/$tdir/striped_dir/a $DIR/$tdir/striped_dir/c ||
26010                 error "rename file under striped dir should succeed"
26011
26012         mrename $DIR/$tdir/striped_dir/dir_b $DIR/$tdir/striped_dir/dir_c ||
26013                 error "rename dir under striped dir should succeed"
26014
26015         rm -rf $DIR/$tdir
26016 }
26017 run_test 300e "check rename under striped directory"
26018
26019 test_300f() {
26020         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26021         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26022         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26023                 skip "Need MDS version at least 2.7.55"
26024
26025         local stripe_count
26026         local file
26027
26028         rm -rf $DIR/$tdir
26029         mkdir -p $DIR/$tdir
26030
26031         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir ||
26032                 error "set striped dir error"
26033
26034         $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir1 ||
26035                 error "set striped dir error"
26036
26037         touch $DIR/$tdir/striped_dir/a
26038         mkdir $DIR/$tdir/striped_dir/dir_a
26039         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir/stp_a ||
26040                 error "create striped dir under striped dir fails"
26041
26042         touch $DIR/$tdir/striped_dir1/b
26043         mkdir $DIR/$tdir/striped_dir1/dir_b
26044         $LFS setdirstripe -i 0 -c 2 $DIR/$tdir/striped_dir/stp_b ||
26045                 error "create striped dir under striped dir fails"
26046
26047         mrename $DIR/$tdir/striped_dir/dir_a $DIR/$tdir/striped_dir1/dir_b ||
26048                 error "rename dir under different striped dir should fail"
26049
26050         mrename $DIR/$tdir/striped_dir/stp_a $DIR/$tdir/striped_dir1/stp_b ||
26051                 error "rename striped dir under diff striped dir should fail"
26052
26053         mrename $DIR/$tdir/striped_dir/a $DIR/$tdir/striped_dir1/a ||
26054                 error "rename file under diff striped dirs fails"
26055
26056         rm -rf $DIR/$tdir
26057 }
26058 run_test 300f "check rename cross striped directory"
26059
26060 test_300_check_default_striped_dir()
26061 {
26062         local dirname=$1
26063         local default_count=$2
26064         local default_index=$3
26065         local stripe_count
26066         local stripe_index
26067         local dir_stripe_index
26068         local dir
26069
26070         echo "checking $dirname $default_count $default_index"
26071         $LFS setdirstripe -D -c $default_count -i $default_index \
26072                                 -H all_char $DIR/$tdir/$dirname ||
26073                 error "set default stripe on striped dir error"
26074         stripe_count=$($LFS getdirstripe -D -c $DIR/$tdir/$dirname)
26075         [ $stripe_count -eq $default_count ] ||
26076                 error "expect $default_count get $stripe_count for $dirname"
26077
26078         stripe_index=$($LFS getdirstripe -D -i $DIR/$tdir/$dirname)
26079         [ $stripe_index -eq $default_index ] ||
26080                 error "expect $default_index get $stripe_index for $dirname"
26081
26082         mkdir $DIR/$tdir/$dirname/{test1,test2,test3,test4} ||
26083                                                 error "create dirs failed"
26084
26085         createmany -o $DIR/$tdir/$dirname/f- 10 || error "create files failed"
26086         unlinkmany $DIR/$tdir/$dirname/f- 10    || error "unlink files failed"
26087         for dir in $(find $DIR/$tdir/$dirname/*); do
26088                 stripe_count=$($LFS getdirstripe -c $dir)
26089                 (( $stripe_count == $default_count )) ||
26090                 (( $stripe_count == $MDSCOUNT && $default_count == -1 )) ||
26091                 (( $stripe_count == 0 )) || (( $default_count == 1 )) ||
26092                 error "stripe count $default_count != $stripe_count for $dir"
26093
26094                 stripe_index=$($LFS getdirstripe -i $dir)
26095                 [ $default_index -eq -1 ] ||
26096                         [ $stripe_index -eq $default_index ] ||
26097                         error "$stripe_index != $default_index for $dir"
26098
26099                 #check default stripe
26100                 stripe_count=$($LFS getdirstripe -D -c $dir)
26101                 [ $stripe_count -eq $default_count ] ||
26102                 error "default count $default_count != $stripe_count for $dir"
26103
26104                 stripe_index=$($LFS getdirstripe -D -i $dir)
26105                 [ $stripe_index -eq $default_index ] ||
26106                 error "default index $default_index != $stripe_index for $dir"
26107         done
26108         rmdir $DIR/$tdir/$dirname/* || error "rmdir failed"
26109 }
26110
26111 test_300g() {
26112         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26113         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26114                 skip "Need MDS version at least 2.7.55"
26115
26116         local dir
26117         local stripe_count
26118         local stripe_index
26119
26120         mkdir_on_mdt0 $DIR/$tdir
26121         mkdir $DIR/$tdir/normal_dir
26122
26123         #Checking when client cache stripe index
26124         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
26125         $LFS setdirstripe -D -i1 $DIR/$tdir/striped_dir ||
26126                 error "create striped_dir failed"
26127
26128         $LFS setdirstripe -i0 $DIR/$tdir/striped_dir/dir0 ||
26129                 error "create dir0 fails"
26130         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/dir0)
26131         [ $stripe_index -eq 0 ] ||
26132                 error "dir0 expect index 0 got $stripe_index"
26133
26134         mkdir $DIR/$tdir/striped_dir/dir1 ||
26135                 error "create dir1 fails"
26136         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/dir1)
26137         [ $stripe_index -eq 1 ] ||
26138                 error "dir1 expect index 1 got $stripe_index"
26139
26140         #check default stripe count/stripe index
26141         test_300_check_default_striped_dir normal_dir $MDSCOUNT 1
26142         test_300_check_default_striped_dir normal_dir 1 0
26143         test_300_check_default_striped_dir normal_dir -1 1
26144         test_300_check_default_striped_dir normal_dir 2 -1
26145
26146         #delete default stripe information
26147         echo "delete default stripeEA"
26148         $LFS setdirstripe -d $DIR/$tdir/normal_dir ||
26149                 error "set default stripe on striped dir error"
26150
26151         mkdir -p $DIR/$tdir/normal_dir/{test1,test2,test3,test4}
26152         for dir in $(find $DIR/$tdir/normal_dir/*); do
26153                 stripe_count=$($LFS getdirstripe -c $dir)
26154                 [ $stripe_count -eq 0 ] ||
26155                         error "expect 1 get $stripe_count for $dir"
26156         done
26157 }
26158 run_test 300g "check default striped directory for normal directory"
26159
26160 test_300h() {
26161         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26162         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26163                 skip "Need MDS version at least 2.7.55"
26164
26165         local dir
26166         local stripe_count
26167
26168         mkdir $DIR/$tdir
26169         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
26170                 error "set striped dir error"
26171
26172         test_300_check_default_striped_dir striped_dir $MDSCOUNT 1
26173         test_300_check_default_striped_dir striped_dir 1 0
26174         test_300_check_default_striped_dir striped_dir -1 1
26175         test_300_check_default_striped_dir striped_dir 2 -1
26176
26177         #delete default stripe information
26178         $LFS setdirstripe -d $DIR/$tdir/striped_dir ||
26179                 error "set default stripe on striped dir error"
26180
26181         mkdir -p $DIR/$tdir/striped_dir/{test1,test2,test3,test4}
26182         for dir in $(find $DIR/$tdir/striped_dir/*); do
26183                 stripe_count=$($LFS getdirstripe -c $dir)
26184                 [ $stripe_count -eq 0 ] ||
26185                         error "expect 1 get $stripe_count for $dir"
26186         done
26187 }
26188 run_test 300h "check default striped directory for striped directory"
26189
26190 test_300i() {
26191         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
26192         (( $MDSCOUNT >= 2 )) || skip_env "needs >= 2 MDTs"
26193         (( $MDS1_VERSION >= $(version_code 2.7.55) )) ||
26194                 skip "Need MDS version at least 2.7.55"
26195
26196         local stripe_count
26197         local file
26198
26199         mkdir $DIR/$tdir
26200
26201         $LFS setdirstripe -i 0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
26202                 error "set striped dir error"
26203
26204         createmany -o $DIR/$tdir/striped_dir/f- 10 ||
26205                 error "create files under striped dir failed"
26206
26207         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir ||
26208                 error "set striped hashdir error"
26209
26210         $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir/d0 ||
26211                 error "create dir0 under hash dir failed"
26212         $LFS setdirstripe -i0 -c$MDSCOUNT -H fnv_1a_64 $DIR/$tdir/hashdir/d1 ||
26213                 error "create dir1 under hash dir failed"
26214         $LFS setdirstripe -i0 -c$MDSCOUNT -H crush $DIR/$tdir/hashdir/d2 ||
26215                 error "create dir2 under hash dir failed"
26216
26217         # unfortunately, we need to umount to clear dir layout cache for now
26218         # once we fully implement dir layout, we can drop this
26219         umount_client $MOUNT || error "umount failed"
26220         mount_client $MOUNT || error "mount failed"
26221
26222         $LFS find -H fnv_1a_64,crush $DIR/$tdir/hashdir
26223         local dircnt=$($LFS find -H fnv_1a_64,crush $DIR/$tdir/hashdir | wc -l)
26224         (( $dircnt == 2 )) || error "lfs find striped dir got $dircnt != 2"
26225
26226         if (( $MDS1_VERSION > $(version_code 2.15.0) )); then
26227                 $LFS mkdir -i0 -c$MDSCOUNT -H crush2 $DIR/$tdir/hashdir/d3 ||
26228                         error "create crush2 dir $tdir/hashdir/d3 failed"
26229                 $LFS find -H crush2 $DIR/$tdir/hashdir
26230                 dircnt=$($LFS find -H crush2 $DIR/$tdir/hashdir | wc -l)
26231                 (( $dircnt == 1 )) || error "find crush2 dir got $dircnt != 1"
26232
26233                 # mkdir with an invalid hash type (hash=fail_val) from client
26234                 # should be replaced on MDS with a valid (default) hash type
26235                 #define OBD_FAIL_LMV_UNKNOWN_STRIPE     0x1901
26236                 $LCTL set_param fail_loc=0x1901 fail_val=99
26237                 $LFS mkdir -c2 $DIR/$tdir/hashdir/d99
26238
26239                 local hash=$($LFS getdirstripe -H $DIR/$tdir/hashdir/d99)
26240                 local expect=$(do_facet mds1 \
26241                         $LCTL get_param -n lod.$FSNAME-MDT0000-mdtlov.mdt_hash)
26242                 [[ $hash == $expect ]] ||
26243                         error "d99 hash '$hash' != expected hash '$expect'"
26244         fi
26245
26246         #set the stripe to be unknown hash type on read
26247         #define OBD_FAIL_LMV_UNKNOWN_STRIPE     0x1901
26248         $LCTL set_param fail_loc=0x1901 fail_val=99
26249         for ((i = 0; i < 10; i++)); do
26250                 $CHECKSTAT -t file $DIR/$tdir/striped_dir/f-$i ||
26251                         error "stat f-$i failed"
26252                 rm $DIR/$tdir/striped_dir/f-$i || error "unlink f-$i failed"
26253         done
26254
26255         touch $DIR/$tdir/striped_dir/f0 &&
26256                 error "create under striped dir with unknown hash should fail"
26257
26258         $LCTL set_param fail_loc=0
26259
26260         umount_client $MOUNT || error "umount failed"
26261         mount_client $MOUNT || error "mount failed"
26262
26263         return 0
26264 }
26265 run_test 300i "client handle unknown hash type striped directory"
26266
26267 test_300j() {
26268         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26269         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26270         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26271                 skip "Need MDS version at least 2.7.55"
26272
26273         local stripe_count
26274         local file
26275
26276         mkdir $DIR/$tdir
26277
26278         #define OBD_FAIL_SPLIT_UPDATE_REC       0x1702
26279         $LCTL set_param fail_loc=0x1702
26280         $LFS setdirstripe -i 0 -c$MDSCOUNT -H all_char $DIR/$tdir/striped_dir ||
26281                 error "set striped dir error"
26282
26283         createmany -o $DIR/$tdir/striped_dir/f- 10 ||
26284                 error "create files under striped dir failed"
26285
26286         $LCTL set_param fail_loc=0
26287
26288         rm -rf $DIR/$tdir || error "unlink striped dir fails"
26289
26290         return 0
26291 }
26292 run_test 300j "test large update record"
26293
26294 test_300k() {
26295         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26296         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26297         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26298                 skip "Need MDS version at least 2.7.55"
26299
26300         # this test needs a huge transaction
26301         local kb
26302         kb=$(do_facet $SINGLEMDS "$LCTL get_param -n \
26303              osd*.$FSNAME-MDT0000.kbytestotal")
26304         [ $kb -lt $((1024*1024)) ] && skip "MDT0 too small: $kb"
26305
26306         local stripe_count
26307         local file
26308
26309         mkdir $DIR/$tdir
26310
26311         #define OBD_FAIL_LARGE_STRIPE   0x1703
26312         $LCTL set_param fail_loc=0x1703
26313         $LFS setdirstripe -i 0 -c192 $DIR/$tdir/striped_dir ||
26314                 error "set striped dir error"
26315         $LCTL set_param fail_loc=0
26316
26317         $LFS getdirstripe $DIR/$tdir/striped_dir ||
26318                 error "getstripeddir fails"
26319         rm -rf $DIR/$tdir/striped_dir ||
26320                 error "unlink striped dir fails"
26321
26322         return 0
26323 }
26324 run_test 300k "test large striped directory"
26325
26326 test_300l() {
26327         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26328         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26329         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26330                 skip "Need MDS version at least 2.7.55"
26331
26332         local stripe_index
26333
26334         test_mkdir -p $DIR/$tdir/striped_dir
26335         chown $RUNAS_ID $DIR/$tdir/striped_dir ||
26336                         error "chown $RUNAS_ID failed"
26337         $LFS setdirstripe -i 1 -D $DIR/$tdir/striped_dir ||
26338                 error "set default striped dir failed"
26339
26340         #define OBD_FAIL_MDS_STALE_DIR_LAYOUT    0x158
26341         $LCTL set_param fail_loc=0x80000158
26342         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir || error "create dir fails"
26343
26344         stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/test_dir)
26345         [ $stripe_index -eq 1 ] ||
26346                 error "expect 1 get $stripe_index for $dir"
26347 }
26348 run_test 300l "non-root user to create dir under striped dir with stale layout"
26349
26350 test_300m() {
26351         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26352         [ $MDSCOUNT -ge 2 ] && skip_env "Only for single MDT"
26353         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26354                 skip "Need MDS version at least 2.7.55"
26355
26356         mkdir -p $DIR/$tdir/striped_dir
26357         $LFS setdirstripe -D -c 1 $DIR/$tdir/striped_dir ||
26358                 error "set default stripes dir error"
26359
26360         mkdir $DIR/$tdir/striped_dir/a || error "mkdir a fails"
26361
26362         stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir/a)
26363         [ $stripe_count -eq 0 ] ||
26364                         error "expect 0 get $stripe_count for a"
26365
26366         $LFS setdirstripe -D -c 2 $DIR/$tdir/striped_dir ||
26367                 error "set default stripes dir error"
26368
26369         mkdir $DIR/$tdir/striped_dir/b || error "mkdir b fails"
26370
26371         stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir/b)
26372         [ $stripe_count -eq 0 ] ||
26373                         error "expect 0 get $stripe_count for b"
26374
26375         $LFS setdirstripe -D -c1 -i2 $DIR/$tdir/striped_dir ||
26376                 error "set default stripes dir error"
26377
26378         mkdir $DIR/$tdir/striped_dir/c &&
26379                 error "default stripe_index is invalid, mkdir c should fails"
26380
26381         rm -rf $DIR/$tdir || error "rmdir fails"
26382 }
26383 run_test 300m "setstriped directory on single MDT FS"
26384
26385 cleanup_300n() {
26386         local list=$(comma_list $(mdts_nodes))
26387
26388         trap 0
26389         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
26390 }
26391
26392 test_300n() {
26393         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26394         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26395         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26396                 skip "Need MDS version at least 2.7.55"
26397         remote_mds_nodsh && skip "remote MDS with nodsh"
26398
26399         local stripe_index
26400         local list=$(comma_list $(mdts_nodes))
26401
26402         trap cleanup_300n RETURN EXIT
26403         mkdir -p $DIR/$tdir
26404         chmod 777 $DIR/$tdir
26405         $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT \
26406                                 $DIR/$tdir/striped_dir > /dev/null 2>&1 &&
26407                 error "create striped dir succeeds with gid=0"
26408
26409         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1
26410         $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir ||
26411                 error "create striped dir fails with gid=-1"
26412
26413         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
26414         $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D \
26415                                 $DIR/$tdir/striped_dir > /dev/null 2>&1 &&
26416                 error "set default striped dir succeeds with gid=0"
26417
26418
26419         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1
26420         $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D $DIR/$tdir/striped_dir ||
26421                 error "set default striped dir fails with gid=-1"
26422
26423
26424         do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0
26425         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir ||
26426                                         error "create test_dir fails"
26427         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir1 ||
26428                                         error "create test_dir1 fails"
26429         $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir2 ||
26430                                         error "create test_dir2 fails"
26431         cleanup_300n
26432 }
26433 run_test 300n "non-root user to create dir under striped dir with default EA"
26434
26435 test_300o() {
26436         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26437         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26438         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26439                 skip "Need MDS version at least 2.7.55"
26440
26441         local numfree1
26442         local numfree2
26443
26444         mkdir -p $DIR/$tdir
26445
26446         numfree1=$(lctl get_param -n mdc.*MDT0000*.filesfree)
26447         numfree2=$(lctl get_param -n mdc.*MDT0001*.filesfree)
26448         if [ $numfree1 -lt 66000 ] || [ $numfree2 -lt 66000 ]; then
26449                 skip "not enough free inodes $numfree1 $numfree2"
26450         fi
26451
26452         numfree1=$(lctl get_param -n mdc.*MDT0000-mdc-*.kbytesfree)
26453         numfree2=$(lctl get_param -n mdc.*MDT0001-mdc-*.kbytesfree)
26454         if [ $numfree1 -lt 300000 ] || [ $numfree2 -lt 300000 ]; then
26455                 skip "not enough free space $numfree1 $numfree2"
26456         fi
26457
26458         $LFS setdirstripe -c2 $DIR/$tdir/striped_dir ||
26459                 error "setdirstripe fails"
26460
26461         createmany -d $DIR/$tdir/striped_dir/d 131000 ||
26462                 error "create dirs fails"
26463
26464         $LCTL set_param ldlm.namespaces.*mdc-*.lru_size=0
26465         ls $DIR/$tdir/striped_dir > /dev/null ||
26466                 error "ls striped dir fails"
26467         unlinkmany -d $DIR/$tdir/striped_dir/d 131000 ||
26468                 error "unlink big striped dir fails"
26469 }
26470 run_test 300o "unlink big sub stripe(> 65000 subdirs)"
26471
26472 test_300p() {
26473         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26474         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26475         remote_mds_nodsh && skip "remote MDS with nodsh"
26476
26477         mkdir_on_mdt0 $DIR/$tdir
26478
26479         #define OBD_FAIL_OUT_ENOSPC     0x1704
26480         do_facet mds2 lctl set_param fail_loc=0x80001704
26481         $LFS setdirstripe -i 0 -c2 $DIR/$tdir/bad_striped_dir > /dev/null 2>&1 \
26482                  && error "create striped directory should fail"
26483
26484         [ -e $DIR/$tdir/bad_striped_dir ] && error "striped dir exists"
26485
26486         $LFS setdirstripe -c2 $DIR/$tdir/bad_striped_dir
26487         true
26488 }
26489 run_test 300p "create striped directory without space"
26490
26491 test_300q() {
26492         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26493         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
26494
26495         local fd=$(free_fd)
26496         local cmd="exec $fd<$tdir"
26497         cd $DIR
26498         $LFS mkdir -c $MDSCOUNT $tdir || error "create $tdir fails"
26499         eval $cmd
26500         cmd="exec $fd<&-"
26501         trap "eval $cmd" EXIT
26502         cd $tdir || error "cd $tdir fails"
26503         rmdir  ../$tdir || error "rmdir $tdir fails"
26504         mkdir local_dir && error "create dir succeeds"
26505         $LFS setdirstripe -i1 remote_dir && error "create remote dir succeeds"
26506         eval $cmd
26507         return 0
26508 }
26509 run_test 300q "create remote directory under orphan directory"
26510
26511 test_300r() {
26512         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26513                 skip "Need MDS version at least 2.7.55" && return
26514         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
26515
26516         mkdir $DIR/$tdir
26517
26518         $LFS setdirstripe -i 0 -c -1 $DIR/$tdir/striped_dir ||
26519                 error "set striped dir error"
26520
26521         $LFS getdirstripe $DIR/$tdir/striped_dir ||
26522                 error "getstripeddir fails"
26523
26524         local stripe_count
26525         stripe_count=$($LFS getdirstripe $DIR/$tdir/striped_dir |
26526                       awk '/lmv_stripe_count:/ { print $2 }')
26527
26528         [ $MDSCOUNT -ne $stripe_count ] &&
26529                 error "wrong stripe count $stripe_count expected $MDSCOUNT"
26530
26531         rm -rf $DIR/$tdir/striped_dir ||
26532                 error "unlink striped dir fails"
26533 }
26534 run_test 300r "test -1 striped directory"
26535
26536 test_300s_helper() {
26537         local count=$1
26538
26539         local stripe_dir=$DIR/$tdir/striped_dir.$count
26540
26541         $LFS mkdir -c $count $stripe_dir ||
26542                 error "lfs mkdir -c error"
26543
26544         $LFS getdirstripe $stripe_dir ||
26545                 error "lfs getdirstripe fails"
26546
26547         local stripe_count
26548         stripe_count=$($LFS getdirstripe $stripe_dir |
26549                       awk '/lmv_stripe_count:/ { print $2 }')
26550
26551         [ $count -ne $stripe_count ] &&
26552                 error_noexit "bad stripe count $stripe_count expected $count"
26553
26554         local dupe_stripes
26555         dupe_stripes=$($LFS getdirstripe $stripe_dir |
26556                 awk '/0x/ {count[$1] += 1}; END {
26557                         for (idx in count) {
26558                                 if (count[idx]>1) {
26559                                         print "index " idx " count " count[idx]
26560                                 }
26561                         }
26562                 }')
26563
26564         if [[ -n "$dupe_stripes" ]] ; then
26565                 lfs getdirstripe $stripe_dir
26566                 error_noexit "Dupe MDT above: $dupe_stripes "
26567         fi
26568
26569         rm -rf $stripe_dir ||
26570                 error_noexit "unlink $stripe_dir fails"
26571 }
26572
26573 test_300s() {
26574         [ $MDS1_VERSION -lt $(version_code 2.7.55) ] &&
26575                 skip "Need MDS version at least 2.7.55" && return
26576         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
26577
26578         mkdir $DIR/$tdir
26579         for count in $(seq 2 $MDSCOUNT); do
26580                 test_300s_helper $count
26581         done
26582 }
26583 run_test 300s "test lfs mkdir -c without -i"
26584
26585 test_300t() {
26586         (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
26587                 skip "need MDS 2.14.55 or later"
26588         (( $MDSCOUNT >= 2 )) || skip "needs at least 2 MDTs"
26589
26590         local testdir="$DIR/$tdir/striped_dir"
26591         local dir1=$testdir/dir1
26592         local dir2=$testdir/dir2
26593
26594         mkdir -p $testdir
26595
26596         $LFS setdirstripe -D -c -1 --max-inherit=3 $testdir ||
26597                 error "failed to set default stripe count for $testdir"
26598
26599         mkdir $dir1
26600         local stripe_count=$($LFS getdirstripe -c $dir1)
26601
26602         (( $stripe_count == $MDSCOUNT )) || error "wrong stripe count"
26603
26604         local max_count=$((MDSCOUNT - 1))
26605         local mdts=$(comma_list $(mdts_nodes))
26606
26607         do_nodes $mdts $LCTL set_param lod.*.max_mdt_stripecount=$max_count
26608         stack_trap "do_nodes $mdts $LCTL set_param lod.*.max_mdt_stripecount=0"
26609
26610         mkdir $dir2
26611         stripe_count=$($LFS getdirstripe -c $dir2)
26612
26613         (( $stripe_count == $max_count )) || error "wrong stripe count"
26614 }
26615 run_test 300t "test max_mdt_stripecount"
26616
26617 MDT_OVSTRP_VER="2.15.60"
26618 # 300u family tests MDT overstriping
26619 test_300ua() {
26620         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26621
26622         local setcount=$((MDSCOUNT * 2))
26623
26624         local expected_count
26625
26626         mkdir $DIR/$tdir
26627         $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.0 ||
26628                 error "(0) failed basic overstriped dir creation test"
26629         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
26630
26631         # This does a basic interop test - if the MDS does not support mdt
26632         # overstriping, we should get stripes == number of MDTs
26633         if (( $MDS1_VERSION < $(version_code $MDT_OVSTRP_VER) )); then
26634                 expected_count=$MDSCOUNT
26635         else
26636                 expected_count=$setcount
26637         fi
26638         (( getstripe_count == expected_count )) ||
26639                 error "(1) incorrect stripe count for simple overstriped dir"
26640
26641         rm -rf $DIR/$tdir/${tdir}.0 ||
26642                 error "(2) unable to rm overstriped dir"
26643
26644         # Tests after this require overstriping support
26645         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26646                 { echo "skipped for MDS < $MDT_OVSTRP_VER"; return 0; }
26647
26648         test_striped_dir 0 $setcount true ||
26649                 error "(3)failed on overstriped dir"
26650         test_striped_dir 1 $setcount true ||
26651                 error "(4)failed on overstriped dir"
26652
26653         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
26654
26655         test_striped_dir 0 $setcount true ||
26656                 error "(5)failed on overstriped dir"
26657 }
26658 run_test 300ua "basic overstriped dir sanity test"
26659
26660 test_300ub() {
26661         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26662                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26663         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26664
26665         mkdir $DIR/$tdir
26666
26667         echo "Testing invalid stripe count, failure expected"
26668         local setcount=$((MDSCOUNT * 2))
26669
26670         $LFS setdirstripe -c $setcount $DIR/$tdir/${tdir}.0
26671         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
26672
26673         (( getstripe_count <= MDSCOUNT )) ||
26674                 error "(0)stripe count ($setcount) > MDT count ($MDSCOUNT) succeeded with -c"
26675
26676         # When a user requests > LMV_MAX_STRIPES_PER_MDT, we reduce to that
26677         setcount=$((MDSCOUNT * 2 * LMV_MAX_STRIPES_PER_MDT))
26678         $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.1
26679
26680         local maxcount=$((MDSCOUNT * LMV_MAX_STRIPES_PER_MDT))
26681
26682         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
26683         (( getstripe_count == maxcount )) ||
26684                 error "(1)stripe_count is $getstripe_count, expect $maxcount"
26685
26686         # Test specific striping with -i
26687         $LFS setdirstripe -i 0,0,0,0 $DIR/$tdir/${tdir}.2
26688
26689         getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.2)
26690         (( getstripe_count == 4 )) ||
26691                 error "(2)stripe_count is $getstripe_count, expect 4"
26692
26693         local nonzeroindices=$($LFS getdirstripe $DIR/$tdir/${tdir}.2 | grep "\[" | \
26694                                grep -v mdtidx | awk '{print $1}' | grep -c -v 0)
26695
26696         [[ -n "$nonzeroindices" ]] ||
26697                 error "(3) stripes indices not all 0: $nonzeroindices"
26698
26699         # Test specific striping with too many stripes on one MDT
26700         echo "Testing invalid striping, failure expected"
26701         $LFS setdirstripe -i 0,1,0,1,0,1,0,1,0,1,0 $DIR/$tdir/${tdir}.3
26702         $LFS getdirstripe $DIR/$tdir/${tdir}.3
26703         getstripe_count=$($LFS getdirstripe $DIR/$tdir/${tdir}.3 | grep "\[" | \
26704                           grep -v mdtidx | awk '{print $1}' | grep -c '0')
26705         echo "stripes on MDT0: $getstripe_count"
26706         (( getstripe_count <= LMV_MAX_STRIPES_PER_MDT )) ||
26707                 error "(4) setstripe with too many stripes on MDT0 succeeded"
26708
26709         setcount=$((MDSCOUNT * 2))
26710         $LFS setdirstripe -C $setcount -H all_char $DIR/${tdir}.4 ||
26711                 error "(5) can't setdirstripe with manually set hash function"
26712
26713         getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.4)
26714         (( getstripe_count == setcount )) ||
26715                 error "(6)stripe_count is $getstripe_count, expect $setcount"
26716
26717         setcount=$((MDSCOUNT * 2))
26718         mkdir $DIR/${tdir}.5
26719         $LFS setdirstripe -C $setcount -D -H crush $DIR/${tdir}.5 ||
26720                 error "(7) can't setdirstripe with manually set hash function"
26721         mkdir $DIR/${tdir}.5/${tdir}.6
26722
26723         getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.5/${tdir}.6)
26724         (( getstripe_count == setcount )) ||
26725                 error "(8)stripe_count is $getstripe_count, expect $setcount"
26726 }
26727 run_test 300ub "test MDT overstriping interface & limits"
26728
26729 test_300uc() {
26730         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26731                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26732         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26733
26734         mkdir $DIR/$tdir
26735
26736         local setcount=$((MDSCOUNT * 2))
26737
26738         $LFS setdirstripe -D -C $setcount $DIR/$tdir
26739
26740         mkdir $DIR/$tdir/${tdir}.1
26741
26742         local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
26743
26744         (( getstripe_count == setcount )) ||
26745                 error "(0)stripe_count is $getstripe_count, expect $setcount"
26746
26747         mkdir $DIR/$tdir/${tdir}.1/${tdir}.2
26748
26749         local getstripe_count=$($LFS getdirstripe -c \
26750                                 $DIR/$tdir/${tdir}.1/${tdir}.2)
26751
26752         (( getstripe_count == setcount )) ||
26753                 error "(1)stripe_count is $getstripe_count, expect $setcount"
26754 }
26755 run_test 300uc "test MDT overstriping as default & inheritance"
26756
26757 test_300ud() {
26758         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26759                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26760         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26761
26762         local mdts=$(comma_list $(mdts_nodes))
26763         local timeout=100
26764
26765         local restripe_status
26766         local delta
26767         local i
26768
26769         [[ $mds1_FSTYPE == zfs ]] && timeout=300
26770
26771         # in case "crush" hash type is not set
26772         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
26773
26774         restripe_status=$(do_facet mds1 $LCTL get_param -n \
26775                            mdt.*MDT0000.enable_dir_restripe)
26776         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
26777         stack_trap "do_nodes $mdts $LCTL set_param \
26778                     mdt.*.enable_dir_restripe=$restripe_status"
26779
26780         mkdir $DIR/$tdir
26781         createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
26782                 error "create files under remote dir failed $i"
26783         createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
26784                 error "create dirs under remote dir failed $i"
26785
26786         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
26787
26788         (( setcount < 13 )) || setcount=12
26789         for i in $(seq 2 $setcount); do
26790                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
26791                 $LFS setdirstripe -C $i $DIR/$tdir ||
26792                         error "split -C $i $tdir failed"
26793                 wait_update $HOSTNAME \
26794                         "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
26795                         error "dir split not finished"
26796                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
26797                         awk '/migrate/ {sum += $2} END { print sum }')
26798                 echo "$delta migrated when dir split $((i - 1)) to $i stripes"
26799                 # delta is around total_files/stripe_count, deviation 3%
26800                 (( delta < 100 * MDSCOUNT / i + 3 * MDSCOUNT )) ||
26801                         error "$delta files migrated >= $((100 * MDSCOUNT / i + 3 * MDSCOUNT))"
26802         done
26803 }
26804 run_test 300ud "dir split"
26805
26806 test_300ue() {
26807         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26808                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26809         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26810
26811         local mdts=$(comma_list $(mdts_nodes))
26812         local timeout=100
26813
26814         local restripe_status
26815         local delta
26816         local c
26817
26818         [[ $mds1_FSTYPE == zfs ]] && timeout=300
26819
26820         do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
26821
26822         restripe_status=$(do_facet mds1 $LCTL get_param -n \
26823                            mdt.*MDT0000.enable_dir_restripe)
26824         do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
26825         stack_trap "do_nodes $mdts $LCTL set_param \
26826                     mdt.*.enable_dir_restripe=$restripe_status"
26827
26828         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
26829
26830         (( setcount < 13 )) || setcount=12
26831         test_mkdir -C $setcount -H crush $DIR/$tdir
26832         createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
26833                 error "create files under remote dir failed"
26834         createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
26835                 error "create dirs under remote dir failed"
26836
26837         for c in $(seq $((setcount - 1)) -1 1); do
26838                 do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
26839                 $LFS setdirstripe -C $c $DIR/$tdir ||
26840                         error "split -C $c $tdir failed"
26841                 wait_update $HOSTNAME \
26842                         "$LFS getdirstripe -H $DIR/$tdir" "crush,fixed" $timeout ||
26843                         error "dir merge not finished"
26844                 delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
26845                         awk '/migrate/ {sum += $2} END { print sum }')
26846                 echo "$delta migrated when dir merge $((c + 1)) to $c stripes"
26847                 # delta is around total_files/stripe_count, deviation 3%
26848                 (( delta < 100 * MDSCOUNT / c + 3 * MDSCOUNT )) ||
26849                         error "$delta files migrated >= $((100 * MDSCOUNT / c + 3 * MDSCOUNT))"
26850         done
26851 }
26852 run_test 300ue "dir merge"
26853
26854 test_300uf() {
26855         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26856                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26857         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26858
26859         # maximum amount of local locks:
26860         # parent striped dir - 2 locks
26861         # new stripe in parent to migrate to - 1 lock
26862         # source and target - 2 locks
26863         # Total 5 locks for regular file
26864         #
26865         # NB: Overstriping should add several extra local locks
26866         # FIXME: Remove this once understood
26867         #lctl set_param *debug=-1 debug_mb=10000
26868         lctl clear
26869         lctl mark "touch/create"
26870         mkdir -p $DIR/$tdir
26871         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
26872         local setcount=$((MDSCOUNT * 5))
26873
26874         $LFS mkdir -i1 -C $setcount $DIR/$tdir/dir1
26875         touch $DIR/$tdir/dir1/eee
26876
26877         lctl mark "hardlinks"
26878         # create 4 hardlink for 4 more locks
26879         # Total: 9 locks > RS_MAX_LOCKS (8)
26880         $LFS mkdir -i1 -c1 $DIR/$tdir/dir2
26881         $LFS mkdir -i1 -c1 $DIR/$tdir/dir3
26882         $LFS mkdir -i1 -c1 $DIR/$tdir/dir4
26883         $LFS mkdir -i1 -c1 $DIR/$tdir/dir5
26884         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir2/eee
26885         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir3/eee
26886         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir4/eee
26887         ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir5/eee
26888
26889         lctl mark "cancel lru"
26890         cancel_lru_locks mdc
26891
26892         lctl mark "migrate"
26893         $LFS migrate -m1 -c1 $DIR/$tdir/dir1 ||
26894                 error "migrate dir fails"
26895
26896         rm -rf $DIR/$tdir || error "rm dir failed after migration"
26897 }
26898 run_test 300uf "migrate with too many local locks"
26899
26900 test_300ug() {
26901         (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
26902                 skip "skipped for MDS < $MDT_OVSTRP_VER"
26903         (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
26904
26905         mkdir -p $DIR/$tdir
26906         local migrate_dir=$DIR/$tdir/migrate_dir
26907         local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
26908         local setcount2=$((setcount - 2))
26909
26910         $LFS setdirstripe -c 2 $migrate_dir ||
26911                 error "(0) failed to create striped directory"
26912
26913         $LFS migrate -m 0 -C $setcount $migrate_dir ||
26914                 error "(1)failed to migrate to overstriped directory"
26915         local getstripe_count=$($LFS getdirstripe -c $migrate_dir)
26916
26917         (( getstripe_count == setcount )) ||
26918                 error "(2)stripe_count is $getstripe_count, expect $setcount"
26919         touch $DIR/$tdir/migrate_dir/$tfile ||
26920                 error "(3)failed to create file in overstriped directory"
26921         $LFS migrate -m 0 -C $setcount2 $migrate_dir ||
26922                 error "(4)failed to migrate overstriped directory"
26923         # Check stripe count after migration
26924         $LFS getdirstripe $migrate_dir
26925         getstripe_count=$($LFS getdirstripe -c $migrate_dir)
26926         (( getstripe_count == setcount2 )) ||
26927                 error "(5)stripe_count is $getstripe_count, expect $setcount2"
26928
26929         rm -rf $migrate_dir || error "(6) unable to rm overstriped dir"
26930 }
26931 run_test 300ug "migrate overstriped dirs"
26932
26933 prepare_remote_file() {
26934         mkdir $DIR/$tdir/src_dir ||
26935                 error "create remote source failed"
26936
26937         cp /etc/hosts $DIR/$tdir/src_dir/a ||
26938                  error "cp to remote source failed"
26939         touch $DIR/$tdir/src_dir/a
26940
26941         $LFS mkdir -i 1 $DIR/$tdir/tgt_dir ||
26942                 error "create remote target dir failed"
26943
26944         touch $DIR/$tdir/tgt_dir/b
26945
26946         mrename $DIR/$tdir/src_dir/a $DIR/$tdir/tgt_dir/b ||
26947                 error "rename dir cross MDT failed!"
26948
26949         $CHECKSTAT -t file $DIR/$tdir/src_dir/a &&
26950                 error "src_child still exists after rename"
26951
26952         $CHECKSTAT -t file $DIR/$tdir/tgt_dir/b ||
26953                 error "missing file(a) after rename"
26954
26955         diff /etc/hosts $DIR/$tdir/tgt_dir/b ||
26956                 error "diff after rename"
26957 }
26958
26959 test_310a() {
26960         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 4 MDTs"
26961         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26962
26963         local remote_file=$DIR/$tdir/tgt_dir/b
26964
26965         mkdir -p $DIR/$tdir
26966
26967         prepare_remote_file || error "prepare remote file failed"
26968
26969         #open-unlink file
26970         $OPENUNLINK $remote_file $remote_file ||
26971                 error "openunlink $remote_file failed"
26972         $CHECKSTAT -a $remote_file || error "$remote_file exists"
26973 }
26974 run_test 310a "open unlink remote file"
26975
26976 test_310b() {
26977         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 4 MDTs"
26978         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26979
26980         local remote_file=$DIR/$tdir/tgt_dir/b
26981
26982         mkdir -p $DIR/$tdir
26983
26984         prepare_remote_file || error "prepare remote file failed"
26985
26986         ln $remote_file $DIR/$tfile || error "link failed for remote file"
26987         $MULTIOP $DIR/$tfile Ouc || error "mulitop failed"
26988         $CHECKSTAT -t file $remote_file || error "check file failed"
26989 }
26990 run_test 310b "unlink remote file with multiple links while open"
26991
26992 test_310c() {
26993         [ $PARALLEL == "yes" ] && skip "skip parallel run"
26994         [[ $MDSCOUNT -lt 4 ]] && skip_env "needs >= 4 MDTs"
26995
26996         local remote_file=$DIR/$tdir/tgt_dir/b
26997
26998         mkdir -p $DIR/$tdir
26999
27000         prepare_remote_file || error "prepare remote file failed"
27001
27002         ln $remote_file $DIR/$tfile || error "link failed for remote file"
27003         multiop_bg_pause $remote_file O_uc ||
27004                         error "mulitop failed for remote file"
27005         MULTIPID=$!
27006         $MULTIOP $DIR/$tfile Ouc
27007         kill -USR1 $MULTIPID
27008         wait $MULTIPID
27009 }
27010 run_test 310c "open-unlink remote file with multiple links"
27011
27012 #LU-4825
27013 test_311() {
27014         [ $PARALLEL == "yes" ] && skip "skip parallel run"
27015         [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"
27016         [ $MDS1_VERSION -lt $(version_code 2.8.54) ] &&
27017                 skip "lustre < 2.8.54 does not contain LU-4825 fix"
27018         remote_mds_nodsh && skip "remote MDS with nodsh"
27019
27020         local old_iused=$($LFS df -i | awk '/OST0000/ { print $3; exit; }')
27021         local mdts=$(comma_list $(mdts_nodes))
27022
27023         mkdir -p $DIR/$tdir
27024         $LFS setstripe -i 0 -c 1 $DIR/$tdir
27025         createmany -o $DIR/$tdir/$tfile. 1000
27026
27027         # statfs data is not real time, let's just calculate it
27028         old_iused=$((old_iused + 1000))
27029
27030         local count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
27031                         osp.*OST0000*MDT0000.create_count")
27032         local max_count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
27033                                 osp.*OST0000*MDT0000.max_create_count")
27034         do_nodes $mdts "$LCTL set_param -n osp.*OST0000*.max_create_count=0"
27035
27036         $LFS setstripe -i 0 $DIR/$tdir/$tfile || error "setstripe failed"
27037         local index=$($LFS getstripe -i $DIR/$tdir/$tfile)
27038         [ $index -ne 0 ] || error "$tfile stripe index is 0"
27039
27040         unlinkmany $DIR/$tdir/$tfile. 1000
27041
27042         do_nodes $mdts "$LCTL set_param -n \
27043                         osp.*OST0000*.max_create_count=$max_count"
27044         [ $MDS1_VERSION -lt $(version_code 2.12.51) ] &&
27045                 do_nodes $mdts "$LCTL set_param -n \
27046                                 osp.*OST0000*.create_count=$count"
27047         do_nodes $mdts "$LCTL get_param osp.*OST0000*.create_count" |
27048                         grep "=0" && error "create_count is zero"
27049
27050         local new_iused
27051         for i in $(seq 120); do
27052                 new_iused=$($LFS df -i | awk '/OST0000/ { print $3; exit; }')
27053                 # system may be too busy to destroy all objs in time, use
27054                 # a somewhat small value to not fail autotest
27055                 [ $((old_iused - new_iused)) -gt 400 ] && break
27056                 sleep 1
27057         done
27058
27059         echo "waited $i sec, old Iused $old_iused, new Iused $new_iused"
27060         [ $((old_iused - new_iused)) -gt 400 ] ||
27061                 error "objs not destroyed after unlink"
27062 }
27063 run_test 311 "disable OSP precreate, and unlink should destroy objs"
27064
27065 zfs_get_objid()
27066 {
27067         local ost=$1
27068         local tf=$2
27069         local fid=($($LFS getstripe $tf | grep 0x))
27070         local seq=${fid[3]#0x}
27071         local objid=${fid[1]}
27072
27073         local vdevdir=$(dirname $(facet_vdevice $ost))
27074         local cmd="$ZDB -e -p $vdevdir -ddddd $(facet_device $ost)"
27075         local zfs_zapid=$(do_facet $ost $cmd |
27076                           grep -w "/O/$seq/d$((objid%32))" -C 5 |
27077                           awk '/Object/{getline; print $1}')
27078         local zfs_objid=$(do_facet $ost $cmd $zfs_zapid |
27079                           awk "/$objid = /"'{printf $3}')
27080
27081         echo $zfs_objid
27082 }
27083
27084 zfs_object_blksz() {
27085         local ost=$1
27086         local objid=$2
27087
27088         local vdevdir=$(dirname $(facet_vdevice $ost))
27089         local cmd="$ZDB -e -p $vdevdir -dddd $(facet_device $ost)"
27090         local blksz=$(do_facet $ost $cmd $objid |
27091                       awk '/dblk/{getline; printf $4}')
27092
27093         case "${blksz: -1}" in
27094                 k|K) blksz=$((${blksz:0:$((${#blksz} - 1))}*1024)) ;;
27095                 m|M) blksz=$((${blksz:0:$((${#blksz} - 1))}*1024*1024)) ;;
27096                 *) ;;
27097         esac
27098
27099         echo $blksz
27100 }
27101
27102 test_312() { # LU-4856
27103         remote_ost_nodsh && skip "remote OST with nodsh"
27104         [[ "$ost1_FSTYPE" == "zfs" ]] || skip "the test only applies to zfs"
27105
27106         local max_blksz=$(do_facet ost1 \
27107                           $ZFS get -p recordsize $(facet_device ost1) |
27108                           awk '!/VALUE/{print $3}')
27109         local tf=$DIR/$tfile
27110
27111         $LFS setstripe -c1 $tf
27112         local facet="ost$(($($LFS getstripe -i $tf) + 1))"
27113
27114         # Get ZFS object id
27115         local zfs_objid=$(zfs_get_objid $facet $tf)
27116         # block size change by sequential overwrite
27117         local bs
27118
27119         for ((bs=$PAGE_SIZE; bs <= max_blksz; bs *= 4)) ; do
27120                 dd if=/dev/zero of=$tf bs=$bs count=1 oflag=sync conv=notrunc
27121
27122                 local blksz=$(zfs_object_blksz $facet $zfs_objid)
27123                 [[ $blksz -eq $bs ]] || error "blksz error: $blksz, expected: $bs"
27124         done
27125         rm -f $tf
27126
27127         $LFS setstripe -c1 $tf
27128         facet="ost$(($($LFS getstripe -i $tf) + 1))"
27129
27130         # block size change by sequential append write
27131         dd if=/dev/zero of=$tf bs=$PAGE_SIZE count=1 oflag=sync conv=notrunc
27132         zfs_objid=$(zfs_get_objid $facet $tf)
27133         local count
27134
27135         for ((count = 1; count < $((max_blksz / PAGE_SIZE)); count *= 2)); do
27136                 dd if=/dev/zero of=$tf bs=$PAGE_SIZE count=$count seek=$count \
27137                         oflag=sync conv=notrunc
27138
27139                 blksz=$(zfs_object_blksz $facet $zfs_objid)
27140                 (( $blksz == 2 * count * PAGE_SIZE )) ||
27141                         error "blksz error, actual $blksz, " \
27142                                 "expected: 2 * $count * $PAGE_SIZE"
27143         done
27144         rm -f $tf
27145
27146         # random write
27147         $LFS setstripe -c1 $tf
27148         facet="ost$(($($LFS getstripe -i $tf) + 1))"
27149         zfs_objid=$(zfs_get_objid $facet $tf)
27150
27151         dd if=/dev/zero of=$tf bs=1K count=1 oflag=sync conv=notrunc
27152         blksz=$(zfs_object_blksz $facet $zfs_objid)
27153         (( blksz == PAGE_SIZE )) ||
27154                 error "blksz error: $blksz, expected: $PAGE_SIZE"
27155
27156         dd if=/dev/zero of=$tf bs=64K count=1 oflag=sync conv=notrunc seek=128
27157         blksz=$(zfs_object_blksz $facet $zfs_objid)
27158         (( blksz == 65536 )) || error "blksz error: $blksz, expected: 64k"
27159
27160         dd if=/dev/zero of=$tf bs=1M count=1 oflag=sync conv=notrunc
27161         blksz=$(zfs_object_blksz $facet $zfs_objid)
27162         (( blksz == 65536 )) || error "rewrite error: $blksz, expected: 64k"
27163 }
27164 run_test 312 "make sure ZFS adjusts its block size by write pattern"
27165
27166 test_313() {
27167         remote_ost_nodsh && skip "remote OST with nodsh"
27168
27169         local file=$DIR/$tfile
27170
27171         rm -f $file
27172         $LFS setstripe -c 1 -i 0 $file || error "setstripe failed"
27173
27174         # define OBD_FAIL_TGT_RCVD_EIO           0x720
27175         do_facet ost1 "$LCTL set_param fail_loc=0x720"
27176         dd if=/dev/zero of=$file bs=$PAGE_SIZE oflag=direct count=1 &&
27177                 error "write should failed"
27178         do_facet ost1 "$LCTL set_param fail_loc=0"
27179         rm -f $file
27180 }
27181 run_test 313 "io should fail after last_rcvd update fail"
27182
27183 test_314() {
27184         [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"
27185
27186         $LFS setstripe -c 2 -i 0 $DIR/$tfile || error "setstripe failed"
27187         do_facet ost1 "$LCTL set_param fail_loc=0x720"
27188         rm -f $DIR/$tfile
27189         wait_delete_completed
27190         do_facet ost1 "$LCTL set_param fail_loc=0"
27191 }
27192 run_test 314 "OSP shouldn't fail after last_rcvd update failure"
27193
27194 test_315() { # LU-618
27195         [ -f /proc/$$/io ] || skip_env "no IO accounting in kernel"
27196
27197         local file=$DIR/$tfile
27198         rm -f $file
27199
27200         $MULTIOP $file oO_CREAT:O_DIRECT:O_RDWR:w4063232c ||
27201                 error "multiop file write failed"
27202         $MULTIOP $file oO_RDONLY:r4063232_c &
27203         PID=$!
27204
27205         sleep 2
27206
27207         local rbytes=$(awk '/read_bytes/ { print $2 }' /proc/$PID/io)
27208         kill -USR1 $PID
27209
27210         [ $rbytes -gt 4000000 ] || error "read is not accounted ($rbytes)"
27211         rm -f $file
27212 }
27213 run_test 315 "read should be accounted"
27214
27215 test_316() {
27216         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
27217         large_xattr_enabled || skip "ea_inode feature disabled"
27218
27219         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
27220         mkdir $DIR/$tdir/d || error "mkdir $tdir/d failed"
27221         chown nobody $DIR/$tdir/d || error "chown $tdir/d failed"
27222         touch $DIR/$tdir/d/$tfile || error "touch $tdir/d/$tfile failed"
27223
27224         $LFS migrate -m1 $DIR/$tdir/d || error "lfs migrate -m1 failed"
27225 }
27226 run_test 316 "lfs migrate of file with large_xattr enabled"
27227
27228 test_317() {
27229         [ $MDS1_VERSION -lt $(version_code 2.11.53) ] &&
27230                 skip "Need MDS version at least 2.11.53"
27231         if [ "$ost1_FSTYPE" == "zfs" ]; then
27232                 skip "LU-10370: no implementation for ZFS"
27233         fi
27234
27235         local trunc_sz
27236         local grant_blk_size
27237
27238         grant_blk_size=$($LCTL get_param osc.$FSNAME*.import |
27239                         awk '/grant_block_size:/ { print $2; exit; }')
27240         #
27241         # Create File of size 5M. Truncate it to below size's and verify
27242         # blocks count.
27243         #
27244         dd if=/dev/zero of=$DIR/$tfile bs=5M count=1 conv=fsync ||
27245                 error "Create file $DIR/$tfile failed"
27246         stack_trap "rm -f $DIR/$tfile" EXIT
27247
27248         for trunc_sz in 2097152 4097 4000 509 0; do
27249                 $TRUNCATE $DIR/$tfile $trunc_sz ||
27250                         error "truncate $tfile to $trunc_sz failed"
27251                 local sz=$(stat --format=%s $DIR/$tfile)
27252                 local blk=$(stat --format=%b $DIR/$tfile)
27253                 local trunc_blk=$((((trunc_sz + (grant_blk_size - 1) ) /
27254                                      grant_blk_size) * 8))
27255
27256                 if [[ $blk -ne $trunc_blk ]]; then
27257                         $(which stat) $DIR/$tfile
27258                         error "Expected Block $trunc_blk got $blk for $tfile"
27259                 fi
27260
27261                 $CHECKSTAT -s $trunc_sz $DIR/$tfile ||
27262                         error "Expected Size $trunc_sz got $sz for $tfile"
27263         done
27264
27265         #
27266         # sparse file test
27267         # Create file with a hole and write actual 65536 bytes which aligned
27268         # with 4K and 64K PAGE_SIZE. Block count must be 128.
27269         #
27270         local bs=65536
27271         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 seek=5 conv=fsync ||
27272                 error "Create file : $DIR/$tfile"
27273
27274         #
27275         # Truncate to size $trunc_sz bytes. Strip tail blocks and leave only 8
27276         # blocks. The block count must drop to 8.
27277         #
27278         trunc_sz=$(($(stat --format=%s $DIR/$tfile) -
27279                 ((bs - grant_blk_size) + 1)))
27280         $TRUNCATE $DIR/$tfile $trunc_sz ||
27281                 error "truncate $tfile to $trunc_sz failed"
27282
27283         local trunc_bsz=$((grant_blk_size / $(stat --format=%B $DIR/$tfile)))
27284         sz=$(stat --format=%s $DIR/$tfile)
27285         blk=$(stat --format=%b $DIR/$tfile)
27286
27287         if [[ $blk -ne $trunc_bsz ]]; then
27288                 $(which stat) $DIR/$tfile
27289                 error "Expected Block $trunc_bsz got $blk for $tfile"
27290         fi
27291
27292         $CHECKSTAT -s $trunc_sz $DIR/$tfile ||
27293                 error "Expected Size $trunc_sz got $sz for $tfile"
27294 }
27295 run_test 317 "Verify blocks get correctly update after truncate"
27296
27297 test_318() {
27298         local llite_name="llite.$($LFS getname $MOUNT | awk '{print $1}')"
27299         local old_max_active=$($LCTL get_param -n \
27300                             ${llite_name}.max_read_ahead_async_active \
27301                             2>/dev/null)
27302
27303         $LCTL set_param llite.*.max_read_ahead_async_active=256
27304         local max_active=$($LCTL get_param -n \
27305                            ${llite_name}.max_read_ahead_async_active \
27306                            2>/dev/null)
27307         [ $max_active -ne 256 ] && error "expected 256 but got $max_active"
27308
27309         $LCTL set_param llite.*.max_read_ahead_async_active=0 ||
27310                 error "set max_read_ahead_async_active should succeed"
27311
27312         $LCTL set_param llite.*.max_read_ahead_async_active=512
27313         max_active=$($LCTL get_param -n \
27314                      ${llite_name}.max_read_ahead_async_active 2>/dev/null)
27315         [ $max_active -eq 512 ] || error "expected 512 but got $max_active"
27316
27317         # restore @max_active
27318         [ $old_max_active -ne 0 ] && $LCTL set_param \
27319                 llite.*.max_read_ahead_async_active=$old_max_active
27320
27321         local old_threshold=$($LCTL get_param -n \
27322                 ${llite_name}.read_ahead_async_file_threshold_mb 2>/dev/null)
27323         local max_per_file_mb=$($LCTL get_param -n \
27324                 ${llite_name}.max_read_ahead_per_file_mb 2>/dev/null)
27325
27326         local invalid=$(($max_per_file_mb + 1))
27327         $LCTL set_param \
27328                 llite.*.read_ahead_async_file_threshold_mb=$invalid\
27329                         && error "set $invalid should fail"
27330
27331         local valid=$(($invalid - 1))
27332         $LCTL set_param \
27333                 llite.*.read_ahead_async_file_threshold_mb=$valid ||
27334                         error "set $valid should succeed"
27335         local threshold=$($LCTL get_param -n \
27336                 ${llite_name}.read_ahead_async_file_threshold_mb 2>/dev/null)
27337         [ $threshold -eq $valid ] || error \
27338                 "expect threshold $valid got $threshold"
27339         $LCTL set_param \
27340                 llite.*.read_ahead_async_file_threshold_mb=$old_threshold
27341 }
27342 run_test 318 "Verify async readahead tunables"
27343
27344 test_319() {
27345         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
27346
27347         local before=$(date +%s)
27348         local evict
27349         local mdir=$DIR/$tdir
27350         local file=$mdir/xxx
27351
27352         $LFS mkdir -i0 $mdir || error "mkdir $mdir fails"
27353         touch $file
27354
27355 #define OBD_FAIL_LDLM_LOCAL_CANCEL_PAUSE 0x32c
27356         $LCTL set_param fail_val=5 fail_loc=0x8000032c
27357         $LFS migrate -m1 $mdir &
27358
27359         sleep 1
27360         dd if=$file of=/dev/null
27361         wait
27362         evict=$($LCTL get_param mdc.$FSNAME-MDT*.state |
27363           awk -F"[ [,]" '/EVICTED ]$/ { if (mx<$5) {mx=$5;} } END { print mx }')
27364
27365         [ -z "$evict" ] || [[ $evict -le $before ]] || error "eviction happened"
27366 }
27367 run_test 319 "lost lease lock on migrate error"
27368
27369 test_350() {
27370         local mdts=$(comma_list $(mdts_nodes))
27371
27372         mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
27373         stack_trap "rm -r $DIR/$tdir"
27374
27375         #force 1/100 of replies to take "NID mismatch" codepath
27376         #define CFS_FAIL_MATCH_MD_NID 0xe001  CFS_FAIL_SOME 0x10000000
27377         do_nodes $mdts $LCTL set_param fail_loc=0x1000e001 fail_val=100
27378
27379         while ls -lR $DIR/$tdir > /dev/null; do :; done &
27380         stack_trap "killall -9 ls || killall -9 ls"
27381
27382         cp -a /etc $DIR/$tdir || error "cp failed"
27383 }
27384 run_test 350 "force NID mismatch path to be exercised"
27385
27386 test_360() {
27387         (( $OST1_VERSION >= $(version_code 2.15.58.96) )) ||
27388                 skip "Need OST version at least 2.15.58.96"
27389         [[ "$ost1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
27390
27391         check_set_fallocate_or_skip
27392         local param="osd-ldiskfs.delayed_unlink_mb"
27393         local old=($(do_facet ost1 "$LCTL get_param -n $param"))
27394
27395         do_facet ost1 "$LCTL set_param $param=1MiB"
27396         stack_trap "do_facet ost1 $LCTL set_param $param=${old[0]}"
27397
27398         mkdir $DIR/$tdir/
27399         do_facet ost1 $LCTL set_param debug=+inode
27400         do_facet ost1 $LCTL clear
27401         local files=100
27402
27403         for ((i = 0; i < $files; i++)); do
27404                 fallocate -l 1280k $DIR/$tdir/$tfile.$i ||
27405                         error "fallocate 1280k $DIR/$tdir/$tfile.$i failed"
27406         done
27407         local min=$(($($LFS find $DIR/$tdir --ost 0 | wc -l) / 2))
27408
27409         for ((i = 0; i < $files; i++)); do
27410                 unlink $DIR/$tdir/$tfile.$i ||
27411                         error "unlink $DIR/$tdir/$tfile.$i failed"
27412         done
27413
27414         local count=0
27415         local loop
27416
27417         for (( loop = 0; loop < 30 && count < min; loop++)); do
27418                 sleep 1
27419                 (( count += $(do_facet ost1 $LCTL dk | grep -c "delayed iput")))
27420                 echo "Count[$loop]: $count"
27421         done
27422         (( count >= min )) || error "$count < $min delayed iput after $loop s"
27423 }
27424 run_test 360 "ldiskfs unlink in a separate thread"
27425
27426 test_398a() { # LU-4198
27427         local ost1_imp=$(get_osc_import_name client ost1)
27428         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
27429                          cut -d'.' -f2)
27430
27431         $LFS setstripe -c 1 -i 0 $DIR/$tfile
27432         stack_trap "rm -f $DIR/$tfile"
27433         $LCTL set_param ldlm.namespaces.*.lru_size=clear
27434
27435         # request a new lock on client
27436         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
27437
27438         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct conv=notrunc
27439         local lock_count=$($LCTL get_param -n \
27440                            ldlm.namespaces.$imp_name.lru_size)
27441         [[ $lock_count -eq 0 ]] || error "lock should be cancelled by direct IO"
27442
27443         $LCTL set_param ldlm.namespaces.$imp_name.lru_size=clear
27444
27445         # no lock cached, should use lockless DIO and not enqueue new lock
27446         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct conv=notrunc
27447         lock_count=$($LCTL get_param -n \
27448                      ldlm.namespaces.$imp_name.lru_size)
27449         [[ $lock_count -eq 0 ]] || error "no lock should be held by direct IO"
27450
27451         $LCTL set_param ldlm.namespaces.$imp_name.lru_size=clear
27452
27453         # no lock cached, should use locked DIO append
27454         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 oflag=direct oflag=append \
27455                 conv=notrunc || error "DIO append failed"
27456         lock_count=$($LCTL get_param -n \
27457                      ldlm.namespaces.$imp_name.lru_size)
27458         [[ $lock_count -ne 0 ]] || error "lock still must be held by DIO append"
27459 }
27460 run_test 398a "direct IO should cancel lock otherwise lockless"
27461
27462 test_398b() { # LU-4198
27463         local before=$(date +%s)
27464         local njobs=4
27465         local size=48
27466
27467         which fio || skip_env "no fio installed"
27468         $LFS setstripe -c -1 -S 1M $DIR/$tfile
27469         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$size
27470
27471         # Single page, multiple pages, stripe size, 4*stripe size
27472         for bsize in $(( $PAGE_SIZE )) $(( 4*$PAGE_SIZE )) 1048576 4194304; do
27473                 echo "mix direct rw ${bsize} by fio with $njobs jobs..."
27474                 fio --name=rand-rw --rw=randrw --bs=$bsize --direct=1 \
27475                         --numjobs=$njobs --fallocate=none \
27476                         --iodepth=16 --allow_file_create=0 \
27477                         --size=$((size/njobs))M \
27478                         --filename=$DIR/$tfile &
27479                 bg_pid=$!
27480
27481                 echo "mix buffer rw ${bsize} by fio with $njobs jobs..."
27482                 fio --name=rand-rw --rw=randrw --bs=$bsize \
27483                         --numjobs=$njobs --fallocate=none \
27484                         --iodepth=16 --allow_file_create=0 \
27485                         --size=$((size/njobs))M \
27486                         --filename=$DIR/$tfile || true
27487                 wait $bg_pid
27488         done
27489
27490         evict=$(do_facet client $LCTL get_param \
27491                 osc.$FSNAME-OST*-osc-*/state |
27492             awk -F"[ [,]" '/EVICTED ]$/ { if (t<$5) {t=$5;} } END { print t }')
27493
27494         [ -z "$evict" ] || [[ $evict -le $before ]] ||
27495                 (do_facet client $LCTL get_param \
27496                         osc.$FSNAME-OST*-osc-*/state;
27497                     error "eviction happened: $evict before:$before")
27498
27499         rm -f $DIR/$tfile
27500 }
27501 run_test 398b "DIO and buffer IO race"
27502
27503 test_398c() { # LU-4198
27504         local ost1_imp=$(get_osc_import_name client ost1)
27505         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
27506                          cut -d'.' -f2)
27507
27508         which fio || skip_env "no fio installed"
27509
27510         saved_debug=$($LCTL get_param -n debug)
27511         $LCTL set_param debug=0
27512
27513         local size=$(lctl get_param -n osc.$FSNAME-OST0000*.kbytesavail | head -1)
27514         ((size /= 1024)) # by megabytes
27515         ((size /= 2)) # write half of the OST at most
27516         [ $size -gt 40 ] && size=40 #reduce test time anyway
27517
27518         $LFS setstripe -c 1 $DIR/$tfile
27519
27520         # it seems like ldiskfs reserves more space than necessary if the
27521         # writing blocks are not mapped, so it extends the file firstly
27522         dd if=/dev/zero of=$DIR/$tfile bs=1M count=$size && sync
27523         cancel_lru_locks osc
27524
27525         # clear and verify rpc_stats later
27526         $LCTL set_param osc.${FSNAME}-OST0000-osc-ffff*.rpc_stats=clear
27527
27528         local njobs=4
27529         echo "writing ${size}M to OST0 by fio with $njobs jobs..."
27530         fio --name=rand-write --rw=randwrite --bs=$PAGE_SIZE --direct=1 \
27531                 --numjobs=$njobs --fallocate=none --ioengine=libaio \
27532                 --iodepth=16 --allow_file_create=0 --size=$((size/njobs))M \
27533                 --filename=$DIR/$tfile
27534         [ $? -eq 0 ] || error "fio write error"
27535
27536         [ $($LCTL get_param -n ldlm.namespaces.$imp_name.lock_count) -eq 0 ] ||
27537                 error "Locks were requested while doing AIO"
27538
27539         # get the percentage of 1-page I/O
27540         pct=$($LCTL get_param osc.${imp_name}.rpc_stats |
27541                 grep -A 1 'pages per rpc' | grep -v 'pages per rpc' |
27542                 awk '{print $7}')
27543         (( $pct <= 50 )) || {
27544                 $LCTL get_param osc.${imp_name}.rpc_stats
27545                 error "$pct% of I/O are 1-page"
27546         }
27547
27548         echo "mix rw ${size}M to OST0 by fio with $njobs jobs..."
27549         fio --name=rand-rw --rw=randrw --bs=$PAGE_SIZE --direct=1 \
27550                 --numjobs=$njobs --fallocate=none --ioengine=libaio \
27551                 --iodepth=16 --allow_file_create=0 --size=$((size/njobs))M \
27552                 --filename=$DIR/$tfile
27553         [ $? -eq 0 ] || error "fio mixed read write error"
27554
27555         echo "AIO with large block size ${size}M"
27556         fio --name=rand-rw --rw=randrw --bs=${size}M --direct=1 \
27557                 --numjobs=1 --fallocate=none --ioengine=libaio \
27558                 --iodepth=16 --allow_file_create=0 --size=${size}M \
27559                 --filename=$DIR/$tfile
27560         [ $? -eq 0 ] || error "fio large block size failed"
27561
27562         rm -f $DIR/$tfile
27563         $LCTL set_param debug="$saved_debug"
27564 }
27565 run_test 398c "run fio to test AIO"
27566
27567 test_398d() { #  LU-13846
27568         which aiocp || skip_env "no aiocp installed"
27569         local aio_file=$DIR/$tfile.aio
27570
27571         $LFS setstripe -c -1 -S 1M $DIR/$tfile $aio_file
27572
27573         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=64
27574         aiocp -a $PAGE_SIZE -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file
27575         stack_trap "rm -f $DIR/$tfile $aio_file"
27576
27577         diff $DIR/$tfile $aio_file || error "file diff after aiocp"
27578
27579         # test memory unaligned aio
27580         aiocp -a 512 -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file ||
27581                 error "unaligned aio failed"
27582         diff $DIR/$tfile $aio_file || error "file diff after aiocp"
27583
27584         rm -f $DIR/$tfile $aio_file
27585 }
27586 run_test 398d "run aiocp to verify block size > stripe size"
27587
27588 test_398e() {
27589         dd if=/dev/zero of=$DIR/$tfile bs=1234 count=1
27590         touch $DIR/$tfile.new
27591         dd if=$DIR/$tfile of=$DIR/$tfile.new bs=1M count=1 oflag=direct
27592 }
27593 run_test 398e "O_Direct open cleared by fcntl doesn't cause hang"
27594
27595 test_398f() { #  LU-14687
27596         which aiocp || skip_env "no aiocp installed"
27597         local aio_file=$DIR/$tfile.aio
27598
27599         $LFS setstripe -c -1 -S 1M $DIR/$tfile $aio_file
27600
27601         dd if=/dev/zero of=$DIR/$tfile bs=1M count=64
27602         stack_trap "rm -f $DIR/$tfile $aio_file"
27603
27604         #define OBD_FAIL_LLITE_PAGE_ALLOC 0x1418
27605         $LCTL set_param fail_loc=0x1418
27606         # make sure we don't crash and fail properly
27607         aiocp -b 64M -s 64M -f O_DIRECT $DIR/$tfile $aio_file &&
27608                 error "aio with page allocation failure succeeded"
27609         $LCTL set_param fail_loc=0
27610         diff $DIR/$tfile $aio_file
27611         [[ $? != 0 ]] || error "no diff after failed aiocp"
27612 }
27613 run_test 398f "verify aio handles ll_direct_rw_pages errors correctly"
27614
27615 # NB: To get the parallel DIO behavior in LU-13798, there must be > 1
27616 # stripe and i/o size must be > stripe size
27617 # Old style synchronous DIO waits after submitting each chunk, resulting in a
27618 # single RPC in flight.  This test shows async DIO submission is working by
27619 # showing multiple RPCs in flight.
27620 test_398g() { #  LU-13798
27621         $LFS setstripe -o 0,0 -S 1M $DIR/$tfile
27622
27623         # We need to do some i/o first to acquire enough grant to put our RPCs
27624         # in flight; otherwise a new connection may not have enough grant
27625         # available
27626         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
27627                 error "parallel dio failed"
27628         stack_trap "rm -f $DIR/$tfile"
27629
27630         # Reduce RPC size to 1M to avoid combination in to larger RPCs
27631         local pages_per_rpc=$($LCTL get_param osc.*-OST0000-*.max_pages_per_rpc)
27632         $LCTL set_param osc.*-OST0000-*.max_pages_per_rpc=1M
27633         stack_trap "$LCTL set_param -n $pages_per_rpc"
27634
27635         # Recreate file so it's empty
27636         rm -f $DIR/$tfile
27637         $LFS setstripe -o 0,0 -S 1M $DIR/$tfile
27638         #Pause rpc completion to guarantee we see multiple rpcs in flight
27639         #define OBD_FAIL_OST_BRW_PAUSE_BULK
27640         do_facet ost1 $LCTL set_param fail_loc=0x214 fail_val=2
27641         stack_trap "do_facet ost1 $LCTL set_param fail_loc=0"
27642
27643         # Clear rpc stats
27644         $LCTL set_param osc.*.rpc_stats=c
27645
27646         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
27647                 error "parallel dio failed"
27648         stack_trap "rm -f $DIR/$tfile"
27649
27650         $LCTL get_param osc.*-OST0000-*.rpc_stats
27651         pct=$($LCTL get_param osc.*-OST0000-*.rpc_stats |
27652                 grep -A 8 'rpcs in flight' | grep -v 'rpcs in flight' |
27653                 grep "8:" | awk '{print $8}')
27654         # We look at the "8 rpcs in flight" field, and verify A) it is present
27655         # and B) it includes all RPCs.  This proves we had 8 RPCs in flight,
27656         # as expected for an 8M DIO to a file with 1M stripes.
27657         # NB: There is occasionally a mystery extra write RPC to a different
27658         # file.  I can't identify why that's happening, so we set up a margin
27659         # of 1 RPC here, ie, 8/9 RPCs at this size, or ~88%
27660         [ $pct -gt 87 ] || error "we should see 8 RPCs in flight"
27661
27662         # Verify turning off parallel dio works as expected
27663         # Clear rpc stats
27664         $LCTL set_param osc.*.rpc_stats=c
27665         $LCTL set_param llite.*.parallel_dio=0
27666         stack_trap '$LCTL set_param llite.*.parallel_dio=1'
27667
27668         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=1 oflag=direct ||
27669                 error "dio with parallel dio disabled failed"
27670
27671         # Ideally, we would see only one RPC in flight here, but there is an
27672         # unavoidable race between i/o completion and RPC in flight counting,
27673         # so while only 1 i/o is in flight at a time, the RPC in flight counter
27674         # will sometimes exceed 1 (3 or 4 is not rare on VM testing).
27675         # So instead we just verify it's always < 8.
27676         $LCTL get_param osc.*-OST0000-*.rpc_stats
27677         ret=$($LCTL get_param osc.*-OST0000-*.rpc_stats |
27678                 grep -A 8 'rpcs in flight' | grep -v 'rpcs in flight' |
27679                 grep '^$' -B1 | grep . | awk '{print $1}')
27680         [ $ret != "8:" ] ||
27681                 error "we should see fewer than 8 RPCs in flight (saw $ret)"
27682 }
27683 run_test 398g "verify parallel dio async RPC submission"
27684
27685 test_398h() { #  LU-13798
27686         local dio_file=$DIR/$tfile.dio
27687
27688         $LFS setstripe -C 2 -S 1M $DIR/$tfile $dio_file
27689
27690         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
27691         stack_trap "rm -f $DIR/$tfile $dio_file"
27692
27693         dd if=$DIR/$tfile of=$dio_file bs=8M count=8 iflag=direct oflag=direct ||
27694                 error "parallel dio failed"
27695         diff $DIR/$tfile $dio_file
27696         [[ $? == 0 ]] || error "file diff after aiocp"
27697 }
27698 run_test 398h "verify correctness of read & write with i/o size >> stripe size"
27699
27700 test_398i() { #  LU-13798
27701         local dio_file=$DIR/$tfile.dio
27702
27703         $LFS setstripe -C 2 -S 1M $DIR/$tfile $dio_file
27704
27705         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
27706         stack_trap "rm -f $DIR/$tfile $dio_file"
27707
27708         #define OBD_FAIL_LLITE_PAGE_ALLOC 0x1418
27709         $LCTL set_param fail_loc=0x1418
27710         # make sure we don't crash and fail properly
27711         dd if=$DIR/$tfile of=$dio_file bs=8M count=8 iflag=direct oflag=direct &&
27712                 error "parallel dio page allocation failure succeeded"
27713         diff $DIR/$tfile $dio_file
27714         [[ $? != 0 ]] || error "no diff after failed aiocp"
27715 }
27716 run_test 398i "verify parallel dio handles ll_direct_rw_pages errors correctly"
27717
27718 test_398j() { #  LU-13798
27719         # Stripe size > RPC size but less than i/o size tests split across
27720         # stripes and RPCs for individual i/o op
27721         $LFS setstripe -o 0,0 -S 4M $DIR/$tfile $DIR/$tfile.2
27722
27723         # Reduce RPC size to 1M to guarantee split to multiple RPCs per stripe
27724         local pages_per_rpc=$($LCTL get_param osc.*-OST0000-*.max_pages_per_rpc)
27725         $LCTL set_param osc.*-OST0000-*.max_pages_per_rpc=1M
27726         stack_trap "$LCTL set_param -n $pages_per_rpc"
27727
27728         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
27729                 error "parallel dio write failed"
27730         stack_trap "rm -f $DIR/$tfile $DIR/$tfile.2"
27731
27732         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct ||
27733                 error "parallel dio read failed"
27734         diff $DIR/$tfile $DIR/$tfile.2
27735         [[ $? == 0 ]] || error "file diff after parallel dio read"
27736 }
27737 run_test 398j "test parallel dio where stripe size > rpc_size"
27738
27739 test_398k() { #  LU-13798
27740         wait_delete_completed
27741         wait_mds_ost_sync
27742
27743         # 4 stripe file; we will cause out of space on OST0
27744         $LFS setstripe -o 0,1,0,1 -S 1M $DIR/$tfile
27745
27746         # Fill OST0 (if it's not too large)
27747         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
27748                    head -n1)
27749         if [[ $ORIGFREE -gt $MAXFREE ]]; then
27750                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
27751         fi
27752         $LFS setstripe -i 0 -c 1 $DIR/$tfile.1
27753         dd if=/dev/zero of=$DIR/$tfile.1 bs=1024 count=$MAXFREE &&
27754                 error "dd should fill OST0"
27755         stack_trap "rm -f $DIR/$tfile.1"
27756
27757         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct
27758         err=$?
27759
27760         ls -la $DIR/$tfile
27761         $CHECKSTAT -t file -s 0 $DIR/$tfile ||
27762                 error "file is not 0 bytes in size"
27763
27764         # dd above should not succeed, but don't error until here so we can
27765         # get debug info above
27766         [[ $err != 0 ]] ||
27767                 error "parallel dio write with enospc succeeded"
27768         stack_trap "rm -f $DIR/$tfile"
27769 }
27770 run_test 398k "test enospc on first stripe"
27771
27772 test_398l() { #  LU-13798
27773         wait_delete_completed
27774         wait_mds_ost_sync
27775
27776         # 4 stripe file; we will cause out of space on OST0
27777         # Note the 1M stripe size and the > 1M i/o size mean this ENOSPC
27778         # happens on the second i/o chunk we issue
27779         $LFS setstripe -o 1,0,1,0 -S 1M $DIR/$tfile $DIR/$tfile.2
27780
27781         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=2 oflag=direct
27782         stack_trap "rm -f $DIR/$tfile"
27783
27784         # Fill OST0 (if it's not too large)
27785         ORIGFREE=$($LCTL get_param -n lov.$FSNAME-clilov-*.kbytesavail |
27786                    head -n1)
27787         if [[ $ORIGFREE -gt $MAXFREE ]]; then
27788                 skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
27789         fi
27790         $LFS setstripe -i 0 -c 1 $DIR/$tfile.1
27791         dd if=/dev/zero of=$DIR/$tfile.1 bs=1024 count=$MAXFREE &&
27792                 error "dd should fill OST0"
27793         stack_trap "rm -f $DIR/$tfile.1"
27794
27795         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 oflag=direct
27796         err=$?
27797         stack_trap "rm -f $DIR/$tfile.2"
27798
27799         # Check that short write completed as expected
27800         ls -la $DIR/$tfile.2
27801         $CHECKSTAT -t file -s 1048576 $DIR/$tfile.2 ||
27802                 error "file is not 1M in size"
27803
27804         # dd above should not succeed, but don't error until here so we can
27805         # get debug info above
27806         [[ $err != 0 ]] ||
27807                 error "parallel dio write with enospc succeeded"
27808
27809         # Truncate source file to same length as output file and diff them
27810         $TRUNCATE $DIR/$tfile 1048576
27811         diff $DIR/$tfile $DIR/$tfile.2
27812         [[ $? == 0 ]] || error "data incorrect after short write"
27813 }
27814 run_test 398l "test enospc on intermediate stripe/RPC"
27815
27816 test_398m() { #  LU-13798
27817         $LFS setstripe -o 0,1,0,1 -S 1M $DIR/$tfile
27818
27819         # Set up failure on OST0, the first stripe:
27820         #define OBD_FAIL_OST_BRW_WRITE_BULK     0x20e
27821         #NB: Fail val is ost # + 1, because we cannot use cfs_fail_val = 0
27822         # OST0 is on ost1, OST1 is on ost2.
27823         # So this fail_val specifies OST0
27824         do_facet ost1 $LCTL set_param fail_loc=0x20e fail_val=1
27825         stack_trap "do_facet ost1 $LCTL set_param fail_loc=0"
27826
27827         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct &&
27828                 error "parallel dio write with failure on first stripe succeeded"
27829         stack_trap "rm -f $DIR/$tfile"
27830         do_facet ost1 $LCTL set_param fail_loc=0 fail_val=0
27831
27832         # Place data in file for read
27833         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
27834                 error "parallel dio write failed"
27835
27836         # Fail read on OST0, first stripe
27837         #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
27838         do_facet ost1 $LCTL set_param fail_loc=0x20f fail_val=1
27839         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct &&
27840                 error "parallel dio read with error on first stripe succeeded"
27841         rm -f $DIR/$tfile.2
27842         do_facet ost1 $LCTL set_param fail_loc=0 fail_val=0
27843
27844         # Switch to testing on OST1, second stripe
27845         # Clear file contents, maintain striping
27846         echo > $DIR/$tfile
27847         # Set up failure on OST1, second stripe:
27848         do_facet ost2 $LCTL set_param fail_loc=0x20e fail_val=2
27849         stack_trap "do_facet ost2 $LCTL set_param fail_loc=0"
27850
27851         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct &&
27852                 error "parallel dio write with failure on second stripe succeeded"
27853         stack_trap "rm -f $DIR/$tfile"
27854         do_facet ost2 $LCTL set_param fail_loc=0 fail_val=0
27855
27856         # Place data in file for read
27857         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 oflag=direct ||
27858                 error "parallel dio write failed"
27859
27860         # Fail read on OST1, second stripe
27861         #define OBD_FAIL_OST_BRW_READ_BULK       0x20f
27862         do_facet ost2 $LCTL set_param fail_loc=0x20f fail_val=2
27863         dd if=$DIR/$tfile of=$DIR/$tfile.2 bs=8M count=8 iflag=direct &&
27864                 error "parallel dio read with error on second stripe succeeded"
27865         rm -f $DIR/$tfile.2
27866         do_facet ost2 $LCTL set_param fail_loc=0 fail_val=0
27867 }
27868 run_test 398m "test RPC failures with parallel dio"
27869
27870 # Parallel submission of DIO should not cause problems for append, but it's
27871 # important to verify.
27872 test_398n() { #  LU-13798
27873         $LFS setstripe -C 2 -S 1M $DIR/$tfile
27874
27875         dd if=/dev/urandom of=$DIR/$tfile bs=8M count=8 ||
27876                 error "dd to create source file failed"
27877         stack_trap "rm -f $DIR/$tfile"
27878
27879         dd if=$DIR/$tfile of=$DIR/$tfile.1 bs=8M count=8 oflag=direct oflag=append ||
27880                 error "parallel dio write with failure on second stripe succeeded"
27881         stack_trap "rm -f $DIR/$tfile $DIR/$tfile.1"
27882         diff $DIR/$tfile $DIR/$tfile.1
27883         [[ $? == 0 ]] || error "data incorrect after append"
27884
27885 }
27886 run_test 398n "test append with parallel DIO"
27887
27888 test_398o() {
27889         directio rdwr $DIR/$tfile 0 1 1 || error "bad KMS"
27890 }
27891 run_test 398o "right kms with DIO"
27892
27893 test_398p()
27894 {
27895         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
27896         which aiocp || skip_env "no aiocp installed"
27897
27898         local stripe_size=$((1024 * 1024)) #1 MiB
27899         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
27900         local file_size=$((25 * stripe_size))
27901
27902         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
27903         stack_trap "rm -f $DIR/$tfile*"
27904         # Just a bit bigger than the largest size in the test set below
27905         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
27906                 error "buffered i/o to create file failed"
27907
27908         for bs in $PAGE_SIZE $((PAGE_SIZE * 4)) $stripe_size \
27909                 $((stripe_size * 4)); do
27910
27911                 $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
27912
27913                 echo "bs: $bs, file_size $file_size"
27914                 aiocp -a $PAGE_SIZE -b $bs -s $file_size -f O_DIRECT \
27915                         $DIR/$tfile.1 $DIR/$tfile.2 &
27916                 pid_dio1=$!
27917                 # Buffered I/O with similar but not the same block size
27918                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
27919                         conv=notrunc &
27920                 pid_bio2=$!
27921                 wait $pid_dio1
27922                 rc1=$?
27923                 wait $pid_bio2
27924                 rc2=$?
27925                 if (( rc1 != 0 )); then
27926                         error "aio copy 1 w/bsize $bs failed: $rc1"
27927                 fi
27928                 if (( rc2 != 0 )); then
27929                         error "buffered copy 2 w/bsize $bs failed: $rc2"
27930                 fi
27931
27932                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
27933                         error "size incorrect"
27934                 cmp --verbose $DIR/$tfile.1 $DIR/$tfile.2 ||
27935                         error "files differ, bsize $bs"
27936                 rm -f $DIR/$tfile.2
27937         done
27938 }
27939 run_test 398p "race aio with buffered i/o"
27940
27941 test_398q()
27942 {
27943         (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
27944
27945         local stripe_size=$((1024 * 1024)) #1 MiB
27946         # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os
27947         local file_size=$((25 * stripe_size))
27948
27949         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.1
27950         $LFS setstripe -c 2 -S $stripe_size $DIR/$tfile.2
27951
27952         # Just a bit bigger than the largest size in the test set below
27953         dd if=/dev/urandom bs=$file_size count=1 of=$DIR/$tfile.1 ||
27954                 error "buffered i/o to create file failed"
27955
27956         for bs in $PAGE_SIZE $((PAGE_SIZE * 4)) $stripe_size \
27957                 $((stripe_size * 4)); do
27958
27959                 echo "bs: $bs, file_size $file_size"
27960                 dd if=$DIR/$tfile.1 bs=$((bs *2 )) of=$DIR/$tfile.2 \
27961                         conv=notrunc oflag=direct iflag=direct &
27962                 pid_dio1=$!
27963                 # Buffered I/O with similar but not the same block size
27964                 dd if=$DIR/$tfile.1 bs=$((bs * 2)) of=$DIR/$tfile.2 \
27965                         conv=notrunc &
27966                 pid_bio2=$!
27967                 wait $pid_dio1
27968                 rc1=$?
27969                 wait $pid_bio2
27970                 rc2=$?
27971                 if (( rc1 != 0 )); then
27972                         error "dio copy 1 w/bsize $bs failed: $rc1"
27973                 fi
27974                 if (( rc2 != 0 )); then
27975                         error "buffered copy 2 w/bsize $bs failed: $rc2"
27976                 fi
27977
27978                 $CHECKSTAT -t file -s $file_size $DIR/$tfile.2 ||
27979                         error "size incorrect"
27980                 diff $DIR/$tfile.1 $DIR/$tfile.2 ||
27981                         error "files differ, bsize $bs"
27982         done
27983
27984         rm -f $DIR/$tfile*
27985 }
27986 run_test 398q "race dio with buffered i/o"
27987
27988 test_fake_rw() {
27989         local read_write=$1
27990         if [ "$read_write" = "write" ]; then
27991                 local dd_cmd="dd if=/dev/zero of=$DIR/$tfile"
27992         elif [ "$read_write" = "read" ]; then
27993                 local dd_cmd="dd of=/dev/null if=$DIR/$tfile"
27994         else
27995                 error "argument error"
27996         fi
27997
27998         # turn off debug for performance testing
27999         local saved_debug=$($LCTL get_param -n debug)
28000         $LCTL set_param debug=0
28001
28002         $LFS setstripe -c 1 -i 0 $DIR/$tfile
28003
28004         # get ost1 size - $FSNAME-OST0000
28005         local ost1_avail_size=$($LFS df $DIR | awk /${ost1_svc}/'{ print $4 }')
28006         local blocks=$((ost1_avail_size/2/1024)) # half avail space by megabytes
28007         [ $blocks -gt 1000 ] && blocks=1000 # 1G in maximum
28008
28009         if [ "$read_write" = "read" ]; then
28010                 $TRUNCATE $DIR/$tfile $(expr 1048576 \* $blocks)
28011         fi
28012
28013         local start_time=$(date +%s.%N)
28014         $dd_cmd bs=1M count=$blocks oflag=sync ||
28015                 error "real dd $read_write error"
28016         local duration=$(bc <<< "$(date +%s.%N) - $start_time")
28017
28018         if [ "$read_write" = "write" ]; then
28019                 rm -f $DIR/$tfile
28020         fi
28021
28022         # define OBD_FAIL_OST_FAKE_RW           0x238
28023         do_facet ost1 $LCTL set_param fail_loc=0x238
28024
28025         local start_time=$(date +%s.%N)
28026         $dd_cmd bs=1M count=$blocks oflag=sync ||
28027                 error "fake dd $read_write error"
28028         local duration_fake=$(bc <<< "$(date +%s.%N) - $start_time")
28029
28030         if [ "$read_write" = "write" ]; then
28031                 # verify file size
28032                 cancel_lru_locks osc
28033                 $CHECKSTAT -t file -s $((blocks * 1024 * 1024)) $DIR/$tfile ||
28034                         error "$tfile size not $blocks MB"
28035         fi
28036         do_facet ost1 $LCTL set_param fail_loc=0
28037
28038         echo "fake $read_write $duration_fake vs. normal $read_write" \
28039                 "$duration in seconds"
28040         [ $(bc <<< "$duration_fake < $duration") -eq 1 ] ||
28041                 error_not_in_vm "fake write is slower"
28042
28043         $LCTL set_param -n debug="$saved_debug"
28044         rm -f $DIR/$tfile
28045 }
28046 test_399a() { # LU-7655 for OST fake write
28047         remote_ost_nodsh && skip "remote OST with nodsh"
28048
28049         test_fake_rw write
28050 }
28051 run_test 399a "fake write should not be slower than normal write"
28052
28053 test_399b() { # LU-8726 for OST fake read
28054         remote_ost_nodsh && skip "remote OST with nodsh"
28055         if [ "$ost1_FSTYPE" != "ldiskfs" ]; then
28056                 skip_env "ldiskfs only test"
28057         fi
28058
28059         test_fake_rw read
28060 }
28061 run_test 399b "fake read should not be slower than normal read"
28062
28063 test_400a() { # LU-1606, was conf-sanity test_74
28064         if ! which $CC > /dev/null 2>&1; then
28065                 skip_env "$CC is not installed"
28066         fi
28067
28068         local extra_flags=''
28069         local out=$TMP/$tfile
28070         local prefix=/usr/include/lustre
28071         local prog
28072
28073         # Oleg removes .c files in his test rig so test if any c files exist
28074         [[ -n "$(ls -A $LUSTRE_TESTS_API_DIR)" ]] ||
28075                 skip_env "Needed .c test files are missing"
28076
28077         if ! [[ -d $prefix ]]; then
28078                 # Assume we're running in tree and fixup the include path.
28079                 extra_flags+=" -I$LUSTRE/../lnet/include/uapi"
28080                 extra_flags+=" -I$LUSTRE/include/uapi -I$LUSTRE/include"
28081                 extra_flags+=" -L$LUSTRE/utils/.libs"
28082         fi
28083
28084         for prog in $LUSTRE_TESTS_API_DIR/*.c; do
28085                 $CC -Wall -Werror $extra_flags -o $out $prog -llustreapi ||
28086                         error "client api broken"
28087         done
28088         rm -f $out
28089 }
28090 run_test 400a "Lustre client api program can compile and link"
28091
28092 test_400b() { # LU-1606, LU-5011
28093         local header
28094         local out=$TMP/$tfile
28095         local prefix=/usr/include/linux/lustre
28096
28097         # We use a hard coded prefix so that this test will not fail
28098         # when run in tree. There are headers in lustre/include/lustre/
28099         # that are not packaged (like lustre_idl.h) and have more
28100         # complicated include dependencies (like config.h and lnet/types.h).
28101         # Since this test about correct packaging we just skip them when
28102         # they don't exist (see below) rather than try to fixup cppflags.
28103
28104         if ! which $CC > /dev/null 2>&1; then
28105                 skip_env "$CC is not installed"
28106         fi
28107
28108         for header in $prefix/*.h; do
28109                 if ! [[ -f "$header" ]]; then
28110                         continue
28111                 fi
28112
28113                 if [[ "$(basename $header)" == lustre_ioctl.h ]]; then
28114                         continue # lustre_ioctl.h is internal header
28115                 fi
28116
28117                 $CC -Wall -Werror -include $header -c -x c /dev/null -o $out ||
28118                         error "cannot compile '$header'"
28119         done
28120         rm -f $out
28121 }
28122 run_test 400b "packaged headers can be compiled"
28123
28124 test_401a() { #LU-7437
28125         local printf_arg=$(find -printf 2>&1 | grep "unrecognized:")
28126         [ -n "$printf_arg" ] && skip_env "find does not support -printf"
28127
28128         #count the number of parameters by "list_param -R"
28129         local params=$($LCTL list_param -R '*' 2>/dev/null | wc -l)
28130         #count the number of parameters by listing proc files
28131         local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
28132         echo "proc_dirs='$proc_dirs'"
28133         [ -n "$proc_dirs" ] || error "no proc_dirs on $HOSTNAME"
28134         local procs=$(find -L $proc_dirs -mindepth 1 -printf '%P\n' 2>/dev/null|
28135                       sort -u | wc -l)
28136
28137         [ $params -eq $procs ] ||
28138                 error "found $params parameters vs. $procs proc files"
28139
28140         # test the list_param -D option only returns directories
28141         params=$($LCTL list_param -R -D '*' 2>/dev/null | wc -l)
28142         #count the number of parameters by listing proc directories
28143         procs=$(find -L $proc_dirs -mindepth 1 -type d -printf '%P\n' 2>/dev/null |
28144                 sort -u | wc -l)
28145
28146         [ $params -eq $procs ] ||
28147                 error "found $params parameters vs. $procs proc files"
28148 }
28149 run_test 401a "Verify if 'lctl list_param -R' can list parameters recursively"
28150
28151 test_401b() {
28152         # jobid_var may not allow arbitrary values, so use jobid_name
28153         # if available
28154         if $LCTL list_param jobid_name > /dev/null 2>&1; then
28155                 local testname=jobid_name tmp='testing%p'
28156         else
28157                 local testname=jobid_var tmp=testing
28158         fi
28159
28160         local save=$($LCTL get_param -n $testname)
28161
28162         $LCTL set_param foo=bar $testname=$tmp bar=baz &&
28163                 error "no error returned when setting bad parameters"
28164
28165         local jobid_new=$($LCTL get_param -n foe $testname baz)
28166         [[ "$jobid_new" == "$tmp" ]] || error "jobid tmp $jobid_new != $tmp"
28167
28168         $LCTL set_param -n fog=bam $testname=$save bat=fog
28169         local jobid_old=$($LCTL get_param -n foe $testname bag)
28170         [[ "$jobid_old" == "$save" ]] || error "jobid new $jobid_old != $save"
28171 }
28172 run_test 401b "Verify 'lctl {get,set}_param' continue after error"
28173
28174 test_401c() {
28175         # jobid_var may not allow arbitrary values, so use jobid_name
28176         # if available
28177         if $LCTL list_param jobid_name > /dev/null 2>&1; then
28178                 local testname=jobid_name
28179         else
28180                 local testname=jobid_var
28181         fi
28182
28183         local jobid_var_old=$($LCTL get_param -n $testname)
28184         local jobid_var_new
28185
28186         $LCTL set_param $testname= &&
28187                 error "no error returned for 'set_param a='"
28188
28189         jobid_var_new=$($LCTL get_param -n $testname)
28190         [[ "$jobid_var_old" == "$jobid_var_new" ]] ||
28191                 error "$testname was changed by setting without value"
28192
28193         $LCTL set_param $testname &&
28194                 error "no error returned for 'set_param a'"
28195
28196         jobid_var_new=$($LCTL get_param -n $testname)
28197         [[ "$jobid_var_old" == "$jobid_var_new" ]] ||
28198                 error "$testname was changed by setting without value"
28199 }
28200 run_test 401c "Verify 'lctl set_param' without value fails in either format."
28201
28202 test_401d() {
28203         # jobid_var may not allow arbitrary values, so use jobid_name
28204         # if available
28205         if $LCTL list_param jobid_name > /dev/null 2>&1; then
28206                 local testname=jobid_name new_value='foo=bar%p'
28207         else
28208                 local testname=jobid_var new_valuie=foo=bar
28209         fi
28210
28211         local jobid_var_old=$($LCTL get_param -n $testname)
28212         local jobid_var_new
28213
28214         $LCTL set_param $testname=$new_value ||
28215                 error "'set_param a=b' did not accept a value containing '='"
28216
28217         jobid_var_new=$($LCTL get_param -n $testname)
28218         [[ "$jobid_var_new" == "$new_value" ]] ||
28219                 error "'set_param a=b' failed on a value containing '='"
28220
28221         # Reset the $testname to test the other format
28222         $LCTL set_param $testname=$jobid_var_old
28223         jobid_var_new=$($LCTL get_param -n $testname)
28224         [[ "$jobid_var_new" == "$jobid_var_old" ]] ||
28225                 error "failed to reset $testname"
28226
28227         $LCTL set_param $testname $new_value ||
28228                 error "'set_param a b' did not accept a value containing '='"
28229
28230         jobid_var_new=$($LCTL get_param -n $testname)
28231         [[ "$jobid_var_new" == "$new_value" ]] ||
28232                 error "'set_param a b' failed on a value containing '='"
28233
28234         $LCTL set_param $testname $jobid_var_old
28235         jobid_var_new=$($LCTL get_param -n $testname)
28236         [[ "$jobid_var_new" == "$jobid_var_old" ]] ||
28237                 error "failed to reset $testname"
28238 }
28239 run_test 401d "Verify 'lctl set_param' accepts values containing '='"
28240
28241 test_401e() { # LU-14779
28242         $LCTL list_param -R "ldlm.namespaces.MGC*" ||
28243                 error "lctl list_param MGC* failed"
28244         $LCTL get_param "ldlm.namespaces.MGC*" || error "lctl get_param failed"
28245         $LCTL get_param "ldlm.namespaces.MGC*.lru_size" ||
28246                 error "lctl get_param lru_size failed"
28247 }
28248 run_test 401e "verify 'lctl get_param' works with NID in parameter"
28249
28250 test_402() {
28251         [[ $MDS1_VERSION -ge $(version_code 2.7.66) ]] ||
28252         [[ $MDS1_VERSION -ge $(version_code 2.7.18.4) &&
28253                 $MDS1_VERSION -lt $(version_code 2.7.50) ]] ||
28254         [[ $MDS1_VERSION -ge $(version_code 2.7.2) &&
28255                 $MDS1_VERSION -lt $(version_code 2.7.11) ]] ||
28256                 skip "Need MDS version 2.7.2+ or 2.7.18.4+ or 2.7.66+"
28257         remote_mds_nodsh && skip "remote MDS with nodsh"
28258
28259         $LFS setdirstripe -i 0 $DIR/$tdir || error "setdirstripe -i 0 failed"
28260 #define OBD_FAIL_MDS_FLD_LOOKUP 0x15c
28261         do_facet mds1 "lctl set_param fail_loc=0x8000015c"
28262         touch $DIR/$tdir/$tfile && error "touch should fail with ENOENT" ||
28263                 echo "Touch failed - OK"
28264 }
28265 run_test 402 "Return ENOENT to lod_generate_and_set_lovea"
28266
28267 test_403() {
28268         local file1=$DIR/$tfile.1
28269         local file2=$DIR/$tfile.2
28270         local tfile=$TMP/$tfile
28271
28272         rm -f $file1 $file2 $tfile
28273
28274         touch $file1
28275         ln $file1 $file2
28276
28277         # 30 sec OBD_TIMEOUT in ll_getattr()
28278         # right before populating st_nlink
28279         $LCTL set_param fail_loc=0x80001409
28280         stat -c %h $file1 > $tfile &
28281
28282         # create an alias, drop all locks and reclaim the dentry
28283         < $file2
28284         cancel_lru_locks mdc
28285         cancel_lru_locks osc
28286         sysctl -w vm.drop_caches=2
28287
28288         wait
28289
28290         [ $(cat $tfile) -gt 0 ] || error "wrong nlink count: $(cat $tfile)"
28291
28292         rm -f $tfile $file1 $file2
28293 }
28294 run_test 403 "i_nlink should not drop to zero due to aliasing"
28295
28296 test_404() { # LU-6601
28297         [[ $MDS1_VERSION -ge $(version_code 2.8.53) ]] ||
28298                 skip "Need server version newer than 2.8.52"
28299         remote_mds_nodsh && skip "remote MDS with nodsh"
28300
28301         local mosps=$(do_facet $SINGLEMDS $LCTL dl |
28302                 awk '/osp .*-osc-MDT/ { print $4}')
28303
28304         local osp
28305         for osp in $mosps; do
28306                 echo "Deactivate: " $osp
28307                 do_facet $SINGLEMDS $LCTL --device %$osp deactivate
28308                 local stat=$(do_facet $SINGLEMDS $LCTL dl |
28309                         awk -vp=$osp '$4 == p { print $2 }')
28310                 [ $stat = IN ] || {
28311                         do_facet $SINGLEMDS $LCTL dl | grep -w $osp
28312                         error "deactivate error"
28313                 }
28314                 echo "Activate: " $osp
28315                 do_facet $SINGLEMDS $LCTL --device %$osp activate
28316                 local stat=$(do_facet $SINGLEMDS $LCTL dl |
28317                         awk -vp=$osp '$4 == p { print $2 }')
28318                 [ $stat = UP ] || {
28319                         do_facet $SINGLEMDS $LCTL dl | grep -w $osp
28320                         error "activate error"
28321                 }
28322         done
28323 }
28324 run_test 404 "validate manual {de}activated works properly for OSPs"
28325
28326 test_405() {
28327         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
28328         [ $MDS1_VERSION -lt $(version_code 2.6.92) ] ||
28329                 [ $CLIENT_VERSION -lt $(version_code 2.6.99) ] &&
28330                         skip "Layout swap lock is not supported"
28331
28332         check_swap_layouts_support
28333         check_swap_layout_no_dom $DIR
28334
28335         test_mkdir $DIR/$tdir
28336         swap_lock_test -d $DIR/$tdir ||
28337                 error "One layout swap locked test failed"
28338 }
28339 run_test 405 "Various layout swap lock tests"
28340
28341 test_406() {
28342         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28343         [ $OSTCOUNT -lt 2 ] && skip_env "needs >= 2 OSTs"
28344         [ -n "$FILESET" ] && skip "SKIP due to FILESET set"
28345         [ $PARALLEL == "yes" ] && skip "skip parallel run"
28346         [ $MDS1_VERSION -lt $(version_code 2.8.50) ] &&
28347                 skip "Need MDS version at least 2.8.50"
28348
28349         local def_stripe_size=$($LFS getstripe -S $MOUNT)
28350         local test_pool=$TESTNAME
28351
28352         pool_add $test_pool || error "pool_add failed"
28353         pool_add_targets $test_pool 0 $(($OSTCOUNT - 1)) 1 ||
28354                 error "pool_add_targets failed"
28355
28356         save_layout_restore_at_exit $MOUNT
28357
28358         # parent set default stripe count only, child will stripe from both
28359         # parent and fs default
28360         $LFS setstripe -c 1 -i 1 -S $((def_stripe_size * 2)) -p $test_pool $MOUNT ||
28361                 error "setstripe $MOUNT failed"
28362         $LFS mkdir -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
28363         $LFS setstripe -c $OSTCOUNT $DIR/$tdir || error "setstripe $tdir failed"
28364         for i in $(seq 10); do
28365                 local f=$DIR/$tdir/$tfile.$i
28366                 touch $f || error "touch failed"
28367                 local count=$($LFS getstripe -c $f)
28368                 [ $count -eq $OSTCOUNT ] ||
28369                         error "$f stripe count $count != $OSTCOUNT"
28370                 local offset=$($LFS getstripe -i $f)
28371                 [ $offset -eq 1 ] || error "$f stripe offset $offset != 1"
28372                 local size=$($LFS getstripe -S $f)
28373                 [ $size -eq $((def_stripe_size * 2)) ] ||
28374                         error "$f stripe size $size != $((def_stripe_size * 2))"
28375                 local pool=$($LFS getstripe -p $f)
28376                 [ $pool == $test_pool ] || error "$f pool $pool != $test_pool"
28377         done
28378
28379         # change fs default striping, delete parent default striping, now child
28380         # will stripe from new fs default striping only
28381         $LFS setstripe -c 1 -S $def_stripe_size -i 0 $MOUNT ||
28382                 error "change $MOUNT default stripe failed"
28383         $LFS setstripe -c 0 $DIR/$tdir ||
28384                 error "delete $tdir default stripe failed"
28385         for i in $(seq 11 20); do
28386                 local f=$DIR/$tdir/$tfile.$i
28387                 touch $f || error "touch $f failed"
28388                 local count=$($LFS getstripe -c $f)
28389                 [ $count -eq 1 ] || error "$f stripe count $count != 1"
28390                 local offset=$($LFS getstripe -i $f)
28391                 [ $offset -eq 0 ] || error "$f stripe offset $offset != 0"
28392                 local size=$($LFS getstripe -S $f)
28393                 [ $size -eq $def_stripe_size ] ||
28394                         error "$f stripe size $size != $def_stripe_size"
28395                 local pool=$($LFS getstripe -p $f)
28396                 [ $pool == $test_pool ] || error "$f pool $pool isn't set"
28397         done
28398
28399         unlinkmany $DIR/$tdir/$tfile. 1 20
28400
28401         local f=$DIR/$tdir/$tfile
28402         pool_remove_all_targets $test_pool $f
28403         pool_remove $test_pool $f
28404 }
28405 run_test 406 "DNE support fs default striping"
28406
28407 test_407() {
28408         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
28409         [[ $MDS1_VERSION -lt $(version_code 2.8.55) ]] &&
28410                 skip "Need MDS version at least 2.8.55"
28411         remote_mds_nodsh && skip "remote MDS with nodsh"
28412
28413         $LFS mkdir -i 0 -c 1 $DIR/$tdir.0 ||
28414                 error "$LFS mkdir -i 0 -c 1 $tdir.0 failed"
28415         $LFS mkdir -i 1 -c 1 $DIR/$tdir.1 ||
28416                 error "$LFS mkdir -i 1 -c 1 $tdir.1 failed"
28417         touch $DIR/$tdir.0/$tfile.0 || error "touch $tdir.0/$tfile.0 failed"
28418
28419         #define OBD_FAIL_DT_TXN_STOP    0x2019
28420         for idx in $(seq $MDSCOUNT); do
28421                 do_facet mds$idx "lctl set_param fail_loc=0x2019"
28422         done
28423         $LFS mkdir -c 2 $DIR/$tdir && error "$LFS mkdir -c 2 $tdir should fail"
28424         mv $DIR/$tdir.0/$tfile.0 $DIR/$tdir.1/$tfile.1 &&
28425                 error "mv $tdir.0/$tfile.0 $tdir.1/$tfile.1 should fail"
28426         true
28427 }
28428 run_test 407 "transaction fail should cause operation fail"
28429
28430 test_408() {
28431         dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1 oflag=direct
28432
28433         #define OBD_FAIL_OSC_BRW_PREP_REQ2        0x40a
28434         lctl set_param fail_loc=0x8000040a
28435         # let ll_prepare_partial_page() fail
28436         dd if=/dev/zero of=$DIR/$tfile bs=2048 count=1 conv=notrunc || true
28437
28438         rm -f $DIR/$tfile
28439
28440         # create at least 100 unused inodes so that
28441         # shrink_icache_memory(0) should not return 0
28442         touch $DIR/$tfile-{0..100}
28443         rm -f $DIR/$tfile-{0..100}
28444         sync
28445
28446         echo 2 > /proc/sys/vm/drop_caches
28447 }
28448 run_test 408 "drop_caches should not hang due to page leaks"
28449
28450 test_409()
28451 {
28452         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
28453
28454         mkdir -p $DIR/$tdir || error "(0) Fail to mkdir"
28455         $LFS mkdir -i 1 -c 2 $DIR/$tdir/foo || error "(1) Fail to mkdir"
28456         touch $DIR/$tdir/guard || error "(2) Fail to create"
28457
28458         local PREFIX=$(str_repeat 'A' 128)
28459         echo "Create 1K hard links start at $(date)"
28460         createmany -l $DIR/$tdir/guard $DIR/$tdir/foo/${PREFIX}_ 1000 ||
28461                 error "(3) Fail to hard link"
28462
28463         echo "Links count should be right although linkEA overflow"
28464         stat $DIR/$tdir/guard || error "(4) Fail to stat"
28465         local linkcount=$(stat --format=%h $DIR/$tdir/guard)
28466         [ $linkcount -eq 1001 ] ||
28467                 error "(5) Unexpected hard links count: $linkcount"
28468
28469         echo "List all links start at $(date)"
28470         ls -l $DIR/$tdir/foo > /dev/null ||
28471                 error "(6) Fail to list $DIR/$tdir/foo"
28472
28473         echo "Unlink hard links start at $(date)"
28474         unlinkmany $DIR/$tdir/foo/${PREFIX}_ 1000 ||
28475                 error "(7) Fail to unlink"
28476         echo "Unlink hard links finished at $(date)"
28477 }
28478 run_test 409 "Large amount of cross-MDTs hard links on the same file"
28479
28480 test_410()
28481 {
28482         [[ $CLIENT_VERSION -lt $(version_code 2.9.59) ]] &&
28483                 skip "Need client version at least 2.9.59"
28484
28485         # Create a file, and stat it from the kernel
28486         local testfile=$DIR/$tfile
28487         touch $testfile
28488
28489         local run_id=$RANDOM
28490         local my_ino=$(stat --format "%i" $testfile)
28491
28492         # Try to insert the module.
28493         load_module kunit/kinode run_id=$run_id fname=$testfile ||
28494                 error "load_module failed"
28495
28496         # Anything but success is a test failure
28497         dmesg | grep -q \
28498             "lustre_kinode_$run_id: inode numbers are identical: $my_ino" ||
28499             error "no inode match"
28500
28501         # Remove the test module
28502         rmmod -v kinode ||
28503                 error "rmmod failed (may trigger a failure in a later test)"
28504 }
28505 run_test 410 "Test inode number returned from kernel thread"
28506
28507 cleanup_test411_cgroup() {
28508         trap 0
28509         cat $1/memory.stat
28510         rmdir "$1"
28511 }
28512
28513 test_411a() {
28514         local cg_basedir=/sys/fs/cgroup/memory
28515         # LU-9966
28516         test -f "$cg_basedir/memory.kmem.limit_in_bytes" ||
28517                 skip "no setup for cgroup"
28518
28519         dd if=/dev/zero of=$DIR/$tfile bs=1M count=100 conv=fsync ||
28520                 error "test file creation failed"
28521         cancel_lru_locks osc
28522
28523         # Create a very small memory cgroup to force a slab allocation error
28524         local cgdir=$cg_basedir/osc_slab_alloc
28525         mkdir $cgdir || error "cgroup mkdir '$cgdir' failed"
28526         trap "cleanup_test411_cgroup $cgdir" EXIT
28527         echo 2M > $cgdir/memory.kmem.limit_in_bytes
28528         echo 1M > $cgdir/memory.limit_in_bytes
28529
28530         # Should not LBUG, just be killed by oom-killer
28531         # dd will return 0 even allocation failure in some environment.
28532         # So don't check return value
28533         bash -c "echo \$$ > $cgdir/tasks && dd if=$DIR/$tfile of=/dev/null"
28534         cleanup_test411_cgroup $cgdir
28535
28536         return 0
28537 }
28538 run_test 411a "Slab allocation error with cgroup does not LBUG"
28539
28540 test_411b() {
28541         local cg_basedir=/sys/fs/cgroup/memory
28542         # LU-9966
28543         [ -e "$cg_basedir/memory.kmem.limit_in_bytes" ] ||
28544                 skip "no setup for cgroup"
28545         $LFS setstripe -c 2 $DIR/$tfile || error "unable to setstripe"
28546         # (x86) testing suggests we can't reliably avoid OOM with a 64M-256M
28547         # limit, so we have 384M in cgroup
28548         # (arm) this seems to hit OOM more often than x86, so 1024M
28549         if [[ $(uname -m) = aarch64 ]]; then
28550                 local memlimit_mb=1024
28551         else
28552                 local memlimit_mb=384
28553         fi
28554
28555         # Create a cgroup and set memory limit
28556         # (tfile is used as an easy way to get a recognizable cgroup name)
28557         local cgdir=$cg_basedir/$tfile
28558         mkdir $cgdir || error "cgroup mkdir '$cgdir' failed"
28559         stack_trap "cleanup_test411_cgroup $cgdir" EXIT
28560         echo $((memlimit_mb * 1024 * 1024)) > $cgdir/memory.limit_in_bytes
28561
28562         echo "writing first file"
28563         # Write a file 4x the memory limit in size
28564         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile bs=1M count=$((memlimit_mb * 4))" ||
28565                 error "(1) failed to write successfully"
28566
28567         sync
28568         cancel_lru_locks osc
28569
28570         rm -f $DIR/$tfile
28571         $LFS setstripe -c 2 $DIR/$tfile || error "unable to setstripe"
28572
28573         # Try writing at a larger block size
28574         # NB: if block size is >= 1/2 cgroup size, we sometimes get OOM killed
28575         # so test with 1/4 cgroup size (this seems reasonable to me - we do
28576         # need *some* memory to do IO in)
28577         echo "writing at larger block size"
28578         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile bs=64M count=$((memlimit_mb * 4 / 128))" ||
28579                 error "(3) failed to write successfully"
28580
28581         sync
28582         cancel_lru_locks osc
28583         rm -f $DIR/$tfile
28584         $LFS setstripe -c 2 $DIR/$tfile.{1..4} || error "unable to setstripe"
28585
28586         # Try writing multiple files at once
28587         echo "writing multiple files"
28588         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.1 bs=32M count=$((memlimit_mb * 4 / 64))" &
28589         local pid1=$!
28590         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.2 bs=32M count=$((memlimit_mb * 4 / 64))" &
28591         local pid2=$!
28592         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.3 bs=32M count=$((memlimit_mb * 4 / 64))" &
28593         local pid3=$!
28594         bash -c "echo \$$ > $cgdir/tasks && dd if=/dev/zero of=$DIR/$tfile.4 bs=32M count=$((memlimit_mb * 4 / 64))" &
28595         local pid4=$!
28596
28597         wait $pid1
28598         local rc1=$?
28599         wait $pid2
28600         local rc2=$?
28601         wait $pid3
28602         local rc3=$?
28603         wait $pid4
28604         local rc4=$?
28605         if (( rc1 != 0)); then
28606                 error "error $rc1 writing to file from $pid1"
28607         fi
28608         if (( rc2 != 0)); then
28609                 error "error $rc2 writing to file from $pid2"
28610         fi
28611         if (( rc3 != 0)); then
28612                 error "error $rc3 writing to file from $pid3"
28613         fi
28614         if (( rc4 != 0)); then
28615                 error "error $rc4 writing to file from $pid4"
28616         fi
28617
28618         sync
28619         cancel_lru_locks osc
28620
28621         # These files can be large-ish (~1 GiB total), so delete them rather
28622         # than leave for later cleanup
28623         rm -f $DIR/$tfile.*
28624         return 0
28625 }
28626 run_test 411b "confirm Lustre can avoid OOM with reasonable cgroups limits"
28627
28628 test_412() {
28629         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
28630         (( $MDS1_VERSION >= $(version_code 2.10.55) )) ||
28631                 skip "Need server version at least 2.10.55"
28632
28633         $LFS mkdir -i $((MDSCOUNT - 1)),$((MDSCOUNT - 2)) $DIR/$tdir ||
28634                 error "mkdir failed"
28635         $LFS getdirstripe $DIR/$tdir
28636         local stripe_index=$($LFS getdirstripe -i $DIR/$tdir)
28637         [ $stripe_index -eq $((MDSCOUNT - 1)) ] ||
28638                 error "expect $((MDSCOUT - 1)) get $stripe_index"
28639         local stripe_count=$($LFS getdirstripe -T $DIR/$tdir)
28640         [ $stripe_count -eq 2 ] ||
28641                 error "expect 2 get $stripe_count"
28642
28643         (( $MDS1_VERSION >= $(version_code 2.14.55) )) || return 0
28644
28645         local index
28646         local index2
28647
28648         # subdirs should be on the same MDT as parent
28649         for i in $(seq 0 $((MDSCOUNT - 1))); do
28650                 $LFS mkdir -i $i $DIR/$tdir/mdt$i || error "mkdir mdt$i failed"
28651                 mkdir $DIR/$tdir/mdt$i/sub || error "mkdir sub failed"
28652                 index=$($LFS getstripe -m $DIR/$tdir/mdt$i/sub)
28653                 (( index == i )) || error "mdt$i/sub on MDT$index"
28654         done
28655
28656         # stripe offset -1, ditto
28657         for i in {1..10}; do
28658                 $LFS mkdir -i -1 $DIR/$tdir/qos$i || error "mkdir qos$i failed"
28659                 index=$($LFS getstripe -m $DIR/$tdir/qos$i)
28660                 mkdir $DIR/$tdir/qos$i/sub || error "mkdir sub failed"
28661                 index2=$($LFS getstripe -m $DIR/$tdir/qos$i/sub)
28662                 (( index == index2 )) ||
28663                         error "qos$i on MDT$index, sub on MDT$index2"
28664         done
28665
28666         local testdir=$DIR/$tdir/inherit
28667
28668         $LFS mkdir -i 1 --max-inherit=3 $testdir || error "mkdir inherit failed"
28669         # inherit 2 levels
28670         for i in 1 2; do
28671                 testdir=$testdir/s$i
28672                 mkdir $testdir || error "mkdir $testdir failed"
28673                 index=$($LFS getstripe -m $testdir)
28674                 (( index == 1 )) ||
28675                         error "$testdir on MDT$index"
28676         done
28677
28678         # not inherit any more
28679         testdir=$testdir/s3
28680         mkdir $testdir || error "mkdir $testdir failed"
28681         getfattr -d -m dmv $testdir | grep dmv &&
28682                 error "default LMV set on $testdir" || true
28683 }
28684 run_test 412 "mkdir on specific MDTs"
28685
28686 TEST413_COUNT=${TEST413_COUNT:-200}
28687
28688 #
28689 # set_maxage() is used by test_413 only.
28690 # This is a helper function to set maxage. Does not return any value.
28691 # Input: maxage to set
28692 #
28693 set_maxage() {
28694         local lmv_qos_maxage
28695         local lod_qos_maxage
28696         local new_maxage=$1
28697
28698         lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
28699         $LCTL set_param lmv.*.qos_maxage=$new_maxage
28700         stack_trap "$LCTL set_param \
28701                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null"
28702         lod_qos_maxage=$(do_facet mds1 $LCTL get_param -n \
28703                 lod.$FSNAME-MDT0000-mdtlov.qos_maxage | awk '{ print $1 }')
28704         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
28705                 lod.*.mdt_qos_maxage=$new_maxage
28706         stack_trap "do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
28707                 lod.*.mdt_qos_maxage=$lod_qos_maxage > /dev/null"
28708 }
28709
28710 generate_uneven_mdts() {
28711         local threshold=$1
28712         local ffree
28713         local bavail
28714         local max
28715         local min
28716         local max_index
28717         local min_index
28718         local tmp
28719         local i
28720
28721         echo
28722         echo "Check for uneven MDTs: "
28723
28724         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
28725         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
28726         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
28727
28728         max=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
28729         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
28730         max_index=0
28731         min_index=0
28732         for ((i = 1; i < ${#ffree[@]}; i++)); do
28733                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
28734                 if [ $tmp -gt $max ]; then
28735                         max=$tmp
28736                         max_index=$i
28737                 fi
28738                 if [ $tmp -lt $min ]; then
28739                         min=$tmp
28740                         min_index=$i
28741                 fi
28742         done
28743
28744         (( min > 0 )) || skip "low space on MDT$min_index"
28745         (( ${ffree[min_index]} > 0 )) ||
28746                 skip "no free files on MDT$min_index"
28747         (( ${ffree[min_index]} < 10000000 )) ||
28748                 skip "too many free files on MDT$min_index"
28749
28750         # Check if we need to generate uneven MDTs
28751         local diff=$(((max - min) * 100 / min))
28752         local testdirp=$DIR/$tdir-fillmdt # parent fill folder
28753         local testdir # individual folder within $testdirp
28754         local start
28755         local cmd
28756
28757         # fallocate is faster to consume space on MDT, if available
28758         if check_fallocate_supported mds$((min_index + 1)); then
28759                 cmd="fallocate -l 128K "
28760         else
28761                 cmd="dd if=/dev/zero bs=128K count=1 of="
28762         fi
28763
28764         echo "using cmd $cmd"
28765         for (( i = 0; diff < threshold; i++ )); do
28766                 testdir=${testdirp}/$i
28767                 [ -d $testdir ] && continue
28768
28769                 (( i % 10 > 0 )) || { $LFS df; $LFS df -i; }
28770
28771                 mkdir -p $testdirp
28772                 # generate uneven MDTs, create till $threshold% diff
28773                 echo -n "weight diff=$diff% must be > $threshold% ..."
28774                 echo "Fill MDT$min_index with $TEST413_COUNT files: loop $i"
28775                 $LFS mkdir -i $min_index $testdir ||
28776                         error "mkdir $testdir failed"
28777                 $LFS setstripe -E 1M -L mdt $testdir ||
28778                         error "setstripe $testdir failed"
28779                 start=$SECONDS
28780                 for (( f = 0; f < TEST413_COUNT; f++ )); do
28781                         $cmd$testdir/f.$f &> /dev/null || error "$cmd $f failed"
28782                 done
28783                 sync; sleep 1; sync
28784
28785                 # wait for QOS to update
28786                 (( SECONDS < start + 2 )) && sleep $((start + 2 - SECONDS))
28787
28788                 ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-*.filesfree))
28789                 bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-*.kbytesavail))
28790                 max=$(((${ffree[max_index]} >> 8) *
28791                         (${bavail[max_index]} * bsize >> 16)))
28792                 min=$(((${ffree[min_index]} >> 8) *
28793                         (${bavail[min_index]} * bsize >> 16)))
28794                 (( min > 0 )) || skip "low space on MDT$min_index"
28795                 diff=$(((max - min) * 100 / min))
28796         done
28797
28798         echo "MDT filesfree available: ${ffree[*]}"
28799         echo "MDT blocks available: ${bavail[*]}"
28800         echo "weight diff=$diff%"
28801 }
28802
28803 test_qos_mkdir() {
28804         local mkdir_cmd=$1
28805         local stripe_count=$2
28806         local mdts=$(comma_list $(mdts_nodes))
28807
28808         local testdir
28809         local lmv_qos_prio_free
28810         local lmv_qos_threshold_rr
28811         local lod_qos_prio_free
28812         local lod_qos_threshold_rr
28813         local total
28814         local count
28815         local i
28816
28817         # @total is total directories created if it's testing plain
28818         # directories, otherwise it's total stripe object count for
28819         # striped directories test.
28820         # remote/striped directory unlinking is slow on zfs and may
28821         # timeout, test with fewer directories
28822         [ "$mds1_FSTYPE" = "zfs" ] && total=120 || total=240
28823
28824         lmv_qos_prio_free=$($LCTL get_param -n lmv.*.qos_prio_free | head -n1)
28825         lmv_qos_prio_free=${lmv_qos_prio_free%%%}
28826         lmv_qos_threshold_rr=$($LCTL get_param -n lmv.*.qos_threshold_rr |
28827                 head -n1)
28828         lmv_qos_threshold_rr=${lmv_qos_threshold_rr%%%}
28829         stack_trap "$LCTL set_param \
28830                 lmv.*.qos_prio_free=$lmv_qos_prio_free > /dev/null"
28831         stack_trap "$LCTL set_param \
28832                 lmv.*.qos_threshold_rr=$lmv_qos_threshold_rr > /dev/null"
28833
28834         lod_qos_prio_free=$(do_facet mds1 $LCTL get_param -n \
28835                 lod.$FSNAME-MDT0000-mdtlov.mdt_qos_prio_free | head -n1)
28836         lod_qos_prio_free=${lod_qos_prio_free%%%}
28837         lod_qos_threshold_rr=$(do_facet mds1 $LCTL get_param -n \
28838                 lod.$FSNAME-MDT0000-mdtlov.mdt_qos_threshold_rr | head -n1)
28839         lod_qos_threshold_rr=${lod_qos_threshold_rr%%%}
28840         stack_trap "do_nodes $mdts $LCTL set_param \
28841                 lod.*.mdt_qos_prio_free=$lod_qos_prio_free > /dev/null"
28842         stack_trap "do_nodes $mdts $LCTL set_param \
28843                 lod.*.mdt_qos_threshold_rr=$lod_qos_threshold_rr > /dev/null"
28844
28845         $LCTL set_param lmv.*.qos_threshold_rr=100 > /dev/null
28846         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_threshold_rr=100 > /dev/null
28847
28848         testdir=$DIR/$tdir-s$stripe_count/rr
28849
28850         local stripe_index=$($LFS getstripe -m $testdir)
28851         local test_mkdir_rr=true
28852
28853         getfattr -d -m dmv -e hex $testdir | grep dmv
28854         if (( $? == 0 && $MDS1_VERSION >= $(version_code 2.14.51) )); then
28855                 echo "defstripe: '$($LFS getdirstripe -D $testdir)'"
28856                 (( $($LFS getdirstripe -D --max-inherit-rr $testdir) == 0 )) &&
28857                         test_mkdir_rr=false
28858         fi
28859
28860         echo
28861         $test_mkdir_rr &&
28862                 echo "Mkdir (stripe_count $stripe_count) roundrobin:" ||
28863                 echo "Mkdir (stripe_count $stripe_count) on stripe $stripe_index"
28864
28865         stack_trap "unlinkmany -d $testdir/subdir $((total / stripe_count))"
28866         for (( i = 0; i < total / stripe_count; i++ )); do
28867                 eval $mkdir_cmd $testdir/subdir$i ||
28868                         error "$mkdir_cmd subdir$i failed"
28869         done
28870
28871         for (( i = 0; i < $MDSCOUNT; i++ )); do
28872                 count=$($LFS getdirstripe -i $testdir/* | grep -c "^$i$")
28873                 echo "$count directories created on MDT$i"
28874                 if $test_mkdir_rr; then
28875                         (( count == total / stripe_count / MDSCOUNT )) ||
28876                                 error "subdirs are not evenly distributed"
28877                 elif (( i == stripe_index )); then
28878                         (( count == total / stripe_count )) ||
28879                                 error "$count subdirs created on MDT$i"
28880                 else
28881                         (( count == 0 )) ||
28882                                 error "$count subdirs created on MDT$i"
28883                 fi
28884
28885                 if $test_mkdir_rr && [ $stripe_count -gt 1 ]; then
28886                         count=$($LFS getdirstripe $testdir/* |
28887                                 grep -c -P "^\s+$i\t")
28888                         echo "$count stripes created on MDT$i"
28889                         # deviation should < 5% of average
28890                         delta=$((count - total / MDSCOUNT))
28891                         (( ${delta#-} <= total / MDSCOUNT / 20 )) ||
28892                                 error "stripes are not evenly distributed"
28893                 fi
28894         done
28895
28896         echo
28897         echo "Check for uneven MDTs: "
28898
28899         local ffree
28900         local bavail
28901         local max
28902         local min
28903         local max_index
28904         local min_index
28905         local tmp
28906
28907         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
28908         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
28909         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
28910
28911         max=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
28912         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
28913         max_index=0
28914         min_index=0
28915         for ((i = 1; i < ${#ffree[@]}; i++)); do
28916                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
28917                 if [ $tmp -gt $max ]; then
28918                         max=$tmp
28919                         max_index=$i
28920                 fi
28921                 if [ $tmp -lt $min ]; then
28922                         min=$tmp
28923                         min_index=$i
28924                 fi
28925         done
28926         echo "stripe_count=$stripe_count min_idx=$min_index max_idx=$max_index"
28927
28928         (( min > 0 )) || skip "low space on MDT$min_index"
28929         (( ${ffree[min_index]} < 10000000 )) ||
28930                 skip "too many free files on MDT$min_index"
28931
28932         generate_uneven_mdts 120
28933
28934         echo "MDT filesfree available: ${ffree[*]}"
28935         echo "MDT blocks available: ${bavail[*]}"
28936         echo "weight diff=$(((max - min) * 100 / min))%"
28937         echo
28938         echo "Mkdir (stripe_count $stripe_count) with balanced space usage:"
28939
28940         $LCTL set_param lmv.*.qos_threshold_rr=0 > /dev/null
28941         $LCTL set_param lmv.*.qos_prio_free=100 > /dev/null
28942         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_threshold_rr=0 > /dev/null
28943         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_prio_free=100 > /dev/null
28944         # decrease statfs age, so that it can be updated in time
28945         $LCTL set_param lmv.*.qos_maxage=1 > /dev/null
28946         do_nodes $mdts $LCTL set_param lod.*.mdt_qos_maxage=1 > /dev/null
28947
28948         sleep 1
28949
28950         testdir=$DIR/$tdir-s$stripe_count/qos
28951
28952         stack_trap "unlinkmany -d $testdir/subdir $((total / stripe_count))"
28953         for (( i = 0; i < total / stripe_count; i++ )); do
28954                 eval $mkdir_cmd $testdir/subdir$i ||
28955                         error "$mkdir_cmd subdir$i failed"
28956         done
28957
28958         max=0
28959         for (( i = 0; i < $MDSCOUNT; i++ )); do
28960                 count=$($LFS getdirstripe -i $testdir/* | grep -c "^$i$")
28961                 (( count > max )) && max=$count
28962                 echo "$count directories created on MDT$i : curmax=$max"
28963         done
28964
28965         min=$($LFS getdirstripe -i $testdir/* | grep -c "^$min_index$")
28966
28967         # D-value should > 10% of average
28968         (( max - min > total / stripe_count / MDSCOUNT / 10 )) ||
28969                 error "subdirs shouldn't be evenly distributed: $max - $min <= $((total / stripe_count / MDSCOUNT / 10))"
28970
28971         # ditto for stripes
28972         if (( stripe_count > 1 )); then
28973                 max=0
28974                 for (( i = 0; i < $MDSCOUNT; i++ )); do
28975                         count=$($LFS getdirstripe $testdir/* |
28976                                 grep -c -P "^\s+$i\t")
28977                         (( count > max )) && max=$count
28978                         echo "$count stripes created on MDT$i"
28979                 done
28980
28981                 min=$($LFS getdirstripe $testdir/* |
28982                         grep -c -P "^\s+$min_index\t")
28983                 (( max - min > total / MDSCOUNT / 10 )) ||
28984                         error "stripes shouldn't be evenly distributed: $max - $min <= $((total / MDSCOUNT / 10))"
28985         fi
28986 }
28987
28988 most_full_mdt() {
28989         local ffree
28990         local bavail
28991         local bsize
28992         local min
28993         local min_index
28994         local tmp
28995
28996         ffree=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.filesfree))
28997         bavail=($(lctl get_param -n mdc.*[mM][dD][cC]-[^M]*.kbytesavail))
28998         bsize=$(lctl get_param -n mdc.*MDT0000*.blocksize)
28999
29000         min=$(((${ffree[0]} >> 8) * (${bavail[0]} * bsize >> 16)))
29001         min_index=0
29002         for ((i = 1; i < ${#ffree[@]}; i++)); do
29003                 tmp=$(((${ffree[i]} >> 8) * (${bavail[i]} * bsize >> 16)))
29004                 (( tmp < min )) && min=$tmp && min_index=$i
29005         done
29006
29007         echo -n $min_index
29008 }
29009
29010 test_413a() {
29011         [ $MDSCOUNT -lt 2 ] &&
29012                 skip "We need at least 2 MDTs for this test"
29013
29014         [ $MDS1_VERSION -lt $(version_code 2.12.52) ] &&
29015                 skip "Need server version at least 2.12.52"
29016
29017         local stripe_max=$((MDSCOUNT - 1))
29018         local stripe_count
29019
29020         # let caller set maxage for latest result
29021         set_maxage 1
29022
29023         # fill MDT unevenly
29024         generate_uneven_mdts 120
29025
29026         # test 4-stripe directory at most, otherwise it's too slow
29027         # We are being very defensive. Although Autotest uses 4 MDTs.
29028         # We make sure stripe_max does not go over 4.
29029         (( stripe_max > 4 )) && stripe_max=4
29030         # unlinking striped directory is slow on zfs, and may timeout, only test
29031         # plain directory
29032         [ "$mds1_FSTYPE" == "zfs" ] && stripe_max=1
29033         for stripe_count in $(seq 1 $stripe_max); do
29034                 mkdir $DIR/$tdir-s$stripe_count || error "mkdir failed"
29035                 mkdir $DIR/$tdir-s$stripe_count/rr || error "mkdir failed"
29036                 $LFS mkdir -i $(most_full_mdt) $DIR/$tdir-s$stripe_count/qos ||
29037                         error "mkdir failed"
29038                 test_qos_mkdir "$LFS mkdir -i -1 -c $stripe_count" $stripe_count
29039         done
29040 }
29041 run_test 413a "QoS mkdir with 'lfs mkdir -i -1'"
29042
29043 test_413b() {
29044         [ $MDSCOUNT -lt 2 ] &&
29045                 skip "We need at least 2 MDTs for this test"
29046
29047         [ $MDS1_VERSION -lt $(version_code 2.12.52) ] &&
29048                 skip "Need server version at least 2.12.52"
29049
29050         local stripe_max=$((MDSCOUNT - 1))
29051         local testdir
29052         local stripe_count
29053
29054         # let caller set maxage for latest result
29055         set_maxage 1
29056
29057         # fill MDT unevenly
29058         generate_uneven_mdts 120
29059
29060         # test 4-stripe directory at most, otherwise it's too slow
29061         # We are being very defensive. Although Autotest uses 4 MDTs.
29062         # We make sure stripe_max does not go over 4.
29063         (( stripe_max > 4 )) && stripe_max=4
29064         [ "$mds1_FSTYPE" == "zfs" ] && stripe_max=1
29065         for stripe_count in $(seq 1 $stripe_max); do
29066                 testdir=$DIR/$tdir-s$stripe_count
29067                 mkdir $testdir || error "mkdir $testdir failed"
29068                 mkdir $testdir/rr || error "mkdir rr failed"
29069                 $LFS mkdir -i $(most_full_mdt) $testdir/qos ||
29070                         error "mkdir qos failed"
29071                 $LFS setdirstripe -D -c $stripe_count --max-inherit-rr 2 \
29072                         $testdir/rr || error "setdirstripe rr failed"
29073                 $LFS setdirstripe -D -c $stripe_count $testdir/qos ||
29074                         error "setdirstripe failed"
29075                 test_qos_mkdir "mkdir" $stripe_count
29076         done
29077 }
29078 run_test 413b "QoS mkdir under dir whose default LMV starting MDT offset is -1"
29079
29080 test_413c() {
29081         (( $MDSCOUNT >= 2 )) ||
29082                 skip "We need at least 2 MDTs for this test"
29083
29084         (( $MDS1_VERSION >= $(version_code 2.14.51) )) ||
29085                 skip "Need server version at least 2.14.51"
29086
29087         local testdir
29088         local inherit
29089         local inherit_rr
29090         local lmv_qos_maxage
29091         local lod_qos_maxage
29092
29093         # let caller set maxage for latest result
29094         lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
29095         $LCTL set_param lmv.*.qos_maxage=1
29096         stack_trap "$LCTL set_param \
29097                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null" RETURN
29098         lod_qos_maxage=$(do_facet mds1 $LCTL get_param -n \
29099                 lod.$FSNAME-MDT0000-mdtlov.qos_maxage | awk '{ print $1 }')
29100         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
29101                 lod.*.mdt_qos_maxage=1
29102         stack_trap "do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param \
29103                 lod.*.mdt_qos_maxage=$lod_qos_maxage > /dev/null" RETURN
29104
29105         # fill MDT unevenly
29106         generate_uneven_mdts 120
29107
29108         testdir=$DIR/${tdir}-s1
29109         mkdir $testdir || error "mkdir $testdir failed"
29110         mkdir $testdir/rr || error "mkdir rr failed"
29111         $LFS mkdir -i $(most_full_mdt) $testdir/qos || error "mkdir qos failed"
29112         # default max_inherit is -1, default max_inherit_rr is 0
29113         $LFS setdirstripe -D -c 1 $testdir/rr ||
29114                 error "setdirstripe rr failed"
29115         $LFS setdirstripe -D -c 1 -i -1 -X 2 --max-inherit-rr 1 $testdir/qos ||
29116                 error "setdirstripe qos failed"
29117         test_qos_mkdir "mkdir" 1
29118
29119         mkdir $testdir/rr/level1 || error "mkdir rr/level1 failed"
29120         inherit=$($LFS getdirstripe -D -X $testdir/rr/level1)
29121         (( $inherit == -1 )) || error "rr/level1 inherit $inherit != -1"
29122         inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir/rr/level1)
29123         (( $inherit_rr == 0 )) || error "rr/level1 inherit-rr $inherit_rr != 0"
29124
29125         mkdir $testdir/qos/level1 || error "mkdir qos/level1 failed"
29126         inherit=$($LFS getdirstripe -D -X $testdir/qos/level1)
29127         (( $inherit == 1 )) || error "qos/level1 inherit $inherit != 1"
29128         inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir/qos/level1)
29129         (( $inherit_rr == 0 )) || error "qos/level1 inherit-rr $inherit_rr != 0"
29130         mkdir $testdir/qos/level1/level2 || error "mkdir level2 failed"
29131         getfattr -d -m dmv -e hex $testdir/qos/level1/level2 | grep dmv &&
29132                 error "level2 shouldn't have default LMV" || true
29133 }
29134 run_test 413c "mkdir with default LMV max inherit rr"
29135
29136 test_413d() {
29137         (( MDSCOUNT >= 2 )) ||
29138                 skip "We need at least 2 MDTs for this test"
29139
29140         (( MDS1_VERSION >= $(version_code 2.14.51) )) ||
29141                 skip "Need server version at least 2.14.51"
29142
29143         local lmv_qos_threshold_rr
29144
29145         lmv_qos_threshold_rr=$($LCTL get_param -n lmv.*.qos_threshold_rr |
29146                 head -n1)
29147         stack_trap "$LCTL set_param \
29148                 lmv.*.qos_threshold_rr=$lmv_qos_threshold_rr > /dev/null" EXIT
29149
29150         $LCTL set_param lmv.*.qos_threshold_rr=100 > /dev/null
29151         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
29152         getfattr -d -m dmv -e hex $DIR/$tdir | grep dmv &&
29153                 error "$tdir shouldn't have default LMV"
29154         createmany -d $DIR/$tdir/sub $((100 * MDSCOUNT)) ||
29155                 error "mkdir sub failed"
29156
29157         local count=$($LFS getstripe -m $DIR/$tdir/* | grep -c ^0)
29158
29159         (( count == 100 )) || error "$count subdirs on MDT0"
29160 }
29161 run_test 413d "inherit ROOT default LMV"
29162
29163 test_413e() {
29164         (( MDSCOUNT >= 2 )) ||
29165                 skip "We need at least 2 MDTs for this test"
29166         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
29167                 skip "Need server version at least 2.14.55"
29168
29169         local testdir=$DIR/$tdir
29170         local tmpfile=$TMP/temp.setdirstripe.stderr.$$
29171         local max_inherit
29172         local sub_max_inherit
29173
29174         mkdir -p $testdir || error "failed to create $testdir"
29175
29176         # set default max-inherit to -1 if stripe count is 0 or 1
29177         $LFS setdirstripe -D -c 1 $testdir ||
29178                 error "failed to set default LMV"
29179         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
29180         (( max_inherit == -1 )) ||
29181                 error "wrong max_inherit value $max_inherit"
29182
29183         # set default max_inherit to a fixed value if stripe count is not 0 or 1
29184         $LFS setdirstripe -D -c -1 $testdir ||
29185                 error "failed to set default LMV"
29186         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
29187         (( max_inherit > 0 )) ||
29188                 error "wrong max_inherit value $max_inherit"
29189
29190         # and the subdir will decrease the max_inherit by 1
29191         mkdir -p $testdir/subdir-1 || error "failed to make subdir"
29192         sub_max_inherit=$($LFS getdirstripe -D --max-inherit $testdir/subdir-1)
29193         (( sub_max_inherit == max_inherit - 1)) ||
29194                 error "wrong max-inherit of subdir $sub_max_inherit"
29195
29196         # check specified --max-inherit and warning message
29197         stack_trap "rm -f $tmpfile"
29198         $LFS setdirstripe -D -c 2 --max-inherit=-1 $testdir 2> $tmpfile ||
29199                 error "failed to set default LMV"
29200         max_inherit=$($LFS getdirstripe -D --max-inherit $testdir)
29201         (( max_inherit == -1 )) ||
29202                 error "wrong max_inherit value $max_inherit"
29203
29204         # check the warning messages
29205         if ! [[ $(cat $tmpfile) =~ "max-inherit=" ]]; then
29206                 error "failed to detect warning string"
29207         fi
29208 }
29209 run_test 413e "check default max-inherit value"
29210
29211 test_fs_dmv_inherit()
29212 {
29213         local testdir=$DIR/$tdir
29214
29215         local count
29216         local inherit
29217         local inherit_rr
29218
29219         for i in 1 2; do
29220                 mkdir $testdir || error "mkdir $testdir failed"
29221                 count=$($LFS getdirstripe -D -c $testdir)
29222                 (( count == 1 )) ||
29223                         error "$testdir default LMV count mismatch $count != 1"
29224                 inherit=$($LFS getdirstripe -D -X $testdir)
29225                 (( inherit == 3 - i )) ||
29226                         error "$testdir default LMV max-inherit $inherit != $((3 - i))"
29227                 inherit_rr=$($LFS getdirstripe -D --max-inherit-rr $testdir)
29228                 (( inherit_rr == 3 - i )) ||
29229                         error "$testdir default LMV max-inherit-rr $inherit_rr != $((3 - i))"
29230                 testdir=$testdir/sub
29231         done
29232
29233         mkdir $testdir || error "mkdir $testdir failed"
29234         count=$($LFS getdirstripe -D -c $testdir)
29235         (( count == 0 )) ||
29236                 error "$testdir default LMV count not zero: $count"
29237 }
29238
29239 test_413f() {
29240         (( MDSCOUNT >= 2 )) || skip "We need at least 2 MDTs for this test"
29241
29242         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
29243                 skip "Need server version at least 2.14.55"
29244
29245         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
29246                 error "dump $DIR default LMV failed"
29247         stack_trap "setfattr --restore=$TMP/dmv.ea"
29248
29249         $LFS setdirstripe -D -i -1 -c 1 -X 3 --max-inherit-rr 3 $DIR ||
29250                 error "set $DIR default LMV failed"
29251
29252         test_fs_dmv_inherit
29253 }
29254 run_test 413f "lfs getdirstripe -D list ROOT default LMV if it's not set on dir"
29255
29256 test_413g() {
29257         (( MDSCOUNT >= 2 )) || skip "We need at least 2 MDTs for this test"
29258
29259         mkdir -p $DIR/$tdir/l2/l3/l4 || error "mkdir $tdir/l1/l2/l3 failed"
29260         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
29261                 error "dump $DIR default LMV failed"
29262         stack_trap "setfattr --restore=$TMP/dmv.ea"
29263
29264         $LFS setdirstripe -D -i -1 -c 1 -X 3 --max-inherit-rr 3 $DIR ||
29265                 error "set $DIR default LMV failed"
29266
29267         FILESET="$FILESET/$tdir/l2/l3/l4" mount_client $MOUNT2 ||
29268                 error "mount $MOUNT2 failed"
29269         stack_trap "umount_client $MOUNT2"
29270
29271         local saved_DIR=$DIR
29272
29273         export DIR=$MOUNT2
29274
29275         stack_trap "export DIR=$saved_DIR"
29276
29277         # first check filesystem-wide default LMV inheritance
29278         test_fs_dmv_inherit || error "incorrect fs default LMV inheritance"
29279
29280         # then check subdirs are spread to all MDTs
29281         createmany -d $DIR/s $((MDSCOUNT * 100)) || error "createmany failed"
29282
29283         local count=$($LFS getstripe -m $DIR/s* | sort -u | wc -l)
29284
29285         (( $count == $MDSCOUNT )) || error "dirs are spread to $count MDTs"
29286 }
29287 run_test 413g "enforce ROOT default LMV on subdir mount"
29288
29289 test_413h() {
29290         (( MDSCOUNT >= 2 )) ||
29291                 skip "We need at least 2 MDTs for this test"
29292
29293         (( MDS1_VERSION >= $(version_code 2.15.50.6) )) ||
29294                 skip "Need server version at least 2.15.50.6"
29295
29296         local lmv_qos_maxage=$($LCTL get_param -n lmv.*.qos_maxage)
29297
29298         stack_trap "$LCTL set_param \
29299                 lmv.*.qos_maxage=$lmv_qos_maxage > /dev/null"
29300         $LCTL set_param lmv.*.qos_maxage=1
29301
29302         local depth=5
29303         local rr_depth=4
29304         local dir=$DIR/$tdir/l1/l2/l3/l4/l5
29305         local count=$((MDSCOUNT * 20))
29306
29307         generate_uneven_mdts 50
29308
29309         mkdir -p $dir || error "mkdir $dir failed"
29310         stack_trap "rm -rf $dir"
29311         $LFS setdirstripe -D -c 1 -i -1 --max-inherit=$depth \
29312                 --max-inherit-rr=$rr_depth $dir
29313
29314         for ((d=0; d < depth + 2; d++)); do
29315                 log "dir=$dir:"
29316                 for ((sub=0; sub < count; sub++)); do
29317                         mkdir $dir/d$sub
29318                 done
29319                 $LFS getdirstripe -i $dir/d* | sort | uniq -c | sort -nr
29320                 local num=($($LFS getdirstripe -i $dir/d* | sort | uniq -c))
29321                 # subdirs within $rr_depth should be created round-robin
29322                 if (( d < rr_depth )); then
29323                         (( ${num[0]} != count )) ||
29324                                 error "all objects created on MDT ${num[1]}"
29325                 fi
29326
29327                 dir=$dir/d0
29328         done
29329 }
29330 run_test 413h "don't stick to parent for round-robin dirs"
29331
29332 test_413i() {
29333         [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
29334
29335         (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
29336                 skip "Need server version at least 2.14.55"
29337
29338         getfattr -d -m trusted.dmv --absolute-names $DIR > $TMP/dmv.ea ||
29339                 error "dump $DIR default LMV failed"
29340         stack_trap "setfattr --restore=$TMP/dmv.ea"
29341
29342         local testdir=$DIR/$tdir
29343         local def_max_rr=1
29344         local def_max=3
29345         local count
29346
29347         $LFS setdirstripe -D -i-1 -c1 --max-inherit=$def_max \
29348                 --max-inherit-rr=$def_max_rr $DIR ||
29349                 error "set $DIR default LMV failed"
29350
29351         for i in $(seq 2 3); do
29352                 def_max=$((def_max - 1))
29353                 (( def_max_rr == 0 )) || def_max_rr=$((def_max_rr - 1))
29354
29355                 mkdir $testdir
29356                 # RR is decremented and keeps zeroed once exhausted
29357                 count=$($LFS getdirstripe -D --max-inherit-rr $testdir)
29358                 (( count == def_max_rr )) ||
29359                         error_noexit "$testdir: max-inherit-rr $count != $def_max_rr"
29360
29361                 # max-inherit is decremented
29362                 count=$($LFS getdirstripe -D --max-inherit $testdir)
29363                 (( count == def_max )) ||
29364                         error_noexit "$testdir: max-inherit $count != $def_max"
29365
29366                 testdir=$testdir/d$i
29367         done
29368
29369         # d3 is the last inherited from ROOT, no inheritance anymore
29370         # i.e. no the default layout anymore
29371         mkdir -p $testdir/d4/d5
29372         count=$($LFS getdirstripe -D --max-inherit $testdir)
29373         (( count == -1 )) ||
29374                 error_noexit "$testdir: max-inherit $count != -1"
29375
29376         local p_count=$($LFS getdirstripe -i $testdir)
29377
29378         for i in $(seq 4 5); do
29379                 testdir=$testdir/d$i
29380
29381                 # the root default layout is not applied once exhausted
29382                 count=$($LFS getdirstripe -i $testdir)
29383                 (( count == p_count )) ||
29384                         error_noexit "$testdir: stripe-offset $count != parent offset $p_count"
29385         done
29386
29387         $LFS setdirstripe -i 0 $DIR/d2
29388         count=$($LFS getdirstripe -D --max-inherit $DIR/d2)
29389         (( count == -1 )) ||
29390                 error_noexit "$DIR/d2: max-inherit non-striped default $count != -1"
29391 }
29392 run_test 413i "check default layout inheritance"
29393
29394 test_413j()
29395 {
29396         (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
29397
29398         mkdir -p $DIR/$tdir || error "mkdir $tdir failed"
29399         $LFS setdirstripe -D -c2 --max-inherit=2 $DIR/$tdir ||
29400                 error "setdirstripe $tdir failed"
29401
29402         local value=$(getfattr -n trusted.dmv $DIR/$tdir | \
29403                       grep "trusted.dmv" |sed -e 's/[^=]\+=//')
29404
29405         mkdir -p $DIR/$tdir/sub || error "mkdir sub failed"
29406         # setfattr dmv calls setdirstripe -D
29407         setfattr -n trusted.dmv -v $value $DIR/$tdir/sub ||
29408                 error "setfattr sub failed"
29409         local value2=$(getfattr -n trusted.dmv $DIR/$tdir/sub | \
29410                        grep "trusted.dmv" |sed -e 's/[^=]\+=//')
29411
29412         [ $value == $value2 ] || error "dmv mismatch"
29413
29414         (( MDS1_VERSION >= $(version_code 2.15.58) )) || return 0
29415
29416         # do not allow remove dmv by setfattr -x
29417         do_nodes $(comma_list $(mdts_nodes)) \
29418                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=0"
29419         setfattr -x trusted.dmv $DIR/$tdir/sub || error "setfattr sub failed"
29420         getfattr -n trusted.dmv $DIR/$tdir/sub || error "default LMV deleted"
29421
29422         # allow remove dmv by setfattr -x
29423         do_nodes $(comma_list $(mdts_nodes)) \
29424                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=1"
29425         setfattr -x trusted.dmv $DIR/$tdir/sub || error "setfattr sub failed"
29426         getfattr -n trusted.dmv $DIR/$tdir/sub && error "default LMV exists"
29427         do_nodes $(comma_list $(mdts_nodes)) \
29428                 "$LCTL set_param -n mdt.*MDT*.enable_dmv_xattr=0"
29429 }
29430 run_test 413j "set default LMV by setxattr"
29431
29432 test_413z() {
29433         local pids=""
29434         local subdir
29435         local pid
29436
29437         for subdir in $(\ls -1 -d $DIR/d413*-fillmdt/*); do
29438                 unlinkmany $subdir/f. $TEST413_COUNT &
29439                 pids="$pids $!"
29440         done
29441
29442         for pid in $pids; do
29443                 wait $pid
29444         done
29445
29446         true
29447 }
29448 run_test 413z "413 test cleanup"
29449
29450 test_414() {
29451 #define OBD_FAIL_PTLRPC_BULK_ATTACH      0x521
29452         $LCTL set_param fail_loc=0x80000521
29453         dd if=/dev/zero of=$DIR/$tfile bs=2M count=1 oflag=sync
29454         rm -f $DIR/$tfile
29455 }
29456 run_test 414 "simulate ENOMEM in ptlrpc_register_bulk()"
29457
29458 test_415() {
29459         [[ $PARALLEL == "yes" ]] && skip "skip parallel run"
29460         (( $MDS1_VERSION >= $(version_code 2.11.52) )) ||
29461                 skip "Need server version at least 2.11.52"
29462
29463         # LU-11102
29464         local total=500
29465         local max=120
29466
29467         # this test may be slow on ZFS
29468         [[ "$mds1_FSTYPE" == "zfs" ]] && total=50
29469
29470         # though this test is designed for striped directory, let's test normal
29471         # directory too since lock is always saved as CoS lock.
29472         test_mkdir $DIR/$tdir || error "mkdir $tdir"
29473         createmany -o $DIR/$tdir/$tfile. $total || error "createmany"
29474         stack_trap "unlinkmany $DIR/$tdir/$tfile. $total || true"
29475         # if looping with ONLY_REPEAT, wait for previous deletions to finish
29476         wait_delete_completed_mds
29477
29478         # run a loop without concurrent touch to measure rename duration.
29479         # only for test debug/robustness, NOT part of COS functional test.
29480         local start_time=$SECONDS
29481         for ((i = 0; i < total; i++)); do
29482                 mrename $DIR/$tdir/$tfile.$i $DIR/$tdir/$tfile-new.$i \
29483                         > /dev/null
29484         done
29485         local baseline=$((SECONDS - start_time))
29486         echo "rename $total files without 'touch' took $baseline sec"
29487
29488         (
29489                 while true; do
29490                         touch $DIR/$tdir
29491                 done
29492         ) &
29493         local setattr_pid=$!
29494
29495         # rename files back to original name so unlinkmany works
29496         start_time=$SECONDS
29497         for ((i = 0; i < total; i++)); do
29498                 mrename $DIR/$tdir/$tfile-new.$i $DIR/$tdir/$tfile.$i\
29499                         > /dev/null
29500         done
29501         local duration=$((SECONDS - start_time))
29502
29503         kill -9 $setattr_pid
29504
29505         echo "rename $total files with 'touch' took $duration sec"
29506         (( max > 2 * baseline )) || max=$((2 * baseline + 5))
29507         (( duration <= max )) ||
29508                 error_not_in_vm "rename took $duration > $max sec"
29509 }
29510 run_test 415 "lock revoke is not missing"
29511
29512 test_416() {
29513         [ $MDS1_VERSION -lt $(version_code 2.11.55) ] &&
29514                 skip "Need server version at least 2.11.55"
29515
29516         # define OBD_FAIL_OSD_TXN_START    0x19a
29517         do_facet mds1 lctl set_param fail_loc=0x19a
29518
29519         lfs mkdir -c $MDSCOUNT $DIR/$tdir
29520
29521         true
29522 }
29523 run_test 416 "transaction start failure won't cause system hung"
29524
29525 cleanup_417() {
29526         trap 0
29527         do_nodes $(comma_list $(mdts_nodes)) \
29528                 "$LCTL set_param -n mdt.*MDT*.enable_dir_migration=1"
29529         do_nodes $(comma_list $(mdts_nodes)) \
29530                 "$LCTL set_param -n mdt.*MDT*.enable_remote_dir=1"
29531         do_nodes $(comma_list $(mdts_nodes)) \
29532                 "$LCTL set_param -n mdt.*MDT*.enable_striped_dir=1"
29533 }
29534
29535 test_417() {
29536         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
29537         [[ $MDS1_VERSION -lt $(version_code 2.11.56) ]] &&
29538                 skip "Need MDS version at least 2.11.56"
29539
29540         trap cleanup_417 RETURN EXIT
29541
29542         $LFS mkdir -i 1 $DIR/$tdir.1 || error "create remote dir $tdir.1 failed"
29543         do_nodes $(comma_list $(mdts_nodes)) \
29544                 "$LCTL set_param -n mdt.*MDT*.enable_dir_migration=0"
29545         $LFS migrate -m 0 $DIR/$tdir.1 &&
29546                 error "migrate dir $tdir.1 should fail"
29547
29548         do_nodes $(comma_list $(mdts_nodes)) \
29549                 "$LCTL set_param -n mdt.*MDT*.enable_remote_dir=0"
29550         $LFS mkdir -i 1 $DIR/$tdir.2 &&
29551                 error "create remote dir $tdir.2 should fail"
29552
29553         do_nodes $(comma_list $(mdts_nodes)) \
29554                 "$LCTL set_param -n mdt.*MDT*.enable_striped_dir=0"
29555         $LFS mkdir -c 2 $DIR/$tdir.3 &&
29556                 error "create striped dir $tdir.3 should fail"
29557         true
29558 }
29559 run_test 417 "disable remote dir, striped dir and dir migration"
29560
29561 # Checks that the outputs of df [-i] and lfs df [-i] match
29562 #
29563 # usage: check_lfs_df <blocks | inodes> <mountpoint>
29564 check_lfs_df() {
29565         local dir=$2
29566         local inodes
29567         local df_out
29568         local lfs_df_out
29569         local count
29570         local passed=false
29571
29572         # blocks or inodes
29573         [ "$1" == "blocks" ] && inodes= || inodes="-i"
29574
29575         for count in {1..100}; do
29576                 do_nodes "$CLIENTS" \
29577                         $LCTL set_param ldlm.namespaces.*.lru_size=clear
29578                 sync; sleep 0.2
29579
29580                 # read the lines of interest
29581                 df_out=($(df -P $inodes $dir | tail -n +2)) ||
29582                         error "df $inodes $dir | tail -n +2 failed"
29583                 lfs_df_out=($($LFS df $inodes $dir | grep summary:)) ||
29584                         error "lfs df $inodes $dir | grep summary: failed"
29585
29586                 # skip first substrings of each output as they are different
29587                 # "<NID>:/<fsname>" for df, "filesystem_summary:" for lfs df
29588                 # compare the two outputs
29589                 passed=true
29590                 #  skip "available" on MDT until LU-13997 is fixed.
29591                 #for i in {1..5}; do
29592                 for i in 1 2 4 5; do
29593                         [ "${df_out[i]}" != "${lfs_df_out[i]}" ] && passed=false
29594                 done
29595                 $passed && break
29596         done
29597
29598         if ! $passed; then
29599                 df -P $inodes $dir
29600                 echo
29601                 lfs df $inodes $dir
29602                 error "df and lfs df $1 output mismatch: "      \
29603                       "df ${inodes}: ${df_out[*]}, "            \
29604                       "lfs df ${inodes}: ${lfs_df_out[*]}"
29605         fi
29606 }
29607
29608 test_418() {
29609         [ $PARALLEL == "yes" ] && skip "skip parallel run"
29610
29611         local dir=$DIR/$tdir
29612         local numfiles=$((RANDOM % 4096 + 2))
29613         local numblocks=$((RANDOM % 256 + 1))
29614
29615         wait_delete_completed
29616         test_mkdir $dir
29617
29618         # check block output
29619         check_lfs_df blocks $dir
29620         # check inode output
29621         check_lfs_df inodes $dir
29622
29623         # create a single file and retest
29624         echo "Creating a single file and testing"
29625         createmany -o $dir/$tfile- 1 &>/dev/null ||
29626                 error "creating 1 file in $dir failed"
29627         check_lfs_df blocks $dir
29628         check_lfs_df inodes $dir
29629
29630         # create a random number of files
29631         echo "Creating $((numfiles - 1)) files and testing"
29632         createmany -o $dir/$tfile- 1 $((numfiles - 1)) &>/dev/null ||
29633                 error "creating $((numfiles - 1)) files in $dir failed"
29634
29635         # write a random number of blocks to the first test file
29636         echo "Writing $numblocks 4K blocks and testing"
29637         dd if=/dev/urandom of=$dir/${tfile}-0 bs=4K conv=fsync \
29638                 count=$numblocks &>/dev/null ||
29639                 error "dd to $dir/${tfile}-0 failed"
29640
29641         # retest
29642         check_lfs_df blocks $dir
29643         check_lfs_df inodes $dir
29644
29645         unlinkmany $dir/$tfile- $numfiles &>/dev/null ||
29646                 error "unlinking $numfiles files in $dir failed"
29647 }
29648 run_test 418 "df and lfs df outputs match"
29649
29650 test_419()
29651 {
29652         local dir=$DIR/$tdir
29653
29654         mkdir -p $dir
29655         touch $dir/file
29656
29657         cancel_lru_locks mdc
29658
29659         #OBD_FAIL_LLITE_OPEN_BY_NAME    0x1410
29660         $LCTL set_param fail_loc=0x1410
29661         cat $dir/file
29662         $LCTL set_param fail_loc=0
29663         rm -rf $dir
29664 }
29665 run_test 419 "Verify open file by name doesn't crash kernel"
29666
29667 test_420()
29668 {
29669         [[ $MDS1_VERSION -ge $(version_code 2.12.53) ]] ||
29670                 skip "Need MDS version at least 2.12.53"
29671
29672         local SAVE_UMASK=$(umask)
29673         local dir=$DIR/$tdir
29674         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
29675
29676         mkdir -p $dir
29677         umask 0000
29678         mkdir -m03777 $dir/testdir
29679         ls -dn $dir/testdir
29680         # Need to remove trailing '.' when SELinux is enabled
29681         local dirperms=$(ls -dn $dir/testdir |
29682                          awk '{ sub(/\.$/, "", $1); print $1}')
29683         [ $dirperms == "drwxrwsrwt" ] ||
29684                 error "incorrect perms on $dir/testdir"
29685
29686         su - $uname -c "PATH=$LUSTRE/tests:\$PATH; \
29687                 openfile -f O_RDONLY:O_CREAT -m 02755 $dir/testdir/testfile"
29688         ls -n $dir/testdir/testfile
29689         local fileperms=$(ls -n $dir/testdir/testfile |
29690                           awk '{ sub(/\.$/, "", $1); print $1}')
29691         [ $fileperms == "-rwxr-xr-x" ] ||
29692                 error "incorrect perms on $dir/testdir/testfile"
29693
29694         umask $SAVE_UMASK
29695 }
29696 run_test 420 "clear SGID bit on non-directories for non-members"
29697
29698 test_421a() {
29699         local cnt
29700         local fid1
29701         local fid2
29702
29703         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29704                 skip "Need MDS version at least 2.12.54"
29705
29706         test_mkdir $DIR/$tdir
29707         createmany -o $DIR/$tdir/f 3
29708         cnt=$(ls -1 $DIR/$tdir | wc -l)
29709         [ $cnt != 3 ] && error "unexpected #files: $cnt"
29710
29711         fid1=$(lfs path2fid $DIR/$tdir/f1)
29712         fid2=$(lfs path2fid $DIR/$tdir/f2)
29713         $LFS rmfid $DIR $fid1 $fid2 || error "rmfid failed"
29714
29715         stat $DIR/$tdir/f1 && error "f1 still visible on the client"
29716         stat $DIR/$tdir/f2 && error "f2 still visible on the client"
29717
29718         cnt=$(ls -1 $DIR/$tdir | wc -l)
29719         [ $cnt == 1 ] || error "unexpected #files after: $cnt"
29720
29721         rm -f $DIR/$tdir/f3 || error "can't remove f3"
29722         createmany -o $DIR/$tdir/f 3
29723         cnt=$(ls -1 $DIR/$tdir | wc -l)
29724         [ $cnt != 3 ] && error "unexpected #files: $cnt"
29725
29726         fid1=$(lfs path2fid $DIR/$tdir/f1)
29727         fid2=$(lfs path2fid $DIR/$tdir/f2)
29728         echo "remove using fsname $FSNAME"
29729         $LFS rmfid $FSNAME $fid1 $fid2 || error "rmfid with fsname failed"
29730
29731         cnt=$(ls -1 $DIR/$tdir | wc -l)
29732         [ $cnt == 1 ] || error "unexpected #files after: $cnt"
29733 }
29734 run_test 421a "simple rm by fid"
29735
29736 test_421b() {
29737         local cnt
29738         local FID1
29739         local FID2
29740
29741         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29742                 skip "Need MDS version at least 2.12.54"
29743
29744         test_mkdir $DIR/$tdir
29745         createmany -o $DIR/$tdir/f 3
29746         multiop_bg_pause $DIR/$tdir/f1 o_c || error "multiop failed to start"
29747         MULTIPID=$!
29748
29749         FID1=$(lfs path2fid $DIR/$tdir/f1)
29750         FID2=$(lfs path2fid $DIR/$tdir/f2)
29751         $LFS rmfid $DIR $FID1 $FID2 && error "rmfid didn't fail"
29752
29753         kill -USR1 $MULTIPID
29754         wait
29755
29756         cnt=$(ls $DIR/$tdir | wc -l)
29757         [ $cnt == 2 ] || error "unexpected #files after: $cnt"
29758 }
29759 run_test 421b "rm by fid on open file"
29760
29761 test_421c() {
29762         local cnt
29763         local FIDS
29764
29765         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29766                 skip "Need MDS version at least 2.12.54"
29767
29768         test_mkdir $DIR/$tdir
29769         createmany -o $DIR/$tdir/f 3
29770         touch $DIR/$tdir/$tfile
29771         createmany -l$DIR/$tdir/$tfile $DIR/$tdir/h 180
29772         cnt=$(ls -1 $DIR/$tdir | wc -l)
29773         [ $cnt != 184 ] && error "unexpected #files: $cnt"
29774
29775         FID1=$(lfs path2fid $DIR/$tdir/$tfile)
29776         $LFS rmfid $DIR $FID1 || error "rmfid failed"
29777
29778         cnt=$(ls $DIR/$tdir | wc -l)
29779         [ $cnt == 3 ] || error "unexpected #files after: $cnt"
29780 }
29781 run_test 421c "rm by fid against hardlinked files"
29782
29783 test_421d() {
29784         local cnt
29785         local FIDS
29786
29787         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29788                 skip "Need MDS version at least 2.12.54"
29789
29790         test_mkdir $DIR/$tdir
29791         createmany -o $DIR/$tdir/f 4097
29792         cnt=$(ls -1 $DIR/$tdir | wc -l)
29793         [ $cnt != 4097 ] && error "unexpected #files: $cnt"
29794
29795         FIDS=$(lfs path2fid $DIR/$tdir/f* | sed "s/[/][^:]*://g")
29796         $LFS rmfid $DIR $FIDS || error "rmfid failed"
29797
29798         cnt=$(ls $DIR/$tdir | wc -l)
29799         rm -rf $DIR/$tdir
29800         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
29801 }
29802 run_test 421d "rmfid en masse"
29803
29804 test_421e() {
29805         local cnt
29806         local FID
29807
29808         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
29809         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29810                 skip "Need MDS version at least 2.12.54"
29811
29812         mkdir -p $DIR/$tdir
29813         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
29814         createmany -o $DIR/$tdir/striped_dir/f 512
29815         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
29816         [ $cnt != 512 ] && error "unexpected #files: $cnt"
29817
29818         FIDS=$(lfs path2fid $DIR/$tdir/striped_dir/f* |
29819                 sed "s/[/][^:]*://g")
29820         $LFS rmfid $DIR $FIDS || error "rmfid failed"
29821
29822         cnt=$(ls $DIR/$tdir/striped_dir | wc -l)
29823         rm -rf $DIR/$tdir
29824         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
29825 }
29826 run_test 421e "rmfid in DNE"
29827
29828 test_421f() {
29829         local cnt
29830         local FID
29831
29832         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29833                 skip "Need MDS version at least 2.12.54"
29834
29835         test_mkdir $DIR/$tdir
29836         touch $DIR/$tdir/f
29837         cnt=$(ls -1 $DIR/$tdir | wc -l)
29838         [ $cnt != 1 ] && error "unexpected #files: $cnt"
29839
29840         FID=$(lfs path2fid $DIR/$tdir/f)
29841         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail (1)"
29842         # rmfid should fail
29843         cnt=$(ls -1 $DIR/$tdir | wc -l)
29844         [ $cnt != 1 ] && error "unexpected #files after (2): $cnt"
29845
29846         chmod a+rw $DIR/$tdir
29847         ls -la $DIR/$tdir
29848         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail (2)"
29849         # rmfid should fail
29850         cnt=$(ls -1 $DIR/$tdir | wc -l)
29851         [ $cnt != 1 ] && error "unexpected #files after (3): $cnt"
29852
29853         rm -f $DIR/$tdir/f
29854         $RUNAS touch $DIR/$tdir/f
29855         FID=$(lfs path2fid $DIR/$tdir/f)
29856         echo "rmfid as root"
29857         $LFS rmfid $DIR $FID || error "rmfid as root failed"
29858         cnt=$(ls -1 $DIR/$tdir | wc -l)
29859         [ $cnt == 0 ] || error "unexpected #files after (4): $cnt"
29860
29861         rm -f $DIR/$tdir/f
29862         $RUNAS touch $DIR/$tdir/f
29863         cnt=$(ls -1 $DIR/$tdir | wc -l)
29864         [ $cnt != 1 ] && error "unexpected #files (4): $cnt"
29865         FID=$(lfs path2fid $DIR/$tdir/f)
29866         # rmfid w/o user_fid2path mount option should fail
29867         $RUNAS $LFS rmfid $DIR $FID && error "rmfid didn't fail(3)"
29868         cnt=$(ls -1 $DIR/$tdir | wc -l)
29869         [ $cnt == 1 ] || error "unexpected #files after (5): $cnt"
29870
29871         tmpdir=$(mktemp -d /tmp/lustre-XXXXXX)
29872         stack_trap "rmdir $tmpdir"
29873         mount_client $tmpdir "$MOUNT_OPTS,user_fid2path" ||
29874                 error "failed to mount client'"
29875         stack_trap "umount_client $tmpdir"
29876
29877         $RUNAS $LFS rmfid $tmpdir $FID || error "rmfid failed"
29878         # rmfid should succeed
29879         cnt=$(ls -1 $tmpdir/$tdir | wc -l)
29880         [ $cnt == 0 ] || error "unexpected #files after (6): $cnt"
29881
29882         # rmfid shouldn't allow to remove files due to dir's permission
29883         chmod a+rwx $tmpdir/$tdir
29884         touch $tmpdir/$tdir/f
29885         ls -la $tmpdir/$tdir
29886         FID=$(lfs path2fid $tmpdir/$tdir/f)
29887         $RUNAS $LFS rmfid $tmpdir $FID && error "rmfid didn't fail"
29888         return 0
29889 }
29890 run_test 421f "rmfid checks permissions"
29891
29892 test_421g() {
29893         local cnt
29894         local FIDS
29895
29896         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
29897         [ $MDS1_VERSION -lt $(version_code 2.12.54) ] &&
29898                 skip "Need MDS version at least 2.12.54"
29899
29900         mkdir -p $DIR/$tdir
29901         $LFS setdirstripe -c$MDSCOUNT $DIR/$tdir/striped_dir
29902         createmany -o $DIR/$tdir/striped_dir/f 512
29903         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
29904         [ $cnt != 512 ] && error "unexpected #files: $cnt"
29905
29906         FIDS=$(lfs path2fid $DIR/$tdir/striped_dir/f* |
29907                 sed "s/[/][^:]*://g")
29908
29909         rm -f $DIR/$tdir/striped_dir/f1*
29910         cnt=$(ls -1 $DIR/$tdir/striped_dir | wc -l)
29911         removed=$((512 - cnt))
29912
29913         # few files have been just removed, so we expect
29914         # rmfid to fail on their fids
29915         errors=$($LFS rmfid $DIR $FIDS 2>&1 | wc -l)
29916         [ $removed != $errors ] && error "$errors != $removed"
29917
29918         cnt=$(ls $DIR/$tdir/striped_dir | wc -l)
29919         rm -rf $DIR/$tdir
29920         [ $cnt == 0 ] || error "unexpected #files after: $cnt"
29921 }
29922 run_test 421g "rmfid to return errors properly"
29923
29924 test_421h() {
29925         local mount_other
29926         local mount_ret
29927         local rmfid_ret
29928         local old_fid
29929         local fidA
29930         local fidB
29931         local fidC
29932         local fidD
29933
29934         (( MDS1_VERSION >= $(version_code 2.15.53) )) ||
29935                 skip "Need MDS version at least 2.15.53"
29936
29937         test_mkdir $DIR/$tdir
29938         test_mkdir $DIR/$tdir/subdir
29939         touch $DIR/$tdir/subdir/file0
29940         old_fid=$(lfs path2fid $DIR/$tdir/subdir/file0 | sed "s/[/][^:]*://g")
29941         echo File $DIR/$tdir/subdir/file0 FID $old_fid
29942         rm -f $DIR/$tdir/subdir/file0
29943         touch $DIR/$tdir/subdir/fileA
29944         fidA=$(lfs path2fid $DIR/$tdir/subdir/fileA | sed "s/[/][^:]*://g")
29945         echo File $DIR/$tdir/subdir/fileA FID $fidA
29946         touch $DIR/$tdir/subdir/fileB
29947         fidB=$(lfs path2fid $DIR/$tdir/subdir/fileB | sed "s/[/][^:]*://g")
29948         echo File $DIR/$tdir/subdir/fileB FID $fidB
29949         ln $DIR/$tdir/subdir/fileB $DIR/$tdir/subdir/fileB_hl
29950         touch $DIR/$tdir/subdir/fileC
29951         fidC=$(lfs path2fid $DIR/$tdir/subdir/fileC | sed "s/[/][^:]*://g")
29952         echo File $DIR/$tdir/subdir/fileC FID $fidC
29953         ln $DIR/$tdir/subdir/fileC $DIR/$tdir/fileC
29954         touch $DIR/$tdir/fileD
29955         fidD=$(lfs path2fid $DIR/$tdir/fileD | sed "s/[/][^:]*://g")
29956         echo File $DIR/$tdir/fileD FID $fidD
29957
29958         # mount another client mount point with subdirectory mount
29959         export FILESET=/$tdir/subdir
29960         mount_other=${MOUNT}_other
29961         mount_client $mount_other ${MOUNT_OPTS}
29962         mount_ret=$?
29963         export FILESET=""
29964         (( mount_ret == 0 )) || error "mount $mount_other failed"
29965
29966         echo Removing FIDs:
29967         echo $LFS rmfid $mount_other $old_fid $fidA $fidD $fidB $fidC
29968         $LFS rmfid $mount_other $old_fid $fidA $fidD $fidB $fidC
29969         rmfid_ret=$?
29970
29971         umount_client $mount_other || error "umount $mount_other failed"
29972
29973         (( rmfid_ret != 0 )) || error "rmfid should have failed"
29974
29975         # fileA should have been deleted
29976         stat $DIR/$tdir/subdir/fileA && error "fileA not deleted"
29977
29978         # fileB should have been deleted
29979         stat $DIR/$tdir/subdir/fileB && error "fileB not deleted"
29980
29981         # fileC should not have been deleted, fid also exists outside of fileset
29982         stat $DIR/$tdir/subdir/fileC || error "fileC deleted"
29983
29984         # fileD should not have been deleted, it exists outside of fileset
29985         stat $DIR/$tdir/fileD || error "fileD deleted"
29986 }
29987 run_test 421h "rmfid with fileset mount"
29988
29989 test_422() {
29990         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d1
29991         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d2
29992         test_mkdir -i 0 -c 1 -p $DIR/$tdir/d3
29993         dd if=/dev/zero of=$DIR/$tdir/d1/file1 bs=1k count=1
29994         dd if=/dev/zero of=$DIR/$tdir/d2/file1 bs=1k count=1
29995
29996         local amc=$(at_max_get client)
29997         local amo=$(at_max_get mds1)
29998         local timeout=`lctl get_param -n timeout`
29999
30000         at_max_set 0 client
30001         at_max_set 0 mds1
30002
30003 #define OBD_FAIL_PTLRPC_PAUSE_REQ        0x50a
30004         do_facet mds1 $LCTL set_param fail_loc=0x8000050a \
30005                         fail_val=$(((2*timeout + 10)*1000))
30006         touch $DIR/$tdir/d3/file &
30007         sleep 2
30008 #define OBD_FAIL_TGT_REPLY_DATA_RACE     0x722
30009         do_facet mds1 $LCTL set_param fail_loc=0x80000722 \
30010                         fail_val=$((2*timeout + 5))
30011         mv $DIR/$tdir/d1/file1 $DIR/$tdir/d1/file2 &
30012         local pid=$!
30013         sleep 1
30014         kill -9 $pid
30015         sleep $((2 * timeout))
30016         echo kill $pid
30017         kill -9 $pid
30018         lctl mark touch
30019         touch $DIR/$tdir/d2/file3
30020         touch $DIR/$tdir/d2/file4
30021         touch $DIR/$tdir/d2/file5
30022
30023         wait
30024         at_max_set $amc client
30025         at_max_set $amo mds1
30026
30027         # LU-12838 - verify the ptlrpc thread watchdog is not always throttled
30028         do_facet mds1 "dmesg | grep 'Dumping the stack trace for debugging'" ||
30029                 error "Watchdog is always throttled"
30030 }
30031 run_test 422 "kill a process with RPC in progress"
30032
30033 stat_test() {
30034     df -h $MOUNT &
30035     df -h $MOUNT &
30036     df -h $MOUNT &
30037     df -h $MOUNT &
30038     df -h $MOUNT &
30039     df -h $MOUNT &
30040 }
30041
30042 test_423() {
30043     local _stats
30044     # ensure statfs cache is expired
30045     sleep 2;
30046
30047     _stats=$(stat_test | grep $MOUNT | sort -u | wc -l)
30048     [[ ${_stats} -ne 1 ]] && error "statfs wrong"
30049
30050     return 0
30051 }
30052 run_test 423 "statfs should return a right data"
30053
30054 test_424() {
30055 #define OBD_FAIL_PTLRPC_BULK_REPLY_ATTACH      0x522 | CFS_FAIL_ONCE
30056         $LCTL set_param fail_loc=0x80000522
30057         dd if=/dev/zero of=$DIR/$tfile bs=2M count=1 oflag=sync
30058         rm -f $DIR/$tfile
30059 }
30060 run_test 424 "simulate ENOMEM in ptl_send_rpc bulk reply ME attach"
30061
30062 test_425() {
30063         test_mkdir -c -1 $DIR/$tdir
30064         $LFS setstripe -c -1 $DIR/$tdir
30065
30066         lru_resize_disable "" 100
30067         stack_trap "lru_resize_enable" EXIT
30068
30069         sleep 5
30070
30071         for i in $(seq $((MDSCOUNT * 125))); do
30072                 local t=$DIR/$tdir/$tfile_$i
30073
30074                 dd if=/dev/zero of=$t bs=4K count=1 > /dev/null 2>&1 ||
30075                         error_noexit "Create file $t"
30076         done
30077         stack_trap "rm -rf $DIR/$tdir" EXIT
30078
30079         for oscparam in $($LCTL list_param ldlm.namespaces.*osc-[-0-9a-f]*); do
30080                 local lru_size=$($LCTL get_param -n $oscparam.lru_size)
30081                 local lock_count=$($LCTL get_param -n $oscparam.lock_count)
30082
30083                 [ $lock_count -le $lru_size ] ||
30084                         error "osc lock count $lock_count > lru size $lru_size"
30085         done
30086
30087         for mdcparam in $($LCTL list_param ldlm.namespaces.*mdc-*); do
30088                 local lru_size=$($LCTL get_param -n $mdcparam.lru_size)
30089                 local lock_count=$($LCTL get_param -n $mdcparam.lock_count)
30090
30091                 [ $lock_count -le $lru_size ] ||
30092                         error "mdc lock count $lock_count > lru size $lru_size"
30093         done
30094 }
30095 run_test 425 "lock count should not exceed lru size"
30096
30097 test_426() {
30098         splice-test -r $DIR/$tfile
30099         splice-test -rd $DIR/$tfile
30100         splice-test $DIR/$tfile
30101         splice-test -d $DIR/$tfile
30102 }
30103 run_test 426 "splice test on Lustre"
30104
30105 test_427() {
30106         [ $MDSCOUNT -ge 2 ] || skip "needs >= 2 MDTs"
30107         (( $MDS1_VERSION >= $(version_code 2.12.4) )) ||
30108                 skip "Need MDS version at least 2.12.4"
30109         local log
30110
30111         mkdir $DIR/$tdir
30112         mkdir $DIR/$tdir/1
30113         mkdir $DIR/$tdir/2
30114         test_mkdir -c $MDSCOUNT -i 1 $DIR/$tdir/1/dir
30115         test_mkdir -c $MDSCOUNT -i 1 $DIR/$tdir/2/dir2
30116
30117         $LFS getdirstripe $DIR/$tdir/1/dir
30118
30119         #first setfattr for creating updatelog
30120         setfattr -n user.attr0 -v "some text" $DIR/$tdir/1/dir
30121
30122 #define OBD_FAIL_OUT_OBJECT_MISS        0x1708
30123         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x80001708
30124         setfattr -n user.attr1 -v "some text" $DIR/$tdir/1/dir &
30125         setfattr -n user.attr2 -v "another attr"  $DIR/$tdir/2/dir2 &
30126
30127         sleep 2
30128         fail mds2
30129         wait_recovery_complete mds2 $((2*TIMEOUT))
30130
30131         log=$(do_facet mds1 dmesg | tac | sed "/${TESTNAME//_/ }/,$ d")
30132         echo $log | grep "get update log failed" &&
30133                 error "update log corruption is detected" || true
30134 }
30135 run_test 427 "Failed DNE2 update request shouldn't corrupt updatelog"
30136
30137 test_428() {
30138         [ $PARALLEL == "yes" ] && skip "skip parallel run"
30139         local max_cached_mb=$($LCTL get_param llite.*.max_cached_mb |
30140                               awk '/^max_cached_mb/ { print $2 }')
30141         stack_trap "$LCTL set_param -n llite.*.max_cached_mb=$max_cached_mb"
30142
30143         $LCTL set_param -n llite.*.max_cached_mb=64
30144
30145         mkdir $DIR/$tdir
30146         $LFS setstripe -c 1 $DIR/$tdir
30147         eval touch $DIR/$tdir/$tfile.{1..$OSTCOUNT}
30148         stack_trap "rm -f $DIR/$tdir/$tfile.*"
30149         #test write
30150         for f in $(seq 4); do
30151                 dd if=/dev/zero of=$DIR/$tdir/$tfile.$f bs=128M count=1 &
30152         done
30153         wait
30154
30155         cancel_lru_locks osc
30156         # Test read
30157         for f in $(seq 4); do
30158                 dd if=$DIR/$tdir/$tfile.$f of=/dev/null bs=128M count=1 &
30159         done
30160         wait
30161 }
30162 run_test 428 "large block size IO should not hang"
30163
30164 test_429() { # LU-7915 / LU-10948
30165         local ll_opencache_threshold_count="llite.*.opencache_threshold_count"
30166         local testfile=$DIR/$tfile
30167         local mdc_rpcstats="mdc.$FSNAME-MDT0000-*.stats"
30168         local new_flag=1
30169         local first_rpc
30170         local second_rpc
30171         local third_rpc
30172
30173         $LCTL get_param $ll_opencache_threshold_count ||
30174                 skip "client does not have opencache parameter"
30175
30176         set_opencache $new_flag
30177         stack_trap "restore_opencache"
30178         [ $($LCTL get_param -n $ll_opencache_threshold_count) == $new_flag ] ||
30179                 error "enable opencache failed"
30180         touch $testfile
30181         # drop MDC DLM locks
30182         cancel_lru_locks mdc
30183         # clear MDC RPC stats counters
30184         $LCTL set_param $mdc_rpcstats=clear
30185
30186         # According to the current implementation, we need to run 3 times
30187         # open & close file to verify if opencache is enabled correctly.
30188         # 1st, RPCs are sent for lookup/open and open handle is released on
30189         #      close finally.
30190         # 2nd, RPC is sent for open, MDS_OPEN_LOCK is fetched automatically,
30191         #      so open handle won't be released thereafter.
30192         # 3rd, No RPC is sent out.
30193         $MULTIOP $testfile oc || error "multiop failed"
30194         first_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
30195         echo "1st: $first_rpc RPCs in flight"
30196
30197         $MULTIOP $testfile oc || error "multiop failed"
30198         second_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
30199         echo "2nd: $second_rpc RPCs in flight"
30200
30201         $MULTIOP $testfile oc || error "multiop failed"
30202         third_rpc=$(calc_stats $mdc_rpcstats ldlm_ibits_enqueue)
30203         echo "3rd: $third_rpc RPCs in flight"
30204
30205         #verify no MDC RPC is sent
30206         [[ $second_rpc == $third_rpc ]] || error "MDC RPC is still sent"
30207 }
30208 run_test 429 "verify if opencache flag on client side does work"
30209
30210 lseek_test_430() {
30211         local offset
30212         local file=$1
30213
30214         # data at [200K, 400K)
30215         dd if=/dev/urandom of=$file bs=256K count=1 seek=1 ||
30216                 error "256K->512K dd fails"
30217         # data at [2M, 3M)
30218         dd if=/dev/urandom of=$file bs=1M count=1 seek=2 ||
30219                 error "2M->3M dd fails"
30220         # data at [4M, 5M)
30221         dd if=/dev/urandom of=$file bs=1M count=1 seek=4 ||
30222                 error "4M->5M dd fails"
30223         echo "Data at 256K...512K, 2M...3M and 4M...5M"
30224         # start at first component hole #1
30225         printf "Seeking hole from 1000 ... "
30226         offset=$(lseek_test -l 1000 $file)
30227         echo $offset
30228         [[ $offset == 1000 ]] || error "offset $offset != 1000"
30229         printf "Seeking data from 1000 ... "
30230         offset=$(lseek_test -d 1000 $file)
30231         echo $offset
30232         [[ $offset == 262144 ]] || error "offset $offset != 262144"
30233
30234         # start at first component data block
30235         printf "Seeking hole from 300000 ... "
30236         offset=$(lseek_test -l 300000 $file)
30237         echo $offset
30238         [[ $offset == 524288 ]] || error "offset $offset != 524288"
30239         printf "Seeking data from 300000 ... "
30240         offset=$(lseek_test -d 300000 $file)
30241         echo $offset
30242         [[ $offset == 300000 ]] || error "offset $offset != 300000"
30243
30244         # start at the first component but beyond end of object size
30245         printf "Seeking hole from 1000000 ... "
30246         offset=$(lseek_test -l 1000000 $file)
30247         echo $offset
30248         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
30249         printf "Seeking data from 1000000 ... "
30250         offset=$(lseek_test -d 1000000 $file)
30251         echo $offset
30252         [[ $offset == 2097152 ]] || error "offset $offset != 2097152"
30253
30254         # start at second component stripe 2 (empty file)
30255         printf "Seeking hole from 1500000 ... "
30256         offset=$(lseek_test -l 1500000 $file)
30257         echo $offset
30258         [[ $offset == 1500000 ]] || error "offset $offset != 1500000"
30259         printf "Seeking data from 1500000 ... "
30260         offset=$(lseek_test -d 1500000 $file)
30261         echo $offset
30262         [[ $offset == 2097152 ]] || error "offset $offset != 2097152"
30263
30264         # start at second component stripe 1 (all data)
30265         printf "Seeking hole from 3000000 ... "
30266         offset=$(lseek_test -l 3000000 $file)
30267         echo $offset
30268         [[ $offset == 3145728 ]] || error "offset $offset != 3145728"
30269         printf "Seeking data from 3000000 ... "
30270         offset=$(lseek_test -d 3000000 $file)
30271         echo $offset
30272         [[ $offset == 3000000 ]] || error "offset $offset != 3000000"
30273
30274         dd if=/dev/urandom of=$file bs=640K count=1 seek=1 ||
30275                 error "2nd dd fails"
30276         echo "Add data block at 640K...1280K"
30277
30278         # start at before new data block, in hole
30279         printf "Seeking hole from 600000 ... "
30280         offset=$(lseek_test -l 600000 $file)
30281         echo $offset
30282         [[ $offset == 600000 ]] || error "offset $offset != 600000"
30283         printf "Seeking data from 600000 ... "
30284         offset=$(lseek_test -d 600000 $file)
30285         echo $offset
30286         [[ $offset == 655360 ]] || error "offset $offset != 655360"
30287
30288         # start at the first component new data block
30289         printf "Seeking hole from 1000000 ... "
30290         offset=$(lseek_test -l 1000000 $file)
30291         echo $offset
30292         [[ $offset == 1310720 ]] || error "offset $offset != 1310720"
30293         printf "Seeking data from 1000000 ... "
30294         offset=$(lseek_test -d 1000000 $file)
30295         echo $offset
30296         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
30297
30298         # start at second component stripe 2, new data
30299         printf "Seeking hole from 1200000 ... "
30300         offset=$(lseek_test -l 1200000 $file)
30301         echo $offset
30302         [[ $offset == 1310720 ]] || error "offset $offset != 1310720"
30303         printf "Seeking data from 1200000 ... "
30304         offset=$(lseek_test -d 1200000 $file)
30305         echo $offset
30306         [[ $offset == 1200000 ]] || error "offset $offset != 1200000"
30307
30308         # start beyond file end
30309         printf "Using offset > filesize ... "
30310         lseek_test -l 4000000 $file && error "lseek should fail"
30311         printf "Using offset > filesize ... "
30312         lseek_test -d 4000000 $file && error "lseek should fail"
30313
30314         printf "Done\n\n"
30315 }
30316
30317 test_430a() {
30318         $LCTL get_param mdc.*.import | grep -q 'connect_flags:.*seek' ||
30319                 skip "MDT does not support SEEK_HOLE"
30320
30321         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
30322                 skip "OST does not support SEEK_HOLE"
30323
30324         local file=$DIR/$tdir/$tfile
30325
30326         mkdir -p $DIR/$tdir
30327
30328         $LFS setstripe -E 1M -L mdt -E eof -c2 $file
30329         # OST stripe #1 will have continuous data at [1M, 3M)
30330         # OST stripe #2 is empty
30331         echo "Component #1: 1M DoM, component #2: EOF, 2 stripes 1M"
30332         lseek_test_430 $file
30333         rm $file
30334         $LFS setstripe -E 1M -c2 -S 64K -E 10M -c2 -S 1M $file
30335         echo "Component #1: 1M, 2 stripes 64K, component #2: EOF, 2 stripes 1M"
30336         lseek_test_430 $file
30337         rm $file
30338         $LFS setstripe -c2 -S 512K $file
30339         echo "Two stripes, stripe size 512K"
30340         lseek_test_430 $file
30341         rm $file
30342         # FLR with stale mirror
30343         $LFS setstripe -N -E 512K -c1 -S 64K -E eof -c2 -S 512K \
30344                        -N -c2 -S 1M $file
30345         echo "Mirrored file:"
30346         echo "Component #1: 512K, stripe 64K, component #2: EOF, 2 stripes 512K"
30347         echo "Plain 2 stripes 1M"
30348         lseek_test_430 $file
30349         rm $file
30350 }
30351 run_test 430a "lseek: SEEK_DATA/SEEK_HOLE basic functionality"
30352
30353 test_430b() {
30354         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
30355                 skip "OST does not support SEEK_HOLE"
30356
30357         local offset
30358         local file=$DIR/$tdir/$tfile
30359
30360         mkdir -p $DIR/$tdir
30361         # Empty layout lseek should fail
30362         $MCREATE $file
30363         # seek from 0
30364         printf "Seeking hole from 0 ... "
30365         lseek_test -l 0 $file && error "lseek should fail"
30366         printf "Seeking data from 0 ... "
30367         lseek_test -d 0 $file && error "lseek should fail"
30368         rm $file
30369
30370         # 1M-hole file
30371         $LFS setstripe -E 1M -c2 -E eof $file
30372         $TRUNCATE $file 1048576
30373         printf "Seeking hole from 1000000 ... "
30374         offset=$(lseek_test -l 1000000 $file)
30375         echo $offset
30376         [[ $offset == 1000000 ]] || error "offset $offset != 1000000"
30377         printf "Seeking data from 1000000 ... "
30378         lseek_test -d 1000000 $file && error "lseek should fail"
30379         rm $file
30380
30381         # full component followed by non-inited one
30382         $LFS setstripe -E 1M -c2 -E eof $file
30383         dd if=/dev/urandom of=$file bs=1M count=1
30384         printf "Seeking hole from 1000000 ... "
30385         offset=$(lseek_test -l 1000000 $file)
30386         echo $offset
30387         [[ $offset == 1048576 ]] || error "offset $offset != 1048576"
30388         printf "Seeking hole from 1048576 ... "
30389         lseek_test -l 1048576 $file && error "lseek should fail"
30390         # init second component and truncate back
30391         echo "123" >> $file
30392         $TRUNCATE $file 1048576
30393         printf "Seeking hole from 1000000 ... "
30394         offset=$(lseek_test -l 1000000 $file)
30395         echo $offset
30396         [[ $offset == 1048576 ]] || error "offset $offset != 1048576"
30397         printf "Seeking hole from 1048576 ... "
30398         lseek_test -l 1048576 $file && error "lseek should fail"
30399         # boundary checks for big values
30400         dd if=/dev/urandom of=$file.10g bs=1 count=1 seek=10G
30401         offset=$(lseek_test -d 0 $file.10g)
30402         [[ $offset == 10737418240 ]] || error "offset $offset != 10737418240"
30403         dd if=/dev/urandom of=$file.100g bs=1 count=1 seek=100G
30404         offset=$(lseek_test -d 0 $file.100g)
30405         [[ $offset == 107374182400 ]] || error "offset $offset != 107374182400"
30406         return 0
30407 }
30408 run_test 430b "lseek: SEEK_DATA/SEEK_HOLE special cases"
30409
30410 test_430c() {
30411         $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' ||
30412                 skip "OST does not support SEEK_HOLE"
30413
30414         local file=$DIR/$tdir/$tfile
30415         local start
30416
30417         mkdir -p $DIR/$tdir
30418         stack_trap "rm -f $file $file.tmp"
30419         dd if=/dev/urandom of=$file bs=1k count=1 seek=5M || error "dd failed"
30420
30421         # cp version 8.33+ prefers lseek over fiemap
30422         local ver=$(cp --version | awk '{ print $4; exit; }')
30423
30424         echo "cp $ver installed"
30425         if (( $(version_code $ver) >= $(version_code 8.33) )); then
30426                 start=$SECONDS
30427                 time cp -v $file $file.tmp || error "cp $file failed"
30428                 (( SECONDS - start < 5 )) || {
30429                         strace cp $file $file.tmp |&
30430                                 grep -E "open|read|seek|FIEMAP" |
30431                                 grep -A 100 $file
30432                         error "cp: too long runtime $((SECONDS - start))"
30433                 }
30434         else
30435                 echo "cp test skipped due to $ver < 8.33"
30436         fi
30437
30438         # tar version 1.29+ supports SEEK_HOLE/DATA
30439         ver=$(tar --version | awk '{ print $4; exit; }')
30440         echo "tar $ver installed"
30441         if (( $(version_code $ver) >= $(version_code 1.29) )); then
30442                 start=$SECONDS
30443                 time tar cvf $file.tmp --sparse $file || error "tar $file error"
30444                 (( SECONDS - start < 5 )) || {
30445                         strace tar cf $file.tmp --sparse $file |&
30446                                 grep -E "open|read|seek|FIEMAP" |
30447                                 grep -A 100 $file
30448                         error "tar: too long runtime $((SECONDS - start))"
30449                 }
30450         else
30451                 echo "tar test skipped due to $ver < 1.29"
30452         fi
30453 }
30454 run_test 430c "lseek: external tools check"
30455
30456 test_431() { # LU-14187
30457         local file=$DIR/$tdir/$tfile
30458
30459         mkdir -p $DIR/$tdir
30460         $LFS setstripe -c 1 -i 0 $file || error "lfs setstripe failed"
30461         dd if=/dev/urandom of=$file bs=4k count=1
30462         dd if=/dev/urandom of=$file bs=4k count=1 seek=10 conv=notrunc
30463         dd if=/dev/urandom of=$file bs=4k count=1 seek=12 conv=notrunc
30464         #define OBD_FAIL_OST_RESTART_IO 0x251
30465         do_facet ost1 "$LCTL set_param fail_loc=0x251"
30466         $LFS setstripe -c 1 -i 0 $file.0 || error "lfs setstripe failed"
30467         cp $file $file.0
30468         cancel_lru_locks
30469         sync_all_data
30470         echo 3 > /proc/sys/vm/drop_caches
30471         diff  $file $file.0 || error "data diff"
30472 }
30473 run_test 431 "Restart transaction for IO"
30474
30475 cleanup_test_432() {
30476         do_facet mgs $LCTL nodemap_activate 0
30477         wait_nm_sync active
30478 }
30479
30480 test_432() {
30481         local tmpdir=$TMP/dir432
30482
30483         (( $MDS1_VERSION >= $(version_code 2.14.52) )) ||
30484                 skip "Need MDS version at least 2.14.52"
30485
30486         stack_trap cleanup_test_432 EXIT
30487         mkdir $DIR/$tdir
30488         mkdir $tmpdir
30489
30490         do_facet mgs $LCTL nodemap_activate 1
30491         wait_nm_sync active
30492         do_facet mgs $LCTL nodemap_modify --name default \
30493                 --property admin --value 1
30494         do_facet mgs $LCTL nodemap_modify --name default \
30495                 --property trusted --value 1
30496         cancel_lru_locks mdc
30497         wait_nm_sync default admin_nodemap
30498         wait_nm_sync default trusted_nodemap
30499
30500         if [ $(mv $tmpdir $DIR/$tdir/ 2>&1 |
30501                grep -ci "Operation not permitted") -ne 0 ]; then
30502                 error "mv $tmpdir $DIR/$tdir/ hits 'Operation not permitted'"
30503         fi
30504 }
30505 run_test 432 "mv dir from outside Lustre"
30506
30507 test_433() {
30508         [ $PARALLEL == "yes" ] && skip "skip parallel run"
30509
30510         [[ -n "$($LCTL list_param llite.*.inode_cache 2>/dev/null)" ]] ||
30511                 skip "inode cache not supported"
30512
30513         $LCTL set_param llite.*.inode_cache=0
30514         stack_trap "$LCTL set_param llite.*.inode_cache=1"
30515
30516         local count=256
30517         local before
30518         local after
30519
30520         cancel_lru_locks mdc
30521         test_mkdir $DIR/$tdir || error "mkdir $tdir"
30522         createmany -m $DIR/$tdir/f $count
30523         createmany -d $DIR/$tdir/d $count
30524         ls -l $DIR/$tdir > /dev/null
30525         stack_trap "rm -rf $DIR/$tdir"
30526
30527         before=$(num_objects)
30528         cancel_lru_locks mdc
30529         after=$(num_objects)
30530
30531         # sometimes even @before is less than 2 * count
30532         while (( before - after < count )); do
30533                 sleep 1
30534                 after=$(num_objects)
30535                 wait=$((wait + 1))
30536                 (( wait % 5 == 0 )) && echo "wait $wait seconds objects: $after"
30537                 if (( wait > 60 )); then
30538                         error "inode slab grew from $before to $after"
30539                 fi
30540         done
30541
30542         echo "lustre_inode_cache $before objs before lock cancel, $after after"
30543 }
30544 run_test 433 "ldlm lock cancel releases dentries and inodes"
30545
30546 test_434() {
30547         local file
30548         local getxattr_count
30549         local mdc_stat_param="mdc.$FSNAME-MDT0000*.md_stats"
30550         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
30551
30552         [[ $(getenforce) == "Disabled" ]] ||
30553                 skip "lsm selinux module have to be disabled for this test"
30554
30555         test_mkdir -i 0 -c1 $DIR/$tdir/ ||
30556                 error "fail to create $DIR/$tdir/ on MDT0000"
30557
30558         touch $DIR/$tdir/$tfile-{001..100}
30559
30560         # disable the xattr cache
30561         save_lustre_params client "llite.*.xattr_cache" > $p
30562         lctl set_param llite.*.xattr_cache=0
30563         stack_trap "restore_lustre_params < $p; rm -f $p" EXIT
30564
30565         # clear clients mdc stats
30566         clear_stats $mdc_stat_param ||
30567                 error "fail to clear stats on mdc MDT0000"
30568
30569         for file in $DIR/$tdir/$tfile-{001..100}; do
30570                 getfattr -n security.selinux $file |&
30571                         grep -q "Operation not supported" ||
30572                         error "getxattr on security.selinux should return EOPNOTSUPP"
30573         done
30574
30575         getxattr_count=$(calc_stats $mdc_stat_param "getxattr")
30576         (( getxattr_count < 100 )) ||
30577                 error "client sent $getxattr_count getxattr RPCs to the MDS"
30578 }
30579 run_test 434 "Client should not send RPCs for security.selinux with SElinux disabled"
30580
30581 test_440() {
30582         if [[ -f $LUSTRE/scripts/bash-completion/lustre ]]; then
30583                 source $LUSTRE/scripts/bash-completion/lustre
30584         elif [[ -f /usr/share/bash-completion/completions/lustre ]]; then
30585                 source /usr/share/bash-completion/completions/lustre
30586         else
30587                 skip "bash completion scripts not found"
30588         fi
30589
30590         local lctl_completions
30591         local lfs_completions
30592
30593         lctl_completions=$(_lustre_cmds lctl)
30594         if [[ ! $lctl_completions =~ "get_param" ]]; then
30595                 error "lctl bash completion failed"
30596         fi
30597
30598         lfs_completions=$(_lustre_cmds lfs)
30599         if [[ ! $lfs_completions =~ "setstripe" ]]; then
30600                 error "lfs bash completion failed"
30601         fi
30602 }
30603 run_test 440 "bash completion for lfs, lctl"
30604
30605 test_442() {
30606         local pid1
30607         local pid2
30608         mkdir -p $DIR/$tdir
30609         multiop $DIR/$tdir/$tfile.1 O_w1 & pid1=$!
30610         multiop $DIR/$tdir/$tfile.1 O_w1 & pid2=$!
30611         sleep 1
30612         touch $DIR/$tdir/$tfile.2
30613         $LFS swap_layouts -n $DIR/$tdir/$tfile.1 $DIR/$tdir/$tfile.2
30614         $LCTL set_param fail_loc=0x1430
30615         kill -USR1 $pid1
30616         sleep 1
30617         kill -USR1 $pid2
30618         wait
30619 }
30620 run_test 442 "truncate vs read/write should not panic"
30621
30622 test_460d() {
30623         verify_yaml_available || skip_env "YAML verification not installed"
30624         $LCTL get_param -n sptlrpc.page_pools
30625         $LCTL get_param -n sptlrpc.page_pools | verify_yaml ||
30626                 error "The output of encrypt_page_pools is not an valid YAML"
30627 }
30628 run_test 460d "Check encrypt pools output"
30629
30630 prep_801() {
30631         [[ $MDS1_VERSION -lt $(version_code 2.9.55) ]] ||
30632         [[ $OST1_VERSION -lt $(version_code 2.9.55) ]] &&
30633                 skip "Need server version at least 2.9.55"
30634
30635         start_full_debug_logging
30636 }
30637
30638 post_801() {
30639         stop_full_debug_logging
30640 }
30641
30642 barrier_stat() {
30643         if [ $MGS_VERSION -le $(version_code 2.10.0) ]; then
30644                 local st=$(do_facet mgs $LCTL barrier_stat $FSNAME |
30645                            awk '/The barrier for/ { print $7 }')
30646                 echo $st
30647         else
30648                 local st=$(do_facet mgs $LCTL barrier_stat -s $FSNAME)
30649                 echo \'$st\'
30650         fi
30651 }
30652
30653 barrier_expired() {
30654         local expired
30655
30656         if [ $MGS_VERSION -le $(version_code 2.10.0) ]; then
30657                 expired=$(do_facet mgs $LCTL barrier_stat $FSNAME |
30658                           awk '/will be expired/ { print $7 }')
30659         else
30660                 expired=$(do_facet mgs $LCTL barrier_stat -t $FSNAME)
30661         fi
30662
30663         echo $expired
30664 }
30665
30666 test_801a() {
30667         prep_801
30668
30669         echo "Start barrier_freeze at: $(date)"
30670         #define OBD_FAIL_BARRIER_DELAY          0x2202
30671         do_facet mgs $LCTL set_param fail_val=5 fail_loc=0x2202
30672         # Do not reduce barrier time - See LU-11873
30673         do_facet mgs $LCTL barrier_freeze $FSNAME 20 &
30674
30675         sleep 2
30676         local b_status=$(barrier_stat)
30677         echo "Got barrier status at: $(date)"
30678         [ "$b_status" = "'freezing_p1'" ] ||
30679                 error "(1) unexpected barrier status $b_status"
30680
30681         do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
30682         wait
30683         b_status=$(barrier_stat)
30684         [ "$b_status" = "'frozen'" ] ||
30685                 error "(2) unexpected barrier status $b_status"
30686
30687         local expired=$(barrier_expired)
30688         echo "sleep $((expired + 3)) seconds, then the barrier will be expired"
30689         sleep $((expired + 3))
30690
30691         b_status=$(barrier_stat)
30692         [ "$b_status" = "'expired'" ] ||
30693                 error "(3) unexpected barrier status $b_status"
30694
30695         # Do not reduce barrier time - See LU-11873
30696         do_facet mgs $LCTL barrier_freeze $FSNAME 20 ||
30697                 error "(4) fail to freeze barrier"
30698
30699         b_status=$(barrier_stat)
30700         [ "$b_status" = "'frozen'" ] ||
30701                 error "(5) unexpected barrier status $b_status"
30702
30703         echo "Start barrier_thaw at: $(date)"
30704         #define OBD_FAIL_BARRIER_DELAY          0x2202
30705         do_facet mgs $LCTL set_param fail_val=5 fail_loc=0x2202
30706         do_facet mgs $LCTL barrier_thaw $FSNAME &
30707
30708         sleep 2
30709         b_status=$(barrier_stat)
30710         echo "Got barrier status at: $(date)"
30711         [ "$b_status" = "'thawing'" ] ||
30712                 error "(6) unexpected barrier status $b_status"
30713
30714         do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
30715         wait
30716         b_status=$(barrier_stat)
30717         [ "$b_status" = "'thawed'" ] ||
30718                 error "(7) unexpected barrier status $b_status"
30719
30720         #define OBD_FAIL_BARRIER_FAILURE        0x2203
30721         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2203
30722         do_facet mgs $LCTL barrier_freeze $FSNAME
30723
30724         b_status=$(barrier_stat)
30725         [ "$b_status" = "'failed'" ] ||
30726                 error "(8) unexpected barrier status $b_status"
30727
30728         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
30729         do_facet mgs $LCTL barrier_thaw $FSNAME
30730
30731         post_801
30732 }
30733 run_test 801a "write barrier user interfaces and stat machine"
30734
30735 test_801b() {
30736         prep_801
30737
30738         mkdir $DIR/$tdir || error "(1) fail to mkdir"
30739         createmany -d $DIR/$tdir/d 6 || error "(2) fail to mkdir"
30740         touch $DIR/$tdir/d2/f10 || error "(3) fail to touch"
30741         touch $DIR/$tdir/d3/f11 || error "(4) fail to touch"
30742         touch $DIR/$tdir/d4/f12 || error "(5) fail to touch"
30743
30744         cancel_lru_locks mdc
30745
30746         # 180 seconds should be long enough
30747         do_facet mgs $LCTL barrier_freeze $FSNAME 180
30748
30749         local b_status=$(barrier_stat)
30750         [ "$b_status" = "'frozen'" ] ||
30751                 error "(6) unexpected barrier status $b_status"
30752
30753         mkdir $DIR/$tdir/d0/d10 &
30754         mkdir_pid=$!
30755
30756         touch $DIR/$tdir/d1/f13 &
30757         touch_pid=$!
30758
30759         ln $DIR/$tdir/d2/f10 $DIR/$tdir/d2/f14 &
30760         ln_pid=$!
30761
30762         mv $DIR/$tdir/d3/f11 $DIR/$tdir/d3/f15 &
30763         mv_pid=$!
30764
30765         rm -f $DIR/$tdir/d4/f12 &
30766         rm_pid=$!
30767
30768         stat $DIR/$tdir/d5 || error "(7) stat should succeed"
30769
30770         # To guarantee taht the 'stat' is not blocked
30771         b_status=$(barrier_stat)
30772         [ "$b_status" = "'frozen'" ] ||
30773                 error "(8) unexpected barrier status $b_status"
30774
30775         # let above commands to run at background
30776         sleep 5
30777
30778         ps -p $mkdir_pid || error "(9) mkdir should be blocked"
30779         ps -p $touch_pid || error "(10) touch should be blocked"
30780         ps -p $ln_pid || error "(11) link should be blocked"
30781         ps -p $mv_pid || error "(12) rename should be blocked"
30782         ps -p $rm_pid || error "(13) unlink should be blocked"
30783
30784         b_status=$(barrier_stat)
30785         [ "$b_status" = "'frozen'" ] ||
30786                 error "(14) unexpected barrier status $b_status"
30787
30788         do_facet mgs $LCTL barrier_thaw $FSNAME
30789         b_status=$(barrier_stat)
30790         [ "$b_status" = "'thawed'" ] ||
30791                 error "(15) unexpected barrier status $b_status"
30792
30793         wait $mkdir_pid || error "(16) mkdir should succeed"
30794         wait $touch_pid || error "(17) touch should succeed"
30795         wait $ln_pid || error "(18) link should succeed"
30796         wait $mv_pid || error "(19) rename should succeed"
30797         wait $rm_pid || error "(20) unlink should succeed"
30798
30799         post_801
30800 }
30801 run_test 801b "modification will be blocked by write barrier"
30802
30803 test_801c() {
30804         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
30805
30806         prep_801
30807
30808         stop mds2 || error "(1) Fail to stop mds2"
30809
30810         do_facet mgs $LCTL barrier_freeze $FSNAME 30
30811
30812         local b_status=$(barrier_stat)
30813         [ "$b_status" = "'expired'" ] || [ "$b_status" = "'failed'" ] || {
30814                 do_facet mgs $LCTL barrier_thaw $FSNAME
30815                 error "(2) unexpected barrier status $b_status"
30816         }
30817
30818         do_facet mgs $LCTL barrier_rescan $FSNAME ||
30819                 error "(3) Fail to rescan barrier bitmap"
30820
30821         # Do not reduce barrier time - See LU-11873
30822         do_facet mgs $LCTL barrier_freeze $FSNAME 20
30823
30824         b_status=$(barrier_stat)
30825         [ "$b_status" = "'frozen'" ] ||
30826                 error "(4) unexpected barrier status $b_status"
30827
30828         do_facet mgs $LCTL barrier_thaw $FSNAME
30829         b_status=$(barrier_stat)
30830         [ "$b_status" = "'thawed'" ] ||
30831                 error "(5) unexpected barrier status $b_status"
30832
30833         local devname=$(mdsdevname 2)
30834
30835         start mds2 $devname $MDS_MOUNT_OPTS || error "(6) Fail to start mds2"
30836
30837         do_facet mgs $LCTL barrier_rescan $FSNAME ||
30838                 error "(7) Fail to rescan barrier bitmap"
30839
30840         post_801
30841 }
30842 run_test 801c "rescan barrier bitmap"
30843
30844 test_802b() {
30845         [ $PARALLEL == "yes" ] && skip "skip parallel run"
30846         remote_mds_nodsh && skip "remote MDS with nodsh"
30847
30848         do_facet $SINGLEMDS $LCTL get_param mdt.*.readonly ||
30849                 skip "readonly option not available"
30850
30851         $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "(1) fail to mkdir"
30852
30853         cp $LUSTRE/tests/test-framework.sh $DIR/$tdir/ ||
30854                 error "(2) Fail to copy"
30855
30856         # write back all cached data before setting MDT to readonly
30857         cancel_lru_locks
30858         sync_all_data
30859
30860         do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=1
30861         stack_trap "do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=0" EXIT
30862
30863         echo "Modify should be refused"
30864         touch $DIR/$tdir/guard && error "(6) Touch should fail under ro mode"
30865
30866         echo "Read should be allowed"
30867         diff $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh ||
30868                 error "(7) Read should succeed under ro mode"
30869
30870         # disable readonly
30871         do_facet $SINGLEMDS $LCTL set_param mdt.*.readonly=0
30872 }
30873 run_test 802b "be able to set MDTs to readonly"
30874
30875 test_803a() {
30876         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
30877         [ $MDS1_VERSION -lt $(version_code 2.10.54) ] &&
30878                 skip "MDS needs to be newer than 2.10.54"
30879
30880         mkdir_on_mdt0 $DIR/$tdir
30881         # Create some objects on all MDTs to trigger related logs objects
30882         for idx in $(seq $MDSCOUNT); do
30883                 $LFS mkdir -c $MDSCOUNT -i $((idx % $MDSCOUNT)) \
30884                         $DIR/$tdir/dir${idx} ||
30885                         error "Fail to create $DIR/$tdir/dir${idx}"
30886         done
30887
30888         wait_delete_completed # ensure old test cleanups are finished
30889         sleep 3
30890         echo "before create:"
30891         $LFS df -i $MOUNT
30892         local before_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
30893
30894         for i in {1..10}; do
30895                 $LFS mkdir -c 1 -i 1 $DIR/$tdir/foo$i ||
30896                         error "Fail to create $DIR/$tdir/foo$i"
30897         done
30898
30899         # sync ZFS-on-MDS to refresh statfs data
30900         wait_zfs_commit mds1
30901         sleep 3
30902         echo "after create:"
30903         $LFS df -i $MOUNT
30904         local after_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
30905
30906         # allow for an llog to be cleaned up during the test
30907         [ $after_used -ge $((before_used + 10 - 1)) ] ||
30908                 error "before ($before_used) + 10 > after ($after_used)"
30909
30910         for i in {1..10}; do
30911                 rm -rf $DIR/$tdir/foo$i ||
30912                         error "Fail to remove $DIR/$tdir/foo$i"
30913         done
30914
30915         # sync ZFS-on-MDS to refresh statfs data
30916         wait_zfs_commit mds1
30917         wait_delete_completed
30918         sleep 3 # avoid MDT return cached statfs
30919         echo "after unlink:"
30920         $LFS df -i $MOUNT
30921         after_used=$($LFS df -i | grep MDT0000_UUID | awk '{print $3}')
30922
30923         # allow for an llog to be created during the test
30924         [ $after_used -le $((before_used + 1)) ] ||
30925                 error "after ($after_used) > before ($before_used) + 1"
30926 }
30927 run_test 803a "verify agent object for remote object"
30928
30929 test_803b() {
30930         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
30931         [ $MDS1_VERSION -lt $(version_code 2.13.56) ] &&
30932                 skip "MDS needs to be newer than 2.13.56"
30933         [ $PARALLEL == "yes" ] && skip "skip parallel run"
30934
30935         for i in $(seq 0 $((MDSCOUNT - 1))); do
30936                 $LFS mkdir -i $i $DIR/$tdir.$i || error "mkdir $tdir.$i"
30937         done
30938
30939         local before=0
30940         local after=0
30941
30942         local tmp
30943
30944         stat $DIR/$tdir.* >/dev/null || error "stat $tdir.*"
30945         for i in $(seq 0 $((MDSCOUNT - 1))); do
30946                 tmp=$(do_facet mds$i $LCTL get_param mdt.*-MDT000$i.md_stats |
30947                         awk '/getattr/ { print $2 }')
30948                 before=$((before + tmp))
30949         done
30950         stat $DIR/$tdir.* >/dev/null || error "stat $tdir.*"
30951         for i in $(seq 0 $((MDSCOUNT - 1))); do
30952                 tmp=$(do_facet mds$i $LCTL get_param mdt.*-MDT000$i.md_stats |
30953                         awk '/getattr/ { print $2 }')
30954                 after=$((after + tmp))
30955         done
30956
30957         [ $before -eq $after ] || error "getattr count $before != $after"
30958 }
30959 run_test 803b "remote object can getattr from cache"
30960
30961 test_804() {
30962         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
30963         [ $MDS1_VERSION -lt $(version_code 2.10.54) ] &&
30964                 skip "MDS needs to be newer than 2.10.54"
30965         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
30966
30967         mkdir -p $DIR/$tdir
30968         $LFS mkdir -c 1 -i 1 $DIR/$tdir/dir0 ||
30969                 error "Fail to create $DIR/$tdir/dir0"
30970
30971         local fid=$($LFS path2fid $DIR/$tdir/dir0)
30972         local dev=$(mdsdevname 2)
30973
30974         do_facet mds2 "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
30975                 grep ${fid} || error "NOT found agent entry for dir0"
30976
30977         $LFS mkdir -c $MDSCOUNT -i 0 $DIR/$tdir/dir1 ||
30978                 error "Fail to create $DIR/$tdir/dir1"
30979
30980         touch $DIR/$tdir/dir1/foo0 ||
30981                 error "Fail to create $DIR/$tdir/dir1/foo0"
30982         fid=$($LFS path2fid $DIR/$tdir/dir1/foo0)
30983         local rc=0
30984
30985         for idx in $(seq $MDSCOUNT); do
30986                 dev=$(mdsdevname $idx)
30987                 do_facet mds${idx} \
30988                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
30989                         grep ${fid} && rc=$idx
30990         done
30991
30992         mv $DIR/$tdir/dir1/foo0 $DIR/$tdir/dir1/foo1 ||
30993                 error "Fail to rename foo0 to foo1"
30994         if [ $rc -eq 0 ]; then
30995                 for idx in $(seq $MDSCOUNT); do
30996                         dev=$(mdsdevname $idx)
30997                         do_facet mds${idx} \
30998                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
30999                         grep ${fid} && rc=$idx
31000                 done
31001         fi
31002
31003         mv $DIR/$tdir/dir1/foo1 $DIR/$tdir/dir1/foo2 ||
31004                 error "Fail to rename foo1 to foo2"
31005         if [ $rc -eq 0 ]; then
31006                 for idx in $(seq $MDSCOUNT); do
31007                         dev=$(mdsdevname $idx)
31008                         do_facet mds${idx} \
31009                         "$DEBUGFS -c -R 'ls /REMOTE_PARENT_DIR' $dev" |
31010                         grep ${fid} && rc=$idx
31011                 done
31012         fi
31013
31014         [ $rc -ne 0 ] || error "NOT found agent entry for foo"
31015
31016         ln $DIR/$tdir/dir1/foo2 $DIR/$tdir/dir0/guard ||
31017                 error "Fail to link to $DIR/$tdir/dir1/foo2"
31018         mv $DIR/$tdir/dir1/foo2 $DIR/$tdir/dir1/foo0 ||
31019                 error "Fail to rename foo2 to foo0"
31020         unlink $DIR/$tdir/dir1/foo0 ||
31021                 error "Fail to unlink $DIR/$tdir/dir1/foo0"
31022         rm -rf $DIR/$tdir/dir0 ||
31023                 error "Fail to rm $DIR/$tdir/dir0"
31024
31025         for idx in $(seq $MDSCOUNT); do
31026                 rc=0
31027
31028                 stop mds${idx}
31029                 dev=$(mdsdevname $idx)
31030                 run_e2fsck $(facet_active_host mds$idx) $dev -n ||
31031                         rc=$?
31032                 start mds${idx} $dev $MDS_MOUNT_OPTS ||
31033                         error "mount mds$idx failed"
31034                 df $MOUNT > /dev/null 2>&1
31035
31036                 # e2fsck should not return error
31037                 [ $rc -eq 0 ] ||
31038                         error "e2fsck detected error on MDT${idx}: rc=$rc"
31039         done
31040 }
31041 run_test 804 "verify agent entry for remote entry"
31042
31043 cleanup_805() {
31044         do_facet $SINGLEMDS zfs set quota=$old $fsset
31045         unlinkmany $DIR/$tdir/f- 1000000
31046         trap 0
31047 }
31048
31049 test_805() {
31050         local zfs_version=$(do_facet mds1 cat /sys/module/zfs/version)
31051         [ "$mds1_FSTYPE" != "zfs" ] && skip "ZFS specific test"
31052         [ $(version_code $zfs_version) -lt $(version_code 0.7.2) ] &&
31053                 skip "netfree not implemented before 0.7"
31054         [[ $MDS1_VERSION -ge $(version_code 2.10.57) ]] ||
31055                 skip "Need MDS version at least 2.10.57"
31056
31057         local fsset
31058         local freekb
31059         local usedkb
31060         local old
31061         local quota
31062         local pref="osd-zfs.$FSNAME-MDT0000."
31063
31064         # limit available space on MDS dataset to meet nospace issue
31065         # quickly. then ZFS 0.7.2 can use reserved space if asked
31066         # properly (using netfree flag in osd_declare_destroy()
31067         fsset=$(do_facet $SINGLEMDS lctl get_param -n $pref.mntdev)
31068         old=$(do_facet $SINGLEMDS zfs get -H quota $fsset | \
31069                 gawk '{print $3}')
31070         freekb=$(do_facet $SINGLEMDS lctl get_param -n $pref.kbytesfree)
31071         usedkb=$(do_facet $SINGLEMDS lctl get_param -n $pref.kbytestotal)
31072         let "usedkb=usedkb-freekb"
31073         let "freekb=freekb/2"
31074         if let "freekb > 5000"; then
31075                 let "freekb=5000"
31076         fi
31077         do_facet $SINGLEMDS zfs set quota=$(((usedkb+freekb)*1024)) $fsset
31078         trap cleanup_805 EXIT
31079         mkdir_on_mdt0 $DIR/$tdir
31080         $LFS setstripe -E 1M -c2 -E 4M -c2 -E -1 -c2 $DIR/$tdir ||
31081                 error "Can't set PFL layout"
31082         createmany -m $DIR/$tdir/f- 1000000 && error "ENOSPC wasn't met"
31083         rm -rf $DIR/$tdir || error "not able to remove"
31084         do_facet $SINGLEMDS zfs set quota=$old $fsset
31085         trap 0
31086 }
31087 run_test 805 "ZFS can remove from full fs"
31088
31089 # Size-on-MDS test
31090 check_lsom_data()
31091 {
31092         local file=$1
31093         local expect=$(stat -c %s $file)
31094
31095         check_lsom_size $1 $expect
31096
31097         local blocks=$($LFS getsom -b $file)
31098         expect=$(stat -c %b $file)
31099         [[ $blocks == $expect ]] ||
31100                 error "$file expected blocks: $expect, got: $blocks"
31101 }
31102
31103 check_lsom_size()
31104 {
31105         local size
31106         local expect=$2
31107
31108         cancel_lru_locks mdc
31109
31110         size=$($LFS getsom -s $1)
31111         [[ $size == $expect ]] ||
31112                 error "$file expected size: $expect, got: $size"
31113 }
31114
31115 test_806() {
31116         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
31117                 skip "Need MDS version at least 2.11.52"
31118
31119         local bs=1048576
31120
31121         $LFS setstripe -c-1 $DIR/$tfile || error "setstripe $tfile failed"
31122
31123         disable_opencache
31124         stack_trap "restore_opencache"
31125
31126         # single-threaded write
31127         echo "Test SOM for single-threaded write"
31128         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 ||
31129                 error "write $tfile failed"
31130         check_lsom_size $DIR/$tfile $bs
31131
31132         local num=32
31133         local size=$(($num * $bs))
31134         local offset=0
31135         local i
31136
31137         echo "Test SOM for single client multi-threaded($num) write"
31138         $TRUNCATE $DIR/$tfile 0
31139         for ((i = 0; i < $num; i++)); do
31140                 $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
31141                 local pids[$i]=$!
31142                 offset=$((offset + $bs))
31143         done
31144         for (( i=0; i < $num; i++ )); do
31145                 wait ${pids[$i]}
31146         done
31147         check_lsom_size $DIR/$tfile $size
31148
31149         $TRUNCATE $DIR/$tfile 0
31150         for ((i = 0; i < $num; i++)); do
31151                 offset=$((offset - $bs))
31152                 $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
31153                 local pids[$i]=$!
31154         done
31155         for (( i=0; i < $num; i++ )); do
31156                 wait ${pids[$i]}
31157         done
31158         check_lsom_size $DIR/$tfile $size
31159
31160         # multi-client writes
31161         num=$(get_node_count ${CLIENTS//,/ })
31162         size=$(($num * $bs))
31163         offset=0
31164         i=0
31165
31166         echo "Test SOM for multi-client ($num) writes"
31167         $TRUNCATE $DIR/$tfile 0
31168         for client in ${CLIENTS//,/ }; do
31169                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
31170                 local pids[$i]=$!
31171                 i=$((i + 1))
31172                 offset=$((offset + $bs))
31173         done
31174         for (( i=0; i < $num; i++ )); do
31175                 wait ${pids[$i]}
31176         done
31177         check_lsom_size $DIR/$tfile $offset
31178
31179         i=0
31180         $TRUNCATE $DIR/$tfile 0
31181         for client in ${CLIENTS//,/ }; do
31182                 offset=$((offset - $bs))
31183                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
31184                 local pids[$i]=$!
31185                 i=$((i + 1))
31186         done
31187         for (( i=0; i < $num; i++ )); do
31188                 wait ${pids[$i]}
31189         done
31190         check_lsom_size $DIR/$tfile $size
31191
31192         # verify SOM blocks count
31193         echo "Verify SOM block count"
31194         $TRUNCATE $DIR/$tfile 0
31195         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs))YSc ||
31196                 error "failed to write file $tfile with fdatasync and fstat"
31197         check_lsom_data $DIR/$tfile
31198
31199         $TRUNCATE $DIR/$tfile 0
31200         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs * 2))Yc ||
31201                 error "failed to write file $tfile with fdatasync"
31202         check_lsom_data $DIR/$tfile
31203
31204         $TRUNCATE $DIR/$tfile 0
31205         $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:O_SYNC:w$((bs * 3))c ||
31206                 error "failed to write file $tfile with sync IO"
31207         check_lsom_data $DIR/$tfile
31208
31209         # verify truncate
31210         echo "Test SOM for truncate"
31211         # use ftruncate to sync blocks on close request
31212         $MULTIOP $DIR/$tfile oO_WRONLY:T16384c
31213         check_lsom_size $DIR/$tfile 16384
31214         check_lsom_data $DIR/$tfile
31215
31216         $TRUNCATE $DIR/$tfile 1234
31217         check_lsom_size $DIR/$tfile 1234
31218         # sync blocks on the MDT
31219         $MULTIOP $DIR/$tfile oc
31220         check_lsom_data $DIR/$tfile
31221 }
31222 run_test 806 "Verify Lazy Size on MDS"
31223
31224 test_807() {
31225         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
31226         [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
31227                 skip "Need MDS version at least 2.11.52"
31228
31229         # Registration step
31230         changelog_register || error "changelog_register failed"
31231         local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
31232         changelog_users $SINGLEMDS | grep -q $cl_user ||
31233                 error "User $cl_user not found in changelog_users"
31234
31235         rm -rf $DIR/$tdir || error "rm $tdir failed"
31236         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
31237         touch $DIR/$tdir/trunc || error "touch $tdir/trunc failed"
31238         $TRUNCATE $DIR/$tdir/trunc 1024 || error "truncate $tdir/trunc failed"
31239         $TRUNCATE $DIR/$tdir/trunc 1048576 ||
31240                 error "truncate $tdir/trunc failed"
31241
31242         local bs=1048576
31243         echo "Test SOM for single-threaded write with fsync"
31244         dd if=/dev/zero of=$DIR/$tdir/single_dd bs=$bs count=1 ||
31245                 error "write $tfile failed"
31246         sync;sync;sync
31247
31248         # multi-client wirtes
31249         local num=$(get_node_count ${CLIENTS//,/ })
31250         local offset=0
31251         local i=0
31252
31253         echo "Test SOM for multi-client ($num) writes"
31254         touch $DIR/$tfile || error "touch $tfile failed"
31255         $TRUNCATE $DIR/$tfile 0
31256         for client in ${CLIENTS//,/ }; do
31257                 do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
31258                 local pids[$i]=$!
31259                 i=$((i + 1))
31260                 offset=$((offset + $bs))
31261         done
31262         for (( i=0; i < $num; i++ )); do
31263                 wait ${pids[$i]}
31264         done
31265
31266         do_rpc_nodes "$CLIENTS" cancel_lru_locks osc
31267         do_nodes "$CLIENTS" "sync ; sleep 5 ; sync"
31268         $LSOM_SYNC -u $cl_user -m $FSNAME-MDT0000 $MOUNT
31269         check_lsom_data $DIR/$tdir/trunc
31270         check_lsom_data $DIR/$tdir/single_dd
31271         check_lsom_data $DIR/$tfile
31272
31273         rm -rf $DIR/$tdir
31274         # Deregistration step
31275         changelog_deregister || error "changelog_deregister failed"
31276 }
31277 run_test 807 "verify LSOM syncing tool"
31278
31279 check_som_nologged()
31280 {
31281         local lines=$($LFS changelog $FSNAME-MDT0000 |
31282                 grep 'x=trusted.som' | wc -l)
31283         [ $lines -ne 0 ] && error "trusted.som xattr is logged in Changelogs"
31284 }
31285
31286 test_808() {
31287         [ $MDS1_VERSION -lt $(version_code 2.11.55) ] &&
31288                 skip "Need MDS version at least 2.11.55"
31289
31290         # Registration step
31291         changelog_register || error "changelog_register failed"
31292
31293         touch $DIR/$tfile || error "touch $tfile failed"
31294         check_som_nologged
31295
31296         dd if=/dev/zero of=$DIR/$tfile bs=1048576 count=1 ||
31297                 error "write $tfile failed"
31298         check_som_nologged
31299
31300         $TRUNCATE $DIR/$tfile 1234
31301         check_som_nologged
31302
31303         $TRUNCATE $DIR/$tfile 1048576
31304         check_som_nologged
31305
31306         # Deregistration step
31307         changelog_deregister || error "changelog_deregister failed"
31308 }
31309 run_test 808 "Check trusted.som xattr not logged in Changelogs"
31310
31311 check_som_nodata()
31312 {
31313         $LFS getsom $1
31314         [[ $? -eq 61 ]] || error "DoM-only file $1 has SOM xattr"
31315 }
31316
31317 test_809() {
31318         [ $MDS1_VERSION -lt $(version_code 2.11.56) ] &&
31319                 skip "Need MDS version at least 2.11.56"
31320
31321         $LFS setstripe -E 1M -L mdt $DIR/$tfile ||
31322                 error "failed to create DoM-only file $DIR/$tfile"
31323         touch $DIR/$tfile || error "touch $tfile failed"
31324         check_som_nodata $DIR/$tfile
31325
31326         dd if=/dev/zero of=$DIR/$tfile bs=2048 count=1 ||
31327                 error "write $tfile failed"
31328         check_som_nodata $DIR/$tfile
31329
31330         $TRUNCATE $DIR/$tfile 1234
31331         check_som_nodata $DIR/$tfile
31332
31333         $TRUNCATE $DIR/$tfile 4097
31334         check_som_nodata $DIR/$file
31335 }
31336 run_test 809 "Verify no SOM xattr store for DoM-only files"
31337
31338 test_810() {
31339         [ $PARALLEL == "yes" ] && skip "skip parallel run"
31340         $GSS && skip_env "could not run with gss"
31341         [[ $OST1_VERSION -gt $(version_code 2.12.58) ]] ||
31342                 skip "OST < 2.12.58 doesn't align checksum"
31343
31344         set_checksums 1
31345         stack_trap "set_checksums $ORIG_CSUM" EXIT
31346         stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
31347
31348         local csum
31349         local before
31350         local after
31351         for csum in $CKSUM_TYPES; do
31352                 #define OBD_FAIL_OSC_NO_GRANT   0x411
31353                 $LCTL set_param osc.*.checksum_type=$csum fail_loc=0x411
31354                 for i in "10240 0" "10000 0" "4000 1" "500 1"; do
31355                         eval set -- $i
31356                         dd if=/dev/urandom of=$DIR/$tfile bs=$1 count=2 seek=$2
31357                         before=$(md5sum $DIR/$tfile)
31358                         $LCTL set_param ldlm.namespaces.*osc*.lru_size=clear
31359                         after=$(md5sum $DIR/$tfile)
31360                         [ "$before" == "$after" ] ||
31361                                 error "$csum: $before != $after bs=$1 seek=$2"
31362                 done
31363         done
31364 }
31365 run_test 810 "partial page writes on ZFS (LU-11663)"
31366
31367 test_812a() {
31368         [ $OST1_VERSION -lt $(version_code 2.12.51) ] &&
31369                 skip "OST < 2.12.51 doesn't support this fail_loc"
31370
31371         $LFS setstripe -c 1 -i 0 $DIR/$tfile
31372         # ensure ost1 is connected
31373         stat $DIR/$tfile >/dev/null || error "can't stat"
31374         wait_osc_import_state client ost1 FULL
31375         # no locks, no reqs to let the connection idle
31376         cancel_lru_locks osc
31377
31378         # delay OST_DISCONNECT on OST1 to put OSC into intermediate state
31379 #define OBD_FAIL_OST_DISCONNECT_DELAY    0x245
31380         do_facet ost1 "$LCTL set_param fail_loc=0x245 fail_val=8"
31381         wait_osc_import_state client ost1 CONNECTING
31382         do_facet ost1 "$LCTL set_param fail_loc=0 fail_val=0"
31383
31384         stat $DIR/$tfile >/dev/null || error "can't stat file"
31385 }
31386 run_test 812a "do not drop reqs generated when imp is going to idle (LU-11951)"
31387
31388 test_812b() { # LU-12378
31389         [ $OST1_VERSION -lt $(version_code 2.12.51) ] &&
31390                 skip "OST < 2.12.51 doesn't support this fail_loc"
31391
31392         $LFS setstripe -c 1 -i 0 $DIR/$tfile || error "setstripe failed"
31393         # ensure ost1 is connected
31394         stat $DIR/$tfile >/dev/null || error "can't stat"
31395         wait_osc_import_state client ost1 FULL
31396         # no locks, no reqs to let the connection idle
31397         cancel_lru_locks osc
31398
31399         # delay OST_DISCONNECT on OST1 to put OSC into intermediate state
31400 #define OBD_FAIL_OST_DISCONNECT_DELAY    0x245
31401         do_facet ost1 "$LCTL set_param fail_loc=0x245 fail_val=8"
31402         wait_osc_import_state client ost1 CONNECTING
31403         do_facet ost1 "$LCTL set_param fail_loc=0 fail_val=0"
31404
31405         $LFS quota -u 0 $DIR/ || error "lfs quota should succeed"
31406         wait_osc_import_state client ost1 IDLE
31407 }
31408 run_test 812b "do not drop no resend request for idle connect"
31409
31410 test_812c() {
31411         local old
31412
31413         old=$($LCTL get_param -n osc.*.idle_timeout | head -n 1)
31414
31415         $LFS setstripe -c 1 -o 0 $DIR/$tfile
31416         $LFS getstripe $DIR/$tfile
31417         $LCTL set_param osc.*.idle_timeout=10
31418         stack_trap "$LCTL set_param osc.*.idle_timeout=$old" EXIT
31419         # ensure ost1 is connected
31420         stat $DIR/$tfile >/dev/null || error "can't stat"
31421         wait_osc_import_state client ost1 FULL
31422         # no locks, no reqs to let the connection idle
31423         cancel_lru_locks osc
31424
31425 #define OBD_FAIL_PTLRPC_IDLE_RACE        0x533
31426         $LCTL set_param fail_loc=0x80000533
31427         sleep 15
31428         dd if=/dev/zero of=$DIR/$tfile count=1 conv=sync || error "dd failed"
31429 }
31430 run_test 812c "idle import vs lock enqueue race"
31431
31432 test_813() {
31433         local file_heat_sav=$($LCTL get_param -n llite.*.file_heat 2>/dev/null)
31434         [ -z "$file_heat_sav" ] && skip "no file heat support"
31435
31436         local readsample
31437         local writesample
31438         local readbyte
31439         local writebyte
31440         local readsample1
31441         local writesample1
31442         local readbyte1
31443         local writebyte1
31444
31445         local period_second=$($LCTL get_param -n llite.*.heat_period_second)
31446         local decay_pct=$($LCTL get_param -n llite.*.heat_decay_percentage)
31447
31448         $LCTL set_param -n llite.*.file_heat=1
31449         echo "Turn on file heat"
31450         echo "Period second: $period_second, Decay percentage: $decay_pct"
31451
31452         echo "QQQQ" > $DIR/$tfile
31453         echo "QQQQ" > $DIR/$tfile
31454         echo "QQQQ" > $DIR/$tfile
31455         cat $DIR/$tfile > /dev/null
31456         cat $DIR/$tfile > /dev/null
31457         cat $DIR/$tfile > /dev/null
31458         cat $DIR/$tfile > /dev/null
31459
31460         local out=$($LFS heat_get $DIR/$tfile)
31461
31462         $LFS heat_get $DIR/$tfile
31463         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31464         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31465         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31466         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31467
31468         [ $readsample -le 4 ] || error "read sample ($readsample) is wrong"
31469         [ $writesample -le 3 ] || error "write sample ($writesample) is wrong"
31470         [ $readbyte -le 20 ] || error "read bytes ($readbyte) is wrong"
31471         [ $writebyte -le 15 ] || error "write bytes ($writebyte) is wrong"
31472
31473         sleep $((period_second + 3))
31474         echo "Sleep $((period_second + 3)) seconds..."
31475         # The recursion formula to calculate the heat of the file f is as
31476         # follow:
31477         # Hi+1(f) = (1-P)*Hi(f)+ P*Ci
31478         # Where Hi is the heat value in the period between time points i*I and
31479         # (i+1)*I; Ci is the access count in the period; the symbol P refers
31480         # to the weight of Ci.
31481         out=$($LFS heat_get $DIR/$tfile)
31482         $LFS heat_get $DIR/$tfile
31483         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31484         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31485         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31486         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31487
31488         [ $(bc <<< "$readsample <= 4 * $decay_pct / 100") -eq 1 ] ||
31489                 error "read sample ($readsample) is wrong"
31490         [ $(bc <<< "$writesample <= 3 * $decay_pct / 100") -eq 1 ] ||
31491                 error "write sample ($writesample) is wrong"
31492         [ $(bc <<< "$readbyte <= 20 * $decay_pct / 100") -eq 1 ] ||
31493                 error "read bytes ($readbyte) is wrong"
31494         [ $(bc <<< "$writebyte <= 15 * $decay_pct / 100") -eq 1 ] ||
31495                 error "write bytes ($writebyte) is wrong"
31496
31497         echo "QQQQ" > $DIR/$tfile
31498         echo "QQQQ" > $DIR/$tfile
31499         echo "QQQQ" > $DIR/$tfile
31500         cat $DIR/$tfile > /dev/null
31501         cat $DIR/$tfile > /dev/null
31502         cat $DIR/$tfile > /dev/null
31503         cat $DIR/$tfile > /dev/null
31504
31505         sleep $((period_second + 3))
31506         echo "Sleep $((period_second + 3)) seconds..."
31507
31508         out=$($LFS heat_get $DIR/$tfile)
31509         $LFS heat_get $DIR/$tfile
31510         readsample1=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31511         writesample1=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31512         readbyte1=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31513         writebyte1=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31514
31515         [ $(bc <<< "$readsample1 <= ($readsample * (100 - $decay_pct) + \
31516                 4 * $decay_pct) / 100") -eq 1 ] ||
31517                 error "read sample ($readsample1) is wrong"
31518         [ $(bc <<< "$writesample1 <= ($writesample * (100 - $decay_pct) + \
31519                 3 * $decay_pct) / 100") -eq 1 ] ||
31520                 error "write sample ($writesample1) is wrong"
31521         [ $(bc <<< "$readbyte1 <= ($readbyte * (100 - $decay_pct) + \
31522                 20 * $decay_pct) / 100") -eq 1 ] ||
31523                 error "read bytes ($readbyte1) is wrong"
31524         [ $(bc <<< "$writebyte1 <= ($writebyte * (100 - $decay_pct) + \
31525                 15 * $decay_pct) / 100") -eq 1 ] ||
31526                 error "write bytes ($writebyte1) is wrong"
31527
31528         echo "Turn off file heat for the file $DIR/$tfile"
31529         $LFS heat_set -o $DIR/$tfile
31530
31531         echo "QQQQ" > $DIR/$tfile
31532         echo "QQQQ" > $DIR/$tfile
31533         echo "QQQQ" > $DIR/$tfile
31534         cat $DIR/$tfile > /dev/null
31535         cat $DIR/$tfile > /dev/null
31536         cat $DIR/$tfile > /dev/null
31537         cat $DIR/$tfile > /dev/null
31538
31539         out=$($LFS heat_get $DIR/$tfile)
31540         $LFS heat_get $DIR/$tfile
31541         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31542         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31543         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31544         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31545
31546         [ $readsample -eq 0 ] || error "read sample ($readsample) is wrong"
31547         [ $writesample -eq 0 ] || error "write sample ($writesample) is wrong"
31548         [ $readbyte -eq 0 ] || error "read bytes ($readbyte) is wrong"
31549         [ $writebyte -eq 0 ] || error "write bytes ($writebyte) is wrong"
31550
31551         echo "Trun on file heat for the file $DIR/$tfile"
31552         $LFS heat_set -O $DIR/$tfile
31553
31554         echo "QQQQ" > $DIR/$tfile
31555         echo "QQQQ" > $DIR/$tfile
31556         echo "QQQQ" > $DIR/$tfile
31557         cat $DIR/$tfile > /dev/null
31558         cat $DIR/$tfile > /dev/null
31559         cat $DIR/$tfile > /dev/null
31560         cat $DIR/$tfile > /dev/null
31561
31562         out=$($LFS heat_get $DIR/$tfile)
31563         $LFS heat_get $DIR/$tfile
31564         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31565         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31566         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31567         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31568
31569         [ $readsample -gt 0 ] || error "read sample ($readsample) is wrong"
31570         [ $writesample -gt 0 ] || error "write sample ($writesample) is wrong"
31571         [ $readbyte -gt 0 ] || error "read bytes ($readbyte) is wrong"
31572         [ $writebyte -gt 0 ] || error "write bytes ($writebyte) is wrong"
31573
31574         $LFS heat_set -c $DIR/$tfile
31575         $LCTL set_param -n llite.*.file_heat=0
31576         echo "Turn off file heat support for the Lustre filesystem"
31577
31578         echo "QQQQ" > $DIR/$tfile
31579         echo "QQQQ" > $DIR/$tfile
31580         echo "QQQQ" > $DIR/$tfile
31581         cat $DIR/$tfile > /dev/null
31582         cat $DIR/$tfile > /dev/null
31583         cat $DIR/$tfile > /dev/null
31584         cat $DIR/$tfile > /dev/null
31585
31586         out=$($LFS heat_get $DIR/$tfile)
31587         $LFS heat_get $DIR/$tfile
31588         readsample=$(echo "$out" | grep 'readsample' | awk '{ print $2 }')
31589         writesample=$(echo "$out" | grep 'writesample' | awk '{ print $2 }')
31590         readbyte=$(echo "$out" | grep 'readbyte' | awk '{ print $2 }')
31591         writebyte=$(echo "$out" | grep 'writebyte' | awk '{ print $2 }')
31592
31593         [ $readsample -eq 0 ] || error "read sample ($readsample) is wrong"
31594         [ $writesample -eq 0 ] || error "write sample ($writesample) is wrong"
31595         [ $readbyte -eq 0 ] || error "read bytes ($readbyte) is wrong"
31596         [ $writebyte -eq 0 ] || error "write bytes ($writebyte) is wrong"
31597
31598         $LCTL set_param -n llite.*.file_heat=$file_heat_sav
31599         rm -f $DIR/$tfile
31600 }
31601 run_test 813 "File heat verfication"
31602
31603 test_814()
31604 {
31605         dd of=$DIR/$tfile seek=128 bs=1k < /dev/null
31606         echo -n y >> $DIR/$tfile
31607         cp --sparse=always $DIR/$tfile $DIR/${tfile}.cp || error "copy failed"
31608         diff $DIR/$tfile $DIR/${tfile}.cp || error "files should be same"
31609 }
31610 run_test 814 "sparse cp works as expected (LU-12361)"
31611
31612 test_815()
31613 {
31614         writeme -b 100 $DIR/$tfile || error "write 100 bytes failed"
31615         writeme -b 0 $DIR/$tfile || error "write 0 byte failed"
31616 }
31617 run_test 815 "zero byte tiny write doesn't hang (LU-12382)"
31618
31619 test_816() {
31620         local ost1_imp=$(get_osc_import_name client ost1)
31621         local imp_name=$($LCTL list_param osc.$ost1_imp | head -n1 |
31622                          cut -d'.' -f2)
31623
31624         $LFS setstripe -c 1 -i 0 $DIR/$tfile
31625         # ensure ost1 is connected
31626
31627         stat $DIR/$tfile >/dev/null || error "can't stat"
31628         wait_osc_import_state client ost1 FULL
31629         # no locks, no reqs to let the connection idle
31630         cancel_lru_locks osc
31631         lru_resize_disable osc
31632         local before
31633         local now
31634         before=$($LCTL get_param -n \
31635                  ldlm.namespaces.$imp_name.lru_size)
31636
31637         wait_osc_import_state client ost1 IDLE
31638         dd if=/dev/null of=$DIR/$tfile bs=1k count=1 conv=sync
31639         now=$($LCTL get_param -n \
31640               ldlm.namespaces.$imp_name.lru_size)
31641         [ $before == $now ] || error "lru_size changed $before != $now"
31642 }
31643 run_test 816 "do not reset lru_resize on idle reconnect"
31644
31645 cleanup_817() {
31646         umount $tmpdir
31647         exportfs -u localhost:$DIR/nfsexp
31648         rm -rf $DIR/nfsexp
31649 }
31650
31651 test_817() {
31652         systemctl restart nfs-server.service || skip "failed to restart nfsd"
31653
31654         mkdir -p $DIR/nfsexp
31655         exportfs -orw,no_root_squash localhost:$DIR/nfsexp ||
31656                 error "failed to export nfs"
31657
31658         tmpdir=$(mktemp -d /tmp/nfs-XXXXXX)
31659         stack_trap cleanup_817 EXIT
31660
31661         mount -t nfs -orw localhost:$DIR/nfsexp $tmpdir ||
31662                 error "failed to mount nfs to $tmpdir"
31663
31664         cp /bin/true $tmpdir
31665         $DIR/nfsexp/true || error "failed to execute 'true' command"
31666 }
31667 run_test 817 "nfsd won't cache write lock for exec file"
31668
31669 test_818() {
31670         test_mkdir -i0 -c1 $DIR/$tdir
31671         $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
31672         $LFS setstripe -c1 -i1 $DIR/$tdir/$tfile
31673         stop $SINGLEMDS
31674
31675         # restore osp-syn threads
31676         stack_trap "fail $SINGLEMDS"
31677
31678         #define OBD_FAIL_OSP_CANT_PROCESS_LLOG          0x2105
31679         do_facet $SINGLEMDS lctl set_param fail_loc=0x80002105
31680         start $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) $MDS_MOUNT_OPTS ||
31681                 error "start $SINGLEMDS failed"
31682         rm -rf $DIR/$tdir
31683
31684         local testid=$(echo $TESTNAME | tr '_' ' ')
31685
31686         do_facet mds1 dmesg | tac | sed "/$testid/,$ d" |
31687                 grep "run LFSCK" || error "run LFSCK is not suggested"
31688 }
31689 run_test 818 "unlink with failed llog"
31690
31691 test_819a() {
31692         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
31693         cancel_lru_locks osc
31694         #define OBD_FAIL_OST_2BIG_NIOBUF                0x248
31695         do_facet $SINGLEMDS lctl set_param fail_loc=0x80000248
31696         dd if=$DIR/$tfile of=/dev/null bs=1M count=1
31697         rm -f $TDIR/$tfile
31698 }
31699 run_test 819a "too big niobuf in read"
31700
31701 test_819b() {
31702         #define OBD_FAIL_OST_2BIG_NIOBUF                0x248
31703         do_facet $SINGLEMDS lctl set_param fail_loc=0x80000248
31704         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
31705         cancel_lru_locks osc
31706         sleep 1
31707         rm -f $TDIR/$tfile
31708 }
31709 run_test 819b "too big niobuf in write"
31710
31711
31712 function test_820_start_ost() {
31713         sleep 5
31714
31715         for num in $(seq $OSTCOUNT); do
31716                 start ost$num $(ostdevname $num) $OST_MOUNT_OPTS
31717         done
31718 }
31719
31720 test_820() {
31721         [[ $MDSCOUNT -lt 2 ]] && skip_env "needs >= 2 MDTs"
31722
31723         mkdir $DIR/$tdir
31724         umount_client $MOUNT || error "umount failed"
31725         for num in $(seq $OSTCOUNT); do
31726                 stop ost$num
31727         done
31728
31729         # mount client with no active OSTs
31730         # so that the client can't initialize max LOV EA size
31731         # from OSC notifications
31732         mount_client $MOUNT || error "mount failed"
31733         # delay OST starting to keep this 0 max EA size for a while
31734         test_820_start_ost &
31735
31736         # create a directory on MDS2
31737         test_mkdir -i 1 -c1 $DIR/$tdir/mds2 ||
31738                 error "Failed to create directory"
31739         # open intent should update default EA size
31740         # see mdc_update_max_ea_from_body()
31741         # notice this is the very first RPC to MDS2
31742         out=$(cp /etc/services $DIR/$tdir/mds2 2>&1)
31743         ret=$?
31744         echo $out
31745         # With SSK, this situation can lead to -EPERM being returned.
31746         # In that case, simply retry.
31747         if [ $ret -ne 0 ] && $SHARED_KEY; then
31748                 if echo "$out" | grep -q "not permitted"; then
31749                         cp /etc/services $DIR/$tdir/mds2
31750                         ret=$?
31751                 fi
31752         fi
31753         [ $ret -eq 0 ] || error "Failed to copy files to mds$n"
31754 }
31755 run_test 820 "update max EA from open intent"
31756
31757 test_823() {
31758         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
31759         local OST_MAX_PRECREATE=20000
31760
31761         (( $MDS1_VERSION >= $(version_code 2.14.56) )) ||
31762                 skip "Need MDS version at least 2.14.56"
31763
31764         save_lustre_params mds1 \
31765                 "osp.$FSNAME-OST*-osc-MDT0000.max_create_count" > $p
31766         do_facet $SINGLEMDS "$LCTL set_param -n \
31767                 osp.$FSNAME-OST*MDT0000.max_create_count=0"
31768         do_facet $SINGLEMDS "$LCTL set_param -n \
31769                 osp.$FSNAME-OST0000*MDT0000.max_create_count=$OST_MAX_PRECREATE"
31770
31771         stack_trap "restore_lustre_params < $p; rm $p"
31772
31773         do_facet $SINGLEMDS "$LCTL set_param -n \
31774                 osp.$FSNAME-OST*-osc-MDT*.create_count=100200"
31775
31776         local count=$(do_facet $SINGLEMDS "$LCTL get_param -n \
31777                       osp.$FSNAME-OST0000*MDT0000.create_count")
31778         local max=$(do_facet $SINGLEMDS "$LCTL get_param -n \
31779                     osp.$FSNAME-OST0000*MDT0000.max_create_count")
31780         local expect_count=$(((($max/2)/256) * 256))
31781
31782         log "setting create_count to 100200:"
31783         log " -result- count: $count with max: $max, expecting: $expect_count"
31784
31785         [[ $count -eq expect_count ]] ||
31786                 error "Create count not set to max precreate."
31787 }
31788 run_test 823 "Setting create_count > OST_MAX_PRECREATE is lowered to maximum"
31789
31790 test_831() {
31791         [[ $MDS1_VERSION -lt $(version_code 2.14.56) ]] &&
31792                 skip "Need MDS version 2.14.56"
31793
31794         local sync_changes=$(do_facet $SINGLEMDS \
31795                 $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
31796
31797         [ "$sync_changes" -gt 100 ] &&
31798                 skip "Sync changes $sync_changes > 100 already"
31799
31800         local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
31801
31802         $LFS mkdir -i 0 $DIR/$tdir
31803         $LFS setstripe -c 1 -i 0 $DIR/$tdir
31804
31805         save_lustre_params mds1 \
31806                 "osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes" > $p
31807         save_lustre_params mds1 \
31808                 "osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress" >> $p
31809
31810         do_facet mds1 "$LCTL set_param -n \
31811                 osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes=100 \
31812                 osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress=128"
31813         stack_trap "restore_lustre_params < $p" EXIT
31814
31815         createmany -o $DIR/$tdir/f- 1000
31816         unlinkmany $DIR/$tdir/f- 1000 &
31817         local UNLINK_PID=$!
31818
31819         while sleep 1; do
31820                 sync_changes=$(do_facet mds1 \
31821                 $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
31822                 # the check in the code is racy, fail the test
31823                 # if the value above the limit by 10.
31824                 [ $sync_changes -gt 110 ] && {
31825                         kill -2 $UNLINK_PID
31826                         wait
31827                         error "osp changes throttling failed, $sync_changes>110"
31828                 }
31829                 kill -0 $UNLINK_PID 2> /dev/null || break
31830         done
31831         wait
31832 }
31833 run_test 831 "throttling unlink/setattr queuing on OSP"
31834
31835 test_832() {
31836         (( $MDSCOUNT >= 2 )) || skip "needs >= 2 MDTs"
31837         (( $MDS1_VERSION >= $(version_code 2.15.52) )) ||
31838                 skip "Need MDS version 2.15.52+"
31839         is_rmentry_supported || skip "rm_entry not supported"
31840
31841         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
31842         mkdir $DIR/$tdir/local_dir || error "mkdir local_dir failed"
31843         mkdir_on_mdt -i 1 $DIR/$tdir/remote_dir ||
31844                 error "mkdir remote_dir failed"
31845         $LFS mkdir -c $MDSCOUNT $DIR/$tdir/striped_dir ||
31846                 error "mkdir striped_dir failed"
31847         touch $DIR/$tdir/file || error "touch file failed"
31848         $LFS rm_entry $DIR/$tdir/* || error "lfs rm_entry $tdir/* failed"
31849         [ -z "$(ls -A $DIR/$tdir)" ] || error "$tdir not empty"
31850 }
31851 run_test 832 "lfs rm_entry"
31852
31853 test_833() {
31854         local file=$DIR/$tfile
31855
31856         stack_trap "rm -f $file" EXIT
31857         dd if=/dev/zero of=$file bs=1M count=50 || error "Write $file failed"
31858
31859         local wpid
31860         local rpid
31861         local rpid2
31862
31863         # Buffered I/O write
31864         (
31865                 while [ ! -e $DIR/sanity.833.lck ]; do
31866                         dd if=/dev/zero of=$file bs=1M count=50 conv=notrunc ||
31867                                 error "failed to write $file"
31868                         sleep 0.$((RANDOM % 4 + 1))
31869                 done
31870         )&
31871         wpid=$!
31872
31873         # Buffered I/O read
31874         (
31875                 while [ ! -e $DIR/sanity.833.lck ]; do
31876                         dd if=$file of=/dev/null bs=1M count=50 ||
31877                                 error "failed to read $file"
31878                         sleep 0.$((RANDOM % 4 + 1))
31879                 done
31880         )&
31881         rpid=$!
31882
31883         # Direct I/O read
31884         (
31885                 while [ ! -e $DIR/sanity.833.lck ]; do
31886                         dd if=$file of=/dev/null bs=1M count=50 iflag=direct ||
31887                                 error "failed to read $file in direct I/O mode"
31888                         sleep 0.$((RANDOM % 4 + 1))
31889                 done
31890         )&
31891         rpid2=$!
31892
31893         sleep 30
31894         touch $DIR/sanity.833.lck
31895         wait $wpid || error "$?: buffered write failed"
31896         wait $rpid || error "$?: buffered read failed"
31897         wait $rpid2 || error "$?: direct read failed"
31898 }
31899 run_test 833 "Mixed buffered/direct read and write should not return -EIO"
31900
31901 test_850() {
31902         local dir=$DIR/$tdir
31903         local file=$dir/$tfile
31904         local statsfile=$dir/all_job_stats.txt
31905
31906         test_mkdir -p $dir || error "failed to create dir $dir"
31907         echo "abcdefg" > $file || error "failed to create file $file"
31908
31909         # read job_stats in the living system
31910         lljobstat -n 1 ||
31911                 error "failed to run lljobstat on living system"
31912
31913         $LCTL get_param *.*.job_stats > $statsfile
31914         lljobstat --statsfile=$statsfile ||
31915                 error "failed to run lljobstat on file $statsfile"
31916 }
31917 run_test 850 "lljobstat can parse living and aggregated job_stats"
31918
31919 #
31920 # tests that do cleanup/setup should be run at the end
31921 #
31922
31923 test_900() {
31924         [ $PARALLEL == "yes" ] && skip "skip parallel run"
31925         local ls
31926
31927         #define OBD_FAIL_MGC_PAUSE_PROCESS_LOG   0x903
31928         $LCTL set_param fail_loc=0x903
31929
31930         cancel_lru_locks MGC
31931
31932         FAIL_ON_ERROR=true cleanup
31933         FAIL_ON_ERROR=true setup
31934 }
31935 run_test 900 "umount should not race with any mgc requeue thread"
31936
31937 # LUS-6253/LU-11185
31938 test_901() {
31939         local old
31940         local count
31941         local oldc
31942         local newc
31943         local olds
31944         local news
31945         [ $PARALLEL == "yes" ] && skip "skip parallel run"
31946
31947         # some get_param have a bug to handle dot in param name
31948         cancel_lru_locks MGC
31949         old=$(mount -t lustre | wc -l)
31950         # 1 config+sptlrpc
31951         # 2 params
31952         # 3 nodemap
31953         # 4 IR
31954         old=$((old * 4))
31955         oldc=0
31956         count=0
31957         while [ $old -ne $oldc ]; do
31958                 oldc=$($LCTL get_param -n 'ldlm.namespaces.MGC*.lock_count')
31959                 sleep 1
31960                 ((count++))
31961                 if [ $count -ge $TIMEOUT ]; then
31962                         error "too large timeout"
31963                 fi
31964         done
31965         umount_client $MOUNT || error "umount failed"
31966         mount_client $MOUNT || error "mount failed"
31967         cancel_lru_locks MGC
31968         newc=$($LCTL get_param -n 'ldlm.namespaces.MGC*.lock_count')
31969
31970         [ $oldc -lt $newc ] && error "mgc lock leak ($oldc != $newc)"
31971
31972         return 0
31973 }
31974 run_test 901 "don't leak a mgc lock on client umount"
31975
31976 # LU-13377
31977 test_902() {
31978         [ $CLIENT_VERSION -lt $(version_code 2.13.52) ] &&
31979                 skip "client does not have LU-13377 fix"
31980         #define OBD_FAIL_LLITE_SHORT_COMMIT 0x1415
31981         $LCTL set_param fail_loc=0x1415
31982         dd if=/dev/zero of=$DIR/$tfile bs=1M count=1
31983         cancel_lru_locks osc
31984         rm -f $DIR/$tfile
31985 }
31986 run_test 902 "test short write doesn't hang lustre"
31987
31988 # LU-14711
31989 test_903() {
31990         $LFS setstripe -i 0 -c 1 $DIR/$tfile $DIR/${tfile}-2
31991         echo "blah" > $DIR/${tfile}-2
31992         dd if=/dev/zero of=$DIR/$tfile bs=1M count=6 conv=fsync
31993         #define OBD_FAIL_OSC_SLOW_PAGE_EVICT 0x417
31994         $LCTL set_param fail_loc=0x417 fail_val=20
31995
31996         mv $DIR/${tfile}-2 $DIR/$tfile # Destroys the big object
31997         sleep 1 # To start the destroy
31998         wait_destroy_complete 150 || error "Destroy taking too long"
31999         cat $DIR/$tfile > /dev/null || error "Evicted"
32000 }
32001 run_test 903 "Test long page discard does not cause evictions"
32002
32003 test_904() {
32004         [ "$mds1_FSTYPE" == "ldiskfs" ] || skip "ldiskfs only test"
32005         do_facet mds1 $DEBUGFS -R features $(mdsdevname 1) |
32006                 grep -q project || skip "skip project quota not supported"
32007
32008         local testfile="$DIR/$tdir/$tfile"
32009         local xattr="trusted.projid"
32010         local projid
32011         local mdts=$(comma_list $(mdts_nodes))
32012         local saved=$(do_facet mds1 $LCTL get_param -n \
32013                 osd-ldiskfs.*MDT0000.enable_projid_xattr)
32014
32015         do_nodes $mdts $LCTL set_param osd-ldiskfs.*MDT*.enable_projid_xattr=0
32016         stack_trap "do_nodes $mdts $LCTL set_param \
32017                 osd-ldiskfs.*MDT*.enable_projid_xattr=$saved"
32018
32019         mkdir -p $DIR/$tdir
32020         touch $testfile
32021         #hide projid xattr on server
32022         $LFS project -p 1 $testfile ||
32023                 error "set $testfile project id failed"
32024         getfattr -m - $testfile | grep $xattr &&
32025                 error "do not show trusted.projid when disabled on server"
32026         do_nodes $mdts $LCTL set_param osd-ldiskfs.*MDT*.enable_projid_xattr=1
32027         #should be hidden when projid is 0
32028         $LFS project -p 0 $testfile ||
32029                 error "set $testfile project id failed"
32030         getfattr -m - $testfile | grep $xattr &&
32031                 error "do not show trusted.projid with project ID 0"
32032
32033         #still can getxattr explicitly
32034         projid=$(getfattr -n $xattr $testfile |
32035                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
32036         [ $projid == "0" ] ||
32037                 error "projid expected 0 not $projid"
32038
32039         #set the projid via setxattr
32040         setfattr -n $xattr -v "1000" $testfile ||
32041                 error "setattr failed with $?"
32042         projid=($($LFS project $testfile))
32043         [ ${projid[0]} == "1000" ] ||
32044                 error "projid expected 1000 not $projid"
32045
32046         #check the new projid via getxattr
32047         $LFS project -p 1001 $testfile ||
32048                 error "set $testfile project id failed"
32049         getfattr -m - $testfile | grep $xattr ||
32050                 error "should show trusted.projid when project ID != 0"
32051         projid=$(getfattr -n $xattr $testfile |
32052                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
32053         [ $projid == "1001" ] ||
32054                 error "projid expected 1001 not $projid"
32055
32056         #try to set invalid projid
32057         setfattr -n $xattr -v "4294967295" $testfile &&
32058                 error "set invalid projid should fail"
32059
32060         #remove the xattr means setting projid to 0
32061         setfattr -x $xattr $testfile ||
32062                 error "setfattr failed with $?"
32063         projid=($($LFS project $testfile))
32064         [ ${projid[0]} == "0" ] ||
32065                 error "projid expected 0 not $projid"
32066
32067         #should be hidden when parent has inherit flag and same projid
32068         $LFS project -srp 1002 $DIR/$tdir ||
32069                 error "set $tdir project id failed"
32070         getfattr -m - $testfile | grep $xattr &&
32071                 error "do not show trusted.projid with inherit flag"
32072
32073         #still can getxattr explicitly
32074         projid=$(getfattr -n $xattr $testfile |
32075                 sed -n 's/^trusted\.projid="\(.*\)"/\1/p')
32076         [ $projid == "1002" ] ||
32077                 error "projid expected 1002 not $projid"
32078 }
32079 run_test 904 "virtual project ID xattr"
32080
32081 # LU-8582
32082 test_905() {
32083         (( $OST1_VERSION >= $(version_code 2.15.50.220) )) ||
32084                 skip "need OST version >= 2.15.50.220 for fail_loc"
32085
32086         remote_ost_nodsh && skip "remote OST with nodsh"
32087         $LFS setstripe -c -1 -i 0 $DIR/$tfile || error "setstripe failed"
32088
32089         $LFS ladvise -a willread $DIR/$tfile || error "ladvise does not work"
32090
32091         #define OBD_FAIL_OST_OPCODE 0x253
32092         # OST_LADVISE = 21
32093         do_facet ost1 "$LCTL set_param fail_val=21 fail_loc=0x0253"
32094         $LFS ladvise -a willread $DIR/$tfile &&
32095                 error "unexpected success of ladvise with fault injection"
32096         $LFS ladvise -a willread $DIR/$tfile |&
32097                 grep -q "Operation not supported"
32098         (( $? == 0 )) || error "unexpected stderr of ladvise with fault injection"
32099 }
32100 run_test 905 "bad or new opcode should not stuck client"
32101
32102 test_906() {
32103         grep -q io_uring_setup /proc/kallsyms ||
32104                 skip "Client OS does not support io_uring I/O engine"
32105         io_uring_probe || skip "kernel does not support io_uring fully"
32106         which fio || skip_env "no fio installed"
32107         fio --enghelp | grep -q io_uring ||
32108                 skip_env "fio does not support io_uring I/O engine"
32109
32110         local file=$DIR/$tfile
32111         local ioengine="io_uring"
32112         local numjobs=2
32113         local size=50M
32114
32115         fio --name=seqwrite --ioengine=$ioengine        \
32116                 --bs=$PAGE_SIZE --direct=1 --numjobs=$numjobs   \
32117                 --iodepth=64 --size=$size --filename=$file --rw=write ||
32118                 error "fio seqwrite $file failed"
32119
32120         fio --name=seqread --ioengine=$ioengine \
32121                 --bs=$PAGE_SIZE --direct=1 --numjobs=$numjobs   \
32122                 --iodepth=64 --size=$size --filename=$file --rw=read ||
32123                 error "fio seqread $file failed"
32124
32125         rm -f $file || error "rm -f $file failed"
32126 }
32127 run_test 906 "Simple test for io_uring I/O engine via fio"
32128
32129 test_907() {
32130         local max_pages=$($LCTL get_param -n osc.*.max_pages_per_rpc | head -n1)
32131
32132         # set stripe size to max rpc size
32133         $LFS setstripe -i 0 -c 2 -S $((max_pages * PAGE_SIZE)) $DIR/$tfile
32134         $LFS getstripe $DIR/$tfile
32135 #define OBD_FAIL_OST_EROFS               0x216
32136         do_facet ost1 "$LCTL set_param fail_val=3 fail_loc=0x80000216"
32137
32138         local bs=$((max_pages * PAGE_SIZE / 16))
32139
32140         # write full one stripe and one block
32141         dd if=/dev/zero of=$DIR/$tfile bs=$bs count=17 || error "dd failed"
32142
32143         rm $DIR/$tfile || error "rm failed"
32144 }
32145 run_test 907 "write rpc error during unlink"
32146
32147
32148 complete_test $SECONDS
32149 [ -f $EXT2_DEV ] && rm $EXT2_DEV || true
32150 check_and_cleanup_lustre
32151 if [ "$I_MOUNTED" != "yes" ]; then
32152         lctl set_param debug="$OLDDEBUG" 2> /dev/null || true
32153 fi
32154 exit_status