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