Whamcloud - gitweb
bb11656c9f6aea89d83d0cd9aa457fc28f974cf2
[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 require_dsh_mds || exit 0
21
22 MCREATE=${MCREATE:-mcreate}
23 SAVED_MDSSIZE=${MDSSIZE}
24 SAVED_OSTSIZE=${OSTSIZE}
25 SAVED_OSTCOUNT=${OSTCOUNT}
26 # use small MDS + OST size to speed formatting time
27 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
28 MDSSIZE=100000
29 OSTSIZE=100000
30 # no need too much OSTs, to reduce the format/start/stop overhead
31 [ $OSTCOUNT -gt 4 ] && OSTCOUNT=4
32
33 # build up a clean test environment.
34 formatall
35 setupall
36
37 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.60) ]] &&
38         skip "Need MDS version at least 2.3.60" && check_and_cleanup_lustre &&
39         exit 0
40
41 [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.4.90) ]] &&
42         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2c"
43
44 [[ $(lustre_version_code ost1) -lt $(version_code 2.5.55) ]] &&
45         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 11 12 13 14 15 16 17 18 19"
46
47 build_test_filter
48
49 $LCTL set_param debug=+lfsck > /dev/null || true
50
51 MDT_DEV="${FSNAME}-MDT0000"
52 OST_DEV="${FSNAME}-OST0000"
53 MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/})
54 START_NAMESPACE="do_facet $SINGLEMDS \
55                 $LCTL lfsck_start -M ${MDT_DEV} -t namespace"
56 START_LAYOUT="do_facet $SINGLEMDS \
57                 $LCTL lfsck_start -M ${MDT_DEV} -t layout"
58 START_LAYOUT_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV} -t layout"
59 STOP_LFSCK="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
60 SHOW_NAMESPACE="do_facet $SINGLEMDS \
61                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_namespace"
62 SHOW_LAYOUT="do_facet $SINGLEMDS \
63                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_layout"
64 SHOW_LAYOUT_ON_OST="do_facet ost1 \
65                 $LCTL get_param -n obdfilter.${OST_DEV}.lfsck_layout"
66 MOUNT_OPTS_SCRUB="-o user_xattr"
67 MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
68
69 lfsck_prep() {
70         local ndirs=$1
71         local nfiles=$2
72         local igif=$3
73
74         check_mount_and_prep
75
76         echo "preparing... $nfiles * $ndirs files will be created $(date)."
77         if [ ! -z $igif ]; then
78                 #define OBD_FAIL_FID_IGIF       0x1504
79                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1504
80         fi
81
82         cp $LUSTRE/tests/*.sh $DIR/$tdir/
83         if [ $ndirs -gt 0 ]; then
84                 createmany -d $DIR/$tdir/d $ndirs
85                 createmany -m $DIR/$tdir/f $ndirs
86                 if [ $nfiles -gt 0 ]; then
87                         for ((i = 0; i < $ndirs; i++)); do
88                                 createmany -m $DIR/$tdir/d${i}/f $nfiles > \
89                                         /dev/null || error "createmany $nfiles"
90                         done
91                 fi
92                 createmany -d $DIR/$tdir/e $ndirs
93         fi
94
95         if [ ! -z $igif ]; then
96                 touch $DIR/$tdir/dummy
97                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0
98         fi
99
100         echo "prepared $(date)."
101 }
102
103 test_0() {
104         lfsck_prep 3 3
105
106         #define OBD_FAIL_LFSCK_DELAY1           0x1600
107         do_facet $SINGLEMDS $LCTL set_param fail_val=3 fail_loc=0x1600
108         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
109
110         $SHOW_NAMESPACE || error "Fail to monitor LFSCK (3)"
111
112         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
113         [ "$STATUS" == "scanning-phase1" ] ||
114                 error "(4) Expect 'scanning-phase1', but got '$STATUS'"
115
116         $STOP_LFSCK || error "(5) Fail to stop LFSCK!"
117
118         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
119         [ "$STATUS" == "stopped" ] ||
120                 error "(6) Expect 'stopped', but got '$STATUS'"
121
122         $START_NAMESPACE || error "(7) Fail to start LFSCK for namespace!"
123
124         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
125         [ "$STATUS" == "scanning-phase1" ] ||
126                 error "(8) Expect 'scanning-phase1', but got '$STATUS'"
127
128         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
129         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
130                 mdd.${MDT_DEV}.lfsck_namespace |
131                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
132                 $SHOW_NAMESPACE
133                 error "(9) unexpected status"
134         }
135
136         local repaired=$($SHOW_NAMESPACE |
137                          awk '/^updated_phase1/ { print $2 }')
138         [ $repaired -eq 0 ] ||
139                 error "(10) Expect nothing to be repaired, but got: $repaired"
140
141         local scanned1=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
142         $START_NAMESPACE -r || error "(11) Fail to reset LFSCK!"
143         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
144                 mdd.${MDT_DEV}.lfsck_namespace |
145                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
146                 $SHOW_NAMESPACE
147                 error "(12) unexpected status"
148         }
149
150         local scanned2=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
151         [ $((scanned1 + 1)) -eq $scanned2 ] ||
152                 error "(13) Expect success $((scanned1 + 1)), but got $scanned2"
153
154         echo "stopall, should NOT crash LU-3649"
155         stopall || error "(14) Fail to stopall"
156 }
157 run_test 0 "Control LFSCK manually"
158
159 test_1a() {
160         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
161                 skip "OI Scrub not implemented for ZFS" && return
162
163         lfsck_prep 1 1
164
165         #define OBD_FAIL_FID_INDIR      0x1501
166         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1501
167         touch $DIR/$tdir/dummy
168
169         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
170         umount_client $MOUNT
171         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
172         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
173                 mdd.${MDT_DEV}.lfsck_namespace |
174                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
175                 $SHOW_NAMESPACE
176                 error "(4) unexpected status"
177         }
178
179         local repaired=$($SHOW_NAMESPACE |
180                          awk '/^dirent_repaired/ { print $2 }')
181         # for interop with old server
182         [ -z "$repaired" ] &&
183                 repaired=$($SHOW_NAMESPACE |
184                          awk '/^updated_phase1/ { print $2 }')
185
186         [ $repaired -eq 1 ] ||
187                 error "(5) Fail to repair crashed FID-in-dirent: $repaired"
188
189         mount_client $MOUNT || error "(6) Fail to start client!"
190
191         #define OBD_FAIL_FID_LOOKUP     0x1505
192         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
193         ls $DIR/$tdir/ > /dev/null || error "(7) no FID-in-dirent."
194
195         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
196 }
197 run_test 1a "LFSCK can find out and repair crashed FID-in-dirent"
198
199 test_1b()
200 {
201         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
202                 skip "OI Scrub not implemented for ZFS" && return
203
204         lfsck_prep 1 1
205
206         #define OBD_FAIL_FID_INLMA      0x1502
207         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1502
208         touch $DIR/$tdir/dummy
209
210         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
211         umount_client $MOUNT
212         #define OBD_FAIL_FID_NOLMA      0x1506
213         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1506
214         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
215         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
216                 mdd.${MDT_DEV}.lfsck_namespace |
217                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
218                 $SHOW_NAMESPACE
219                 error "(4) unexpected status"
220         }
221
222         local repaired=$($SHOW_NAMESPACE |
223                          awk '/^dirent_repaired/ { print $2 }')
224         # for interop with old server
225         [ -z "$repaired" ] &&
226                 repaired=$($SHOW_NAMESPACE |
227                          awk '/^updated_phase1/ { print $2 }')
228
229         [ $repaired -eq 1 ] ||
230                 error "(5) Fail to repair missed FID-in-LMA: $repaired"
231
232         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
233         mount_client $MOUNT || error "(6) Fail to start client!"
234
235         #define OBD_FAIL_FID_LOOKUP     0x1505
236         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
237         stat $DIR/$tdir/dummy > /dev/null || error "(7) no FID-in-LMA."
238
239         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
240 }
241 run_test 1b "LFSCK can find out and repair missed FID-in-LMA"
242
243 test_2a() {
244         lfsck_prep 1 1
245
246         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
247         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
248         touch $DIR/$tdir/dummy
249
250         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
251         umount_client $MOUNT
252         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
253         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
254                 mdd.${MDT_DEV}.lfsck_namespace |
255                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
256                 $SHOW_NAMESPACE
257                 error "(4) unexpected status"
258         }
259
260         local repaired=$($SHOW_NAMESPACE |
261                          awk '/^linkea_repaired/ { print $2 }')
262         # for interop with old server
263         [ -z "$repaired" ] &&
264                 repaired=$($SHOW_NAMESPACE |
265                          awk '/^updated_phase1/ { print $2 }')
266
267         [ $repaired -eq 1 ] ||
268                 error "(5) Fail to repair crashed linkEA: $repaired"
269
270         mount_client $MOUNT || error "(6) Fail to start client!"
271
272         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
273                 error "(7) Fail to stat $DIR/$tdir/dummy"
274
275         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
276         local dummyname=$($LFS fid2path $DIR $dummyfid)
277         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
278                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
279 }
280 run_test 2a "LFSCK can find out and repair crashed linkEA entry"
281
282 test_2b()
283 {
284         lfsck_prep 1 1
285
286         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
287         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
288         touch $DIR/$tdir/dummy
289
290         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
291         umount_client $MOUNT
292         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
293         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
294                 mdd.${MDT_DEV}.lfsck_namespace |
295                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
296                 $SHOW_NAMESPACE
297                 error "(4) unexpected status"
298         }
299
300         local repaired=$($SHOW_NAMESPACE |
301                          awk '/^updated_phase2/ { print $2 }')
302         [ $repaired -eq 1 ] ||
303                 error "(5) Fail to repair crashed linkEA: $repaired"
304
305         mount_client $MOUNT || error "(6) Fail to start client!"
306
307         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
308                 error "(7) Fail to stat $DIR/$tdir/dummy"
309
310         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
311         local dummyname=$($LFS fid2path $DIR $dummyfid)
312         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
313                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
314 }
315 run_test 2b "LFSCK can find out and remove invalid linkEA entry"
316
317 test_2c()
318 {
319         lfsck_prep 1 1
320
321         #define OBD_FAIL_LFSCK_LINKEA_MORE2     0x1605
322         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1605
323         touch $DIR/$tdir/dummy
324
325         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
326         umount_client $MOUNT
327         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
328         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
329                 mdd.${MDT_DEV}.lfsck_namespace |
330                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
331                 $SHOW_NAMESPACE
332                 error "(4) unexpected status"
333         }
334
335         local repaired=$($SHOW_NAMESPACE |
336                          awk '/^updated_phase2/ { print $2 }')
337         [ $repaired -eq 1 ] ||
338                 error "(5) Fail to repair crashed linkEA: $repaired"
339
340         mount_client $MOUNT || error "(6) Fail to start client!"
341
342         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
343                 error "(7) Fail to stat $DIR/$tdir/dummy"
344
345         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
346         local dummyname=$($LFS fid2path $DIR $dummyfid)
347         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
348                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
349 }
350 run_test 2c "LFSCK can find out and remove repeated linkEA entry"
351
352 test_4()
353 {
354         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
355                 skip "OI Scrub not implemented for ZFS" && return
356
357         lfsck_prep 3 3
358         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
359         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
360
361         mds_backup_restore $SINGLEMDS || error "(1) Fail to backup/restore!"
362         echo "start $SINGLEMDS with disabling OI scrub"
363         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
364                 error "(2) Fail to start MDS!"
365
366         #define OBD_FAIL_LFSCK_DELAY2           0x1601
367         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
368         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
369         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
370                 mdd.${MDT_DEV}.lfsck_namespace |
371                 awk '/^flags/ { print \\\$2 }'" "inconsistent" 6 || {
372                 $SHOW_NAMESPACE
373                 error "(5) unexpected status"
374         }
375
376         local 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 fail_val=0
381         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
382                 mdd.${MDT_DEV}.lfsck_namespace |
383                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
384                 $SHOW_NAMESPACE
385                 error "(7) unexpected status"
386         }
387
388         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
389         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
390
391         local repaired=$($SHOW_NAMESPACE |
392                          awk '/^dirent_repaired/ { print $2 }')
393         # for interop with old server
394         [ -z "$repaired" ] &&
395                 repaired=$($SHOW_NAMESPACE |
396                          awk '/^updated_phase1/ { print $2 }')
397
398         [ $repaired -ge 9 ] ||
399                 error "(9) Fail to re-generate FID-in-dirent: $repaired"
400
401         mount_client $MOUNT || error "(10) Fail to start client!"
402
403         #define OBD_FAIL_FID_LOOKUP     0x1505
404         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
405         ls $DIR/$tdir/ > /dev/null || error "(11) no FID-in-dirent."
406         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
407 }
408 run_test 4 "FID-in-dirent can be rebuilt after MDT file-level backup/restore"
409
410 test_5()
411 {
412         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
413                 skip "OI Scrub not implemented for ZFS" && return
414
415         lfsck_prep 1 1 1
416         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
417         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
418
419         mds_backup_restore $SINGLEMDS 1 || error "(1) Fail to backup/restore!"
420         echo "start $SINGLEMDS with disabling OI scrub"
421         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
422                 error "(2) Fail to start MDS!"
423
424         #define OBD_FAIL_LFSCK_DELAY2           0x1601
425         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
426         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
427         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
428                 mdd.${MDT_DEV}.lfsck_namespace |
429                 awk '/^flags/ { print \\\$2 }'" "inconsistent,upgrade" 6 || {
430                 $SHOW_NAMESPACE
431                 error "(5) unexpected status"
432         }
433
434         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
435         [ "$STATUS" == "scanning-phase1" ] ||
436                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
437
438         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
439         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
440                 mdd.${MDT_DEV}.lfsck_namespace |
441                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
442                 $SHOW_NAMESPACE
443                 error "(7) unexpected status"
444         }
445
446         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
447         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
448
449         local repaired=$($SHOW_NAMESPACE |
450                          awk '/^dirent_repaired/ { print $2 }')
451         # for interop with old server
452         [ -z "$repaired" ] &&
453                 repaired=$($SHOW_NAMESPACE |
454                          awk '/^updated_phase1/ { print $2 }')
455
456         [ $repaired -ge 2 ] ||
457                 error "(9) Fail to generate FID-in-dirent for IGIF: $repaired"
458
459         mount_client $MOUNT || error "(10) Fail to start client!"
460
461         #define OBD_FAIL_FID_LOOKUP     0x1505
462         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
463         stat $DIR/$tdir/dummy > /dev/null || error "(11) no FID-in-LMA."
464
465         ls $DIR/$tdir/ > /dev/null || error "(12) no FID-in-dirent."
466
467         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
468         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
469         local dummyname=$($LFS fid2path $DIR $dummyfid)
470         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
471                 error "(13) Fail to generate linkEA: $dummyfid $dummyname"
472 }
473 run_test 5 "LFSCK can handle IGIF object upgrading"
474
475 test_6a() {
476         lfsck_prep 5 5
477
478         #define OBD_FAIL_LFSCK_DELAY1           0x1600
479         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
480         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
481
482         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
483         [ "$STATUS" == "scanning-phase1" ] ||
484                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
485
486         # Sleep 3 sec to guarantee at least one object processed by LFSCK
487         sleep 3
488         # Fail the LFSCK to guarantee there is at least one checkpoint
489         #define OBD_FAIL_LFSCK_FATAL1           0x1608
490         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001608
491         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
492                 mdd.${MDT_DEV}.lfsck_namespace |
493                 awk '/^status/ { print \\\$2 }'" "failed" 6 || {
494                 $SHOW_NAMESPACE
495                 error "(4) unexpected status"
496         }
497
498         local POS0=$($SHOW_NAMESPACE |
499                      awk '/^last_checkpoint_position/ { print $2 }' |
500                      tr -d ',')
501
502         #define OBD_FAIL_LFSCK_DELAY1           0x1600
503         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
504         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
505
506         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
507         [ "$STATUS" == "scanning-phase1" ] ||
508                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
509
510         local POS1=$($SHOW_NAMESPACE |
511                      awk '/^latest_start_position/ { print $2 }' |
512                      tr -d ',')
513         [ $POS0 -lt $POS1 ] ||
514                 error "(7) Expect larger than: $POS0, but got $POS1"
515
516         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
517         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
518                 mdd.${MDT_DEV}.lfsck_namespace |
519                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
520                 $SHOW_NAMESPACE
521                 error "(8) unexpected status"
522         }
523 }
524 run_test 6a "LFSCK resumes from last checkpoint (1)"
525
526 test_6b() {
527         lfsck_prep 5 5
528
529         #define OBD_FAIL_LFSCK_DELAY2           0x1601
530         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
531         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
532
533         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
534         [ "$STATUS" == "scanning-phase1" ] ||
535                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
536
537         # Sleep 5 sec to guarantee that we are in the directory scanning
538         sleep 5
539         # Fail the LFSCK to guarantee there is at least one checkpoint
540         #define OBD_FAIL_LFSCK_FATAL2           0x1609
541         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
542         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
543                 mdd.${MDT_DEV}.lfsck_namespace |
544                 awk '/^status/ { print \\\$2 }'" "failed" 6 || {
545                 $SHOW_NAMESPACE
546                 error "(4) unexpected status"
547         }
548
549         local O_POS0=$($SHOW_NAMESPACE |
550                        awk '/^last_checkpoint_position/ { print $2 }' |
551                        tr -d ',')
552
553         local D_POS0=$($SHOW_NAMESPACE |
554                        awk '/^last_checkpoint_position/ { print $4 }')
555
556         #define OBD_FAIL_LFSCK_DELAY2           0x1601
557         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
558         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
559
560         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
561         [ "$STATUS" == "scanning-phase1" ] ||
562                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
563
564         local O_POS1=$($SHOW_NAMESPACE |
565                        awk '/^latest_start_position/ { print $2 }' |
566                        tr -d ',')
567         local D_POS1=$($SHOW_NAMESPACE |
568                        awk '/^latest_start_position/ { print $4 }')
569
570         if [ "$D_POS0" == "N/A" -o "$D_POS1" == "N/A" ]; then
571                 [ $O_POS0 -lt $O_POS1 ] ||
572                         error "(7.1) $O_POS1 is not larger than $O_POS0"
573         else
574                 [ $D_POS0 -lt $D_POS1 ] ||
575                         error "(7.2) $D_POS1 is not larger than $D_POS0"
576         fi
577
578         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
579         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
580                 mdd.${MDT_DEV}.lfsck_namespace |
581                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
582                 $SHOW_NAMESPACE
583                 error "(8) unexpected status"
584         }
585 }
586 run_test 6b "LFSCK resumes from last checkpoint (2)"
587
588 test_7a()
589 {
590         lfsck_prep 5 5
591         umount_client $MOUNT
592
593         #define OBD_FAIL_LFSCK_DELAY2           0x1601
594         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
595         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
596
597         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
598         [ "$STATUS" == "scanning-phase1" ] ||
599                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
600
601         # Sleep 3 sec to guarantee at least one object processed by LFSCK
602         sleep 3
603         echo "stop $SINGLEMDS"
604         stop $SINGLEMDS > /dev/null || error "(4) Fail to stop MDS!"
605
606         echo "start $SINGLEMDS"
607         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
608                 error "(5) Fail to start MDS!"
609
610         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
611         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
612                 mdd.${MDT_DEV}.lfsck_namespace |
613                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
614                 $SHOW_NAMESPACE
615                 error "(6) unexpected status"
616         }
617 }
618 run_test 7a "non-stopped LFSCK should auto restarts after MDS remount (1)"
619
620 test_7b()
621 {
622         lfsck_prep 2 2
623
624         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
625         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
626         for ((i = 0; i < 20; i++)); do
627                 touch $DIR/$tdir/dummy${i}
628         done
629
630         #define OBD_FAIL_LFSCK_DELAY3           0x1602
631         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1602
632         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
633         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
634                 mdd.${MDT_DEV}.lfsck_namespace |
635                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 6 || {
636                 $SHOW_NAMESPACE
637                 error "(4) unexpected status"
638         }
639
640         echo "stop $SINGLEMDS"
641         stop $SINGLEMDS > /dev/null || error "(5) Fail to stop MDS!"
642
643         echo "start $SINGLEMDS"
644         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
645                 error "(6) Fail to start MDS!"
646
647         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
648         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
649                 mdd.${MDT_DEV}.lfsck_namespace |
650                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
651                 $SHOW_NAMESPACE
652                 error "(7) unexpected status"
653         }
654 }
655 run_test 7b "non-stopped LFSCK should auto restarts after MDS remount (2)"
656
657 test_8()
658 {
659         echo "formatall"
660         formatall > /dev/null
661         echo "setupall"
662         setupall > /dev/null
663
664         lfsck_prep 20 20
665
666         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
667         [ "$STATUS" == "init" ] ||
668                 error "(2) Expect 'init', but got '$STATUS'"
669
670         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
671         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
672         mkdir $DIR/$tdir/crashed
673
674         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
675         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
676         for ((i = 0; i < 5; i++)); do
677                 touch $DIR/$tdir/dummy${i}
678         done
679
680         umount_client $MOUNT || error "(3) Fail to stop client!"
681
682         #define OBD_FAIL_LFSCK_DELAY2           0x1601
683         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1601
684         $START_NAMESPACE || error "(4) Fail to start LFSCK for namespace!"
685
686         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
687         [ "$STATUS" == "scanning-phase1" ] ||
688                 error "(5) Expect 'scanning-phase1', but got '$STATUS'"
689
690         $STOP_LFSCK || error "(6) Fail to stop LFSCK!"
691
692         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
693         [ "$STATUS" == "stopped" ] ||
694                 error "(7) Expect 'stopped', but got '$STATUS'"
695
696         $START_NAMESPACE || error "(8) Fail to start LFSCK for namespace!"
697
698         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
699         [ "$STATUS" == "scanning-phase1" ] ||
700                 error "(9) Expect 'scanning-phase1', but got '$STATUS'"
701
702         #define OBD_FAIL_LFSCK_FATAL2           0x1609
703         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
704         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
705                 mdd.${MDT_DEV}.lfsck_namespace |
706                 awk '/^status/ { print \\\$2 }'" "failed" 6 || {
707                 $SHOW_NAMESPACE
708                 error "(10) unexpected status"
709         }
710
711         #define OBD_FAIL_LFSCK_DELAY1           0x1600
712         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
713         $START_NAMESPACE || error "(11) Fail to start LFSCK for namespace!"
714
715         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
716         [ "$STATUS" == "scanning-phase1" ] ||
717                 error "(12) Expect 'scanning-phase1', but got '$STATUS'"
718
719         #define OBD_FAIL_LFSCK_CRASH            0x160a
720         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160a
721         sleep 5
722
723         echo "stop $SINGLEMDS"
724         stop $SINGLEMDS > /dev/null || error "(13) Fail to stop MDS!"
725
726         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
727         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
728
729         echo "start $SINGLEMDS"
730         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
731                 error "(14) Fail to start MDS!"
732
733         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
734         [ "$STATUS" == "crashed" ] ||
735                 error "(15) Expect 'crashed', but got '$STATUS'"
736
737         #define OBD_FAIL_LFSCK_DELAY2           0x1601
738         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
739         $START_NAMESPACE || error "(16) Fail to start LFSCK for namespace!"
740
741         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
742         [ "$STATUS" == "scanning-phase1" ] ||
743                 error "(17) Expect 'scanning-phase1', but got '$STATUS'"
744
745         echo "stop $SINGLEMDS"
746         stop $SINGLEMDS > /dev/null || error "(18) Fail to stop MDS!"
747
748         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
749         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
750
751         echo "start $SINGLEMDS"
752         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
753                 error "(19) Fail to start MDS!"
754
755         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
756         [ "$STATUS" == "paused" ] ||
757                 error "(20) Expect 'paused', but got '$STATUS'"
758
759         #define OBD_FAIL_LFSCK_DELAY3           0x1602
760         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1602
761
762         $START_NAMESPACE || error "(21) Fail to start LFSCK for namespace!"
763         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
764                 mdd.${MDT_DEV}.lfsck_namespace |
765                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 6 || {
766                 $SHOW_NAMESPACE
767                 error "(22) unexpected status"
768         }
769
770         local FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
771         [ "$FLAGS" == "scanned-once,inconsistent" ] ||
772                 error "(23) Expect 'scanned-once,inconsistent',but got '$FLAGS'"
773
774         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
775         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
776                 mdd.${MDT_DEV}.lfsck_namespace |
777                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
778                 $SHOW_NAMESPACE
779                 error "(24) unexpected status"
780         }
781
782         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
783         [ -z "$FLAGS" ] || error "(25) Expect empty flags, but got '$FLAGS'"
784 }
785 run_test 8 "LFSCK state machine"
786
787 test_9a() {
788         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
789                 skip "Testing on UP system, the speed may be inaccurate."
790                 return 0
791         fi
792
793         lfsck_prep 70 70
794
795         local BASE_SPEED1=100
796         local RUN_TIME1=10
797         $START_NAMESPACE -r -s $BASE_SPEED1 || error "(3) Fail to start LFSCK!"
798
799         sleep $RUN_TIME1
800         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
801         [ "$STATUS" == "scanning-phase1" ] ||
802                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
803
804         local SPEED=$($SHOW_NAMESPACE |
805                       awk '/^average_speed_phase1/ { print $2 }')
806
807         # There may be time error, normally it should be less than 2 seconds.
808         # We allow another 20% schedule error.
809         local TIME_DIFF=2
810         # MAX_MARGIN = 1.2 = 12 / 10
811         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
812                            RUN_TIME1 * 12 / 10))
813         [ $SPEED -lt $MAX_SPEED ] ||
814                 error "(4) Got speed $SPEED, expected less than $MAX_SPEED"
815
816         # adjust speed limit
817         local BASE_SPEED2=300
818         local RUN_TIME2=10
819         do_facet $SINGLEMDS \
820                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
821         sleep $RUN_TIME2
822
823         SPEED=$($SHOW_NAMESPACE | awk '/^average_speed_phase1/ { print $2 }')
824         # MIN_MARGIN = 0.8 = 8 / 10
825         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
826                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
827                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
828         # Account for slow ZFS performance - LU-4934
829         [ $SPEED -gt $MIN_SPEED ] || [ $(facet_fstype $SINGLEMDS) -eq zfs ] ||
830                 error "(5) Got speed $SPEED, expected more than $MIN_SPEED"
831
832         # MAX_MARGIN = 1.2 = 12 / 10
833         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
834                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
835                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
836         [ $SPEED -lt $MAX_SPEED ] ||
837                 error "(6) Got speed $SPEED, expected less than $MAX_SPEED"
838
839         do_facet $SINGLEMDS \
840                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
841
842         wait_update_facet $SINGLEMDS \
843             "$LCTL get_param -n mdd.${MDT_DEV}.lfsck_namespace|\
844             awk '/^status/ { print \\\$2 }'" "completed" 30 ||
845                 error "(7) Failed to get expected 'completed'"
846 }
847 run_test 9a "LFSCK speed control (1)"
848
849 test_9b() {
850         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
851                 skip "Testing on UP system, the speed may be inaccurate."
852                 return 0
853         fi
854
855         lfsck_prep 0 0
856
857         echo "Preparing another 50 * 50 files (with error) at $(date)."
858         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
859         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
860         createmany -d $DIR/$tdir/d 50
861         createmany -m $DIR/$tdir/f 50
862         for ((i = 0; i < 50; i++)); do
863                 createmany -m $DIR/$tdir/d${i}/f 50 > /dev/null
864         done
865
866         #define OBD_FAIL_LFSCK_NO_DOUBLESCAN    0x160c
867         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160c
868         $START_NAMESPACE -r || error "(4) Fail to start LFSCK!"
869         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
870                 mdd.${MDT_DEV}.lfsck_namespace |
871                 awk '/^status/ { print \\\$2 }'" "stopped" 10 || {
872                 $SHOW_NAMESPACE
873                 error "(5) unexpected status"
874         }
875
876         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
877         echo "Prepared at $(date)."
878
879         local BASE_SPEED1=50
880         local RUN_TIME1=10
881         $START_NAMESPACE -s $BASE_SPEED1 || error "(6) Fail to start LFSCK!"
882
883         sleep $RUN_TIME1
884         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
885         [ "$STATUS" == "scanning-phase2" ] ||
886                 error "(7) Expect 'scanning-phase2', but got '$STATUS'"
887
888         local SPEED=$($SHOW_NAMESPACE |
889                       awk '/^average_speed_phase2/ { print $2 }')
890         # There may be time error, normally it should be less than 2 seconds.
891         # We allow another 20% schedule error.
892         local TIME_DIFF=2
893         # MAX_MARGIN = 1.2 = 12 / 10
894         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
895                           RUN_TIME1 * 12 / 10))
896         [ $SPEED -lt $MAX_SPEED ] ||
897                 error "(8) Got speed $SPEED, expected less than $MAX_SPEED"
898
899         # adjust speed limit
900         local BASE_SPEED2=150
901         local RUN_TIME2=10
902         do_facet $SINGLEMDS \
903                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
904         sleep $RUN_TIME2
905
906         SPEED=$($SHOW_NAMESPACE | awk '/^average_speed_phase2/ { print $2 }')
907         # MIN_MARGIN = 0.8 = 8 / 10
908         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
909                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
910                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
911         [ $SPEED -gt $MIN_SPEED ] ||[ $(facet_fstype $SINGLEMDS) -eq zfs ] ||
912                 error "(9) Got speed $SPEED, expected more than $MIN_SPEED"
913
914         # MAX_MARGIN = 1.2 = 12 / 10
915         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
916                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
917                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
918         [ $SPEED -lt $MAX_SPEED ] ||
919                 error "(10) Got speed $SPEED, expected less than $MAX_SPEED"
920
921         do_facet $SINGLEMDS \
922                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
923         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
924                 mdd.${MDT_DEV}.lfsck_namespace |
925                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
926                 $SHOW_NAMESPACE
927                 error "(11) unexpected status"
928         }
929 }
930 run_test 9b "LFSCK speed control (2)"
931
932 test_10()
933 {
934         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
935                 skip "lookup(..)/linkea on ZFS issue" && return
936
937         lfsck_prep 1 1
938
939         echo "Preparing more files with error at $(date)."
940         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
941         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
942
943         for ((i = 0; i < 1000; i = $((i+2)))); do
944                 mkdir -p $DIR/$tdir/d${i}
945                 touch $DIR/$tdir/f${i}
946                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
947         done
948
949         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
950         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
951
952         for ((i = 1; i < 1000; i = $((i+2)))); do
953                 mkdir -p $DIR/$tdir/d${i}
954                 touch $DIR/$tdir/f${i}
955                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
956         done
957
958         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
959         echo "Prepared at $(date)."
960
961         ln $DIR/$tdir/f200 $DIR/$tdir/d200/dummy
962
963         umount_client $MOUNT
964         mount_client $MOUNT || error "(3) Fail to start client!"
965
966         $START_NAMESPACE -r -s 100 || error "(5) Fail to start LFSCK!"
967
968         sleep 10
969         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
970         [ "$STATUS" == "scanning-phase1" ] ||
971                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
972
973         ls -ailR $MOUNT > /dev/null || error "(7) Fail to ls!"
974
975         touch $DIR/$tdir/d198/a0 || error "(8) Fail to touch!"
976
977         mkdir $DIR/$tdir/d199/a1 || error "(9) Fail to mkdir!"
978
979         unlink $DIR/$tdir/f200 || error "(10) Fail to unlink!"
980
981         rm -rf $DIR/$tdir/d201 || error "(11) Fail to rmdir!"
982
983         mv $DIR/$tdir/f202 $DIR/$tdir/d203/ || error "(12) Fail to rename!"
984
985         ln $DIR/$tdir/f204 $DIR/$tdir/d205/a3 || error "(13) Fail to hardlink!"
986
987         ln -s $DIR/$tdir/d206 $DIR/$tdir/d207/a4 ||
988                 error "(14) Fail to softlink!"
989
990         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
991         [ "$STATUS" == "scanning-phase1" ] ||
992                 error "(15) Expect 'scanning-phase1', but got '$STATUS'"
993
994         do_facet $SINGLEMDS \
995                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
996         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
997                 mdd.${MDT_DEV}.lfsck_namespace |
998                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
999                 $SHOW_NAMESPACE
1000                 error "(16) unexpected status"
1001         }
1002 }
1003 run_test 10 "System is available during LFSCK scanning"
1004
1005 # remove LAST_ID
1006 ost_remove_lastid() {
1007         local ost=$1
1008         local idx=$2
1009         local rcmd="do_facet ost${ost}"
1010
1011         echo "remove LAST_ID on ost${ost}: idx=${idx}"
1012
1013         # step 1: local mount
1014         mount_fstype ost${ost} || return 1
1015         # step 2: remove the specified LAST_ID
1016         ${rcmd} rm -fv $(facet_mntpt ost${ost})/O/${idx}/{LAST_ID,d0/0}
1017         # step 3: umount
1018         unmount_fstype ost${ost} || return 2
1019 }
1020
1021 test_11a() {
1022         check_mount_and_prep
1023         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1024         createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 64 files."
1025
1026         echo "stopall"
1027         stopall > /dev/null
1028
1029         ost_remove_lastid 1 0 || error "(1) Fail to remove LAST_ID"
1030
1031         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1032                 error "(2) Fail to start ost1"
1033
1034         #define OBD_FAIL_LFSCK_DELAY4           0x160e
1035         do_facet ost1 $LCTL set_param fail_val=3 fail_loc=0x160e
1036
1037         echo "trigger LFSCK for layout on ost1 to rebuild the LAST_ID(s)"
1038         $START_LAYOUT_ON_OST -r || error "(4) Fail to start LFSCK on OST!"
1039
1040         wait_update_facet ost1 "$LCTL get_param -n \
1041                 obdfilter.${OST_DEV}.lfsck_layout |
1042                 awk '/^flags/ { print \\\$2 }'" "crashed_lastid" 60 || {
1043                 $SHOW_LAYOUT_ON_OST
1044                 error "(5) unexpected status"
1045         }
1046
1047         do_facet ost1 $LCTL set_param fail_val=0 fail_loc=0
1048
1049         wait_update_facet ost1 "$LCTL get_param -n \
1050                 obdfilter.${OST_DEV}.lfsck_layout |
1051                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1052                 $SHOW_LAYOUT_ON_OST
1053                 error "(6) unexpected status"
1054         }
1055
1056         echo "the LAST_ID(s) should have been rebuilt"
1057         FLAGS=$($SHOW_LAYOUT_ON_OST | awk '/^flags/ { print $2 }')
1058         [ -z "$FLAGS" ] || error "(7) Expect empty flags, but got '$FLAGS'"
1059 }
1060 run_test 11a "LFSCK can rebuild lost last_id"
1061
1062 test_11b() {
1063         check_mount_and_prep
1064         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1065
1066         echo "set fail_loc=0x160d to skip the updating LAST_ID on-disk"
1067         #define OBD_FAIL_LFSCK_SKIP_LASTID      0x160d
1068         do_facet ost1 $LCTL set_param fail_loc=0x160d
1069         createmany -o $DIR/$tdir/f 64
1070         local lastid1=$(do_facet ost1 "lctl get_param -n \
1071                 obdfilter.${ost1_svc}.last_id" | grep 0x100000000 |
1072                 awk -F: '{ print $2 }')
1073
1074         umount_client $MOUNT
1075         stop ost1 || error "(1) Fail to stop ost1"
1076
1077         #define OBD_FAIL_OST_ENOSPC              0x215
1078         do_facet ost1 $LCTL set_param fail_loc=0x215
1079
1080         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1081                 error "(2) Fail to start ost1"
1082
1083         for ((i = 0; i < 60; i++)); do
1084                 lastid2=$(do_facet ost1 "lctl get_param -n \
1085                         obdfilter.${ost1_svc}.last_id" | grep 0x100000000 |
1086                         awk -F: '{ print $2 }')
1087                 [ ! -z $lastid2 ] && break;
1088                 sleep 1
1089         done
1090
1091         echo "the on-disk LAST_ID should be smaller than the expected one"
1092         [ $lastid1 -gt $lastid2 ] ||
1093                 error "(4) expect lastid1 [ $lastid1 ] > lastid2 [ $lastid2 ]"
1094
1095         echo "trigger LFSCK for layout on ost1 to rebuild the on-disk LAST_ID"
1096         $START_LAYOUT_ON_OST -r || error "(5) Fail to start LFSCK on OST!"
1097
1098         wait_update_facet ost1 "$LCTL get_param -n \
1099                 obdfilter.${OST_DEV}.lfsck_layout |
1100                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1101                 $SHOW_LAYOUT_ON_OST
1102                 error "(6) unexpected status"
1103         }
1104
1105         stop ost1 || error "(7) Fail to stop ost1"
1106
1107         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1108                 error "(8) Fail to start ost1"
1109
1110         echo "the on-disk LAST_ID should have been rebuilt"
1111         wait_update_facet ost1 "$LCTL get_param -n \
1112                 obdfilter.${ost1_svc}.last_id | grep 0x100000000 |
1113                 awk -F: '{ print \\\$2 }'" "$lastid1" 60 || {
1114                 $LCTL get_param -n obdfilter.${ost1_svc}.last_id
1115                 error "(9) expect lastid1 0x100000000:$lastid1"
1116         }
1117
1118         do_facet ost1 $LCTL set_param fail_loc=0
1119         stopall || error "(10) Fail to stopall"
1120 }
1121 run_test 11b "LFSCK can rebuild crashed last_id"
1122
1123 test_12() {
1124         [ $MDSCOUNT -lt 2 ] &&
1125                 skip "We need at least 2 MDSes for test_12" && exit 0
1126
1127         check_mount_and_prep
1128         for k in $(seq $MDSCOUNT); do
1129                 $LFS mkdir -i $((k - 1)) $DIR/$tdir/${k}
1130                 createmany -o $DIR/$tdir/${k}/f 100 ||
1131                         error "(0) Fail to create 100 files."
1132         done
1133
1134         echo "Start namespace LFSCK on all targets by single command (-s 1)."
1135         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1136                 -s 1 -r || error "(2) Fail to start LFSCK on all devices!"
1137
1138         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1139         for k in $(seq $MDSCOUNT); do
1140                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1141                                 mdd.$(facet_svc mds${k}).lfsck_namespace |
1142                                 awk '/^status/ { print $2 }')
1143                 [ "$STATUS" == "scanning-phase1" ] ||
1144                 error "(3) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
1145         done
1146
1147         echo "Stop namespace LFSCK on all targets by single lctl command."
1148         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1149                 error "(4) Fail to stop LFSCK on all devices!"
1150
1151         echo "All the LFSCK targets should be in 'stopped' status."
1152         for k in $(seq $MDSCOUNT); do
1153                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1154                                 mdd.$(facet_svc mds${k}).lfsck_namespace |
1155                                 awk '/^status/ { print $2 }')
1156                 [ "$STATUS" == "stopped" ] ||
1157                         error "(5) MDS${k} Expect 'stopped', but got '$STATUS'"
1158         done
1159
1160         echo "Re-start namespace LFSCK on all targets by single command (-s 0)."
1161         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1162                 -s 0 -r || error "(6) Fail to start LFSCK on all devices!"
1163
1164         echo "All the LFSCK targets should be in 'completed' status."
1165         for k in $(seq $MDSCOUNT); do
1166                 wait_update_facet mds${k} "$LCTL get_param -n \
1167                         mdd.$(facet_svc mds${k}).lfsck_namespace |
1168                         awk '/^status/ { print \\\$2 }'" "completed" 8 ||
1169                         error "(7) MDS${k} is not the expected 'completed'"
1170         done
1171
1172         echo "Start layout LFSCK on all targets by single command (-s 1)."
1173         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1174                 -s 1 -r || error "(8) Fail to start LFSCK on all devices!"
1175
1176         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1177         for k in $(seq $MDSCOUNT); do
1178                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1179                                 mdd.$(facet_svc mds${k}).lfsck_layout |
1180                                 awk '/^status/ { print $2 }')
1181                 [ "$STATUS" == "scanning-phase1" ] ||
1182                 error "(9) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
1183         done
1184
1185         echo "Stop layout LFSCK on all targets by single lctl command."
1186         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1187                 error "(10) Fail to stop LFSCK on all devices!"
1188
1189         echo "All the LFSCK targets should be in 'stopped' status."
1190         for k in $(seq $MDSCOUNT); do
1191                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1192                                 mdd.$(facet_svc mds${k}).lfsck_layout |
1193                                 awk '/^status/ { print $2 }')
1194                 [ "$STATUS" == "stopped" ] ||
1195                         error "(11) MDS${k} Expect 'stopped', but got '$STATUS'"
1196         done
1197
1198         for k in $(seq $OSTCOUNT); do
1199                 local STATUS=$(do_facet ost${k} $LCTL get_param -n \
1200                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1201                                 awk '/^status/ { print $2 }')
1202                 [ "$STATUS" == "stopped" ] ||
1203                         error "(12) OST${k} Expect 'stopped', but got '$STATUS'"
1204         done
1205
1206         echo "Re-start layout LFSCK on all targets by single command (-s 0)."
1207         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1208                 -s 0 -r || error "(13) Fail to start LFSCK on all devices!"
1209
1210         echo "All the LFSCK targets should be in 'completed' status."
1211         for k in $(seq $MDSCOUNT); do
1212                 # The LFSCK status query internal is 30 seconds. For the case
1213                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1214                 # time to guarantee the status sync up.
1215                 wait_update_facet mds${k} "$LCTL get_param -n \
1216                         mdd.$(facet_svc mds${k}).lfsck_layout |
1217                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1218                         error "(14) MDS${k} is not the expected 'completed'"
1219         done
1220 }
1221 run_test 12 "single command to trigger LFSCK on all devices"
1222
1223 test_13() {
1224         echo "#####"
1225         echo "The lmm_oi in layout EA should be consistent with the MDT-object"
1226         echo "FID; otherwise, the LFSCK should re-generate the lmm_oi from the"
1227         echo "MDT-object FID."
1228         echo "#####"
1229
1230         check_mount_and_prep
1231
1232         echo "Inject failure stub to simulate bad lmm_oi"
1233         #define OBD_FAIL_LFSCK_BAD_LMMOI        0x160f
1234         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160f
1235         createmany -o $DIR/$tdir/f 32
1236         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1237
1238         echo "Trigger layout LFSCK to find out the bad lmm_oi and fix them"
1239         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1240
1241         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1242                 mdd.${MDT_DEV}.lfsck_layout |
1243                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1244                 $SHOW_LAYOUT
1245                 error "(2) unexpected status"
1246         }
1247
1248         local repaired=$($SHOW_LAYOUT |
1249                          awk '/^repaired_others/ { print $2 }')
1250         [ $repaired -eq 32 ] ||
1251                 error "(3) Fail to repair crashed lmm_oi: $repaired"
1252 }
1253 run_test 13 "LFSCK can repair crashed lmm_oi"
1254
1255 test_14() {
1256         echo "#####"
1257         echo "The OST-object referenced by the MDT-object should be there;"
1258         echo "otherwise, the LFSCK should re-create the missed OST-object."
1259         echo "#####"
1260
1261         check_mount_and_prep
1262         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1263
1264         local count=$(precreated_ost_obj_count 0 0)
1265
1266         echo "Inject failure stub to simulate dangling referenced MDT-object"
1267         #define OBD_FAIL_LFSCK_DANGLING 0x1610
1268         do_facet ost1 $LCTL set_param fail_loc=0x1610
1269         createmany -o $DIR/$tdir/f $((count + 32))
1270         do_facet ost1 $LCTL set_param fail_loc=0
1271
1272         # exhaust other pre-created dangling cases
1273         count=$(precreated_ost_obj_count 0 0)
1274         createmany -o $DIR/$tdir/a $count ||
1275                 error "(0) Fail to create $count files."
1276
1277         echo "'ls' should fail because of dangling referenced MDT-object"
1278         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(1) ls should fail."
1279
1280         echo "Trigger layout LFSCK to find out dangling reference"
1281         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1282
1283         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1284                 mdd.${MDT_DEV}.lfsck_layout |
1285                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1286                 $SHOW_LAYOUT
1287                 error "(3) unexpected status"
1288         }
1289
1290         local repaired=$($SHOW_LAYOUT |
1291                          awk '/^repaired_dangling/ { print $2 }')
1292         [ $repaired -ge 32 ] ||
1293                 error "(4) Fail to repair dangling reference: $repaired"
1294
1295         echo "'ls' should fail because it will not repair dangling by default"
1296         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail."
1297
1298         echo "Trigger layout LFSCK to repair dangling reference"
1299         $START_LAYOUT -r -c || error "(6) Fail to start LFSCK for layout!"
1300
1301         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1302                 mdd.${MDT_DEV}.lfsck_layout |
1303                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1304                 $SHOW_LAYOUT
1305                 error "(7) unexpected status"
1306         }
1307
1308         repaired=$($SHOW_LAYOUT |
1309                          awk '/^repaired_dangling/ { print $2 }')
1310         [ $repaired -ge 32 ] ||
1311                 error "(8) Fail to repair dangling reference: $repaired"
1312
1313         echo "'ls' should success after layout LFSCK repairing"
1314         ls -ail $DIR/$tdir > /dev/null || error "(9) ls should success."
1315 }
1316 run_test 14 "LFSCK can repair MDT-object with dangling reference"
1317
1318 test_15a() {
1319         echo "#####"
1320         echo "If the OST-object referenced by the MDT-object back points"
1321         echo "to some non-exist MDT-object, then the LFSCK should repair"
1322         echo "the OST-object to back point to the right MDT-object."
1323         echo "#####"
1324
1325         check_mount_and_prep
1326         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1327
1328         echo "Inject failure stub to make the OST-object to back point to"
1329         echo "non-exist MDT-object."
1330         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
1331
1332         do_facet ost1 $LCTL set_param fail_loc=0x1611
1333         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1334         cancel_lru_locks osc
1335         do_facet ost1 $LCTL set_param fail_loc=0
1336
1337         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1338         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1339
1340         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1341                 mdd.${MDT_DEV}.lfsck_layout |
1342                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1343                 $SHOW_LAYOUT
1344                 error "(2) unexpected status"
1345         }
1346
1347         local repaired=$($SHOW_LAYOUT |
1348                          awk '/^repaired_unmatched_pair/ { print $2 }')
1349         [ $repaired -eq 1 ] ||
1350                 error "(3) Fail to repair unmatched pair: $repaired"
1351 }
1352 run_test 15a "LFSCK can repair unmatched MDT-object/OST-object pairs (1)"
1353
1354 test_15b() {
1355         echo "#####"
1356         echo "If the OST-object referenced by the MDT-object back points"
1357         echo "to other MDT-object that doesn't recognize the OST-object,"
1358         echo "then the LFSCK should repair it to back point to the right"
1359         echo "MDT-object (the first one)."
1360         echo "#####"
1361
1362         check_mount_and_prep
1363         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1364         dd if=/dev/zero of=$DIR/$tdir/guard bs=1M count=1
1365         cancel_lru_locks osc
1366
1367         echo "Inject failure stub to make the OST-object to back point to"
1368         echo "other MDT-object"
1369
1370         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR2  0x1612
1371         do_facet ost1 $LCTL set_param fail_loc=0x1612
1372         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1373         cancel_lru_locks osc
1374         do_facet ost1 $LCTL set_param fail_loc=0
1375
1376         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1377         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1378
1379         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1380                 mdd.${MDT_DEV}.lfsck_layout |
1381                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1382                 $SHOW_LAYOUT
1383                 error "(2) unexpected status"
1384         }
1385
1386         local repaired=$($SHOW_LAYOUT |
1387                          awk '/^repaired_unmatched_pair/ { print $2 }')
1388         [ $repaired -eq 1 ] ||
1389                 error "(3) Fail to repair unmatched pair: $repaired"
1390 }
1391 run_test 15b "LFSCK can repair unmatched MDT-object/OST-object pairs (2)"
1392
1393 test_16() {
1394         echo "#####"
1395         echo "If the OST-object's owner information does not match the owner"
1396         echo "information stored in the MDT-object, then the LFSCK trust the"
1397         echo "MDT-object and update the OST-object's owner information."
1398         echo "#####"
1399
1400         check_mount_and_prep
1401         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1402         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1403         cancel_lru_locks osc
1404
1405         echo "Inject failure stub to skip OST-object owner changing"
1406         #define OBD_FAIL_LFSCK_BAD_OWNER        0x1613
1407         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1613
1408         chown 1.1 $DIR/$tdir/f0
1409         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1410
1411         echo "Trigger layout LFSCK to find out inconsistent OST-object owner"
1412         echo "and fix them"
1413
1414         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1415
1416         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1417                 mdd.${MDT_DEV}.lfsck_layout |
1418                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1419                 $SHOW_LAYOUT
1420                 error "(2) unexpected status"
1421         }
1422
1423         local repaired=$($SHOW_LAYOUT |
1424                          awk '/^repaired_inconsistent_owner/ { print $2 }')
1425         [ $repaired -eq 1 ] ||
1426                 error "(3) Fail to repair inconsistent owner: $repaired"
1427 }
1428 run_test 16 "LFSCK can repair inconsistent MDT-object/OST-object owner"
1429
1430 test_17() {
1431         echo "#####"
1432         echo "If more than one MDT-objects reference the same OST-object,"
1433         echo "and the OST-object only recognizes one MDT-object, then the"
1434         echo "LFSCK should create new OST-objects for such non-recognized"
1435         echo "MDT-objects."
1436         echo "#####"
1437
1438         check_mount_and_prep
1439         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1440
1441         echo "Inject failure stub to make two MDT-objects to refernce"
1442         echo "the OST-object"
1443
1444         #define OBD_FAIL_LFSCK_MULTIPLE_REF     0x1614
1445         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0x1614
1446
1447         dd if=/dev/zero of=$DIR/$tdir/guard bs=1M count=1
1448         cancel_lru_locks osc
1449
1450         createmany -o $DIR/$tdir/f 1
1451
1452         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
1453
1454         cancel_lru_locks mdc
1455         cancel_lru_locks osc
1456
1457         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard use the same OST-objects"
1458         local size=$(ls -l $DIR/$tdir/f0 | awk '{ print $5 }')
1459         [ $size -eq 1048576 ] ||
1460                 error "(1) f0 (wrong) size should be 1048576, but got $size"
1461
1462         echo "Trigger layout LFSCK to find out multiple refenced MDT-objects"
1463         echo "and fix them"
1464
1465         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1466
1467         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1468                 mdd.${MDT_DEV}.lfsck_layout |
1469                 awk '/^status/ { print \\\$2 }'" "completed" 6 || {
1470                 $SHOW_LAYOUT
1471                 error "(3) unexpected status"
1472         }
1473
1474         local repaired=$($SHOW_LAYOUT |
1475                          awk '/^repaired_multiple_referenced/ { print $2 }')
1476         [ $repaired -eq 1 ] ||
1477                 error "(4) Fail to repair multiple references: $repaired"
1478
1479         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard should use diff OST-objects"
1480         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=2 ||
1481                 error "(5) Fail to write f0."
1482         size=$(ls -l $DIR/$tdir/guard | awk '{ print $5 }')
1483         [ $size -eq 1048576 ] ||
1484                 error "(6) guard size should be 1048576, but got $size"
1485 }
1486 run_test 17 "LFSCK can repair multiple references"
1487
1488 test_18a() {
1489         echo "#####"
1490         echo "The target MDT-object is there, but related stripe information"
1491         echo "is lost or partly lost. The LFSCK should regenerate the missed"
1492         echo "layout EA entries."
1493         echo "#####"
1494
1495         check_mount_and_prep
1496         $LFS mkdir -i 0 $DIR/$tdir/a1
1497         $LFS setstripe -c 1 -i 0 -s 1M $DIR/$tdir/a1
1498         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1499
1500         local saved_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1501
1502         $LFS path2fid $DIR/$tdir/a1/f1
1503         $LFS getstripe $DIR/$tdir/a1/f1
1504
1505         if [ $MDSCOUNT -ge 2 ]; then
1506                 $LFS mkdir -i 1 $DIR/$tdir/a2
1507                 $LFS setstripe -c 2 -i 1 -s 1M $DIR/$tdir/a2
1508                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1509                 $LFS path2fid $DIR/$tdir/a2/f2
1510                 $LFS getstripe $DIR/$tdir/a2/f2
1511         fi
1512
1513         cancel_lru_locks osc
1514
1515         echo "Inject failure, to make the MDT-object lost its layout EA"
1516         #define OBD_FAIL_LFSCK_LOST_STRIPE 0x1615
1517         do_facet mds1 $LCTL set_param fail_loc=0x1615
1518         chown 1.1 $DIR/$tdir/a1/f1
1519
1520         if [ $MDSCOUNT -ge 2 ]; then
1521                 do_facet mds2 $LCTL set_param fail_loc=0x1615
1522                 chown 1.1 $DIR/$tdir/a2/f2
1523         fi
1524
1525         sync
1526         sleep 2
1527
1528         do_facet mds1 $LCTL set_param fail_loc=0
1529         if [ $MDSCOUNT -ge 2 ]; then
1530                 do_facet mds2 $LCTL set_param fail_loc=0
1531         fi
1532
1533         cancel_lru_locks mdc
1534         cancel_lru_locks osc
1535
1536         echo "The file size should be incorrect since layout EA is lost"
1537         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1538         [ "$cur_size" != "$saved_size" ] ||
1539                 error "(1) Expect incorrect file1 size"
1540
1541         if [ $MDSCOUNT -ge 2 ]; then
1542                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1543                 [ "$cur_size" != "$saved_size" ] ||
1544                         error "(2) Expect incorrect file2 size"
1545         fi
1546
1547         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1548         $START_LAYOUT -r -o || error "(3) Fail to start LFSCK for layout!"
1549
1550         for k in $(seq $MDSCOUNT); do
1551                 # The LFSCK status query internal is 30 seconds. For the case
1552                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1553                 # time to guarantee the status sync up.
1554                 wait_update_facet mds${k} "$LCTL get_param -n \
1555                         mdd.$(facet_svc mds${k}).lfsck_layout |
1556                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1557                         error "(4) MDS${k} is not the expected 'completed'"
1558         done
1559
1560         for k in $(seq $OSTCOUNT); do
1561                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1562                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1563                                 awk '/^status/ { print $2 }')
1564                 [ "$cur_status" == "completed" ] ||
1565                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
1566         done
1567
1568         local repaired=$(do_facet mds1 $LCTL get_param -n \
1569                          mdd.$(facet_svc mds1).lfsck_layout |
1570                          awk '/^repaired_orphan/ { print $2 }')
1571         [ $repaired -eq 1 ] ||
1572         error "(6.1) Expect 1 fixed on mds1, but got: $repaired"
1573
1574         if [ $MDSCOUNT -ge 2 ]; then
1575                 repaired=$(do_facet mds2 $LCTL get_param -n \
1576                          mdd.$(facet_svc mds2).lfsck_layout |
1577                                  awk '/^repaired_orphan/ { print $2 }')
1578                 [ $repaired -eq 2 ] ||
1579                 error "(6.2) Expect 2 fixed on mds2, but got: $repaired"
1580         fi
1581
1582         $LFS path2fid $DIR/$tdir/a1/f1
1583         $LFS getstripe $DIR/$tdir/a1/f1
1584
1585         if [ $MDSCOUNT -ge 2 ]; then
1586                 $LFS path2fid $DIR/$tdir/a2/f2
1587                 $LFS getstripe $DIR/$tdir/a2/f2
1588         fi
1589
1590         echo "The file size should be correct after layout LFSCK scanning"
1591         cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1592         [ "$cur_size" == "$saved_size" ] ||
1593                 error "(7) Expect file1 size $saved_size, but got $cur_size"
1594
1595         if [ $MDSCOUNT -ge 2 ]; then
1596                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1597                 [ "$cur_size" == "$saved_size" ] ||
1598                 error "(8) Expect file2 size $saved_size, but got $cur_size"
1599         fi
1600 }
1601 run_test 18a "Find out orphan OST-object and repair it (1)"
1602
1603 test_18b() {
1604         echo "#####"
1605         echo "The target MDT-object is lost. The LFSCK should re-create the"
1606         echo "MDT-object under .lustre/lost+found/MDTxxxx. The admin should"
1607         echo "can move it back to normal namespace manually."
1608         echo "#####"
1609
1610         check_mount_and_prep
1611         $LFS mkdir -i 0 $DIR/$tdir/a1
1612         $LFS setstripe -c 1 -i 0 -s 1M $DIR/$tdir/a1
1613         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1614         local saved_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1615         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
1616         echo ${fid1}
1617         $LFS getstripe $DIR/$tdir/a1/f1
1618
1619         if [ $MDSCOUNT -ge 2 ]; then
1620                 $LFS mkdir -i 1 $DIR/$tdir/a2
1621                 $LFS setstripe -c 2 -i 1 -s 1M $DIR/$tdir/a2
1622                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1623                 fid2=$($LFS path2fid $DIR/$tdir/a2/f2)
1624                 echo ${fid2}
1625                 $LFS getstripe $DIR/$tdir/a2/f2
1626         fi
1627
1628         cancel_lru_locks osc
1629
1630         echo "Inject failure, to simulate the case of missing the MDT-object"
1631         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
1632         do_facet mds1 $LCTL set_param fail_loc=0x1616
1633         rm -f $DIR/$tdir/a1/f1
1634
1635         if [ $MDSCOUNT -ge 2 ]; then
1636                 do_facet mds2 $LCTL set_param fail_loc=0x1616
1637                 rm -f $DIR/$tdir/a2/f2
1638         fi
1639
1640         sync
1641         sleep 2
1642
1643         do_facet mds1 $LCTL set_param fail_loc=0
1644         if [ $MDSCOUNT -ge 2 ]; then
1645                 do_facet mds2 $LCTL set_param fail_loc=0
1646         fi
1647
1648         cancel_lru_locks mdc
1649         cancel_lru_locks osc
1650
1651         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1652         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
1653
1654         for k in $(seq $MDSCOUNT); do
1655                 # The LFSCK status query internal is 30 seconds. For the case
1656                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1657                 # time to guarantee the status sync up.
1658                 wait_update_facet mds${k} "$LCTL get_param -n \
1659                         mdd.$(facet_svc mds${k}).lfsck_layout |
1660                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1661                         error "(2) MDS${k} is not the expected 'completed'"
1662         done
1663
1664         for k in $(seq $OSTCOUNT); do
1665                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1666                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1667                                 awk '/^status/ { print $2 }')
1668                 [ "$cur_status" == "completed" ] ||
1669                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
1670         done
1671
1672         local repaired=$(do_facet mds1 $LCTL get_param -n \
1673                          mdd.$(facet_svc mds1).lfsck_layout |
1674                          awk '/^repaired_orphan/ { print $2 }')
1675         [ $repaired -eq 1 ] ||
1676         error "(4.1) Expect 1 fixed on mds1, but got: $repaired"
1677
1678         if [ $MDSCOUNT -ge 2 ]; then
1679                 repaired=$(do_facet mds2 $LCTL get_param -n \
1680                          mdd.$(facet_svc mds2).lfsck_layout |
1681                          awk '/^repaired_orphan/ { print $2 }')
1682                 [ $repaired -eq 2 ] ||
1683                 error "(4.2) Expect 2 fixed on mds2, but got: $repaired"
1684         fi
1685
1686         echo "Move the files from ./lustre/lost+found/MDTxxxx to namespace"
1687         mv $MOUNT/.lustre/lost+found/MDT0000/R-${fid1} $DIR/$tdir/a1/f1 ||
1688         error "(5) Fail to move $MOUNT/.lustre/lost+found/MDT0000/R-${fid1}"
1689
1690         if [ $MDSCOUNT -ge 2 ]; then
1691                 local name=$MOUNT/.lustre/lost+found/MDT0001/R-${fid2}
1692                 mv $name $DIR/$tdir/a2/f2 || error "(6) Fail to move $name"
1693         fi
1694
1695         $LFS path2fid $DIR/$tdir/a1/f1
1696         $LFS getstripe $DIR/$tdir/a1/f1
1697
1698         if [ $MDSCOUNT -ge 2 ]; then
1699                 $LFS path2fid $DIR/$tdir/a2/f2
1700                 $LFS getstripe $DIR/$tdir/a2/f2
1701         fi
1702
1703         echo "The file size should be correct after layout LFSCK scanning"
1704         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1705         [ "$cur_size" == "$saved_size" ] ||
1706                 error "(7) Expect file1 size $saved_size, but got $cur_size"
1707
1708         if [ $MDSCOUNT -ge 2 ]; then
1709                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1710                 [ "$cur_size" == "$saved_size" ] ||
1711                 error "(8) Expect file2 size $saved_size, but got $cur_size"
1712         fi
1713 }
1714 run_test 18b "Find out orphan OST-object and repair it (2)"
1715
1716 test_18c() {
1717         echo "#####"
1718         echo "The target MDT-object is lost, and the OST-object FID is missing."
1719         echo "The LFSCK should re-create the MDT-object with new FID under the "
1720         echo "directory .lustre/lost+found/MDTxxxx."
1721         echo "#####"
1722
1723         check_mount_and_prep
1724         $LFS mkdir -i 0 $DIR/$tdir/a1
1725         $LFS setstripe -c 1 -i 0 -s 1M $DIR/$tdir/a1
1726
1727         echo "Inject failure, to simulate the case of missing parent FID"
1728         #define OBD_FAIL_LFSCK_NOPFID           0x1617
1729         do_facet ost1 $LCTL set_param fail_loc=0x1617
1730
1731         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1732         $LFS getstripe $DIR/$tdir/a1/f1
1733
1734         if [ $MDSCOUNT -ge 2 ]; then
1735                 $LFS mkdir -i 1 $DIR/$tdir/a2
1736                 $LFS setstripe -c 2 -i 1 -s 1M $DIR/$tdir/a2
1737                 do_facet ost2 $LCTL set_param fail_loc=0x1617
1738                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1739                 $LFS getstripe $DIR/$tdir/a2/f2
1740         fi
1741
1742         cancel_lru_locks osc
1743
1744         echo "Inject failure, to simulate the case of missing the MDT-object"
1745         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
1746         do_facet mds1 $LCTL set_param fail_loc=0x1616
1747         rm -f $DIR/$tdir/a1/f1
1748
1749         if [ $MDSCOUNT -ge 2 ]; then
1750                 do_facet mds2 $LCTL set_param fail_loc=0x1616
1751                 rm -f $DIR/$tdir/a2/f2
1752         fi
1753
1754         sync
1755         sleep 2
1756
1757         do_facet mds1 $LCTL set_param fail_loc=0
1758         if [ $MDSCOUNT -ge 2 ]; then
1759                 do_facet mds2 $LCTL set_param fail_loc=0
1760         fi
1761
1762         cancel_lru_locks mdc
1763         cancel_lru_locks osc
1764
1765         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1766         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
1767
1768         for k in $(seq $MDSCOUNT); do
1769                 # The LFSCK status query internal is 30 seconds. For the case
1770                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1771                 # time to guarantee the status sync up.
1772                 wait_update_facet mds${k} "$LCTL get_param -n \
1773                         mdd.$(facet_svc mds${k}).lfsck_layout |
1774                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1775                         error "(2) MDS${k} is not the expected 'completed'"
1776         done
1777
1778         for k in $(seq $OSTCOUNT); do
1779                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1780                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1781                                 awk '/^status/ { print $2 }')
1782                 [ "$cur_status" == "completed" ] ||
1783                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
1784         done
1785
1786         if [ $MDSCOUNT -ge 2 ]; then
1787                 expected=3
1788         else
1789                 expected=1
1790         fi
1791
1792         local repaired=$(do_facet mds1 $LCTL get_param -n \
1793                          mdd.$(facet_svc mds1).lfsck_layout |
1794                          awk '/^repaired_orphan/ { print $2 }')
1795         [ $repaired -eq $expected ] ||
1796                 error "(4) Expect $expected fixed on mds1, but got: $repaired"
1797
1798         if [ $MDSCOUNT -ge 2 ]; then
1799                 repaired=$(do_facet mds2 $LCTL get_param -n \
1800                            mdd.$(facet_svc mds2).lfsck_layout |
1801                            awk '/^repaired_orphan/ { print $2 }')
1802                 [ $repaired -eq 0 ] ||
1803                         error "(5) Expect 0 fixed on mds2, but got: $repaired"
1804         fi
1805
1806         echo "There should be some stub under .lustre/lost+found/MDT0001/"
1807         ls -ail $MOUNT/.lustre/lost+found/MDT0001/N-* &&
1808                 error "(6) .lustre/lost+found/MDT0001/ should be empty"
1809
1810         echo "There should be some stub under .lustre/lost+found/MDT0000/"
1811         ls -ail $MOUNT/.lustre/lost+found/MDT0000/N-* ||
1812                 error "(7) .lustre/lost+found/MDT0000/ should not be empty"
1813 }
1814 run_test 18c "Find out orphan OST-object and repair it (3)"
1815
1816 test_18d() {
1817         echo "#####"
1818         echo "The target MDT-object layout EA slot is occpuied by some new"
1819         echo "created OST-object when repair dangling reference case. Such"
1820         echo "conflict OST-object has never been modified. Then when found"
1821         echo "the orphan OST-object, LFSCK will replace it with the orphan"
1822         echo "OST-object."
1823         echo "#####"
1824
1825         check_mount_and_prep
1826         mkdir $DIR/$tdir/a1
1827         $LFS setstripe -c 1 -i 0 -s 1M $DIR/$tdir/a1
1828         echo "guard" > $DIR/$tdir/a1/f1
1829         echo "foo" > $DIR/$tdir/a1/f2
1830         local saved_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
1831         $LFS path2fid $DIR/$tdir/a1/f1
1832         $LFS getstripe $DIR/$tdir/a1/f1
1833         $LFS path2fid $DIR/$tdir/a1/f2
1834         $LFS getstripe $DIR/$tdir/a1/f2
1835         cancel_lru_locks osc
1836
1837         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
1838         echo "to reference the same OST-object (which is f1's OST-obejct)."
1839         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
1840         echo "dangling reference case, but f2's old OST-object is there."
1841         echo
1842
1843         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
1844         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
1845         chown 1.1 $DIR/$tdir/a1/f2
1846         rm -f $DIR/$tdir/a1/f1
1847         sync
1848         sleep 2
1849         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1850
1851         echo "stopall to cleanup object cache"
1852         stopall > /dev/null
1853         echo "setupall"
1854         setupall > /dev/null
1855
1856         echo "The file size should be incorrect since dangling referenced"
1857         local cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
1858         [ "$cur_size" != "$saved_size" ] ||
1859                 error "(1) Expect incorrect file2 size"
1860
1861         #define OBD_FAIL_LFSCK_DELAY3           0x1602
1862         do_facet $SINGLEMDS $LCTL set_param fail_val=5 fail_loc=0x1602
1863
1864         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1865         $START_LAYOUT -r -o -c || error "(2) Fail to start LFSCK for layout!"
1866
1867         wait_update_facet mds1 "$LCTL get_param -n \
1868                 mdd.$(facet_svc mds1).lfsck_layout |
1869                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 6 ||
1870                 error "(3.0) MDS1 is not the expected 'scanning-phase2'"
1871
1872         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
1873
1874         for k in $(seq $MDSCOUNT); do
1875                 # The LFSCK status query internal is 30 seconds. For the case
1876                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1877                 # time to guarantee the status sync up.
1878                 wait_update_facet mds${k} "$LCTL get_param -n \
1879                         mdd.$(facet_svc mds${k}).lfsck_layout |
1880                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1881                         error "(3) MDS${k} is not the expected 'completed'"
1882         done
1883
1884         for k in $(seq $OSTCOUNT); do
1885                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1886                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1887                                 awk '/^status/ { print $2 }')
1888                 [ "$cur_status" == "completed" ] ||
1889                 error "(4) OST${k} Expect 'completed', but got '$cur_status'"
1890         done
1891
1892         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
1893                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
1894                          awk '/^repaired_orphan/ { print $2 }')
1895         [ $repaired -eq 1 ] ||
1896                 error "(5) Expect 1 orphan has been fixed, but got: $repaired"
1897
1898         echo "The file size should be correct after layout LFSCK scanning"
1899         cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
1900         [ "$cur_size" == "$saved_size" ] ||
1901                 error "(6) Expect file2 size $saved_size, but got $cur_size"
1902
1903         echo "The LFSCK should find back the original data."
1904         cat $DIR/$tdir/a1/f2
1905         $LFS path2fid $DIR/$tdir/a1/f2
1906         $LFS getstripe $DIR/$tdir/a1/f2
1907 }
1908 run_test 18d "Find out orphan OST-object and repair it (4)"
1909
1910 test_18e() {
1911         echo "#####"
1912         echo "The target MDT-object layout EA slot is occpuied by some new"
1913         echo "created OST-object when repair dangling reference case. Such"
1914         echo "conflict OST-object has been modified by others. To keep the"
1915         echo "new data, the LFSCK will create a new file to refernece this"
1916         echo "old orphan OST-object."
1917         echo "#####"
1918
1919         check_mount_and_prep
1920         mkdir $DIR/$tdir/a1
1921         $LFS setstripe -c 1 -i 0 -s 1M $DIR/$tdir/a1
1922         echo "guard" > $DIR/$tdir/a1/f1
1923         echo "foo" > $DIR/$tdir/a1/f2
1924         local saved_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
1925         $LFS path2fid $DIR/$tdir/a1/f1
1926         $LFS getstripe $DIR/$tdir/a1/f1
1927         $LFS path2fid $DIR/$tdir/a1/f2
1928         $LFS getstripe $DIR/$tdir/a1/f2
1929         cancel_lru_locks osc
1930
1931         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
1932         echo "to reference the same OST-object (which is f1's OST-obejct)."
1933         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
1934         echo "dangling reference case, but f2's old OST-object is there."
1935         echo
1936
1937         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
1938         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
1939         chown 1.1 $DIR/$tdir/a1/f2
1940         rm -f $DIR/$tdir/a1/f1
1941         sync
1942         sleep 2
1943         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1944
1945         echo "stopall to cleanup object cache"
1946         stopall > /dev/null
1947         echo "setupall"
1948         setupall > /dev/null
1949
1950         echo "The file size should be incorrect since dangling referenced"
1951         local cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
1952         [ "$cur_size" != "$saved_size" ] ||
1953                 error "(1) Expect incorrect file2 size"
1954
1955         #define OBD_FAIL_LFSCK_DELAY3           0x1602
1956         do_facet $SINGLEMDS $LCTL set_param fail_val=10 fail_loc=0x1602
1957
1958         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1959         $START_LAYOUT -r -o -c || error "(2) Fail to start LFSCK for layout!"
1960
1961         wait_update_facet mds1 "$LCTL get_param -n \
1962                 mdd.$(facet_svc mds1).lfsck_layout |
1963                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 6 ||
1964                 error "(3) MDS1 is not the expected 'scanning-phase2'"
1965
1966         # to guarantee all updates are synced.
1967         sync
1968         sleep 2
1969
1970         echo "Write new data to f2 to modify the new created OST-object."
1971         echo "dummy" >> $DIR/$tdir/a1/f2
1972
1973         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
1974
1975         for k in $(seq $MDSCOUNT); do
1976                 # The LFSCK status query internal is 30 seconds. For the case
1977                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1978                 # time to guarantee the status sync up.
1979                 wait_update_facet mds${k} "$LCTL get_param -n \
1980                         mdd.$(facet_svc mds${k}).lfsck_layout |
1981                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1982                         error "(4) MDS${k} is not the expected 'completed'"
1983         done
1984
1985         for k in $(seq $OSTCOUNT); do
1986                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1987                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1988                                 awk '/^status/ { print $2 }')
1989                 [ "$cur_status" == "completed" ] ||
1990                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
1991         done
1992
1993         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
1994                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
1995                          awk '/^repaired_orphan/ { print $2 }')
1996         [ $repaired -eq 1 ] ||
1997                 error "(6) Expect 1 orphan has been fixed, but got: $repaired"
1998
1999         echo "There should be stub file under .lustre/lost+found/MDT0000/"
2000         local cname=$(ls $MOUNT/.lustre/lost+found/MDT0000/C-*)
2001         [ ! -z $name ] ||
2002                 error "(7) .lustre/lost+found/MDT0000/ should not be empty"
2003
2004         echo "The stub file should keep the original f2 data"
2005         cur_size=$(ls -il $cname | awk '{ print $6 }')
2006         [ "$cur_size" == "$saved_size" ] ||
2007                 error "(8) Expect file2 size $saved_size, but got $cur_size"
2008
2009         cat $cname
2010         $LFS path2fid $cname
2011         $LFS getstripe $cname
2012
2013         echo "The f2 should contains new data."
2014         cat $DIR/$tdir/a1/f2
2015         $LFS path2fid $DIR/$tdir/a1/f2
2016         $LFS getstripe $DIR/$tdir/a1/f2
2017 }
2018 run_test 18e "Find out orphan OST-object and repair it (5)"
2019
2020 test_19a() {
2021         check_mount_and_prep
2022         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2023
2024         echo "foo" > $DIR/$tdir/a0
2025         echo "guard" > $DIR/$tdir/a1
2026         cancel_lru_locks osc
2027
2028         echo "Inject failure, then client will offer wrong parent FID when read"
2029         do_facet ost1 $LCTL set_param -n \
2030                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2031         #define OBD_FAIL_LFSCK_INVALID_PFID     0x1619
2032         $LCTL set_param fail_loc=0x1619
2033
2034         echo "Read RPC with wrong parent FID should be denied"
2035         cat $DIR/$tdir/a0 && error "(3) Read should be denied!"
2036         $LCTL set_param fail_loc=0
2037 }
2038 run_test 19a "OST-object inconsistency self detect"
2039
2040 test_19b() {
2041         check_mount_and_prep
2042         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2043
2044         echo "Inject failure stub to make the OST-object to back point to"
2045         echo "non-exist MDT-object"
2046
2047         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
2048         do_facet ost1 $LCTL set_param fail_loc=0x1611
2049         echo "foo" > $DIR/$tdir/f0
2050         cancel_lru_locks osc
2051         do_facet ost1 $LCTL set_param fail_loc=0
2052
2053         echo "Nothing should be fixed since self detect and repair is disabled"
2054         local repaired=$(do_facet ost1 $LCTL get_param -n \
2055                         obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2056                         awk '/^repaired/ { print $2 }')
2057         [ $repaired -eq 0 ] ||
2058                 error "(1) Expected 0 repaired, but got $repaired"
2059
2060         echo "Read RPC with right parent FID should be accepted,"
2061         echo "and cause parent FID on OST to be fixed"
2062
2063         do_facet ost1 $LCTL set_param -n \
2064                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2065         cat $DIR/$tdir/f0 || error "(2) Read should not be denied!"
2066
2067         repaired=$(do_facet ost1 $LCTL get_param -n \
2068                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2069                 awk '/^repaired/ { print $2 }')
2070         [ $repaired -eq 1 ] ||
2071                 error "(3) Expected 1 repaired, but got $repaired"
2072 }
2073 run_test 19b "OST-object inconsistency self repair"
2074
2075 test_20() {
2076         [ $OSTCOUNT -lt 2 ] &&
2077                 skip "The test needs at least 2 OSTs" && return
2078
2079         echo "#####"
2080         echo "The target MDT-object and some of its OST-object are lost."
2081         echo "The LFSCK should find out the left OST-objects and re-create"
2082         echo "the MDT-object under the direcotry .lustre/lost+found/MDTxxxx/"
2083         echo "with the partial OST-objects (LOV EA hole)."
2084
2085         echo "New client can access the file with LOV EA hole via normal"
2086         echo "system tools or commands without crash the system."
2087
2088         echo "For old client, even though it cannot access the file with"
2089         echo "LOV EA hole, it should not cause the system crash."
2090         echo "#####"
2091
2092         check_mount_and_prep
2093         $LFS mkdir -i 0 $DIR/$tdir/a1
2094         if [ $OSTCOUNT -gt 2 ]; then
2095                 $LFS setstripe -c 3 -i 0 -s 1M $DIR/$tdir/a1
2096                 bcount=513
2097         else
2098                 $LFS setstripe -c 2 -i 0 -s 1M $DIR/$tdir/a1
2099                 bcount=257
2100         fi
2101
2102         # 256 blocks on the stripe0.
2103         # 1 block on the stripe1 for 2 OSTs case.
2104         # 256 blocks on the stripe1 for other cases.
2105         # 1 block on the stripe2 if OSTs > 2
2106         dd if=/dev/zero of=$DIR/$tdir/a1/f0 bs=4096 count=$bcount
2107         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=4096 count=$bcount
2108         dd if=/dev/zero of=$DIR/$tdir/a1/f2 bs=4096 count=$bcount
2109
2110         local fid0=$($LFS path2fid $DIR/$tdir/a1/f0)
2111         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
2112         local fid2=$($LFS path2fid $DIR/$tdir/a1/f2)
2113
2114         echo ${fid0}
2115         $LFS getstripe $DIR/$tdir/a1/f0
2116         echo ${fid1}
2117         $LFS getstripe $DIR/$tdir/a1/f1
2118         echo ${fid2}
2119         $LFS getstripe $DIR/$tdir/a1/f2
2120
2121         if [ $OSTCOUNT -gt 2 ]; then
2122                 dd if=/dev/zero of=$DIR/$tdir/a1/f3 bs=4096 count=$bcount
2123                 fid3=$($LFS path2fid $DIR/$tdir/a1/f3)
2124                 echo ${fid3}
2125                 $LFS getstripe $DIR/$tdir/a1/f3
2126         fi
2127
2128         cancel_lru_locks osc
2129
2130         echo "Inject failure..."
2131         echo "To simulate f0 lost MDT-object"
2132         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2133         do_facet mds1 $LCTL set_param fail_loc=0x1616
2134         rm -f $DIR/$tdir/a1/f0
2135
2136         echo "To simulate f1 lost MDT-object and OST-object0"
2137         #define OBD_FAIL_LFSCK_LOST_SPEOBJ      0x161a
2138         do_facet mds1 $LCTL set_param fail_loc=0x161a
2139         rm -f $DIR/$tdir/a1/f1
2140
2141         echo "To simulate f2 lost MDT-object and OST-object1"
2142         do_facet mds1 $LCTL set_param fail_val=1
2143         rm -f $DIR/$tdir/a1/f2
2144
2145         if [ $OSTCOUNT -gt 2 ]; then
2146                 echo "To simulate f3 lost MDT-object and OST-object2"
2147                 do_facet mds1 $LCTL set_param fail_val=2
2148                 rm -f $DIR/$tdir/a1/f3
2149         fi
2150
2151         umount_client $MOUNT
2152         sync
2153         sleep 2
2154         do_facet mds1 $LCTL set_param fail_loc=0 fail_val=0
2155
2156         echo "Inject failure to slow down the LFSCK on OST0"
2157         #define OBD_FAIL_LFSCK_DELAY5           0x161b
2158         do_facet ost1 $LCTL set_param fail_loc=0x161b
2159
2160         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2161         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2162
2163         sleep 3
2164         do_facet ost1 $LCTL set_param fail_loc=0
2165
2166         for k in $(seq $MDSCOUNT); do
2167                 # The LFSCK status query internal is 30 seconds. For the case
2168                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2169                 # time to guarantee the status sync up.
2170                 wait_update_facet mds${k} "$LCTL get_param -n \
2171                         mdd.$(facet_svc mds${k}).lfsck_layout |
2172                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
2173                         error "(2) MDS${k} is not the expected 'completed'"
2174         done
2175
2176         for k in $(seq $OSTCOUNT); do
2177                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2178                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2179                                 awk '/^status/ { print $2 }')
2180                 [ "$cur_status" == "completed" ] ||
2181                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2182         done
2183
2184         local repaired=$(do_facet mds1 $LCTL get_param -n \
2185                          mdd.$(facet_svc mds1).lfsck_layout |
2186                          awk '/^repaired_orphan/ { print $2 }')
2187         if [ $OSTCOUNT -gt 2 ]; then
2188                 [ $repaired -eq 9 ] ||
2189                         error "(4.1) Expect 9 fixed on mds1, but got: $repaired"
2190         else
2191                 [ $repaired -eq 4 ] ||
2192                         error "(4.2) Expect 4 fixed on mds1, but got: $repaired"
2193         fi
2194
2195         mount_client $MOUNT || error "(5.0) Fail to start client!"
2196
2197         LOV_PATTERN_F_HOLE=0x40000000
2198
2199         #
2200         # R-${fid0} is the old f0
2201         #
2202         local name="$MOUNT/.lustre/lost+found/MDT0000/R-${fid0}"
2203         echo "Check $name, which is the old f0"
2204
2205         $LFS getstripe -v $name || error "(5.1) cannot getstripe on $name"
2206
2207         local pattern=0x$($LFS getstripe -L $name)
2208         [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2209                 error "(5.2) NOT expect pattern flag hole, but got $pattern"
2210
2211         local stripes=$($LFS getstripe -c $name)
2212         if [ $OSTCOUNT -gt 2 ]; then
2213                 [ $stripes -eq 3 ] ||
2214                 error "(5.3.1) expect the stripe count is 3, but got $stripes"
2215         else
2216                 [ $stripes -eq 2 ] ||
2217                 error "(5.3.2) expect the stripe count is 2, but got $stripes"
2218         fi
2219
2220         local size=$(stat $name | awk '/Size:/ { print $2 }')
2221         [ $size -eq $((4096 * $bcount)) ] ||
2222                 error "(5.4) expect the size $((4096 * $bcount)), but got $size"
2223
2224         cat $name > /dev/null || error "(5.5) cannot read $name"
2225
2226         echo "dummy" >> $name || error "(5.6) cannot write $name"
2227
2228         chown $RUNAS_ID:$RUNAS_GID $name || error "(5.7) cannot chown on $name"
2229
2230         touch $name || error "(5.8) cannot touch $name"
2231
2232         rm -f $name || error "(5.9) cannot unlink $name"
2233
2234         #
2235         # R-${fid1} contains the old f1's stripe1 (and stripe2 if OSTs > 2)
2236         #
2237         name="$MOUNT/.lustre/lost+found/MDT0000/R-${fid1}"
2238         if [ $OSTCOUNT -gt 2 ]; then
2239                 echo "Check $name, it contains the old f1's stripe1 and stripe2"
2240         else
2241                 echo "Check $name, it contains the old f1's stripe1"
2242         fi
2243
2244         $LFS getstripe -v $name || error "(6.1) cannot getstripe on $name"
2245
2246         pattern=0x$($LFS getstripe -L $name)
2247         [[ $((pattern & LOV_PATTERN_F_HOLE)) -ne 0 ]] ||
2248                 error "(6.2) expect pattern flag hole, but got $pattern"
2249
2250         stripes=$($LFS getstripe -c $name)
2251         if [ $OSTCOUNT -gt 2 ]; then
2252                 [ $stripes -eq 3 ] ||
2253                 error "(6.3.1) expect the stripe count is 3, but got $stripes"
2254         else
2255                 [ $stripes -eq 2 ] ||
2256                 error "(6.3.2) expect the stripe count is 2, but got $stripes"
2257         fi
2258
2259         size=$(stat $name | awk '/Size:/ { print $2 }')
2260         [ $size -eq $((4096 * $bcount)) ] ||
2261                 error "(6.4) expect the size $((4096 * $bcount)), but got $size"
2262
2263         cat $name > /dev/null && error "(6.5) normal read $name should fail"
2264
2265         local failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
2266                          bs=4096 2>&1 | grep "Input/output error" | wc -l)
2267
2268         # stripe0 is dummy
2269         [ $failures -eq 256 ] ||
2270                 error "(6.6) expect 256 IO failures, but get $failures"
2271
2272         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
2273         [ $size -eq $((4096 * $bcount)) ] ||
2274                 error "(6.7) expect the size $((4096 * $bcount)), but got $size"
2275
2276         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 &&
2277                 error "(6.8) write to the LOV EA hole should fail"
2278
2279         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 seek=300 ||
2280                 error "(6.9) write to normal stripe should NOT fail"
2281
2282         echo "foo" >> $name && error "(6.10) append write $name should fail"
2283
2284         chown $RUNAS_ID:$RUNAS_GID $name || error "(6.11) cannot chown on $name"
2285
2286         touch $name || error "(6.12) cannot touch $name"
2287
2288         rm -f $name || error "(6.13) cannot unlink $name"
2289
2290         #
2291         # R-${fid2} it contains the old f2's stripe0 (and stripe2 if OSTs > 2)
2292         #
2293         name="$MOUNT/.lustre/lost+found/MDT0000/R-${fid2}"
2294         if [ $OSTCOUNT -gt 2 ]; then
2295                 echo "Check $name, it contains the old f2's stripe0 and stripe2"
2296         else
2297                 echo "Check $name, it contains the old f2's stripe0"
2298         fi
2299
2300         $LFS getstripe -v $name || error "(7.1) cannot getstripe on $name"
2301
2302         pattern=0x$($LFS getstripe -L $name)
2303         stripes=$($LFS getstripe -c $name)
2304         size=$(stat $name | awk '/Size:/ { print $2 }')
2305         if [ $OSTCOUNT -gt 2 ]; then
2306                 [[ $((pattern & LOV_PATTERN_F_HOLE)) -ne 0 ]] ||
2307                 error "(7.2.1) expect pattern flag hole, but got $pattern"
2308
2309                 [ $stripes -eq 3 ] ||
2310                 error "(7.3.1) expect the stripe count is 3, but got $stripes"
2311
2312                 [ $size -eq $((4096 * $bcount)) ] ||
2313                 error "(7.4.1) expect size $((4096 * $bcount)), but got $size"
2314
2315                 cat $name > /dev/null &&
2316                         error "(7.5.1) normal read $name should fail"
2317
2318                 failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
2319                            bs=4096 2>&1 | grep "Input/output error" | wc -l)
2320                 # stripe1 is dummy
2321                 [ $failures -eq 256 ] ||
2322                         error "(7.6) expect 256 IO failures, but get $failures"
2323
2324                 size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
2325                 [ $size -eq $((4096 * $bcount)) ] ||
2326                 error "(7.7) expect the size $((4096 * $bcount)), but got $size"
2327
2328                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
2329                 seek=300 && error "(7.8.0) write to the LOV EA hole should fail"
2330
2331                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 ||
2332                 error "(7.8.1) write to normal stripe should NOT fail"
2333
2334                 echo "foo" >> $name &&
2335                         error "(7.8.3) append write $name should fail"
2336
2337                 chown $RUNAS_ID:$RUNAS_GID $name ||
2338                         error "(7.9.1) cannot chown on $name"
2339
2340                 touch $name || error "(7.10.1) cannot touch $name"
2341         else
2342                 [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2343                 error "(7.2.2) NOT expect pattern flag hole, but got $pattern"
2344
2345                 [ $stripes -eq 1 ] ||
2346                 error "(7.3.2) expect the stripe count is 1, but got $stripes"
2347
2348                 # stripe1 is dummy
2349                 [ $size -eq $((4096 * (256 + 0))) ] ||
2350                 error "(7.4.2) expect the size $((4096 * 256)), but got $size"
2351
2352                 cat $name > /dev/null || error "(7.5.2) cannot read $name"
2353
2354                 echo "dummy" >> $name || error "(7.8.2) cannot write $name"
2355
2356                 chown $RUNAS_ID:$RUNAS_GID $name ||
2357                         error "(7.9.2) cannot chown on $name"
2358
2359                 touch $name || error "(7.10.2) cannot touch $name"
2360         fi
2361
2362         rm -f $name || error "(7.11) cannot unlink $name"
2363
2364         [ $OSTCOUNT -le 2 ] && return
2365
2366         #
2367         # R-${fid3} should contains the old f3's stripe0 and stripe1
2368         #
2369         name="$MOUNT/.lustre/lost+found/MDT0000/R-${fid3}"
2370         echo "Check $name, which contains the old f3's stripe0 and stripe1"
2371
2372         $LFS getstripe -v $name || error "(8.1) cannot getstripe on $name"
2373
2374         pattern=0x$($LFS getstripe -L $name)
2375         [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2376                 error "(8.2) NOT expect pattern flag hole, but got $pattern"
2377
2378         stripes=$($LFS getstripe -c $name)
2379         # LFSCK does not know the old f3 had 3 stripes.
2380         # It only tries to find as much as possible.
2381         # The stripe count depends on the last stripe's offset.
2382         [ $stripes -eq 2 ] ||
2383                 error "(8.3) expect the stripe count is 2, but got $stripes"
2384
2385         size=$(stat $name | awk '/Size:/ { print $2 }')
2386         # stripe2 is lost
2387         [ $size -eq $((4096 * (256 + 256 + 0))) ] ||
2388                 error "(8.4) expect the size $((4096 * 512)), but got $size"
2389
2390         cat $name > /dev/null || error "(8.5) cannot read $name"
2391
2392         echo "dummy" >> $name || error "(8.6) cannot write $name"
2393
2394         chown $RUNAS_ID:$RUNAS_GID $name ||
2395                 error "(8.7) cannot chown on $name"
2396
2397         touch $name || error "(8.8) cannot touch $name"
2398
2399         rm -f $name || error "(8.9) cannot unlink $name"
2400 }
2401 run_test 20 "Handle the orphan with dummy LOV EA slot properly"
2402
2403 $LCTL set_param debug=-lfsck > /dev/null || true
2404
2405 # restore MDS/OST size
2406 MDSSIZE=${SAVED_MDSSIZE}
2407 OSTSIZE=${SAVED_OSTSIZE}
2408 OSTCOUNT=${SAVED_OSTCOUNT}
2409
2410 # cleanup the system at last
2411 formatall
2412
2413 complete $SECONDS
2414 exit_status