Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[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 -lt 400000 || "$mds1_FSTYPE" == ldiskfs ]] && MDSSIZE=400000
42 [[ $OSTSIZE -lt 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_4e() {
679         [[ "$mds1_FSTYPE" == "ldiskfs" ]] || skip "ldiskfs only test"
680
681         check_mount_and_prep
682         $LFS setstripe -c 1 -i 0 $DIR/$tdir
683
684         local count=$(precreated_ost_obj_count 0 0)
685
686         count=$((count + 32))
687
688         #define OBD_FAIL_OSD_FID_REUSE 0x1a0
689         do_facet ost1 $LCTL set_param fail_loc=0x1a0
690         for ((i=0; i<count; i++)); do
691                 echo $i > $DIR/$tdir/f_$i || error "write f_$i failed"
692         done
693         do_facet ost1 $LCTL set_param fail_loc=0
694
695         $START_SCRUB_ON_OST -r || error "start OI scrub on OST0 failed"
696         wait_update_facet ost1 "$LCTL get_param -n \
697                 osd-*.$(facet_svc ost1).oi_scrub |
698                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
699                 error "Expected '$expected' on ost1"
700
701         for ((i=0; i<count; i++)); do
702                 echo $i | cmp -l $DIR/$tdir/f_$i - || error "f_$i data corrupt"
703         done
704 }
705 run_test 4e "FID reuse can be fixed"
706
707 test_5() {
708         formatall > /dev/null
709         setupall > /dev/null
710
711         scrub_prep 100 1
712         echo "starting MDTs with OI scrub disabled (1)"
713         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
714         scrub_check_status 3 init
715         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
716                 scrub_check_flags 4 recreated,inconsistent
717         mount_client $MOUNT || error "(5) Fail to start client!"
718         scrub_enable_auto
719         full_scrub_ratio 0
720
721         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
722         do_nodes $(comma_list $(mdts_nodes)) \
723                 $LCTL set_param fail_val=3 fail_loc=0x190
724
725         scrub_check_data 6
726         umount_client $MOUNT || error "(7) Fail to stop client!"
727         scrub_check_status 8 scanning
728
729         #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
730         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191
731
732         sleep 4
733         scrub_stop_mds 9
734
735         do_nodes $(comma_list $(mdts_nodes)) \
736                 $LCTL set_param fail_loc=0 fail_val=0
737
738         echo "starting MDTs with OI scrub disabled (2)"
739         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
740         scrub_check_status 11 crashed
741         scrub_stop_mds 12
742
743         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
744         do_nodes $(comma_list $(mdts_nodes)) \
745                 $LCTL set_param fail_val=3 fail_loc=0x190
746
747         echo "starting MDTs without disabling OI scrub"
748         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
749         scrub_check_status 14 scanning
750
751         #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
752         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192
753
754         scrub_check_status 15 failed
755         mount_client $MOUNT || error "(16) Fail to start client!"
756
757         full_scrub_ratio 0
758         do_nodes $(comma_list $(mdts_nodes)) \
759                 $LCTL set_param fail_loc=0 fail_val=0
760
761         local n
762         declare -a pids
763
764         for n in $(seq $MDSCOUNT); do
765                 stat $DIR/$tdir/mds$n/sanity-scrub.sh &
766                 pids[$n]=$!
767         done
768
769         for n in $(seq $MDSCOUNT); do
770                 wait ${pids[$n]} ||
771                         error "(18) Fail to stat mds$n/sanity-scrub.sh"
772         done
773
774         scrub_check_status 19 completed
775         scrub_check_flags 20 ""
776 }
777 run_test 5 "OI scrub state machine"
778
779 test_6() {
780         scrub_prep 100 1
781         echo "starting MDTs with OI scrub disabled"
782         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
783         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
784                 scrub_check_flags 4 recreated,inconsistent
785         mount_client $MOUNT || error "(5) Fail to start client!"
786         scrub_enable_auto
787         full_scrub_ratio 0
788
789         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
790         do_nodes $(comma_list $(mdts_nodes)) \
791                 $LCTL set_param fail_val=2 fail_loc=0x190
792
793         scrub_check_data 6
794
795         # Sleep 5 sec to guarantee at least one object processed by OI scrub
796         sleep 5
797         # Fail the OI scrub to guarantee there is at least one checkpoint
798         #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
799         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192
800
801         scrub_check_status 7 failed
802
803         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
804         do_nodes $(comma_list $(mdts_nodes)) \
805                 $LCTL set_param fail_val=3 fail_loc=0x190
806
807         local n
808         for n in $(seq $MDSCOUNT); do
809                 # stat will re-trigger OI scrub
810                 stat $DIR/$tdir/mds$n/sanity-scrub.sh ||
811                         error "(8) Failed to stat mds$n/sanity-scrub.sh"
812         done
813
814         umount_client $MOUNT || error "(9) Fail to stop client!"
815         scrub_check_status 10 scanning
816
817         #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
818         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191
819
820         sleep 4
821         local -a position0
822         for n in $(seq $MDSCOUNT); do
823                 position0[$n]=$(scrub_status $n |
824                         awk '/^last_checkpoint_position/ {print $2}')
825                 position0[$n]=$((${position0[$n]} + 1))
826         done
827
828         scrub_stop_mds 11
829
830         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
831         do_nodes $(comma_list $(mdts_nodes)) \
832                 $LCTL set_param fail_val=3 fail_loc=0x190
833
834         echo "starting MDTs without disabling OI scrub"
835         scrub_start_mds 12 "$MOUNT_OPTS_SCRUB"
836
837         scrub_check_status 13 scanning
838
839         local -a position1
840         for n in $(seq $MDSCOUNT); do
841                 position1[$n]=$(scrub_status $n |
842                         awk '/^latest_start_position/ {print $2}')
843                 if [ ${position0[$n]} -ne ${position1[$n]} ]; then
844                         error "(14) Expected position ${position0[$n]}, but" \
845                                 "got ${position1[$n]}"
846                 fi
847         done
848
849         do_nodes $(comma_list $(mdts_nodes)) \
850                 $LCTL set_param fail_loc=0 fail_val=0
851
852         scrub_check_status 15 completed
853         scrub_check_flags 16 ""
854 }
855 run_test 6 "OI scrub resumes from last checkpoint"
856
857 test_7() {
858         scrub_prep 500 1
859         echo "starting MDTs with OI scrub disabled"
860         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
861         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
862                 scrub_check_flags 4 recreated,inconsistent
863         mount_client $MOUNT || error "(5) Fail to start client!"
864         scrub_enable_auto
865         full_scrub_ratio 0
866
867         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
868         do_nodes $(comma_list $(mdts_nodes)) \
869                 $LCTL set_param fail_val=3 fail_loc=0x190
870
871         scrub_check_data 6
872
873         local n
874         for n in $(seq $MDSCOUNT); do
875                 stat $DIR/$tdir/mds$n/${tfile}300 ||
876                         error "(7) Failed to stat mds$n/${tfile}300!"
877         done
878
879         scrub_check_status 8 scanning
880         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
881                 scrub_check_flags 9 inconsistent,auto
882         else
883                 scrub_check_flags 9 recreated,inconsistent,auto
884         fi
885
886         do_nodes $(comma_list $(mdts_nodes)) \
887                 $LCTL set_param fail_loc=0 fail_val=0
888
889         scrub_check_status 10 completed
890         scrub_check_flags ""
891 }
892 run_test 7 "System is available during OI scrub scanning"
893
894 test_8() {
895         scrub_prep 128 1
896         echo "starting MDTs with OI scrub disabled"
897         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
898         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
899                 scrub_check_flags 4 recreated,inconsistent
900
901         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
902         do_nodes $(comma_list $(mdts_nodes)) \
903                 $LCTL set_param fail_val=1 fail_loc=0x190
904
905         scrub_start 5
906         scrub_check_status 6 scanning
907         scrub_stop 7
908         scrub_check_status 8 stopped
909         scrub_start 9
910         scrub_check_status 10 scanning
911
912         do_nodes $(comma_list $(mdts_nodes)) \
913                 $LCTL set_param fail_loc=0 fail_val=0
914
915         scrub_check_status 11 completed
916         scrub_check_flags 12 ""
917 }
918 run_test 8 "Control OI scrub manually"
919
920 test_9() {
921         # Skip scrub speed test for ZFS because of performance unstable
922         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
923                 skip "test scrub speed only on ldiskfs"
924
925         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
926                 skip "Testing on UP system, the speed may be inaccurate."
927         fi
928
929         scrub_prep 6000 1
930
931         echo "starting MDTs with OI scrub disabled"
932         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
933         scrub_check_flags 4 recreated,inconsistent
934
935         local BASE_SPEED1=100
936         local RUN_TIME1=10
937         # OI scrub should run with full speed under inconsistent case
938         scrub_start 5 -s $BASE_SPEED1
939
940         sleep $RUN_TIME1
941         scrub_check_status 6 completed
942         scrub_check_flags 7 ""
943
944         # OI scrub should run with limited speed under non-inconsistent case
945         scrub_start 8 -s $BASE_SPEED1 -r
946
947         sleep $RUN_TIME1
948         scrub_check_status 9 scanning
949
950         # Do NOT ignore that there are 1024 pre-fetched items. And there
951         # may be time error, normally it should be less than 2 seconds.
952         # We allow another 20% schedule error.
953         local PRE_FETCHED=1024
954         local TIME_DIFF=2
955         # MAX_MARGIN = 1.2 = 12 / 10
956         local MAX_SPEED=$(((PRE_FETCHED + BASE_SPEED1 *
957                 (RUN_TIME1 + TIME_DIFF)) / RUN_TIME1 * 12 / 10))
958         local n
959         for n in $(seq $MDSCOUNT); do
960                 local SPEED=$(scrub_status $n | \
961                         awk '/^average_speed/ { print $2 }')
962                 [ $SPEED -lt $MAX_SPEED ] ||
963                         error "(10) Got speed $SPEED, expected less than" \
964                                 "$MAX_SPEED"
965         done
966
967         # adjust speed limit
968         local BASE_SPEED2=300
969         local RUN_TIME2=10
970         for n in $(seq $MDSCOUNT); do
971                 do_facet mds$n $LCTL set_param -n \
972                         mdd.$(facet_svc mds$n).lfsck_speed_limit $BASE_SPEED2
973         done
974         sleep $RUN_TIME2
975
976         # 30% margin
977         local MARGIN=3
978         local MIN_SPEED=$(((PRE_FETCHED +
979                             BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) +
980                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) /
981                            (RUN_TIME1 + RUN_TIME2) * (10 - MARGIN) / 10))
982         # MAX_MARGIN = 1.2 = 12 / 10
983         MAX_SPEED=$(((PRE_FETCHED +
984                       BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) +
985                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) /
986                      (RUN_TIME1 + RUN_TIME2) * (10 + MARGIN) / 10))
987         for n in $(seq $MDSCOUNT); do
988                 SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }')
989                 [ $SPEED -gt $MIN_SPEED ] ||
990                         error "(11) Got speed $SPEED, expected more than" \
991                                 "$MIN_SPEED"
992                 [ $SPEED -lt $MAX_SPEED ] ||
993                         error "(12) Got speed $SPEED, expected less than" \
994                                 "$MAX_SPEED"
995
996                 do_facet mds$n $LCTL set_param -n \
997                                 mdd.$(facet_svc mds$n).lfsck_speed_limit 0
998         done
999
1000         scrub_check_status 13 completed
1001 }
1002 run_test 9 "OI scrub speed control"
1003
1004 test_10a() {
1005         scrub_prep 0 1
1006         echo "starting mds$n with OI scrub disabled (1)"
1007         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1008         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
1009                 scrub_check_flags 4 recreated,inconsistent
1010         mount_client $MOUNT || error "(5) Fail to start client!"
1011         scrub_enable_auto
1012         full_scrub_ratio 0
1013
1014         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
1015         do_nodes $(comma_list $(mdts_nodes)) \
1016                 $LCTL set_param fail_val=1 fail_loc=0x190
1017
1018         scrub_check_data 6
1019         scrub_check_status 7 scanning
1020         umount_client $MOUNT || error "(8) Fail to stop client!"
1021         scrub_stop_mds 9
1022         echo "starting MDTs with OI scrub disabled (2)"
1023         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
1024         scrub_check_status 11 paused
1025         scrub_stop_mds 12
1026         echo "starting MDTs without disabling OI scrub"
1027         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
1028         scrub_check_status 14 scanning
1029
1030         do_nodes $(comma_list $(mdts_nodes)) \
1031                 $LCTL set_param fail_loc=0 fail_val=0
1032
1033         scrub_check_status 15 completed
1034         scrub_check_flags 16 ""
1035 }
1036 run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)"
1037
1038 # test_10b is obsolete, it will be coverded by related sanity-lfsck tests.
1039 test_10b() {
1040         scrub_prep 0 1
1041         echo "starting MDTs with OI scrub disabled"
1042         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1043         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
1044                 scrub_check_flags 4 recreated,inconsistent
1045
1046         #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
1047         do_nodes $(comma_list $(mdts_nodes)) \
1048                 $LCTL set_param fail_val=3 fail_loc=0x190
1049
1050         scrub_start 5
1051         scrub_check_status 6 scanning
1052         scrub_stop_mds 7
1053         echo "starting MDTs with OI scrub disabled"
1054         scrub_start_mds 8 "$MOUNT_OPTS_NOSCRUB"
1055         scrub_check_status 9 paused
1056         scrub_stop_mds 10
1057         echo "starting MDTs without disabling OI scrub"
1058         scrub_start_mds 11 "$MOUNT_OPTS_SCRUB"
1059         scrub_check_status 12 scanning
1060
1061         do_nodes $(comma_list $(mdts_nodes)) \
1062                 $LCTL set_param fail_loc=0 fail_val=0
1063
1064         scrub_check_status 13 completed
1065         scrub_check_flags 14 ""
1066 }
1067 #run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)"
1068
1069 test_11() {
1070         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
1071                 skip "ldiskfs special test"
1072
1073         local CREATED=100
1074         local n
1075
1076         check_mount_and_prep
1077
1078         for n in $(seq $MDSCOUNT); do
1079                 test_mkdir -i $((n - 1)) -c1 $DIR/$tdir/mds$n ||
1080                         error "(1) Fail to mkdir $DIR/$tdir/mds$n"
1081
1082                 createmany -o $DIR/$tdir/mds$n/f $CREATED ||
1083                         error "(2) Fail to create under $tdir/mds$n"
1084         done
1085
1086         # reset OI scrub start point by force
1087         scrub_start 3 -r
1088         scrub_check_status 4 completed
1089
1090         declare -a checked0
1091         declare -a checked1
1092
1093         # OI scrub should skip the new created objects for the first accessing
1094         # notice we're creating a new llog for every OST on every startup
1095         # new features can make this even less stable, so we only check that
1096         # the number of skipped files is more than the number or known created
1097         local MINIMUM=$((CREATED + 1)) # files + directory
1098         for n in $(seq $MDSCOUNT); do
1099                 local SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
1100                 [ $SKIPPED -lt $MINIMUM ] &&
1101                         error "(5) Expect at least $MINIMUM objects" \
1102                                 "skipped on mds$n, but got $SKIPPED"
1103
1104                 checked0[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }')
1105         done
1106
1107         # reset OI scrub start point by force
1108         scrub_start 6 -r
1109         scrub_check_status 7 completed
1110
1111         # OI scrub should skip the new created object only once
1112         for n in $(seq $MDSCOUNT); do
1113                 SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
1114                 checked1[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }')
1115
1116                 [ ${checked0[$n]} -ne ${checked1[$n]} -o $SKIPPED -eq 0 ] ||
1117                         error "(8) Expect 0 objects skipped on mds$n, but" \
1118                                 "got $SKIPPED"
1119         done
1120 }
1121 run_test 11 "OI scrub skips the new created objects only once"
1122
1123 test_12() {
1124         check_mount_and_prep
1125         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1126
1127         #define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY               0x195
1128         do_facet ost1 $LCTL set_param fail_loc=0x195
1129         local count=$(precreated_ost_obj_count 0 0)
1130
1131         createmany -o $DIR/$tdir/f $((count + 32))
1132         umount_client $MOUNT || error "(1) Fail to stop client!"
1133
1134         stop ost1 || error "(2) Fail to stop ost1"
1135
1136         #define OBD_FAIL_OST_NODESTROY           0x233
1137         do_facet ost1 $LCTL set_param fail_loc=0x233
1138
1139         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB ||
1140                 error "(3) Fail to start ost1"
1141
1142         mount_client $MOUNT || error "(4) Fail to start client!"
1143
1144         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail"
1145
1146         $START_SCRUB_ON_OST -r || error "(6) Fail to start OI scrub on OST!"
1147
1148         do_facet ost1 $LCTL set_param fail_loc=0
1149         wait_update_facet ost1 "$LCTL get_param -n \
1150                 osd-*.$(facet_svc ost1).oi_scrub |
1151                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1152                 error "(7) Expected '$expected' on ost1"
1153
1154         ls -ail $DIR/$tdir > /dev/null || {
1155                 $SHOW_SCRUB_ON_OST
1156                 error "(8) ls should succeed"
1157         }
1158 }
1159 run_test 12 "OI scrub can rebuild invalid /O entries"
1160
1161 test_13() {
1162         check_mount_and_prep
1163         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1164
1165         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
1166         do_facet ost1 $LCTL set_param fail_loc=0x196
1167         local count=$(precreated_ost_obj_count 0 0)
1168
1169         createmany -o $DIR/$tdir/f $((count + 32))
1170         do_facet ost1 $LCTL set_param fail_loc=0
1171
1172         umount_client $MOUNT || error "(1) Fail to stop client!"
1173
1174         stop ost1 || error "(2) Fail to stop ost1"
1175
1176         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB ||
1177                 error "(3) Fail to start ost1"
1178
1179         mount_client $MOUNT || error "(4) Fail to start client!"
1180
1181         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail"
1182
1183         $START_SCRUB_ON_OST -r || error "(6) Fail to start OI scrub on OST!"
1184
1185         wait_update_facet ost1 "$LCTL get_param -n \
1186                 osd-*.$(facet_svc ost1).oi_scrub |
1187                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1188                 error "(7) Expected '$expected' on ost1"
1189
1190         ls -ail $DIR/$tdir > /dev/null || error "(8) ls should succeed"
1191 }
1192 run_test 13 "OI scrub can rebuild missed /O entries"
1193
1194 test_14() {
1195         [ "$mds1_FSTYPE" != "ldiskfs" ] &&
1196                 skip "ldiskfs special test"
1197
1198         check_mount_and_prep
1199         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1200
1201         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
1202         do_facet ost1 $LCTL set_param fail_loc=0x196
1203         local count=$(precreated_ost_obj_count 0 0)
1204
1205         createmany -o $DIR/$tdir/f $((count + 1000))
1206         do_facet ost1 $LCTL set_param fail_loc=0
1207
1208         umount_client $MOUNT || error "(1) Fail to stop client!"
1209
1210         stop ost1 || error "(2) Fail to stop ost1"
1211
1212         echo "run e2fsck"
1213         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
1214                 error "(3) Fail to run e2fsck error"
1215
1216         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1217                 error "(4) Fail to start ost1"
1218
1219         mount_client $MOUNT || error "(5) Fail to start client!"
1220
1221         local LF_REPAIRED=$($SHOW_SCRUB_ON_OST |
1222                             awk '/^lf_repa[ir]*ed/ { print $2 }')
1223         [ $LF_REPAIRED -ge 1000 ] ||
1224                 error "(6) Some entry under /lost+found should be repaired"
1225
1226         ls -ail $DIR/$tdir > /dev/null || error "(7) ls should succeed"
1227
1228         stopall
1229
1230         echo "run e2fsck again after LFSCK"
1231         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
1232                 error "(8) Fail to run e2fsck error"
1233 }
1234 run_test 14 "OI scrub can repair OST objects under lost+found"
1235
1236 test_15() {
1237         local repaired
1238
1239         formatall > /dev/null
1240         setupall > /dev/null
1241
1242         scrub_prep 20 1
1243         echo "starting MDTs with OI scrub disabled"
1244         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1245         scrub_check_status 3 init
1246         [ "$mds1_FSTYPE" != "ldiskfs" ] ||
1247                 scrub_check_flags 4 recreated,inconsistent
1248
1249         # run under dryrun mode
1250         scrub_start 5 --dryrun
1251         scrub_check_status 6 completed
1252         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
1253                 scrub_check_flags 7 inconsistent
1254                 repaired=2
1255         else
1256                 scrub_check_flags 7 recreated,inconsistent
1257                 repaired=20
1258         fi
1259         scrub_check_params 8 dryrun
1260         scrub_check_repaired 9 $repaired 1
1261
1262         # run under dryrun mode again
1263         scrub_start 10 --dryrun
1264         scrub_check_status 11 completed
1265         if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
1266                 scrub_check_flags 12 inconsistent
1267         else
1268                 scrub_check_flags 12 recreated,inconsistent
1269         fi
1270         scrub_check_params 13 dryrun
1271         scrub_check_repaired 14 $repaired 1
1272
1273         # run under normal mode
1274         scrub_start 15
1275         scrub_check_status 16 completed
1276         scrub_check_flags 17 ""
1277         scrub_check_params 18 ""
1278         scrub_check_repaired 19 $repaired 0
1279
1280         # run under normal mode again
1281         scrub_start 20
1282         scrub_check_status 21 completed
1283         scrub_check_flags 22 ""
1284         scrub_check_params 23 ""
1285         scrub_check_repaired 24 0 0
1286 }
1287 run_test 15 "Dryrun mode OI scrub"
1288
1289 test_16() {
1290         check_mount_and_prep
1291         scrub_enable_index_backup
1292
1293         #define OBD_FAIL_OSD_INDEX_CRASH        0x199
1294         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x199
1295         scrub_prep 0
1296         do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0
1297
1298         echo "starting MDTs without disabling OI scrub"
1299         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
1300         mount_client $MOUNT || error "(2) Fail to start client!"
1301         scrub_check_data 3
1302         scrub_disable_index_backup
1303 }
1304 run_test 16 "Initial OI scrub can rebuild crashed index objects"
1305
1306 test_17a() {
1307         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
1308
1309 #define OBD_FAIL_OSD_OI_ENOSPC                          0x19d
1310         do_facet mds1 $LCTL set_param fail_loc=0x8000019d
1311         mkdir $DIR/$tdir && error "mkdir should fail"
1312         stop mds1
1313         local devname=$(mdsdevname 1)
1314
1315         stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
1316         FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
1317                 error "e2fsck returned $?"
1318 }
1319 run_test 17a "ENOSPC on OI insert shouldn't leak inodes"
1320
1321 test_17b() {
1322         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
1323
1324 #define OBD_FAIL_OSD_DOTDOT_ENOSPC                      0x19e
1325         do_facet mds1 $LCTL set_param fail_loc=0x8000019e
1326         mkdir_on_mdt0 $DIR/$tdir && error "mkdir should fail"
1327         stop mds1
1328         local devname=$(mdsdevname 1)
1329
1330         stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
1331         FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
1332                 error "e2fsck returned $?"
1333 }
1334 run_test 17b "ENOSPC on .. insertion shouldn't leak inodes"
1335
1336 test_18() {
1337         local n
1338         local fids=()
1339         local opts=$(csa_add "$MOUNT_OPTS_SCRUB" -o resetoi)
1340
1341         scrub_prep 10
1342         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
1343         mount_client $MOUNT || error "(2) Fail to start client!"
1344         for n in $(seq $MDSCOUNT); do
1345                 fids+=($($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh))
1346         done
1347         cleanup_mount $MOUNT > /dev/null || error "(3) Fail to stop client!"
1348         for n in $(seq $MDSCOUNT); do
1349                 stop mds$n > /dev/null || error "(4) Fail to stop MDS$n!"
1350         done
1351         scrub_start_mds 5 "$opts"
1352         do_facet mds1 dmesg | grep "reset Object Index" ||
1353                 error "(6) reset log not found"
1354         mount_client $MOUNT || error "(7) Fail to start client!"
1355         scrub_check_data 7
1356
1357         local fid
1358         local path
1359         for n in $(seq $MDSCOUNT); do
1360                 path=$($LFS fid2path $DIR ${fids[$((n - 1))]})
1361                 [ "$path" == "$DIR/$tdir/mds$n/test-framework.sh" ] ||
1362                         error "path mismatch $path != $DIR/$tdir/mds$n/test-framework.sh"
1363                 fid=$($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh)
1364                 [ "${fids[$((n - 1))]}" == "$fid" ] ||
1365                         error "$DIR/$tdir/mds$n/test-framework.sh FID mismatch ${fids[$((n - 1))]} != $fid"
1366         done
1367 }
1368 run_test 18 "test mount -o resetoi to recreate OI files"
1369
1370 test_19() {
1371         check_mount_and_prep
1372         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1373         createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 64 files."
1374         local fid=($($LFS getstripe $DIR/$tdir/f0 | grep 0x))
1375         local seq=${fid[3]#0x}
1376         local oid=${fid[1]}
1377         local oid_hex
1378
1379         if [ $seq = 0 ] || [ "$ost1_FSTYPE" == "zfs" ]; then
1380                 oid_hex=${fid[1]}
1381         else
1382                 oid_hex=${fid[2]#0x}
1383         fi
1384
1385         echo "stopall"
1386         stopall > /dev/null
1387
1388         # create mulitple link file
1389         mount_fstype ost1 || error "(1) Fail to mount ost1"
1390         mntpt=$(facet_mntpt ost1)
1391
1392         local path="$mntpt/O/$seq/d$(($oid % 32))"
1393
1394         # create link to the first file
1395         echo "link $path/$(($oid + 1)) to $path/$oid_hex"
1396         do_facet ost1 ln $path/$oid_hex $path/$(($oid + 1)) ||
1397                 { do_facet ost1 "ls -l $path"; error "(1b) link error"; }
1398         unmount_fstype ost1 || error "(2) Fail to umount ost1"
1399
1400         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1401                 error "(2) Fail to start ost1"
1402
1403         $START_SCRUB_ON_OST -r || error "(3) Fail to start OI scrub on OST!"
1404
1405         wait_update_facet ost1 "$LCTL get_param -n \
1406                 osd-*.$(facet_svc ost1).oi_scrub |
1407                 awk '/^status/ { print \\\$2 }'" "completed" 6 ||
1408                 error "(4) Expected '$expected' on ost1"
1409
1410         stop ost1
1411         mount_fstype ost1 || error "(5) Fail to mount ost1 again"
1412         do_facet ost1 "stat $path/$oid_hex" || do_facet ost1 "ls -l $path"
1413         links=$(do_facet ost1 "stat $path/$oid_hex" | awk '/Links:/ { print $6 }')
1414         unmount_fstype ost1 || error "(6) Fail to umount ost1"
1415
1416         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1417                 error "(7) Fail to start ost1"
1418
1419         (( links == 1)) || error "(8) object links $links != 1 after scrub"
1420 }
1421 run_test 19 "LFSCK can fix multiple linked files on OST"
1422
1423 test_20() {
1424         [ "$mds1_FSTYPE" == "ldiskfs" ] || skip "ldiskfs only test"
1425
1426         check_mount_and_prep
1427
1428         rm -rf $DIR/$tdir
1429         mkdir_on_mdt0 $DIR/$tdir || error "mkdir $tdir failed"
1430         #define OBD_FAIL_OSD_FID_MAPPING        0x193
1431         do_facet mds1 $LCTL set_param fail_loc=0x193
1432         chmod 757 $DIR/$tdir || error "chmod $tdir failed"
1433
1434         stop mds1
1435         start mds1 $(mdsdevname 1) $MOUNT_OPTS_NOSCRUB
1436         scrub_enable_auto
1437
1438         local sec
1439
1440         #define OBD_FAIL_OSD_SCRUB_IRREPARABLE  0x19f
1441         do_facet mds1 $LCTL set_param fail_loc=0x19f
1442         stat $DIR/$tdir && error "stat $tdir should fail"
1443         sec=$(scrub_status 1 | awk '/^time_since_latest_start/ { print $2 }')
1444         echo "OI scrub was triggerred $sec seconds ago"
1445
1446         sleep 5
1447         # OI mappings are irreparable, which shouldn't trigger scrub again
1448         stat $DIR/$tdir && error "stat $tdir should fail"
1449         sec=$(scrub_status 1 | awk '/^time_since_latest_start/ { print $2 }')
1450         echo "OI scrub was triggerred $sec seconds ago"
1451         (( sec >= 5 )) || error "OI scrub retriggered"
1452 }
1453 run_test 20 "Don't trigger OI scrub for irreparable oi repeatedly"
1454
1455 test_21() {
1456         [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
1457         [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
1458
1459         local timeout
1460         local td=$TMP/$tdir
1461         local device=$(mdsdevname 1)
1462
1463         echo $device
1464
1465         timeout=$(do_facet mds2 "$LCTL get_param -n \
1466                 mdt.$FSNAME-MDT0001.recovery_time_hard")
1467         for idx in $(seq $MDSCOUNT); do
1468             stop mds${idx}
1469         done
1470
1471         #test reproduce simple situation, when  OI record exist
1472         #and inode was reused/wrong. Scrub should handle it.
1473         do_facet mds1 "mkdir -p $td && mount -t ldiskfs $device $td &&
1474             rm -rf $td/update_log_dir/*; umount $td; rm -rf $td"
1475
1476         for idx in $(seq $MDSCOUNT); do
1477             start mds${idx} $(mdsdevname $idx) $MDS_MOUNT_OPTS ||
1478                 error "mount mds$idx failed"
1479         done
1480
1481         wait_recovery_complete mds2 $((timeout + TIMEOUT))
1482
1483 }
1484 run_test 21 "don't hang MDS recovery when failed to get update log"
1485
1486
1487 # restore MDS/OST size
1488 MDSSIZE=${SAVED_MDSSIZE}
1489 OSTSIZE=${SAVED_OSTSIZE}
1490 OSTCOUNT=${SAVED_OSTCOUNT}
1491
1492 # cleanup the system at last
1493 REFORMAT="yes" cleanup_and_setup_lustre
1494
1495 complete_test $SECONDS
1496 check_and_cleanup_lustre
1497 exit_status