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