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