Whamcloud - gitweb
LU-14876 out: don't connect to busy MDS-MDS export
[fs/lustre-release.git] / lustre / tests / sanity-scrub.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
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10
11 LUSTRE=${LUSTRE:-$(dirname $0)/..}
12 . $LUSTRE/tests/test-framework.sh
13 init_test_env $@
14 init_logging
15
16 ALWAYS_EXCEPT="$SANITY_SCRUB_EXCEPT"
17
18 [ "$SLOW" = "no" ] && EXCEPT_SLOW=""
19 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
20
21 build_test_filter
22
23 require_dsh_mds || exit 0
24
25 load_modules
26
27 if ! check_versions; then
28         skip "It is NOT necessary to test scrub under interoperation mode"
29         exit 0
30 fi
31
32 cleanupall
33
34 SAVED_MDSSIZE=${MDSSIZE}
35 SAVED_OSTSIZE=${OSTSIZE}
36 SAVED_OSTCOUNT=${OSTCOUNT}
37
38 # use small MDS + OST size to speed formatting time
39 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
40 # 400M MDT device can guarantee uninitialized groups during the OI scrub
41 [[ $MDSSIZE < 400000 || "$mds1_FSTYPE" == ldiskfs ]] && MDSSIZE=400000
42 [[ $OSTSIZE < 400000 || "$ost1_FSTYPE" == ldiskfs ]] && OSTSIZE=400000
43
44 # no need too many OSTs, to reduce the format/start/stop overhead
45 [ $OSTCOUNT -gt 4 ] && OSTCOUNT=4
46
47 # build up a clean test environment.
48 REFORMAT="yes" check_and_setup_lustre
49
50 MDT_DEV="${FSNAME}-MDT0000"
51 OST_DEV="${FSNAME}-OST0000"
52
53 scrub_start() {
54         local error_id=$1
55         local n
56
57         # use "lfsck_start -A" when we no longer need testing interop
58         for n in $(seq $MDSCOUNT); do
59                 do_facet mds$n $LCTL lfsck_start -M $(facet_svc mds$n) \
60                         -t scrub "$@" ||
61                         error "($error_id) Failed to start OI scrub on mds$n"
62         done
63 }
64
65 scrub_stop() {
66         local error_id=$1
67         local n
68
69         # use "lfsck_stop -A" when we no longer need testing interop
70         for n in $(seq $MDSCOUNT); do
71                 do_facet mds$n $LCTL lfsck_stop -M $(facet_svc mds$n) ||
72                         error "($error_id) Failed to stop OI scrub on mds$n"
73         done
74 }
75
76 scrub_status() {
77         local n=$1
78
79         do_facet mds$n $LCTL get_param -n osd-*.$(facet_svc mds$n).oi_scrub
80 }
81
82 START_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_start -M ${MDT_DEV} -t scrub"
83 START_SCRUB_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV} -t scrub"
84 STOP_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
85 SHOW_SCRUB="do_facet $SINGLEMDS \
86                 $LCTL get_param -n osd-*.${MDT_DEV}.oi_scrub"
87 SHOW_SCRUB_ON_OST="do_facet ost1 \
88                 $LCTL get_param -n osd-*.${OST_DEV}.oi_scrub"
89 MOUNT_OPTS_SCRUB="$MDS_MOUNT_OPTS -o user_xattr"
90 MOUNT_OPTS_NOSCRUB="$MDS_MOUNT_OPTS -o user_xattr,noscrub"
91
92 scrub_prep() {
93         local nfiles=$1
94         local inject=$2
95         local n
96
97         check_mount_and_prep
98
99         echo "preparing... $(date)"
100         for n in $(seq $MDSCOUNT); do
101                 echo "creating $nfiles files on mds$n"
102                 test_mkdir -i $((n - 1)) -c1 $DIR/$tdir/mds$n ||
103                         error "Failed to create directory mds$n"
104                 cp $LUSTRE/tests/*.sh $DIR/$tdir/mds$n ||
105                         error "Failed to copy files to mds$n"
106                 mkdir -p $DIR/$tdir/mds$n/d_$tfile ||
107                         error "mkdir failed on mds$n"
108                 touch $DIR/$tdir/mds$n/d_$tfile/f1 > \
109                         /dev/null || error "create failed on mds$n"
110                 dd if=/dev/zero of=$DIR/$tdir/mds$n/d_$tfile/f2 bs=1M count=1 ||
111                         error "write failed on mds$n"
112                 if [[ $nfiles -gt 0 ]]; then
113                         createmany -m $DIR/$tdir/mds$n/$tfile $nfiles > \
114                                 /dev/null || error "createmany failed on mds$n"
115                 fi
116         done
117         echo "prepared $(date)."
118
119         [ ! -z $inject ] && [ $inject -eq 2 ] && {
120                 #define OBD_FAIL_OSD_NO_OI_ENTRY        0x198
121                 do_nodes $(comma_list $(mdts_nodes)) \
122                                 $LCTL set_param fail_loc=0x198
123
124                 for n in $(seq $MDSCOUNT); do
125                         cp $LUSTRE/tests/runas $DIR/$tdir/mds$n ||
126                                 error "Fail to copy runas to MDS$n"
127                 done
128
129                 do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0
130         }
131
132         [ ! -z $inject ] && [ $inject -eq 1 ] &&
133                 [ "$mds1_FSTYPE" = "zfs" ] && {
134                 #define OBD_FAIL_OSD_FID_MAPPING        0x193
135                 do_nodes $(comma_list $(mdts_nodes)) \
136                         $LCTL set_param fail_loc=0x193
137
138                 for n in $(seq $MDSCOUNT); do
139                         chmod 0400 $DIR/$tdir/mds$n/test-framework.sh
140                         chmod 0400 $DIR/$tdir/mds$n/sanity-scrub.sh
141                 done
142
143                 do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0
144         }
145
146         cleanup_mount $MOUNT > /dev/null || error "Fail to stop client!"
147
148         # sync local transactions on every MDT
149         do_nodes $(comma_list $(mdts_nodes)) \
150                 "$LCTL set_param -n osd*.*MDT*.force_sync=1"
151
152         # wait for a while to cancel update logs after transactions committed.
153         sleep 3
154
155         # sync again to guarantee all things done.
156         do_nodes $(comma_list $(mdts_nodes)) \
157                 "$LCTL set_param -n osd*.*MDT*.force_sync=1"
158
159         for n in $(seq $MDSCOUNT); do
160                 echo "stop mds$n"
161                 stop mds$n > /dev/null || error "Fail to stop MDS$n!"
162         done
163
164         [ ! -z $inject ] && [ "$mds1_FSTYPE" = "ldiskfs" ] && {
165                 if [ $inject -eq 1 ]; then
166                         for n in $(seq $MDSCOUNT); do
167                                 mds_backup_restore mds$n ||
168                                         error "Backup/restore on mds$n failed"
169                         done
170                 elif [ $inject -eq 2 ]; then
171                         scrub_remove_ois 1
172                 fi
173         }
174 }
175
176 scrub_start_mds() {
177         local error_id=$1
178         local opts=$2
179         local n
180
181         for n in $(seq $MDSCOUNT); do
182                 start mds$n $(mdsdevname $n) $opts >/dev/null ||
183                         error "($error_id) Failed to start mds$n"
184         done
185 }
186
187 scrub_stop_mds() {
188         local error_id=$1
189         local n
190
191         for n in $(seq $MDSCOUNT); do
192                 echo "stopping mds$n"
193                 stop mds$n >/dev/null ||
194                         error "($error_id) Failed to stop mds$n"
195         done
196 }
197
198 scrub_check_status() {
199         local error_id=$1
200         local expected=$2
201         local n
202
203         for n in $(seq $MDSCOUNT); do
204                 wait_update_facet mds$n "$LCTL get_param -n \
205                         osd-*.$(facet_svc mds$n).oi_scrub |
206                         awk '/^status/ { print \\\$2 }'" "$expected" 6 ||
207                         error "($error_id) Expected '$expected' on mds$n"
208         done
209 }
210
211 scrub_check_flags() {
212         local error_id=$1
213         local expected=$2
214         local actual
215         local n
216
217         for n in $(seq $MDSCOUNT); do
218                 actual=$(do_facet mds$n $LCTL get_param -n \
219                         osd-*.$(facet_svc mds$n).oi_scrub |
220                         awk '/^flags/ { print $2 }')
221                 if [ "$actual" != "$expected" ]; then
222                         error "($error_id) Expected '$expected' on mds$n, but" \
223                                "got '$actual'"
224                 fi
225         done
226 }
227
228 scrub_check_params() {
229         local error_id=$1
230         local expected=$2
231         local actual
232         local n
233
234         for n in $(seq $MDSCOUNT); do
235                 actual=$(do_facet mds$n $LCTL get_param -n \
236                         osd-*.$(facet_svc mds$n).oi_scrub |
237                         awk '/^param/ { print $2 }')
238                 if [ "$actual" != "$expected" ]; then
239                         error "($error_id) Expected '$expected' on mds$n, but" \
240                                "got '$actual'"
241                 fi
242         done
243 }
244
245 scrub_check_repaired() {
246         local error_id=$1
247         local expected=$2
248         local dryrun=$3
249         local actual
250         local n
251
252         for n in $(seq $MDSCOUNT); do
253                 if [ $dryrun -eq 1 ]; then
254                         actual=$(do_facet mds$n $LCTL get_param -n \
255                                 osd-*.$(facet_svc mds$n).oi_scrub |
256                                 awk '/^inconsistent:/ { print $2 }')
257                 else
258                         actual=$(do_facet mds$n $LCTL get_param -n \
259                                 osd-*.$(facet_svc mds$n).oi_scrub |
260                                 awk '/^updated:/ { print $2 }')
261                 fi
262
263                 if [ $expected -eq 0 -a $actual -ne 0 ]; then
264                         error "($error_id) Expected no repaired on mds$n, but" \
265                                "got '$actual'"
266                 fi
267
268                 if [ $expected -ne 0 -a $actual -lt $expected ]; then
269                         error "($error_id) Expected '$expected' on mds$n, but" \
270                                "got '$actual'"
271                 fi
272         done
273 }
274
275 scrub_check_data() {
276         local error_id=$1
277         local n
278
279         for n in $(seq $MDSCOUNT); do
280                 diff -q $LUSTRE/tests/test-framework.sh \
281                         $DIR/$tdir/mds$n/test-framework.sh ||
282                         error "($error_id) File data check failed"
283         done
284 }
285
286 scrub_check_data2() {
287         local filename=$1
288         local error_id=$2
289         local n
290
291         for n in $(seq $MDSCOUNT); do
292                 diff -q $LUSTRE/tests/$filename \
293                         $DIR/$tdir/mds$n/$filename ||
294                         error "($error_id) File data check failed"
295         done
296 }
297
298 scrub_remove_ois() {
299         [ "$mds1_FSTYPE" != "ldiskfs" ] && return
300
301         local error_id=$1
302         local index=$2
303         local n
304
305         for n in $(seq $MDSCOUNT); do
306                 mds_remove_ois mds$n $index ||
307                         error "($error_id) Failed to remove OI .$index on mds$n"
308         done
309 }
310
311 scrub_enable_auto() {
312         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \
313                 osd-*.*.auto_scrub=1
314 }
315
316 full_scrub_ratio() {
317         [ "$mds1_FSTYPE" != "ldiskfs" ] && return
318
319         local ratio=$1
320
321         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \
322                 osd-*.*.full_scrub_ratio=$ratio
323 }
324
325 full_scrub_threshold_rate() {
326         [ "$mds1_FSTYPE" != "ldiskfs" ] && return
327
328         local rate=$1
329
330         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \
331                 osd-*.*.full_scrub_threshold_rate=$rate
332 }
333
334 scrub_enable_index_backup() {
335         do_nodes $(comma_list $(all_server_nodes)) $LCTL set_param -n \
336                 osd-*.*.index_backup=1
337 }
338
339 scrub_disable_index_backup() {
340         do_nodes $(comma_list $(all_server_nodes)) $LCTL set_param -n \
341                 osd-*.*.index_backup=0
342 }
343
344 test_0() {
345         scrub_prep 0
346         echo "starting MDTs without disabling OI scrub"
347         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
348         scrub_check_status 2 init
349         scrub_check_flags 3 ""
350         mount_client $MOUNT || error "(4) Fail to start client!"
351         scrub_check_data 5
352 }
353 run_test 0 "Do not auto trigger OI scrub for non-backup/restore case"
354
355 test_1a() {
356         [ -n "$FILESET" ] && skip "Not functional for FILESET set"
357
358         scrub_prep 0
359         echo "start $SINGLEMDS without disabling OI scrub: $MOUNT_OPTS_SCRUB"
360         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
361
362         local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
363         [ -z "$FLAGS" ] || error "(3) Expect empty flags, but got '$FLAGS'"
364
365         mount_client $MOUNT || error "(4) Fail to start client!"
366         #define OBD_FAIL_OSD_FID_MAPPING                        0x193
367         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x193
368         # update .lustre OI mapping
369         touch $MOUNT/.lustre
370         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
371         umount_client $MOUNT || error "(5) Fail to stop client!"
372
373         echo "stop $SINGLEMDS"
374         stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!"
375
376         echo "start $SINGLEMDS with disabling OI scrub: $MOUNT_OPTS_NOSCRUB"
377         start $SINGLEMDS $(mdsdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
378                 error "(7) Fail to start MDS!"
379
380         local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
381         [ "$FLAGS" == "inconsistent" ] ||
382                 error "(9) Expect 'inconsistent', but got '$FLAGS'"
383 }
384 run_test 1a "Auto trigger initial OI scrub when server mounts"
385
386 test_1b() {
387         scrub_prep 0 2
388         echo "start MDTs without disabling OI scrub"
389         scrub_start_mds 2 "$MOUNT_OPTS_SCRUB"
390         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
391                 scrub_check_status 3 completed
392         mount_client $MOUNT || error "(4) Fail to start client!"
393         scrub_check_data2 runas 5
394         scrub_check_status 6 completed
395 }
396 run_test 1b "Trigger OI scrub when MDT mounts for OI files remove/recreate case"
397
398 test_1c() {
399         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
400                 skip "ldiskfs special test"
401
402         local index
403
404         # OI files to be removed:
405         # idx 0: oi.16.0
406         # idx 2: oi.16.{2,4,8,16,32}
407         # idx 3: oi.16.{3,9,27}
408         for index in 0 2 3; do
409                 scrub_prep 0
410                 scrub_remove_ois 1 $index
411                 echo "start MDTs with OI scrub disabled"
412                 scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
413                 scrub_check_flags 3 recreated
414                 scrub_start 4
415                 scrub_check_status 5 completed
416                 scrub_check_flags 6 ""
417         done
418 }
419 run_test 1c "Auto detect kinds of OI file(s) removed/recreated cases"
420
421 test_2() {
422         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
423                 skip "ldiskfs special test"
424
425         scrub_prep 0 1
426         echo "starting MDTs without disabling OI scrub"
427         scrub_start_mds 2 "$MOUNT_OPTS_SCRUB"
428         scrub_check_status 3 completed
429         mount_client $MOUNT || error "(4) Fail to start client!"
430         scrub_check_data 5
431 }
432 run_test 2 "Trigger OI scrub when MDT mounts for backup/restore case"
433
434 # test_3 is obsolete, it will be covered by test_5.
435 test_3() {
436         formatall > /dev/null
437         setupall > /dev/null
438
439         scrub_prep 0 1
440         echo "starting MDTs with OI scrub disabled"
441         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
442         scrub_check_status 3 init
443         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
444                 scrub_check_flags 4 recreated,inconsistent
445 }
446 #run_test 3 "Do not trigger OI scrub when MDT mounts if 'noscrub' specified"
447
448 test_4a() {
449         scrub_prep 0 1
450         echo "starting MDTs with OI scrub disabled"
451         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
452         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
453                 scrub_check_flags 4 recreated,inconsistent
454         mount_client $MOUNT || error "(5) Fail to start client!"
455         scrub_enable_auto
456         full_scrub_ratio 0
457         scrub_check_data 6
458         sleep 3
459
460         scrub_check_status 7 completed
461         scrub_check_flags 8 ""
462
463         local -a updated0
464         for n in $(seq $MDSCOUNT); do
465                 updated0[$n]=$(scrub_status $n |
466                                awk '/^prior_updated/ { print $2 }')
467         done
468
469         scrub_check_data2 sanity-scrub.sh 9
470         sleep 3
471
472         local -a updated1
473         for n in $(seq $MDSCOUNT); do
474                 updated1[$n]=$(scrub_status $n |
475                                awk '/^prior_updated/ { print $2 }')
476                 [ ${updated0[$n]} -eq ${updated1[$n]} ] ||
477                         error "(10) NOT auto trigger full scrub as expected"
478         done
479 }
480 run_test 4a "Auto trigger OI scrub if bad OI mapping was found (1)"
481
482 test_4b() {
483         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
484                 skip "ldiskfs special test"
485
486         scrub_prep 5 1
487         echo "starting MDTs with OI scrub disabled"
488         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
489         scrub_check_flags 4 recreated,inconsistent
490         mount_client $MOUNT || error "(5) Fail to start client!"
491         scrub_enable_auto
492         full_scrub_ratio 10
493         full_scrub_threshold_rate 10000
494         scrub_check_data 6
495         sleep 3
496
497         scrub_check_status 7 completed
498         scrub_check_flags 8 ""
499
500         local -a updated0
501         for n in $(seq $MDSCOUNT); do
502                 updated0[$n]=$(scrub_status $n |
503                                awk '/^prior_updated/ { print $2 }')
504
505                 echo "OI scrub on MDS$n status for the 1st time:"
506                 do_facet mds$n $LCTL get_param -n \
507                         osd-*.$(facet_svc mds$n).oi_scrub
508         done
509
510         scrub_check_data2 sanity-scrub.sh 9
511         sleep 3
512
513         scrub_check_status 10 completed
514         scrub_check_flags 11 ""
515
516         local -a updated1
517         for n in $(seq $MDSCOUNT); do
518                 updated1[$n]=$(scrub_status $n |
519                                awk '/^prior_updated/ { print $2 }')
520
521                 echo "OI scrub on MDS$n status for the 2nd time:"
522                 do_facet mds$n $LCTL get_param -n \
523                         osd-*.$(facet_svc mds$n).oi_scrub
524
525                 [ ${updated0[$n]} -lt ${updated1[$n]} ] ||
526                         error "(12) Auto trigger full scrub unexpectedly"
527         done
528
529         for n in $(seq $MDSCOUNT); do
530                 ls -l $DIR/$tdir/mds$n/*.sh > /dev/null ||
531                         error "(13) fail to ls"
532         done
533         sleep 3
534
535         scrub_check_status 14 completed
536         scrub_check_flags 15 ""
537
538         for n in $(seq $MDSCOUNT); do
539                 updated0[$n]=$(scrub_status $n |
540                                awk '/^prior_updated/ { print $2 }')
541
542                 echo "OI scrub on MDS$n status for the 3rd time:"
543                 do_facet mds$n $LCTL get_param -n \
544                         osd-*.$(facet_svc mds$n).oi_scrub
545
546                 [ ${updated0[$n]} -gt ${updated1[$n]} ] ||
547                         error "(16) Auto trigger full scrub unexpectedly"
548         done
549
550         for n in $(seq $MDSCOUNT); do
551                 ls -l $DIR/$tdir/mds$n/d_${tfile}/ || error "(17) fail to ls"
552         done
553         sleep 3
554
555         for n in $(seq $MDSCOUNT); do
556                 updated1[$n]=$(scrub_status $n |
557                                awk '/^prior_updated/ { print $2 }')
558                 [ ${updated0[$n]} -eq ${updated1[$n]} ] || {
559                         echo "OI scrub on MDS$n status for the 4th time:"
560                         do_facet mds$n $LCTL get_param -n \
561                                 osd-*.$(facet_svc mds$n).oi_scrub
562
563                         error "(18) NOT auto trigger full scrub as expected"
564                 }
565         done
566 }
567 run_test 4b "Auto trigger OI scrub if bad OI mapping was found (2)"
568
569 test_4c() {
570         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
571                 skip "ldiskfs special test"
572
573         scrub_prep 500 1
574         echo "starting MDTs with OI scrub disabled"
575         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
576         scrub_check_flags 4 recreated,inconsistent
577         mount_client $MOUNT || error "(5) Fail to start client!"
578         scrub_enable_auto
579         full_scrub_ratio 2
580         full_scrub_threshold_rate 20
581         scrub_check_data 6
582         sleep 3
583
584         scrub_check_status 7 completed
585         scrub_check_flags 8 ""
586
587         local -a updated0
588         for n in $(seq $MDSCOUNT); do
589                 updated0[$n]=$(scrub_status $n |
590                                awk '/^prior_updated/ { print $2 }')
591
592                 echo "OI scrub on MDS$n status for the 1st time:"
593                 do_facet mds$n $LCTL get_param -n \
594                         osd-*.$(facet_svc mds$n).oi_scrub
595         done
596
597         scrub_check_data2 sanity-scrub.sh 9
598         sleep 3
599
600         scrub_check_status 10 completed
601         scrub_check_flags 11 ""
602
603         local -a updated1
604         for n in $(seq $MDSCOUNT); do
605                 updated1[$n]=$(scrub_status $n |
606                                awk '/^prior_updated/ { print $2 }')
607
608                 echo "OI scrub on MDS$n status for the 2nd time:"
609                 do_facet mds$n $LCTL get_param -n \
610                         osd-*.$(facet_svc mds$n).oi_scrub
611
612                 [ ${updated0[$n]} -lt ${updated1[$n]} ] ||
613                         error "(12) Auto trigger full scrub unexpectedly"
614         done
615
616         for n in $(seq $MDSCOUNT); do
617                 ls -l $DIR/$tdir/mds$n/*.sh > /dev/null ||
618                         error "(13) fail to ls"
619         done
620         sleep 3
621
622         scrub_check_status 14 completed
623         scrub_check_flags 15 ""
624
625         for n in $(seq $MDSCOUNT); do
626                 updated0[$n]=$(scrub_status $n |
627                                awk '/^prior_updated/ { print $2 }')
628
629                 echo "OI scrub on MDS$n status for the 3rd time:"
630                 do_facet mds$n $LCTL get_param -n \
631                         osd-*.$(facet_svc mds$n).oi_scrub
632
633                 [ ${updated0[$n]} -gt ${updated1[$n]} ] ||
634                         error "(16) Auto trigger full scrub unexpectedly"
635         done
636
637         for n in $(seq $MDSCOUNT); do
638                 ls -l $DIR/$tdir/mds$n/${tfile}1 || error "(17) fail to ls"
639         done
640         sleep 3
641
642         for n in $(seq $MDSCOUNT); do
643                 updated1[$n]=$(scrub_status $n |
644                                awk '/^prior_updated/ { print $2 }')
645                 [ ${updated0[$n]} -eq ${updated1[$n]} ] || {
646                         echo "OI scrub on MDS$n status for the 4th time:"
647                         do_facet mds$n $LCTL get_param -n \
648                                 osd-*.$(facet_svc mds$n).oi_scrub
649
650                         error "(18) NOT auto trigger full scrub as expected"
651                 }
652         done
653 }
654 run_test 4c "Auto trigger OI scrub if bad OI mapping was found (3)"
655
656 test_4d() {
657         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
658
659         check_mount_and_prep
660
661         #define OBD_FAIL_OSD_DUPLICATE_MAP      0x19b
662         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x19b
663         for i in {1..100}; do
664                 echo $i > $DIR/$tdir/f_$i || error "write f_$i failed"
665         done
666         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0
667
668         for i in {101..200}; do
669                 echo $i > $DIR/$tdir/f_$i || error "write f_$i failed"
670         done
671
672         for i in {1..200}; do
673                 echo $i | cmp $DIR/$tdir/f_$i - || error "f_$i data corrupt"
674         done
675 }
676 run_test 4d "FID in LMA mismatch with object FID won't block create"
677
678 test_5() {
679         formatall > /dev/null
680         setupall > /dev/null
681
682         scrub_prep 100 1
683         echo "starting MDTs with OI scrub disabled (1)"
684         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
685         scrub_check_status 3 init
686         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
687                 scrub_check_flags 4 recreated,inconsistent
688         mount_client $MOUNT || error "(5) Fail to start client!"
689         scrub_enable_auto
690         full_scrub_ratio 0
691
692         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
693         do_nodes $(comma_list $(mdts_nodes)) \
694                 $LCTL set_param fail_val=3 fail_loc=0x190
695
696         scrub_check_data 6
697         umount_client $MOUNT || error "(7) Fail to stop client!"
698         scrub_check_status 8 scanning
699
700         #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
701         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191
702
703         sleep 4
704         scrub_stop_mds 9
705
706         do_nodes $(comma_list $(mdts_nodes)) \
707                 $LCTL set_param fail_loc=0 fail_val=0
708
709         echo "starting MDTs with OI scrub disabled (2)"
710         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
711         scrub_check_status 11 crashed
712         scrub_stop_mds 12
713
714         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
715         do_nodes $(comma_list $(mdts_nodes)) \
716                 $LCTL set_param fail_val=3 fail_loc=0x190
717
718         echo "starting MDTs without disabling OI scrub"
719         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
720         scrub_check_status 14 scanning
721
722         #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
723         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192
724
725         scrub_check_status 15 failed
726         mount_client $MOUNT || error "(16) Fail to start client!"
727
728         full_scrub_ratio 0
729         do_nodes $(comma_list $(mdts_nodes)) \
730                 $LCTL set_param fail_loc=0 fail_val=0
731
732         local n
733         declare -a pids
734
735         for n in $(seq $MDSCOUNT); do
736                 stat $DIR/$tdir/mds$n/sanity-scrub.sh &
737                 pids[$n]=$!
738         done
739
740         for n in $(seq $MDSCOUNT); do
741                 wait ${pids[$n]} ||
742                         error "(18) Fail to stat mds$n/sanity-scrub.sh"
743         done
744
745         scrub_check_status 19 completed
746         scrub_check_flags 20 ""
747 }
748 run_test 5 "OI scrub state machine"
749
750 test_6() {
751         scrub_prep 100 1
752         echo "starting MDTs with OI scrub disabled"
753         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
754         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
755                 scrub_check_flags 4 recreated,inconsistent
756         mount_client $MOUNT || error "(5) Fail to start client!"
757         scrub_enable_auto
758         full_scrub_ratio 0
759
760         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
761         do_nodes $(comma_list $(mdts_nodes)) \
762                 $LCTL set_param fail_val=2 fail_loc=0x190
763
764         scrub_check_data 6
765
766         # Sleep 5 sec to guarantee at least one object processed by OI scrub
767         sleep 5
768         # Fail the OI scrub to guarantee there is at least one checkpoint
769         #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
770         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192
771
772         scrub_check_status 7 failed
773
774         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
775         do_nodes $(comma_list $(mdts_nodes)) \
776                 $LCTL set_param fail_val=3 fail_loc=0x190
777
778         local n
779         for n in $(seq $MDSCOUNT); do
780                 # stat will re-trigger OI scrub
781                 stat $DIR/$tdir/mds$n/sanity-scrub.sh ||
782                         error "(8) Failed to stat mds$n/sanity-scrub.sh"
783         done
784
785         umount_client $MOUNT || error "(9) Fail to stop client!"
786         scrub_check_status 10 scanning
787
788         #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
789         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191
790
791         sleep 4
792         local -a position0
793         for n in $(seq $MDSCOUNT); do
794                 position0[$n]=$(scrub_status $n |
795                         awk '/^last_checkpoint_position/ {print $2}')
796                 position0[$n]=$((${position0[$n]} + 1))
797         done
798
799         scrub_stop_mds 11
800
801         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
802         do_nodes $(comma_list $(mdts_nodes)) \
803                 $LCTL set_param fail_val=3 fail_loc=0x190
804
805         echo "starting MDTs without disabling OI scrub"
806         scrub_start_mds 12 "$MOUNT_OPTS_SCRUB"
807
808         scrub_check_status 13 scanning
809
810         local -a position1
811         for n in $(seq $MDSCOUNT); do
812                 position1[$n]=$(scrub_status $n |
813                         awk '/^latest_start_position/ {print $2}')
814                 if [ ${position0[$n]} -ne ${position1[$n]} ]; then
815                         error "(14) Expected position ${position0[$n]}, but" \
816                                 "got ${position1[$n]}"
817                 fi
818         done
819
820         do_nodes $(comma_list $(mdts_nodes)) \
821                 $LCTL set_param fail_loc=0 fail_val=0
822
823         scrub_check_status 15 completed
824         scrub_check_flags 16 ""
825 }
826 run_test 6 "OI scrub resumes from last checkpoint"
827
828 test_7() {
829         scrub_prep 500 1
830         echo "starting MDTs with OI scrub disabled"
831         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
832         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
833                 scrub_check_flags 4 recreated,inconsistent
834         mount_client $MOUNT || error "(5) Fail to start client!"
835         scrub_enable_auto
836         full_scrub_ratio 0
837
838         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
839         do_nodes $(comma_list $(mdts_nodes)) \
840                 $LCTL set_param fail_val=3 fail_loc=0x190
841
842         scrub_check_data 6
843
844         local n
845         for n in $(seq $MDSCOUNT); do
846                 stat $DIR/$tdir/mds$n/${tfile}300 ||
847                         error "(7) Failed to stat mds$n/${tfile}300!"
848         done
849
850         scrub_check_status 8 scanning
851         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
852                 scrub_check_flags 9 inconsistent,auto
853         else
854                 scrub_check_flags 9 recreated,inconsistent,auto
855         fi
856
857         do_nodes $(comma_list $(mdts_nodes)) \
858                 $LCTL set_param fail_loc=0 fail_val=0
859
860         scrub_check_status 10 completed
861         scrub_check_flags ""
862 }
863 run_test 7 "System is available during OI scrub scanning"
864
865 test_8() {
866         scrub_prep 128 1
867         echo "starting MDTs with OI scrub disabled"
868         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
869         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
870                 scrub_check_flags 4 recreated,inconsistent
871
872         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
873         do_nodes $(comma_list $(mdts_nodes)) \
874                 $LCTL set_param fail_val=1 fail_loc=0x190
875
876         scrub_start 5
877         scrub_check_status 6 scanning
878         scrub_stop 7
879         scrub_check_status 8 stopped
880         scrub_start 9
881         scrub_check_status 10 scanning
882
883         do_nodes $(comma_list $(mdts_nodes)) \
884                 $LCTL set_param fail_loc=0 fail_val=0
885
886         scrub_check_status 11 completed
887         scrub_check_flags 12 ""
888 }
889 run_test 8 "Control OI scrub manually"
890
891 test_9() {
892         # Skip scrub speed test for ZFS because of performance unstable
893         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
894                 skip "test scrub speed only on ldiskfs"
895
896         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
897                 skip "Testing on UP system, the speed may be inaccurate."
898         fi
899
900         scrub_prep 6000 1
901
902         echo "starting MDTs with OI scrub disabled"
903         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
904         scrub_check_flags 4 recreated,inconsistent
905
906         local BASE_SPEED1=100
907         local RUN_TIME1=10
908         # OI scrub should run with full speed under inconsistent case
909         scrub_start 5 -s $BASE_SPEED1
910
911         sleep $RUN_TIME1
912         scrub_check_status 6 completed
913         scrub_check_flags 7 ""
914
915         # OI scrub should run with limited speed under non-inconsistent case
916         scrub_start 8 -s $BASE_SPEED1 -r
917
918         sleep $RUN_TIME1
919         scrub_check_status 9 scanning
920
921         # Do NOT ignore that there are 1024 pre-fetched items. And there
922         # may be time error, normally it should be less than 2 seconds.
923         # We allow another 20% schedule error.
924         local PRE_FETCHED=1024
925         local TIME_DIFF=2
926         # MAX_MARGIN = 1.2 = 12 / 10
927         local MAX_SPEED=$(((PRE_FETCHED + BASE_SPEED1 * \
928                 (RUN_TIME1 + TIME_DIFF)) / RUN_TIME1 * 12 / 10))
929         local n
930         for n in $(seq $MDSCOUNT); do
931                 local SPEED=$(scrub_status $n | \
932                         awk '/^average_speed/ { print $2 }')
933                 [ $SPEED -lt $MAX_SPEED ] ||
934                         error "(10) Got speed $SPEED, expected less than" \
935                                 "$MAX_SPEED"
936         done
937
938         # adjust speed limit
939         local BASE_SPEED2=300
940         local RUN_TIME2=10
941         for n in $(seq $MDSCOUNT); do
942                 do_facet mds$n $LCTL set_param -n \
943                         mdd.$(facet_svc mds$n).lfsck_speed_limit $BASE_SPEED2
944         done
945         sleep $RUN_TIME2
946
947         # 30% margin
948         local MARGIN=3
949         local MIN_SPEED=$(((PRE_FETCHED + \
950                             BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
951                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
952                            (RUN_TIME1 + RUN_TIME2) * (10 - MARGIN) / 10))
953         # MAX_MARGIN = 1.2 = 12 / 10
954         MAX_SPEED=$(((PRE_FETCHED + \
955                       BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
956                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
957                      (RUN_TIME1 + RUN_TIME2) * (10 + MARGIN) / 10))
958         for n in $(seq $MDSCOUNT); do
959                 SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }')
960                 [ $SPEED -gt $MIN_SPEED ] ||
961                         error "(11) Got speed $SPEED, expected more than" \
962                                 "$MIN_SPEED"
963                 [ $SPEED -lt $MAX_SPEED ] ||
964                         error "(12) Got speed $SPEED, expected less than" \
965                                 "$MAX_SPEED"
966
967                 do_facet mds$n $LCTL set_param -n \
968                                 mdd.$(facet_svc mds$n).lfsck_speed_limit 0
969         done
970
971         scrub_check_status 13 completed
972 }
973 run_test 9 "OI scrub speed control"
974
975 test_10a() {
976         scrub_prep 0 1
977         echo "starting mds$n with OI scrub disabled (1)"
978         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
979         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
980                 scrub_check_flags 4 recreated,inconsistent
981         mount_client $MOUNT || error "(5) Fail to start client!"
982         scrub_enable_auto
983         full_scrub_ratio 0
984
985         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
986         do_nodes $(comma_list $(mdts_nodes)) \
987                 $LCTL set_param fail_val=1 fail_loc=0x190
988
989         scrub_check_data 6
990         scrub_check_status 7 scanning
991         umount_client $MOUNT || error "(8) Fail to stop client!"
992         scrub_stop_mds 9
993         echo "starting MDTs with OI scrub disabled (2)"
994         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
995         scrub_check_status 11 paused
996         scrub_stop_mds 12
997         echo "starting MDTs without disabling OI scrub"
998         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
999         scrub_check_status 14 scanning
1000
1001         do_nodes $(comma_list $(mdts_nodes)) \
1002                 $LCTL set_param fail_loc=0 fail_val=0
1003
1004         scrub_check_status 15 completed
1005         scrub_check_flags 16 ""
1006 }
1007 run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)"
1008
1009 # test_10b is obsolete, it will be coverded by related sanity-lfsck tests.
1010 test_10b() {
1011         scrub_prep 0 1
1012         echo "starting MDTs with OI scrub disabled"
1013         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1014         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
1015                 scrub_check_flags 4 recreated,inconsistent
1016
1017         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
1018         do_nodes $(comma_list $(mdts_nodes)) \
1019                 $LCTL set_param fail_val=3 fail_loc=0x190
1020
1021         scrub_start 5
1022         scrub_check_status 6 scanning
1023         scrub_stop_mds 7
1024         echo "starting MDTs with OI scrub disabled"
1025         scrub_start_mds 8 "$MOUNT_OPTS_NOSCRUB"
1026         scrub_check_status 9 paused
1027         scrub_stop_mds 10
1028         echo "starting MDTs without disabling OI scrub"
1029         scrub_start_mds 11 "$MOUNT_OPTS_SCRUB"
1030         scrub_check_status 12 scanning
1031
1032         do_nodes $(comma_list $(mdts_nodes)) \
1033                 $LCTL set_param fail_loc=0 fail_val=0
1034
1035         scrub_check_status 13 completed
1036         scrub_check_flags 14 ""
1037 }
1038 #run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)"
1039
1040 test_11() {
1041         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
1042                 skip "ldiskfs special test"
1043
1044         local CREATED=100
1045         local n
1046
1047         check_mount_and_prep
1048
1049         for n in $(seq $MDSCOUNT); do
1050                 test_mkdir -i $((n - 1)) -c1 $DIR/$tdir/mds$n ||
1051                         error "(1) Fail to mkdir $DIR/$tdir/mds$n"
1052
1053                 createmany -o $DIR/$tdir/mds$n/f $CREATED ||
1054                         error "(2) Fail to create under $tdir/mds$n"
1055         done
1056
1057         # reset OI scrub start point by force
1058         scrub_start 3 -r
1059         scrub_check_status 4 completed
1060
1061         declare -a checked0
1062         declare -a checked1
1063
1064         # OI scrub should skip the new created objects for the first accessing
1065         # notice we're creating a new llog for every OST on every startup
1066         # new features can make this even less stable, so we only check that
1067         # the number of skipped files is more than the number or known created
1068         local MINIMUM=$((CREATED + 1)) # files + directory
1069         for n in $(seq $MDSCOUNT); do
1070                 local SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
1071                 [ $SKIPPED -lt $MINIMUM ] &&
1072                         error "(5) Expect at least $MINIMUM objects" \
1073                                 "skipped on mds$n, but got $SKIPPED"
1074
1075                 checked0[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }')
1076         done
1077
1078         # reset OI scrub start point by force
1079         scrub_start 6 -r
1080         scrub_check_status 7 completed
1081
1082         # OI scrub should skip the new created object only once
1083         for n in $(seq $MDSCOUNT); do
1084                 SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
1085                 checked1[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }')
1086
1087                 [ ${checked0[$n]} -ne ${checked1[$n]} -o $SKIPPED -eq 0 ] ||
1088                         error "(8) Expect 0 objects skipped on mds$n, but" \
1089                                 "got $SKIPPED"
1090         done
1091 }
1092 run_test 11 "OI scrub skips the new created objects only once"
1093
1094 test_12() {
1095         check_mount_and_prep
1096         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1097
1098         #define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY               0x195
1099         do_facet ost1 $LCTL set_param fail_loc=0x195
1100         local count=$(precreated_ost_obj_count 0 0)
1101
1102         createmany -o $DIR/$tdir/f $((count + 32))
1103         umount_client $MOUNT || error "(1) Fail to stop client!"
1104
1105         stop ost1 || error "(2) Fail to stop ost1"
1106
1107         #define OBD_FAIL_OST_NODESTROY           0x233
1108         do_facet ost1 $LCTL set_param fail_loc=0x233
1109
1110         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB ||
1111                 error "(3) Fail to start ost1"
1112
1113         mount_client $MOUNT || error "(4) Fail to start client!"
1114
1115         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail"
1116
1117         $START_SCRUB_ON_OST -r || error "(6) Fail to start OI scrub on OST!"
1118
1119         do_facet ost1 $LCTL set_param fail_loc=0
1120         wait_update_facet ost1 "$LCTL get_param -n \
1121                 osd-*.$(facet_svc ost1).oi_scrub |
1122                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1123                 error "(7) Expected '$expected' on ost1"
1124
1125         ls -ail $DIR/$tdir > /dev/null || {
1126                 $SHOW_SCRUB_ON_OST
1127                 error "(8) ls should succeed"
1128         }
1129 }
1130 run_test 12 "OI scrub can rebuild invalid /O entries"
1131
1132 test_13() {
1133         check_mount_and_prep
1134         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1135
1136         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
1137         do_facet ost1 $LCTL set_param fail_loc=0x196
1138         local count=$(precreated_ost_obj_count 0 0)
1139
1140         createmany -o $DIR/$tdir/f $((count + 32))
1141         do_facet ost1 $LCTL set_param fail_loc=0
1142
1143         umount_client $MOUNT || error "(1) Fail to stop client!"
1144
1145         stop ost1 || error "(2) Fail to stop ost1"
1146
1147         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB ||
1148                 error "(3) Fail to start ost1"
1149
1150         mount_client $MOUNT || error "(4) Fail to start client!"
1151
1152         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail"
1153
1154         $START_SCRUB_ON_OST -r || error "(6) Fail to start OI scrub on OST!"
1155
1156         wait_update_facet ost1 "$LCTL get_param -n \
1157                 osd-*.$(facet_svc ost1).oi_scrub |
1158                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1159                 error "(7) Expected '$expected' on ost1"
1160
1161         ls -ail $DIR/$tdir > /dev/null || error "(8) ls should succeed"
1162 }
1163 run_test 13 "OI scrub can rebuild missed /O entries"
1164
1165 test_14() {
1166         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
1167                 skip "ldiskfs special test"
1168
1169         check_mount_and_prep
1170         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1171
1172         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
1173         do_facet ost1 $LCTL set_param fail_loc=0x196
1174         local count=$(precreated_ost_obj_count 0 0)
1175
1176         createmany -o $DIR/$tdir/f $((count + 1000))
1177         do_facet ost1 $LCTL set_param fail_loc=0
1178
1179         umount_client $MOUNT || error "(1) Fail to stop client!"
1180
1181         stop ost1 || error "(2) Fail to stop ost1"
1182
1183         echo "run e2fsck"
1184         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
1185                 error "(3) Fail to run e2fsck error"
1186
1187         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1188                 error "(4) Fail to start ost1"
1189
1190         mount_client $MOUNT || error "(5) Fail to start client!"
1191
1192         local LF_REPAIRED=$($SHOW_SCRUB_ON_OST |
1193                             awk '/^lf_repa[ir]*ed/ { print $2 }')
1194         [ $LF_REPAIRED -ge 1000 ] ||
1195                 error "(6) Some entry under /lost+found should be repaired"
1196
1197         ls -ail $DIR/$tdir > /dev/null || error "(7) ls should succeed"
1198
1199         stopall
1200
1201         echo "run e2fsck again after LFSCK"
1202         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
1203                 error "(8) Fail to run e2fsck error"
1204 }
1205 run_test 14 "OI scrub can repair OST objects under lost+found"
1206
1207 test_15() {
1208         local repaired
1209
1210         formatall > /dev/null
1211         setupall > /dev/null
1212
1213         scrub_prep 20 1
1214         echo "starting MDTs with OI scrub disabled"
1215         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1216         scrub_check_status 3 init
1217         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
1218                 scrub_check_flags 4 recreated,inconsistent
1219
1220         # run under dryrun mode
1221         scrub_start 5 --dryrun
1222         scrub_check_status 6 completed
1223         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
1224                 scrub_check_flags 7 inconsistent
1225                 repaired=2
1226         else
1227                 scrub_check_flags 7 recreated,inconsistent
1228                 repaired=20
1229         fi
1230         scrub_check_params 8 dryrun
1231         scrub_check_repaired 9 $repaired 1
1232
1233         # run under dryrun mode again
1234         scrub_start 10 --dryrun
1235         scrub_check_status 11 completed
1236         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
1237                 scrub_check_flags 12 inconsistent
1238         else
1239                 scrub_check_flags 12 recreated,inconsistent
1240         fi
1241         scrub_check_params 13 dryrun
1242         scrub_check_repaired 14 $repaired 1
1243
1244         # run under normal mode
1245         scrub_start 15
1246         scrub_check_status 16 completed
1247         scrub_check_flags 17 ""
1248         scrub_check_params 18 ""
1249         scrub_check_repaired 19 $repaired 0
1250
1251         # run under normal mode again
1252         scrub_start 20
1253         scrub_check_status 21 completed
1254         scrub_check_flags 22 ""
1255         scrub_check_params 23 ""
1256         scrub_check_repaired 24 0 0
1257 }
1258 run_test 15 "Dryrun mode OI scrub"
1259
1260 test_16() {
1261         check_mount_and_prep
1262         scrub_enable_index_backup
1263
1264         #define OBD_FAIL_OSD_INDEX_CRASH        0x199
1265         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x199
1266         scrub_prep 0
1267         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0
1268
1269         echo "starting MDTs without disabling OI scrub"
1270         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
1271         mount_client $MOUNT || error "(2) Fail to start client!"
1272         scrub_check_data 3
1273         scrub_disable_index_backup
1274 }
1275 run_test 16 "Initial OI scrub can rebuild crashed index objects"
1276
1277 test_17a() {
1278         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
1279
1280 #define OBD_FAIL_OSD_OI_ENOSPC                          0x19d
1281         do_facet mds1 $LCTL set_param fail_loc=0x8000019d
1282         mkdir $DIR/$tdir && error "mkdir should fail"
1283         stop mds1
1284         local devname=$(mdsdevname 1)
1285
1286         stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
1287         FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
1288                 error "e2fsck returned $?"
1289 }
1290 run_test 17a "ENOSPC on OI insert shouldn't leak inodes"
1291
1292 test_17b() {
1293         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
1294
1295 #define OBD_FAIL_OSD_DOTDOT_ENOSPC                      0x19e
1296         do_facet mds1 $LCTL set_param fail_loc=0x8000019e
1297         mkdir_on_mdt0 $DIR/$tdir && error "mkdir should fail"
1298         stop mds1
1299         local devname=$(mdsdevname 1)
1300
1301         stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
1302         FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
1303                 error "e2fsck returned $?"
1304 }
1305 run_test 17b "ENOSPC on .. insertion shouldn't leak inodes"
1306
1307 test_18() {
1308         local n
1309         local fids=()
1310         local opts=$(csa_add "$MOUNT_OPTS_SCRUB" -o resetoi)
1311
1312         scrub_prep 10
1313         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
1314         mount_client $MOUNT || error "(2) Fail to start client!"
1315         for n in $(seq $MDSCOUNT); do
1316                 fids+=($($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh))
1317         done
1318         cleanup_mount $MOUNT > /dev/null || error "(3) Fail to stop client!"
1319         for n in $(seq $MDSCOUNT); do
1320                 stop mds$n > /dev/null || error "(4) Fail to stop MDS$n!"
1321         done
1322         scrub_start_mds 5 "$opts"
1323         do_facet mds1 dmesg | grep "reset Object Index" ||
1324                 error "(6) reset log not found"
1325         mount_client $MOUNT || error "(7) Fail to start client!"
1326         scrub_check_data 7
1327
1328         local fid
1329         local path
1330         for n in $(seq $MDSCOUNT); do
1331                 path=$($LFS fid2path $DIR ${fids[$((n - 1))]})
1332                 [ "$path" == "$DIR/$tdir/mds$n/test-framework.sh" ] ||
1333                         error "path mismatch $path != $DIR/$tdir/mds$n/test-framework.sh"
1334                 fid=$($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh)
1335                 [ "${fids[$((n - 1))]}" == "$fid" ] ||
1336                         error "$DIR/$tdir/mds$n/test-framework.sh FID mismatch ${fids[$((n - 1))]} != $fid"
1337         done
1338 }
1339 run_test 18 "test mount -o resetoi to recreate OI files"
1340
1341 test_19() {
1342         local rcmd="do_facet ost${ost}"
1343
1344         check_mount_and_prep
1345         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1346         createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 32 files."
1347
1348         echo "stopall"
1349         stopall > /dev/null
1350
1351         # create mulitple link file
1352         mount_fstype ost1 || error "(1) Fail to mount ost1"
1353         mntpt=$(facet_mntpt ost1)
1354
1355         local path=$mntpt/O/0/d2
1356         local file=$(${rcmd} ls $path | awk '{print $0; exit}')
1357
1358         # create link to the first file
1359         echo "link $path/1 to $path/$file"
1360         ${rcmd} ln $path/$file $path/1
1361         unmount_fstype ost1 || error "(2) Fail to umount ost1"
1362
1363         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1364                 error "(2) Fail to start ost1"
1365
1366         $START_SCRUB_ON_OST -r || error "(3) Fail to start OI scrub on OST!"
1367
1368         wait_update_facet ost1 "$LCTL get_param -n \
1369                 osd-*.$(facet_svc ost1).oi_scrub |
1370                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1371                 error "(4) Expected '$expected' on ost1"
1372
1373         stop ost1
1374         mount_fstype ost1 || error "(5) Fail to mount ost1"
1375         links=$(do_facet ost1 "stat $path/$file" | awk '/Links:/ { print $6 }')
1376         unmount_fstype ost1 || error "(6) Fail to umount ost1"
1377
1378         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1379                 error "(7) Fail to start ost1"
1380
1381         (( links == 1)) || error "(8) object links $links != 1 after scrub"
1382 }
1383 run_test 19 "LFSCK can fix multiple linked files on OST"
1384
1385 # restore MDS/OST size
1386 MDSSIZE=${SAVED_MDSSIZE}
1387 OSTSIZE=${SAVED_OSTSIZE}
1388 OSTCOUNT=${SAVED_OSTCOUNT}
1389
1390 # cleanup the system at last
1391 REFORMAT="yes" cleanup_and_setup_lustre
1392
1393 complete $SECONDS
1394 check_and_cleanup_lustre
1395 exit_status