Whamcloud - gitweb
3e50c773097324720ccbe4784a1013ff6838b5d3
[fs/lustre-release.git] / lustre / tests / sanity-flr.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6 # Run test by setting NOSETUP=true when ltest has setup env for us
7 set -e
8 set +o posix
9
10 SRCDIR=$(dirname $0)
11 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
12
13 ONLY=${ONLY:-"$*"}
14 # Bug number for skipped test:
15 ALWAYS_EXCEPT="$SANITY_FLR_EXCEPT 201"
16 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
17
18 [ "$ALWAYS_EXCEPT$EXCEPT" ] &&
19         echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
20
21 TMP=${TMP:-/tmp}
22 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
23 LFS=${LFS:-lfs}
24 LCTL=${LCTL:-lctl}
25 MULTIOP=${MULTIOP:-multiop}
26
27 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
28 . $LUSTRE/tests/test-framework.sh
29 init_test_env $@
30 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
31 init_logging
32
33 check_and_setup_lustre
34 DIR=${DIR:-$MOUNT}
35 assert_DIR
36
37 if [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.64) ]]; then
38         skip_env "Need MDS version at least 2.7.64" && exit
39 fi
40
41 build_test_filter
42
43 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] &&
44         error "\$RUNAS_ID set to 0, but \$UID is also 0!"
45 check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
46
47 # global array to store mirror IDs
48 declare -a mirror_array
49 get_mirror_ids() {
50         local tf=$1
51         local id
52         local array
53
54         array=()
55         for id in $($LFS getstripe $tf | awk '/lcme_id/{print $2}'); do
56                 array[${#array[@]}]=$((id >> 16))
57         done
58
59         mirror_array=($(printf "%s\n" "${array[@]}" | sort -u))
60
61         echo ${#mirror_array[@]}
62 }
63
64 drop_client_cache() {
65         echo 3 > /proc/sys/vm/drop_caches
66 }
67
68 stop_osts() {
69         local idx
70
71         for idx in "$@"; do
72                 stop ost$idx
73         done
74
75         for idx in "$@"; do
76                 wait_osc_import_state client ost$idx DISCONN
77         done
78 }
79
80 start_osts() {
81         local idx
82
83         for idx in "$@"; do
84                 start ost$idx $(ostdevname $idx) $OST_MOUNT_OPTS ||
85                         error "start ost$idx failed"
86         done
87
88         for idx in "$@"; do
89                 wait_osc_import_state client ost$idx FULL
90         done
91 }
92
93 # command line test cases
94 test_1() {
95         local tf=$DIR/$tfile
96         local mirror_count=16 # LUSTRE_MIRROR_COUNT_MAX
97
98         $LFS setstripe -E EOF -c -1 $tf
99
100         local stripes[0]=$OSTCOUNT
101
102         for ((i = 1; i < $mirror_count; i++)); do
103                 # add mirrors with different stripes to the file
104                 stripes[$i]=$((RANDOM % OSTCOUNT))
105                 [ ${stripes[$i]} -eq 0 ] && stripes[$i]=1
106
107                 $LFS setstripe --component-add --mirror -c ${stripes[$i]} $tf
108         done
109
110         [ $(get_mirror_ids $tf) -ne $mirror_count ] &&
111                 error "mirror count error"
112
113         # can't create mirrors exceeding LUSTRE_MIRROR_COUNT_MAX
114         $LFS setstripe --component-add --mirror $tf &&
115                 error "Creating the $((mirror_count+1))th mirror succeeded"
116
117         local ids=($($LFS getstripe $tf | awk '/lcme_id/{print $2}' |
118                         tr '\n' ' '))
119
120         # verify the range of components and stripe counts
121         for ((i = 0; i < $mirror_count; i++)); do
122                 local sc=$($LFS getstripe -I${ids[$i]} -c $tf)
123                 local start=$($LFS getstripe -I${ids[$i]} --component-start $tf)
124                 local end=$($LFS getstripe -I${ids[$i]} --component-end $tf)
125
126                 [[ ${stripes[$i]} = $sc ]] || {
127                         $LFS getstripe -v $tf;
128                         error "$i: sc error: id: ${ids[$i]}, ${stripes[$i]}";
129                 }
130                 [ $start -eq 0 ] || {
131                         $LFS getstripe -v $tf;
132                         error "$i: start error id: ${ids[$i]}";
133                 }
134                 [ $end = "EOF" ] || {
135                         $LFS getstripe -v $tf;
136                         error "$i: end error id: ${ids[$i]}";
137                 }
138         done
139 }
140 run_test 1 "create components with setstripe options"
141
142 test_2() {
143         local tf=$DIR/$tfile
144         local tf2=$DIR/$tfile-2
145
146         $LFS setstripe -E 1M -E EOF -c 1 $tf
147         $LFS setstripe -E 2M -E EOF -c -1 $tf2
148
149         local layout=$($LFS getstripe $tf2 | grep -A 4 lmm_objects)
150
151         $LFS setstripe --component-add --mirror=$tf2 $tf
152
153         [ $(get_mirror_ids $tf) -ne 2 ] && error "mirror count should be 2"
154         $LFS getstripe $tf2 | grep -q 'no stripe info' ||
155                 error "$tf2 still has stripe info"
156 }
157 run_test 2 "create components from existing files"
158
159 test_3() {
160         [[ $MDSCOUNT -lt 2 ]] && skip "need >= 2 MDTs" && return
161
162         for ((i = 0; i < 2; i++)); do
163                 $LFS mkdir -i $i $DIR/$tdir-$i
164                 $LFS setstripe -E -1 $DIR/$tdir-$i/$tfile
165         done
166
167         $LFS setstripe --component-add --mirror=$DIR/$tdir-1/$tfile \
168                 $DIR/$tdir-0/$tfile || error "creating mirrors"
169
170         # mdt doesn't support to cancel layout lock for remote objects, do
171         # it here manually.
172         cancel_lru_locks mdc
173
174         # make sure the mirrorted file was created successfully
175         [[ $($LFS getstripe --component-count $DIR/$tdir-0/$tfile) -eq 2 ]] ||
176                 { $LFS getstripe $DIR/$tdir-0/$tfile;
177                         error "expected 2 components"; }
178
179         # cleanup
180         rm -rf $DIR/$tdir-*
181 }
182 run_test 3 "create components from files located on different MDTs"
183
184 test_21() {
185         local tf=$DIR/$tfile
186         local tf2=$DIR/$tfile-2
187
188         [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return
189
190         $LFS setstripe -E EOF -o 0 $tf
191         $LFS setstripe -E EOF -o 1 $tf2
192
193         local dd_count=$((RANDOM % 20 + 1))
194         dd if=/dev/zero of=$tf bs=1M count=$dd_count
195         dd if=/dev/zero of=$tf2 bs=1M count=1 seek=$((dd_count - 1))
196         cancel_lru_locks osc
197
198         local blocks=$(du -kc $tf $tf2 | awk '/total/{print $1}')
199
200         # add component
201         $LFS setstripe --component-add --mirror=$tf2 $tf
202
203         # cancel layout lock
204         cancel_lru_locks mdc
205
206         local new_blocks=$(du -k $tf | awk '{print $1}')
207         [ $new_blocks -eq $blocks ] ||
208         error "i_blocks error expected: $blocks, actual: $new_blocks"
209 }
210 run_test 21 "glimpse should report accurate i_blocks"
211
212 get_osc_lock_count() {
213         local lock_count=0
214
215         for idx in "$@"; do
216                 local osc_name
217                 local count
218
219                 osc_name=${FSNAME}-OST$(printf "%04x" $((idx-1)))-osc-'ffff*'
220                 count=$($LCTL get_param -n ldlm.namespaces.$osc_name.lock_count)
221                 lock_count=$((lock_count + count))
222         done
223         echo $lock_count
224 }
225
226 test_22() {
227         local tf=$DIR/$tfile
228
229         $LFS setstripe -E EOF -o 0 $tf
230         dd if=/dev/zero of=$tf bs=1M count=$((RANDOM % 20 + 1))
231
232         # add component, two mirrors located on the same OST ;-)
233         $LFS setstripe --component-add --mirror -o 0 $tf
234
235         size_blocks=$(stat --format="%b %s" $tf)
236
237         cancel_lru_locks mdc
238         cancel_lru_locks osc
239
240         local new_size_blocks=$(stat --format="%b %s" $tf)
241
242         # make sure there is no lock cached
243         [ $(get_osc_lock_count 1) -eq 0 ] || error "glimpse requests were sent"
244
245         [ "$new_size_blocks" = "$size_blocks" ] ||
246                 echo "size expected: $size_blocks, actual: $new_size_blocks"
247
248         rm -f $tmpfile
249 }
250 run_test 22 "no glimpse to OSTs for READ_ONLY files"
251
252 test_31() {
253         local tf=$DIR/$tfile
254
255         $LFS setstripe -E EOF -o 0 $tf
256         $LFS setstripe --component-add --mirror -o 1 $tf
257
258         #define OBD_FAIL_GLIMPSE_IMMUTABLE 0x1A00
259         $LCTL set_param fail_loc=0x1A00
260
261         local ost_idx
262         for ((ost_idx = 1; ost_idx <= 2; ost_idx++)); do
263                 cancel_lru_locks osc
264                 stop_osts $ost_idx
265
266                 local tmpfile=$(mktemp)
267                 stat --format="%b %s" $tf > $tmpfile  &
268                 local pid=$!
269
270                 local cnt=0
271                 while [ $cnt -le 5 ]; do
272                         kill -0 $pid > /dev/null 2>&1 || break
273                         sleep 1
274                         ((cnt += 1))
275                 done
276                 kill -0 $pid > /dev/null 2>&1 &&
277                         error "stat process stuck due to unavailable OSTs"
278
279                 # make sure glimpse request has been sent
280                 [ $(get_osc_lock_count 1 2) -ne 0 ] ||
281                         error "OST $ost_idx: no glimpse request was sent"
282
283                 start_osts $ost_idx
284         done
285 }
286 run_test 31 "make sure glimpse request can be retried"
287
288 test_32() {
289         [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return
290         rm -f $DIR/$tfile $DIR/$tfile-2
291
292         $LFS setstripe -E EOF -o 0 $DIR/$tfile
293         dd if=/dev/urandom of=$DIR/$tfile bs=1M count=$((RANDOM % 10 + 2))
294
295         local fsize=$(stat -c %s $DIR/$tfile)
296         [[ $fsize -ne 0 ]] || error "file size is (wrongly) zero"
297
298         local cksum=$(md5sum $DIR/$tfile)
299
300         # create a new mirror in sync mode
301         $LFS setstripe --component-add --mirror -o 1 $DIR/$tfile
302
303         # make sure the mirrored file was created successfully
304         [ $(get_mirror_ids $DIR/$tfile) -eq 2 ] ||
305                 { $LFS getstripe $DIR/$tfile; error "expected 2 mirrors"; }
306
307         drop_client_cache
308         stop_osts 1
309
310         # check size is correct, glimpse request should go to the 2nd mirror
311         $CHECKSTAT -t file -s $fsize $DIR/$tfile ||
312                 error "file size error $fsize vs. $(stat -c %s $DIR/$tfile)"
313
314         echo "reading file from the 2nd mirror and verify checksum"
315         [[ "$cksum" == "$(md5sum $DIR/$tfile)" ]] ||
316                 error "checksum error: expected $cksum"
317
318         start_osts 1
319 }
320 run_test 32 "data should be mirrored to newly created mirror"
321
322 test_33() {
323         [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return
324
325         rm -f $DIR/$tfile $DIR/$tfile-2
326
327         # create a file with two mirrors
328         $LFS setstripe -E EOF -o 0 $DIR/$tfile
329         local max_count=100
330         local count=0
331         while [ $count -lt $max_count ]; do
332                 echo "ost1" >> $DIR/$tfile
333                 count=$((count + 1));
334         done
335
336         # tmp file that will be used as mirror
337         $LFS setstripe -E EOF -o 1 $DIR/$tfile-2
338         count=0
339         while [ $count -lt $max_count ]; do
340                 echo "ost2" >> $DIR/$tfile-2
341                 count=$((count + 1));
342         done
343
344         # create a mirrored file
345         $LFS setstripe --component-add --mirror=$DIR/$tfile-2 $DIR/$tfile
346
347         # make sure that $tfile has two mirrors and $tfile-2 has no stripe
348         [ $(get_mirror_ids $DIR/$tfile) -eq 2 ] ||
349                 { $LFS getstripe $DIR/$tfile; error "expected count 2"; }
350         $LFS getstripe $DIR/$tfile-2 | grep -q "no stripe info" ||
351                 { $LFS getstripe $DIR/$tfile; error "expected no stripe"; }
352
353         # execpted file size
354         local fsize=$((5 * max_count))
355         $CHECKSTAT -t file -s $fsize $DIR/$tfile ||
356                 error "mirrored file size is not $fsize"
357
358         # read file - all OSTs are available
359         echo "reading file (data should be provided by ost1)... "
360         local rs=$(cat $DIR/$tfile | head -1)
361         [[ "$rs" == "ost1" ]] ||
362                 error "file content error: expected: \"ost1\", actual: \"$rs\""
363
364         # read file again with ost1 failed
365         stop_osts 1
366         drop_client_cache
367
368         echo "reading file (data should be provided by ost2)..."
369         local rs=$(cat $DIR/$tfile | head -1)
370         [[ "$rs" == "ost2" ]] ||
371                 error "file content error: expected: \"ost2\", actual: \"$rs\""
372
373         # remount ost1
374         start_osts 1
375
376         # read file again with ost2 failed
377         $LCTL set_param ldlm.namespaces.lustre-*-osc-ffff*.lru_size=clear
378
379         fail ost2 &
380         sleep 1
381
382         # check size, glimpse should work
383         $CHECKSTAT -t file -s $fsize $DIR/$tfile ||
384                 error "mirrored file size is not $fsize"
385
386         echo "reading file (data should be provided by ost1)..."
387         local rs=$(cat $DIR/$tfile | head -1)
388         [[ "$rs" == "ost1" ]] ||
389                 error "file content error: expected: \"ost1\", actual: \"$rs\""
390
391         wait_osc_import_state client ost2 FULL
392 }
393 run_test 33 "read can choose available mirror to read"
394
395 test_34a() {
396         [[ $OSTCOUNT -lt 4 ]] && skip "need >= 4 OSTs" && return
397
398         rm -f $DIR/$tfile $DIR/$tfile-2 $DIR/$tfile-ref
399
400         # reference file
401         $LFS setstripe -o 0 $DIR/$tfile-ref
402         dd if=/dev/urandom of=$DIR/$tfile-ref bs=1M count=3
403
404         # create a file with two mirrors
405         $LFS setstripe -E -1 -o 0,1 -S 1M $DIR/$tfile
406         dd if=$DIR/$tfile-ref of=$DIR/$tfile bs=1M
407
408         $LFS setstripe -E -1 -o 2,3 -S 1M $DIR/$tfile-2
409         dd if=$DIR/$tfile-ref of=$DIR/$tfile-2 bs=1M
410
411         $CHECKSTAT -t file -s $((3 * 1024 * 1024)) $DIR/$tfile ||
412                 error "mirrored file size is not 3M"
413
414         # merge a mirrored file
415         $LFS setstripe --component-add --mirror=$DIR/$tfile-2 $DIR/$tfile
416
417         cancel_lru_locks osc
418
419         # stop two OSTs, so the 2nd stripe of the 1st mirror and
420         # the 1st stripe of the 2nd mirror will be inaccessible, ...
421         stop_osts 2 3
422
423         echo "comparing files ... "
424
425         # however, read can still return the correct data. It should return
426         # the 1st stripe from mirror 1 and 2st stripe from mirror 2.
427         cmp -n 2097152 <(rwv -f $DIR/$tfile -r -o -n 1 2097152) \
428                 $DIR/$tfile-ref || error "file reading error"
429
430         start_osts 2 3
431 }
432 run_test 34a "read mirrored file with multiple stripes"
433
434 test_34b() {
435         [[ $OSTCOUNT -lt 4 ]] && skip "need >= 4 OSTs" && return
436
437         rm -f $DIR/$tfile $DIR/$tfile-2 $DIR/$tfile-ref
438
439         # reference file
440         $LFS setstripe -o 0 $DIR/$tfile-ref
441         dd if=/dev/urandom of=$DIR/$tfile-ref bs=1M count=3
442
443         $LFS setstripe -E 1M -S 1M -o 0 -E eof -o 1 $DIR/$tfile
444         dd if=$DIR/$tfile-ref of=$DIR/$tfile bs=1M
445
446         $LFS setstripe -E 1M -S 1M -o 2 -E eof -o 3 $DIR/$tfile-2
447         dd if=$DIR/$tfile-ref of=$DIR/$tfile-2 bs=1M
448
449         $CHECKSTAT -t file -s $((3 * 1024 * 1024)) $DIR/$tfile ||
450                 error "mirrored file size is not 3M"
451
452         # merge a mirrored file
453         $LFS setstripe --component-add --mirror=$DIR/$tfile-2 $DIR/$tfile
454
455         cancel_lru_locks osc
456
457         # stop two OSTs, so the 2nd component of the 1st mirror and
458         # the 1st component of the 2nd mirror will be inaccessible, ...
459         stop_osts 2 3
460
461         echo "comparing files ... "
462
463         # however, read can still return the correct data. It should return
464         # the 1st stripe from mirror 1 and 2st stripe from mirror 2.
465         cmp -n 2097152 <(rwv -f $DIR/$tfile -r -o -n 1 2097152) \
466                 $DIR/$tfile-ref || error "file reading error"
467
468         start_osts 2 3
469 }
470 run_test 34b "read mirrored file with multiple components"
471
472 test_35() {
473         local tf=$DIR/$tfile
474
475         $LFS setstripe -E eof $tf
476
477         # add an out-of-sync mirror to the file
478         $LFS setstripe --component-add --mirror -c 2 $tf
479
480         $MULTIOP $tf oO_WRONLY:c ||
481                 error "write open a mirrored file failed"
482
483         # truncate file should return error
484         $TRUNCATE $tf 100 || error "error truncating a mirrored file"
485 }
486 run_test 35 "allow to write to mirrored files"
487
488 verify_ost_layout_version() {
489         local tf=$1
490
491         # get file layout version
492         local flv=$($LFS getstripe $tf | awk '/lcm_layout_gen/{print $2}')
493
494         # layout version from OST objects
495         local olv=$($MULTIOP $tf oXc | awk '/ostlayoutversion/{print $2}')
496
497         [ $flv -eq $olv ] || error "layout version mismatch: $flv vs. $olv"
498 }
499
500 create_file_36() {
501         local tf
502
503         for tf in "$@"; do
504                 $LFS setstripe -E 1M -E 2M -E 4M -E eof -c -1 $tf
505                 $LFS setstripe -E 3M -E 6M -E eof -c -1 $tf-tmp
506
507                 $LFS setstripe --component-add --mirror=$tf-tmp $tf
508                 rm -f $tf-tmp
509         done
510 }
511
512 test_36() {
513         local tf=$DIR/$tfile
514
515         create_file_36 $tf $tf-2 $tf-3
516
517         [ $(get_mirror_ids $tf) -gt 1 ] || error "wrong mirror count"
518
519         # test case 1 - check file write and verify layout version
520         $MULTIOP $tf oO_WRONLY:c ||
521                 error "write open a mirrored file failed"
522
523         # write open file should not return error
524         $MULTIOP $tf oO_WRONLY:w1024Yc || error "write mirrored file error"
525
526         # instantiate components should work
527         dd if=/dev/zero of=$tf bs=1M count=12 || error "write file error"
528
529         # verify OST layout version
530         verify_ost_layout_version $tf
531
532         # test case 2
533         local mds_idx=mds$(($($LFS getstripe -M $tf-2) + 1))
534
535         local delay_sec=10
536         do_facet $mds_idx $LCTL set_param fail_val=$delay_sec
537
538         #define OBD_FAIL_FLR_LV_DELAY 0x1A01
539         do_facet $mds_idx $LCTL set_param fail_loc=0x1A01
540
541         # write should take at least $fail_loc seconds and succeed
542         local st=$(date +%s)
543         $MULTIOP $tf-2 oO_WRONLY:w1024Yc || error "write mirrored file error"
544
545         [ $(date +%s) -ge $((st+delay_sec)) ] ||
546                 error "write finished before layout version is transmitted"
547
548         # verify OST layout version
549         verify_ost_layout_version $tf
550
551         do_facet $mds_idx $LCTL set_param fail_loc=0
552
553         # test case 3
554         mds_idx=mds$(($($LFS getstripe -M $tf-3) + 1))
555
556         #define OBD_FAIL_FLR_LV_INC 0x1A02
557         do_facet $mds_idx $LCTL set_param fail_loc=0x1A02
558
559         # write open file should return error
560         $MULTIOP $tf-3 oO_WRONLY:O_SYNC:w1024c &&
561                 error "write a mirrored file succeeded" || true
562
563         do_facet $mds_idx $LCTL set_param fail_loc=0
564 }
565 run_test 36 "write to mirrored files"
566
567 create_files_37() {
568         local tf
569         local fsize=$1
570
571         echo "create test files with size $fsize .."
572
573         shift
574         for tf in "$@"; do
575                 $LFS setstripe -E 1M -c 1 -E eof -c -1 $tf
576
577                 dd if=/dev/urandom of=$tf bs=1M count=16 &> /dev/null
578                 $TRUNCATE $tf $fsize
579         done
580 }
581
582 test_37()
583 {
584         local tf=$DIR/$tfile
585         local tf2=$DIR/$tfile-2
586         local tf3=$DIR/$tfile-3
587
588         create_files_37 $((RANDOM + 15 * 1048576)) $tf $tf2 $tf3
589
590         # assume the mirror id will be 1, 2, and 3
591         declare -A checksums
592         checksums[1]=$(md5sum $tf | cut -f 1 -d' ')
593         checksums[2]=$(md5sum $tf2 | cut -f 1 -d' ')
594         checksums[3]=$(md5sum $tf3 | cut -f 1 -d' ')
595
596         printf '%s\n' "${checksums[@]}"
597
598         # merge these files into a mirrored file
599         $LFS setstripe --component-add --mirror=$tf2 $tf
600         $LFS setstripe --component-add --mirror=$tf3 $tf
601
602         get_mirror_ids $tf
603
604         # verify mirror read, checksums should equal to the original files'
605         echo "Verifying mirror read .."
606
607         local sum
608         for i in ${mirror_array[@]}; do
609                 sum=$(mirror_io dump -i $i $tf | md5sum | cut -f 1 -d' ')
610                 [ "$sum" = "${checksums[$i]}" ] ||
611                         error "$i: mismatch: \'${checksums[$i]}\' vs. \'$sum\'"
612         done
613
614         # verify mirror copy, write to this mirrored file will invalidate
615         # the other two mirrors
616         echo "Verifying mirror copy .."
617
618         local osts=$(comma_list $(osts_nodes))
619
620         # define OBD_FAIL_OST_SKIP_LV_CHECK     0x241
621         do_nodes $osts lctl set_param fail_loc=0x241
622
623         mirror_io copy -i ${mirror_array[0]} \
624                 -t $(echo ${mirror_array[@]:1} | tr ' ' ',') $tf ||
625                         error "mirror copy error"
626
627         do_nodes $osts lctl set_param fail_loc=0
628
629         # verify copying is successful by checking checksums
630         remount_client $MOUNT
631         for i in ${mirror_array[@]}; do
632                 sum=$(mirror_io dump -i $i $tf | md5sum | cut -f 1 -d' ')
633                 [ "$sum" = "${checksums[1]}" ] ||
634                         error "$i: mismatch checksum after copy"
635         done
636
637         rm -f $tf $tf2 $tf3
638 }
639 run_test 37 "mirror I/O API verification"
640
641 verify_flr_state()
642 {
643         local tf=$1
644         local expected_state=$2
645         local state_strings=("not_flr" "read_only" "write_pending" \
646                 "sync_pending")
647
648         local state=$($LFS getstripe -v $tf | awk '/lcm_flags/{ print $2 }')
649         [ $expected_state = ${state_strings[$state]} ] ||
650                 error "expected: $expected_state, " \
651                         "actual ${state_strings[$state]}($state)"
652 }
653
654 test_38() {
655         local tf=$DIR/$tfile
656         local ref=$DIR/${tfile}-ref
657
658         $LFS setstripe -E 1M -c 1 -E 4M -c 2 -E eof -c -1 $tf
659         $LFS setstripe -E 2M -c 1 -E 6M -c 2 -E 8M -c -1 -E eof -c -1 $tf-2
660         $LFS setstripe -E 4M -c 1 -E 8M -c 2 -E eof -c -1 $tf-3
661
662         # instantiate all components
663         $LFS setstripe --component-add --mirror=$tf-2 $tf
664         $LFS setstripe --component-add --mirror=$tf-3 $tf
665         $LFS setstripe --component-add --mirror -c 1 $tf
666
667         verify_flr_state $tf "read_only"
668
669         dd if=/dev/urandom of=$ref  bs=1M count=16 &> /dev/null
670
671         local fsize=$((RANDOM << 8 + 1048576))
672         $TRUNCATE $ref $fsize
673
674         local ref_cksum=$(md5sum $ref | cut -f 1 -d' ')
675
676         # case 1: verify write to mirrored file & resync work
677         cp $ref $tf || error "copy from $ref to $f error"
678         verify_flr_state $tf "write_pending"
679
680         local file_cksum=$(md5sum $tf | cut -f 1 -d' ')
681         [ "$file_cksum" = "$ref_cksum" ] || error "write failed, cksum mismatch"
682
683         get_mirror_ids $tf
684         echo "mirror IDs: ${mirror_array[@]}"
685
686         local valid_mirror stale_mirror id mirror_cksum
687         for id in "${mirror_array[@]}"; do
688                 mirror_cksum=$(mirror_io dump -i $id $tf |
689                                 md5sum | cut -f 1 -d' ')
690                 [ "$ref_cksum" == "$mirror_cksum" ] &&
691                         { valid_mirror=$id; continue; }
692
693                 stale_mirror=$id
694         done
695
696         [ -z "$stale_mirror" ] && error "stale mirror doesn't exist"
697         [ -z "$valid_mirror" ] && error "valid mirror doesn't exist"
698
699         mirror_io resync $tf || error "resync failed"
700         verify_flr_state $tf "read_only"
701
702         mirror_cksum=$(mirror_io dump -i $stale_mirror $tf |
703                         md5sum | cut -f 1 -d' ')
704         [ "$file_cksum" = "$ref_cksum" ] || error "resync failed"
705
706         # case 2: inject an error to make mirror_io exit after changing
707         # the file state to sync_pending so that we can start a concurrent
708         # write.
709         $MULTIOP $tf oO_WRONLY:w$((RANDOM % 1048576 + 1024))c
710         verify_flr_state $tf "write_pending"
711
712         mirror_io resync -e resync_start $tf && error "resync succeeded"
713         verify_flr_state $tf "sync_pending"
714
715         # from sync_pending to write_pending
716         $MULTIOP $tf oO_WRONLY:w$((RANDOM % 1048576 + 1024))c
717         verify_flr_state $tf "write_pending"
718
719         mirror_io resync -e resync_start $tf && error "resync succeeded"
720         verify_flr_state $tf "sync_pending"
721
722         # from sync_pending to read_only
723         mirror_io resync $tf || error "resync failed"
724         verify_flr_state $tf "read_only"
725 }
726 run_test 38 "resync"
727
728 ctrl_file=$(mktemp /tmp/CTRL.XXXXXX)
729 lock_file=$(mktemp /var/lock/FLR.XXXXXX)
730
731 write_file_200() {
732         local tf=$1
733
734         local fsize=$(stat --printf=%s $tf)
735
736         while [ -f $ctrl_file ]; do
737                 local off=$((RANDOM << 8))
738                 local len=$((RANDOM << 5 + 131072))
739
740                 [ $((off + len)) -gt $fsize ] && {
741                         fsize=$((off + len))
742                         echo "Extending file size to $fsize .."
743                 }
744
745                 flock -s $lock_file -c \
746                         "$MULTIOP $tf oO_WRONLY:z${off}w${len}c" ||
747                                 { rm -f $ctrl_file;
748                                   error "failed writing to $off:$len"; }
749                 sleep 0.$((RANDOM % 2 + 1))
750         done
751 }
752
753 read_file_200() {
754         local tf=$1
755
756         while [ -f $ctrl_file ]; do
757                 flock -s $lock_file -c "cat $tf &> /dev/null" ||
758                         { rm -f $ctrl_file; error "read failed"; }
759                 sleep 0.$((RANDOM % 2 + 1))
760         done
761 }
762
763 resync_file_200() {
764         local tf=$1
765
766         options=("" "-e resync_start" "-e delay_before_copy -d 1" "" "")
767
768         exec 200<>$lock_file
769         while [ -f $ctrl_file ]; do
770                 local index=$((RANDOM % ${#options[@]}))
771                 local lock_taken=false
772
773                 [ $((RANDOM % 4)) -eq 0 ] && {
774                         index=0
775                         lock_taken=true
776                         echo -n "lock to "
777                 }
778
779                 echo -n "resync file $tf with '${options[$index]}' .."
780
781                 $lock_taken && flock -x 200
782                 mirror_io resync ${options[$index]} $tf &> /dev/null &&
783                         echo "done" || echo "failed"
784
785                 $lock_taken && flock -u 200
786
787                 sleep 0.$((RANDOM % 8 + 1))
788         done
789 }
790
791 test_200() {
792         local tf=$DIR/$tfile
793         local tf2=$DIR2/$tfile
794         local tf3=$DIR3/$tfile
795
796         $LFS setstripe -E 1M -E 2M -c 2 -E 4M -E 16M -E eof $tf
797         $LFS setstripe -E 2M -E 6M -c 2 -E 8M -E 32M -E eof $tf-2
798         $LFS setstripe -E 4M -c 2 -E 8M -E 64M -E eof $tf-3
799
800         $LFS setstripe --component-add --mirror=$tf-2 $tf
801         $LFS setstripe --component-add --mirror=$tf-3 $tf
802
803         mkdir -p $MOUNT2 && mount_client $MOUNT2
804
805         mkdir -p $MOUNT3 && mount_client $MOUNT3
806
807         verify_flr_state $tf3 "read_only"
808
809         #define OBD_FAIL_FLR_RANDOM_PICK_MIRROR 0x1A03
810         $LCTL set_param fail_loc=0x1A03
811
812         local mds_idx=mds$(($($LFS getstripe -M $tf) + 1))
813         do_facet $mds_idx $LCTL set_param fail_loc=0x1A03
814
815         declare -a pids
816
817         write_file_200 $tf &
818         pids+=($!)
819
820         read_file_200 $tf &
821         pids+=($!)
822
823         write_file_200 $tf2 &
824         pids+=($!)
825
826         read_file_200 $tf2 &
827         pids+=($!)
828
829         resync_file_200 $tf3 &
830         pids+=($!)
831
832         local sleep_time=60
833         [ "$SLOW" = "yes" ] && sleep_time=360
834         while [ $sleep_time -gt 0 -a -f $ctrl_file ]; do
835                 sleep 1
836                 ((--sleep_time))
837         done
838
839         rm -f $ctrl_file
840
841         echo "Waiting ${pids[@]}"
842         wait ${pids[@]}
843
844         umount_client $MOUNT2
845         umount_client $MOUNT3
846
847         rm -f $lock_file
848
849         # resync and verify mirrors
850         mirror_io resync $tf
851         get_mirror_ids $tf
852
853         local csum=$(mirror_io dump -i ${mirror_array[0]} $tf | md5sum)
854         for id in ${mirror_array[@]:1}; do
855                 [ "$(mirror_io dump -i $id $tf | md5sum)" = "$csum" ] ||
856                         error "checksum error for mirror $id"
857         done
858
859         true
860 }
861 run_test 200 "stress test"
862
863 cleanup_test_201() {
864         trap 0
865         do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister $CL_USER
866
867         umount_client $MOUNT2
868 }
869
870 test_201() {
871         local delay=${RESYNC_DELAY:-5}
872
873         MDT0=$($LCTL get_param -n mdc.*.mds_server_uuid |
874                awk '{ gsub(/_UUID/,""); print $1 }' | head -n1)
875
876         trap cleanup_test_201 EXIT
877
878         CL_USER=$(do_facet $SINGLEMDS $LCTL --device $MDT0 \
879                         changelog_register -n)
880
881         mkdir -p $MOUNT2 && mount_client $MOUNT2
882
883         local index=0
884         while :; do
885                 local log=$($LFS changelog $MDT0 $index | grep FLRW)
886                 [ -z "$log" ] && { sleep 1; continue; }
887
888                 index=$(echo $log | awk '{print $1}')
889                 local ts=$(date -d "$(echo $log | awk '{print $3}')" "+%s" -u)
890                 local fid=$(echo $log | awk '{print $6}' | sed -e 's/t=//')
891                 local file=$($LFS fid2path $MOUNT2 $fid 2> /dev/null)
892
893                 ((++index))
894                 [ -z "$file" ] && continue
895
896                 local now=$(date +%s)
897
898                 echo "file: $file $fid was modified at $ts, now: $now, " \
899                      "will be resynced at $((ts+delay))"
900
901                 [ $now -lt $((ts + delay)) ] && sleep $((ts + delay - now))
902
903                 mirror_io resync $file
904                 echo "$file resync done"
905         done
906
907         cleanup_test_201
908 }
909 run_test 201 "FLR data mover"
910
911 complete $SECONDS
912 check_and_cleanup_lustre
913 exit_status