Whamcloud - gitweb
LU-4106 scrub: Trigger OI scrub properly
[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 ALWAYS_EXCEPT="$SANITY_SCRUB_EXCEPT"
11 [ "$SLOW" = "no" ] && EXCEPT_SLOW=""
12 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
13
14 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
15 . $LUSTRE/tests/test-framework.sh
16 init_test_env $@
17 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
18 init_logging
19
20 require_dsh_mds || exit 0
21
22 SAVED_MDSSIZE=${MDSSIZE}
23 SAVED_OSTSIZE=${OSTSIZE}
24 # use small MDS + OST size to speed formatting time
25 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
26 MDSSIZE=100000
27 OSTSIZE=100000
28
29 MOUNT_2=""
30 check_and_setup_lustre
31
32 [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
33         skip "test OI scrub only for ldiskfs" && check_and_cleanup_lustre &&
34         exit 0
35 [ $(facet_fstype ost1) != "ldiskfs" ] &&
36         skip "test OI scrub only for ldiskfs" && check_and_cleanup_lustre &&
37         exit 0
38 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.2.90) ]] &&
39         skip "Need MDS version at least 2.2.90" && check_and_cleanup_lustre &&
40         exit 0
41
42 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.90) ]] &&
43         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 1a"
44
45 [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.4.1) ]] &&
46         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 15"
47
48 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.4.90) ]] &&
49 [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.4.50) ]] &&
50         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 15"
51
52 [[ $(lustre_version_code ost1) -lt $(version_code 2.4.50) ]] &&
53         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 11 12 13 14"
54
55 build_test_filter
56
57 MDT_DEV="${FSNAME}-MDT0000"
58 OST_DEV="${FSNAME}-OST0000"
59 MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/})
60
61 scrub_start() {
62         local error_id=$1
63         local n
64
65         for n in $(seq $MDSCOUNT); do
66                 do_facet mds$n $LCTL lfsck_start -M $(facet_svc mds$n) "$@" ||
67                         error "($error_id) Failed to start OI scrub on mds$n"
68         done
69 }
70
71 scrub_stop() {
72         local error_id=$1
73         local n
74
75         for n in $(seq $MDSCOUNT); do
76                 do_facet mds$n $LCTL lfsck_stop -M $(facet_svc mds$n) ||
77                         error "($error_id) Failed to stop OI scrub on mds$n"
78         done
79 }
80
81 scrub_status() {
82         local n=$1
83
84         do_facet mds$n $LCTL get_param -n \
85                 osd-ldiskfs.$(facet_svc mds$n).oi_scrub
86 }
87
88 START_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_start -M ${MDT_DEV}"
89 START_SCRUB_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV}"
90 STOP_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
91 SHOW_SCRUB="do_facet $SINGLEMDS \
92                 $LCTL get_param -n osd-ldiskfs.${MDT_DEV}.oi_scrub"
93 SHOW_SCRUB_ON_OST="do_facet ost1 \
94                 $LCTL get_param -n osd-ldiskfs.${OST_DEV}.oi_scrub"
95 MOUNT_OPTS_SCRUB="-o user_xattr"
96 MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
97
98 scrub_prep() {
99         local nfiles=$1
100         local n
101
102         echo "formatall"
103         formatall > /dev/null
104         echo "setupall"
105         setupall > /dev/null
106
107         echo "preparing..."
108         for n in $(seq $MDSCOUNT); do
109                 echo "creating $nfiles files on mds$n"
110                 if [ $n -eq 1 ]; then
111                         mkdir -p $DIR/$tdir/mds$n ||
112                                 error "Failed to create directory mds$n"
113                 else
114                         $LFS mkdir -i $((n - 1)) $DIR/$tdir/mds$n ||
115                                 error "Failed to create remote directory mds$n"
116                 fi
117                 cp $LUSTRE/tests/*.sh $DIR/$tdir/mds$n ||
118                         error "Failed to copy files to mds$n"
119                 if [[ $nfiles -gt 0 ]]; then
120                         createmany -o $DIR/$tdir/mds$n/$tfile $nfiles ||
121                                 error "createmany failed on mds$n"
122                 fi
123         done
124         echo "prepared."
125         cleanup_mount $MOUNT > /dev/null || error "Fail to stop client!"
126         for n in $(seq $MDSCOUNT); do
127                 echo "stop mds$n"
128                 stop mds$n > /dev/null || error "Fail to stop MDS$n!"
129         done
130 }
131
132 scrub_start_mds() {
133         local error_id=$1
134         local opts=$2
135         local n
136
137         for n in $(seq $MDSCOUNT); do
138                 start mds$n $(mdsdevname $n) $opts >/dev/null ||
139                         error "($error_id) Failed to start mds$n"
140         done
141 }
142
143 scrub_stop_mds() {
144         local error_id=$1
145         local n
146
147         for n in $(seq $MDSCOUNT); do
148                 echo "stopping mds$n"
149                 stop mds$n >/dev/null ||
150                         error "($error_id) Failed to stop mds$n"
151         done
152 }
153
154 scrub_check_status() {
155         local error_id=$1
156         local expected=$2
157         local actual
158         local n
159
160         for n in $(seq $MDSCOUNT); do
161                 actual=$(do_facet mds$n $LCTL get_param -n \
162                         osd-ldiskfs.$(facet_svc mds$n).oi_scrub |
163                         awk '/^status/ { print $2 }')
164                 if [ "$actual" != "$expected" ]; then
165                         error "($error_id) Expected '$expected' on mds$n, but" \
166                                "got '$actual'"
167                 fi
168         done
169 }
170
171 scrub_check_flags() {
172         local error_id=$1
173         local expected=$2
174         local actual
175         local n
176
177         for n in $(seq $MDSCOUNT); do
178                 actual=$(do_facet mds$n $LCTL get_param -n \
179                         osd-ldiskfs.$(facet_svc mds$n).oi_scrub |
180                         awk '/^flags/ { print $2 }')
181                 if [ "$actual" != "$expected" ]; then
182                         error "($error_id) Expected '$expected' on mds$n, but" \
183                                "got '$actual'"
184                 fi
185         done
186 }
187
188 scrub_check_params() {
189         local error_id=$1
190         local expected=$2
191         local actual
192         local n
193
194         for n in $(seq $MDSCOUNT); do
195                 actual=$(do_facet mds$n $LCTL get_param -n \
196                         osd-ldiskfs.$(facet_svc mds$n).oi_scrub |
197                         awk '/^param/ { print $2 }')
198                 if [ "$actual" != "$expected" ]; then
199                         error "($error_id) Expected '$expected' on mds$n, but" \
200                                "got '$actual'"
201                 fi
202         done
203 }
204
205 scrub_check_repaired() {
206         local error_id=$1
207         local expected=$2
208         local actual
209         local n
210
211         for n in $(seq $MDSCOUNT); do
212                 actual=$(do_facet mds$n $LCTL get_param -n \
213                         osd-ldiskfs.$(facet_svc mds$n).oi_scrub |
214                         awk '/^updated/ { print $2 }')
215
216                 if [ $expected -eq 0 -a $actual -ne 0 ]; then
217                         error "($error_id) Expected no repaired on mds$n, but" \
218                                "got '$actual'"
219                 fi
220
221                 if [ $expected -ne 0 -a $actual -lt $expected ]; then
222                         error "($error_id) Expected '$expected' on mds$n, but" \
223                                "got '$actual'"
224                 fi
225         done
226 }
227
228 scrub_check_data() {
229         local error_id=$1
230         local n
231
232         for n in $(seq $MDSCOUNT); do
233                 diff -q $LUSTRE/tests/test-framework.sh \
234                         $DIR/$tdir/mds$n/test-framework.sh ||
235                         error "($error_id) File data check failed"
236         done
237 }
238
239 scrub_remove_ois() {
240         local error_id=$1
241         local index=$2
242         local n
243
244         for n in $(seq $MDSCOUNT); do
245                 mds_remove_ois mds$n $index ||
246                         error "($error_id) Failed to remove OI .$index on mds$n"
247         done
248 }
249
250 scrub_backup_restore() {
251         local error_id=$1
252         local igif=$2
253         local n
254
255         for n in $(seq $MDSCOUNT); do
256                 mds_backup_restore mds$n $igif ||
257                         error "(error_id) Backup/restore on mds$n failed"
258         done
259 }
260
261 scrub_enable_auto() {
262         local n
263
264         for n in $(seq $MDSCOUNT); do
265                 do_facet mds$n $LCTL set_param -n \
266                         osd-ldiskfs.$(facet_svc mds$n).auto_scrub 1
267         done
268 }
269
270 test_0() {
271         scrub_prep 0
272         echo "starting MDTs without disabling OI scrub"
273         scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
274         scrub_check_status 2 init
275         scrub_check_flags 3 ""
276         mount_client $MOUNT || error "(4) Fail to start client!"
277         scrub_check_data 5
278 }
279 run_test 0 "Do not auto trigger OI scrub for non-backup/restore case"
280
281 test_1a() {
282         scrub_prep 0
283         echo "start $SINGLEMDS without disabling OI scrub"
284         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
285                 error "(1) Fail to start MDS!"
286
287         local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }')
288         [ "$STATUS" == "init" ] ||
289                 error "(2) Expect 'init', but got '$STATUS'"
290
291         local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
292         [ -z "$FLAGS" ] || error "(3) Expect empty flags, but got '$FLAGS'"
293
294         mount_client $MOUNT || error "(4) Fail to start client!"
295
296         #define OBD_FAIL_OSD_FID_MAPPING                        0x193
297         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x193
298         # update .lustre OI mapping
299         touch $MOUNT/.lustre
300         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
301
302         umount_client $MOUNT || error "(5) Fail to stop client!"
303
304         echo "stop $SINGLEMDS"
305         stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!"
306
307         echo "start $SINGLEMDS with disabling OI scrub"
308         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
309                 error "(7) Fail to start MDS!"
310
311         local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }')
312         [ "$STATUS" == "init" ] ||
313                 error "(8) Expect 'init', but got '$STATUS'"
314
315         local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
316         [ "$FLAGS" == "inconsistent" ] ||
317                 error "(9) Expect 'inconsistent', but got '$FLAGS'"
318 }
319 run_test 1a "Auto trigger initial OI scrub when server mounts"
320
321 test_1b() {
322         scrub_prep 0
323         scrub_remove_ois 1
324         echo "start MDTs without disabling OI scrub"
325         scrub_start_mds 2 "$MOUNT_OPTS_SCRUB"
326         sleep 3
327         scrub_check_status 3 completed
328         mount_client $MOUNT || error "(4) Fail to start client!"
329         scrub_check_data 5
330 }
331 run_test 1b "Trigger OI scrub when MDT mounts for OI files remove/recreate case"
332
333 test_1c() {
334         local index
335
336         # OI files to be removed:
337         # idx 0: oi.16.0
338         # idx 1: oi.16.1
339         # idx 2: oi.16.{2,4,8,16,32}
340         # idx 3: oi.16.{3,9,27}
341         # idx 5: oi.16.{5,25}
342         # idx 7: oi.16.{7,49}
343         for index in 0 1 2 3 5 7; do
344                 scrub_prep 0
345                 scrub_remove_ois 1 $index
346
347                 echo "start MDTs with OI scrub disabled"
348                 scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
349                 scrub_check_flags 3 recreated
350                 scrub_start 4
351                 sleep 3
352                 scrub_check_status 5 completed
353                 scrub_check_flags 6 ""
354         done
355 }
356 run_test 1c "Auto detect kinds of OI file(s) removed/recreated cases"
357
358 test_2() {
359         scrub_prep 0
360         scrub_backup_restore 1
361         echo "starting MDTs without disabling OI scrub"
362         scrub_start_mds 2 "$MOUNT_OPTS_SCRUB"
363         sleep 3
364         scrub_check_status 3 completed
365         mount_client $MOUNT || error "(4) Fail to start client!"
366         scrub_check_data 5
367 }
368 run_test 2 "Trigger OI scrub when MDT mounts for backup/restore case"
369
370 test_3() {
371         scrub_prep 0
372         scrub_backup_restore 1
373         echo "starting MDTs with OI scrub disabled"
374         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
375         sleep 3
376         scrub_check_status 3 init
377         scrub_check_flags 4 inconsistent
378         echo "stopall"
379         stopall > /dev/null
380 }
381 run_test 3 "Do not trigger OI scrub when MDT mounts if 'noscrub' specified"
382
383 test_4() {
384         scrub_prep 0
385         scrub_backup_restore 1
386         echo "starting MDTs with OI scrub disabled"
387         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
388         scrub_check_status 3 init
389         scrub_check_flags 4 inconsistent
390         mount_client $MOUNT || error "(5) Fail to start client!"
391         scrub_enable_auto
392         scrub_check_data 6
393         sleep 3
394         scrub_check_status 7 completed
395 }
396 run_test 4 "Trigger OI scrub automatically if inconsistent OI mapping was found"
397
398 test_5() {
399         scrub_prep 1500
400         scrub_backup_restore 1
401         echo "starting MDTs with OI scrub disabled"
402         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
403         scrub_check_status 3 init
404         scrub_check_flags 4 inconsistent
405         mount_client $MOUNT || error "(5) Fail to start client!"
406         scrub_enable_auto
407
408         local n
409         for n in $(seq $MDSCOUNT); do
410                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
411                 do_facet mds$n $LCTL set_param fail_val=3
412                 do_facet mds$n $LCTL set_param fail_loc=0x190
413         done
414         scrub_check_data 6
415
416         umount_client $MOUNT || error "(7) Fail to stop client!"
417
418         scrub_check_status 8 scanning
419
420         for n in $(seq $MDSCOUNT); do
421                 #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
422                 do_facet mds$n $LCTL set_param fail_loc=0x191
423         done
424         sleep 4
425         scrub_stop_mds 9
426
427         for n in $(seq $MDSCOUNT); do
428                 do_facet mds$n $LCTL set_param fail_loc=0
429                 do_facet mds$n $LCTL set_param fail_val=0
430         done
431
432         echo "starting MDTs with OI scrub disabled"
433         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
434
435         scrub_check_status 11 crashed
436
437         scrub_stop_mds 12
438
439         for n in $(seq $MDSCOUNT); do
440                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
441                 do_facet mds$n $LCTL set_param fail_val=3
442                 do_facet mds$n $LCTL set_param fail_loc=0x190
443         done
444         echo "starting MDTs without disabling OI scrub"
445         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
446
447         scrub_check_status 14 scanning
448
449         for n in $(seq $MDSCOUNT); do
450                 #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
451                 do_facet mds$n $LCTL set_param fail_loc=0x192
452         done
453         sleep 4
454         scrub_check_status 15 failed
455
456         mount_client $MOUNT || error "(16) Fail to start client!"
457
458         for n in $(seq $MDSCOUNT); do
459                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
460                 do_facet mds$n $LCTL set_param fail_val=3
461                 do_facet mds$n $LCTL set_param fail_loc=0x190
462                 stat $DIR/$tdir/mds$n/${tfile}1000 ||
463                         error "(17) Failed to stat mds$n/${tfile}1000"
464         done
465
466         scrub_check_status 18 scanning
467
468         for n in $(seq $MDSCOUNT); do
469                 do_facet mds$n $LCTL set_param fail_loc=0
470                 do_facet mds$n $LCTL set_param fail_val=0
471         done
472         sleep 5
473         scrub_check_status 19 completed
474
475         scrub_check_flags 20 ""
476 }
477 run_test 5 "OI scrub state machine"
478
479 test_6() {
480         scrub_prep 1000
481         scrub_backup_restore 1
482         echo "starting MDTs with OI scrub disabled"
483         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
484         scrub_check_status 3 init
485         scrub_check_flags 4 inconsistent
486         mount_client $MOUNT || error "(5) Fail to start client!"
487         scrub_enable_auto
488         local n
489         for n in $(seq $MDSCOUNT); do
490                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
491                 do_facet mds$n $LCTL set_param fail_val=3
492                 do_facet mds$n $LCTL set_param fail_loc=0x190
493         done
494         scrub_check_data 6
495
496         # Sleep 5 sec to guarantee at least one object processed by OI scrub
497         sleep 5
498         # Fail the OI scrub to guarantee there is at least one checkpoint
499         for n in $(seq $MDSCOUNT); do
500                 #define OBD_FAIL_OSD_SCRUB_FATAL         0x192
501                 do_facet mds$n $LCTL set_param fail_loc=0x192
502         done
503         sleep 4
504         scrub_check_status 7 failed
505
506         for n in $(seq $MDSCOUNT); do
507                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
508                 do_facet mds$n $LCTL set_param fail_val=3
509                 do_facet mds$n $LCTL set_param fail_loc=0x190
510                 # stat will re-trigger OI scrub
511                 stat $DIR/$tdir/mds$n/${tfile}800 ||
512                         error "(8) Failed to stat mds$n/${tfile}800"
513         done
514
515         umount_client $MOUNT || error "(9) Fail to stop client!"
516
517         scrub_check_status 10 scanning
518
519         for n in $(seq $MDSCOUNT); do
520                 #define OBD_FAIL_OSD_SCRUB_CRASH         0x191
521                 do_facet mds$n $LCTL set_param fail_loc=0x191
522         done
523         sleep 4
524         local -a position0
525         for n in $(seq $MDSCOUNT); do
526                 position0[$n]=$(scrub_status $n |
527                         awk '/^last_checkpoint_position/ {print $2}')
528                 position0[$n]=$((${position0[$n]} + 1))
529         done
530
531         scrub_stop_mds 11
532
533         for n in $(seq $MDSCOUNT); do
534                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
535                 do_facet mds$n $LCTL set_param fail_val=3
536                 do_facet mds$n $LCTL set_param fail_loc=0x190
537         done
538         echo "starting MDTs without disabling OI scrub"
539         scrub_start_mds 12 "$MOUNT_OPTS_SCRUB"
540
541         scrub_check_status 13 scanning
542
543         local -a position1
544         for n in $(seq $MDSCOUNT); do
545                 position1[$n]=$(scrub_status $n |
546                         awk '/^latest_start_position/ {print $2}')
547                 if [ ${position0[$n]} -ne ${position1[$n]} ]; then
548                         error "(14) Expected position ${position0[$n]}, but" \
549                                 "got ${position1[$n]}"
550                 fi
551         done
552
553         for n in $(seq $MDSCOUNT); do
554                 do_facet mds$n $LCTL set_param fail_loc=0
555                 do_facet mds$n $LCTL set_param fail_val=0
556         done
557         sleep 5
558         scrub_check_status 15 completed
559
560         scrub_check_flags 16 ""
561 }
562 run_test 6 "OI scrub resumes from last checkpoint"
563
564 test_7() {
565         scrub_prep 500
566         scrub_backup_restore 1
567
568         echo "starting MDTs with OI scrub disabled"
569         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
570         scrub_check_status 3 init
571         scrub_check_flags 4 inconsistent
572
573         mount_client $MOUNT || error "(5) Fail to start client!"
574
575         scrub_enable_auto
576         local n
577         for n in $(seq $MDSCOUNT); do
578                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
579                 do_facet mds$n $LCTL set_param fail_val=3
580                 do_facet mds$n $LCTL set_param fail_loc=0x190
581         done
582         scrub_check_data 6
583
584         for n in $(seq $MDSCOUNT); do
585                 stat $DIR/$tdir/mds$n/${tfile}300 ||
586                         error "(7) Failed to stat mds$n/${tfile}300!"
587         done
588
589         scrub_check_status 8 scanning
590
591         scrub_check_flags 9 inconsistent,auto
592
593         for n in $(seq $MDSCOUNT); do
594                 do_facet mds$n $LCTL set_param fail_loc=0
595                 do_facet mds$n $LCTL set_param fail_val=0
596         done
597         sleep 5
598         scrub_check_status 10 completed
599
600         scrub_check_flags ""
601 }
602 run_test 7 "System is available during OI scrub scanning"
603
604 test_8() {
605         scrub_prep 128
606         scrub_backup_restore 1
607
608         echo "starting MDTs with OI scrub disabled"
609         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
610
611         scrub_check_status 3 init
612
613         scrub_check_flags 4 inconsistent
614
615         local n
616         for n in $(seq $MDSCOUNT); do
617                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
618                 do_facet mds$n $LCTL set_param fail_val=1
619                 do_facet mds$n $LCTL set_param fail_loc=0x190
620         done
621         scrub_start 5
622
623         scrub_check_status 6 scanning
624
625         scrub_stop 7
626
627         scrub_check_status 8 stopped
628
629         scrub_start 9
630
631         scrub_check_status 10 scanning
632
633         for n in $(seq $MDSCOUNT); do
634                 do_facet mds$n $LCTL set_param fail_loc=0
635                 do_facet mds$n $LCTL set_param fail_val=0
636         done
637         sleep 5
638         scrub_check_status 11 completed
639
640         scrub_check_flags 12 ""
641 }
642 run_test 8 "Control OI scrub manually"
643
644 test_9() {
645         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
646                 skip "Testing on UP system, the speed may be inaccurate."
647                 return 0
648         fi
649
650         scrub_prep 8000
651         scrub_backup_restore 1
652
653         echo "starting MDTs with OI scrub disabled"
654         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
655
656         scrub_check_status 3 init
657
658         scrub_check_flags 4 inconsistent
659
660         local BASE_SPEED1=100
661         local RUN_TIME1=10
662         # OI scrub should run with full speed under inconsistent case
663         scrub_start 5 -s $BASE_SPEED1
664
665         sleep $RUN_TIME1
666         scrub_check_status 6 completed
667
668         scrub_check_flags 7 ""
669
670         # OI scrub should run with limited speed under non-inconsistent case
671         scrub_start 8 -s $BASE_SPEED1 -r
672
673         sleep $RUN_TIME1
674         scrub_check_status 9 scanning
675
676         # Do NOT ignore that there are 1024 pre-fetched items. And there
677         # may be time error, normally it should be less than 2 seconds.
678         # We allow another 20% schedule error.
679         local PRE_FETCHED=1024
680         local TIME_DIFF=2
681         # MAX_MARGIN = 1.2 = 12 / 10
682         local MAX_SPEED=$(((PRE_FETCHED + BASE_SPEED1 * \
683                 (RUN_TIME1 + TIME_DIFF)) / RUN_TIME1 * 12 / 10))
684         local n
685         for n in $(seq $MDSCOUNT); do
686                 local SPEED=$(scrub_status $n | \
687                         awk '/^average_speed/ { print $2 }')
688                 [ $SPEED -lt $MAX_SPEED ] ||
689                         error "(10) Got speed $SPEED, expected less than" \
690                                 "$MAX_SPEED"
691         done
692
693         # adjust speed limit
694         local BASE_SPEED2=300
695         local RUN_TIME2=10
696         for n in $(seq $MDSCOUNT); do
697                 do_facet mds$n $LCTL set_param -n \
698                         mdd.$(facet_svc mds$n).lfsck_speed_limit $BASE_SPEED2
699         done
700         sleep $RUN_TIME2
701
702         # MIN_MARGIN = 0.8 = 8 / 10
703         local MIN_SPEED=$(((PRE_FETCHED + \
704                             BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
705                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
706                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
707         # MAX_MARGIN = 1.2 = 12 / 10
708         MAX_SPEED=$(((PRE_FETCHED + \
709                       BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
710                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
711                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
712         for n in $(seq $MDSCOUNT); do
713                 SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }')
714                 [ $SPEED -gt $MIN_SPEED ] ||
715                         error "(11) Got speed $SPEED, expected more than" \
716                                 "$MIN_SPEED"
717                 [ $SPEED -lt $MAX_SPEED ] ||
718                         error "(12) Got speed $SPEED, expected less than" \
719                                 "$MAX_SPEED"
720
721                 do_facet mds$n $LCTL set_param -n \
722                                 mdd.$(facet_svc mds$n).lfsck_speed_limit 0
723         done
724         sleep 6
725         scrub_check_status 13 completed
726 }
727 run_test 9 "OI scrub speed control"
728
729 test_10a() {
730         scrub_prep 0
731         scrub_backup_restore 1
732
733         echo "starting mds$n with OI scrub disabled"
734         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
735
736         scrub_check_status 3 init
737
738         scrub_check_flags 4 inconsistent
739
740         mount_client $MOUNT || error "(5) Fail to start client!"
741
742         scrub_enable_auto
743         local n
744         for n in $(seq $MDSCOUNT); do
745                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
746                 do_facet mds$n $LCTL set_param fail_val=1
747                 do_facet mds$n $LCTL set_param fail_loc=0x190
748         done
749         scrub_check_data 6
750
751         scrub_check_status 7 scanning
752
753         umount_client $MOUNT || error "(8) Fail to stop client!"
754
755         scrub_stop_mds 9
756
757         echo "starting MDTs with OI scrub disabled"
758         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
759
760         scrub_check_status 11 paused
761
762         scrub_stop_mds 12
763
764         echo "starting MDTs without disabling OI scrub"
765         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
766
767         scrub_check_status 14 scanning
768
769         for n in $(seq $MDSCOUNT); do
770                 do_facet mds$n $LCTL set_param fail_loc=0
771                 do_facet mds$n $LCTL set_param fail_val=0
772         done
773         sleep 5
774         scrub_check_status 15 completed
775
776         scrub_check_flags 16 ""
777 }
778 run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)"
779
780 # test_10b is obsolete, it will be coverded by related sanity-lfsck tests.
781 test_10b() {
782         scrub_prep 0
783         scrub_backup_restore 1
784
785         echo "starting MDTs with OI scrub disabled"
786         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
787
788         scrub_check_status 3 init
789
790         scrub_check_flags 4 inconsistent
791
792         local n
793         for n in $(seq $MDSCOUNT); do
794                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
795                 do_facet mds$n $LCTL set_param fail_val=3
796                 do_facet mds$n $LCTL set_param fail_loc=0x190
797         done
798
799         scrub_start 5
800
801         scrub_check_status 6 scanning
802
803         scrub_stop_mds 7
804
805         echo "starting MDTs with OI scrub disabled"
806         scrub_start_mds 8 "$MOUNT_OPTS_NOSCRUB"
807
808         scrub_check_status 9 paused
809
810         scrub_stop_mds 10
811
812         echo "starting MDTs without disabling OI scrub"
813         scrub_start_mds 11 "$MOUNT_OPTS_SCRUB"
814
815         scrub_check_status 12 scanning
816
817         for n in $(seq $MDSCOUNT); do
818                 do_facet mds$n $LCTL set_param fail_loc=0
819                 do_facet mds$n $LCTL set_param fail_val=0
820         done
821         sleep 5
822         scrub_check_status 13 completed
823
824         scrub_check_flags 14 ""
825 }
826 #run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)"
827
828 test_11() {
829         echo "stopall"
830         stopall > /dev/null
831         echo "formatall"
832         formatall > /dev/null
833         echo "setupall"
834         setupall > /dev/null
835
836         local CREATED=100
837         local tname=`date +%s`
838         rm -rf $MOUNT/$tname > /dev/null
839         mkdir -p $MOUNT/$tname || error "(0) Failed to create $MOUNT/$tname"
840         local n
841         for n in $(seq $MDSCOUNT); do
842                 $LFS mkdir -i $((n - 1)) $MOUNT/$tname/mds$n ||
843                         error "(1) Fail to mkdir $MOUNT/$tname/mds$n"
844
845                 createmany -o $MOUNT/$tname/mds$n/f $CREATED ||
846                         error "(2) Fail to create in $tname/mds$n"
847         done
848
849         cleanup_mount $MOUNT
850         do_facet $SINGLEMDS $LCTL clear
851         start_full_debug_logging
852         # reset OI scrub start point by force
853         scrub_start 3 -r
854         sleep 3
855         scrub_check_status 4 completed
856
857         # OI scrub should skip the new created objects for the first accessing
858         # notice we're creating a new llog for every OST on every startup
859         # new features can make this even less stable, so we only check
860         # that the number of skipped files is less than 2x the number of files
861         local MAXIMUM=$((CREATED * 2))
862         local MINIMUM=$((CREATED + 1)) # files + directory
863         for n in $(seq $MDSCOUNT); do
864                 local SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
865                 [ $SKIPPED -ge $MAXIMUM -o $SKIPPED -lt $MINIMUM ] &&
866                         error "(5) Expect [ $MINIMUM , $MAXIMUM ) objects" \
867                                 "skipped on mds$n, but got $SKIPPED"
868         done
869
870         # reset OI scrub start point by force
871         scrub_start -r
872         sleep 3
873         scrub_check_status 7 completed
874
875         # OI scrub should skip the new created object only once
876         for n in $(seq $MDSCOUNT); do
877                 SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
878                 [ $SKIPPED -eq 0 ] ||
879                         error "(8) Expect 0 objects skipped on mds$n, but" \
880                                 "got $SKIPPED"
881         done
882
883         stop_full_debug_logging
884         restore_mount $MOUNT || error "(9) Fail to start client!"
885         rm -rf $MOUNT/$tname > /dev/null
886 }
887 run_test 11 "OI scrub skips the new created objects only once"
888
889 test_12() {
890         echo "stopall"
891         stopall > /dev/null
892         echo "formatall"
893         formatall > /dev/null
894         echo "setupall"
895         setupall > /dev/null
896
897         mkdir -p $DIR/$tdir
898         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
899
900         #define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY               0x195
901         do_facet ost1 $LCTL set_param fail_loc=0x195
902         createmany -o $DIR/$tdir/f 1000
903
904         echo "stopall"
905         stopall > /dev/null
906         echo "setupall"
907         setupall > /dev/null
908
909         do_facet ost1 $LCTL set_param fail_loc=0
910         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
911         [ "$STATUS" == "init" ] ||
912                 error "(1) Expect 'init', but got '$STATUS'"
913
914         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
915
916         sleep 3
917         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
918         [ "$STATUS" == "completed" ] ||
919                 error "(3) Expect 'completed', but got '$STATUS'"
920
921         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(4) ls should succeed"
922 }
923 run_test 12 "OI scrub can rebuild invalid /O entries"
924
925 test_13() {
926         echo "stopall"
927         stopall > /dev/null
928         echo "formatall"
929         formatall > /dev/null
930         echo "setupall"
931         setupall > /dev/null
932
933         mkdir -p $DIR/$tdir
934         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
935
936         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
937         do_facet ost1 $LCTL set_param fail_loc=0x196
938         createmany -o $DIR/$tdir/f 1000
939         do_facet ost1 $LCTL set_param fail_loc=0
940
941         echo "stopall"
942         stopall > /dev/null
943         echo "setupall"
944         setupall > /dev/null
945
946         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
947         [ "$STATUS" == "init" ] ||
948                 error "(1) Expect 'init', but got '$STATUS'"
949
950         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
951
952         $START_SCRUB_ON_OST || error "(3) Fail to start OI scrub on OST!"
953         sleep 3
954         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
955         [ "$STATUS" == "completed" ] ||
956                 error "(4) Expect 'completed', but got '$STATUS'"
957
958         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(5) ls should succeed"
959 }
960 run_test 13 "OI scrub can rebuild missed /O entries"
961
962 test_14() {
963         echo "stopall"
964         stopall > /dev/null
965         echo "formatall"
966         formatall > /dev/null
967         echo "setupall"
968         setupall > /dev/null
969
970         mkdir -p $DIR/$tdir
971         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
972
973         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
974         do_facet ost1 $LCTL set_param fail_loc=0x196
975         createmany -o $DIR/$tdir/f 64
976         do_facet ost1 $LCTL set_param fail_loc=0
977
978         echo "stopall"
979         stopall > /dev/null
980         echo "setupall"
981         setupall > /dev/null
982
983         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
984         [ "$STATUS" == "init" ] ||
985                 error "(1) Expect 'init', but got '$STATUS'"
986
987         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
988
989         echo "stopall"
990         stopall > /dev/null
991
992         echo "run e2fsck"
993         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
994                 error "(3) Fail to run e2fsck error"
995
996         echo "setupall"
997         setupall > /dev/null
998
999         local LF_REPAIRED=$($SHOW_SCRUB_ON_OST |
1000                             awk '/^lf_reparied/ { print $2 }')
1001         [ $LF_REPAIRED -gt 0 ] ||
1002                 error "(4) Some entry under /lost+found should be repaired"
1003
1004         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(5) ls should succeed"
1005 }
1006 run_test 14 "OI scrub can repair objects under lost+found"
1007
1008 test_15() {
1009         # skip test_15 for LU-4182
1010         [ $MDSCOUNT -ge 2 ] && skip "skip now for >= 2 MDTs" && return
1011         scrub_prep 20
1012         scrub_backup_restore 1
1013         echo "starting MDTs with OI scrub disabled"
1014         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1015         scrub_check_status 3 init
1016         scrub_check_flags 4 inconsistent
1017
1018         # run under dryrun mode
1019         scrub_start 5 -n on
1020         sleep 3
1021         scrub_check_status 6 completed
1022         scrub_check_flags 7 inconsistent
1023         scrub_check_params 8 dryrun
1024         scrub_check_repaired 9 20
1025
1026         # run under dryrun mode again
1027         scrub_start 10 -n on
1028         sleep 3
1029         scrub_check_status 11 completed
1030         scrub_check_flags 12 inconsistent
1031         scrub_check_params 13 dryrun
1032         scrub_check_repaired 14 20
1033
1034         # run under normal mode
1035         scrub_start 15 -n off
1036         sleep 3
1037         scrub_check_status 16 completed
1038         scrub_check_flags 17 ""
1039         scrub_check_params 18 ""
1040         scrub_check_repaired 19 20
1041
1042         # run under normal mode again
1043         scrub_start 20 -n off
1044         sleep 3
1045         scrub_check_status 21 completed
1046         scrub_check_flags 22 ""
1047         scrub_check_params 23 ""
1048         scrub_check_repaired 24 0
1049 }
1050 run_test 15 "Dryrun mode OI scrub"
1051
1052 # restore MDS/OST size
1053 MDSSIZE=${SAVED_MDSSIZE}
1054 OSTSIZE=${SAVED_OSTSIZE}
1055
1056 # cleanup the system at last
1057 formatall
1058
1059 complete $SECONDS
1060 exit_status