Whamcloud - gitweb
LU-1866 lfsck: FID-in-{dirent,LMA} check and repair
[fs/lustre-release.git] / lustre / tests / sanity-lfsck.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_LFSCK_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 [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
21         skip "test LFSCK only for ldiskfs" && exit 0
22 require_dsh_mds || exit 0
23
24 MCREATE=${MCREATE:-mcreate}
25 SAVED_MDSSIZE=${MDSSIZE}
26 SAVED_OSTSIZE=${OSTSIZE}
27 # use small MDS + OST size to speed formatting time
28 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
29 MDSSIZE=100000
30 OSTSIZE=100000
31
32 check_and_setup_lustre
33 build_test_filter
34
35 $LCTL set_param debug=+lfsck > /dev/null || true
36
37 MDT_DEV="${FSNAME}-MDT0000"
38 MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/})
39 START_NAMESPACE="do_facet $SINGLEMDS \
40                 $LCTL lfsck_start -M ${MDT_DEV} -t namespace"
41 STOP_LFSCK="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
42 SHOW_NAMESPACE="do_facet $SINGLEMDS \
43                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_namespace"
44 MOUNT_OPTS_SCRUB="-o user_xattr"
45 MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
46
47 lfsck_prep() {
48         local ndirs=$1
49         local nfiles=$2
50
51         echo "formatall"
52         formatall > /dev/null
53
54         echo "setupall"
55         setupall > /dev/null
56
57         echo "preparing... ${nfiles} * ${ndirs} files will be created."
58         mkdir -p $DIR/$tdir
59         cp $LUSTRE/tests/*.sh $DIR/$tdir/
60         for ((i=0; i<${ndirs}; i++)); do
61                 mkdir $DIR/$tdir/d${i}
62                 touch $DIR/$tdir/f${i}
63                 for ((j=0; j<${nfiles}; j++)); do
64                         touch $DIR/$tdir/d${i}/f${j}
65                 done
66                 mkdir $DIR/$tdir/e${i}
67         done
68
69         echo "prepared."
70         cleanup_mount $MOUNT > /dev/null || error "Fail to stop client!"
71         echo "stop $SINGLEMDS"
72         stop $SINGLEMDS > /dev/null || error "Fail to stop MDS!"
73 }
74
75 test_0() {
76         lfsck_prep 10 10
77         echo "start $SINGLEMDS"
78         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
79                 error "(1) Fail to start MDS!"
80
81         #define OBD_FAIL_LFSCK_DELAY1           0x1600
82         do_facet $SINGLEMDS $LCTL set_param fail_val=3
83         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
84         $START_NAMESPACE || error "(2) Fail to start LFSCK for namespace!"
85
86         $SHOW_NAMESPACE || error "Fail to monitor LFSCK (3)"
87
88         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
89         [ "$STATUS" == "scanning-phase1" ] ||
90                 error "(4) Expect 'scanning-phase1', but got '$STATUS'"
91
92         $STOP_LFSCK || error "(5) Fail to stop LFSCK!"
93
94         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
95         [ "$STATUS" == "stopped" ] ||
96                 error "(6) Expect 'stopped', but got '$STATUS'"
97
98         $START_NAMESPACE || error "(7) Fail to start LFSCK for namespace!"
99
100         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
101         [ "$STATUS" == "scanning-phase1" ] ||
102                 error "(8) Expect 'scanning-phase1', but got '$STATUS'"
103
104         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
105         do_facet $SINGLEMDS $LCTL set_param fail_val=0
106         sleep 3
107         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
108         [ "$STATUS" == "completed" ] ||
109                 error "(9) Expect 'completed', but got '$STATUS'"
110
111         local repaired=$($SHOW_NAMESPACE |
112                          awk '/^updated_phase1/ { print $2 }')
113         [ $repaired -eq 0 ] ||
114                 error "(10) Expect nothing to be repaired, but got: $repaired"
115 }
116 run_test 0 "Control LFSCK manually"
117
118 test_1a() {
119         lfsck_prep 1 1
120         echo "start $SINGLEMDS"
121         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
122                 error "(1) Fail to start MDS!"
123
124         mount_client $MOUNT || error "(2) Fail to start client!"
125
126         #define OBD_FAIL_FID_INDIR      0x1501
127         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1501
128         touch $DIR/$tdir/dummy
129
130         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
131         umount_client $MOUNT
132         $START_NAMESPACE || error "(3) Fail to start LFSCK for namespace!"
133
134         sleep 3
135         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
136         [ "$STATUS" == "completed" ] ||
137                 error "(4) Expect 'completed', but got '$STATUS'"
138
139         local repaired=$($SHOW_NAMESPACE |
140                          awk '/^updated_phase1/ { print $2 }')
141         [ $repaired -eq 1 ] ||
142                 error "(5) Fail to repair crashed FID-in-dirent: $repaired"
143
144         mount_client $MOUNT || error "(6) Fail to start client!"
145
146         #define OBD_FAIL_FID_LOOKUP     0x1505
147         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
148         ls $DIR/$tdir/ > /dev/null || error "(7) no FID-in-dirent."
149
150         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
151 }
152 run_test 1a "LFSCK can find out and repair crashed FID-in-dirent"
153
154 test_1b()
155 {
156         lfsck_prep 1 1
157         echo "start $SINGLEMDS"
158         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
159                 error "(1) Fail to start MDS!"
160
161         mount_client $MOUNT || error "(2) Fail to start client!"
162
163         #define OBD_FAIL_FID_INLMA      0x1502
164         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1502
165         touch $DIR/$tdir/dummy
166
167         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
168         umount_client $MOUNT
169         #define OBD_FAIL_FID_NOLMA      0x1506
170         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1506
171         $START_NAMESPACE || error "(3) Fail to start LFSCK for namespace!"
172
173         sleep 3
174         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
175         [ "$STATUS" == "completed" ] ||
176                 error "(4) Expect 'completed', but got '$STATUS'"
177
178         local repaired=$($SHOW_NAMESPACE |
179                          awk '/^updated_phase1/ { print $2 }')
180         [ $repaired -eq 1 ] ||
181                 error "(5) Fail to repair missed FID-in-LMA: $repaired"
182
183         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
184         mount_client $MOUNT || error "(6) Fail to start client!"
185
186         #define OBD_FAIL_FID_LOOKUP     0x1505
187         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
188         stat $DIR/$tdir/dummy > /dev/null || error "(7) no FID-in-LMA."
189
190         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
191 }
192 run_test 1b "LFSCK can find out and repair missed FID-in-LMA"
193
194 test_4()
195 {
196         lfsck_prep 3 3
197         mds_backup_restore || error "(1) Fail to backup/restore!"
198         echo "start $SINGLEMDS with disabling OI scrub"
199         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
200                 error "(2) Fail to start MDS!"
201
202         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
203         [ "$STATUS" == "init" ] ||
204                 error "(3) Expect 'init', but got '$STATUS'"
205
206         #define OBD_FAIL_LFSCK_DELAY2           0x1601
207         do_facet $SINGLEMDS $LCTL set_param fail_val=1
208         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
209         $START_NAMESPACE || error "(4) Fail to start LFSCK for namespace!"
210
211         sleep 5
212         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
213         [ "$STATUS" == "scanning-phase1" ] ||
214                 error "(5) Expect 'scanning-phase1', but got '$STATUS'"
215
216         local FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
217         [ "$FLAGS" == "inconsistent" ] ||
218                 error "(6) Expect 'inconsistent', but got '$FLAGS'"
219
220         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
221         do_facet $SINGLEMDS $LCTL set_param fail_val=0
222         sleep 3
223         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
224         [ "$STATUS" == "completed" ] ||
225                 error "(7) Expect 'completed', but got '$STATUS'"
226
227         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
228         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
229
230         local repaired=$($SHOW_NAMESPACE |
231                          awk '/^updated_phase1/ { print $2 }')
232         [ $repaired -ge 9 ] ||
233                 error "(9) Fail to repair crashed linkEA: $repaired"
234
235         mount_client $MOUNT || error "(10) Fail to start client!"
236
237         #define OBD_FAIL_FID_LOOKUP     0x1505
238         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
239         ls $DIR/$tdir/ > /dev/null || error "(11) no FID-in-dirent."
240
241         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
242 }
243 run_test 4 "FID-in-dirent can be rebuilt after MDT file-level backup/restore"
244
245 test_6a() {
246         lfsck_prep 10 10
247         echo "start $SINGLEMDS"
248         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
249                 error "(1) Fail to start MDS!"
250
251         #define OBD_FAIL_LFSCK_DELAY1           0x1600
252         do_facet $SINGLEMDS $LCTL set_param fail_val=1
253         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
254         $START_NAMESPACE || error "(2) Fail to start LFSCK for namespace!"
255
256         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
257         [ "$STATUS" == "scanning-phase1" ] ||
258                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
259
260         # Sleep 3 sec to guarantee at least one object processed by LFSCK
261         sleep 3
262         # Fail the LFSCK to guarantee there is at least one checkpoint
263         #define OBD_FAIL_LFSCK_FATAL1           0x1608
264         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001608
265         sleep 3
266         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
267         [ "$STATUS" == "failed" ] ||
268                 error "(4) Expect 'failed', but got '$STATUS'"
269
270         local POSITION0=$($SHOW_NAMESPACE |
271                           awk '/^last_checkpoint_position/ { print $2 }' |
272                           tr -d ',')
273
274         #define OBD_FAIL_LFSCK_DELAY1           0x1600
275         do_facet $SINGLEMDS $LCTL set_param fail_val=1
276         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
277         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
278
279         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
280         [ "$STATUS" == "scanning-phase1" ] ||
281                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
282
283         local POSITION1=$($SHOW_NAMESPACE |
284                           awk '/^latest_start_position/ { print $2 }' |
285                           tr -d ',')
286         [ $POSITION0 -lt $POSITION1 ] ||
287                 error "(7) Expect larger than: $POSITION0, but got $POSITION1"
288
289         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
290         do_facet $SINGLEMDS $LCTL set_param fail_val=0
291         sleep 3
292         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
293         [ "$STATUS" == "completed" ] ||
294                 error "(8) Expect 'completed', but got '$STATUS'"
295 }
296 run_test 6a "LFSCK resumes from last checkpoint (1)"
297
298 test_6b() {
299         lfsck_prep 10 10
300         echo "start $SINGLEMDS"
301         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
302                 error "(1) Fail to start MDS!"
303
304         #define OBD_FAIL_LFSCK_DELAY2           0x1601
305         do_facet $SINGLEMDS $LCTL set_param fail_val=1
306         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
307         $START_NAMESPACE || error "(2) Fail to start LFSCK for namespace!"
308
309         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
310         [ "$STATUS" == "scanning-phase1" ] ||
311                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
312
313         # Sleep 3 sec to guarantee at least one object processed by LFSCK
314         sleep 3
315         # Fail the LFSCK to guarantee there is at least one checkpoint
316         #define OBD_FAIL_LFSCK_FATAL2           0x1609
317         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
318         sleep 3
319         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
320         [ "$STATUS" == "failed" ] ||
321                 error "(4) Expect 'failed', but got '$STATUS'"
322
323         local POSITION0=$($SHOW_NAMESPACE |
324                           awk '/^last_checkpoint_position/ { print $4 }')
325
326         #define OBD_FAIL_LFSCK_DELAY2           0x1601
327         do_facet $SINGLEMDS $LCTL set_param fail_val=1
328         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
329         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
330
331         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
332         [ "$STATUS" == "scanning-phase1" ] ||
333                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
334
335         local POSITION1=$($SHOW_NAMESPACE |
336                           awk '/^latest_start_position/ { print $4 }')
337         if [ $POSITION0 -gt $POSITION1 ]; then
338                 [ $POSITION1 -eq 0 -a $POSITINO0 -eq $((POSITION1 + 1)) ] ||
339                 error "(7) Expect larger than: $POSITION0, but got $POSITION1"
340         fi
341
342         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
343         do_facet $SINGLEMDS $LCTL set_param fail_val=0
344         sleep 3
345         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
346         [ "$STATUS" == "completed" ] ||
347                 error "(8) Expect 'completed', but got '$STATUS'"
348 }
349 run_test 6b "LFSCK resumes from last checkpoint (2)"
350
351 test_7a()
352 {
353         lfsck_prep 10 10
354         echo "start $SINGLEMDS"
355         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
356                 error "(1) Fail to start MDS!"
357
358         #define OBD_FAIL_LFSCK_DELAY2           0x1601
359         do_facet $SINGLEMDS $LCTL set_param fail_val=1
360         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
361         $START_NAMESPACE || error "(2) Fail to start LFSCK for namespace!"
362
363         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
364         [ "$STATUS" == "scanning-phase1" ] ||
365                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
366
367         # Sleep 3 sec to guarantee at least one object processed by LFSCK
368         sleep 3
369         echo "stop $SINGLEMDS"
370         stop $SINGLEMDS > /dev/null || error "(4) Fail to stop MDS!"
371
372         echo "start $SINGLEMDS"
373         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
374                 error "(5) Fail to start MDS!"
375
376         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
377         [ "$STATUS" == "scanning-phase1" ] ||
378                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
379
380         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
381         do_facet $SINGLEMDS $LCTL set_param fail_val=0
382         sleep 3
383         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
384         [ "$STATUS" == "completed" ] ||
385                 error "(7) Expect 'completed', but got '$STATUS'"
386 }
387 run_test 7a "non-stopped LFSCK should auto restarts after MDS remount (1)"
388
389 test_9a() {
390         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
391                 skip "Testing on UP system, the speed may be inaccurate."
392                 return 0
393         fi
394
395         lfsck_prep 70 70
396         echo "start $SINGLEMDS"
397         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
398                 error "(1) Fail to start MDS!"
399
400         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
401         [ "$STATUS" == "init" ] ||
402                 error "(2) Expect 'init', but got '$STATUS'"
403
404         $START_NAMESPACE -s 100 || error "(3) Fail to start LFSCK!"
405
406         sleep 10
407         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
408         [ "$STATUS" == "scanning-phase1" ] ||
409                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
410
411         local SPEED=$($SHOW_NAMESPACE |
412                       awk '/^average_speed_phase1/ { print $2 }')
413         # (100 * (10 + 1)) / 10 = 110
414         [ $SPEED -lt 120 ] ||
415                 error "(4) Unexpected speed $SPEED, should not more than 120"
416
417         # adjust speed limit
418         do_facet $SINGLEMDS \
419                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 300
420         sleep 10
421
422         SPEED=$($SHOW_NAMESPACE | awk '/^average_speed_phase1/ { print $2 }')
423         # (100 * (10 - 1) + 300 * (10 - 1)) / 20 = 180
424         [ $SPEED -lt 170 ] &&
425                 error "(5) Unexpected speed $SPEED, should not less than 170"
426
427         # (100 * (10 + 1) + 300 * (10 + 1)) / 20 = 220
428         [ $SPEED -lt 230 ] ||
429                 error "(6) Unexpected speed $SPEED, should not more than 230"
430
431         do_facet $SINGLEMDS \
432                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
433         sleep 5
434         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
435         [ "$STATUS" == "completed" ] ||
436                 error "(7) Expect 'completed', but got '$STATUS'"
437 }
438 run_test 9a "LFSCK speed control (1)"
439
440 $LCTL set_param debug=-lfsck > /dev/null || true
441
442 # restore MDS/OST size
443 MDSSIZE=${SAVED_MDSSIZE}
444 OSTSIZE=${SAVED_OSTSIZE}
445
446 # cleanup the system at last
447 formatall
448
449 complete $SECONDS
450 exit_status