Whamcloud - gitweb
LU-8998 pfl: test cases for lfsck on PFL
[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
11 #Bug number for excepting test
12 ALWAYS_EXCEPT="$SANITY_LFSCK_EXCEPT"
13
14 [ "$SLOW" = "no" ] && EXCEPT_SLOW=""
15 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
16
17 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
18 . $LUSTRE/tests/test-framework.sh
19 init_test_env $@
20 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
21 init_logging
22
23 require_dsh_mds || exit 0
24
25 load_modules
26
27 if ! check_versions; then
28         skip "It is NOT necessary to test lfsck under interoperation mode"
29         exit 0
30 fi
31
32 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.60) ]] &&
33         skip "Need MDS version at least 2.3.60" && exit 0
34
35 LTIME=${LTIME:-120}
36
37 SAVED_MDSSIZE=${MDSSIZE}
38 SAVED_OSTSIZE=${OSTSIZE}
39 SAVED_OSTCOUNT=${OSTCOUNT}
40 # use small MDS + OST size to speed formatting time
41 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
42 MDSSIZE=100000
43 OSTSIZE=100000
44 # no need too many OSTs, to reduce the format/start/stop overhead
45 [ $OSTCOUNT -gt 4 ] && OSTCOUNT=4
46
47 # build up a clean test environment.
48 formatall
49 setupall
50
51 [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.4.90) ]] &&
52         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2c"
53
54 [[ $(lustre_version_code ost1) -lt $(version_code 2.5.55) ]] &&
55         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 11 12 13 14 15 16 17 18 19 20 21"
56
57 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.50) ]] &&
58         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2d 2e 3 22 23 24 25 26 27 28 29 30 31"
59
60 # DNE does not support striped directory on zfs-based backend yet.
61 [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
62         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 31"
63
64 build_test_filter
65
66 MDT_DEV="${FSNAME}-MDT0000"
67 OST_DEV="${FSNAME}-OST0000"
68 MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/})
69 START_NAMESPACE="do_facet $SINGLEMDS \
70                 $LCTL lfsck_start -M ${MDT_DEV} -t namespace"
71 START_LAYOUT="do_facet $SINGLEMDS \
72                 $LCTL lfsck_start -M ${MDT_DEV} -t layout"
73 START_LAYOUT_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV} -t layout"
74 STOP_LFSCK="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
75 SHOW_NAMESPACE="do_facet $SINGLEMDS \
76                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_namespace"
77 SHOW_LAYOUT="do_facet $SINGLEMDS \
78                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_layout"
79 SHOW_LAYOUT_ON_OST="do_facet ost1 \
80                 $LCTL get_param -n obdfilter.${OST_DEV}.lfsck_layout"
81 MOUNT_OPTS_SCRUB="-o user_xattr"
82 MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
83 MOUNT_OPTS_SKIP_LFSCK="-o user_xattr,skip_lfsck"
84
85 lfsck_prep() {
86         local ndirs=$1
87         local nfiles=$2
88         local igif=$3
89
90         check_mount_and_prep
91
92         echo "preparing... $nfiles * $ndirs files will be created $(date)."
93         if [ ! -z $igif ]; then
94                 #define OBD_FAIL_FID_IGIF       0x1504
95                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1504
96         fi
97
98         cp $LUSTRE/tests/*.sh $DIR/$tdir/
99         if [ $ndirs -gt 0 ]; then
100                 createmany -d $DIR/$tdir/d $ndirs
101                 createmany -m $DIR/$tdir/f $ndirs
102                 if [ $nfiles -gt 0 ]; then
103                         for ((i = 0; i < $ndirs; i++)); do
104                                 createmany -m $DIR/$tdir/d${i}/f $nfiles > \
105                                         /dev/null || error "createmany $nfiles"
106                         done
107                 fi
108                 createmany -d $DIR/$tdir/e $ndirs
109         fi
110
111         if [ ! -z $igif ]; then
112                 touch $DIR/$tdir/dummy
113                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0
114         fi
115
116         echo "prepared $(date)."
117 }
118
119 run_e2fsck_on_mdt0() {
120         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] && return
121
122         stop $SINGLEMDS > /dev/null || error "(0) Fail to the stop MDT0"
123         run_e2fsck $(facet_active_host $SINGLEMDS) $(mdsdevname 1) "-n" |
124                 grep "Fix? no" && {
125                 run_e2fsck $(facet_active_host $SINGLEMDS) $(mdsdevname 1) "-n"
126                 error "(2) Detected inconsistency on MDT0"
127         }
128         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
129                 error "(3) Fail to start MDT0"
130 }
131
132 wait_all_targets_blocked() {
133         local com=$1
134         local status=$2
135         local err=$3
136
137         local count=$(do_facet mds1 \
138                      "$LCTL lfsck_query -t $com -M ${FSNAME}-MDT0000 -w |
139                       awk '/^${com}_mdts_${status}/ { print \\\$2 }'")
140         [[ $count -eq $MDSCOUNT ]] || {
141                 do_facet mds1 "$LCTL lfsck_query -t $com -M ${FSNAME}-MDT0000"
142                 error "($err) only $count of $MDSCOUNT MDTs are in ${status}"
143         }
144 }
145
146 wait_all_targets() {
147         local com=$1
148         local status=$2
149         local err=$3
150
151         wait_update_facet mds1 "$LCTL lfsck_query -t $com -M ${FSNAME}-MDT0000 |
152                 awk '/^${com}_mdts_${status}/ { print \\\$2 }'" \
153                 "$MDSCOUNT" $LTIME || {
154                 do_facet mds1 "$LCTL lfsck_query -t $com -M ${FSNAME}-MDT0000"
155                 error "($err) some MDTs are not in ${status}"
156         }
157 }
158
159 test_0() {
160         lfsck_prep 3 3
161
162         #define OBD_FAIL_LFSCK_DELAY1           0x1600
163         do_facet $SINGLEMDS $LCTL set_param fail_val=3 fail_loc=0x1600
164         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
165
166         $SHOW_NAMESPACE || error "Fail to monitor LFSCK (3)"
167
168         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
169         [ "$STATUS" == "scanning-phase1" ] ||
170                 error "(4) Expect 'scanning-phase1', but got '$STATUS'"
171
172         $STOP_LFSCK || error "(5) Fail to stop LFSCK!"
173
174         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
175         [ "$STATUS" == "stopped" ] ||
176                 error "(6) Expect 'stopped', but got '$STATUS'"
177
178         $START_NAMESPACE || error "(7) Fail to start LFSCK for namespace!"
179
180         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
181         [ "$STATUS" == "scanning-phase1" ] ||
182                 error "(8) Expect 'scanning-phase1', but got '$STATUS'"
183
184         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
185         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
186                 mdd.${MDT_DEV}.lfsck_namespace |
187                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
188                 $SHOW_NAMESPACE
189                 error "(9) unexpected status"
190         }
191
192         local repaired=$($SHOW_NAMESPACE |
193                          awk '/^updated_phase1/ { print $2 }')
194         [ $repaired -eq 0 ] ||
195                 error "(10) Expect nothing to be repaired, but got: $repaired"
196
197         local scanned1=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
198         $START_NAMESPACE -r || error "(11) Fail to reset LFSCK!"
199         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
200                 mdd.${MDT_DEV}.lfsck_namespace |
201                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
202                 $SHOW_NAMESPACE
203                 error "(12) unexpected status"
204         }
205
206         local scanned2=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
207         [ $((scanned1 + 1)) -eq $scanned2 ] ||
208                 error "(13) Expect success $((scanned1 + 1)), but got $scanned2"
209
210         echo "stopall, should NOT crash LU-3649"
211         stopall || error "(14) Fail to stopall"
212 }
213 run_test 0 "Control LFSCK manually"
214
215 test_1a() {
216         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
217                 skip "OI Scrub not implemented for ZFS" && return
218
219         lfsck_prep 1 1
220
221         #define OBD_FAIL_FID_INDIR      0x1501
222         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1501
223         touch $DIR/$tdir/dummy
224
225         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
226         umount_client $MOUNT
227         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
228         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
229                 mdd.${MDT_DEV}.lfsck_namespace |
230                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
231                 $SHOW_NAMESPACE
232                 error "(4) unexpected status"
233         }
234
235         local repaired=$($SHOW_NAMESPACE |
236                          awk '/^dirent_repaired/ { print $2 }')
237         # for interop with old server
238         [ -z "$repaired" ] &&
239                 repaired=$($SHOW_NAMESPACE |
240                          awk '/^updated_phase1/ { print $2 }')
241
242         [ $repaired -eq 1 ] ||
243                 error "(5) Fail to repair crashed FID-in-dirent: $repaired"
244
245         run_e2fsck_on_mdt0
246
247         mount_client $MOUNT || error "(6) Fail to start client!"
248
249         #define OBD_FAIL_FID_LOOKUP     0x1505
250         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
251         ls $DIR/$tdir/ > /dev/null || error "(7) no FID-in-dirent."
252
253         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
254 }
255 run_test 1a "LFSCK can find out and repair crashed FID-in-dirent"
256
257 test_1b()
258 {
259         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
260                 skip "OI Scrub not implemented for ZFS" && return
261
262         lfsck_prep 1 1
263
264         #define OBD_FAIL_FID_INLMA      0x1502
265         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1502
266         touch $DIR/$tdir/dummy
267
268         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
269         umount_client $MOUNT
270         #define OBD_FAIL_FID_NOLMA      0x1506
271         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1506
272         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
273         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
274                 mdd.${MDT_DEV}.lfsck_namespace |
275                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
276                 $SHOW_NAMESPACE
277                 error "(4) unexpected status"
278         }
279
280         local repaired=$($SHOW_NAMESPACE |
281                          awk '/^dirent_repaired/ { print $2 }')
282         # for interop with old server
283         [ -z "$repaired" ] &&
284                 repaired=$($SHOW_NAMESPACE |
285                          awk '/^updated_phase1/ { print $2 }')
286
287         [ $repaired -eq 1 ] ||
288                 error "(5) Fail to repair the missing FID-in-LMA: $repaired"
289
290         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
291         run_e2fsck_on_mdt0
292
293         mount_client $MOUNT || error "(6) Fail to start client!"
294
295         #define OBD_FAIL_FID_LOOKUP     0x1505
296         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
297         stat $DIR/$tdir/dummy > /dev/null || error "(7) no FID-in-LMA."
298
299         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
300 }
301 run_test 1b "LFSCK can find out and repair the missing FID-in-LMA"
302
303 test_2a() {
304         lfsck_prep 1 1
305
306         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
307         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
308         touch $DIR/$tdir/dummy
309
310         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
311         umount_client $MOUNT
312         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
313         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
314                 mdd.${MDT_DEV}.lfsck_namespace |
315                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
316                 $SHOW_NAMESPACE
317                 error "(4) unexpected status"
318         }
319
320         local repaired=$($SHOW_NAMESPACE |
321                          awk '/^linkea_repaired/ { print $2 }')
322         # for interop with old server
323         [ -z "$repaired" ] &&
324                 repaired=$($SHOW_NAMESPACE |
325                          awk '/^updated_phase2/ { print $2 }')
326
327         [ $repaired -eq 1 ] ||
328                 error "(5) Fail to repair crashed linkEA: $repaired"
329
330         run_e2fsck_on_mdt0
331
332         mount_client $MOUNT || error "(6) Fail to start client!"
333
334         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
335                 error "(7) Fail to stat $DIR/$tdir/dummy"
336
337         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
338         local dummyname=$($LFS fid2path $DIR $dummyfid)
339         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
340                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
341 }
342 run_test 2a "LFSCK can find out and repair crashed linkEA entry"
343
344 test_2b()
345 {
346         lfsck_prep 1 1
347
348         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
349         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
350         touch $DIR/$tdir/dummy
351
352         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
353         umount_client $MOUNT
354         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
355         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
356                 mdd.${MDT_DEV}.lfsck_namespace |
357                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
358                 $SHOW_NAMESPACE
359                 error "(4) unexpected status"
360         }
361
362         local repaired=$($SHOW_NAMESPACE |
363                          awk '/^updated_phase2/ { print $2 }')
364         [ $repaired -eq 1 ] ||
365                 error "(5) Fail to repair crashed linkEA: $repaired"
366
367         run_e2fsck_on_mdt0
368
369         mount_client $MOUNT || error "(6) Fail to start client!"
370
371         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
372                 error "(7) Fail to stat $DIR/$tdir/dummy"
373
374         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
375         local dummyname=$($LFS fid2path $DIR $dummyfid)
376         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
377                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
378 }
379 run_test 2b "LFSCK can find out and remove invalid linkEA entry"
380
381 test_2c()
382 {
383         lfsck_prep 1 1
384
385         #define OBD_FAIL_LFSCK_LINKEA_MORE2     0x1605
386         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1605
387         touch $DIR/$tdir/dummy
388
389         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
390         umount_client $MOUNT
391         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
392         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
393                 mdd.${MDT_DEV}.lfsck_namespace |
394                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
395                 $SHOW_NAMESPACE
396                 error "(4) unexpected status"
397         }
398
399         local repaired=$($SHOW_NAMESPACE |
400                          awk '/^updated_phase2/ { print $2 }')
401         [ $repaired -eq 1 ] ||
402                 error "(5) Fail to repair crashed linkEA: $repaired"
403
404         run_e2fsck_on_mdt0
405
406         mount_client $MOUNT || error "(6) Fail to start client!"
407
408         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
409                 error "(7) Fail to stat $DIR/$tdir/dummy"
410
411         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
412         local dummyname=$($LFS fid2path $DIR $dummyfid)
413         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
414                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
415 }
416 run_test 2c "LFSCK can find out and remove repeated linkEA entry"
417
418 test_2d()
419 {
420         lfsck_prep 1 1
421
422         #define OBD_FAIL_LFSCK_NO_LINKEA        0x161d
423         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161d
424         touch $DIR/$tdir/dummy
425
426         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
427         umount_client $MOUNT
428         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
429         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
430                 mdd.${MDT_DEV}.lfsck_namespace |
431                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
432                 $SHOW_NAMESPACE
433                 error "(4) unexpected status"
434         }
435
436         local repaired=$($SHOW_NAMESPACE |
437                          awk '/^linkea_repaired/ { print $2 }')
438         [ $repaired -eq 1 ] ||
439                 error "(5) Fail to repair crashed linkEA: $repaired"
440
441         run_e2fsck_on_mdt0
442
443         mount_client $MOUNT || error "(6) Fail to start client!"
444
445         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
446                 error "(7) Fail to stat $DIR/$tdir/dummy"
447
448         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
449         local dummyname=$($LFS fid2path $DIR $dummyfid)
450         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
451                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
452 }
453 run_test 2d "LFSCK can recover the missing linkEA entry"
454
455 test_2e()
456 {
457         [ $MDSCOUNT -lt 2 ] &&
458                 skip "We need at least 2 MDSes for this test" && return
459
460         check_mount_and_prep
461
462         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT1"
463
464         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
465         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
466         $LFS mkdir -i 0 $DIR/$tdir/d0/d1 || error "(2) Fail to mkdir d1 on MDT0"
467         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
468
469         $START_NAMESPACE -r -A || error "(3) Fail to start LFSCK for namespace!"
470
471         wait_all_targets_blocked namespace completed 4
472
473         local repaired=$($SHOW_NAMESPACE |
474                          awk '/^linkea_repaired/ { print $2 }')
475         [ $repaired -eq 1 ] ||
476                 error "(5) Fail to repair crashed linkEA: $repaired"
477
478         local fid=$($LFS path2fid $DIR/$tdir/d0/d1)
479         local name=$($LFS fid2path $DIR $fid)
480         [ "$name" == "$DIR/$tdir/d0/d1" ] ||
481                 error "(6) Fail to repair linkEA: $fid $name"
482 }
483 run_test 2e "namespace LFSCK can verify remote object linkEA"
484
485 test_3()
486 {
487         lfsck_prep 4 4
488
489         mkdir $DIR/$tdir/dummy || error "(1) Fail to mkdir"
490         ln $DIR/$tdir/d0/f0 $DIR/$tdir/dummy/f0 || error "(2) Fail to hardlink"
491         ln $DIR/$tdir/d0/f1 $DIR/$tdir/dummy/f1 || error "(3) Fail to hardlink"
492
493         $LFS mkdir -i 0 $DIR/$tdir/edir || error "(4) Fail to mkdir"
494         touch $DIR/$tdir/edir/f0 || error "(5) Fail to touch"
495         touch $DIR/$tdir/edir/f1 || error "(6) Fail to touch"
496
497         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
498         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
499         ln $DIR/$tdir/edir/f0 $DIR/$tdir/edir/w0 || error "(7) Fail to hardlink"
500
501         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
502         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
503         ln $DIR/$tdir/edir/f1 $DIR/$tdir/edir/w1 || error "(8) Fail to hardlink"
504
505         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
506
507         $START_NAMESPACE -r || error "(9) Fail to start LFSCK for namespace!"
508         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
509                 mdd.${MDT_DEV}.lfsck_namespace |
510                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
511                 $SHOW_NAMESPACE
512                 error "(10) unexpected status"
513         }
514
515         local checked=$($SHOW_NAMESPACE |
516                         awk '/^checked_phase2/ { print $2 }')
517         [ $checked -ge 4 ] ||
518                 error "(11) Fail to check multiple-linked object: $checked"
519
520         local repaired=$($SHOW_NAMESPACE |
521                          awk '/^multiple_linked_repaired/ { print $2 }')
522         [ $repaired -ge 2 ] ||
523                 error "(12) Fail to repair multiple-linked object: $repaired"
524 }
525 run_test 3 "LFSCK can verify multiple-linked objects"
526
527 test_4()
528 {
529         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
530                 skip "OI Scrub not implemented for ZFS" && return
531
532         lfsck_prep 3 3
533         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
534         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
535
536         mds_backup_restore $SINGLEMDS || error "(1) Fail to backup/restore!"
537         echo "start $SINGLEMDS with disabling OI scrub"
538         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
539                 error "(2) Fail to start MDS!"
540
541         #define OBD_FAIL_LFSCK_DELAY2           0x1601
542         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
543         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
544         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
545                 mdd.${MDT_DEV}.lfsck_namespace |
546                 awk '/^flags/ { print \\\$2 }'" "inconsistent" 32 || {
547                 $SHOW_NAMESPACE
548                 error "(5) unexpected status"
549         }
550
551         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
552         [ "$STATUS" == "scanning-phase1" ] ||
553                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
554
555         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
556         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
557                 mdd.${MDT_DEV}.lfsck_namespace |
558                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
559                 $SHOW_NAMESPACE
560                 error "(7) unexpected status"
561         }
562
563         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
564         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
565
566         local repaired=$($SHOW_NAMESPACE |
567                          awk '/^dirent_repaired/ { print $2 }')
568         # for interop with old server
569         [ -z "$repaired" ] &&
570                 repaired=$($SHOW_NAMESPACE |
571                          awk '/^updated_phase1/ { print $2 }')
572
573         [ $repaired -ge 9 ] ||
574                 error "(9) Fail to re-generate FID-in-dirent: $repaired"
575
576         run_e2fsck_on_mdt0
577
578         mount_client $MOUNT || error "(10) Fail to start client!"
579
580         #define OBD_FAIL_FID_LOOKUP     0x1505
581         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
582         ls $DIR/$tdir/ > /dev/null || error "(11) no FID-in-dirent."
583         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
584 }
585 run_test 4 "FID-in-dirent can be rebuilt after MDT file-level backup/restore"
586
587 test_5()
588 {
589         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
590                 skip "OI Scrub not implemented for ZFS" && return
591
592         lfsck_prep 1 1 1
593         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
594         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
595
596         mds_backup_restore $SINGLEMDS 1 || error "(1) Fail to backup/restore!"
597         echo "start $SINGLEMDS with disabling OI scrub"
598         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
599                 error "(2) Fail to start MDS!"
600
601         #define OBD_FAIL_LFSCK_DELAY2           0x1601
602         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
603         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
604         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
605                 mdd.${MDT_DEV}.lfsck_namespace |
606                 awk '/^flags/ { print \\\$2 }'" "inconsistent,upgrade" 32 || {
607                 $SHOW_NAMESPACE
608                 error "(5) unexpected status"
609         }
610
611         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
612         [ "$STATUS" == "scanning-phase1" ] ||
613                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
614
615         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
616         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
617                 mdd.${MDT_DEV}.lfsck_namespace |
618                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
619                 $SHOW_NAMESPACE
620                 error "(7) unexpected status"
621         }
622
623         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
624         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
625
626         local repaired=$($SHOW_NAMESPACE |
627                          awk '/^dirent_repaired/ { print $2 }')
628         # for interop with old server
629         [ -z "$repaired" ] &&
630                 repaired=$($SHOW_NAMESPACE |
631                          awk '/^updated_phase1/ { print $2 }')
632
633         [ $repaired -ge 2 ] ||
634                 error "(9) Fail to generate FID-in-dirent for IGIF: $repaired"
635
636         run_e2fsck_on_mdt0
637
638         mount_client $MOUNT || error "(10) Fail to start client!"
639
640         #define OBD_FAIL_FID_LOOKUP     0x1505
641         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
642         stat $DIR/$tdir/dummy > /dev/null || error "(11) no FID-in-LMA."
643
644         ls $DIR/$tdir/ > /dev/null || error "(12) no FID-in-dirent."
645
646         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
647         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
648         local dummyname=$($LFS fid2path $DIR $dummyfid)
649         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
650                 error "(13) Fail to generate linkEA: $dummyfid $dummyname"
651 }
652 run_test 5 "LFSCK can handle IGIF object upgrading"
653
654 test_6a() {
655         lfsck_prep 5 5
656
657         #define OBD_FAIL_LFSCK_DELAY1           0x1600
658         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
659         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
660
661         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
662         [ "$STATUS" == "scanning-phase1" ] ||
663                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
664
665         # Sleep 3 sec to guarantee at least one object processed by LFSCK
666         sleep 3
667         # Fail the LFSCK to guarantee there is at least one checkpoint
668         #define OBD_FAIL_LFSCK_FATAL1           0x1608
669         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001608
670         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
671                 mdd.${MDT_DEV}.lfsck_namespace |
672                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
673                 $SHOW_NAMESPACE
674                 error "(4) unexpected status"
675         }
676
677         local POS0=$($SHOW_NAMESPACE |
678                      awk '/^last_checkpoint_position/ { print $2 }' |
679                      tr -d ',')
680
681         #define OBD_FAIL_LFSCK_DELAY1           0x1600
682         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
683         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
684
685         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
686         [ "$STATUS" == "scanning-phase1" ] ||
687                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
688
689         local POS1=$($SHOW_NAMESPACE |
690                      awk '/^latest_start_position/ { print $2 }' |
691                      tr -d ',')
692         [[ $POS0 -lt $POS1 ]] ||
693                 error "(7) Expect larger than: $POS0, but got $POS1"
694
695         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
696         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
697                 mdd.${MDT_DEV}.lfsck_namespace |
698                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
699                 $SHOW_NAMESPACE
700                 error "(8) unexpected status"
701         }
702 }
703 run_test 6a "LFSCK resumes from last checkpoint (1)"
704
705 test_6b() {
706         lfsck_prep 5 5
707
708         #define OBD_FAIL_LFSCK_DELAY2           0x1601
709         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
710         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
711
712         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
713         [ "$STATUS" == "scanning-phase1" ] ||
714                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
715
716         # Sleep 5 sec to guarantee that we are in the directory scanning
717         sleep 5
718         # Fail the LFSCK to guarantee there is at least one checkpoint
719         #define OBD_FAIL_LFSCK_FATAL2           0x1609
720         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
721         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
722                 mdd.${MDT_DEV}.lfsck_namespace |
723                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
724                 $SHOW_NAMESPACE
725                 error "(4) unexpected status"
726         }
727
728         local O_POS0=$($SHOW_NAMESPACE |
729                        awk '/^last_checkpoint_position/ { print $2 }' |
730                        tr -d ',')
731
732         local D_POS0=$($SHOW_NAMESPACE |
733                        awk '/^last_checkpoint_position/ { print $4 }')
734
735         #define OBD_FAIL_LFSCK_DELAY2           0x1601
736         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
737         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
738
739         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
740         [ "$STATUS" == "scanning-phase1" ] ||
741                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
742
743         local O_POS1=$($SHOW_NAMESPACE |
744                        awk '/^latest_start_position/ { print $2 }' |
745                        tr -d ',')
746         local D_POS1=$($SHOW_NAMESPACE |
747                        awk '/^latest_start_position/ { print $4 }')
748
749         if [ "$D_POS0" == "N/A" -o "$D_POS1" == "N/A" ]; then
750                 [[ $O_POS0 -lt $O_POS1 ]] ||
751                         error "(7.1) $O_POS1 is not larger than $O_POS0"
752         else
753                 [[ $D_POS0 -lt $D_POS1 ]] ||
754                         error "(7.2) $D_POS1 is not larger than $D_POS0"
755         fi
756
757         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
758         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
759                 mdd.${MDT_DEV}.lfsck_namespace |
760                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
761                 $SHOW_NAMESPACE
762                 error "(8) unexpected status"
763         }
764 }
765 run_test 6b "LFSCK resumes from last checkpoint (2)"
766
767 test_7a()
768 {
769         lfsck_prep 5 5
770         umount_client $MOUNT
771
772         #define OBD_FAIL_LFSCK_DELAY2           0x1601
773         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
774         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
775
776         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
777         [ "$STATUS" == "scanning-phase1" ] ||
778                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
779
780         # Sleep 3 sec to guarantee at least one object processed by LFSCK
781         sleep 3
782         echo "stop $SINGLEMDS"
783         stop $SINGLEMDS > /dev/null || error "(4) Fail to stop MDS!"
784
785         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
786         echo "start $SINGLEMDS"
787         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
788                 error "(5) Fail to start MDS!"
789
790         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
791                 mdd.${MDT_DEV}.lfsck_namespace |
792                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
793                 $SHOW_NAMESPACE
794                 error "(6) unexpected status"
795         }
796 }
797 run_test 7a "non-stopped LFSCK should auto restarts after MDS remount (1)"
798
799 test_7b()
800 {
801         lfsck_prep 2 2
802
803         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
804         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
805         for ((i = 0; i < 20; i++)); do
806                 touch $DIR/$tdir/dummy${i}
807         done
808
809         #define OBD_FAIL_LFSCK_DELAY3           0x1602
810         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1602
811         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
812         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
813                 mdd.${MDT_DEV}.lfsck_namespace |
814                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 32 || {
815                 $SHOW_NAMESPACE
816                 error "(4) unexpected status"
817         }
818
819         umount_client $MOUNT
820         echo "stop $SINGLEMDS"
821         stop $SINGLEMDS > /dev/null || error "(5) Fail to stop MDS!"
822
823         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
824         echo "start $SINGLEMDS"
825         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
826                 error "(6) Fail to start MDS!"
827
828         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
829                 mdd.${MDT_DEV}.lfsck_namespace |
830                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
831                 $SHOW_NAMESPACE
832                 error "(7) unexpected status"
833         }
834 }
835 run_test 7b "non-stopped LFSCK should auto restarts after MDS remount (2)"
836
837 test_8()
838 {
839         echo "formatall"
840         formatall > /dev/null
841         echo "setupall"
842         setupall > /dev/null
843
844         lfsck_prep 20 20
845
846         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
847         [ "$STATUS" == "init" ] ||
848                 error "(2) Expect 'init', but got '$STATUS'"
849
850         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
851         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
852         mkdir $DIR/$tdir/crashed
853
854         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
855         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
856         for ((i = 0; i < 5; i++)); do
857                 touch $DIR/$tdir/dummy${i}
858         done
859
860         umount_client $MOUNT || error "(3) Fail to stop client!"
861
862         #define OBD_FAIL_LFSCK_DELAY2           0x1601
863         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1601
864         $START_NAMESPACE || error "(4) Fail to start LFSCK for namespace!"
865
866         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
867         [ "$STATUS" == "scanning-phase1" ] ||
868                 error "(5) Expect 'scanning-phase1', but got '$STATUS'"
869
870         $STOP_LFSCK || error "(6) Fail to stop LFSCK!"
871
872         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
873         [ "$STATUS" == "stopped" ] ||
874                 error "(7) Expect 'stopped', but got '$STATUS'"
875
876         $START_NAMESPACE || error "(8) Fail to start LFSCK for namespace!"
877
878         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
879         [ "$STATUS" == "scanning-phase1" ] ||
880                 error "(9) Expect 'scanning-phase1', but got '$STATUS'"
881
882         #define OBD_FAIL_LFSCK_FATAL2           0x1609
883         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
884         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
885                 mdd.${MDT_DEV}.lfsck_namespace |
886                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
887                 $SHOW_NAMESPACE
888                 error "(10) unexpected status"
889         }
890
891         #define OBD_FAIL_LFSCK_DELAY1           0x1600
892         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
893         $START_NAMESPACE || error "(11) Fail to start LFSCK for namespace!"
894
895         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
896         [ "$STATUS" == "scanning-phase1" ] ||
897                 error "(12) Expect 'scanning-phase1', but got '$STATUS'"
898
899         #define OBD_FAIL_LFSCK_CRASH            0x160a
900         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160a
901         sleep 5
902
903         echo "stop $SINGLEMDS"
904         stop $SINGLEMDS > /dev/null || error "(13) Fail to stop MDS!"
905
906         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
907         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
908
909         echo "start $SINGLEMDS"
910         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
911                 error "(14) Fail to start MDS!"
912
913         local timeout=$(max_recovery_time)
914         local timer=0
915
916         while [ $timer -lt $timeout ]; do
917                 STATUS=$(do_facet $SINGLEMDS "$LCTL get_param -n \
918                         mdt.${MDT_DEV}.recovery_status |
919                         awk '/^status/ { print \\\$2 }'")
920                 [ "$STATUS" != "RECOVERING" ] && break;
921                 sleep 1
922                 timer=$((timer + 1))
923         done
924
925         [ $timer != $timeout ] ||
926                 error "(14.1) recovery timeout"
927
928         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
929         [ "$STATUS" == "crashed" ] ||
930                 error "(15) Expect 'crashed', but got '$STATUS'"
931
932         #define OBD_FAIL_LFSCK_DELAY2           0x1601
933         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
934         $START_NAMESPACE || error "(16) Fail to start LFSCK for namespace!"
935
936         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
937         [ "$STATUS" == "scanning-phase1" ] ||
938                 error "(17) Expect 'scanning-phase1', but got '$STATUS'"
939
940         echo "stop $SINGLEMDS"
941         stop $SINGLEMDS > /dev/null || error "(18) Fail to stop MDS!"
942
943         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
944         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
945
946         echo "start $SINGLEMDS"
947         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
948                 error "(19) Fail to start MDS!"
949
950         timer=0
951         while [ $timer -lt $timeout ]; do
952                 STATUS=$(do_facet $SINGLEMDS "$LCTL get_param -n \
953                         mdt.${MDT_DEV}.recovery_status |
954                         awk '/^status/ { print \\\$2 }'")
955                 [ "$STATUS" != "RECOVERING" ] && break;
956                 sleep 1
957                 timer=$((timer + 1))
958         done
959
960         [ $timer != $timeout ] ||
961                 error "(19.1) recovery timeout"
962
963         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
964         [ "$STATUS" == "paused" ] ||
965                 error "(20) Expect 'paused', but got '$STATUS'"
966
967         echo "stop $SINGLEMDS"
968         stop $SINGLEMDS > /dev/null || error "(20.1) Fail to stop MDS!"
969
970         echo "start $SINGLEMDS without resume LFSCK"
971         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SKIP_LFSCK > /dev/null ||
972                 error "(20.2) Fail to start MDS!"
973
974         timer=0
975         while [ $timer -lt $timeout ]; do
976                 STATUS=$(do_facet $SINGLEMDS "$LCTL get_param -n \
977                         mdt.${MDT_DEV}.recovery_status |
978                         awk '/^status/ { print \\\$2 }'")
979                 [ "$STATUS" != "RECOVERING" ] && break;
980                 sleep 1
981                 timer=$((timer + 1))
982         done
983
984         [ $timer != $timeout ] ||
985                 error "(20.3) recovery timeout"
986
987         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
988         [ "$STATUS" == "paused" ] ||
989                 error "(20.4) Expect 'paused', but got '$STATUS'"
990
991         #define OBD_FAIL_LFSCK_DELAY3           0x1602
992         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1602
993
994         $START_NAMESPACE || error "(21) Fail to start LFSCK for namespace!"
995         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
996                 mdd.${MDT_DEV}.lfsck_namespace |
997                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 32 || {
998                 $SHOW_NAMESPACE
999                 error "(22) unexpected status"
1000         }
1001
1002         local FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
1003         [ "$FLAGS" == "scanned-once,inconsistent" ] ||
1004                 error "(23) Expect 'scanned-once,inconsistent',but got '$FLAGS'"
1005
1006         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
1007         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1008                 mdd.${MDT_DEV}.lfsck_namespace |
1009                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1010                 $SHOW_NAMESPACE
1011                 error "(24) unexpected status"
1012         }
1013
1014         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
1015         [ -z "$FLAGS" ] || error "(25) Expect empty flags, but got '$FLAGS'"
1016 }
1017 run_test 8 "LFSCK state machine"
1018
1019 test_9a() {
1020         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
1021                 skip "Testing on UP system, the speed may be inaccurate."
1022                 return 0
1023         fi
1024
1025         [[ $server_version -ge $(version_code 2.7.50) ]] ||
1026                 { skip "Need MDS version >= 2.7.50"; return; }
1027
1028         check_mount_and_prep
1029         $LFS mkdir -i 0 $DIR/$tdir/lfsck || error "(1) Fail to mkdir lfsck"
1030         $LFS setstripe -c 1 -i -1 $DIR/$tdir/lfsck
1031         createmany -o $DIR/$tdir/lfsck/f 5000
1032
1033         local BASE_SPEED1=100
1034         local RUN_TIME1=10
1035         $START_LAYOUT -r -s $BASE_SPEED1 || error "(2) Fail to start LFSCK!"
1036
1037         sleep $RUN_TIME1
1038         STATUS=$($SHOW_LAYOUT | awk '/^status/ { print $2 }')
1039         [ "$STATUS" == "scanning-phase1" ] ||
1040                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
1041
1042         local SPEED=$($SHOW_LAYOUT |
1043                       awk '/^average_speed_phase1/ { print $2 }')
1044
1045         # There may be time error, normally it should be less than 2 seconds.
1046         # We allow another 20% schedule error.
1047         local TIME_DIFF=2
1048         # MAX_MARGIN = 1.2 = 12 / 10
1049         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
1050                            RUN_TIME1 * 12 / 10))
1051         [ $SPEED -lt $MAX_SPEED ] ||
1052                 error "(4) Got speed $SPEED, expected less than $MAX_SPEED"
1053
1054         # adjust speed limit
1055         local BASE_SPEED2=300
1056         local RUN_TIME2=10
1057         do_facet $SINGLEMDS \
1058                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
1059         sleep $RUN_TIME2
1060
1061         SPEED=$($SHOW_LAYOUT | awk '/^average_speed_phase1/ { print $2 }')
1062         # MIN_MARGIN = 0.8 = 8 / 10
1063         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
1064                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
1065                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
1066         [ $SPEED -gt $MIN_SPEED ] || {
1067                 if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
1068                         error_ignore LU-5624 \
1069                         "(5.1) Got speed $SPEED, expected more than $MIN_SPEED"
1070                 else
1071                         error \
1072                         "(5.2) Got speed $SPEED, expected more than $MIN_SPEED"
1073                 fi
1074         }
1075
1076         # MAX_MARGIN = 1.2 = 12 / 10
1077         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
1078                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
1079                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
1080         [ $SPEED -lt $MAX_SPEED ] ||
1081                 error "(6) Got speed $SPEED, expected less than $MAX_SPEED"
1082
1083         do_facet $SINGLEMDS \
1084                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
1085
1086         wait_update_facet $SINGLEMDS \
1087                 "$LCTL get_param -n mdd.${MDT_DEV}.lfsck_layout |
1088                 awk '/^status/ { print \\\$2 }'" "completed" 30 ||
1089                 error "(7) Failed to get expected 'completed'"
1090 }
1091 run_test 9a "LFSCK speed control (1)"
1092
1093 test_9b() {
1094         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
1095                 skip "Testing on UP system, the speed may be inaccurate."
1096                 return 0
1097         fi
1098
1099         [[ $server_version -ge $(version_code 2.7.50) ]] ||
1100                 { skip "Need MDS version >= 2.7.50"; return; }
1101
1102         lfsck_prep 0 0
1103
1104         echo "Preparing another 50 * 50 files (with error) at $(date)."
1105         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
1106         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
1107         createmany -d $DIR/$tdir/d 50
1108         createmany -m $DIR/$tdir/f 50
1109         for ((i = 0; i < 50; i++)); do
1110                 createmany -m $DIR/$tdir/d${i}/f 50 > /dev/null
1111         done
1112
1113         #define OBD_FAIL_LFSCK_NO_DOUBLESCAN    0x160c
1114         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160c
1115         $START_NAMESPACE -r || error "(4) Fail to start LFSCK!"
1116         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1117                 mdd.${MDT_DEV}.lfsck_namespace |
1118                 awk '/^status/ { print \\\$2 }'" "stopped" 10 || {
1119                 $SHOW_NAMESPACE
1120                 error "(5) unexpected status"
1121         }
1122
1123         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1124         echo "Prepared at $(date)."
1125
1126         local BASE_SPEED1=50
1127         local RUN_TIME1=10
1128         $START_NAMESPACE -s $BASE_SPEED1 || error "(6) Fail to start LFSCK!"
1129
1130         sleep $RUN_TIME1
1131         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1132         [ "$STATUS" == "scanning-phase2" ] ||
1133                 error "(7) Expect 'scanning-phase2', but got '$STATUS'"
1134
1135         local SPEED=$($SHOW_NAMESPACE |
1136                       awk '/^average_speed_phase2/ { print $2 }')
1137         # There may be time error, normally it should be less than 2 seconds.
1138         # We allow another 20% schedule error.
1139         local TIME_DIFF=2
1140         # MAX_MARGIN = 1.2 = 12 / 10
1141         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
1142                           RUN_TIME1 * 12 / 10))
1143         [ $SPEED -lt $MAX_SPEED ] ||
1144                 error "(8) Got speed $SPEED, expected less than $MAX_SPEED"
1145
1146         # adjust speed limit
1147         local BASE_SPEED2=150
1148         local RUN_TIME2=10
1149         do_facet $SINGLEMDS \
1150                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
1151         sleep $RUN_TIME2
1152
1153         SPEED=$($SHOW_NAMESPACE | awk '/^average_speed_phase2/ { print $2 }')
1154         # MIN_MARGIN = 0.8 = 8 / 10
1155         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
1156                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
1157                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
1158         [ $SPEED -gt $MIN_SPEED ] || {
1159                 if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
1160                         error_ignore LU-5624 \
1161                         "(9.1) Got speed $SPEED, expected more than $MIN_SPEED"
1162                 else
1163                         error \
1164                         "(9.2) Got speed $SPEED, expected more than $MIN_SPEED"
1165                 fi
1166         }
1167
1168         # MAX_MARGIN = 1.2 = 12 / 10
1169         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
1170                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
1171                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
1172         [ $SPEED -lt $MAX_SPEED ] ||
1173                 error "(10) Got speed $SPEED, expected less than $MAX_SPEED"
1174
1175         do_facet $SINGLEMDS \
1176                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
1177         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1178                 mdd.${MDT_DEV}.lfsck_namespace |
1179                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1180                 $SHOW_NAMESPACE
1181                 error "(11) unexpected status"
1182         }
1183 }
1184 run_test 9b "LFSCK speed control (2)"
1185
1186 test_10()
1187 {
1188         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
1189                 skip "lookup(..)/linkea on ZFS issue" && return
1190
1191         lfsck_prep 1 1
1192
1193         echo "Preparing more files with error at $(date)."
1194         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
1195         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
1196
1197         for ((i = 0; i < 1000; i = $((i+2)))); do
1198                 mkdir -p $DIR/$tdir/d${i}
1199                 touch $DIR/$tdir/f${i}
1200                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
1201         done
1202
1203         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
1204         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
1205
1206         for ((i = 1; i < 1000; i = $((i+2)))); do
1207                 mkdir -p $DIR/$tdir/d${i}
1208                 touch $DIR/$tdir/f${i}
1209                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
1210         done
1211
1212         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1213         echo "Prepared at $(date)."
1214
1215         ln $DIR/$tdir/f200 $DIR/$tdir/d200/dummy
1216
1217         umount_client $MOUNT
1218         mount_client $MOUNT || error "(3) Fail to start client!"
1219
1220         $START_NAMESPACE -r -s 100 || error "(5) Fail to start LFSCK!"
1221
1222         sleep 10
1223         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1224         [ "$STATUS" == "scanning-phase1" ] ||
1225                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
1226
1227         ls -ailR $MOUNT > /dev/null || error "(7) Fail to ls!"
1228
1229         touch $DIR/$tdir/d198/a0 || error "(8) Fail to touch!"
1230
1231         mkdir $DIR/$tdir/d199/a1 || error "(9) Fail to mkdir!"
1232
1233         unlink $DIR/$tdir/f200 || error "(10) Fail to unlink!"
1234
1235         rm -rf $DIR/$tdir/d201 || error "(11) Fail to rmdir!"
1236
1237         mv $DIR/$tdir/f202 $DIR/$tdir/d203/ || error "(12) Fail to rename!"
1238
1239         ln $DIR/$tdir/f204 $DIR/$tdir/d205/a3 || error "(13) Fail to hardlink!"
1240
1241         ln -s $DIR/$tdir/d206 $DIR/$tdir/d207/a4 ||
1242                 error "(14) Fail to softlink!"
1243
1244         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1245         [ "$STATUS" == "scanning-phase1" ] ||
1246                 error "(15) Expect 'scanning-phase1', but got '$STATUS'"
1247
1248         do_facet $SINGLEMDS \
1249                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
1250         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1251                 mdd.${MDT_DEV}.lfsck_namespace |
1252                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1253                 $SHOW_NAMESPACE
1254                 error "(16) unexpected status"
1255         }
1256 }
1257 run_test 10 "System is available during LFSCK scanning"
1258
1259 # remove LAST_ID
1260 ost_remove_lastid() {
1261         local ost=$1
1262         local idx=$2
1263         local rcmd="do_facet ost${ost}"
1264
1265         echo "remove LAST_ID on ost${ost}: idx=${idx}"
1266
1267         # step 1: local mount
1268         mount_fstype ost${ost} || return 1
1269         # step 2: remove the specified LAST_ID
1270         ${rcmd} rm -fv $(facet_mntpt ost${ost})/O/${idx}/{LAST_ID,d0/0}
1271         # step 3: umount
1272         unmount_fstype ost${ost} || return 2
1273 }
1274
1275 test_11a() {
1276         check_mount_and_prep
1277         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1278         createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 64 files."
1279
1280         echo "stopall"
1281         stopall > /dev/null
1282
1283         ost_remove_lastid 1 0 || error "(1) Fail to remove LAST_ID"
1284
1285         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1286                 error "(2) Fail to start ost1"
1287
1288         #define OBD_FAIL_LFSCK_DELAY4           0x160e
1289         do_facet ost1 $LCTL set_param fail_val=3 fail_loc=0x160e
1290
1291         echo "trigger LFSCK for layout on ost1 to rebuild the LAST_ID(s)"
1292         $START_LAYOUT_ON_OST -r || error "(4) Fail to start LFSCK on OST!"
1293
1294         wait_update_facet ost1 "$LCTL get_param -n \
1295                 obdfilter.${OST_DEV}.lfsck_layout |
1296                 awk '/^flags/ { print \\\$2 }'" "crashed_lastid" 60 || {
1297                 $SHOW_LAYOUT_ON_OST
1298                 error "(5) unexpected status"
1299         }
1300
1301         do_facet ost1 $LCTL set_param fail_val=0 fail_loc=0
1302
1303         wait_update_facet ost1 "$LCTL get_param -n \
1304                 obdfilter.${OST_DEV}.lfsck_layout |
1305                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1306                 $SHOW_LAYOUT_ON_OST
1307                 error "(6) unexpected status"
1308         }
1309
1310         echo "the LAST_ID(s) should have been rebuilt"
1311         FLAGS=$($SHOW_LAYOUT_ON_OST | awk '/^flags/ { print $2 }')
1312         [ -z "$FLAGS" ] || error "(7) Expect empty flags, but got '$FLAGS'"
1313 }
1314 run_test 11a "LFSCK can rebuild lost last_id"
1315
1316 test_11b() {
1317         check_mount_and_prep
1318         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1319
1320         echo "set fail_loc=0x160d to skip the updating LAST_ID on-disk"
1321         #define OBD_FAIL_LFSCK_SKIP_LASTID      0x160d
1322         do_facet ost1 $LCTL set_param fail_loc=0x160d
1323
1324         local count=$(precreated_ost_obj_count 0 0)
1325
1326         createmany -o $DIR/$tdir/f $((count + 32))
1327
1328         local proc_path="${FSNAME}-OST0000-osc-MDT0000"
1329         local seq=$(do_facet mds1 $LCTL get_param -n \
1330                     osp.${proc_path}.prealloc_last_seq)
1331         local lastid1=$(do_facet ost1 "lctl get_param -n \
1332                 obdfilter.${ost1_svc}.last_id" | grep $seq |
1333                 awk -F: '{ print $2 }')
1334
1335         umount_client $MOUNT
1336         stop ost1 || error "(1) Fail to stop ost1"
1337
1338         # stop MDS to forget last precreated object
1339         echo "stop $SINGLEMDS"
1340         stop $SINGLEMDS > /dev/null || error "(11) Fail to stop MDS!"
1341         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
1342         echo "start $SINGLEMDS"
1343         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
1344                 error "(12) Fail to start MDS!"
1345
1346         #define OBD_FAIL_OST_ENOSPC              0x215
1347         do_facet ost1 $LCTL set_param fail_loc=0x215
1348
1349         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1350                 error "(2) Fail to start ost1"
1351
1352         for ((i = 0; i < 60; i++)); do
1353                 lastid2=$(do_facet ost1 "lctl get_param -n \
1354                         obdfilter.${ost1_svc}.last_id" | grep $seq |
1355                         awk -F: '{ print $2 }')
1356                 [ ! -z $lastid2 ] && break;
1357                 sleep 1
1358         done
1359
1360         echo "the on-disk LAST_ID should be smaller than the expected one"
1361         [ $lastid1 -gt $lastid2 ] ||
1362                 error "(4) expect lastid1 [ $lastid1 ] > lastid2 [ $lastid2 ]"
1363
1364         echo "trigger LFSCK for layout on ost1 to rebuild the on-disk LAST_ID"
1365         $START_LAYOUT_ON_OST -r || error "(5) Fail to start LFSCK on OST!"
1366
1367         wait_update_facet ost1 "$LCTL get_param -n \
1368                 obdfilter.${OST_DEV}.lfsck_layout |
1369                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1370                 $SHOW_LAYOUT_ON_OST
1371                 error "(6) unexpected status"
1372         }
1373
1374         stop ost1 || error "(7) Fail to stop ost1"
1375
1376         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1377                 error "(8) Fail to start ost1"
1378
1379         echo "the on-disk LAST_ID should have been rebuilt"
1380         wait_update_facet ost1 "$LCTL get_param -n \
1381                 obdfilter.${ost1_svc}.last_id | grep $seq |
1382                 awk -F: '{ print \\\$2 }'" "$lastid1" 60 || {
1383                 do_facet ost1 $LCTL get_param -n \
1384                 obdfilter.${ost1_svc}.last_id
1385                 error "(9) expect lastid1 $seq:$lastid1"
1386         }
1387
1388         do_facet ost1 $LCTL set_param fail_loc=0
1389         stopall || error "(10) Fail to stopall"
1390 }
1391 run_test 11b "LFSCK can rebuild crashed last_id"
1392
1393 test_12a() {
1394         [ $MDSCOUNT -lt 2 ] &&
1395                 skip "We need at least 2 MDSes for test_12a" && return
1396
1397         check_mount_and_prep
1398         for k in $(seq $MDSCOUNT); do
1399                 $LFS mkdir -i $((k - 1)) $DIR/$tdir/${k}
1400                 createmany -o $DIR/$tdir/${k}/f 100 ||
1401                         error "(0) Fail to create 100 files."
1402         done
1403
1404         echo "Start namespace LFSCK on all targets by single command (-s 1)."
1405         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1406                 -s 1 -r || error "(2) Fail to start LFSCK on all devices!"
1407
1408         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1409         wait_all_targets namespace scanning-phase1 3
1410
1411         echo "Stop namespace LFSCK on all targets by single lctl command."
1412         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1413                 error "(4) Fail to stop LFSCK on all devices!"
1414
1415         echo "All the LFSCK targets should be in 'stopped' status."
1416         wait_all_targets_blocked namespace stopped 5
1417
1418         echo "Re-start namespace LFSCK on all targets by single command (-s 0)."
1419         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1420                 -s 0 -r || error "(6) Fail to start LFSCK on all devices!"
1421
1422         echo "All the LFSCK targets should be in 'completed' status."
1423         wait_all_targets_blocked namespace completed 7
1424
1425         start_full_debug_logging
1426
1427         echo "Start layout LFSCK on all targets by single command (-s 1)."
1428         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1429                 -s 1 -r || error "(8) Fail to start LFSCK on all devices!"
1430
1431         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1432         wait_all_targets layout scanning-phase1 9
1433
1434         echo "Stop layout LFSCK on all targets by single lctl command."
1435         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1436                 error "(10) Fail to stop LFSCK on all devices!"
1437
1438         echo "All the LFSCK targets should be in 'stopped' status."
1439         wait_all_targets_blocked layout stopped 11
1440
1441         for k in $(seq $OSTCOUNT); do
1442                 local STATUS=$(do_facet ost${k} $LCTL get_param -n \
1443                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1444                                 awk '/^status/ { print $2 }')
1445                 [ "$STATUS" == "stopped" ] ||
1446                         error "(12) OST${k} Expect 'stopped', but got '$STATUS'"
1447         done
1448
1449         echo "Re-start layout LFSCK on all targets by single command (-s 0)."
1450         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1451                 -s 0 -r || error "(13) Fail to start LFSCK on all devices!"
1452
1453         echo "All the LFSCK targets should be in 'completed' status."
1454         wait_all_targets_blocked layout completed 14
1455
1456         stop_full_debug_logging
1457 }
1458 run_test 12a "single command to trigger LFSCK on all devices"
1459
1460 test_12b() {
1461         check_mount_and_prep
1462
1463         echo "Start LFSCK without '-M' specified."
1464         do_facet mds1 $LCTL lfsck_start -A -r ||
1465                 error "(0) Fail to start LFSCK without '-M'"
1466
1467         wait_all_targets_blocked namespace completed 1
1468         wait_all_targets_blocked layout completed 2
1469
1470         local count=$(do_facet mds1 $LCTL dl |
1471                       awk '{ print $3 }' | grep mdt | wc -l)
1472         if [ $count -gt 1 ]; then
1473                 echo
1474                 echo "Start layout LFSCK on the node with multipe targets,"
1475                 echo "but not specify '-M'/'-A' option. Should get failure."
1476                 echo
1477                 do_facet mds1 $LCTL lfsck_start -t layout -r &&
1478                         error "(3) Start layout LFSCK should fail" || true
1479         fi
1480 }
1481 run_test 12b "auto detect Lustre device"
1482
1483 test_13() {
1484         echo "#####"
1485         echo "The lmm_oi in layout EA should be consistent with the MDT-object"
1486         echo "FID; otherwise, the LFSCK should re-generate the lmm_oi from the"
1487         echo "MDT-object FID."
1488         echo "#####"
1489
1490         check_mount_and_prep
1491
1492         echo "Inject failure stub to simulate bad lmm_oi"
1493         #define OBD_FAIL_LFSCK_BAD_LMMOI        0x160f
1494         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160f
1495         createmany -o $DIR/$tdir/f 1
1496         $LFS setstripe -E 1M -E -1 $DIR/$tdir/f1 ||
1497                 error "(0) Fail to create PFL $DIR/$tdir/f1"
1498         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1499
1500         echo "Trigger layout LFSCK to find out the bad lmm_oi and fix them"
1501         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1502
1503         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1504                 mdd.${MDT_DEV}.lfsck_layout |
1505                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1506                 $SHOW_LAYOUT
1507                 error "(2) unexpected status"
1508         }
1509
1510         local repaired=$($SHOW_LAYOUT |
1511                          awk '/^repaired_others/ { print $2 }')
1512         [ $repaired -eq 2 ] ||
1513                 error "(3) Fail to repair crashed lmm_oi: $repaired"
1514 }
1515 run_test 13 "LFSCK can repair crashed lmm_oi"
1516
1517 test_14a() {
1518         echo "#####"
1519         echo "The OST-object referenced by the MDT-object should be there;"
1520         echo "otherwise, the LFSCK should re-create the missing OST-object."
1521         echo "without '--delay-create-ostobj' option."
1522         echo "#####"
1523
1524         check_mount_and_prep
1525         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1526
1527         echo "Inject failure stub to simulate dangling referenced MDT-object"
1528         #define OBD_FAIL_LFSCK_DANGLING 0x1610
1529         do_facet ost1 $LCTL set_param fail_loc=0x1610
1530         local count=$(precreated_ost_obj_count 0 0)
1531
1532         createmany -o $DIR/$tdir/f $((count + 16)) ||
1533                 error "(0.1) Fail to create $DIR/$tdir/fx"
1534         touch $DIR/$tdir/guard0
1535
1536         for ((i = 0; i < 16; i++)); do
1537                 $LFS setstripe -E 512K -S 256K -o 0 -E 2M \
1538                         $DIR/$tdir/f_comp${i} ||
1539                         error "(0.2) Fail to create $DIR/$tdir/f_comp${i}"
1540         done
1541         touch $DIR/$tdir/guard1
1542
1543         do_facet ost1 $LCTL set_param fail_loc=0
1544
1545         start_full_debug_logging
1546
1547         # exhaust other pre-created dangling cases
1548         count=$(precreated_ost_obj_count 0 0)
1549         createmany -o $DIR/$tdir/a $count ||
1550                 error "(0.5) Fail to create $count files."
1551
1552         echo "'ls' should fail because of dangling referenced MDT-object"
1553         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(1) ls should fail."
1554
1555         echo "Trigger layout LFSCK to find out dangling reference"
1556         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1557
1558         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1559                 mdd.${MDT_DEV}.lfsck_layout |
1560                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1561                 $SHOW_LAYOUT
1562                 error "(3) unexpected status"
1563         }
1564
1565         local repaired=$($SHOW_LAYOUT |
1566                          awk '/^repaired_dangling/ { print $2 }')
1567         [ $repaired -ge 32 ] ||
1568                 error "(4) Fail to repair dangling reference: $repaired"
1569
1570         echo "'stat' should fail because of not repair dangling by default"
1571         stat $DIR/$tdir/guard0 > /dev/null 2>&1 &&
1572                 error "(5.1) stat should fail"
1573         stat $DIR/$tdir/guard1 > /dev/null 2>&1 &&
1574                 error "(5.2) stat should fail"
1575
1576         echo "Trigger layout LFSCK to repair dangling reference"
1577         $START_LAYOUT -r -c || error "(6) Fail to start LFSCK for layout!"
1578
1579         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1580                 mdd.${MDT_DEV}.lfsck_layout |
1581                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1582                 $SHOW_LAYOUT
1583                 error "(7) unexpected status"
1584         }
1585
1586         # There may be some async LFSCK updates in processing, wait for
1587         # a while until the target reparation has been done. LU-4970.
1588
1589         echo "'stat' should success after layout LFSCK repairing"
1590         wait_update_facet client "stat $DIR/$tdir/guard0 |
1591                 awk '/Size/ { print \\\$2 }'" "0" 32 || {
1592                 stat $DIR/$tdir/guard0
1593                 $SHOW_LAYOUT
1594                 error "(8.1) unexpected size"
1595         }
1596
1597         wait_update_facet client "stat $DIR/$tdir/guard1 |
1598                 awk '/Size/ { print \\\$2 }'" "0" 32 || {
1599                 stat $DIR/$tdir/guard1
1600                 $SHOW_LAYOUT
1601                 error "(8.2) unexpected size"
1602         }
1603
1604         repaired=$($SHOW_LAYOUT |
1605                          awk '/^repaired_dangling/ { print $2 }')
1606         [ $repaired -ge 32 ] ||
1607                 error "(9) Fail to repair dangling reference: $repaired"
1608
1609         stop_full_debug_logging
1610
1611         echo "stopall to cleanup object cache"
1612         stopall > /dev/null
1613         echo "setupall"
1614         setupall > /dev/null
1615 }
1616 run_test 14a "LFSCK can repair MDT-object with dangling LOV EA reference (1)"
1617
1618 test_14b() {
1619         echo "#####"
1620         echo "The OST-object referenced by the MDT-object should be there;"
1621         echo "otherwise, the LFSCK should re-create the missing OST-object."
1622         echo "with '--delay-create-ostobj' option."
1623         echo "#####"
1624
1625         check_mount_and_prep
1626         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1627
1628         echo "Inject failure stub to simulate dangling referenced MDT-object"
1629         #define OBD_FAIL_LFSCK_DANGLING 0x1610
1630         do_facet ost1 $LCTL set_param fail_loc=0x1610
1631         local count=$(precreated_ost_obj_count 0 0)
1632
1633         createmany -o $DIR/$tdir/f $((count + 31))
1634         touch $DIR/$tdir/guard
1635         do_facet ost1 $LCTL set_param fail_loc=0
1636
1637         start_full_debug_logging
1638
1639         # exhaust other pre-created dangling cases
1640         count=$(precreated_ost_obj_count 0 0)
1641         createmany -o $DIR/$tdir/a $count ||
1642                 error "(0) Fail to create $count files."
1643
1644         echo "'ls' should fail because of dangling referenced MDT-object"
1645         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(1) ls should fail."
1646
1647         echo "Trigger layout LFSCK to find out dangling reference"
1648         $START_LAYOUT -r -o -d || error "(2) Fail to start LFSCK for layout!"
1649
1650         wait_all_targets_blocked layout completed 3
1651
1652         local repaired=$($SHOW_LAYOUT |
1653                          awk '/^repaired_dangling/ { print $2 }')
1654         [ $repaired -ge 32 ] ||
1655                 error "(4) Fail to repair dangling reference: $repaired"
1656
1657         echo "'stat' should fail because of not repair dangling by default"
1658         stat $DIR/$tdir/guard > /dev/null 2>&1 && error "(5) stat should fail"
1659
1660         echo "Trigger layout LFSCK to repair dangling reference"
1661         $START_LAYOUT -r -o -c -d || error "(6) Fail to start LFSCK for layout!"
1662
1663         wait_all_targets_blocked layout completed 7
1664
1665         # There may be some async LFSCK updates in processing, wait for
1666         # a while until the target reparation has been done. LU-4970.
1667
1668         echo "'stat' should success after layout LFSCK repairing"
1669         wait_update_facet client "stat $DIR/$tdir/guard |
1670                 awk '/Size/ { print \\\$2 }'" "0" 32 || {
1671                 stat $DIR/$tdir/guard
1672                 $SHOW_LAYOUT
1673                 error "(8) unexpected size"
1674         }
1675
1676         repaired=$($SHOW_LAYOUT |
1677                          awk '/^repaired_dangling/ { print $2 }')
1678         [ $repaired -ge 32 ] ||
1679                 error "(9) Fail to repair dangling reference: $repaired"
1680
1681         stop_full_debug_logging
1682
1683         echo "stopall to cleanup object cache"
1684         stopall > /dev/null
1685         echo "setupall"
1686         setupall > /dev/null
1687 }
1688 run_test 14b "LFSCK can repair MDT-object with dangling LOV EA reference (2)"
1689
1690 test_15a() {
1691         echo "#####"
1692         echo "If the OST-object referenced by the MDT-object back points"
1693         echo "to some non-exist MDT-object, then the LFSCK should repair"
1694         echo "the OST-object to back point to the right MDT-object."
1695         echo "#####"
1696
1697         check_mount_and_prep
1698         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1699
1700         echo "Inject failure stub to make the OST-object to back point to"
1701         echo "non-exist MDT-object."
1702         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
1703
1704         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x1611
1705         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1706         $LFS setstripe -E 1M -S 256K -c 1 -E -1 -S 512K -c $OSTCOUNT \
1707                 $DIR/$tdir/f1 ||
1708                 error "(0) Fail to create PFL $DIR/$tdir/f1"
1709         # 'dd' will trigger punch RPC firstly on every OST-objects.
1710         # So even though some OST-object will not be write by 'dd',
1711         # as long as it is allocated (may be NOT allocated in pfl_3b)
1712         # its layout information will be set also.
1713         dd if=/dev/zero of=$DIR/$tdir/f1 bs=4K count=257
1714         cancel_lru_locks osc
1715         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0
1716
1717         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1718         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1719
1720         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1721                 mdd.${MDT_DEV}.lfsck_layout |
1722                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1723                 $SHOW_LAYOUT
1724                 error "(2) unexpected status"
1725         }
1726
1727         local repaired=$($SHOW_LAYOUT |
1728                          awk '/^repaired_unmatched_pair/ { print $2 }')
1729         [ $repaired -ge 3 ] ||
1730                 error "(3) Fail to repair unmatched pair: $repaired"
1731 }
1732 run_test 15a "LFSCK can repair unmatched MDT-object/OST-object pairs (1)"
1733
1734 test_15b() {
1735         echo "#####"
1736         echo "If the OST-object referenced by the MDT-object back points"
1737         echo "to other MDT-object that doesn't recognize the OST-object,"
1738         echo "then the LFSCK should repair it to back point to the right"
1739         echo "MDT-object (the first one)."
1740         echo "#####"
1741
1742         check_mount_and_prep
1743         mkdir -p $DIR/$tdir/0
1744         $LFS setstripe -c 1 -i 0 $DIR/$tdir/0
1745         dd if=/dev/zero of=$DIR/$tdir/0/guard bs=1M count=1
1746         cancel_lru_locks osc
1747
1748         echo "Inject failure stub to make the OST-object to back point to"
1749         echo "other MDT-object"
1750
1751         local stripes=1
1752         [ $OSTCOUNT -ge 2 ] && stripes=2
1753
1754         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR2  0x1612
1755         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x1612
1756         dd if=/dev/zero of=$DIR/$tdir/0/f0 bs=1M count=1
1757         $LFS setstripe -E 1M -S 256K -c $stripes -E 2M -S 512K -c 1 \
1758                 $DIR/$tdir/f1 ||
1759                 error "(0) Fail to create PFL $DIR/$tdir/f1"
1760         dd if=/dev/zero of=$DIR/$tdir/f1 bs=1M count=2
1761         cancel_lru_locks osc
1762         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0
1763
1764         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1765         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1766
1767         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1768                 mdd.${MDT_DEV}.lfsck_layout |
1769                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1770                 $SHOW_LAYOUT
1771                 error "(2) unexpected status"
1772         }
1773
1774         local repaired=$($SHOW_LAYOUT |
1775                          awk '/^repaired_unmatched_pair/ { print $2 }')
1776         [ $repaired -eq 4 ] ||
1777                 error "(3) Fail to repair unmatched pair: $repaired"
1778 }
1779 run_test 15b "LFSCK can repair unmatched MDT-object/OST-object pairs (2)"
1780
1781 test_15c() {
1782         [ $MDSCOUNT -lt 2 ] &&
1783                 skip "We need at least 2 MDSes for this test" && return
1784
1785         [ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.7.55) ] &&
1786                 skip "Skip the test after 2.7.55 see LU-6437" && return
1787
1788         echo "#####"
1789         echo "According to current metadata migration implementation,"
1790         echo "before the old MDT-object is removed, both the new MDT-object"
1791         echo "and old MDT-object will reference the same LOV layout. Then if"
1792         echo "the layout LFSCK finds the new MDT-object by race, it will"
1793         echo "regard related OST-object(s) as multiple referenced case, and"
1794         echo "will try to create new OST-object(s) for the new MDT-object."
1795         echo "To avoid such trouble, the layout LFSCK needs to lock the old"
1796         echo "MDT-object before confirm the multiple referenced case."
1797         echo "#####"
1798
1799         check_mount_and_prep
1800         $LFS mkdir -i 1 $DIR/$tdir/a1
1801         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
1802         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=1
1803         cancel_lru_locks osc
1804
1805         echo "Inject failure stub on MDT1 to delay the migration"
1806
1807         #define OBD_FAIL_MIGRATE_DELAY                  0x1803
1808         do_facet mds2 $LCTL set_param fail_val=5 fail_loc=0x1803
1809         echo "Migrate $DIR/$tdir/a1 from MDT1 to MDT0 with delay"
1810         $LFS migrate -m 0 $DIR/$tdir/a1 &
1811
1812         sleep 1
1813         echo "Trigger layout LFSCK to race with the migration"
1814         $START_LAYOUT -A -r || error "(1) Fail to start layout LFSCK!"
1815
1816         wait_all_targets_blocked layout completed 2
1817
1818         do_facet mds2 $LCTL set_param fail_loc=0 fail_val=0
1819         local repaired=$($SHOW_LAYOUT |
1820                          awk '/^repaired_unmatched_pair/ { print $2 }')
1821         [ $repaired -eq 1 ] ||
1822                 error "(3) Fail to repair unmatched pair: $repaired"
1823
1824         repaired=$($SHOW_LAYOUT |
1825                    awk '/^repaired_multiple_referenced/ { print $2 }')
1826         [ $repaired -eq 0 ] ||
1827                 error "(4) Unexpectedly repaird multiple references: $repaired"
1828 }
1829 run_test 15c "LFSCK can repair unmatched MDT-object/OST-object pairs (3)"
1830
1831 test_16() {
1832         echo "#####"
1833         echo "If the OST-object's owner information does not match the owner"
1834         echo "information stored in the MDT-object, then the LFSCK trust the"
1835         echo "MDT-object and update the OST-object's owner information."
1836         echo "#####"
1837
1838         check_mount_and_prep
1839         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1840         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1841         cancel_lru_locks osc
1842
1843         echo "Inject failure stub to skip OST-object owner changing"
1844         #define OBD_FAIL_LFSCK_BAD_OWNER        0x1613
1845         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1613
1846         chown 1.1 $DIR/$tdir/f0
1847         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1848
1849         echo "Trigger layout LFSCK to find out inconsistent OST-object owner"
1850         echo "and fix them"
1851
1852         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1853
1854         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1855                 mdd.${MDT_DEV}.lfsck_layout |
1856                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1857                 $SHOW_LAYOUT
1858                 error "(2) unexpected status"
1859         }
1860
1861         local repaired=$($SHOW_LAYOUT |
1862                          awk '/^repaired_inconsistent_owner/ { print $2 }')
1863         [ $repaired -eq 1 ] ||
1864                 error "(3) Fail to repair inconsistent owner: $repaired"
1865 }
1866 run_test 16 "LFSCK can repair inconsistent MDT-object/OST-object owner"
1867
1868 test_17() {
1869         echo "#####"
1870         echo "If more than one MDT-objects reference the same OST-object,"
1871         echo "and the OST-object only recognizes one MDT-object, then the"
1872         echo "LFSCK should create new OST-objects for such non-recognized"
1873         echo "MDT-objects."
1874         echo "#####"
1875
1876         check_mount_and_prep
1877         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1878
1879         echo "Inject failure stub to make two MDT-objects to refernce"
1880         echo "the OST-object"
1881
1882         #define OBD_FAIL_LFSCK_MULTIPLE_REF     0x1614
1883         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0x1614
1884         dd if=/dev/zero of=$DIR/$tdir/guard bs=1M count=1
1885         cancel_lru_locks mdc
1886         cancel_lru_locks osc
1887
1888         createmany -o $DIR/$tdir/f 1
1889         cancel_lru_locks mdc
1890         cancel_lru_locks osc
1891
1892         $LFS setstripe -E 2M -S 256K -o 0 -E 4M -S 512K -o 0 \
1893                 $DIR/$tdir/f1 ||
1894                 error "(0) Fail to create PFL $DIR/$tdir/f1"
1895         cancel_lru_locks mdc
1896         cancel_lru_locks osc
1897         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
1898
1899         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard use the same OST-objects"
1900         echo "$DIR/$tdir/f1 and $DIR/$tdir/guard use the same OST-objects"
1901         local size=$(ls -l $DIR/$tdir/f0 | awk '{ print $5 }')
1902         [ $size -eq 1048576 ] ||
1903                 error "(1.1) f0 (wrong) size should be 1048576, but got $size"
1904
1905         size=$(ls -l $DIR/$tdir/f1 | awk '{ print $5 }')
1906         [ $size -eq 1048576 ] ||
1907                 error "(1.2) f1 (wrong) size should be 1048576, but got $size"
1908
1909         echo "Trigger layout LFSCK to find out multiple refenced MDT-objects"
1910         echo "and fix them"
1911
1912         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1913
1914         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1915                 mdd.${MDT_DEV}.lfsck_layout |
1916                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1917                 $SHOW_LAYOUT
1918                 error "(3) unexpected status"
1919         }
1920
1921         local repaired=$($SHOW_LAYOUT |
1922                          awk '/^repaired_multiple_referenced/ { print $2 }')
1923         [ $repaired -eq 2 ] ||
1924                 error "(4) Fail to repair multiple references: $repaired"
1925
1926         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard should use diff OST-objects"
1927         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=2 ||
1928                 error "(5) Fail to write f0."
1929         size=$(ls -l $DIR/$tdir/guard | awk '{ print $5 }')
1930         [ $size -eq 1048576 ] ||
1931                 error "(6) guard size should be 1048576, but got $size"
1932
1933         echo "$DIR/$tdir/f1 and $DIR/$tdir/guard should use diff OST-objects"
1934         dd if=/dev/zero of=$DIR/$tdir/f1 bs=1M count=2 ||
1935                 error "(7) Fail to write f1."
1936         size=$(ls -l $DIR/$tdir/guard | awk '{ print $5 }')
1937         [ $size -eq 1048576 ] ||
1938                 error "(8) guard size should be 1048576, but got $size"
1939 }
1940 run_test 17 "LFSCK can repair multiple references"
1941
1942 $LCTL set_param debug=+cache > /dev/null
1943
1944 test_18a() {
1945         echo "#####"
1946         echo "The target MDT-object is there, but related stripe information"
1947         echo "is lost or partly lost. The LFSCK should regenerate the missing"
1948         echo "layout EA entries."
1949         echo "#####"
1950
1951         check_mount_and_prep
1952         $LFS mkdir -i 0 $DIR/$tdir/a1
1953         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
1954         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1955
1956         local saved_size1=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1957
1958         $LFS path2fid $DIR/$tdir/a1/f1
1959         $LFS getstripe $DIR/$tdir/a1/f1
1960
1961         if [ $MDSCOUNT -ge 2 ]; then
1962                 $LFS mkdir -i 1 $DIR/$tdir/a2
1963                 $LFS setstripe -c 2 -i 1 -S 1M $DIR/$tdir/a2
1964                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1965                 $LFS path2fid $DIR/$tdir/a2/f2
1966                 $LFS getstripe $DIR/$tdir/a2/f2
1967         fi
1968
1969         $LFS setstripe -E 1M -S 1M -o 0 -E -1 -S 1M $DIR/$tdir/f3 ||
1970                 error "(0) Fail to create PFL $DIR/$tdir/f3"
1971
1972         dd if=/dev/zero of=$DIR/$tdir/f3 bs=1M count=2
1973
1974         local saved_size2=$(ls -il $DIR/$tdir/f3 | awk '{ print $6 }')
1975
1976         $LFS path2fid $DIR/$tdir/f3
1977         $LFS getstripe $DIR/$tdir/f3
1978
1979         cancel_lru_locks osc
1980
1981         echo "Inject failure, to make the MDT-object lost its layout EA"
1982         #define OBD_FAIL_LFSCK_LOST_STRIPE 0x1615
1983         do_facet mds1 $LCTL set_param fail_loc=0x1615
1984         chown 1.1 $DIR/$tdir/a1/f1
1985
1986         if [ $MDSCOUNT -ge 2 ]; then
1987                 do_facet mds2 $LCTL set_param fail_loc=0x1615
1988                 chown 1.1 $DIR/$tdir/a2/f2
1989         fi
1990
1991         chown 1.1 $DIR/$tdir/f3
1992
1993         sync
1994         sleep 2
1995
1996         do_facet mds1 $LCTL set_param fail_loc=0
1997         if [ $MDSCOUNT -ge 2 ]; then
1998                 do_facet mds2 $LCTL set_param fail_loc=0
1999         fi
2000
2001         cancel_lru_locks mdc
2002         cancel_lru_locks osc
2003
2004         echo "The file size should be incorrect since layout EA is lost"
2005         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
2006         [ "$cur_size" != "$saved_size1" ] ||
2007                 error "(1) Expect incorrect file1 size"
2008
2009         if [ $MDSCOUNT -ge 2 ]; then
2010                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
2011                 [ "$cur_size" != "$saved_size1" ] ||
2012                         error "(2) Expect incorrect file2 size"
2013         fi
2014
2015         cur_size=$(ls -il $DIR/$tdir/f3 | awk '{ print $6 }')
2016         [ "$cur_size" != "$saved_size2" ] ||
2017                 error "(1.2) Expect incorrect file3 size"
2018
2019         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2020         $START_LAYOUT -r -o || error "(3) Fail to start LFSCK for layout!"
2021
2022         for k in $(seq $MDSCOUNT); do
2023                 # The LFSCK status query internal is 30 seconds. For the case
2024                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2025                 # time to guarantee the status sync up.
2026                 wait_update_facet mds${k} "$LCTL get_param -n \
2027                         mdd.$(facet_svc mds${k}).lfsck_layout |
2028                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2029                         error "(4) MDS${k} is not the expected 'completed'"
2030         done
2031
2032         for k in $(seq $OSTCOUNT); do
2033                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2034                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2035                                 awk '/^status/ { print $2 }')
2036                 [ "$cur_status" == "completed" ] ||
2037                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
2038         done
2039
2040         local repaired=$(do_facet mds1 $LCTL get_param -n \
2041                          mdd.$(facet_svc mds1).lfsck_layout |
2042                          awk '/^repaired_orphan/ { print $2 }')
2043         [ $repaired -eq 3 ] ||
2044         error "(6.1) Expect 3 fixed on mds1, but got: $repaired"
2045
2046         if [ $MDSCOUNT -ge 2 ]; then
2047                 repaired=$(do_facet mds2 $LCTL get_param -n \
2048                          mdd.$(facet_svc mds2).lfsck_layout |
2049                                  awk '/^repaired_orphan/ { print $2 }')
2050                 [ $repaired -eq 2 ] ||
2051                 error "(6.2) Expect 2 fixed on mds2, but got: $repaired"
2052         fi
2053
2054         $LFS path2fid $DIR/$tdir/a1/f1
2055         $LFS getstripe $DIR/$tdir/a1/f1
2056
2057         if [ $MDSCOUNT -ge 2 ]; then
2058                 $LFS path2fid $DIR/$tdir/a2/f2
2059                 $LFS getstripe $DIR/$tdir/a2/f2
2060         fi
2061
2062         $LFS path2fid $DIR/$tdir/f3
2063         $LFS getstripe $DIR/$tdir/f3
2064
2065         echo "The file size should be correct after layout LFSCK scanning"
2066         cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
2067         [ "$cur_size" == "$saved_size1" ] ||
2068                 error "(7) Expect file1 size $saved_size1, but got $cur_size"
2069
2070         if [ $MDSCOUNT -ge 2 ]; then
2071                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
2072                 [ "$cur_size" == "$saved_size1" ] ||
2073                 error "(8) Expect file2 size $saved_size1, but got $cur_size"
2074         fi
2075
2076         cur_size=$(ls -il $DIR/$tdir/f3 | awk '{ print $6 }')
2077         [ "$cur_size" == "$saved_size2" ] ||
2078                 error "(9) Expect file1 size $saved_size2, but got $cur_size"
2079 }
2080 run_test 18a "Find out orphan OST-object and repair it (1)"
2081
2082 test_18b() {
2083         echo "#####"
2084         echo "The target MDT-object is lost. The LFSCK should re-create the"
2085         echo "MDT-object under .lustre/lost+found/MDTxxxx. The admin should"
2086         echo "can move it back to normal namespace manually."
2087         echo "#####"
2088
2089         check_mount_and_prep
2090         $LFS mkdir -i 0 $DIR/$tdir/a1
2091         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
2092         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
2093         local saved_size1=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
2094         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
2095         echo ${fid1}
2096         $LFS getstripe $DIR/$tdir/a1/f1
2097
2098         if [ $MDSCOUNT -ge 2 ]; then
2099                 $LFS mkdir -i 1 $DIR/$tdir/a2
2100                 $LFS setstripe -c 2 -i 1 -S 1M $DIR/$tdir/a2
2101                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
2102                 fid2=$($LFS path2fid $DIR/$tdir/a2/f2)
2103                 echo ${fid2}
2104                 $LFS getstripe $DIR/$tdir/a2/f2
2105         fi
2106
2107         $LFS setstripe -E 1M -S 1M -o 0 -E -1 -S 1M $DIR/$tdir/f3 ||
2108                 error "(0) Fail to create PFL $DIR/$tdir/f3"
2109
2110         dd if=/dev/zero of=$DIR/$tdir/f3 bs=1M count=2
2111
2112         local saved_size2=$(ls -il $DIR/$tdir/f3 | awk '{ print $6 }')
2113         local fid3=$($LFS path2fid $DIR/$tdir/f3)
2114         echo ${fid3}
2115         $LFS getstripe $DIR/$tdir/f3
2116
2117         cancel_lru_locks osc
2118
2119         echo "Inject failure, to simulate the case of missing the MDT-object"
2120         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2121         do_facet mds1 $LCTL set_param fail_loc=0x1616
2122         rm -f $DIR/$tdir/a1/f1
2123
2124         if [ $MDSCOUNT -ge 2 ]; then
2125                 do_facet mds2 $LCTL set_param fail_loc=0x1616
2126                 rm -f $DIR/$tdir/a2/f2
2127         fi
2128
2129         rm -f $DIR/$tdir/f3
2130
2131         sync
2132         sleep 2
2133
2134         do_facet mds1 $LCTL set_param fail_loc=0
2135         if [ $MDSCOUNT -ge 2 ]; then
2136                 do_facet mds2 $LCTL set_param fail_loc=0
2137         fi
2138
2139         cancel_lru_locks mdc
2140         cancel_lru_locks osc
2141
2142         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2143         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2144
2145         for k in $(seq $MDSCOUNT); do
2146                 # The LFSCK status query internal is 30 seconds. For the case
2147                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2148                 # time to guarantee the status sync up.
2149                 wait_update_facet mds${k} "$LCTL get_param -n \
2150                         mdd.$(facet_svc mds${k}).lfsck_layout |
2151                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2152                         error "(2) MDS${k} is not the expected 'completed'"
2153         done
2154
2155         for k in $(seq $OSTCOUNT); do
2156                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2157                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2158                                 awk '/^status/ { print $2 }')
2159                 [ "$cur_status" == "completed" ] ||
2160                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2161         done
2162
2163         local repaired=$(do_facet mds1 $LCTL get_param -n \
2164                          mdd.$(facet_svc mds1).lfsck_layout |
2165                          awk '/^repaired_orphan/ { print $2 }')
2166         [ $repaired -eq 3 ] ||
2167         error "(4.1) Expect 3 fixed on mds1, but got: $repaired"
2168
2169         if [ $MDSCOUNT -ge 2 ]; then
2170                 repaired=$(do_facet mds2 $LCTL get_param -n \
2171                          mdd.$(facet_svc mds2).lfsck_layout |
2172                          awk '/^repaired_orphan/ { print $2 }')
2173                 [ $repaired -eq 2 ] ||
2174                 error "(4.2) Expect 2 fixed on mds2, but got: $repaired"
2175         fi
2176
2177         echo "Move the files from ./lustre/lost+found/MDTxxxx to namespace"
2178         mv $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0 $DIR/$tdir/a1/f1 ||
2179         error "(5) Fail to move $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
2180
2181         if [ $MDSCOUNT -ge 2 ]; then
2182                 local name=$MOUNT/.lustre/lost+found/MDT0001/${fid2}-R-0
2183                 mv $name $DIR/$tdir/a2/f2 || error "(6) Fail to move $name"
2184         fi
2185
2186         mv $MOUNT/.lustre/lost+found/MDT0000/${fid3}-R-0 $DIR/$tdir/f3 ||
2187         error "(5) Fail to move $MOUNT/.lustre/lost+found/MDT0000/${fid3}-R-0"
2188
2189         $LFS path2fid $DIR/$tdir/a1/f1
2190         $LFS getstripe $DIR/$tdir/a1/f1
2191
2192         if [ $MDSCOUNT -ge 2 ]; then
2193                 $LFS path2fid $DIR/$tdir/a2/f2
2194                 $LFS getstripe $DIR/$tdir/a2/f2
2195         fi
2196
2197         $LFS path2fid $DIR/$tdir/f3
2198         $LFS getstripe $DIR/$tdir/f3
2199
2200         echo "The file size should be correct after layout LFSCK scanning"
2201         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
2202         [ "$cur_size" == "$saved_size1" ] ||
2203                 error "(7) Expect file1 size $saved_size1, but got $cur_size"
2204
2205         if [ $MDSCOUNT -ge 2 ]; then
2206                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
2207                 [ "$cur_size" == "$saved_size1" ] ||
2208                 error "(8) Expect file2 size $saved_size1, but got $cur_size"
2209         fi
2210
2211         cur_size=$(ls -il $DIR/$tdir/f3 | awk '{ print $6 }')
2212         [ "$cur_size" == "$saved_size2" ] ||
2213                 error "(9) Expect file1 size $saved_size2, but got $cur_size"
2214 }
2215 run_test 18b "Find out orphan OST-object and repair it (2)"
2216
2217 test_18c() {
2218         echo "#####"
2219         echo "The target MDT-object is lost, and the OST-object FID is missing."
2220         echo "The LFSCK should re-create the MDT-object with new FID under the "
2221         echo "directory .lustre/lost+found/MDTxxxx."
2222         echo "#####"
2223
2224         check_mount_and_prep
2225         $LFS mkdir -i 0 $DIR/$tdir/a1
2226         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
2227
2228         echo "Inject failure, to simulate the case of missing parent FID"
2229         #define OBD_FAIL_LFSCK_NOPFID           0x1617
2230         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x1617
2231
2232         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
2233         $LFS getstripe $DIR/$tdir/a1/f1
2234
2235         if [ $MDSCOUNT -ge 2 ]; then
2236                 $LFS mkdir -i 1 $DIR/$tdir/a2
2237                 $LFS setstripe -c 1 -i 0 $DIR/$tdir/a2
2238                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
2239                 $LFS getstripe $DIR/$tdir/a2/f2
2240         fi
2241
2242         $LFS setstripe -E 1M -S 1M -o 0 -E -1 -S 1M $DIR/$tdir/f3 ||
2243                 error "(0) Fail to create PFL $DIR/$tdir/f3"
2244
2245         dd if=/dev/zero of=$DIR/$tdir/f3 bs=1M count=2
2246         $LFS getstripe $DIR/$tdir/f3
2247
2248         cancel_lru_locks osc
2249         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0
2250
2251         echo "Inject failure, to simulate the case of missing the MDT-object"
2252         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2253         do_facet mds1 $LCTL set_param fail_loc=0x1616
2254         rm -f $DIR/$tdir/a1/f1
2255
2256         if [ $MDSCOUNT -ge 2 ]; then
2257                 do_facet mds2 $LCTL set_param fail_loc=0x1616
2258                 rm -f $DIR/$tdir/a2/f2
2259         fi
2260
2261         rm -f $DIR/$tdir/f3
2262
2263         sync
2264         sleep 2
2265
2266         do_facet mds1 $LCTL set_param fail_loc=0
2267         if [ $MDSCOUNT -ge 2 ]; then
2268                 do_facet mds2 $LCTL set_param fail_loc=0
2269         fi
2270
2271         cancel_lru_locks mdc
2272         cancel_lru_locks osc
2273
2274         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2275         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2276
2277         for k in $(seq $MDSCOUNT); do
2278                 # The LFSCK status query internal is 30 seconds. For the case
2279                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2280                 # time to guarantee the status sync up.
2281                 wait_update_facet mds${k} "$LCTL get_param -n \
2282                         mdd.$(facet_svc mds${k}).lfsck_layout |
2283                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2284                         error "(2) MDS${k} is not the expected 'completed'"
2285         done
2286
2287         for k in $(seq $OSTCOUNT); do
2288                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2289                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2290                                 awk '/^status/ { print $2 }')
2291                 [ "$cur_status" == "completed" ] ||
2292                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2293         done
2294
2295         if [ $MDSCOUNT -ge 2 ]; then
2296                 expected=4
2297         else
2298                 expected=3
2299         fi
2300
2301         local repaired=$(do_facet mds1 $LCTL get_param -n \
2302                          mdd.$(facet_svc mds1).lfsck_layout |
2303                          awk '/^repaired_orphan/ { print $2 }')
2304         [ $repaired -eq $expected ] ||
2305                 error "(4) Expect $expected fixed on mds1, but got: $repaired"
2306
2307         if [ $MDSCOUNT -ge 2 ]; then
2308                 repaired=$(do_facet mds2 $LCTL get_param -n \
2309                            mdd.$(facet_svc mds2).lfsck_layout |
2310                            awk '/^repaired_orphan/ { print $2 }')
2311                 [ $repaired -eq 0 ] ||
2312                         error "(5) Expect 0 fixed on mds2, but got: $repaired"
2313         fi
2314
2315         ls -ail $MOUNT/.lustre/lost+found/
2316
2317         echo "There should NOT be some stub under .lustre/lost+found/MDT0001/"
2318         if [ -d $MOUNT/.lustre/lost+found/MDT0001 ]; then
2319                 cname=$(find $MOUNT/.lustre/lost+found/MDT0001/ -name *-N-*)
2320                 [ -z "$cname" ] ||
2321                         error "(6) .lustre/lost+found/MDT0001/ should be empty"
2322         fi
2323
2324         echo "There should be some stub under .lustre/lost+found/MDT0000/"
2325         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
2326                 error "(7) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
2327
2328         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-N-*)
2329         [ ! -z "$cname" ] ||
2330                 error "(8) .lustre/lost+found/MDT0000/ should not be empty"
2331 }
2332 run_test 18c "Find out orphan OST-object and repair it (3)"
2333
2334 test_18d() {
2335         echo "#####"
2336         echo "The target MDT-object layout EA is corrupted, but the right"
2337         echo "OST-object is still alive as orphan. The layout LFSCK will"
2338         echo "not create new OST-object to occupy such slot."
2339         echo "#####"
2340
2341         check_mount_and_prep
2342         mkdir $DIR/$tdir/a1
2343         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
2344         echo "guard" > $DIR/$tdir/a1/f1
2345         echo "foo" > $DIR/$tdir/a1/f2
2346
2347         echo "guard" > $DIR/$tdir/a1/f3
2348         $LFS setstripe -E 1M -S 1M -o 0 -E -1 -S 1M $DIR/$tdir/a1/f4 ||
2349                 error "(0) Fail to create PFL $DIR/$tdir/a1/f4"
2350         echo "foo" > $DIR/$tdir/a1/f4
2351
2352         local saved_size1=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2353         local saved_size2=$(ls -il $DIR/$tdir/a1/f4 | awk '{ print $6 }')
2354         $LFS path2fid $DIR/$tdir/a1/f1
2355         $LFS getstripe $DIR/$tdir/a1/f1
2356         $LFS path2fid $DIR/$tdir/a1/f2
2357         $LFS getstripe $DIR/$tdir/a1/f2
2358         $LFS path2fid $DIR/$tdir/a1/f3
2359         $LFS getstripe $DIR/$tdir/a1/f3
2360         $LFS path2fid $DIR/$tdir/a1/f4
2361         $LFS getstripe $DIR/$tdir/a1/f4
2362         cancel_lru_locks osc
2363
2364         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
2365         echo "to reference the same OST-object (which is f1's OST-obejct)."
2366         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
2367         echo "dangling reference case, but f2's old OST-object is there."
2368
2369         echo "The failure also makes $DIR/$tdir/a1/f3 and $DIR/$tdir/a1/f4"
2370         echo "to reference the same OST-object (which is f3's OST-obejct)."
2371         echo "Then drop $DIR/$tdir/a1/f3 and its OST-object, so f4 becomes"
2372         echo "dangling reference case, but f4's old OST-object is there."
2373         echo
2374
2375         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
2376         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
2377         chown 1.1 $DIR/$tdir/a1/f2
2378         chown 1.1 $DIR/$tdir/a1/f4
2379         rm -f $DIR/$tdir/a1/f1
2380         rm -f $DIR/$tdir/a1/f3
2381         sync
2382         sleep 2
2383         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2384
2385         echo "stopall to cleanup object cache"
2386         stopall > /dev/null
2387         echo "setupall"
2388         setupall > /dev/null
2389
2390         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2391         $START_LAYOUT -r -o -c -d || error "(2) Fail to start LFSCK for layout!"
2392
2393         for k in $(seq $MDSCOUNT); do
2394                 # The LFSCK status query internal is 30 seconds. For the case
2395                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2396                 # time to guarantee the status sync up.
2397                 wait_update_facet mds${k} "$LCTL get_param -n \
2398                         mdd.$(facet_svc mds${k}).lfsck_layout |
2399                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2400                         error "(3) MDS${k} is not the expected 'completed'"
2401         done
2402
2403         for k in $(seq $OSTCOUNT); do
2404                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2405                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2406                                 awk '/^status/ { print $2 }')
2407                 [ "$cur_status" == "completed" ] ||
2408                 error "(4) OST${k} Expect 'completed', but got '$cur_status'"
2409         done
2410
2411         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
2412                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
2413                          awk '/^repaired_orphan/ { print $2 }')
2414         [ $repaired -eq 2 ] ||
2415                 error "(5) Expect 2 orphans have been fixed, but got: $repaired"
2416
2417         repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
2418                    mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
2419                    awk '/^repaired_dangling/ { print $2 }')
2420         [ $repaired -eq 0 ] ||
2421                 error "(6) Expect 0 dangling has been fixed, but got: $repaired"
2422
2423         echo "The file size should be correct after layout LFSCK scanning"
2424         local cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2425         [ "$cur_size" == "$saved_size1" ] ||
2426                 error "(7) Expect file2 size $saved_size1, but got $cur_size"
2427
2428         cur_size=$(ls -il $DIR/$tdir/a1/f4 | awk '{ print $6 }')
2429         [ "$cur_size" == "$saved_size2" ] ||
2430                 error "(8) Expect file4 size $saved_size2, but got $cur_size"
2431
2432         echo "The LFSCK should find back the original data."
2433         cat $DIR/$tdir/a1/f2
2434         $LFS path2fid $DIR/$tdir/a1/f2
2435         $LFS getstripe $DIR/$tdir/a1/f2
2436         cat $DIR/$tdir/a1/f4
2437         $LFS path2fid $DIR/$tdir/a1/f4
2438         $LFS getstripe $DIR/$tdir/a1/f4
2439 }
2440 run_test 18d "Find out orphan OST-object and repair it (4)"
2441
2442 test_18e() {
2443         echo "#####"
2444         echo "The target MDT-object layout EA slot is occpuied by some new"
2445         echo "created OST-object when repair dangling reference case. Such"
2446         echo "conflict OST-object has been modified by others. To keep the"
2447         echo "new data, the LFSCK will create a new file to refernece this"
2448         echo "old orphan OST-object."
2449         echo "#####"
2450
2451         check_mount_and_prep
2452         mkdir $DIR/$tdir/a1
2453         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
2454         echo "guard" > $DIR/$tdir/a1/f1
2455         echo "foo" > $DIR/$tdir/a1/f2
2456
2457         echo "guard" > $DIR/$tdir/a1/f3
2458         $LFS setstripe -E 1M -S 1M -o 0 -E -1 -S 1M $DIR/$tdir/a1/f4 ||
2459                 error "(0) Fail to create PFL $DIR/$tdir/a1/f4"
2460         echo "foo" > $DIR/$tdir/a1/f4
2461
2462         local saved_size1=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2463         local saved_size2=$(ls -il $DIR/$tdir/a1/f4 | awk '{ print $6 }')
2464
2465         $LFS path2fid $DIR/$tdir/a1/f1
2466         $LFS getstripe $DIR/$tdir/a1/f1
2467         $LFS path2fid $DIR/$tdir/a1/f2
2468         $LFS getstripe $DIR/$tdir/a1/f2
2469         $LFS path2fid $DIR/$tdir/a1/f3
2470         $LFS getstripe $DIR/$tdir/a1/f3
2471         $LFS path2fid $DIR/$tdir/a1/f4
2472         $LFS getstripe $DIR/$tdir/a1/f4
2473         cancel_lru_locks osc
2474
2475         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
2476         echo "to reference the same OST-object (which is f1's OST-obejct)."
2477         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
2478         echo "dangling reference case, but f2's old OST-object is there."
2479
2480         echo "Also the failure makes $DIR/$tdir/a1/f3 and $DIR/$tdir/a1/f4"
2481         echo "to reference the same OST-object (which is f3's OST-obejct)."
2482         echo "Then drop $DIR/$tdir/a1/f3 and its OST-object, so f4 becomes"
2483         echo "dangling reference case, but f4's old OST-object is there."
2484         echo
2485
2486         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
2487         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
2488         chown 1.1 $DIR/$tdir/a1/f2
2489         chown 1.1 $DIR/$tdir/a1/f4
2490         rm -f $DIR/$tdir/a1/f1
2491         rm -f $DIR/$tdir/a1/f3
2492         sync
2493         sleep 2
2494         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2495
2496         echo "stopall to cleanup object cache"
2497         stopall > /dev/null
2498         echo "setupall"
2499         setupall > /dev/null
2500
2501         #define OBD_FAIL_LFSCK_DELAY3           0x1602
2502         do_facet $SINGLEMDS $LCTL set_param fail_val=10 fail_loc=0x1602
2503
2504         start_full_debug_logging
2505
2506         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2507         $START_LAYOUT -r -o -c || error "(2) Fail to start LFSCK for layout!"
2508
2509         wait_update_facet mds1 "$LCTL get_param -n \
2510                 mdd.$(facet_svc mds1).lfsck_layout |
2511                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" $LTIME ||
2512                 error "(3) MDS1 is not the expected 'scanning-phase2'"
2513
2514         # to guarantee all updates are synced.
2515         sync
2516         sleep 2
2517
2518         echo "Write new data to f2/f4 to modify the new created OST-object."
2519         echo "dummy" >> $DIR/$tdir/a1/f2
2520         echo "dummy" >> $DIR/$tdir/a1/f4
2521
2522         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
2523
2524         for k in $(seq $MDSCOUNT); do
2525                 # The LFSCK status query internal is 30 seconds. For the case
2526                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2527                 # time to guarantee the status sync up.
2528                 wait_update_facet mds${k} "$LCTL get_param -n \
2529                         mdd.$(facet_svc mds${k}).lfsck_layout |
2530                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2531                         error "(4) MDS${k} is not the expected 'completed'"
2532         done
2533
2534         for k in $(seq $OSTCOUNT); do
2535                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2536                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2537                                 awk '/^status/ { print $2 }')
2538                 [ "$cur_status" == "completed" ] ||
2539                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
2540         done
2541
2542         stop_full_debug_logging
2543
2544         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
2545                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
2546                          awk '/^repaired_orphan/ { print $2 }')
2547         [ $repaired -eq 2 ] ||
2548                 error "(6) Expect 2 orphans have been fixed, but got: $repaired"
2549
2550         echo "There should be stub file under .lustre/lost+found/MDT0000/"
2551         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
2552                 error "(7) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
2553
2554         local count=$(ls -l $MOUNT/.lustre/lost+found/MDT0000/*-C-* | wc -l)
2555         if [ $count -ne 2 ]; then
2556                 ls -l $MOUNT/.lustre/lost+found/MDT0000/*-C-*
2557                 error "(8) Expect 2 stubs under lost+found, but got $count"
2558         fi
2559
2560         echo "The stub file should keep the original f2 or f4 data"
2561         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-C-* | head -n 1)
2562         local cur_size=$(ls -il $cname | awk '{ print $6 }')
2563         [ "$cur_size" != "$saved_size1" -a "$cur_size" != "$saved_size2" ] &&
2564                 error "(9) Got unexpected $cur_size"
2565
2566         cat $cname
2567         $LFS path2fid $cname
2568         $LFS getstripe $cname
2569
2570         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-C-* | tail -n 1)
2571         cur_size=$(ls -il $cname | awk '{ print $6 }')
2572         [ "$cur_size" != "$saved_size1" -a "$cur_size" != "$saved_size2" ] &&
2573                 error "(10) Got unexpected $cur_size"
2574
2575         cat $cname
2576         $LFS path2fid $cname
2577         $LFS getstripe $cname
2578
2579         echo "The f2/f4 should contains new data."
2580         cat $DIR/$tdir/a1/f2
2581         $LFS path2fid $DIR/$tdir/a1/f2
2582         $LFS getstripe $DIR/$tdir/a1/f2
2583         cat $DIR/$tdir/a1/f4
2584         $LFS path2fid $DIR/$tdir/a1/f4
2585         $LFS getstripe $DIR/$tdir/a1/f4
2586 }
2587 run_test 18e "Find out orphan OST-object and repair it (5)"
2588
2589 test_18f() {
2590         [ $OSTCOUNT -lt 2 ] &&
2591                 skip "The test needs at least 2 OSTs" && return
2592
2593         echo "#####"
2594         echo "The target MDT-object is lost. The LFSCK should re-create the"
2595         echo "MDT-object under .lustre/lost+found/MDTxxxx. If some OST fail"
2596         echo "to verify some OST-object(s) during the first stage-scanning,"
2597         echo "the LFSCK should skip orphan OST-objects for such OST. Others"
2598         echo "should not be affected."
2599         echo "#####"
2600
2601         check_mount_and_prep
2602         $LFS mkdir -i 0 $DIR/$tdir/a1
2603         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
2604         dd if=/dev/zero of=$DIR/$tdir/a1/guard bs=1M count=2
2605         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
2606         $LFS mkdir -i 0 $DIR/$tdir/a2
2607         $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a2
2608         dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
2609         $LFS getstripe $DIR/$tdir/a1/f1
2610         $LFS getstripe $DIR/$tdir/a2/f2
2611
2612         if [ $MDSCOUNT -ge 2 ]; then
2613                 $LFS mkdir -i 1 $DIR/$tdir/a3
2614                 $LFS setstripe -c 1 -i 0 $DIR/$tdir/a3
2615                 dd if=/dev/zero of=$DIR/$tdir/a3/guard bs=1M count=2
2616                 dd if=/dev/zero of=$DIR/$tdir/a3/f3 bs=1M count=2
2617                 $LFS mkdir -i 1 $DIR/$tdir/a4
2618                 $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a4
2619                 dd if=/dev/zero of=$DIR/$tdir/a4/f4 bs=1M count=2
2620                 $LFS getstripe $DIR/$tdir/a3/f3
2621                 $LFS getstripe $DIR/$tdir/a4/f4
2622         fi
2623
2624         cancel_lru_locks osc
2625
2626         echo "Inject failure, to simulate the case of missing the MDT-object"
2627         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2628         do_facet mds1 $LCTL set_param fail_loc=0x1616
2629         rm -f $DIR/$tdir/a1/f1
2630         rm -f $DIR/$tdir/a2/f2
2631
2632         if [ $MDSCOUNT -ge 2 ]; then
2633                 do_facet mds2 $LCTL set_param fail_loc=0x1616
2634                 rm -f $DIR/$tdir/a3/f3
2635                 rm -f $DIR/$tdir/a4/f4
2636         fi
2637
2638         sync
2639         sleep 2
2640
2641         do_facet mds1 $LCTL set_param fail_loc=0
2642         if [ $MDSCOUNT -ge 2 ]; then
2643                 do_facet mds2 $LCTL set_param fail_loc=0
2644         fi
2645
2646         cancel_lru_locks mdc
2647         cancel_lru_locks osc
2648
2649         echo "Inject failure, to simulate the OST0 fail to handle"
2650         echo "MDT0 LFSCK request during the first-stage scanning."
2651         #define OBD_FAIL_LFSCK_BAD_NETWORK      0x161c
2652         do_facet mds1 $LCTL set_param fail_loc=0x161c fail_val=0
2653
2654         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2655         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2656
2657         for k in $(seq $MDSCOUNT); do
2658                 # The LFSCK status query internal is 30 seconds. For the case
2659                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2660                 # time to guarantee the status sync up.
2661                 wait_update_facet mds${k} "$LCTL get_param -n \
2662                         mdd.$(facet_svc mds${k}).lfsck_layout |
2663                         awk '/^status/ { print \\\$2 }'" "partial" $LTIME ||
2664                         error "(2) MDS${k} is not the expected 'partial'"
2665         done
2666
2667         wait_update_facet ost1 "$LCTL get_param -n \
2668                 obdfilter.$(facet_svc ost1).lfsck_layout |
2669                 awk '/^status/ { print \\\$2 }'" "partial" $LTIME || {
2670                 error "(3) OST1 is not the expected 'partial'"
2671         }
2672
2673         wait_update_facet ost2 "$LCTL get_param -n \
2674                 obdfilter.$(facet_svc ost2).lfsck_layout |
2675                 awk '/^status/ { print \\\$2 }'" "completed" $LTIME || {
2676                 error "(4) OST2 is not the expected 'completed'"
2677         }
2678
2679         do_facet mds1 $LCTL set_param fail_loc=0 fail_val=0
2680
2681         local repaired=$(do_facet mds1 $LCTL get_param -n \
2682                          mdd.$(facet_svc mds1).lfsck_layout |
2683                          awk '/^repaired_orphan/ { print $2 }')
2684         [ $repaired -eq 1 ] ||
2685                 error "(5) Expect 1 fixed on mds{1}, but got: $repaired"
2686
2687         if [ $MDSCOUNT -ge 2 ]; then
2688                 repaired=$(do_facet mds2 $LCTL get_param -n \
2689                          mdd.$(facet_svc mds2).lfsck_layout |
2690                          awk '/^repaired_orphan/ { print $2 }')
2691                 [ $repaired -eq 1 ] ||
2692                 error "(6) Expect 1 fixed on mds{2}, but got: $repaired"
2693         fi
2694
2695         echo "Trigger layout LFSCK on all devices again to cleanup"
2696         $START_LAYOUT -r -o || error "(7) Fail to start LFSCK for layout!"
2697
2698         for k in $(seq $MDSCOUNT); do
2699                 # The LFSCK status query internal is 30 seconds. For the case
2700                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2701                 # time to guarantee the status sync up.
2702                 wait_update_facet mds${k} "$LCTL get_param -n \
2703                         mdd.$(facet_svc mds${k}).lfsck_layout |
2704                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2705                         error "(8) MDS${k} is not the expected 'completed'"
2706         done
2707
2708         for k in $(seq $OSTCOUNT); do
2709                 cur_status=$(do_facet ost${k} $LCTL get_param -n \
2710                              obdfilter.$(facet_svc ost${k}).lfsck_layout |
2711                              awk '/^status/ { print $2 }')
2712                 [ "$cur_status" == "completed" ] ||
2713                 error "(9) OST${k} Expect 'completed', but got '$cur_status'"
2714
2715         done
2716
2717         local repaired=$(do_facet mds1 $LCTL get_param -n \
2718                          mdd.$(facet_svc mds1).lfsck_layout |
2719                          awk '/^repaired_orphan/ { print $2 }')
2720         [ $repaired -eq 2 ] ||
2721                 error "(10) Expect 2 fixed on mds{1}, but got: $repaired"
2722
2723         if [ $MDSCOUNT -ge 2 ]; then
2724                 repaired=$(do_facet mds2 $LCTL get_param -n \
2725                          mdd.$(facet_svc mds2).lfsck_layout |
2726                          awk '/^repaired_orphan/ { print $2 }')
2727                 [ $repaired -eq 2 ] ||
2728                 error "(11) Expect 2 fixed on mds{2}, but got: $repaired"
2729         fi
2730 }
2731 run_test 18f "Skip the failed OST(s) when handle orphan OST-objects"
2732
2733 test_18g() {
2734         echo "#####"
2735         echo "The target MDT-object is lost, but related OI mapping is there"
2736         echo "The LFSCK should recreate the lost MDT-object without affected"
2737         echo "by the stale OI mapping."
2738         echo "#####"
2739
2740         check_mount_and_prep
2741         $LFS mkdir -i 0 $DIR/$tdir/a1
2742         $LFS setstripe -c -1 -i 0 -S 1M $DIR/$tdir/a1
2743         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=$OSTCOUNT
2744         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
2745         echo ${fid1}
2746         $LFS getstripe $DIR/$tdir/a1/f1
2747         cancel_lru_locks osc
2748
2749         echo "Inject failure to simulate lost MDT-object but keep OI mapping"
2750         #define OBD_FAIL_LFSCK_LOST_MDTOBJ2     0x162e
2751         do_facet mds1 $LCTL set_param fail_loc=0x162e
2752         rm -f $DIR/$tdir/a1/f1
2753
2754         do_facet mds1 $LCTL set_param fail_loc=0
2755         cancel_lru_locks mdc
2756         cancel_lru_locks osc
2757
2758         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2759         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2760
2761         for k in $(seq $MDSCOUNT); do
2762                 # The LFSCK status query internal is 30 seconds. For the case
2763                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2764                 # time to guarantee the status sync up.
2765                 wait_update_facet mds${k} "$LCTL get_param -n \
2766                         mdd.$(facet_svc mds${k}).lfsck_layout |
2767                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2768                         error "(2) MDS${k} is not the expected 'completed'"
2769         done
2770
2771         for k in $(seq $OSTCOUNT); do
2772                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2773                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2774                                 awk '/^status/ { print $2 }')
2775                 [ "$cur_status" == "completed" ] ||
2776                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2777         done
2778
2779         local repaired=$(do_facet mds1 $LCTL get_param -n \
2780                          mdd.$(facet_svc mds1).lfsck_layout |
2781                          awk '/^repaired_orphan/ { print $2 }')
2782         [ $repaired -eq $OSTCOUNT ] ||
2783                 error "(4) Expect $OSTCOUNT fixed, but got: $repaired"
2784
2785         echo "Move the files from ./lustre/lost+found/MDTxxxx to namespace"
2786         mv $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0 $DIR/$tdir/a1/f1 ||
2787         error "(5) Fail to move $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
2788
2789         $LFS path2fid $DIR/$tdir/a1/f1
2790         $LFS getstripe $DIR/$tdir/a1/f1
2791 }
2792 run_test 18g "Find out orphan OST-object and repair it (7)"
2793
2794 test_18h() {
2795         echo "#####"
2796         echo "The PFL extent crashed. During the first cycle LFSCK scanning,"
2797         echo "the layout LFSCK will keep the bad PFL file(s) there without"
2798         echo "scanning its OST-object(s). Then in the second stage scanning,"
2799         echo "the OST will return related OST-object(s) to the MDT as orphan."
2800         echo "And then the LFSCK on the MDT can rebuild the PFL extent with"
2801         echo "the 'orphan(s)' stripe information."
2802         echo "#####"
2803
2804         check_mount_and_prep
2805
2806         $LFS setstripe -E 2M -c 1 -E -1 $DIR/$tdir/f0 ||
2807                 error "(0) Fail to create PFL $DIR/$tdir/f0"
2808
2809         cat $LUSTRE/tests/test-framework.sh > $DIR/$tdir/f0 ||
2810                 error "(1.1) Fail to write $DIR/$tdir/f0"
2811
2812         dd if=$LUSTRE/tests/test-framework.sh of=$DIR/$tdir/f0 bs=1M seek=2 ||
2813                 error "(1.2) Fail to write $DIR/$tdir/f0"
2814
2815         cp $DIR/$tdir/f0 $DIR/$tdir/guard
2816
2817         echo "Inject failure stub to simulate bad PFL extent range"
2818         #define OBD_FAIL_LFSCK_BAD_PFL_RANGE    0x162f
2819         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x162f
2820
2821         chown 1.1 $DIR/$tdir/f0
2822
2823         cancel_lru_locks mdc
2824         cancel_lru_locks osc
2825         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2826
2827         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1 &&
2828                 error "(2) Write to bad PFL file should fail"
2829
2830         echo "Trigger layout LFSCK to find out the bad lmm_oi and fix them"
2831         $START_LAYOUT -r -o || error "(3) Fail to start LFSCK for layout!"
2832
2833         for k in $(seq $MDSCOUNT); do
2834                 # The LFSCK status query internal is 30 seconds. For the case
2835                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2836                 # time to guarantee the status sync up.
2837                 wait_update_facet mds${k} "$LCTL get_param -n \
2838                         mdd.$(facet_svc mds${k}).lfsck_layout |
2839                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2840                         error "(4.1) MDS${k} is not the expected 'completed'"
2841         done
2842
2843         for k in $(seq $OSTCOUNT); do
2844                 cur_status=$(do_facet ost${k} $LCTL get_param -n \
2845                              obdfilter.$(facet_svc ost${k}).lfsck_layout |
2846                              awk '/^status/ { print $2 }')
2847                 [ "$cur_status" == "completed" ] ||
2848                 error "(4.2) OST${k} Expect 'completed', but got '$cur_status'"
2849
2850         done
2851
2852         local repaired=$($SHOW_LAYOUT |
2853                          awk '/^repaired_orphan/ { print $2 }')
2854         [ $repaired -eq 2 ] ||
2855                 error "(5) Fail to repair crashed PFL range: $repaired"
2856
2857         echo "Data in $DIR/$tdir/f0 should not be broken"
2858         diff $DIR/$tdir/f0 $DIR/$tdir/guard ||
2859                 error "(6) Data in $DIR/$tdir/f0 is broken"
2860
2861         echo "Write should succeed after LFSCK repairing the bad PFL range"
2862         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1 ||
2863                 error "(7) Write should succeed after LFSCK"
2864 }
2865 run_test 18h "LFSCK can repair crashed PFL extent range"
2866
2867 $LCTL set_param debug=-cache > /dev/null
2868
2869 test_19a() {
2870         check_mount_and_prep
2871         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2872
2873         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param -n \
2874                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 0
2875
2876         echo "foo1" > $DIR/$tdir/a0
2877         $LFS setstripe -E 512K -S 512K -o 0 -E -1 -S 1M $DIR/$tdir/a1 ||
2878                 error "(0) Fail to create PFL $DIR/$tdir/a1"
2879         echo "foo2" > $DIR/$tdir/a1
2880         echo "guard" > $DIR/$tdir/a2
2881         cancel_lru_locks osc
2882
2883         echo "Inject failure, then client will offer wrong parent FID when read"
2884         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param -n \
2885                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2886
2887         #define OBD_FAIL_LFSCK_INVALID_PFID     0x1619
2888         $LCTL set_param fail_loc=0x1619
2889
2890         echo "Read RPC with wrong parent FID should be denied"
2891         cat $DIR/$tdir/a0 && error "(3.1) Read a0 should be denied!"
2892         cat $DIR/$tdir/a1 && error "(3.2) Read a1 should be denied!"
2893         $LCTL set_param fail_loc=0
2894 }
2895 run_test 19a "OST-object inconsistency self detect"
2896
2897 test_19b() {
2898         check_mount_and_prep
2899         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2900
2901         echo "Inject failure stub to make the OST-object to back point to"
2902         echo "non-exist MDT-object"
2903
2904         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param -n \
2905                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 0
2906
2907         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
2908         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x1611
2909         echo "foo1" > $DIR/$tdir/f0
2910         $LFS setstripe -E 1M -S 1M -o 0 -E 4M -S 256K $DIR/$tdir/f1 ||
2911                 error "(0) Fail to create PFL $DIR/$tdir/f1"
2912         echo "foo2" > $DIR/$tdir/f1
2913         cancel_lru_locks osc
2914         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0
2915
2916         do_facet ost1 $LCTL set_param -n \
2917                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 0
2918         echo "Nothing should be fixed since self detect and repair is disabled"
2919         local repaired=$(do_facet ost1 $LCTL get_param -n \
2920                         obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2921                         awk '/^repaired/ { print $2 }')
2922         [ $repaired -eq 0 ] ||
2923                 error "(1) Expected 0 repaired, but got $repaired"
2924
2925         echo "Read RPC with right parent FID should be accepted,"
2926         echo "and cause parent FID on OST to be fixed"
2927
2928         do_nodes $(comma_list $(osts_nodes)) $LCTL set_param -n \
2929                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2930
2931         cat $DIR/$tdir/f0 || error "(2.1) Read f0 should not be denied!"
2932         cat $DIR/$tdir/f1 || error "(2.2) Read f1 should not be denied!"
2933
2934         repaired=$(do_facet ost1 $LCTL get_param -n \
2935                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2936                 awk '/^repaired/ { print $2 }')
2937         [ $repaired -eq 2 ] ||
2938                 error "(3) Expected 1 repaired, but got $repaired"
2939 }
2940 run_test 19b "OST-object inconsistency self repair"
2941
2942 PATTERN_WITH_HOLE="40000001"
2943 PATTERN_WITHOUT_HOLE="1"
2944
2945 test_20a() {
2946         [ $OSTCOUNT -lt 2 ] &&
2947                 skip "The test needs at least 2 OSTs" && return
2948
2949         echo "#####"
2950         echo "The target MDT-object and some of its OST-object are lost."
2951         echo "The LFSCK should find out the left OST-objects and re-create"
2952         echo "the MDT-object under the direcotry .lustre/lost+found/MDTxxxx/"
2953         echo "with the partial OST-objects (LOV EA hole)."
2954
2955         echo "New client can access the file with LOV EA hole via normal"
2956         echo "system tools or commands without crash the system."
2957
2958         echo "For old client, even though it cannot access the file with"
2959         echo "LOV EA hole, it should not cause the system crash."
2960         echo "#####"
2961
2962         check_mount_and_prep
2963         $LFS mkdir -i 0 $DIR/$tdir/a1
2964         if [ $OSTCOUNT -gt 2 ]; then
2965                 $LFS setstripe -c 3 -i 0 -S 1M $DIR/$tdir/a1
2966                 bcount=513
2967         else
2968                 $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a1
2969                 bcount=257
2970         fi
2971
2972         # 256 blocks on the stripe0.
2973         # 1 block on the stripe1 for 2 OSTs case.
2974         # 256 blocks on the stripe1 for other cases.
2975         # 1 block on the stripe2 if OSTs > 2
2976         dd if=/dev/zero of=$DIR/$tdir/a1/f0 bs=4096 count=$bcount
2977         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=4096 count=$bcount
2978         dd if=/dev/zero of=$DIR/$tdir/a1/f2 bs=4096 count=$bcount
2979
2980         local fid0=$($LFS path2fid $DIR/$tdir/a1/f0)
2981         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
2982         local fid2=$($LFS path2fid $DIR/$tdir/a1/f2)
2983
2984         echo ${fid0}
2985         $LFS getstripe $DIR/$tdir/a1/f0
2986         echo ${fid1}
2987         $LFS getstripe $DIR/$tdir/a1/f1
2988         echo ${fid2}
2989         $LFS getstripe $DIR/$tdir/a1/f2
2990
2991         if [ $OSTCOUNT -gt 2 ]; then
2992                 dd if=/dev/zero of=$DIR/$tdir/a1/f3 bs=4096 count=$bcount
2993                 fid3=$($LFS path2fid $DIR/$tdir/a1/f3)
2994                 echo ${fid3}
2995                 $LFS getstripe $DIR/$tdir/a1/f3
2996         fi
2997
2998         cancel_lru_locks osc
2999
3000         echo "Inject failure..."
3001         echo "To simulate f0 lost MDT-object"
3002         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
3003         do_facet mds1 $LCTL set_param fail_loc=0x1616
3004         rm -f $DIR/$tdir/a1/f0
3005
3006         echo "To simulate f1 lost MDT-object and OST-object0"
3007         #define OBD_FAIL_LFSCK_LOST_SPEOBJ      0x161a
3008         do_facet mds1 $LCTL set_param fail_loc=0x161a
3009         rm -f $DIR/$tdir/a1/f1
3010
3011         echo "To simulate f2 lost MDT-object and OST-object1"
3012         do_facet mds1 $LCTL set_param fail_val=1
3013         rm -f $DIR/$tdir/a1/f2
3014
3015         if [ $OSTCOUNT -gt 2 ]; then
3016                 echo "To simulate f3 lost MDT-object and OST-object2"
3017                 do_facet mds1 $LCTL set_param fail_val=2
3018                 rm -f $DIR/$tdir/a1/f3
3019         fi
3020
3021         umount_client $MOUNT
3022         sync
3023         sleep 2
3024         do_facet mds1 $LCTL set_param fail_loc=0 fail_val=0
3025
3026         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
3027         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
3028
3029         for k in $(seq $MDSCOUNT); do
3030                 # The LFSCK status query internal is 30 seconds. For the case
3031                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
3032                 # time to guarantee the status sync up.
3033                 wait_update_facet mds${k} "$LCTL get_param -n \
3034                         mdd.$(facet_svc mds${k}).lfsck_layout |
3035                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
3036                         error "(2) MDS${k} is not the expected 'completed'"
3037         done
3038
3039         for k in $(seq $OSTCOUNT); do
3040                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
3041                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
3042                                 awk '/^status/ { print $2 }')
3043                 [ "$cur_status" == "completed" ] ||
3044                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
3045         done
3046
3047         local repaired=$(do_facet mds1 $LCTL get_param -n \
3048                          mdd.$(facet_svc mds1).lfsck_layout |
3049                          awk '/^repaired_orphan/ { print $2 }')
3050         if [ $OSTCOUNT -gt 2 ]; then
3051                 [ $repaired -eq 9 ] ||
3052                         error "(4.1) Expect 9 fixed on mds1, but got: $repaired"
3053         else
3054                 [ $repaired -eq 4 ] ||
3055                         error "(4.2) Expect 4 fixed on mds1, but got: $repaired"
3056         fi
3057
3058         mount_client $MOUNT || error "(5.0) Fail to start client!"
3059
3060         LOV_PATTERN_F_HOLE=0x40000000
3061
3062         #
3063         # ${fid0}-R-0 is the old f0
3064         #
3065         local name="$MOUNT/.lustre/lost+found/MDT0000/${fid0}-R-0"
3066         echo "Check $name, which is the old f0"
3067
3068         $LFS getstripe -v $name || error "(5.1) cannot getstripe on $name"
3069
3070         local pattern=$($LFS getstripe -L $name)
3071         [[ "$pattern" = "$PATTERN_WITHOUT_HOLE" ]] ||
3072                 error "(5.2) NOT expect pattern flag hole, but got $pattern"
3073
3074         local stripes=$($LFS getstripe -c $name)
3075         if [ $OSTCOUNT -gt 2 ]; then
3076                 [ $stripes -eq 3 ] ||
3077                 error "(5.3.1) expect the stripe count is 3, but got $stripes"
3078         else
3079                 [ $stripes -eq 2 ] ||
3080                 error "(5.3.2) expect the stripe count is 2, but got $stripes"
3081         fi
3082
3083         local size=$(stat $name | awk '/Size:/ { print $2 }')
3084         [ $size -eq $((4096 * $bcount)) ] ||
3085                 error "(5.4) expect the size $((4096 * $bcount)), but got $size"
3086
3087         cat $name > /dev/null || error "(5.5) cannot read $name"
3088
3089         echo "dummy" >> $name || error "(5.6) cannot write $name"
3090
3091         chown $RUNAS_ID:$RUNAS_GID $name || error "(5.7) cannot chown on $name"
3092
3093         touch $name || error "(5.8) cannot touch $name"
3094
3095         rm -f $name || error "(5.9) cannot unlink $name"
3096
3097         #
3098         # ${fid1}-R-0 contains the old f1's stripe1 (and stripe2 if OSTs > 2)
3099         #
3100         name="$MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
3101         if [ $OSTCOUNT -gt 2 ]; then
3102                 echo "Check $name, it contains the old f1's stripe1 and stripe2"
3103         else
3104                 echo "Check $name, it contains the old f1's stripe1"
3105         fi
3106
3107         $LFS getstripe -v $name || error "(6.1) cannot getstripe on $name"
3108
3109         pattern=$($LFS getstripe -L $name)
3110         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3111                 error "(6.2) expect pattern flag hole, but got $pattern"
3112
3113         stripes=$($LFS getstripe -c $name)
3114         if [ $OSTCOUNT -gt 2 ]; then
3115                 [ $stripes -eq 3 ] ||
3116                 error "(6.3.1) expect the stripe count is 3, but got $stripes"
3117         else
3118                 [ $stripes -eq 2 ] ||
3119                 error "(6.3.2) expect the stripe count is 2, but got $stripes"
3120         fi
3121
3122         size=$(stat $name | awk '/Size:/ { print $2 }')
3123         [ $size -eq $((4096 * $bcount)) ] ||
3124                 error "(6.4) expect the size $((4096 * $bcount)), but got $size"
3125
3126         cat $name > /dev/null && error "(6.5) normal read $name should fail"
3127
3128         local failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3129                          bs=4096 2>&1 | grep "Input/output error" | wc -l)
3130
3131         # stripe0 is dummy
3132         [ $failures -eq 256 ] ||
3133                 error "(6.6) expect 256 IO failures, but get $failures"
3134
3135         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3136         [ $size -eq $((4096 * $bcount)) ] ||
3137                 error "(6.7) expect the size $((4096 * $bcount)), but got $size"
3138
3139         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 &&
3140                 error "(6.8) write to the LOV EA hole should fail"
3141
3142         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 seek=300 ||
3143                 error "(6.9) write to normal stripe should NOT fail"
3144
3145         echo "foo" >> $name && error "(6.10) append write $name should fail"
3146
3147         chown $RUNAS_ID:$RUNAS_GID $name || error "(6.11) cannot chown on $name"
3148
3149         touch $name || error "(6.12) cannot touch $name"
3150
3151         rm -f $name || error "(6.13) cannot unlink $name"
3152
3153         #
3154         # ${fid2}-R-0 it contains the old f2's stripe0 (and stripe2 if OSTs > 2)
3155         #
3156         name="$MOUNT/.lustre/lost+found/MDT0000/${fid2}-R-0"
3157         if [ $OSTCOUNT -gt 2 ]; then
3158                 echo "Check $name, it contains the old f2's stripe0 and stripe2"
3159         else
3160                 echo "Check $name, it contains the old f2's stripe0"
3161         fi
3162
3163         $LFS getstripe -v $name || error "(7.1) cannot getstripe on $name"
3164
3165         pattern=$($LFS getstripe -L $name)
3166         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3167                 error "(7.2) expect pattern flag hole, but got $pattern"
3168
3169         stripes=$($LFS getstripe -c $name)
3170         size=$(stat $name | awk '/Size:/ { print $2 }')
3171         if [ $OSTCOUNT -gt 2 ]; then
3172                 [ $stripes -eq 3 ] ||
3173                 error "(7.3.1) expect the stripe count is 3, but got $stripes"
3174
3175                 [ $size -eq $((4096 * $bcount)) ] ||
3176                 error "(7.4.1) expect size $((4096 * $bcount)), but got $size"
3177
3178                 cat $name > /dev/null &&
3179                         error "(7.5.1) normal read $name should fail"
3180
3181                 failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3182                            bs=4096 2>&1 | grep "Input/output error" | wc -l)
3183                 # stripe1 is dummy
3184                 [ $failures -eq 256 ] ||
3185                         error "(7.6) expect 256 IO failures, but get $failures"
3186
3187                 size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3188                 [ $size -eq $((4096 * $bcount)) ] ||
3189                 error "(7.7) expect the size $((4096 * $bcount)), but got $size"
3190
3191                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
3192                 seek=300 && error "(7.8.0) write to the LOV EA hole should fail"
3193
3194                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 ||
3195                 error "(7.8.1) write to normal stripe should NOT fail"
3196
3197                 echo "foo" >> $name &&
3198                         error "(7.8.3) append write $name should fail"
3199
3200                 chown $RUNAS_ID:$RUNAS_GID $name ||
3201                         error "(7.9.1) cannot chown on $name"
3202
3203                 touch $name || error "(7.10.1) cannot touch $name"
3204         else
3205                 [ $stripes -eq 2 ] ||
3206                 error "(7.3.2) expect the stripe count is 2, but got $stripes"
3207
3208                 # stripe1 is dummy
3209                 [ $size -eq $((4096 * (256 + 0))) ] ||
3210                 error "(7.4.2) expect the size $((4096 * 256)), but got $size"
3211
3212                 cat $name > /dev/null &&
3213                         error "(7.5.2) normal read $name should fail"
3214
3215                 failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3216                            bs=4096 2>&1 | grep "Input/output error" | wc -l)
3217                 [ $failures -eq 256 ] ||
3218                 error "(7.6.2) expect 256 IO failures, but get $failures"
3219
3220                 bcount=$((256 * 2))
3221                 size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3222                 [ $size -eq $((4096 * $bcount)) ] ||
3223                 error "(7.7.2) expect the size $((4096 * $bcount)), got $size"
3224
3225                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
3226                 seek=256 && error "(7.8.2) write to the LOV EA hole should fail"
3227
3228                 chown $RUNAS_ID:$RUNAS_GID $name ||
3229                         error "(7.9.2) cannot chown on $name"
3230
3231                 touch $name || error "(7.10.2) cannot touch $name"
3232         fi
3233
3234         rm -f $name || error "(7.11) cannot unlink $name"
3235
3236         [ $OSTCOUNT -le 2 ] && return
3237
3238         #
3239         # ${fid3}-R-0 should contains the old f3's stripe0 and stripe1
3240         #
3241         name="$MOUNT/.lustre/lost+found/MDT0000/${fid3}-R-0"
3242         echo "Check $name, which contains the old f3's stripe0 and stripe1"
3243
3244         $LFS getstripe -v $name || error "(8.1) cannot getstripe on $name"
3245
3246         pattern=$($LFS getstripe -L $name)
3247         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3248                 error "(8.2) expect pattern flag hole, but got $pattern"
3249
3250         stripes=$($LFS getstripe -c $name)
3251         [ $stripes -eq 3 ] ||
3252                 error "(8.3) expect the stripe count is 3, but got $stripes"
3253
3254         size=$(stat $name | awk '/Size:/ { print $2 }')
3255         # stripe2 is lost
3256         [ $size -eq $((4096 * (256 + 256 + 0))) ] ||
3257                 error "(8.4) expect the size $((4096 * 512)), but got $size"
3258
3259         cat $name > /dev/null &&
3260                 error "(8.5) normal read $name should fail"
3261
3262         failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3263                    bs=4096 2>&1 | grep "Input/output error" | wc -l)
3264         # stripe2 is dummy
3265         [ $failures -eq 256 ] ||
3266                 error "(8.6) expect 256 IO failures, but get $failures"
3267
3268         bcount=$((256 * 3))
3269         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3270         [ $size -eq $((4096 * $bcount)) ] ||
3271                 error "(8.7) expect the size $((4096 * $bcount)), but got $size"
3272
3273         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
3274                 seek=512 && error "(8.8) write to the LOV EA hole should fail"
3275
3276         chown $RUNAS_ID:$RUNAS_GID $name ||
3277                 error "(8.9) cannot chown on $name"
3278
3279         touch $name || error "(8.10) cannot touch $name"
3280
3281         rm -f $name || error "(8.11) cannot unlink $name"
3282 }
3283 run_test 20a "Handle the orphan with dummy LOV EA slot properly"
3284
3285 test_20b() {
3286         [ $OSTCOUNT -lt 2 ] &&
3287                 skip "The test needs at least 2 OSTs" && return
3288
3289         echo "#####"
3290         echo "The target MDT-object and some of its OST-object are lost."
3291         echo "The LFSCK should find out the left OST-objects and re-create"
3292         echo "the MDT-object under the direcotry .lustre/lost+found/MDTxxxx/"
3293         echo "with the partial OST-objects (LOV EA hole)."
3294
3295         echo "New client can access the file with LOV EA hole via normal"
3296         echo "system tools or commands without crash the system - PFL case."
3297         echo "#####"
3298
3299         check_mount_and_prep
3300
3301         $LFS setstripe -E 2M -S 1M -c 2 -E -1 -S 1M -c 2 $DIR/$tdir/f0 ||
3302                 error "(0) Fail to create PFL file $DIR/$tdir/f0"
3303         $LFS setstripe -E 2M -S 1M -c 2 -E -1 -S 1M -c 2 $DIR/$tdir/f1 ||
3304                 error "(1) Fail to create PFL file $DIR/$tdir/f1"
3305         $LFS setstripe -E 2M -S 1M -c 2 -E -1 -S 1M -c 2 $DIR/$tdir/f2 ||
3306                 error "(2) Fail to create PFL file $DIR/$tdir/f2"
3307
3308         local bcount=$((256 * 3 + 1))
3309
3310         dd if=/dev/zero of=$DIR/$tdir/f0 bs=4096 count=$bcount
3311         dd if=/dev/zero of=$DIR/$tdir/f1 bs=4096 count=$bcount
3312         dd if=/dev/zero of=$DIR/$tdir/f2 bs=4096 count=$bcount
3313
3314         local fid0=$($LFS path2fid $DIR/$tdir/f0)
3315         local fid1=$($LFS path2fid $DIR/$tdir/f1)
3316         local fid2=$($LFS path2fid $DIR/$tdir/f2)
3317
3318         echo ${fid0}
3319         $LFS getstripe $DIR/$tdir/f0
3320         echo ${fid1}
3321         $LFS getstripe $DIR/$tdir/f1
3322         echo ${fid2}
3323         $LFS getstripe $DIR/$tdir/f2
3324
3325         cancel_lru_locks mdc
3326         cancel_lru_locks osc
3327
3328         echo "Inject failure..."
3329         echo "To simulate f0 lost MDT-object"
3330         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
3331         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1616
3332         rm -f $DIR/$tdir/f0
3333
3334         echo "To simulate the case of f1 lost MDT-object and "
3335         echo "the first OST-object in each PFL component"
3336         #define OBD_FAIL_LFSCK_LOST_SPEOBJ      0x161a
3337         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161a
3338         rm -f $DIR/$tdir/f1
3339
3340         echo "To simulate the case of f2 lost MDT-object and "
3341         echo "the second OST-object in each PFL component"
3342         do_facet $SINGLEMDS $LCTL set_param fail_val=1
3343         rm -f $DIR/$tdir/f2
3344
3345         sync
3346         sleep 2
3347         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
3348
3349         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
3350         $START_LAYOUT -r -o || error "(3) Fail to start LFSCK for layout!"
3351
3352         for k in $(seq $MDSCOUNT); do
3353                 # The LFSCK status query internal is 30 seconds. For the case
3354                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
3355                 # time to guarantee the status sync up.
3356                 wait_update_facet mds${k} "$LCTL get_param -n \
3357                         mdd.$(facet_svc mds${k}).lfsck_layout |
3358                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
3359                         error "(4) MDS${k} is not the expected 'completed'"
3360         done
3361
3362         for k in $(seq $OSTCOUNT); do
3363                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
3364                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
3365                                 awk '/^status/ { print $2 }')
3366                 [ "$cur_status" == "completed" ] ||
3367                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
3368         done
3369
3370         local repaired=$(do_facet mds1 $LCTL get_param -n \
3371                          mdd.$(facet_svc mds1).lfsck_layout |
3372                          awk '/^repaired_orphan/ { print $2 }')
3373         [ $repaired -eq 8 ] ||
3374                 error "(6) Expect 8 fixed on mds1, but got: $repaired"
3375
3376         #
3377         # ${fid0}-R-0 is the old f0
3378         #
3379         local name="$MOUNT/.lustre/lost+found/MDT0000/${fid0}-R-0"
3380         echo "Check $name, which is the old f0"
3381
3382         $LFS getstripe -v $name || error "(7.1) cannot getstripe on $name"
3383
3384         local pattern=$($LFS getstripe -L -I 1 $name)
3385         [[ "$pattern" = "$PATTERN_WITHOUT_HOLE" ]] ||
3386                 error "(7.2.1) NOT expect pattern flag hole, but got $pattern"
3387
3388         pattern=$($LFS getstripe -L -I 2 $name)
3389         [[ "$pattern" = "$PATTERN_WITHOUT_HOLE" ]] ||
3390                 error "(7.2.2) NOT expect pattern flag hole, but got $pattern"
3391
3392         local stripes=$($LFS getstripe -c -I 1 $name)
3393         [ $stripes -eq 2 ] ||
3394                 error "(7.3.1) expect 2 stripes, but got $stripes"
3395
3396         stripes=$($LFS getstripe -c -I 2 $name)
3397         [ $stripes -eq 2 ] ||
3398                 error "(7.3.2) expect 2 stripes, but got $stripes"
3399
3400         local e_start=$($LFS getstripe -I 1 $name |
3401                         awk '/lcme_extent.e_start:/ { print $2 }')
3402         [ $e_start -eq 0 ] ||
3403                 error "(7.4.1) expect the COMP1 start at 0, got $e_start"
3404
3405         local e_end=$($LFS getstripe -I 1 $name |
3406                       awk '/lcme_extent.e_end:/ { print $2 }')
3407         [ $e_end -eq 2097152 ] ||
3408                 error "(7.4.2) expect the COMP1 end at 2097152, got $e_end"
3409
3410         e_start=$($LFS getstripe -I 2 $name |
3411                   awk '/lcme_extent.e_start:/ { print $2 }')
3412         [ $e_start -eq 2097152 ] ||
3413                 error "(7.5.1) expect the COMP2 start at 2097152, got $e_start"
3414
3415         e_end=$($LFS getstripe -I 2 $name |
3416                 awk '/lcme_extent.e_end:/ { print $2 }')
3417         [ "$e_end" = "EOF" ] ||
3418                 error "(7.5.2) expect the COMP2 end at (EOF), got $e_end"
3419
3420         local size=$(stat $name | awk '/Size:/ { print $2 }')
3421         [ $size -eq $((4096 * $bcount)) ] ||
3422                 error "(7.6) expect the size $((4096 * $bcount)), but got $size"
3423
3424         cat $name > /dev/null || error "(7.7) cannot read $name"
3425
3426         echo "dummy" >> $name || error "(7.8) cannot write $name"
3427
3428         chown $RUNAS_ID:$RUNAS_GID $name || error "(7.9) cannot chown on $name"
3429
3430         touch $name || error "(7.10) cannot touch $name"
3431
3432         rm -f $name || error "(7.11) cannot unlink $name"
3433
3434         #
3435         # ${fid1}-R-0 contains the old f1's second stripe in each COMP
3436         #
3437         name="$MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
3438         echo "Check $name, it contains f1's second OST-object in each COMP"
3439
3440         $LFS getstripe -v $name || error "(8.1) cannot getstripe on $name"
3441
3442         pattern=$($LFS getstripe -L -I 1 $name)
3443         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3444                 error "(8.2.1) expect pattern flag hole, but got $pattern"
3445
3446         pattern=$($LFS getstripe -L -I 2 $name)
3447         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3448                 error "(8.2.2) expect pattern flag hole, but got $pattern"
3449
3450         stripes=$($LFS getstripe -c -I 1 $name)
3451         [ $stripes -eq 2 ] ||
3452                 error "(8.3.2) expect 2 stripes, but got $stripes"
3453
3454         stripes=$($LFS getstripe -c -I 2 $name)
3455         [ $stripes -eq 2 ] ||
3456                 error "(8.3.2) expect 2 stripes, but got $stripes"
3457
3458         e_start=$($LFS getstripe -I 1 $name |
3459                   awk '/lcme_extent.e_start:/ { print $2 }')
3460         [ $e_start -eq 0 ] ||
3461                 error "(8.4.1) expect the COMP1 start at 0, got $e_start"
3462
3463         e_end=$($LFS getstripe -I 1 $name |
3464                 awk '/lcme_extent.e_end:/ { print $2 }')
3465         [ $e_end -eq 2097152 ] ||
3466                 error "(8.4.2) expect the COMP1 end at 2097152, got $e_end"
3467
3468         e_start=$($LFS getstripe -I 2 $name |
3469                   awk '/lcme_extent.e_start:/ { print $2 }')
3470         [ $e_start -eq 2097152 ] ||
3471                 error "(8.5.1) expect the COMP2 start at 2097152, got $e_start"
3472
3473         e_end=$($LFS getstripe -I 2 $name |
3474                 awk '/lcme_extent.e_end:/ { print $2 }')
3475         [ "$e_end" = "EOF" ] ||
3476                 error "(8.5.2) expect the COMP2 end at (EOF), got $e_end"
3477
3478         size=$(stat $name | awk '/Size:/ { print $2 }')
3479         [ $size -eq $((4096 * $bcount)) ] ||
3480                 error "(8.6) expect the size $((4096 * $bcount)), but got $size"
3481
3482         cat $name > /dev/null && error "(8.7) normal read $name should fail"
3483
3484         local failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3485                          bs=4096 2>&1 | grep "Input/output error" | wc -l)
3486
3487         # The first stripe in each COMP was lost
3488         [ $failures -eq 512 ] ||
3489                 error "(8.8) expect 512 IO failures, but get $failures"
3490
3491         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3492         [ $size -eq $((4096 * $bcount)) ] ||
3493                 error "(8.9) expect the size $((4096 * $bcount)), but got $size"
3494
3495         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 &&
3496                 error "(8.10) write to the LOV EA hole should fail"
3497
3498         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 seek=300 ||
3499                 error "(8.11) write to normal stripe should NOT fail"
3500
3501         echo "foo" >> $name && error "(8.12) append write $name should fail"
3502
3503         chown $RUNAS_ID:$RUNAS_GID $name || error "(8.13) cannot chown on $name"
3504
3505         touch $name || error "(8.14) cannot touch $name"
3506
3507         rm -f $name || error "(8.15) cannot unlink $name"
3508
3509         #
3510         # ${fid2}-R-0 contains the old f2's first stripe in each COMP
3511         #
3512         name="$MOUNT/.lustre/lost+found/MDT0000/${fid2}-R-0"
3513         echo "Check $name, it contains f2's first stripe in each COMP"
3514
3515         $LFS getstripe -v $name || error "(9.1) cannot getstripe on $name"
3516
3517         pattern=$($LFS getstripe -L -I 1 $name)
3518         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3519                 error "(9.2.1) expect pattern flag hole, but got $pattern"
3520
3521         pattern=$($LFS getstripe -L -I 2 $name)
3522         [[ "$pattern" = "$PATTERN_WITH_HOLE" ]] ||
3523                 error "(9.2.2) expect pattern flag hole, but got $pattern"
3524
3525         stripes=$($LFS getstripe -c -I 1 $name)
3526         [ $stripes -eq 2 ] ||
3527                 error "(9.3.2) expect 2 stripes, but got $stripes"
3528
3529         stripes=$($LFS getstripe -c -I 2 $name)
3530         [ $stripes -eq 2 ] ||
3531                 error "(9.3.2) expect 2 stripes, but got $stripes"
3532
3533         e_start=$($LFS getstripe -I 1 $name |
3534                   awk '/lcme_extent.e_start:/ { print $2 }')
3535         [ $e_start -eq 0 ] ||
3536                 error "(9.4.1) expect the COMP1 start at 0, got $e_start"
3537
3538         e_end=$($LFS getstripe -I 1 $name |
3539                 awk '/lcme_extent.e_end:/ { print $2 }')
3540         [ $e_end -eq 2097152 ] ||
3541                 error "(9.4.2) expect the COMP1 end at 2097152, got $e_end"
3542
3543         e_start=$($LFS getstripe -I 2 $name |
3544                   awk '/lcme_extent.e_start:/ { print $2 }')
3545         [ $e_start -eq 2097152 ] ||
3546                 error "(9.5.1) expect the COMP2 start at 2097152, got $e_start"
3547
3548         e_end=$($LFS getstripe -I 2 $name |
3549                 awk '/lcme_extent.e_end:/ { print $2 }')
3550         [ "$e_end" = "EOF" ] ||
3551                 error "(9.5.2) expect the COMP2 end at (EOF), got $e_end"
3552
3553         size=$(stat $name | awk '/Size:/ { print $2 }')
3554         # The second stripe in COMP was lost, so we do not know there
3555         # have ever been some data before. 'stat' will regard it as
3556         # no data on the lost stripe.
3557         bcount=$((256 * 3))
3558         [ $size -eq $((4096 * $bcount)) ] ||
3559                 error "(9.6) expect size $((4096 * $bcount)), but got $size"
3560
3561         cat $name > /dev/null &&
3562                 error "(9.7) normal read $name should fail"
3563
3564         failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
3565                    bs=4096 2>&1 | grep "Input/output error" | wc -l)
3566         [ $failures -eq 512 ] ||
3567                 error "(9.8) expect 256 IO failures, but get $failures"
3568
3569         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
3570         # The second stripe in COMP was lost, so we do not know there
3571         # have ever been some data before. Since 'dd' skip failure,
3572         # it will regard the lost stripe contains data.
3573         bcount=$((256 * 4))
3574         [ $size -eq $((4096 * $bcount)) ] ||
3575                 error "(9.9) expect the size $((4096 * $bcount)), but got $size"
3576
3577         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
3578                 seek=300 && error "(9.10) write to the LOV EA hole should fail"
3579
3580         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 ||
3581                 error "(9.11) write to normal stripe should NOT fail"
3582
3583         echo "foo" >> $name &&
3584                 error "(9.12) append write $name should fail"
3585
3586         chown $RUNAS_ID:$RUNAS_GID $name ||
3587                 error "(9.13) cannot chown on $name"
3588
3589         touch $name || error "(9.14) cannot touch $name"
3590
3591         rm -f $name || error "(7.15) cannot unlink $name"
3592 }
3593 run_test 20b "Handle the orphan with dummy LOV EA slot properly - PFL case"
3594
3595 test_21() {
3596         [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.5.59) ]] &&
3597                 skip "ignore the test if MDS is older than 2.5.59" && return
3598
3599         check_mount_and_prep
3600         createmany -o $DIR/$tdir/f 100 || error "(0) Fail to create 100 files"
3601
3602         echo "Start all LFSCK components by default (-s 1)"
3603         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -s 1 -r ||
3604                 error "Fail to start LFSCK"
3605
3606         echo "namespace LFSCK should be in 'scanning-phase1' status"
3607         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
3608         [ "$STATUS" == "scanning-phase1" ] ||
3609                 error "Expect namespace 'scanning-phase1', but got '$STATUS'"
3610
3611         echo "layout LFSCK should be in 'scanning-phase1' status"
3612         STATUS=$($SHOW_LAYOUT | awk '/^status/ { print $2 }')
3613         [ "$STATUS" == "scanning-phase1" ] ||
3614                 error "Expect layout 'scanning-phase1', but got '$STATUS'"
3615
3616         echo "Stop all LFSCK components by default"
3617         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 ||
3618                 error "Fail to stop LFSCK"
3619 }
3620 run_test 21 "run all LFSCK components by default"
3621
3622 test_22a() {
3623         [ $MDSCOUNT -lt 2 ] &&
3624                 skip "We need at least 2 MDSes for this test" && return
3625
3626         echo "#####"
3627         echo "The parent_A references the child directory via some name entry,"
3628         echo "but the child directory back references another parent_B via its"
3629         echo "".." name entry. The parent_B does not exist. Then the namespace"
3630         echo "LFSCK will repair the child directory's ".." name entry."
3631         echo "#####"
3632
3633         check_mount_and_prep
3634
3635         $LFS mkdir -i 1 $DIR/$tdir/guard || error "(1) Fail to mkdir on MDT1"
3636         $LFS mkdir -i 1 $DIR/$tdir/foo || error "(2) Fail to mkdir on MDT1"
3637
3638         echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
3639         echo "The dummy's dotdot name entry references the guard."
3640         #define OBD_FAIL_LFSCK_BAD_PARENT       0x161e
3641         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161e
3642         $LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
3643                 error "(3) Fail to mkdir on MDT0"
3644         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3645
3646         rmdir $DIR/$tdir/guard || error "(4) Fail to rmdir $DIR/$tdir/guard"
3647
3648         echo "Trigger namespace LFSCK to repair unmatched pairs"
3649         $START_NAMESPACE -A -r ||
3650                 error "(5) Fail to start LFSCK for namespace"
3651
3652         wait_all_targets_blocked namespace completed 6
3653
3654         local repaired=$($SHOW_NAMESPACE |
3655                          awk '/^unmatched_pairs_repaired/ { print $2 }')
3656         [ $repaired -eq 1 ] ||
3657                 error "(7) Fail to repair unmatched pairs: $repaired"
3658
3659         echo "'ls' should success after namespace LFSCK repairing"
3660         ls -ail $DIR/$tdir/foo/dummy > /dev/null ||
3661                 error "(8) ls should success."
3662 }
3663 run_test 22a "LFSCK can repair unmatched pairs (1)"
3664
3665 test_22b() {
3666         [ $MDSCOUNT -lt 2 ] &&
3667                 skip "We need at least 2 MDSes for this test" && return
3668
3669         echo "#####"
3670         echo "The parent_A references the child directory via the name entry_B,"
3671         echo "but the child directory back references another parent_C via its"
3672         echo "".." name entry. The parent_C exists, but there is no the name"
3673         echo "entry_B under the parent_C. Then the namespace LFSCK will repair"
3674         echo "the child directory's ".." name entry and its linkEA."
3675         echo "#####"
3676
3677         check_mount_and_prep
3678
3679         $LFS mkdir -i 1 $DIR/$tdir/guard || error "(1) Fail to mkdir on MDT1"
3680         $LFS mkdir -i 1 $DIR/$tdir/foo || error "(2) Fail to mkdir on MDT1"
3681
3682         echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
3683         echo "and bad linkEA. The dummy's dotdot name entry references the"
3684         echo "guard. The dummy's linkEA references n non-exist name entry."
3685         #define OBD_FAIL_LFSCK_BAD_PARENT       0x161e
3686         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161e
3687         $LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
3688                 error "(3) Fail to mkdir on MDT0"
3689         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3690
3691         local dummyfid=$($LFS path2fid $DIR/$tdir/foo/dummy)
3692         echo "fid2path should NOT work on the dummy's FID $dummyfid"
3693         local dummyname=$($LFS fid2path $DIR $dummyfid)
3694         [ "$dummyname" != "$DIR/$tdir/foo/dummy" ] ||
3695                 error "(4) fid2path works unexpectedly."
3696
3697         echo "Trigger namespace LFSCK to repair unmatched pairs"
3698         $START_NAMESPACE -A -r ||
3699                 error "(5) Fail to start LFSCK for namespace"
3700
3701         wait_all_targets_blocked namespace completed 6
3702
3703         local repaired=$($SHOW_NAMESPACE |
3704                          awk '/^unmatched_pairs_repaired/ { print $2 }')
3705         [ $repaired -eq 1 ] ||
3706                 error "(7) Fail to repair unmatched pairs: $repaired"
3707
3708         echo "fid2path should work on the dummy's FID $dummyfid after LFSCK"
3709         local dummyname=$($LFS fid2path $DIR $dummyfid)
3710         [ "$dummyname" == "$DIR/$tdir/foo/dummy" ] ||
3711                 error "(8) fid2path does not work"
3712 }
3713 run_test 22b "LFSCK can repair unmatched pairs (2)"
3714
3715 test_23a() {
3716         [ $MDSCOUNT -lt 2 ] &&
3717                 skip "We need at least 2 MDSes for this test" && return
3718
3719         echo "#####"
3720         echo "The name entry is there, but the MDT-object for such name "
3721         echo "entry does not exist. The namespace LFSCK should find out "
3722         echo "and repair the inconsistency as required."
3723         echo "#####"
3724
3725         check_mount_and_prep
3726
3727         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
3728         $LFS mkdir -i 1 $DIR/$tdir/d0/d1 || error "(2) Fail to mkdir d1 on MDT1"
3729
3730         echo "Inject failure stub on MDT1 to simulate dangling name entry"
3731         #define OBD_FAIL_LFSCK_DANGLING2        0x1620
3732         do_facet mds2 $LCTL set_param fail_loc=0x1620
3733         rmdir $DIR/$tdir/d0/d1 || error "(3) Fail to rmdir d1"
3734         do_facet mds2 $LCTL set_param fail_loc=0
3735
3736         echo "'ls' should fail because of dangling name entry"
3737         ls -ail $DIR/$tdir/d0/d1 > /dev/null 2>&1 && error "(4) ls should fail."
3738
3739         echo "Trigger namespace LFSCK to find out dangling name entry"
3740         $START_NAMESPACE -A -r ||
3741                 error "(5) Fail to start LFSCK for namespace"
3742
3743         wait_all_targets_blocked namespace completed 6
3744
3745         local repaired=$($SHOW_NAMESPACE |
3746                          awk '/^dangling_repaired/ { print $2 }')
3747         [ $repaired -eq 1 ] ||
3748                 error "(7) Fail to repair dangling name entry: $repaired"
3749
3750         echo "'ls' should fail because not re-create MDT-object by default"
3751         ls -ail $DIR/$tdir/d0/d1 > /dev/null 2>&1 && error "(8) ls should fail."
3752
3753         echo "Trigger namespace LFSCK again to repair dangling name entry"
3754         $START_NAMESPACE -A -r -C ||
3755                 error "(9) Fail to start LFSCK for namespace"
3756
3757         wait_all_targets_blocked namespace completed 10
3758
3759         repaired=$($SHOW_NAMESPACE |
3760                    awk '/^dangling_repaired/ { print $2 }')
3761         [ $repaired -eq 1 ] ||
3762                 error "(11) Fail to repair dangling name entry: $repaired"
3763
3764         echo "'ls' should success after namespace LFSCK repairing"
3765         ls -ail $DIR/$tdir/d0/d1 > /dev/null || error "(12) ls should success."
3766 }
3767 run_test 23a "LFSCK can repair dangling name entry (1)"
3768
3769 test_23b() {
3770         echo "#####"
3771         echo "The objectA has multiple hard links, one of them corresponding"
3772         echo "to the name entry_B. But there is something wrong for the name"
3773         echo "entry_B and cause entry_B to references non-exist object_C."
3774         echo "In the first-stage scanning, the LFSCK will think the entry_B"
3775         echo "as dangling, and re-create the lost object_C. When the LFSCK"
3776         echo "comes to the second-stage scanning, it will find that the"
3777         echo "former re-creating object_C is not proper, and will try to"
3778         echo "replace the object_C with the real object_A."
3779         echo "#####"
3780
3781         check_mount_and_prep
3782
3783         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
3784         $LFS path2fid $DIR/$tdir/d0
3785
3786         createmany -o $DIR/$tdir/d0/t 10 || error "(1.5) Fail to creatmany"
3787
3788         echo "dummy" > $DIR/$tdir/d0/f0 || error "(2) Fail to touch on MDT0"
3789         $LFS path2fid $DIR/$tdir/d0/f0
3790
3791         echo "dead" > $DIR/$tdir/d0/f1 || error "(3) Fail to touch on MDT0"
3792         $LFS path2fid $DIR/$tdir/d0/f1
3793
3794         local SEQ0=$($LFS path2fid $DIR/$tdir/d0/f0 | awk -F':' '{print $1}')
3795         local SEQ1=$($LFS path2fid $DIR/$tdir/d0/f1 | awk -F':' '{print $1}')
3796
3797         if [ "$SEQ0" != "$SEQ1" ]; then
3798                 # To guarantee that the f0 and f1 are in the same FID seq
3799                 rm -f $DIR/$tdir/d0/f0 ||
3800                         error "(3.1) Fail to unlink $DIR/$tdir/d0/f0"
3801                 echo "dummy" > $DIR/$tdir/d0/f0 ||
3802                         error "(3.2) Fail to touch on MDT0"
3803                 $LFS path2fid $DIR/$tdir/d0/f0
3804         fi
3805
3806         local OID=$($LFS path2fid $DIR/$tdir/d0/f1 | awk -F':' '{print $2}')
3807         OID=$(printf %d $OID)
3808
3809         echo "Inject failure stub on MDT0 to simulate dangling name entry"
3810         #define OBD_FAIL_LFSCK_DANGLING3        0x1621
3811         do_facet $SINGLEMDS $LCTL set_param fail_val=$OID fail_loc=0x1621
3812         ln $DIR/$tdir/d0/f0 $DIR/$tdir/d0/foo || error "(4) Fail to hard link"
3813         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
3814
3815         # If there is creation after the dangling injection, it may re-use
3816         # the just released local object (inode) that is referenced by the
3817         # dangling name entry. It will fail the dangling injection.
3818         # So before deleting the target object for the dangling name entry,
3819         # remove some other objects to avoid the target object being reused
3820         # by some potential creations. LU-7429
3821         unlinkmany $DIR/$tdir/d0/t 10 || error "(5.0) Fail to unlinkmany"
3822
3823         rm -f $DIR/$tdir/d0/f1 || error "(5) Fail to unlink $DIR/$tdir/d0/f1"
3824
3825         echo "'ls' should fail because of dangling name entry"
3826         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
3827                 error "(6) ls should fail."
3828
3829         echo "Trigger namespace LFSCK to find out dangling name entry"
3830         $START_NAMESPACE -r -C ||
3831                 error "(7) Fail to start LFSCK for namespace"
3832
3833         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3834                 mdd.${MDT_DEV}.lfsck_namespace |
3835                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3836                 $SHOW_NAMESPACE
3837                 error "(8) unexpected status"
3838         }
3839
3840         local repaired=$($SHOW_NAMESPACE |
3841                          awk '/^dangling_repaired/ { print $2 }')
3842         [ $repaired -eq 1 ] ||
3843                 error "(9) Fail to repair dangling name entry: $repaired"
3844
3845         repaired=$($SHOW_NAMESPACE |
3846                    awk '/^multiple_linked_repaired/ { print $2 }')
3847         [ $repaired -eq 1 ] ||
3848                 error "(10) Fail to drop the former created object: $repaired"
3849
3850         local data=$(cat $DIR/$tdir/d0/foo)
3851         [ "$data" == "dummy" ] ||
3852                 error "(11) The $DIR/$tdir/d0/foo is not recovered: $data"
3853 }
3854 run_test 23b "LFSCK can repair dangling name entry (2)"
3855
3856 test_23c() {
3857         echo "#####"
3858         echo "The objectA has multiple hard links, one of them corresponding"
3859         echo "to the name entry_B. But there is something wrong for the name"
3860         echo "entry_B and cause entry_B to references non-exist object_C."
3861         echo "In the first-stage scanning, the LFSCK will think the entry_B"
3862         echo "as dangling, and re-create the lost object_C. And then others"
3863         echo "modified the re-created object_C. When the LFSCK comes to the"
3864         echo "second-stage scanning, it will find that the former re-creating"
3865         echo "object_C maybe wrong and try to replace the object_C with the"
3866         echo "real object_A. But because object_C has been modified, so the"
3867         echo "LFSCK cannot replace it."
3868         echo "#####"
3869
3870         start_full_debug_logging
3871
3872         check_mount_and_prep
3873
3874         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
3875         $LFS path2fid $DIR/$tdir/d0
3876
3877         createmany -o $DIR/$tdir/d0/t 10 || error "(1.5) Fail to creatmany"
3878
3879         echo "dummy" > $DIR/$tdir/d0/f0 || error "(2) Fail to touch on MDT0"
3880         $LFS path2fid $DIR/$tdir/d0/f0
3881
3882         echo "dead" > $DIR/$tdir/d0/f1 || error "(3) Fail to touch on MDT0"
3883         $LFS path2fid $DIR/$tdir/d0/f1
3884
3885         local SEQ0=$($LFS path2fid $DIR/$tdir/d0/f0 | awk -F':' '{print $1}')
3886         local SEQ1=$($LFS path2fid $DIR/$tdir/d0/f1 | awk -F':' '{print $1}')
3887
3888         if [ "$SEQ0" != "$SEQ1" ]; then
3889                 # To guarantee that the f0 and f1 are in the same FID seq
3890                 rm -f $DIR/$tdir/d0/f0 ||
3891                         error "(3.1) Fail to unlink $DIR/$tdir/d0/f0"
3892                 echo "dummy" > $DIR/$tdir/d0/f0 ||
3893                         error "(3.2) Fail to touch on MDT0"
3894                 $LFS path2fid $DIR/$tdir/d0/f0
3895         fi
3896
3897         local OID=$($LFS path2fid $DIR/$tdir/d0/f1 | awk -F':' '{print $2}')
3898         OID=$(printf %d $OID)
3899
3900         echo "Inject failure stub on MDT0 to simulate dangling name entry"
3901         #define OBD_FAIL_LFSCK_DANGLING3        0x1621
3902         do_facet $SINGLEMDS $LCTL set_param fail_val=$OID fail_loc=0x1621
3903         ln $DIR/$tdir/d0/f0 $DIR/$tdir/d0/foo || error "(4) Fail to hard link"
3904         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
3905
3906         # If there is creation after the dangling injection, it may re-use
3907         # the just released local object (inode) that is referenced by the
3908         # dangling name entry. It will fail the dangling injection.
3909         # So before deleting the target object for the dangling name entry,
3910         # remove some other objects to avoid the target object being reused
3911         # by some potential creations. LU-7429
3912         unlinkmany $DIR/$tdir/d0/t 10 || error "(5.0) Fail to unlinkmany"
3913
3914         rm -f $DIR/$tdir/d0/f1 || error "(5) Fail to unlink $DIR/$tdir/d0/f1"
3915
3916         echo "'ls' should fail because of dangling name entry"
3917         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
3918                 error "(6) ls should fail."
3919
3920         #define OBD_FAIL_LFSCK_DELAY3           0x1602
3921         do_facet $SINGLEMDS $LCTL set_param fail_val=10 fail_loc=0x1602
3922
3923         echo "Trigger namespace LFSCK to find out dangling name entry"
3924         $START_NAMESPACE -r -C ||
3925                 error "(7) Fail to start LFSCK for namespace"
3926
3927         wait_update_facet client "stat $DIR/$tdir/d0/foo |
3928                 awk '/Size/ { print \\\$2 }'" "0" $LTIME || {
3929                 stat $DIR/$tdir/d0/foo
3930                 $SHOW_NAMESPACE
3931                 error "(8) unexpected size"
3932         }
3933
3934         echo "data" >> $DIR/$tdir/d0/foo || error "(9) Fail to write"
3935         cancel_lru_locks osc
3936
3937         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
3938         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3939                 mdd.${MDT_DEV}.lfsck_namespace |
3940                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3941                 $SHOW_NAMESPACE
3942                 error "(10) unexpected status"
3943         }
3944
3945         stop_full_debug_logging
3946
3947         local repaired=$($SHOW_NAMESPACE |
3948                          awk '/^dangling_repaired/ { print $2 }')
3949         [ $repaired -eq 1 ] ||
3950                 error "(11) Fail to repair dangling name entry: $repaired"
3951
3952         local data=$(cat $DIR/$tdir/d0/foo)
3953         [ "$data" != "dummy" ] ||
3954                 error "(12) The $DIR/$tdir/d0/foo should not be recovered"
3955 }
3956 run_test 23c "LFSCK can repair dangling name entry (3)"
3957
3958 test_24() {
3959         [ $MDSCOUNT -lt 2 ] &&
3960                 skip "We need at least 2 MDSes for this test" && return
3961
3962         echo "#####"
3963         echo "Two MDT-objects back reference the same name entry via their"
3964         echo "each own linkEA entry, but the name entry only references one"
3965         echo "MDT-object. The namespace LFSCK will remove the linkEA entry"
3966         echo "for the MDT-object that is not recognized. If such MDT-object"
3967         echo "has no other linkEA entry after the removing, then the LFSCK"
3968         echo "will add it as orphan under the .lustre/lost+found/MDTxxxx/."
3969         echo "#####"
3970
3971         check_mount_and_prep
3972
3973         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3974
3975         mkdir $DIR/$tdir/d0/guard || error "(1) Fail to mkdir guard"
3976         $LFS path2fid $DIR/$tdir/d0/guard
3977
3978         mkdir $DIR/$tdir/d0/dummy || error "(2) Fail to mkdir dummy"
3979         $LFS path2fid $DIR/$tdir/d0/dummy
3980
3981         local pfid
3982         if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
3983                 pfid=$($LFS path2fid $DIR/$tdir/d0/guard)
3984         else
3985                 pfid=$($LFS path2fid $DIR/$tdir/d0/dummy)
3986         fi
3987
3988         touch $DIR/$tdir/d0/guard/foo ||
3989                 error "(3) Fail to touch $DIR/$tdir/d0/guard/foo"
3990
3991         echo "Inject failure stub on MDT0 to simulate the case that"
3992         echo "the $DIR/$tdir/d0/dummy/foo has the 'bad' linkEA entry"
3993         echo "that references $DIR/$tdir/d0/guard/foo."
3994         echo "Then remove the name entry $DIR/$tdir/d0/dummy/foo."
3995         echo "So the MDT-object $DIR/$tdir/d0/dummy/foo will be left"
3996         echo "there with the same linkEA entry as another MDT-object"
3997         echo "$DIR/$tdir/d0/guard/foo has"
3998
3999         #define OBD_FAIL_LFSCK_MUL_REF          0x1622
4000         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1622
4001         $LFS mkdir -i 0 $DIR/$tdir/d0/dummy/foo ||
4002                 error "(4) Fail to mkdir $DIR/$tdir/d0/dummy/foo"
4003         $LFS path2fid $DIR/$tdir/d0/dummy/foo
4004         local cfid=$($LFS path2fid $DIR/$tdir/d0/dummy/foo)
4005         rmdir $DIR/$tdir/d0/dummy/foo ||
4006                 error "(5) Fail to remove $DIR/$tdir/d0/dummy/foo name entry"
4007         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4008
4009         echo "stat $DIR/$tdir/d0/dummy/foo should fail"
4010         stat $DIR/$tdir/d0/dummy/foo > /dev/null 2>&1 &&
4011                 error "(6) stat successfully unexpectedly"
4012
4013         echo "Trigger namespace LFSCK to repair multiple-referenced name entry"
4014         $START_NAMESPACE -A -r ||
4015                 error "(7) Fail to start LFSCK for namespace"
4016
4017         wait_all_targets_blocked namespace completed 8
4018
4019         local repaired=$($SHOW_NAMESPACE |
4020                          awk '/^multiple_referenced_repaired/ { print $2 }')
4021         [ $repaired -eq 1 ] ||
4022         error "(9) Fail to repair multiple referenced name entry: $repaired"
4023
4024         echo "There should be an orphan under .lustre/lost+found/MDT0000/"
4025         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
4026                 error "(10) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
4027
4028         local cname="$cfid-$pfid-D-0"
4029         ls -ail $MOUNT/.lustre/lost+found/MDT0000/$cname ||
4030                 error "(11) .lustre/lost+found/MDT0000/ should not be empty"
4031 }
4032 run_test 24 "LFSCK can repair multiple-referenced name entry"
4033
4034 test_25() {
4035         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
4036                 skip "Only support to inject failure on ldiskfs" && return
4037
4038         echo "#####"
4039         echo "The file type in the name entry does not match the file type"
4040         echo "claimed by the referenced object. Then the LFSCK will update"
4041         echo "the file type in the name entry."
4042         echo "#####"
4043
4044         check_mount_and_prep
4045
4046         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4047
4048         echo "Inject failure stub on MDT0 to simulate the case that"
4049         echo "the file type stored in the name entry is wrong."
4050
4051         #define OBD_FAIL_LFSCK_BAD_TYPE         0x1623
4052         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1623
4053         touch $DIR/$tdir/d0/foo || error "(2) Fail to touch $DIR/$tdir/d0/foo"
4054         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4055
4056         echo "Trigger namespace LFSCK to repair bad file type in the name entry"
4057         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace"
4058
4059         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
4060                 mdd.${MDT_DEV}.lfsck_namespace |
4061                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
4062                 $SHOW_NAMESPACE
4063                 error "(4) unexpected status"
4064         }
4065
4066         local repaired=$($SHOW_NAMESPACE |
4067                          awk '/^bad_file_type_repaired/ { print $2 }')
4068         [ $repaired -eq 1 ] ||
4069         error "(5) Fail to repair bad file type in name entry: $repaired"
4070
4071         ls -ail $DIR/$tdir/d0 || error "(6) Fail to 'ls' the $DIR/$tdir/d0"
4072 }
4073 run_test 25 "LFSCK can repair bad file type in the name entry"
4074
4075 test_26a() {
4076         echo "#####"
4077         echo "The local name entry back referenced by the MDT-object is lost."
4078         echo "The namespace LFSCK will add the missing local name entry back"
4079         echo "to the normal namespace."
4080         echo "#####"
4081
4082         check_mount_and_prep
4083
4084         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4085         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
4086         local foofid=$($LFS path2fid $DIR/$tdir/d0/foo)
4087
4088         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/dummy ||
4089                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
4090
4091         echo "Inject failure stub on MDT0 to simulate the case that"
4092         echo "foo's name entry will be removed, but the foo's object"
4093         echo "and its linkEA are kept in the system."
4094
4095         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4096         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
4097         rm -f $DIR/$tdir/d0/foo || error "(4) Fail to unlink $DIR/$tdir/d0/foo"
4098         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4099
4100         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
4101                 error "(5) 'ls' should fail"
4102
4103         echo "Trigger namespace LFSCK to repair the missing remote name entry"
4104         $START_NAMESPACE -r -A ||
4105                 error "(6) Fail to start LFSCK for namespace"
4106
4107         wait_all_targets_blocked namespace completed 7
4108
4109         local repaired=$($SHOW_NAMESPACE |
4110                          awk '/^lost_dirent_repaired/ { print $2 }')
4111         [ $repaired -eq 1 ] ||
4112                 error "(8) Fail to repair lost dirent: $repaired"
4113
4114         ls -ail $DIR/$tdir/d0/foo ||
4115                 error "(9) Fail to 'ls' $DIR/$tdir/d0/foo"
4116
4117         local foofid2=$($LFS path2fid $DIR/$tdir/d0/foo)
4118         [ "$foofid" == "$foofid2" ] ||
4119                 error "(10) foo's FID changed: $foofid, $foofid2"
4120 }
4121 run_test 26a "LFSCK can add the missing local name entry back to the namespace"
4122
4123 test_26b() {
4124         [ $MDSCOUNT -lt 2 ] &&
4125                 skip "We need at least 2 MDSes for this test" && return
4126
4127         echo "#####"
4128         echo "The remote name entry back referenced by the MDT-object is lost."
4129         echo "The namespace LFSCK will add the missing remote name entry back"
4130         echo "to the normal namespace."
4131         echo "#####"
4132
4133         check_mount_and_prep
4134
4135         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4136         $LFS mkdir -i 0 $DIR/$tdir/d0/foo || error "(2) Fail to mkdir foo"
4137         local foofid=$($LFS path2fid $DIR/$tdir/d0/foo)
4138
4139         echo "Inject failure stub on MDT0 to simulate the case that"
4140         echo "foo's name entry will be removed, but the foo's object"
4141         echo "and its linkEA are kept in the system."
4142
4143         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4144         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
4145         rmdir $DIR/$tdir/d0/foo || error "(3) Fail to rmdir $DIR/$tdir/d0/foo"
4146         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4147
4148         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
4149                 error "(4) 'ls' should fail"
4150
4151         echo "Trigger namespace LFSCK to repair the missing remote name entry"
4152         $START_NAMESPACE -r -A ||
4153                 error "(5) Fail to start LFSCK for namespace"
4154
4155         wait_all_targets_blocked namespace completed 6
4156
4157         local repaired=$($SHOW_NAMESPACE |
4158                          awk '/^lost_dirent_repaired/ { print $2 }')
4159         [ $repaired -eq 1 ] ||
4160                 error "(7) Fail to repair lost dirent: $repaired"
4161
4162         ls -ail $DIR/$tdir/d0/foo ||
4163                 error "(8) Fail to 'ls' $DIR/$tdir/d0/foo"
4164
4165         local foofid2=$($LFS path2fid $DIR/$tdir/d0/foo)
4166         [ "$foofid" == "$foofid2" ] ||
4167                 error "(9) foo's FID changed: $foofid, $foofid2"
4168 }
4169 run_test 26b "LFSCK can add the missing remote name entry back to the namespace"
4170
4171 test_27a() {
4172         echo "#####"
4173         echo "The local parent referenced by the MDT-object linkEA is lost."
4174         echo "The namespace LFSCK will re-create the lost parent as orphan."
4175         echo "#####"
4176
4177         check_mount_and_prep
4178
4179         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4180         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
4181         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/dummy ||
4182                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
4183
4184         echo "Inject failure stub on MDT0 to simulate the case that"
4185         echo "foo's name entry will be removed, but the foo's object"
4186         echo "and its linkEA are kept in the system. And then remove"
4187         echo "another hard link and the parent directory."
4188
4189         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4190         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
4191         rm -f $DIR/$tdir/d0/foo ||
4192                 error "(4) Fail to unlink $DIR/$tdir/d0/foo"
4193         rm -f $DIR/$tdir/d0/dummy ||
4194                 error "(5) Fail to unlink $DIR/$tdir/d0/dummy"
4195         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4196
4197         rm -rf $DIR/$tdir/d0 || error "(5) Fail to unlink the dir d0"
4198         ls -ail $DIR/$tdir/d0 > /dev/null 2>&1 && error "(6) 'ls' should fail"
4199
4200         echo "Trigger namespace LFSCK to repair the lost parent"
4201         $START_NAMESPACE -r -A ||
4202                 error "(6) Fail to start LFSCK for namespace"
4203
4204         wait_all_targets_blocked namespace completed 7
4205
4206         local repaired=$($SHOW_NAMESPACE |
4207                          awk '/^lost_dirent_repaired/ { print $2 }')
4208         [ $repaired -eq 1 ] ||
4209                 error "(8) Fail to repair lost dirent: $repaired"
4210
4211         echo "There should be an orphan under .lustre/lost+found/MDT0000/"
4212         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
4213                 error "(9) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
4214
4215         ls -ail $MOUNT/.lustre/lost+found/MDT0000/
4216
4217         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-P-*)
4218         [ ! -z "$cname" ] ||
4219                 error "(10) .lustre/lost+found/MDT0000/ should not be empty"
4220 }
4221 run_test 27a "LFSCK can recreate the lost local parent directory as orphan"
4222
4223 test_27b() {
4224         [ $MDSCOUNT -lt 2 ] &&
4225                 skip "We need at least 2 MDSes for this test" && return
4226
4227         echo "#####"
4228         echo "The remote parent referenced by the MDT-object linkEA is lost."
4229         echo "The namespace LFSCK will re-create the lost parent as orphan."
4230         echo "#####"
4231
4232         check_mount_and_prep
4233
4234         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4235         $LFS mkdir -i 0 $DIR/$tdir/d0/foo || error "(2) Fail to mkdir foo"
4236
4237         $LFS path2fid $DIR/$tdir/d0
4238
4239         echo "Inject failure stub on MDT0 to simulate the case that"
4240         echo "foo's name entry will be removed, but the foo's object"
4241         echo "and its linkEA are kept in the system. And then remove"
4242         echo "the parent directory."
4243
4244         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4245         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
4246         rmdir $DIR/$tdir/d0/foo || error "(3) Fail to rmdir $DIR/$tdir/d0/foo"
4247         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4248
4249         rmdir $DIR/$tdir/d0 || error "(4) Fail to unlink the dir d0"
4250         ls -ail $DIR/$tdir/d0 > /dev/null 2>&1 && error "(5) 'ls' should fail"
4251
4252         echo "Trigger namespace LFSCK to repair the missing remote name entry"
4253         $START_NAMESPACE -r -A ||
4254                 error "(6) Fail to start LFSCK for namespace"
4255
4256         wait_all_targets_blocked namespace completed 7
4257
4258         local repaired=$($SHOW_NAMESPACE |
4259                          awk '/^lost_dirent_repaired/ { print $2 }')
4260         [ $repaired -eq 1 ] ||
4261                 error "(8) Fail to repair lost dirent: $repaired"
4262
4263         ls -ail $MOUNT/.lustre/lost+found/
4264
4265         echo "There should be an orphan under .lustre/lost+found/MDT0001/"
4266         [ -d $MOUNT/.lustre/lost+found/MDT0001 ] ||
4267                 error "(9) $MOUNT/.lustre/lost+found/MDT0001/ should be there"
4268
4269         ls -ail $MOUNT/.lustre/lost+found/MDT0001/
4270
4271         cname=$(find $MOUNT/.lustre/lost+found/MDT0001/ -name *-P-*)
4272         [ ! -z "$cname" ] ||
4273                 error "(10) .lustre/lost+found/MDT0001/ should not be empty"
4274 }
4275 run_test 27b "LFSCK can recreate the lost remote parent directory as orphan"
4276
4277 test_28() {
4278         [ $MDSCOUNT -lt 2 ] &&
4279                 skip "The test needs at least 2 MDTs" && return
4280
4281         echo "#####"
4282         echo "The target name entry is lost. The LFSCK should insert the"
4283         echo "orphan MDT-object under .lustre/lost+found/MDTxxxx. But if"
4284         echo "the MDT (on which the orphan MDT-object resides) has ever"
4285         echo "failed to respond some name entry verification during the"
4286         echo "first stage-scanning, then the LFSCK should skip to handle"
4287         echo "orphan MDT-object on this MDT. But other MDTs should not"
4288         echo "be affected."
4289         echo "#####"
4290
4291         check_mount_and_prep
4292         $LFS mkdir -i 0 $DIR/$tdir/d1
4293         $LFS mkdir -i 1 $DIR/$tdir/d1/a1
4294         $LFS mkdir -i 1 $DIR/$tdir/d1/a2
4295
4296         $LFS mkdir -i 1 $DIR/$tdir/d2
4297         $LFS mkdir -i 0 $DIR/$tdir/d2/a1
4298         $LFS mkdir -i 0 $DIR/$tdir/d2/a2
4299
4300         echo "Inject failure stub on MDT0 to simulate the case that"
4301         echo "d1/a1's name entry will be removed, but the d1/a1's object"
4302         echo "and its linkEA are kept in the system. And the case that"
4303         echo "d2/a2's name entry will be removed, but the d2/a2's object"
4304         echo "and its linkEA are kept in the system."
4305
4306         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4307         do_facet mds1 $LCTL set_param fail_loc=0x1624
4308         do_facet mds2 $LCTL set_param fail_loc=0x1624
4309         rmdir $DIR/$tdir/d1/a1 || error "(1) Fail to rmdir $DIR/$tdir/d1/a1"
4310         rmdir $DIR/$tdir/d2/a2 || error "(2) Fail to rmdir $DIR/$tdir/d2/a2"
4311         do_facet mds1 $LCTL set_param fail_loc=0
4312         do_facet mds2 $LCTL set_param fail_loc=0
4313
4314         cancel_lru_locks mdc
4315         cancel_lru_locks osc
4316
4317         echo "Inject failure, to simulate the MDT0 fail to handle"
4318         echo "MDT1 LFSCK request during the first-stage scanning."
4319         #define OBD_FAIL_LFSCK_BAD_NETWORK      0x161c
4320         do_facet mds2 $LCTL set_param fail_loc=0x161c fail_val=0
4321
4322         echo "Trigger namespace LFSCK on all devices to find out orphan object"
4323         $START_NAMESPACE -r -A ||
4324                 error "(3) Fail to start LFSCK for namespace"
4325
4326         wait_update_facet mds1 "$LCTL get_param -n \
4327                 mdd.$(facet_svc mds1).lfsck_namespace |
4328                 awk '/^status/ { print \\\$2 }'" "partial" 32 || {
4329                 error "(4) mds1 is not the expected 'partial'"
4330         }
4331
4332         wait_update_facet mds2 "$LCTL get_param -n \
4333                 mdd.$(facet_svc mds2).lfsck_namespace |
4334                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
4335                 error "(5) mds2 is not the expected 'completed'"
4336         }
4337
4338         do_facet mds2 $LCTL set_param fail_loc=0 fail_val=0
4339
4340         local repaired=$(do_facet mds1 $LCTL get_param -n \
4341                          mdd.$(facet_svc mds1).lfsck_namespace |
4342                          awk '/^lost_dirent_repaired/ { print $2 }')
4343         [ $repaired -eq 0 ] ||
4344                 error "(6) Expect 0 fixed on mds1, but got: $repaired"
4345
4346         repaired=$(do_facet mds2 $LCTL get_param -n \
4347                    mdd.$(facet_svc mds2).lfsck_namespace |
4348                    awk '/^lost_dirent_repaired/ { print $2 }')
4349         [ $repaired -eq 1 ] ||
4350                 error "(7) Expect 1 fixed on mds2, but got: $repaired"
4351
4352         echo "Trigger namespace LFSCK on all devices again to cleanup"
4353         $START_NAMESPACE -r -A ||
4354                 error "(8) Fail to start LFSCK for namespace"
4355
4356         wait_all_targets_blocked namespace completed 9
4357
4358         local repaired=$(do_facet mds1 $LCTL get_param -n \
4359                          mdd.$(facet_svc mds1).lfsck_namespace |
4360                          awk '/^lost_dirent_repaired/ { print $2 }')
4361         [ $repaired -eq 1 ] ||
4362                 error "(10) Expect 1 fixed on mds1, but got: $repaired"
4363
4364         repaired=$(do_facet mds2 $LCTL get_param -n \
4365                    mdd.$(facet_svc mds2).lfsck_namespace |
4366                    awk '/^lost_dirent_repaired/ { print $2 }')
4367         [ $repaired -eq 0 ] ||
4368                 error "(11) Expect 0 fixed on mds2, but got: $repaired"
4369 }
4370 run_test 28 "Skip the failed MDT(s) when handle orphan MDT-objects"
4371
4372 test_29a() {
4373         echo "#####"
4374         echo "The object's nlink attribute is larger than the object's known"
4375         echo "name entries count. The LFSCK will repair the object's nlink"
4376         echo "attribute to match the known name entries count"
4377         echo "#####"
4378
4379         check_mount_and_prep
4380
4381         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4382         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
4383
4384         echo "Inject failure stub on MDT0 to simulate the case that foo's"
4385         echo "nlink attribute is larger than its name entries count."
4386
4387         #define OBD_FAIL_LFSCK_MORE_NLINK       0x1625
4388         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1625
4389         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/h1 ||
4390                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
4391         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4392
4393         cancel_lru_locks mdc
4394         local count=$(stat --format=%h $DIR/$tdir/d0/foo)
4395         [ $count -eq 3 ] || error "(4) Cannot inject error: $count"
4396
4397         echo "Trigger namespace LFSCK to repair the nlink count"
4398         $START_NAMESPACE -r -A ||
4399                 error "(5) Fail to start LFSCK for namespace"
4400
4401         wait_all_targets_blocked namespace completed 6
4402
4403         local repaired=$($SHOW_NAMESPACE |
4404                          awk '/^nlinks_repaired/ { print $2 }')
4405         [ $repaired -eq 1 ] ||
4406                 error "(7) Fail to repair nlink count: $repaired"
4407
4408         cancel_lru_locks mdc
4409         count=$(stat --format=%h $DIR/$tdir/d0/foo)
4410         [ $count -eq 2 ] || error "(8) Fail to repair nlink count: $count"
4411 }
4412 # Disable 29a, we only allow nlink to be updated if the known linkEA
4413 # entries is larger than nlink count.
4414 #
4415 #run_test 29a "LFSCK can repair bad nlink count (1)"
4416
4417 test_29b() {
4418         echo "#####"
4419         echo "The object's nlink attribute is smaller than the object's known"
4420         echo "name entries count. The LFSCK will repair the object's nlink"
4421         echo "attribute to match the known name entries count"
4422         echo "#####"
4423
4424         check_mount_and_prep
4425
4426         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
4427         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
4428
4429         echo "Inject failure stub on MDT0 to simulate the case that foo's"
4430         echo "nlink attribute is smaller than its name entries count."
4431
4432         #define OBD_FAIL_LFSCK_LESS_NLINK       0x1626
4433         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1626
4434         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/h1 ||
4435                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
4436         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4437
4438         cancel_lru_locks mdc
4439         local count=$(stat --format=%h $DIR/$tdir/d0/foo)
4440         [ $count -eq 1 ] || error "(4) Cannot inject error: $count"
4441
4442         echo "Trigger namespace LFSCK to repair the nlink count"
4443         $START_NAMESPACE -r -A ||
4444                 error "(5) Fail to start LFSCK for namespace"
4445
4446         wait_all_targets_blocked namespace completed 6
4447
4448         local repaired=$($SHOW_NAMESPACE |
4449                          awk '/^nlinks_repaired/ { print $2 }')
4450         [ $repaired -eq 1 ] ||
4451                 error "(7) Fail to repair nlink count: $repaired"
4452
4453         cancel_lru_locks mdc
4454         count=$(stat --format=%h $DIR/$tdir/d0/foo)
4455         [ $count -eq 2 ] || error "(8) Fail to repair nlink count: $count"
4456 }
4457 run_test 29b "LFSCK can repair bad nlink count (2)"
4458
4459 test_29c()
4460 {
4461         echo "#####"
4462         echo "The namespace LFSCK will create many hard links to the target"
4463         echo "file as to exceed the linkEA size limitation. Under such case"
4464         echo "the linkEA will be marked as overflow that will prevent the"
4465         echo "target file to be migrated. Then remove some hard links to"
4466         echo "make the left hard links to be held within the linkEA size"
4467         echo "limitation. But before the namespace LFSCK adding all the"
4468         echo "missed linkEA entries back, the overflow mark (timestamp)"
4469         echo "will not be cleared."
4470         echo "#####"
4471
4472         check_mount_and_prep
4473
4474         mkdir -p $DIR/$tdir/guard || error "(0.1) Fail to mkdir"
4475         $LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/foo ||
4476                 error "(0.2) Fail to mkdir"
4477         touch $DIR/$tdir/guard/f0 || error "(1) Fail to create"
4478         local oldfid=$($LFS path2fid $DIR/$tdir/guard/f0)
4479
4480         # define MAX_LINKEA_SIZE        4096
4481         # sizeof(link_ea_header) = 24
4482         # sizeof(link_ea_entry) = 18
4483         # nlink_min=$(((MAX_LINKEA_SIZE - sizeof(link_ea_header)) /
4484         #             (sizeof(link_ea_entry) + name_length))
4485         # If the average name length is 12 bytes, then 150 hard links
4486         # is totally enough to overflow the linkEA
4487         echo "Create 150 hard links should succeed although the linkEA overflow"
4488         createmany -l $DIR/$tdir/guard/f0 $DIR/$tdir/foo/ttttttttttt 150 ||
4489                 error "(2) Fail to hard link"
4490
4491         cancel_lru_locks mdc
4492         if [ $MDSCOUNT -ge 2 ]; then
4493                 $LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null ||
4494                         error "(3.1) Migrate failure"
4495
4496                 echo "The object with linkEA overflow should NOT be migrated"
4497                 local newfid=$($LFS path2fid $DIR/$tdir/guard/f0)
4498                 [ "$newfid" == "$oldfid" ] ||
4499                         error "(3.2) Migrate should fail: $newfid != $oldfid"
4500         fi
4501
4502         # Remove 100 hard links, then the linkEA should have space
4503         # to hold the missed linkEA entries.
4504         echo "Remove 100 hard links to save space for the missed linkEA entries"
4505         unlinkmany $DIR/$tdir/foo/ttttttttttt 100 || error "(4) Fail to unlink"
4506
4507         if [ $MDSCOUNT -ge 2 ]; then
4508                 $LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null ||
4509                         error "(5.1) Migrate failure"
4510
4511                 # The overflow timestamp is still there, so migration will fail.
4512                 local newfid=$($LFS path2fid $DIR/$tdir/guard/f0)
4513                 [ "$newfid" == "$oldfid" ] ||
4514                         error "(5.2) Migrate should fail: $newfid != $oldfid"
4515         fi
4516
4517         # sleep 3 seconds to guarantee that the overflow is recognized
4518         sleep 3
4519
4520         echo "Trigger namespace LFSCK to clear the overflow timestamp"
4521         $START_NAMESPACE -r -A ||
4522                 error "(6) Fail to start LFSCK for namespace"
4523
4524         wait_all_targets_blocked namespace completed 7
4525
4526         local repaired=$($SHOW_NAMESPACE |
4527                          awk '/^linkea_overflow_cleared/ { print $2 }')
4528         [ $repaired -eq 1 ] ||
4529                 error "(8) Fail to clear linkea overflow: $repaired"
4530
4531         repaired=$($SHOW_NAMESPACE |
4532                    awk '/^nlinks_repaired/ { print $2 }')
4533         [ $repaired -eq 0 ] ||
4534                 error "(9) Unexpected nlink repaired: $repaired"
4535
4536         if [ $MDSCOUNT -ge 2 ]; then
4537                 $LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null ||
4538                         error "(10.1) Migrate failure"
4539
4540                 # Migration should succeed after clear the overflow timestamp.
4541                 local newfid=$($LFS path2fid $DIR/$tdir/guard/f0)
4542                 [ "$newfid" != "$oldfid" ] ||
4543                         error "(10.2) Migrate should succeed"
4544
4545                 ls -l $DIR/$tdir/foo > /dev/null ||
4546                         error "(11) 'ls' failed after migration"
4547         fi
4548
4549         rm -f $DIR/$tdir/guard/f0 || error "(12) Fail to unlink f0"
4550         rm -rf $DIR/$tdir/foo || error "(13) Fail to rmdir foo"
4551 }
4552 run_test 29c "verify linkEA size limitation"
4553
4554 test_30() {
4555         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
4556                 skip "Only support backend /lost+found for ldiskfs" && return
4557
4558         echo "#####"
4559         echo "The namespace LFSCK will move the orphans from backend"
4560         echo "/lost+found directory to normal client visible namespace"
4561         echo "or to global visible ./lustre/lost+found/MDTxxxx/ directory"
4562         echo "#####"
4563
4564         check_mount_and_prep
4565
4566         $LFS mkdir -i 0 $DIR/$tdir/foo || error "(1) Fail to mkdir foo"
4567         touch $DIR/$tdir/foo/f0 || error "(2) Fail to touch f1"
4568
4569         echo "Inject failure stub on MDT0 to simulate the case that"
4570         echo "directory d0 has no linkEA entry, then the LFSCK will"
4571         echo "move it into .lustre/lost+found/MDTxxxx/ later."
4572
4573         #define OBD_FAIL_LFSCK_NO_LINKEA        0x161d
4574         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161d
4575         mkdir $DIR/$tdir/foo/d0 || error "(3) Fail to mkdir d0"
4576         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4577
4578         touch $DIR/$tdir/foo/d0/f1 || error "(4) Fail to touch f1"
4579         mkdir $DIR/$tdir/foo/d0/d1 || error "(5) Fail to mkdir d1"
4580
4581         echo "Inject failure stub on MDT0 to simulate the case that the"
4582         echo "object's name entry will be removed, but not destroy the"
4583         echo "object. Then backend e2fsck will handle it as orphan and"
4584         echo "add them into the backend /lost+found directory."
4585
4586         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
4587         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
4588         rmdir $DIR/$tdir/foo/d0/d1 || error "(6) Fail to rmdir d1"
4589         rm -f $DIR/$tdir/foo/d0/f1 || error "(7) Fail to unlink f1"
4590         rmdir $DIR/$tdir/foo/d0 || error "(8) Fail to rmdir d0"
4591         rm -f $DIR/$tdir/foo/f0 || error "(9) Fail to unlink f0"
4592         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4593
4594         umount_client $MOUNT || error "(10) Fail to stop client!"
4595
4596         stop $SINGLEMDS || error "(11) Fail to stop MDT0"
4597
4598         echo "run e2fsck"
4599         run_e2fsck $(facet_host $SINGLEMDS) $MDT_DEVNAME "-y" ||
4600                 error "(12) Fail to run e2fsck"
4601
4602         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
4603                 error "(13) Fail to start MDT0"
4604
4605         echo "Trigger namespace LFSCK to recover backend orphans"
4606         $START_NAMESPACE -r -A ||
4607                 error "(14) Fail to start LFSCK for namespace"
4608
4609         wait_all_targets_blocked namespace completed 15
4610
4611         local repaired=$($SHOW_NAMESPACE |
4612                          awk '/^local_lost_found_moved/ { print $2 }')
4613         [ $repaired -ge 4 ] ||
4614                 error "(16) Fail to recover backend orphans: $repaired"
4615
4616         mount_client $MOUNT || error "(17) Fail to start client!"
4617
4618         stat $DIR/$tdir/foo/f0 || error "(18) f0 is not recovered"
4619
4620         ls -ail $MOUNT/.lustre/lost+found/
4621
4622         echo "d0 should become orphan under .lustre/lost+found/MDT0000/"
4623         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
4624                 error "(19) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
4625
4626         ls -ail $MOUNT/.lustre/lost+found/MDT0000/
4627
4628         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-*-D-*)
4629         [ ! -z "$cname" ] || error "(20) d0 is not recovered"
4630
4631         stat ${cname}/d1 || error "(21) d0 is not recovered"
4632         stat ${cname}/f1 || error "(22) f1 is not recovered"
4633 }
4634 run_test 30 "LFSCK can recover the orphans from backend /lost+found"
4635
4636 test_31a() {
4637         [ $MDSCOUNT -lt 2 ] &&
4638                 skip "The test needs at least 2 MDTs" && return
4639
4640         echo "#####"
4641         echo "For the name entry under a striped directory, if the name"
4642         echo "hash does not match the shard, then the LFSCK will repair"
4643         echo "the bad name entry"
4644         echo "#####"
4645
4646         check_mount_and_prep
4647
4648         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4649                 error "(1) Fail to create striped directory"
4650
4651         echo "Inject failure stub on client to simulate the case that"
4652         echo "some name entry should be inserted into other non-first"
4653         echo "shard, but inserted into the first shard by wrong"
4654
4655         #define OBD_FAIL_LFSCK_BAD_NAME_HASH    0x1628
4656         $LCTL set_param fail_loc=0x1628 fail_val=0
4657         createmany -d $DIR/$tdir/striped_dir/d $MDSCOUNT ||
4658                 error "(2) Fail to create file under striped directory"
4659         $LCTL set_param fail_loc=0 fail_val=0
4660
4661         echo "Trigger namespace LFSCK to repair bad name hash"
4662         $START_NAMESPACE -r -A ||
4663                 error "(3) Fail to start LFSCK for namespace"
4664
4665         wait_all_targets_blocked namespace completed 4
4666
4667         local repaired=$($SHOW_NAMESPACE |
4668                          awk '/^name_hash_repaired/ { print $2 }')
4669         [ $repaired -ge 1 ] ||
4670                 error "(5) Fail to repair bad name hash: $repaired"
4671
4672         umount_client $MOUNT || error "(6) umount failed"
4673         mount_client $MOUNT || error "(7) mount failed"
4674
4675         for ((i = 0; i < $MDSCOUNT; i++)); do
4676                 stat $DIR/$tdir/striped_dir/d$i ||
4677                         error "(8) Fail to stat d$i after LFSCK"
4678                 rmdir $DIR/$tdir/striped_dir/d$i ||
4679                         error "(9) Fail to unlink d$i after LFSCK"
4680         done
4681
4682         rmdir $DIR/$tdir/striped_dir ||
4683                 error "(10) Fail to remove the striped directory after LFSCK"
4684 }
4685 run_test 31a "The LFSCK can find/repair the name entry with bad name hash (1)"
4686
4687 test_31b() {
4688         [ $MDSCOUNT -lt 2 ] &&
4689                 skip "The test needs at least 2 MDTs" && return
4690
4691         echo "#####"
4692         echo "For the name entry under a striped directory, if the name"
4693         echo "hash does not match the shard, then the LFSCK will repair"
4694         echo "the bad name entry"
4695         echo "#####"
4696
4697         check_mount_and_prep
4698
4699         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4700                 error "(1) Fail to create striped directory"
4701
4702         echo "Inject failure stub on client to simulate the case that"
4703         echo "some name entry should be inserted into other non-second"
4704         echo "shard, but inserted into the secod shard by wrong"
4705
4706         #define OBD_FAIL_LFSCK_BAD_NAME_HASH    0x1628
4707         $LCTL set_param fail_loc=0x1628 fail_val=1
4708         createmany -d $DIR/$tdir/striped_dir/d $MDSCOUNT ||
4709                 error "(2) Fail to create file under striped directory"
4710         $LCTL set_param fail_loc=0 fail_val=0
4711
4712         echo "Trigger namespace LFSCK to repair bad name hash"
4713         $START_NAMESPACE -r -A ||
4714                 error "(3) Fail to start LFSCK for namespace"
4715
4716         wait_all_targets_blocked namespace completed 4
4717
4718         local repaired=$(do_facet mds2 $LCTL get_param -n \
4719                          mdd.$(facet_svc mds2).lfsck_namespace |
4720                          awk '/^name_hash_repaired/ { print $2 }')
4721         [ $repaired -ge 1 ] ||
4722                 error "(5) Fail to repair bad name hash: $repaired"
4723
4724         umount_client $MOUNT || error "(6) umount failed"
4725         mount_client $MOUNT || error "(7) mount failed"
4726
4727         for ((i = 0; i < $MDSCOUNT; i++)); do
4728                 stat $DIR/$tdir/striped_dir/d$i ||
4729                         error "(8) Fail to stat d$i after LFSCK"
4730                 rmdir $DIR/$tdir/striped_dir/d$i ||
4731                         error "(9) Fail to unlink d$i after LFSCK"
4732         done
4733
4734         rmdir $DIR/$tdir/striped_dir ||
4735                 error "(10) Fail to remove the striped directory after LFSCK"
4736 }
4737 run_test 31b "The LFSCK can find/repair the name entry with bad name hash (2)"
4738
4739 test_31c() {
4740         [ $MDSCOUNT -lt 2 ] &&
4741                 skip "The test needs at least 2 MDTs" && return
4742
4743         echo "#####"
4744         echo "For some reason, the master MDT-object of the striped directory"
4745         echo "may lost its master LMV EA. If nobody created files under the"
4746         echo "master directly after the master LMV EA lost, then the LFSCK"
4747         echo "should re-generate the master LMV EA."
4748         echo "#####"
4749
4750         check_mount_and_prep
4751
4752         echo "Inject failure stub on MDT0 to simulate the case that the"
4753         echo "master MDT-object of the striped directory lost the LMV EA."
4754
4755         #define OBD_FAIL_LFSCK_LOST_MASTER_LMV  0x1629
4756         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1629
4757         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4758                 error "(1) Fail to create striped directory"
4759         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
4760
4761         echo "Trigger namespace LFSCK to re-generate master LMV EA"
4762         $START_NAMESPACE -r -A ||
4763                 error "(2) Fail to start LFSCK for namespace"
4764
4765         wait_all_targets_blocked namespace completed 3
4766
4767         local repaired=$($SHOW_NAMESPACE |
4768                          awk '/^striped_dirs_repaired/ { print $2 }')
4769         [ $repaired -eq 1 ] ||
4770                 error "(4) Fail to re-generate master LMV EA: $repaired"
4771
4772         umount_client $MOUNT || error "(5) umount failed"
4773         mount_client $MOUNT || error "(6) mount failed"
4774
4775         local empty=$(ls $DIR/$tdir/striped_dir/)
4776         [ -z "$empty" ] || error "(7) The master LMV EA is not repaired: $empty"
4777
4778         rmdir $DIR/$tdir/striped_dir ||
4779                 error "(8) Fail to remove the striped directory after LFSCK"
4780 }
4781 run_test 31c "Re-generate the lost master LMV EA for striped directory"
4782
4783 test_31d() {
4784         [ $MDSCOUNT -lt 2 ] &&
4785                 skip "The test needs at least 2 MDTs" && return
4786
4787         echo "#####"
4788         echo "For some reason, the master MDT-object of the striped directory"
4789         echo "may lost its master LMV EA. If somebody created files under the"
4790         echo "master directly after the master LMV EA lost, then the LFSCK"
4791         echo "should NOT re-generate the master LMV EA, instead, it should"
4792         echo "change the broken striped dirctory as read-only to prevent"
4793         echo "further damage"
4794         echo "#####"
4795
4796         check_mount_and_prep
4797
4798         echo "Inject failure stub on MDT0 to simulate the case that the"
4799         echo "master MDT-object of the striped directory lost the LMV EA."
4800
4801         #define OBD_FAIL_LFSCK_LOST_MASTER_LMV  0x1629
4802         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1629
4803         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4804                 error "(1) Fail to create striped directory"
4805         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0
4806
4807         umount_client $MOUNT || error "(2) umount failed"
4808         mount_client $MOUNT || error "(3) mount failed"
4809
4810         touch $DIR/$tdir/striped_dir/dummy ||
4811                 error "(4) Fail to touch under broken striped directory"
4812
4813         echo "Trigger namespace LFSCK to find out the inconsistency"
4814         $START_NAMESPACE -r -A ||
4815                 error "(5) Fail to start LFSCK for namespace"
4816
4817         wait_all_targets_blocked namespace completed 6
4818
4819         local repaired=$($SHOW_NAMESPACE |
4820                          awk '/^striped_dirs_repaired/ { print $2 }')
4821         [ $repaired -eq 0 ] ||
4822                 error "(7) Re-generate master LMV EA unexpected: $repaired"
4823
4824         stat $DIR/$tdir/striped_dir/dummy ||
4825                 error "(8) Fail to stat $DIR/$tdir/striped_dir/dummy"
4826
4827         touch $DIR/$tdir/striped_dir/foo &&
4828                 error "(9) The broken striped directory should be read-only"
4829
4830         chattr -i $DIR/$tdir/striped_dir ||
4831                 error "(10) Fail to chattr on the broken striped directory"
4832
4833         rmdir $DIR/$tdir/striped_dir ||
4834                 error "(11) Fail to remove the striped directory after LFSCK"
4835 }
4836 run_test 31d "Set broken striped directory (modified after broken) as read-only"
4837
4838 test_31e() {
4839         [ $MDSCOUNT -lt 2 ] &&
4840                 skip "The test needs at least 2 MDTs" && return
4841
4842         echo "#####"
4843         echo "For some reason, the slave MDT-object of the striped directory"
4844         echo "may lost its slave LMV EA. The LFSCK should re-generate the"
4845         echo "slave LMV EA."
4846         echo "#####"
4847
4848         check_mount_and_prep
4849
4850         echo "Inject failure stub on MDT0 to simulate the case that the"
4851         echo "slave MDT-object (that resides on the same MDT as the master"
4852         echo "MDT-object resides on) lost the LMV EA."
4853
4854         #define OBD_FAIL_LFSCK_LOST_SLAVE_LMV   0x162a
4855         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x162a fail_val=0
4856         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4857                 error "(1) Fail to create striped directory"
4858         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0 fail_val=0
4859
4860         echo "Trigger namespace LFSCK to re-generate slave LMV EA"
4861         $START_NAMESPACE -r -A ||
4862                 error "(2) Fail to start LFSCK for namespace"
4863
4864         wait_all_targets_blocked namespace completed 3
4865
4866         local repaired=$($SHOW_NAMESPACE |
4867                          awk '/^striped_shards_repaired/ { print $2 }')
4868         [ $repaired -eq 1 ] ||
4869                 error "(4) Fail to re-generate slave LMV EA: $repaired"
4870
4871         rmdir $DIR/$tdir/striped_dir ||
4872                 error "(5) Fail to remove the striped directory after LFSCK"
4873 }
4874 run_test 31e "Re-generate the lost slave LMV EA for striped directory (1)"
4875
4876 test_31f() {
4877         [ $MDSCOUNT -lt 2 ] &&
4878                 skip "The test needs at least 2 MDTs" && return
4879
4880         echo "#####"
4881         echo "For some reason, the slave MDT-object of the striped directory"
4882         echo "may lost its slave LMV EA. The LFSCK should re-generate the"
4883         echo "slave LMV EA."
4884         echo "#####"
4885
4886         check_mount_and_prep
4887
4888         echo "Inject failure stub on MDT0 to simulate the case that the"
4889         echo "slave MDT-object (that resides on different MDT as the master"
4890         echo "MDT-object resides on) lost the LMV EA."
4891
4892         #define OBD_FAIL_LFSCK_LOST_SLAVE_LMV   0x162a
4893         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x162a fail_val=1
4894         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4895                 error "(1) Fail to create striped directory"
4896         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0 fail_val=0
4897
4898         echo "Trigger namespace LFSCK to re-generate slave LMV EA"
4899         $START_NAMESPACE -r -A ||
4900                 error "(2) Fail to start LFSCK for namespace"
4901
4902         wait_all_targets_blocked namespace completed 3
4903
4904         local repaired=$(do_facet mds2 $LCTL get_param -n \
4905                          mdd.$(facet_svc mds2).lfsck_namespace |
4906                          awk '/^striped_shards_repaired/ { print $2 }')
4907         [ $repaired -eq 1 ] ||
4908                 error "(4) Fail to re-generate slave LMV EA: $repaired"
4909
4910         rmdir $DIR/$tdir/striped_dir ||
4911                 error "(5) Fail to remove the striped directory after LFSCK"
4912 }
4913 run_test 31f "Re-generate the lost slave LMV EA for striped directory (2)"
4914
4915 test_31g() {
4916         [ $MDSCOUNT -lt 2 ] &&
4917                 skip "The test needs at least 2 MDTs" && return
4918
4919         echo "#####"
4920         echo "For some reason, the stripe index in the slave LMV EA is"
4921         echo "corrupted. The LFSCK should repair the slave LMV EA."
4922         echo "#####"
4923
4924         check_mount_and_prep
4925
4926         echo "Inject failure stub on MDT0 to simulate the case that the"
4927         echo "slave LMV EA on the first shard of the striped directory"
4928         echo "claims the same index as the second shard claims"
4929
4930         #define OBD_FAIL_LFSCK_BAD_SLAVE_LMV    0x162b
4931         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x162b fail_val=0
4932         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4933                 error "(1) Fail to create striped directory"
4934         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0 fail_val=0
4935
4936         echo "Trigger namespace LFSCK to repair the slave LMV EA"
4937         $START_NAMESPACE -r -A ||
4938                 error "(2) Fail to start LFSCK for namespace"
4939
4940         wait_all_targets_blocked namespace completed 3
4941
4942         local repaired=$($SHOW_NAMESPACE |
4943                          awk '/^striped_shards_repaired/ { print $2 }')
4944         [ $repaired -eq 1 ] ||
4945                 error "(4) Fail to repair slave LMV EA: $repaired"
4946
4947         umount_client $MOUNT || error "(5) umount failed"
4948         mount_client $MOUNT || error "(6) mount failed"
4949
4950         touch $DIR/$tdir/striped_dir/foo ||
4951                 error "(7) Fail to touch file after the LFSCK"
4952
4953         rm -f $DIR/$tdir/striped_dir/foo ||
4954                 error "(8) Fail to unlink file after the LFSCK"
4955
4956         rmdir $DIR/$tdir/striped_dir ||
4957                 error "(9) Fail to remove the striped directory after LFSCK"
4958 }
4959 run_test 31g "Repair the corrupted slave LMV EA"
4960
4961 test_31h() {
4962         [ $MDSCOUNT -lt 2 ] &&
4963                 skip "The test needs at least 2 MDTs" && return
4964
4965         echo "#####"
4966         echo "For some reason, the shard's name entry in the striped"
4967         echo "directory may be corrupted. The LFSCK should repair the"
4968         echo "bad shard's name entry."
4969         echo "#####"
4970
4971         check_mount_and_prep
4972
4973         echo "Inject failure stub on MDT0 to simulate the case that the"
4974         echo "first shard's name entry in the striped directory claims"
4975         echo "the same index as the second shard's name entry claims."
4976
4977         #define OBD_FAIL_LFSCK_BAD_SLAVE_NAME   0x162c
4978         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x162c fail_val=0
4979         $LFS setdirstripe -i 0 -c $MDSCOUNT $DIR/$tdir/striped_dir ||
4980                 error "(1) Fail to create striped directory"
4981         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0 fail_val=0
4982
4983         echo "Trigger namespace LFSCK to repair the shard's name entry"
4984         $START_NAMESPACE -r -A ||
4985                 error "(2) Fail to start LFSCK for namespace"
4986
4987         wait_all_targets_blocked namespace completed 3
4988
4989         local repaired=$($SHOW_NAMESPACE |
4990                          awk '/^dirent_repaired/ { print $2 }')
4991         [ $repaired -eq 1 ] ||
4992                 error "(4) Fail to repair shard's name entry: $repaired"
4993
4994         umount_client $MOUNT || error "(5) umount failed"
4995         mount_client $MOUNT || error "(6) mount failed"
4996
4997         touch $DIR/$tdir/striped_dir/foo ||
4998                 error "(7) Fail to touch file after the LFSCK"
4999
5000         rm -f $DIR/$tdir/striped_dir/foo ||
5001                 error "(8) Fail to unlink file after the LFSCK"
5002
5003         rmdir $DIR/$tdir/striped_dir ||
5004                 error "(9) Fail to remove the striped directory after LFSCK"
5005 }
5006 run_test 31h "Repair the corrupted shard's name entry"
5007
5008 test_32()
5009 {
5010         lfsck_prep 5 5
5011         umount_client $MOUNT
5012
5013         #define OBD_FAIL_LFSCK_ASSISTANT_DIRECT 0x162d
5014         do_facet $SINGLEMDS $LCTL set_param fail_val=3 fail_loc=0x162d
5015         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
5016
5017         local STATUS=$($SHOW_LAYOUT | awk '/^status/ { print $2 }')
5018         [ "$STATUS" == "scanning-phase1" ] ||
5019                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
5020
5021         echo "stop ost1"
5022         stop ost1 > /dev/null || error "(4) Fail to stop OST1!"
5023
5024         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
5025         sleep 1
5026
5027         echo "stop LFSCK"
5028         $STOP_LFSCK || error "(5) Fail to stop LFSCK!"
5029 }
5030 run_test 32 "stop LFSCK when some OST failed"
5031
5032 # restore MDS/OST size
5033 MDSSIZE=${SAVED_MDSSIZE}
5034 OSTSIZE=${SAVED_OSTSIZE}
5035 OSTCOUNT=${SAVED_OSTCOUNT}
5036
5037 # cleanup the system at last
5038 formatall
5039
5040 complete $SECONDS
5041 exit_status