Whamcloud - gitweb
efbbd3b135936369c4116a736a8d2200cd70ace2
[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                 positions1[$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         # skip test_7 for LU-4149
566         [ $MDSCOUNT -ge 2 ] && skip "skip now for >= 2 MDTs" && return
567
568         scrub_prep 500
569         scrub_backup_restore 1
570
571         echo "starting MDTs with OI scrub disabled"
572         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
573         scrub_check_status 3 init
574         scrub_check_flags 4 inconsistent
575
576         mount_client $MOUNT || error "(5) Fail to start client!"
577
578         scrub_enable_auto
579         local n
580         for n in $(seq $MDSCOUNT); do
581                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
582                 do_facet mds$n $LCTL set_param fail_val=3
583                 do_facet mds$n $LCTL set_param fail_loc=0x190
584         done
585         scrub_check_data 6
586
587         for n in $(seq $MDSCOUNT); do
588                 stat $DIR/$tdir/mds$n/${tfile}300 ||
589                         error "(7) Failed to stat mds$n/${tfile}300!"
590         done
591
592         scrub_check_status 8 scanning
593
594         scrub_check_flags 9 inconsistent,auto
595
596         for n in $(seq $MDSCOUNT); do
597                 do_facet mds$n $LCTL set_param fail_loc=0
598                 do_facet mds$n $LCTL set_param fail_val=0
599         done
600         sleep 5
601         scrub_check_status 10 completed
602
603         scrub_check_flags ""
604 }
605 run_test 7 "System is available during OI scrub scanning"
606
607 test_8() {
608         scrub_prep 128
609         scrub_backup_restore 1
610
611         echo "starting MDTs with OI scrub disabled"
612         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
613
614         scrub_check_status 3 init
615
616         scrub_check_flags 4 inconsistent
617
618         local n
619         for n in $(seq $MDSCOUNT); do
620                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
621                 do_facet mds$n $LCTL set_param fail_val=1
622                 do_facet mds$n $LCTL set_param fail_loc=0x190
623         done
624         scrub_start 5
625
626         scrub_check_status 6 scanning
627
628         scrub_stop 7
629
630         scrub_check_status 8 stopped
631
632         scrub_start 9
633
634         scrub_check_status 10 scanning
635
636         for n in $(seq $MDSCOUNT); do
637                 do_facet mds$n $LCTL set_param fail_loc=0
638                 do_facet mds$n $LCTL set_param fail_val=0
639         done
640         sleep 5
641         scrub_check_status 11 completed
642
643         scrub_check_flags 12 ""
644 }
645 run_test 8 "Control OI scrub manually"
646
647 test_9() {
648         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
649                 skip "Testing on UP system, the speed may be inaccurate."
650                 return 0
651         fi
652
653         scrub_prep 8000
654         scrub_backup_restore 1
655
656         echo "starting MDTs with OI scrub disabled"
657         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
658
659         scrub_check_status 3 init
660
661         scrub_check_flags 4 inconsistent
662
663         local BASE_SPEED1=100
664         local RUN_TIME1=10
665         # OI scrub should run with full speed under inconsistent case
666         scrub_start 5 -s $BASE_SPEED1
667
668         sleep $RUN_TIME1
669         scrub_check_status 6 completed
670
671         scrub_check_flags 7 ""
672
673         # OI scrub should run with limited speed under non-inconsistent case
674         scrub_start 8 -s $BASE_SPEED1 -r
675
676         sleep $RUN_TIME1
677         scrub_check_status 9 scanning
678
679         # Do NOT ignore that there are 1024 pre-fetched items. And there
680         # may be time error, normally it should be less than 2 seconds.
681         # We allow another 20% schedule error.
682         local PRE_FETCHED=1024
683         local TIME_DIFF=2
684         # MAX_MARGIN = 1.2 = 12 / 10
685         local MAX_SPEED=$(((PRE_FETCHED + BASE_SPEED1 * \
686                 (RUN_TIME1 + TIME_DIFF)) / RUN_TIME1 * 12 / 10))
687         local n
688         for n in $(seq $MDSCOUNT); do
689                 local SPEED=$(scrub_status $n | \
690                         awk '/^average_speed/ { print $2 }')
691                 [ $SPEED -lt $MAX_SPEED ] ||
692                         error "(10) Got speed $SPEED, expected less than" \
693                                 "$MAX_SPEED"
694         done
695
696         # adjust speed limit
697         local BASE_SPEED2=300
698         local RUN_TIME2=10
699         for n in $(seq $MDSCOUNT); do
700                 do_facet mds$n $LCTL set_param -n \
701                         mdd.$(facet_svc mds$n).lfsck_speed_limit $BASE_SPEED2
702         done
703         sleep $RUN_TIME2
704
705         # MIN_MARGIN = 0.8 = 8 / 10
706         local MIN_SPEED=$(((PRE_FETCHED + \
707                             BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
708                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
709                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
710         # MAX_MARGIN = 1.2 = 12 / 10
711         MAX_SPEED=$(((PRE_FETCHED + \
712                       BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
713                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
714                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
715         for n in $(seq $MDSCOUNT); do
716                 SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }')
717                 [ $SPEED -gt $MIN_SPEED ] ||
718                         error "(11) Got speed $SPEED, expected more than" \
719                                 "$MIN_SPEED"
720                 [ $SPEED -lt $MAX_SPEED ] ||
721                         error "(12) Got speed $SPEED, expected less than" \
722                                 "$MAX_SPEED"
723
724                 do_facet mds$n $LCTL set_param -n \
725                                 mdd.$(facet_svc mds$n).lfsck_speed_limit 0
726         done
727         sleep 6
728         scrub_check_status 13 completed
729 }
730 run_test 9 "OI scrub speed control"
731
732 test_10a() {
733         scrub_prep 0
734         scrub_backup_restore 1
735
736         echo "starting mds$n with OI scrub disabled"
737         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
738
739         scrub_check_status 3 init
740
741         scrub_check_flags 4 inconsistent
742
743         mount_client $MOUNT || error "(5) Fail to start client!"
744
745         scrub_enable_auto
746         local n
747         for n in $(seq $MDSCOUNT); do
748                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
749                 do_facet mds$n $LCTL set_param fail_val=1
750                 do_facet mds$n $LCTL set_param fail_loc=0x190
751         done
752         scrub_check_data 6
753
754         scrub_check_status 7 scanning
755
756         umount_client $MOUNT || error "(8) Fail to stop client!"
757
758         scrub_stop_mds 9
759
760         echo "starting MDTs with OI scrub disabled"
761         scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB"
762
763         scrub_check_status 11 paused
764
765         scrub_stop_mds 12
766
767         echo "starting MDTs without disabling OI scrub"
768         scrub_start_mds 13 "$MOUNT_OPTS_SCRUB"
769
770         scrub_check_status 14 scanning
771
772         for n in $(seq $MDSCOUNT); do
773                 do_facet mds$n $LCTL set_param fail_loc=0
774                 do_facet mds$n $LCTL set_param fail_val=0
775         done
776         sleep 5
777         scrub_check_status 15 completed
778
779         scrub_check_flags 16 ""
780 }
781 run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)"
782
783 # test_10b is obsolete, it will be coverded by related sanity-lfsck tests.
784 test_10b() {
785         scrub_prep 0
786         scrub_backup_restore 1
787
788         echo "starting MDTs with OI scrub disabled"
789         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
790
791         scrub_check_status 3 init
792
793         scrub_check_flags 4 inconsistent
794
795         local n
796         for n in $(seq $MDSCOUNT); do
797                 #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
798                 do_facet mds$n $LCTL set_param fail_val=3
799                 do_facet mds$n $LCTL set_param fail_loc=0x190
800         done
801
802         scrub_start 5
803
804         scrub_check_status 6 scanning
805
806         scrub_stop_mds 7
807
808         echo "starting MDTs with OI scrub disabled"
809         scrub_start_mds 8 "$MOUNT_OPTS_NOSCRUB"
810
811         scrub_check_status 9 paused
812
813         scrub_stop_mds 10
814
815         echo "starting MDTs without disabling OI scrub"
816         scrub_start_mds 11 "$MOUNT_OPTS_SCRUB"
817
818         scrub_check_status 12 scanning
819
820         for n in $(seq $MDSCOUNT); do
821                 do_facet mds$n $LCTL set_param fail_loc=0
822                 do_facet mds$n $LCTL set_param fail_val=0
823         done
824         sleep 5
825         scrub_check_status 13 completed
826
827         scrub_check_flags 14 ""
828 }
829 #run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)"
830
831 test_11() {
832         echo "stopall"
833         stopall > /dev/null
834         echo "formatall"
835         formatall > /dev/null
836         echo "setupall"
837         setupall > /dev/null
838
839         local CREATED=100
840         local tname=`date +%s`
841         rm -rf $MOUNT/$tname > /dev/null
842         mkdir -p $MOUNT/$tname || error "(0) Failed to create $MOUNT/$tname"
843         local n
844         for n in $(seq $MDSCOUNT); do
845                 $LFS mkdir -i $((n - 1)) $MOUNT/$tname/mds$n ||
846                         error "(1) Fail to mkdir $MOUNT/$tname/mds$n"
847
848                 createmany -o $MOUNT/$tname/mds$n/f $CREATED ||
849                         error "(2) Fail to create in $tname/mds$n"
850         done
851
852         cleanup_mount $MOUNT
853         do_facet $SINGLEMDS $LCTL clear
854         start_full_debug_logging
855         # reset OI scrub start point by force
856         scrub_start 3 -r
857         sleep 3
858         scrub_check_status 4 completed
859
860         # OI scrub should skip the new created objects for the first accessing
861         # notice we're creating a new llog for every OST on every startup
862         # new features can make this even less stable, so we only check
863         # that the number of skipped files is less than 2x the number of files
864         local MAXIMUM=$((CREATED * 2))
865         local MINIMUM=$((CREATED + 1)) # files + directory
866         for n in $(seq $MDSCOUNT); do
867                 local SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
868                 [ $SKIPPED -ge $MAXIMUM -o $SKIPPED -lt $MINIMUM ] &&
869                         error "(5) Expect [ $MINIMUM , $MAXIMUM ) objects" \
870                                 "skipped on mds$n, but got $SKIPPED"
871         done
872
873         # reset OI scrub start point by force
874         scrub_start -r
875         sleep 3
876         scrub_check_status 7 completed
877
878         # OI scrub should skip the new created object only once
879         for n in $(seq $MDSCOUNT); do
880                 SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }')
881                 [ $SKIPPED -eq 0 ] ||
882                         error "(8) Expect 0 objects skipped on mds$n, but" \
883                                 "got $SKIPPED"
884         done
885
886         stop_full_debug_logging
887         restore_mount $MOUNT || error "(9) Fail to start client!"
888         rm -rf $MOUNT/$tname > /dev/null
889 }
890 run_test 11 "OI scrub skips the new created objects only once"
891
892 test_12() {
893         echo "stopall"
894         stopall > /dev/null
895         echo "formatall"
896         formatall > /dev/null
897         echo "setupall"
898         setupall > /dev/null
899
900         mkdir -p $DIR/$tdir
901         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
902
903         #define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY               0x195
904         do_facet ost1 $LCTL set_param fail_loc=0x195
905         createmany -o $DIR/$tdir/f 1000
906
907         echo "stopall"
908         stopall > /dev/null
909         echo "setupall"
910         setupall > /dev/null
911
912         do_facet ost1 $LCTL set_param fail_loc=0
913         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
914         [ "$STATUS" == "init" ] ||
915                 error "(1) Expect 'init', but got '$STATUS'"
916
917         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
918
919         sleep 3
920         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
921         [ "$STATUS" == "completed" ] ||
922                 error "(3) Expect 'completed', but got '$STATUS'"
923
924         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(4) ls should succeed"
925 }
926 run_test 12 "OI scrub can rebuild invalid /O entries"
927
928 test_13() {
929         echo "stopall"
930         stopall > /dev/null
931         echo "formatall"
932         formatall > /dev/null
933         echo "setupall"
934         setupall > /dev/null
935
936         mkdir -p $DIR/$tdir
937         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
938
939         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
940         do_facet ost1 $LCTL set_param fail_loc=0x196
941         createmany -o $DIR/$tdir/f 1000
942         do_facet ost1 $LCTL set_param fail_loc=0
943
944         echo "stopall"
945         stopall > /dev/null
946         echo "setupall"
947         setupall > /dev/null
948
949         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
950         [ "$STATUS" == "init" ] ||
951                 error "(1) Expect 'init', but got '$STATUS'"
952
953         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
954
955         $START_SCRUB_ON_OST || error "(3) Fail to start OI scrub on OST!"
956         sleep 3
957         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
958         [ "$STATUS" == "completed" ] ||
959                 error "(4) Expect 'completed', but got '$STATUS'"
960
961         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(5) ls should succeed"
962 }
963 run_test 13 "OI scrub can rebuild missed /O entries"
964
965 test_14() {
966         echo "stopall"
967         stopall > /dev/null
968         echo "formatall"
969         formatall > /dev/null
970         echo "setupall"
971         setupall > /dev/null
972
973         mkdir -p $DIR/$tdir
974         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
975
976         #define OBD_FAIL_OSD_COMPAT_NO_ENTRY            0x196
977         do_facet ost1 $LCTL set_param fail_loc=0x196
978         createmany -o $DIR/$tdir/f 64
979         do_facet ost1 $LCTL set_param fail_loc=0
980
981         echo "stopall"
982         stopall > /dev/null
983         echo "setupall"
984         setupall > /dev/null
985
986         local STATUS=$($SHOW_SCRUB_ON_OST | awk '/^status/ { print $2 }')
987         [ "$STATUS" == "init" ] ||
988                 error "(1) Expect 'init', but got '$STATUS'"
989
990         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(2) ls should fail"
991
992         echo "stopall"
993         stopall > /dev/null
994
995         echo "run e2fsck"
996         run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" ||
997                 error "(3) Fail to run e2fsck error"
998
999         echo "setupall"
1000         setupall > /dev/null
1001
1002         local LF_REPAIRED=$($SHOW_SCRUB_ON_OST |
1003                             awk '/^lf_reparied/ { print $2 }')
1004         [ $LF_REPAIRED -gt 0 ] ||
1005                 error "(4) Some entry under /lost+found should be repaired"
1006
1007         ls -ail $DIR/$tdir > /dev/null 2>&1 || error "(5) ls should succeed"
1008 }
1009 run_test 14 "OI scrub can repair objects under lost+found"
1010
1011 test_15() {
1012         # skip test_15 for LU-4182
1013         [ $MDSCOUNT -ge 2 ] && skip "skip now for >= 2 MDTs" && return
1014         scrub_prep 20
1015         scrub_backup_restore 1
1016         echo "starting MDTs with OI scrub disabled"
1017         scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
1018         scrub_check_status 3 init
1019         scrub_check_flags 4 inconsistent
1020
1021         # run under dryrun mode
1022         scrub_start 5 -n on
1023         sleep 3
1024         scrub_check_status 6 completed
1025         scrub_check_flags 7 inconsistent
1026         scrub_check_params 8 dryrun
1027         scrub_check_repaired 9 20
1028
1029         # run under dryrun mode again
1030         scrub_start 10 -n on
1031         sleep 3
1032         scrub_check_status 11 completed
1033         scrub_check_flags 12 inconsistent
1034         scrub_check_params 13 dryrun
1035         scrub_check_repaired 14 20
1036
1037         # run under normal mode
1038         scrub_start 15 -n off
1039         sleep 3
1040         scrub_check_status 16 completed
1041         scrub_check_flags 17 ""
1042         scrub_check_params 18 ""
1043         scrub_check_repaired 19 20
1044
1045         # run under normal mode again
1046         scrub_start 20 -n off
1047         sleep 3
1048         scrub_check_status 21 completed
1049         scrub_check_flags 22 ""
1050         scrub_check_params 23 ""
1051         scrub_check_repaired 24 0
1052 }
1053 run_test 15 "Dryrun mode OI scrub"
1054
1055 # restore MDS/OST size
1056 MDSSIZE=${SAVED_MDSSIZE}
1057 OSTSIZE=${SAVED_OSTSIZE}
1058
1059 # cleanup the system at last
1060 formatall
1061
1062 complete $SECONDS
1063 exit_status