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