Whamcloud - gitweb
646a1f606fc42abd90cf49c0dd197046b8def327
[fs/lustre-release.git] / lustre / tests / sanity-lfsck.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10
11 #Bug number for excepting test
12 ALWAYS_EXCEPT="$SANITY_LFSCK_EXCEPT"
13
14 [ "$SLOW" = "no" ] && EXCEPT_SLOW=""
15 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
16
17 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
18 . $LUSTRE/tests/test-framework.sh
19 init_test_env $@
20 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
21 init_logging
22
23 require_dsh_mds || exit 0
24
25 LTIME=${LTIME:-120}
26
27 SAVED_MDSSIZE=${MDSSIZE}
28 SAVED_OSTSIZE=${OSTSIZE}
29 SAVED_OSTCOUNT=${OSTCOUNT}
30 # use small MDS + OST size to speed formatting time
31 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
32 MDSSIZE=100000
33 OSTSIZE=100000
34 # no need too many OSTs, to reduce the format/start/stop overhead
35 [ $OSTCOUNT -gt 4 ] && OSTCOUNT=4
36
37 # build up a clean test environment.
38 formatall
39 setupall
40
41 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.3.60) ]] &&
42         skip "Need MDS version at least 2.3.60" && check_and_cleanup_lustre &&
43         exit 0
44
45 [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.4.90) ]] &&
46         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2c"
47
48 [[ $(lustre_version_code ost1) -lt $(version_code 2.5.55) ]] &&
49         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 11 12 13 14 15 16 17 18 19 20 21"
50
51 [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.50) ]] &&
52         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2d 2e 3 22 23 24 25 26 27 28 29 30 31"
53
54 # DNE does not support striped directory on zfs-based backend yet.
55 [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
56         ALWAYS_EXCEPT="$ALWAYS_EXCEPT 31"
57
58 build_test_filter
59
60 MDT_DEV="${FSNAME}-MDT0000"
61 OST_DEV="${FSNAME}-OST0000"
62 MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/})
63 START_NAMESPACE="do_facet $SINGLEMDS \
64                 $LCTL lfsck_start -M ${MDT_DEV} -t namespace"
65 START_LAYOUT="do_facet $SINGLEMDS \
66                 $LCTL lfsck_start -M ${MDT_DEV} -t layout"
67 START_LAYOUT_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV} -t layout"
68 STOP_LFSCK="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}"
69 SHOW_NAMESPACE="do_facet $SINGLEMDS \
70                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_namespace"
71 SHOW_LAYOUT="do_facet $SINGLEMDS \
72                 $LCTL get_param -n mdd.${MDT_DEV}.lfsck_layout"
73 SHOW_LAYOUT_ON_OST="do_facet ost1 \
74                 $LCTL get_param -n obdfilter.${OST_DEV}.lfsck_layout"
75 MOUNT_OPTS_SCRUB="-o user_xattr"
76 MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
77
78 lfsck_prep() {
79         local ndirs=$1
80         local nfiles=$2
81         local igif=$3
82
83         check_mount_and_prep
84
85         echo "preparing... $nfiles * $ndirs files will be created $(date)."
86         if [ ! -z $igif ]; then
87                 #define OBD_FAIL_FID_IGIF       0x1504
88                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1504
89         fi
90
91         cp $LUSTRE/tests/*.sh $DIR/$tdir/
92         if [ $ndirs -gt 0 ]; then
93                 createmany -d $DIR/$tdir/d $ndirs
94                 createmany -m $DIR/$tdir/f $ndirs
95                 if [ $nfiles -gt 0 ]; then
96                         for ((i = 0; i < $ndirs; i++)); do
97                                 createmany -m $DIR/$tdir/d${i}/f $nfiles > \
98                                         /dev/null || error "createmany $nfiles"
99                         done
100                 fi
101                 createmany -d $DIR/$tdir/e $ndirs
102         fi
103
104         if [ ! -z $igif ]; then
105                 touch $DIR/$tdir/dummy
106                 do_facet $SINGLEMDS $LCTL set_param fail_loc=0
107         fi
108
109         echo "prepared $(date)."
110 }
111
112 test_0() {
113         lfsck_prep 3 3
114
115         #define OBD_FAIL_LFSCK_DELAY1           0x1600
116         do_facet $SINGLEMDS $LCTL set_param fail_val=3 fail_loc=0x1600
117         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
118
119         $SHOW_NAMESPACE || error "Fail to monitor LFSCK (3)"
120
121         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
122         [ "$STATUS" == "scanning-phase1" ] ||
123                 error "(4) Expect 'scanning-phase1', but got '$STATUS'"
124
125         $STOP_LFSCK || error "(5) Fail to stop LFSCK!"
126
127         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
128         [ "$STATUS" == "stopped" ] ||
129                 error "(6) Expect 'stopped', but got '$STATUS'"
130
131         $START_NAMESPACE || error "(7) Fail to start LFSCK for namespace!"
132
133         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
134         [ "$STATUS" == "scanning-phase1" ] ||
135                 error "(8) Expect 'scanning-phase1', but got '$STATUS'"
136
137         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
138         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
139                 mdd.${MDT_DEV}.lfsck_namespace |
140                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
141                 $SHOW_NAMESPACE
142                 error "(9) unexpected status"
143         }
144
145         local repaired=$($SHOW_NAMESPACE |
146                          awk '/^updated_phase1/ { print $2 }')
147         [ $repaired -eq 0 ] ||
148                 error "(10) Expect nothing to be repaired, but got: $repaired"
149
150         local scanned1=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
151         $START_NAMESPACE -r || error "(11) Fail to reset LFSCK!"
152         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
153                 mdd.${MDT_DEV}.lfsck_namespace |
154                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
155                 $SHOW_NAMESPACE
156                 error "(12) unexpected status"
157         }
158
159         local scanned2=$($SHOW_NAMESPACE | awk '/^success_count/ { print $2 }')
160         [ $((scanned1 + 1)) -eq $scanned2 ] ||
161                 error "(13) Expect success $((scanned1 + 1)), but got $scanned2"
162
163         echo "stopall, should NOT crash LU-3649"
164         stopall || error "(14) Fail to stopall"
165 }
166 run_test 0 "Control LFSCK manually"
167
168 test_1a() {
169         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
170                 skip "OI Scrub not implemented for ZFS" && return
171
172         lfsck_prep 1 1
173
174         #define OBD_FAIL_FID_INDIR      0x1501
175         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1501
176         touch $DIR/$tdir/dummy
177
178         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
179         umount_client $MOUNT
180         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
181         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
182                 mdd.${MDT_DEV}.lfsck_namespace |
183                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
184                 $SHOW_NAMESPACE
185                 error "(4) unexpected status"
186         }
187
188         local repaired=$($SHOW_NAMESPACE |
189                          awk '/^dirent_repaired/ { print $2 }')
190         # for interop with old server
191         [ -z "$repaired" ] &&
192                 repaired=$($SHOW_NAMESPACE |
193                          awk '/^updated_phase1/ { print $2 }')
194
195         [ $repaired -eq 1 ] ||
196                 error "(5) Fail to repair crashed FID-in-dirent: $repaired"
197
198         mount_client $MOUNT || error "(6) Fail to start client!"
199
200         #define OBD_FAIL_FID_LOOKUP     0x1505
201         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
202         ls $DIR/$tdir/ > /dev/null || error "(7) no FID-in-dirent."
203
204         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
205 }
206 run_test 1a "LFSCK can find out and repair crashed FID-in-dirent"
207
208 test_1b()
209 {
210         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
211                 skip "OI Scrub not implemented for ZFS" && return
212
213         lfsck_prep 1 1
214
215         #define OBD_FAIL_FID_INLMA      0x1502
216         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1502
217         touch $DIR/$tdir/dummy
218
219         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
220         umount_client $MOUNT
221         #define OBD_FAIL_FID_NOLMA      0x1506
222         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1506
223         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
224         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
225                 mdd.${MDT_DEV}.lfsck_namespace |
226                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
227                 $SHOW_NAMESPACE
228                 error "(4) unexpected status"
229         }
230
231         local repaired=$($SHOW_NAMESPACE |
232                          awk '/^dirent_repaired/ { print $2 }')
233         # for interop with old server
234         [ -z "$repaired" ] &&
235                 repaired=$($SHOW_NAMESPACE |
236                          awk '/^updated_phase1/ { print $2 }')
237
238         [ $repaired -eq 1 ] ||
239                 error "(5) Fail to repair the missing FID-in-LMA: $repaired"
240
241         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
242         mount_client $MOUNT || error "(6) Fail to start client!"
243
244         #define OBD_FAIL_FID_LOOKUP     0x1505
245         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
246         stat $DIR/$tdir/dummy > /dev/null || error "(7) no FID-in-LMA."
247
248         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
249 }
250 run_test 1b "LFSCK can find out and repair the missing FID-in-LMA"
251
252 test_2a() {
253         lfsck_prep 1 1
254
255         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
256         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
257         touch $DIR/$tdir/dummy
258
259         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
260         umount_client $MOUNT
261         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
262         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
263                 mdd.${MDT_DEV}.lfsck_namespace |
264                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
265                 $SHOW_NAMESPACE
266                 error "(4) unexpected status"
267         }
268
269         local repaired=$($SHOW_NAMESPACE |
270                          awk '/^linkea_repaired/ { print $2 }')
271         # for interop with old server
272         [ -z "$repaired" ] &&
273                 repaired=$($SHOW_NAMESPACE |
274                          awk '/^updated_phase2/ { print $2 }')
275
276         [ $repaired -eq 1 ] ||
277                 error "(5) Fail to repair crashed linkEA: $repaired"
278
279         mount_client $MOUNT || error "(6) Fail to start client!"
280
281         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
282                 error "(7) Fail to stat $DIR/$tdir/dummy"
283
284         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
285         local dummyname=$($LFS fid2path $DIR $dummyfid)
286         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
287                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
288 }
289 run_test 2a "LFSCK can find out and repair crashed linkEA entry"
290
291 test_2b()
292 {
293         lfsck_prep 1 1
294
295         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
296         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
297         touch $DIR/$tdir/dummy
298
299         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
300         umount_client $MOUNT
301         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
302         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
303                 mdd.${MDT_DEV}.lfsck_namespace |
304                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
305                 $SHOW_NAMESPACE
306                 error "(4) unexpected status"
307         }
308
309         local repaired=$($SHOW_NAMESPACE |
310                          awk '/^updated_phase2/ { print $2 }')
311         [ $repaired -eq 1 ] ||
312                 error "(5) Fail to repair crashed linkEA: $repaired"
313
314         mount_client $MOUNT || error "(6) Fail to start client!"
315
316         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
317                 error "(7) Fail to stat $DIR/$tdir/dummy"
318
319         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
320         local dummyname=$($LFS fid2path $DIR $dummyfid)
321         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
322                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
323 }
324 run_test 2b "LFSCK can find out and remove invalid linkEA entry"
325
326 test_2c()
327 {
328         lfsck_prep 1 1
329
330         #define OBD_FAIL_LFSCK_LINKEA_MORE2     0x1605
331         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1605
332         touch $DIR/$tdir/dummy
333
334         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
335         umount_client $MOUNT
336         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
337         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
338                 mdd.${MDT_DEV}.lfsck_namespace |
339                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
340                 $SHOW_NAMESPACE
341                 error "(4) unexpected status"
342         }
343
344         local repaired=$($SHOW_NAMESPACE |
345                          awk '/^updated_phase2/ { print $2 }')
346         [ $repaired -eq 1 ] ||
347                 error "(5) Fail to repair crashed linkEA: $repaired"
348
349         mount_client $MOUNT || error "(6) Fail to start client!"
350
351         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
352                 error "(7) Fail to stat $DIR/$tdir/dummy"
353
354         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
355         local dummyname=$($LFS fid2path $DIR $dummyfid)
356         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
357                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
358 }
359 run_test 2c "LFSCK can find out and remove repeated linkEA entry"
360
361 test_2d()
362 {
363         lfsck_prep 1 1
364
365         #define OBD_FAIL_LFSCK_NO_LINKEA        0x161d
366         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161d
367         touch $DIR/$tdir/dummy
368
369         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
370         umount_client $MOUNT
371         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
372         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
373                 mdd.${MDT_DEV}.lfsck_namespace |
374                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
375                 $SHOW_NAMESPACE
376                 error "(4) unexpected status"
377         }
378
379         local repaired=$($SHOW_NAMESPACE |
380                          awk '/^linkea_repaired/ { print $2 }')
381         [ $repaired -eq 1 ] ||
382                 error "(5) Fail to repair crashed linkEA: $repaired"
383
384         mount_client $MOUNT || error "(6) Fail to start client!"
385
386         stat $DIR/$tdir/dummy | grep "Links: 1" > /dev/null ||
387                 error "(7) Fail to stat $DIR/$tdir/dummy"
388
389         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
390         local dummyname=$($LFS fid2path $DIR $dummyfid)
391         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
392                 error "(8) Fail to repair linkEA: $dummyfid $dummyname"
393 }
394 run_test 2d "LFSCK can recover the missing linkEA entry"
395
396 test_2e()
397 {
398         [ $MDSCOUNT -lt 2 ] &&
399                 skip "We need at least 2 MDSes for this test" && return
400
401         check_mount_and_prep
402
403         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT1"
404
405         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
406         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
407         $LFS mkdir -i 0 $DIR/$tdir/d0/d1 || error "(2) Fail to mkdir d1 on MDT0"
408         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
409
410         $START_NAMESPACE -r -A || error "(3) Fail to start LFSCK for namespace!"
411         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
412                 mdd.${MDT_DEV}.lfsck_namespace |
413                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
414                 $SHOW_NAMESPACE
415                 error "(4) unexpected status"
416         }
417
418         local repaired=$($SHOW_NAMESPACE |
419                          awk '/^linkea_repaired/ { print $2 }')
420         [ $repaired -eq 1 ] ||
421                 error "(5) Fail to repair crashed linkEA: $repaired"
422
423         local fid=$($LFS path2fid $DIR/$tdir/d0/d1)
424         local name=$($LFS fid2path $DIR $fid)
425         [ "$name" == "$DIR/$tdir/d0/d1" ] ||
426                 error "(6) Fail to repair linkEA: $fid $name"
427 }
428 run_test 2e "namespace LFSCK can verify remote object linkEA"
429
430 test_3()
431 {
432         lfsck_prep 4 4
433
434         mkdir $DIR/$tdir/dummy || error "(1) Fail to mkdir"
435         ln $DIR/$tdir/d0/f0 $DIR/$tdir/dummy/f0 || error "(2) Fail to hardlink"
436         ln $DIR/$tdir/d0/f1 $DIR/$tdir/dummy/f1 || error "(3) Fail to hardlink"
437
438         $LFS mkdir -i 0 $DIR/$tdir/edir || error "(4) Fail to mkdir"
439         touch $DIR/$tdir/edir/f0 || error "(5) Fail to touch"
440         touch $DIR/$tdir/edir/f1 || error "(6) Fail to touch"
441
442         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
443         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
444         ln $DIR/$tdir/edir/f0 $DIR/$tdir/edir/w0 || error "(7) Fail to hardlink"
445
446         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
447         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
448         ln $DIR/$tdir/edir/f1 $DIR/$tdir/edir/w1 || error "(8) Fail to hardlink"
449
450         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
451
452         $START_NAMESPACE -r || error "(9) Fail to start LFSCK for namespace!"
453         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
454                 mdd.${MDT_DEV}.lfsck_namespace |
455                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
456                 $SHOW_NAMESPACE
457                 error "(10) unexpected status"
458         }
459
460         local checked=$($SHOW_NAMESPACE |
461                         awk '/^checked_phase2/ { print $2 }')
462         [ $checked -ge 4 ] ||
463                 error "(11) Fail to check multiple-linked object: $checked"
464
465         local repaired=$($SHOW_NAMESPACE |
466                          awk '/^multiple_linked_repaired/ { print $2 }')
467         [ $repaired -ge 2 ] ||
468                 error "(12) Fail to repair multiple-linked object: $repaired"
469 }
470 run_test 3 "LFSCK can verify multiple-linked objects"
471
472 test_4()
473 {
474         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
475                 skip "OI Scrub not implemented for ZFS" && return
476
477         lfsck_prep 3 3
478         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
479         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
480
481         mds_backup_restore $SINGLEMDS || error "(1) Fail to backup/restore!"
482         echo "start $SINGLEMDS with disabling OI scrub"
483         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
484                 error "(2) Fail to start MDS!"
485
486         #define OBD_FAIL_LFSCK_DELAY2           0x1601
487         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
488         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
489         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
490                 mdd.${MDT_DEV}.lfsck_namespace |
491                 awk '/^flags/ { print \\\$2 }'" "inconsistent" 32 || {
492                 $SHOW_NAMESPACE
493                 error "(5) unexpected status"
494         }
495
496         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
497         [ "$STATUS" == "scanning-phase1" ] ||
498                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
499
500         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
501         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
502                 mdd.${MDT_DEV}.lfsck_namespace |
503                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
504                 $SHOW_NAMESPACE
505                 error "(7) unexpected status"
506         }
507
508         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
509         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
510
511         local repaired=$($SHOW_NAMESPACE |
512                          awk '/^dirent_repaired/ { print $2 }')
513         # for interop with old server
514         [ -z "$repaired" ] &&
515                 repaired=$($SHOW_NAMESPACE |
516                          awk '/^updated_phase1/ { print $2 }')
517
518         [ $repaired -ge 9 ] ||
519                 error "(9) Fail to re-generate FID-in-dirent: $repaired"
520
521         mount_client $MOUNT || error "(10) Fail to start client!"
522
523         #define OBD_FAIL_FID_LOOKUP     0x1505
524         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
525         ls $DIR/$tdir/ > /dev/null || error "(11) no FID-in-dirent."
526         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
527 }
528 run_test 4 "FID-in-dirent can be rebuilt after MDT file-level backup/restore"
529
530 test_5()
531 {
532         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
533                 skip "OI Scrub not implemented for ZFS" && return
534
535         lfsck_prep 1 1 1
536         cleanup_mount $MOUNT || error "(0.1) Fail to stop client!"
537         stop $SINGLEMDS > /dev/null || error "(0.2) Fail to stop MDS!"
538
539         mds_backup_restore $SINGLEMDS 1 || error "(1) Fail to backup/restore!"
540         echo "start $SINGLEMDS with disabling OI scrub"
541         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
542                 error "(2) Fail to start MDS!"
543
544         #define OBD_FAIL_LFSCK_DELAY2           0x1601
545         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
546         $START_NAMESPACE -r || error "(4) Fail to start LFSCK for namespace!"
547         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
548                 mdd.${MDT_DEV}.lfsck_namespace |
549                 awk '/^flags/ { print \\\$2 }'" "inconsistent,upgrade" 32 || {
550                 $SHOW_NAMESPACE
551                 error "(5) unexpected status"
552         }
553
554         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
555         [ "$STATUS" == "scanning-phase1" ] ||
556                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
557
558         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
559         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
560                 mdd.${MDT_DEV}.lfsck_namespace |
561                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
562                 $SHOW_NAMESPACE
563                 error "(7) unexpected status"
564         }
565
566         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
567         [ -z "$FLAGS" ] || error "(8) Expect empty flags, but got '$FLAGS'"
568
569         local repaired=$($SHOW_NAMESPACE |
570                          awk '/^dirent_repaired/ { print $2 }')
571         # for interop with old server
572         [ -z "$repaired" ] &&
573                 repaired=$($SHOW_NAMESPACE |
574                          awk '/^updated_phase1/ { print $2 }')
575
576         [ $repaired -ge 2 ] ||
577                 error "(9) Fail to generate FID-in-dirent for IGIF: $repaired"
578
579         mount_client $MOUNT || error "(10) Fail to start client!"
580
581         #define OBD_FAIL_FID_LOOKUP     0x1505
582         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1505
583         stat $DIR/$tdir/dummy > /dev/null || error "(11) no FID-in-LMA."
584
585         ls $DIR/$tdir/ > /dev/null || error "(12) no FID-in-dirent."
586
587         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
588         local dummyfid=$($LFS path2fid $DIR/$tdir/dummy)
589         local dummyname=$($LFS fid2path $DIR $dummyfid)
590         [ "$dummyname" == "$DIR/$tdir/dummy" ] ||
591                 error "(13) Fail to generate linkEA: $dummyfid $dummyname"
592 }
593 run_test 5 "LFSCK can handle IGIF object upgrading"
594
595 test_6a() {
596         lfsck_prep 5 5
597
598         #define OBD_FAIL_LFSCK_DELAY1           0x1600
599         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
600         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
601
602         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
603         [ "$STATUS" == "scanning-phase1" ] ||
604                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
605
606         # Sleep 3 sec to guarantee at least one object processed by LFSCK
607         sleep 3
608         # Fail the LFSCK to guarantee there is at least one checkpoint
609         #define OBD_FAIL_LFSCK_FATAL1           0x1608
610         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001608
611         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
612                 mdd.${MDT_DEV}.lfsck_namespace |
613                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
614                 $SHOW_NAMESPACE
615                 error "(4) unexpected status"
616         }
617
618         local POS0=$($SHOW_NAMESPACE |
619                      awk '/^last_checkpoint_position/ { print $2 }' |
620                      tr -d ',')
621
622         #define OBD_FAIL_LFSCK_DELAY1           0x1600
623         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1600
624         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
625
626         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
627         [ "$STATUS" == "scanning-phase1" ] ||
628                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
629
630         local POS1=$($SHOW_NAMESPACE |
631                      awk '/^latest_start_position/ { print $2 }' |
632                      tr -d ',')
633         [[ $POS0 -lt $POS1 ]] ||
634                 error "(7) Expect larger than: $POS0, but got $POS1"
635
636         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
637         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
638                 mdd.${MDT_DEV}.lfsck_namespace |
639                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
640                 $SHOW_NAMESPACE
641                 error "(8) unexpected status"
642         }
643 }
644 run_test 6a "LFSCK resumes from last checkpoint (1)"
645
646 test_6b() {
647         lfsck_prep 5 5
648
649         #define OBD_FAIL_LFSCK_DELAY2           0x1601
650         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
651         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
652
653         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
654         [ "$STATUS" == "scanning-phase1" ] ||
655                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
656
657         # Sleep 5 sec to guarantee that we are in the directory scanning
658         sleep 5
659         # Fail the LFSCK to guarantee there is at least one checkpoint
660         #define OBD_FAIL_LFSCK_FATAL2           0x1609
661         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
662         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
663                 mdd.${MDT_DEV}.lfsck_namespace |
664                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
665                 $SHOW_NAMESPACE
666                 error "(4) unexpected status"
667         }
668
669         local O_POS0=$($SHOW_NAMESPACE |
670                        awk '/^last_checkpoint_position/ { print $2 }' |
671                        tr -d ',')
672
673         local D_POS0=$($SHOW_NAMESPACE |
674                        awk '/^last_checkpoint_position/ { print $4 }')
675
676         #define OBD_FAIL_LFSCK_DELAY2           0x1601
677         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
678         $START_NAMESPACE || error "(5) Fail to start LFSCK for namespace!"
679
680         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
681         [ "$STATUS" == "scanning-phase1" ] ||
682                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
683
684         local O_POS1=$($SHOW_NAMESPACE |
685                        awk '/^latest_start_position/ { print $2 }' |
686                        tr -d ',')
687         local D_POS1=$($SHOW_NAMESPACE |
688                        awk '/^latest_start_position/ { print $4 }')
689
690         if [ "$D_POS0" == "N/A" -o "$D_POS1" == "N/A" ]; then
691                 [[ $O_POS0 -lt $O_POS1 ]] ||
692                         error "(7.1) $O_POS1 is not larger than $O_POS0"
693         else
694                 [[ $D_POS0 -lt $D_POS1 ]] ||
695                         error "(7.2) $D_POS1 is not larger than $D_POS0"
696         fi
697
698         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
699         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
700                 mdd.${MDT_DEV}.lfsck_namespace |
701                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
702                 $SHOW_NAMESPACE
703                 error "(8) unexpected status"
704         }
705 }
706 run_test 6b "LFSCK resumes from last checkpoint (2)"
707
708 test_7a()
709 {
710         lfsck_prep 5 5
711         umount_client $MOUNT
712
713         #define OBD_FAIL_LFSCK_DELAY2           0x1601
714         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1601
715         $START_NAMESPACE -r || error "(2) Fail to start LFSCK for namespace!"
716
717         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
718         [ "$STATUS" == "scanning-phase1" ] ||
719                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
720
721         # Sleep 3 sec to guarantee at least one object processed by LFSCK
722         sleep 3
723         echo "stop $SINGLEMDS"
724         stop $SINGLEMDS > /dev/null || error "(4) Fail to stop MDS!"
725
726         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
727         echo "start $SINGLEMDS"
728         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
729                 error "(5) Fail to start MDS!"
730
731         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
732                 mdd.${MDT_DEV}.lfsck_namespace |
733                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
734                 $SHOW_NAMESPACE
735                 error "(6) unexpected status"
736         }
737 }
738 run_test 7a "non-stopped LFSCK should auto restarts after MDS remount (1)"
739
740 test_7b()
741 {
742         lfsck_prep 2 2
743
744         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
745         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
746         for ((i = 0; i < 20; i++)); do
747                 touch $DIR/$tdir/dummy${i}
748         done
749
750         #define OBD_FAIL_LFSCK_DELAY3           0x1602
751         do_facet $SINGLEMDS $LCTL set_param fail_val=1 fail_loc=0x1602
752         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace!"
753         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
754                 mdd.${MDT_DEV}.lfsck_namespace |
755                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 32 || {
756                 $SHOW_NAMESPACE
757                 error "(4) unexpected status"
758         }
759
760         umount_client $MOUNT
761         echo "stop $SINGLEMDS"
762         stop $SINGLEMDS > /dev/null || error "(5) Fail to stop MDS!"
763
764         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
765         echo "start $SINGLEMDS"
766         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
767                 error "(6) Fail to start MDS!"
768
769         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
770                 mdd.${MDT_DEV}.lfsck_namespace |
771                 awk '/^status/ { print \\\$2 }'" "completed" 30 || {
772                 $SHOW_NAMESPACE
773                 error "(7) unexpected status"
774         }
775 }
776 run_test 7b "non-stopped LFSCK should auto restarts after MDS remount (2)"
777
778 test_8()
779 {
780         echo "formatall"
781         formatall > /dev/null
782         echo "setupall"
783         setupall > /dev/null
784
785         lfsck_prep 20 20
786
787         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
788         [ "$STATUS" == "init" ] ||
789                 error "(2) Expect 'init', but got '$STATUS'"
790
791         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
792         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
793         mkdir $DIR/$tdir/crashed
794
795         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
796         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
797         for ((i = 0; i < 5; i++)); do
798                 touch $DIR/$tdir/dummy${i}
799         done
800
801         umount_client $MOUNT || error "(3) Fail to stop client!"
802
803         #define OBD_FAIL_LFSCK_DELAY2           0x1601
804         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1601
805         $START_NAMESPACE || error "(4) Fail to start LFSCK for namespace!"
806
807         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
808         [ "$STATUS" == "scanning-phase1" ] ||
809                 error "(5) Expect 'scanning-phase1', but got '$STATUS'"
810
811         $STOP_LFSCK || error "(6) Fail to stop LFSCK!"
812
813         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
814         [ "$STATUS" == "stopped" ] ||
815                 error "(7) Expect 'stopped', but got '$STATUS'"
816
817         $START_NAMESPACE || error "(8) Fail to start LFSCK for namespace!"
818
819         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
820         [ "$STATUS" == "scanning-phase1" ] ||
821                 error "(9) Expect 'scanning-phase1', but got '$STATUS'"
822
823         #define OBD_FAIL_LFSCK_FATAL2           0x1609
824         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001609
825         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
826                 mdd.${MDT_DEV}.lfsck_namespace |
827                 awk '/^status/ { print \\\$2 }'" "failed" 32 || {
828                 $SHOW_NAMESPACE
829                 error "(10) unexpected status"
830         }
831
832         #define OBD_FAIL_LFSCK_DELAY1           0x1600
833         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1600
834         $START_NAMESPACE || error "(11) Fail to start LFSCK for namespace!"
835
836         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
837         [ "$STATUS" == "scanning-phase1" ] ||
838                 error "(12) Expect 'scanning-phase1', but got '$STATUS'"
839
840         #define OBD_FAIL_LFSCK_CRASH            0x160a
841         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160a
842         sleep 5
843
844         echo "stop $SINGLEMDS"
845         stop $SINGLEMDS > /dev/null || error "(13) Fail to stop MDS!"
846
847         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
848         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
849
850         echo "start $SINGLEMDS"
851         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
852                 error "(14) Fail to start MDS!"
853
854         local timeout=$(max_recovery_time)
855         local timer=0
856
857         while [ $timer -lt $timeout ]; do
858                 STATUS=$(do_facet $SINGLEMDS "$LCTL get_param -n \
859                         mdt.${MDT_DEV}.recovery_status |
860                         awk '/^status/ { print \\\$2 }'")
861                 [ "$STATUS" != "RECOVERING" ] && break;
862                 sleep 1
863                 timer=$((timer + 1))
864         done
865
866         [ $timer != $timeout ] ||
867                 error "(14.1) recovery timeout"
868
869         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
870         [ "$STATUS" == "crashed" ] ||
871                 error "(15) Expect 'crashed', but got '$STATUS'"
872
873         #define OBD_FAIL_LFSCK_DELAY2           0x1601
874         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1601
875         $START_NAMESPACE || error "(16) Fail to start LFSCK for namespace!"
876
877         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
878         [ "$STATUS" == "scanning-phase1" ] ||
879                 error "(17) Expect 'scanning-phase1', but got '$STATUS'"
880
881         echo "stop $SINGLEMDS"
882         stop $SINGLEMDS > /dev/null || error "(18) Fail to stop MDS!"
883
884         #define OBD_FAIL_LFSCK_NO_AUTO          0x160b
885         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160b
886
887         echo "start $SINGLEMDS"
888         start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
889                 error "(19) Fail to start MDS!"
890
891         timer=0
892         while [ $timer -lt $timeout ]; do
893                 STATUS=$(do_facet $SINGLEMDS "$LCTL get_param -n \
894                         mdt.${MDT_DEV}.recovery_status |
895                         awk '/^status/ { print \\\$2 }'")
896                 [ "$STATUS" != "RECOVERING" ] && break;
897                 sleep 1
898                 timer=$((timer + 1))
899         done
900
901         [ $timer != $timeout ] ||
902                 error "(19.1) recovery timeout"
903
904         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
905         [ "$STATUS" == "paused" ] ||
906                 error "(20) Expect 'paused', but got '$STATUS'"
907
908         #define OBD_FAIL_LFSCK_DELAY3           0x1602
909         do_facet $SINGLEMDS $LCTL set_param fail_val=2 fail_loc=0x1602
910
911         $START_NAMESPACE || error "(21) Fail to start LFSCK for namespace!"
912         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
913                 mdd.${MDT_DEV}.lfsck_namespace |
914                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" 32 || {
915                 $SHOW_NAMESPACE
916                 error "(22) unexpected status"
917         }
918
919         local FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
920         [ "$FLAGS" == "scanned-once,inconsistent" ] ||
921                 error "(23) Expect 'scanned-once,inconsistent',but got '$FLAGS'"
922
923         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
924         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
925                 mdd.${MDT_DEV}.lfsck_namespace |
926                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
927                 $SHOW_NAMESPACE
928                 error "(24) unexpected status"
929         }
930
931         FLAGS=$($SHOW_NAMESPACE | awk '/^flags/ { print $2 }')
932         [ -z "$FLAGS" ] || error "(25) Expect empty flags, but got '$FLAGS'"
933 }
934 run_test 8 "LFSCK state machine"
935
936 test_9a() {
937         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
938                 skip "Testing on UP system, the speed may be inaccurate."
939                 return 0
940         fi
941
942         check_mount_and_prep
943         $LFS mkdir -i 0 $DIR/$tdir/lfsck || error "(1) Fail to mkdir lfsck"
944         $LFS setstripe -c 1 -i -1 $DIR/$tdir/lfsck
945         createmany -o $DIR/$tdir/lfsck/f 5000
946
947         local BASE_SPEED1=100
948         local RUN_TIME1=10
949         $START_LAYOUT -r -s $BASE_SPEED1 || error "(2) Fail to start LFSCK!"
950
951         sleep $RUN_TIME1
952         STATUS=$($SHOW_LAYOUT | awk '/^status/ { print $2 }')
953         [ "$STATUS" == "scanning-phase1" ] ||
954                 error "(3) Expect 'scanning-phase1', but got '$STATUS'"
955
956         local SPEED=$($SHOW_LAYOUT |
957                       awk '/^average_speed_phase1/ { print $2 }')
958
959         # There may be time error, normally it should be less than 2 seconds.
960         # We allow another 20% schedule error.
961         local TIME_DIFF=2
962         # MAX_MARGIN = 1.2 = 12 / 10
963         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
964                            RUN_TIME1 * 12 / 10))
965         [ $SPEED -lt $MAX_SPEED ] ||
966                 error "(4) Got speed $SPEED, expected less than $MAX_SPEED"
967
968         # adjust speed limit
969         local BASE_SPEED2=300
970         local RUN_TIME2=10
971         do_facet $SINGLEMDS \
972                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
973         sleep $RUN_TIME2
974
975         SPEED=$($SHOW_LAYOUT | awk '/^average_speed_phase1/ { print $2 }')
976         # MIN_MARGIN = 0.8 = 8 / 10
977         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
978                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
979                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
980         [ $SPEED -gt $MIN_SPEED ] || {
981                 if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
982                         error_ignore LU-5624 \
983                         "(5.1) Got speed $SPEED, expected more than $MIN_SPEED"
984                 else
985                         error \
986                         "(5.2) Got speed $SPEED, expected more than $MIN_SPEED"
987                 fi
988         }
989
990         # MAX_MARGIN = 1.2 = 12 / 10
991         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
992                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
993                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
994         [ $SPEED -lt $MAX_SPEED ] ||
995                 error "(6) Got speed $SPEED, expected less than $MAX_SPEED"
996
997         do_facet $SINGLEMDS \
998                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
999
1000         wait_update_facet $SINGLEMDS \
1001                 "$LCTL get_param -n mdd.${MDT_DEV}.lfsck_layout |
1002                 awk '/^status/ { print \\\$2 }'" "completed" 30 ||
1003                 error "(7) Failed to get expected 'completed'"
1004 }
1005 run_test 9a "LFSCK speed control (1)"
1006
1007 test_9b() {
1008         if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
1009                 skip "Testing on UP system, the speed may be inaccurate."
1010                 return 0
1011         fi
1012
1013         lfsck_prep 0 0
1014
1015         echo "Preparing another 50 * 50 files (with error) at $(date)."
1016         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
1017         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
1018         createmany -d $DIR/$tdir/d 50
1019         createmany -m $DIR/$tdir/f 50
1020         for ((i = 0; i < 50; i++)); do
1021                 createmany -m $DIR/$tdir/d${i}/f 50 > /dev/null
1022         done
1023
1024         #define OBD_FAIL_LFSCK_NO_DOUBLESCAN    0x160c
1025         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160c
1026         $START_NAMESPACE -r || error "(4) Fail to start LFSCK!"
1027         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1028                 mdd.${MDT_DEV}.lfsck_namespace |
1029                 awk '/^status/ { print \\\$2 }'" "stopped" 10 || {
1030                 $SHOW_NAMESPACE
1031                 error "(5) unexpected status"
1032         }
1033
1034         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1035         echo "Prepared at $(date)."
1036
1037         local BASE_SPEED1=50
1038         local RUN_TIME1=10
1039         $START_NAMESPACE -s $BASE_SPEED1 || error "(6) Fail to start LFSCK!"
1040
1041         sleep $RUN_TIME1
1042         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1043         [ "$STATUS" == "scanning-phase2" ] ||
1044                 error "(7) Expect 'scanning-phase2', but got '$STATUS'"
1045
1046         local SPEED=$($SHOW_NAMESPACE |
1047                       awk '/^average_speed_phase2/ { print $2 }')
1048         # There may be time error, normally it should be less than 2 seconds.
1049         # We allow another 20% schedule error.
1050         local TIME_DIFF=2
1051         # MAX_MARGIN = 1.2 = 12 / 10
1052         local MAX_SPEED=$((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) / \
1053                           RUN_TIME1 * 12 / 10))
1054         [ $SPEED -lt $MAX_SPEED ] ||
1055                 error "(8) Got speed $SPEED, expected less than $MAX_SPEED"
1056
1057         # adjust speed limit
1058         local BASE_SPEED2=150
1059         local RUN_TIME2=10
1060         do_facet $SINGLEMDS \
1061                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit $BASE_SPEED2
1062         sleep $RUN_TIME2
1063
1064         SPEED=$($SHOW_NAMESPACE | awk '/^average_speed_phase2/ { print $2 }')
1065         # MIN_MARGIN = 0.8 = 8 / 10
1066         local MIN_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
1067                             BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
1068                            (RUN_TIME1 + RUN_TIME2) * 8 / 10))
1069         [ $SPEED -gt $MIN_SPEED ] || {
1070                 if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
1071                         error_ignore LU-5624 \
1072                         "(9.1) Got speed $SPEED, expected more than $MIN_SPEED"
1073                 else
1074                         error \
1075                         "(9.2) Got speed $SPEED, expected more than $MIN_SPEED"
1076                 fi
1077         }
1078
1079         # MAX_MARGIN = 1.2 = 12 / 10
1080         MAX_SPEED=$(((BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
1081                       BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
1082                      (RUN_TIME1 + RUN_TIME2) * 12 / 10))
1083         [ $SPEED -lt $MAX_SPEED ] ||
1084                 error "(10) Got speed $SPEED, expected less than $MAX_SPEED"
1085
1086         do_facet $SINGLEMDS \
1087                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
1088         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1089                 mdd.${MDT_DEV}.lfsck_namespace |
1090                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1091                 $SHOW_NAMESPACE
1092                 error "(11) unexpected status"
1093         }
1094 }
1095 run_test 9b "LFSCK speed control (2)"
1096
1097 test_10()
1098 {
1099         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
1100                 skip "lookup(..)/linkea on ZFS issue" && return
1101
1102         lfsck_prep 1 1
1103
1104         echo "Preparing more files with error at $(date)."
1105         #define OBD_FAIL_LFSCK_LINKEA_CRASH     0x1603
1106         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1603
1107
1108         for ((i = 0; i < 1000; i = $((i+2)))); do
1109                 mkdir -p $DIR/$tdir/d${i}
1110                 touch $DIR/$tdir/f${i}
1111                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
1112         done
1113
1114         #define OBD_FAIL_LFSCK_LINKEA_MORE      0x1604
1115         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1604
1116
1117         for ((i = 1; i < 1000; i = $((i+2)))); do
1118                 mkdir -p $DIR/$tdir/d${i}
1119                 touch $DIR/$tdir/f${i}
1120                 createmany -m $DIR/$tdir/d${i}/f 5 > /dev/null
1121         done
1122
1123         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1124         echo "Prepared at $(date)."
1125
1126         ln $DIR/$tdir/f200 $DIR/$tdir/d200/dummy
1127
1128         umount_client $MOUNT
1129         mount_client $MOUNT || error "(3) Fail to start client!"
1130
1131         $START_NAMESPACE -r -s 100 || error "(5) Fail to start LFSCK!"
1132
1133         sleep 10
1134         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1135         [ "$STATUS" == "scanning-phase1" ] ||
1136                 error "(6) Expect 'scanning-phase1', but got '$STATUS'"
1137
1138         ls -ailR $MOUNT > /dev/null || error "(7) Fail to ls!"
1139
1140         touch $DIR/$tdir/d198/a0 || error "(8) Fail to touch!"
1141
1142         mkdir $DIR/$tdir/d199/a1 || error "(9) Fail to mkdir!"
1143
1144         unlink $DIR/$tdir/f200 || error "(10) Fail to unlink!"
1145
1146         rm -rf $DIR/$tdir/d201 || error "(11) Fail to rmdir!"
1147
1148         mv $DIR/$tdir/f202 $DIR/$tdir/d203/ || error "(12) Fail to rename!"
1149
1150         ln $DIR/$tdir/f204 $DIR/$tdir/d205/a3 || error "(13) Fail to hardlink!"
1151
1152         ln -s $DIR/$tdir/d206 $DIR/$tdir/d207/a4 ||
1153                 error "(14) Fail to softlink!"
1154
1155         STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
1156         [ "$STATUS" == "scanning-phase1" ] ||
1157                 error "(15) Expect 'scanning-phase1', but got '$STATUS'"
1158
1159         do_facet $SINGLEMDS \
1160                 $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0
1161         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1162                 mdd.${MDT_DEV}.lfsck_namespace |
1163                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1164                 $SHOW_NAMESPACE
1165                 error "(16) unexpected status"
1166         }
1167 }
1168 run_test 10 "System is available during LFSCK scanning"
1169
1170 # remove LAST_ID
1171 ost_remove_lastid() {
1172         local ost=$1
1173         local idx=$2
1174         local rcmd="do_facet ost${ost}"
1175
1176         echo "remove LAST_ID on ost${ost}: idx=${idx}"
1177
1178         # step 1: local mount
1179         mount_fstype ost${ost} || return 1
1180         # step 2: remove the specified LAST_ID
1181         ${rcmd} rm -fv $(facet_mntpt ost${ost})/O/${idx}/{LAST_ID,d0/0}
1182         # step 3: umount
1183         unmount_fstype ost${ost} || return 2
1184 }
1185
1186 test_11a() {
1187         check_mount_and_prep
1188         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1189         createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 64 files."
1190
1191         echo "stopall"
1192         stopall > /dev/null
1193
1194         ost_remove_lastid 1 0 || error "(1) Fail to remove LAST_ID"
1195
1196         start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
1197                 error "(2) Fail to start ost1"
1198
1199         #define OBD_FAIL_LFSCK_DELAY4           0x160e
1200         do_facet ost1 $LCTL set_param fail_val=3 fail_loc=0x160e
1201
1202         echo "trigger LFSCK for layout on ost1 to rebuild the LAST_ID(s)"
1203         $START_LAYOUT_ON_OST -r || error "(4) Fail to start LFSCK on OST!"
1204
1205         wait_update_facet ost1 "$LCTL get_param -n \
1206                 obdfilter.${OST_DEV}.lfsck_layout |
1207                 awk '/^flags/ { print \\\$2 }'" "crashed_lastid" 60 || {
1208                 $SHOW_LAYOUT_ON_OST
1209                 error "(5) unexpected status"
1210         }
1211
1212         do_facet ost1 $LCTL set_param fail_val=0 fail_loc=0
1213
1214         wait_update_facet ost1 "$LCTL get_param -n \
1215                 obdfilter.${OST_DEV}.lfsck_layout |
1216                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1217                 $SHOW_LAYOUT_ON_OST
1218                 error "(6) unexpected status"
1219         }
1220
1221         echo "the LAST_ID(s) should have been rebuilt"
1222         FLAGS=$($SHOW_LAYOUT_ON_OST | awk '/^flags/ { print $2 }')
1223         [ -z "$FLAGS" ] || error "(7) Expect empty flags, but got '$FLAGS'"
1224 }
1225 run_test 11a "LFSCK can rebuild lost last_id"
1226
1227 test_11b() {
1228         check_mount_and_prep
1229         $SETSTRIPE -c 1 -i 0 $DIR/$tdir
1230
1231         echo "set fail_loc=0x160d to skip the updating LAST_ID on-disk"
1232         #define OBD_FAIL_LFSCK_SKIP_LASTID      0x160d
1233         do_facet ost1 $LCTL set_param fail_loc=0x160d
1234
1235         local count=$(precreated_ost_obj_count 0 0)
1236
1237         createmany -o $DIR/$tdir/f $((count + 32))
1238
1239         local proc_path="${FSNAME}-OST0000-osc-MDT0000"
1240         local seq=$(do_facet mds1 $LCTL get_param -n \
1241                     osp.${proc_path}.prealloc_last_seq)
1242         local lastid1=$(do_facet ost1 "lctl get_param -n \
1243                 obdfilter.${ost1_svc}.last_id" | grep $seq |
1244                 awk -F: '{ print $2 }')
1245
1246         umount_client $MOUNT
1247         stop ost1 || error "(1) Fail to stop ost1"
1248
1249         #define OBD_FAIL_OST_ENOSPC              0x215
1250         do_facet ost1 $LCTL set_param fail_loc=0x215
1251
1252         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1253                 error "(2) Fail to start ost1"
1254
1255         for ((i = 0; i < 60; i++)); do
1256                 lastid2=$(do_facet ost1 "lctl get_param -n \
1257                         obdfilter.${ost1_svc}.last_id" | grep $seq |
1258                         awk -F: '{ print $2 }')
1259                 [ ! -z $lastid2 ] && break;
1260                 sleep 1
1261         done
1262
1263         echo "the on-disk LAST_ID should be smaller than the expected one"
1264         [ $lastid1 -gt $lastid2 ] ||
1265                 error "(4) expect lastid1 [ $lastid1 ] > lastid2 [ $lastid2 ]"
1266
1267         echo "trigger LFSCK for layout on ost1 to rebuild the on-disk LAST_ID"
1268         $START_LAYOUT_ON_OST -r || error "(5) Fail to start LFSCK on OST!"
1269
1270         wait_update_facet ost1 "$LCTL get_param -n \
1271                 obdfilter.${OST_DEV}.lfsck_layout |
1272                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1273                 $SHOW_LAYOUT_ON_OST
1274                 error "(6) unexpected status"
1275         }
1276
1277         stop ost1 || error "(7) Fail to stop ost1"
1278
1279         start ost1 $(ostdevname 1) $OST_MOUNT_OPTS ||
1280                 error "(8) Fail to start ost1"
1281
1282         echo "the on-disk LAST_ID should have been rebuilt"
1283         wait_update_facet ost1 "$LCTL get_param -n \
1284                 obdfilter.${ost1_svc}.last_id | grep $seq |
1285                 awk -F: '{ print \\\$2 }'" "$lastid1" 60 || {
1286                 do_facet ost1 $LCTL get_param -n \
1287                 obdfilter.${ost1_svc}.last_id
1288                 error "(9) expect lastid1 $seq:$lastid1"
1289         }
1290
1291         do_facet ost1 $LCTL set_param fail_loc=0
1292         stopall || error "(10) Fail to stopall"
1293 }
1294 run_test 11b "LFSCK can rebuild crashed last_id"
1295
1296 test_12() {
1297         [ $MDSCOUNT -lt 2 ] &&
1298                 skip "We need at least 2 MDSes for test_12" && return
1299
1300         check_mount_and_prep
1301         for k in $(seq $MDSCOUNT); do
1302                 $LFS mkdir -i $((k - 1)) $DIR/$tdir/${k}
1303                 createmany -o $DIR/$tdir/${k}/f 100 ||
1304                         error "(0) Fail to create 100 files."
1305         done
1306
1307         echo "Start namespace LFSCK on all targets by single command (-s 1)."
1308         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1309                 -s 1 -r || error "(2) Fail to start LFSCK on all devices!"
1310
1311         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1312         for k in $(seq $MDSCOUNT); do
1313                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1314                                 mdd.$(facet_svc mds${k}).lfsck_namespace |
1315                                 awk '/^status/ { print $2 }')
1316                 [ "$STATUS" == "scanning-phase1" ] ||
1317                 error "(3) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
1318         done
1319
1320         echo "Stop namespace LFSCK on all targets by single lctl command."
1321         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1322                 error "(4) Fail to stop LFSCK on all devices!"
1323
1324         echo "All the LFSCK targets should be in 'stopped' status."
1325         for k in $(seq $MDSCOUNT); do
1326                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1327                                 mdd.$(facet_svc mds${k}).lfsck_namespace |
1328                                 awk '/^status/ { print $2 }')
1329                 [ "$STATUS" == "stopped" ] ||
1330                         error "(5) MDS${k} Expect 'stopped', but got '$STATUS'"
1331         done
1332
1333         echo "Re-start namespace LFSCK on all targets by single command (-s 0)."
1334         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t namespace -A \
1335                 -s 0 -r || error "(6) Fail to start LFSCK on all devices!"
1336
1337         echo "All the LFSCK targets should be in 'completed' status."
1338         for k in $(seq $MDSCOUNT); do
1339                 wait_update_facet mds${k} "$LCTL get_param -n \
1340                         mdd.$(facet_svc mds${k}).lfsck_namespace |
1341                         awk '/^status/ { print \\\$2 }'" "completed" 8 ||
1342                         error "(7) MDS${k} is not the expected 'completed'"
1343         done
1344
1345         start_full_debug_logging
1346
1347         echo "Start layout LFSCK on all targets by single command (-s 1)."
1348         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1349                 -s 1 -r || error "(8) Fail to start LFSCK on all devices!"
1350
1351         echo "All the LFSCK targets should be in 'scanning-phase1' status."
1352         for k in $(seq $MDSCOUNT); do
1353                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1354                                 mdd.$(facet_svc mds${k}).lfsck_layout |
1355                                 awk '/^status/ { print $2 }')
1356                 [ "$STATUS" == "scanning-phase1" ] ||
1357                 error "(9) MDS${k} Expect 'scanning-phase1', but got '$STATUS'"
1358         done
1359
1360         echo "Stop layout LFSCK on all targets by single lctl command."
1361         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 -A ||
1362                 error "(10) Fail to stop LFSCK on all devices!"
1363
1364         echo "All the LFSCK targets should be in 'stopped' status."
1365         for k in $(seq $MDSCOUNT); do
1366                 local STATUS=$(do_facet mds${k} $LCTL get_param -n \
1367                                 mdd.$(facet_svc mds${k}).lfsck_layout |
1368                                 awk '/^status/ { print $2 }')
1369                 [ "$STATUS" == "stopped" ] ||
1370                         error "(11) MDS${k} Expect 'stopped', but got '$STATUS'"
1371         done
1372
1373         for k in $(seq $OSTCOUNT); do
1374                 local STATUS=$(do_facet ost${k} $LCTL get_param -n \
1375                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1376                                 awk '/^status/ { print $2 }')
1377                 [ "$STATUS" == "stopped" ] ||
1378                         error "(12) OST${k} Expect 'stopped', but got '$STATUS'"
1379         done
1380
1381         echo "Re-start layout LFSCK on all targets by single command (-s 0)."
1382         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -t layout -A \
1383                 -s 0 -r || error "(13) Fail to start LFSCK on all devices!"
1384
1385         echo "All the LFSCK targets should be in 'completed' status."
1386         for k in $(seq $MDSCOUNT); do
1387                 # The LFSCK status query internal is 30 seconds. For the case
1388                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1389                 # time to guarantee the status sync up.
1390                 wait_update_facet mds${k} "$LCTL get_param -n \
1391                         mdd.$(facet_svc mds${k}).lfsck_layout |
1392                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
1393                         error "(14) MDS${k} is not the expected 'completed'"
1394         done
1395
1396         stop_full_debug_logging
1397 }
1398 run_test 12 "single command to trigger LFSCK on all devices"
1399
1400 test_13() {
1401         echo "#####"
1402         echo "The lmm_oi in layout EA should be consistent with the MDT-object"
1403         echo "FID; otherwise, the LFSCK should re-generate the lmm_oi from the"
1404         echo "MDT-object FID."
1405         echo "#####"
1406
1407         check_mount_and_prep
1408
1409         echo "Inject failure stub to simulate bad lmm_oi"
1410         #define OBD_FAIL_LFSCK_BAD_LMMOI        0x160f
1411         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x160f
1412         createmany -o $DIR/$tdir/f 32
1413         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1414
1415         echo "Trigger layout LFSCK to find out the bad lmm_oi and fix them"
1416         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1417
1418         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1419                 mdd.${MDT_DEV}.lfsck_layout |
1420                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1421                 $SHOW_LAYOUT
1422                 error "(2) unexpected status"
1423         }
1424
1425         local repaired=$($SHOW_LAYOUT |
1426                          awk '/^repaired_others/ { print $2 }')
1427         [ $repaired -eq 32 ] ||
1428                 error "(3) Fail to repair crashed lmm_oi: $repaired"
1429 }
1430 run_test 13 "LFSCK can repair crashed lmm_oi"
1431
1432 test_14() {
1433         echo "#####"
1434         echo "The OST-object referenced by the MDT-object should be there;"
1435         echo "otherwise, the LFSCK should re-create the missing OST-object."
1436         echo "#####"
1437
1438         check_mount_and_prep
1439         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1440
1441         echo "Inject failure stub to simulate dangling referenced MDT-object"
1442         #define OBD_FAIL_LFSCK_DANGLING 0x1610
1443         do_facet ost1 $LCTL set_param fail_loc=0x1610
1444         local count=$(precreated_ost_obj_count 0 0)
1445
1446         createmany -o $DIR/$tdir/f $((count + 31))
1447         touch $DIR/$tdir/guard
1448         do_facet ost1 $LCTL set_param fail_loc=0
1449
1450         start_full_debug_logging
1451
1452         # exhaust other pre-created dangling cases
1453         count=$(precreated_ost_obj_count 0 0)
1454         createmany -o $DIR/$tdir/a $count ||
1455                 error "(0) Fail to create $count files."
1456
1457         echo "'ls' should fail because of dangling referenced MDT-object"
1458         ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(1) ls should fail."
1459
1460         echo "Trigger layout LFSCK to find out dangling reference"
1461         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1462
1463         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1464                 mdd.${MDT_DEV}.lfsck_layout |
1465                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1466                 $SHOW_LAYOUT
1467                 error "(3) unexpected status"
1468         }
1469
1470         local repaired=$($SHOW_LAYOUT |
1471                          awk '/^repaired_dangling/ { print $2 }')
1472         [ $repaired -ge 32 ] ||
1473                 error "(4) Fail to repair dangling reference: $repaired"
1474
1475         echo "'stat' should fail because of not repair dangling by default"
1476         stat $DIR/$tdir/guard > /dev/null 2>&1 && error "(5) stat should fail"
1477
1478         echo "Trigger layout LFSCK to repair dangling reference"
1479         $START_LAYOUT -r -c || error "(6) Fail to start LFSCK for layout!"
1480
1481         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1482                 mdd.${MDT_DEV}.lfsck_layout |
1483                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1484                 $SHOW_LAYOUT
1485                 error "(7) unexpected status"
1486         }
1487
1488         # There may be some async LFSCK updates in processing, wait for
1489         # a while until the target reparation has been done. LU-4970.
1490
1491         echo "'stat' should success after layout LFSCK repairing"
1492         wait_update_facet client "stat $DIR/$tdir/guard |
1493                 awk '/Size/ { print \\\$2 }'" "0" 32 || {
1494                 stat $DIR/$tdir/guard
1495                 $SHOW_LAYOUT
1496                 error "(8) unexpected size"
1497         }
1498
1499         repaired=$($SHOW_LAYOUT |
1500                          awk '/^repaired_dangling/ { print $2 }')
1501         [ $repaired -ge 32 ] ||
1502                 error "(9) Fail to repair dangling reference: $repaired"
1503
1504         stop_full_debug_logging
1505 }
1506 run_test 14 "LFSCK can repair MDT-object with dangling reference"
1507
1508 test_15a() {
1509         echo "#####"
1510         echo "If the OST-object referenced by the MDT-object back points"
1511         echo "to some non-exist MDT-object, then the LFSCK should repair"
1512         echo "the OST-object to back point to the right MDT-object."
1513         echo "#####"
1514
1515         check_mount_and_prep
1516         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1517
1518         echo "Inject failure stub to make the OST-object to back point to"
1519         echo "non-exist MDT-object."
1520         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
1521
1522         do_facet ost1 $LCTL set_param fail_loc=0x1611
1523         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1524         cancel_lru_locks osc
1525         do_facet ost1 $LCTL set_param fail_loc=0
1526
1527         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1528         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1529
1530         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1531                 mdd.${MDT_DEV}.lfsck_layout |
1532                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1533                 $SHOW_LAYOUT
1534                 error "(2) unexpected status"
1535         }
1536
1537         local repaired=$($SHOW_LAYOUT |
1538                          awk '/^repaired_unmatched_pair/ { print $2 }')
1539         [ $repaired -eq 1 ] ||
1540                 error "(3) Fail to repair unmatched pair: $repaired"
1541 }
1542 run_test 15a "LFSCK can repair unmatched MDT-object/OST-object pairs (1)"
1543
1544 test_15b() {
1545         echo "#####"
1546         echo "If the OST-object referenced by the MDT-object back points"
1547         echo "to other MDT-object that doesn't recognize the OST-object,"
1548         echo "then the LFSCK should repair it to back point to the right"
1549         echo "MDT-object (the first one)."
1550         echo "#####"
1551
1552         check_mount_and_prep
1553         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1554         dd if=/dev/zero of=$DIR/$tdir/guard bs=1M count=1
1555         cancel_lru_locks osc
1556
1557         echo "Inject failure stub to make the OST-object to back point to"
1558         echo "other MDT-object"
1559
1560         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR2  0x1612
1561         do_facet ost1 $LCTL set_param fail_loc=0x1612
1562         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1563         cancel_lru_locks osc
1564         do_facet ost1 $LCTL set_param fail_loc=0
1565
1566         echo "Trigger layout LFSCK to find out unmatched pairs and fix them"
1567         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1568
1569         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1570                 mdd.${MDT_DEV}.lfsck_layout |
1571                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1572                 $SHOW_LAYOUT
1573                 error "(2) unexpected status"
1574         }
1575
1576         local repaired=$($SHOW_LAYOUT |
1577                          awk '/^repaired_unmatched_pair/ { print $2 }')
1578         [ $repaired -eq 1 ] ||
1579                 error "(3) Fail to repair unmatched pair: $repaired"
1580 }
1581 run_test 15b "LFSCK can repair unmatched MDT-object/OST-object pairs (2)"
1582
1583 test_15c() {
1584         [ $MDSCOUNT -lt 2 ] &&
1585                 skip "We need at least 2 MDSes for this test" && return
1586
1587         echo "#####"
1588         echo "According to current metadata migration implementation,"
1589         echo "before the old MDT-object is removed, both the new MDT-object"
1590         echo "and old MDT-object will reference the same LOV layout. Then if"
1591         echo "the layout LFSCK finds the new MDT-object by race, it will"
1592         echo "regard related OST-object(s) as multiple referenced case, and"
1593         echo "will try to create new OST-object(s) for the new MDT-object."
1594         echo "To avoid such trouble, the layout LFSCK needs to lock the old"
1595         echo "MDT-object before confirm the multiple referenced case."
1596         echo "#####"
1597
1598         check_mount_and_prep
1599         $LFS mkdir -i 1 $DIR/$tdir/a1
1600         $LFS setstripe -c 1 -i 0 $DIR/$tdir/a1
1601         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=1
1602         cancel_lru_locks osc
1603
1604         echo "Inject failure stub on MDT1 to delay the migration"
1605
1606         #define OBD_FAIL_MIGRATE_DELAY                  0x1803
1607         do_facet mds2 $LCTL set_param fail_val=5 fail_loc=0x1803
1608         echo "Migrate $DIR/$tdir/a1 from MDT1 to MDT0 with delay"
1609         $LFS mv -M 0 $DIR/$tdir/a1 &
1610
1611         sleep 1
1612         echo "Trigger layout LFSCK to race with the migration"
1613         $START_LAYOUT -A -r || error "(1) Fail to start layout LFSCK!"
1614
1615         for k in $(seq $MDSCOUNT); do
1616                 # The LFSCK status query internal is 30 seconds. For the case
1617                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1618                 # time to guarantee the status sync up.
1619                 wait_update_facet mds${k} "$LCTL get_param -n \
1620                         mdd.$(facet_svc mds${k}).lfsck_layout |
1621                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
1622                         error "(2) MDS${k} is not the expected 'completed'"
1623         done
1624
1625         do_facet mds2 $LCTL set_param fail_loc=0 fail_val=0
1626         local repaired=$($SHOW_LAYOUT |
1627                          awk '/^repaired_unmatched_pair/ { print $2 }')
1628         [ $repaired -eq 1 ] ||
1629                 error "(3) Fail to repair unmatched pair: $repaired"
1630
1631         repaired=$($SHOW_LAYOUT |
1632                    awk '/^repaired_multiple_referenced/ { print $2 }')
1633         [ $repaired -eq 0 ] ||
1634                 error "(4) Unexpectedly repaird multiple references: $repaired"
1635 }
1636 run_test 15c "LFSCK can repair unmatched MDT-object/OST-object pairs (3)"
1637
1638 test_16() {
1639         echo "#####"
1640         echo "If the OST-object's owner information does not match the owner"
1641         echo "information stored in the MDT-object, then the LFSCK trust the"
1642         echo "MDT-object and update the OST-object's owner information."
1643         echo "#####"
1644
1645         check_mount_and_prep
1646         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1647         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=1
1648         cancel_lru_locks osc
1649
1650         echo "Inject failure stub to skip OST-object owner changing"
1651         #define OBD_FAIL_LFSCK_BAD_OWNER        0x1613
1652         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1613
1653         chown 1.1 $DIR/$tdir/f0
1654         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
1655
1656         echo "Trigger layout LFSCK to find out inconsistent OST-object owner"
1657         echo "and fix them"
1658
1659         $START_LAYOUT -r || error "(1) Fail to start LFSCK for layout!"
1660
1661         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1662                 mdd.${MDT_DEV}.lfsck_layout |
1663                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1664                 $SHOW_LAYOUT
1665                 error "(2) unexpected status"
1666         }
1667
1668         local repaired=$($SHOW_LAYOUT |
1669                          awk '/^repaired_inconsistent_owner/ { print $2 }')
1670         [ $repaired -eq 1 ] ||
1671                 error "(3) Fail to repair inconsistent owner: $repaired"
1672 }
1673 run_test 16 "LFSCK can repair inconsistent MDT-object/OST-object owner"
1674
1675 test_17() {
1676         echo "#####"
1677         echo "If more than one MDT-objects reference the same OST-object,"
1678         echo "and the OST-object only recognizes one MDT-object, then the"
1679         echo "LFSCK should create new OST-objects for such non-recognized"
1680         echo "MDT-objects."
1681         echo "#####"
1682
1683         check_mount_and_prep
1684         $LFS setstripe -c 1 -i 0 $DIR/$tdir
1685
1686         echo "Inject failure stub to make two MDT-objects to refernce"
1687         echo "the OST-object"
1688
1689         #define OBD_FAIL_LFSCK_MULTIPLE_REF     0x1614
1690         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0x1614
1691
1692         dd if=/dev/zero of=$DIR/$tdir/guard bs=1M count=1
1693         cancel_lru_locks osc
1694
1695         createmany -o $DIR/$tdir/f 1
1696
1697         do_facet $SINGLEMDS $LCTL set_param fail_loc=0 fail_val=0
1698
1699         cancel_lru_locks mdc
1700         cancel_lru_locks osc
1701
1702         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard use the same OST-objects"
1703         local size=$(ls -l $DIR/$tdir/f0 | awk '{ print $5 }')
1704         [ $size -eq 1048576 ] ||
1705                 error "(1) f0 (wrong) size should be 1048576, but got $size"
1706
1707         echo "Trigger layout LFSCK to find out multiple refenced MDT-objects"
1708         echo "and fix them"
1709
1710         $START_LAYOUT -r || error "(2) Fail to start LFSCK for layout!"
1711
1712         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
1713                 mdd.${MDT_DEV}.lfsck_layout |
1714                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
1715                 $SHOW_LAYOUT
1716                 error "(3) unexpected status"
1717         }
1718
1719         local repaired=$($SHOW_LAYOUT |
1720                          awk '/^repaired_multiple_referenced/ { print $2 }')
1721         [ $repaired -eq 1 ] ||
1722                 error "(4) Fail to repair multiple references: $repaired"
1723
1724         echo "$DIR/$tdir/f0 and $DIR/$tdir/guard should use diff OST-objects"
1725         dd if=/dev/zero of=$DIR/$tdir/f0 bs=1M count=2 ||
1726                 error "(5) Fail to write f0."
1727         size=$(ls -l $DIR/$tdir/guard | awk '{ print $5 }')
1728         [ $size -eq 1048576 ] ||
1729                 error "(6) guard size should be 1048576, but got $size"
1730 }
1731 run_test 17 "LFSCK can repair multiple references"
1732
1733 $LCTL set_param debug=+cache > /dev/null
1734
1735 test_18a() {
1736         echo "#####"
1737         echo "The target MDT-object is there, but related stripe information"
1738         echo "is lost or partly lost. The LFSCK should regenerate the missing"
1739         echo "layout EA entries."
1740         echo "#####"
1741
1742         check_mount_and_prep
1743         $LFS mkdir -i 0 $DIR/$tdir/a1
1744         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
1745         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1746
1747         local saved_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1748
1749         $LFS path2fid $DIR/$tdir/a1/f1
1750         $LFS getstripe $DIR/$tdir/a1/f1
1751
1752         if [ $MDSCOUNT -ge 2 ]; then
1753                 $LFS mkdir -i 1 $DIR/$tdir/a2
1754                 $LFS setstripe -c 2 -i 1 -S 1M $DIR/$tdir/a2
1755                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1756                 $LFS path2fid $DIR/$tdir/a2/f2
1757                 $LFS getstripe $DIR/$tdir/a2/f2
1758         fi
1759
1760         cancel_lru_locks osc
1761
1762         echo "Inject failure, to make the MDT-object lost its layout EA"
1763         #define OBD_FAIL_LFSCK_LOST_STRIPE 0x1615
1764         do_facet mds1 $LCTL set_param fail_loc=0x1615
1765         chown 1.1 $DIR/$tdir/a1/f1
1766
1767         if [ $MDSCOUNT -ge 2 ]; then
1768                 do_facet mds2 $LCTL set_param fail_loc=0x1615
1769                 chown 1.1 $DIR/$tdir/a2/f2
1770         fi
1771
1772         sync
1773         sleep 2
1774
1775         do_facet mds1 $LCTL set_param fail_loc=0
1776         if [ $MDSCOUNT -ge 2 ]; then
1777                 do_facet mds2 $LCTL set_param fail_loc=0
1778         fi
1779
1780         cancel_lru_locks mdc
1781         cancel_lru_locks osc
1782
1783         echo "The file size should be incorrect since layout EA is lost"
1784         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1785         [ "$cur_size" != "$saved_size" ] ||
1786                 error "(1) Expect incorrect file1 size"
1787
1788         if [ $MDSCOUNT -ge 2 ]; then
1789                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1790                 [ "$cur_size" != "$saved_size" ] ||
1791                         error "(2) Expect incorrect file2 size"
1792         fi
1793
1794         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1795         $START_LAYOUT -r -o || error "(3) Fail to start LFSCK for layout!"
1796
1797         for k in $(seq $MDSCOUNT); do
1798                 # The LFSCK status query internal is 30 seconds. For the case
1799                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1800                 # time to guarantee the status sync up.
1801                 wait_update_facet mds${k} "$LCTL get_param -n \
1802                         mdd.$(facet_svc mds${k}).lfsck_layout |
1803                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
1804                         error "(4) MDS${k} is not the expected 'completed'"
1805         done
1806
1807         for k in $(seq $OSTCOUNT); do
1808                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1809                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1810                                 awk '/^status/ { print $2 }')
1811                 [ "$cur_status" == "completed" ] ||
1812                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
1813         done
1814
1815         local repaired=$(do_facet mds1 $LCTL get_param -n \
1816                          mdd.$(facet_svc mds1).lfsck_layout |
1817                          awk '/^repaired_orphan/ { print $2 }')
1818         [ $repaired -eq 1 ] ||
1819         error "(6.1) Expect 1 fixed on mds1, but got: $repaired"
1820
1821         if [ $MDSCOUNT -ge 2 ]; then
1822                 repaired=$(do_facet mds2 $LCTL get_param -n \
1823                          mdd.$(facet_svc mds2).lfsck_layout |
1824                                  awk '/^repaired_orphan/ { print $2 }')
1825                 [ $repaired -eq 2 ] ||
1826                 error "(6.2) Expect 2 fixed on mds2, but got: $repaired"
1827         fi
1828
1829         $LFS path2fid $DIR/$tdir/a1/f1
1830         $LFS getstripe $DIR/$tdir/a1/f1
1831
1832         if [ $MDSCOUNT -ge 2 ]; then
1833                 $LFS path2fid $DIR/$tdir/a2/f2
1834                 $LFS getstripe $DIR/$tdir/a2/f2
1835         fi
1836
1837         echo "The file size should be correct after layout LFSCK scanning"
1838         cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1839         [ "$cur_size" == "$saved_size" ] ||
1840                 error "(7) Expect file1 size $saved_size, but got $cur_size"
1841
1842         if [ $MDSCOUNT -ge 2 ]; then
1843                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1844                 [ "$cur_size" == "$saved_size" ] ||
1845                 error "(8) Expect file2 size $saved_size, but got $cur_size"
1846         fi
1847 }
1848 run_test 18a "Find out orphan OST-object and repair it (1)"
1849
1850 test_18b() {
1851         echo "#####"
1852         echo "The target MDT-object is lost. The LFSCK should re-create the"
1853         echo "MDT-object under .lustre/lost+found/MDTxxxx. The admin should"
1854         echo "can move it back to normal namespace manually."
1855         echo "#####"
1856
1857         check_mount_and_prep
1858         $LFS mkdir -i 0 $DIR/$tdir/a1
1859         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
1860         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1861         local saved_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1862         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
1863         echo ${fid1}
1864         $LFS getstripe $DIR/$tdir/a1/f1
1865
1866         if [ $MDSCOUNT -ge 2 ]; then
1867                 $LFS mkdir -i 1 $DIR/$tdir/a2
1868                 $LFS setstripe -c 2 -i 1 -S 1M $DIR/$tdir/a2
1869                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1870                 fid2=$($LFS path2fid $DIR/$tdir/a2/f2)
1871                 echo ${fid2}
1872                 $LFS getstripe $DIR/$tdir/a2/f2
1873         fi
1874
1875         cancel_lru_locks osc
1876
1877         echo "Inject failure, to simulate the case of missing the MDT-object"
1878         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
1879         do_facet mds1 $LCTL set_param fail_loc=0x1616
1880         rm -f $DIR/$tdir/a1/f1
1881
1882         if [ $MDSCOUNT -ge 2 ]; then
1883                 do_facet mds2 $LCTL set_param fail_loc=0x1616
1884                 rm -f $DIR/$tdir/a2/f2
1885         fi
1886
1887         sync
1888         sleep 2
1889
1890         do_facet mds1 $LCTL set_param fail_loc=0
1891         if [ $MDSCOUNT -ge 2 ]; then
1892                 do_facet mds2 $LCTL set_param fail_loc=0
1893         fi
1894
1895         cancel_lru_locks mdc
1896         cancel_lru_locks osc
1897
1898         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
1899         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
1900
1901         for k in $(seq $MDSCOUNT); do
1902                 # The LFSCK status query internal is 30 seconds. For the case
1903                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
1904                 # time to guarantee the status sync up.
1905                 wait_update_facet mds${k} "$LCTL get_param -n \
1906                         mdd.$(facet_svc mds${k}).lfsck_layout |
1907                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
1908                         error "(2) MDS${k} is not the expected 'completed'"
1909         done
1910
1911         for k in $(seq $OSTCOUNT); do
1912                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
1913                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
1914                                 awk '/^status/ { print $2 }')
1915                 [ "$cur_status" == "completed" ] ||
1916                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
1917         done
1918
1919         local repaired=$(do_facet mds1 $LCTL get_param -n \
1920                          mdd.$(facet_svc mds1).lfsck_layout |
1921                          awk '/^repaired_orphan/ { print $2 }')
1922         [ $repaired -eq 1 ] ||
1923         error "(4.1) Expect 1 fixed on mds1, but got: $repaired"
1924
1925         if [ $MDSCOUNT -ge 2 ]; then
1926                 repaired=$(do_facet mds2 $LCTL get_param -n \
1927                          mdd.$(facet_svc mds2).lfsck_layout |
1928                          awk '/^repaired_orphan/ { print $2 }')
1929                 [ $repaired -eq 2 ] ||
1930                 error "(4.2) Expect 2 fixed on mds2, but got: $repaired"
1931         fi
1932
1933         echo "Move the files from ./lustre/lost+found/MDTxxxx to namespace"
1934         mv $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0 $DIR/$tdir/a1/f1 ||
1935         error "(5) Fail to move $MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
1936
1937         if [ $MDSCOUNT -ge 2 ]; then
1938                 local name=$MOUNT/.lustre/lost+found/MDT0001/${fid2}-R-0
1939                 mv $name $DIR/$tdir/a2/f2 || error "(6) Fail to move $name"
1940         fi
1941
1942         $LFS path2fid $DIR/$tdir/a1/f1
1943         $LFS getstripe $DIR/$tdir/a1/f1
1944
1945         if [ $MDSCOUNT -ge 2 ]; then
1946                 $LFS path2fid $DIR/$tdir/a2/f2
1947                 $LFS getstripe $DIR/$tdir/a2/f2
1948         fi
1949
1950         echo "The file size should be correct after layout LFSCK scanning"
1951         local cur_size=$(ls -il $DIR/$tdir/a1/f1 | awk '{ print $6 }')
1952         [ "$cur_size" == "$saved_size" ] ||
1953                 error "(7) Expect file1 size $saved_size, but got $cur_size"
1954
1955         if [ $MDSCOUNT -ge 2 ]; then
1956                 cur_size=$(ls -il $DIR/$tdir/a2/f2 | awk '{ print $6 }')
1957                 [ "$cur_size" == "$saved_size" ] ||
1958                 error "(8) Expect file2 size $saved_size, but got $cur_size"
1959         fi
1960 }
1961 run_test 18b "Find out orphan OST-object and repair it (2)"
1962
1963 test_18c() {
1964         echo "#####"
1965         echo "The target MDT-object is lost, and the OST-object FID is missing."
1966         echo "The LFSCK should re-create the MDT-object with new FID under the "
1967         echo "directory .lustre/lost+found/MDTxxxx."
1968         echo "#####"
1969
1970         check_mount_and_prep
1971         $LFS mkdir -i 0 $DIR/$tdir/a1
1972         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
1973
1974         echo "Inject failure, to simulate the case of missing parent FID"
1975         #define OBD_FAIL_LFSCK_NOPFID           0x1617
1976         do_facet ost1 $LCTL set_param fail_loc=0x1617
1977
1978         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
1979         $LFS getstripe $DIR/$tdir/a1/f1
1980
1981         if [ $MDSCOUNT -ge 2 ]; then
1982                 $LFS mkdir -i 1 $DIR/$tdir/a2
1983                 $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a2
1984                 dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
1985                 $LFS getstripe $DIR/$tdir/a2/f2
1986         fi
1987
1988         cancel_lru_locks osc
1989
1990         echo "Inject failure, to simulate the case of missing the MDT-object"
1991         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
1992         do_facet mds1 $LCTL set_param fail_loc=0x1616
1993         rm -f $DIR/$tdir/a1/f1
1994
1995         if [ $MDSCOUNT -ge 2 ]; then
1996                 do_facet mds2 $LCTL set_param fail_loc=0x1616
1997                 rm -f $DIR/$tdir/a2/f2
1998         fi
1999
2000         sync
2001         sleep 2
2002
2003         do_facet mds1 $LCTL set_param fail_loc=0
2004         if [ $MDSCOUNT -ge 2 ]; then
2005                 do_facet mds2 $LCTL set_param fail_loc=0
2006         fi
2007
2008         cancel_lru_locks mdc
2009         cancel_lru_locks osc
2010
2011         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2012         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2013
2014         for k in $(seq $MDSCOUNT); do
2015                 # The LFSCK status query internal is 30 seconds. For the case
2016                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2017                 # time to guarantee the status sync up.
2018                 wait_update_facet mds${k} "$LCTL get_param -n \
2019                         mdd.$(facet_svc mds${k}).lfsck_layout |
2020                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2021                         error "(2) MDS${k} is not the expected 'completed'"
2022         done
2023
2024         for k in $(seq $OSTCOUNT); do
2025                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2026                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2027                                 awk '/^status/ { print $2 }')
2028                 [ "$cur_status" == "completed" ] ||
2029                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2030         done
2031
2032         if [ $MDSCOUNT -ge 2 ]; then
2033                 expected=2
2034         else
2035                 expected=1
2036         fi
2037
2038         local repaired=$(do_facet mds1 $LCTL get_param -n \
2039                          mdd.$(facet_svc mds1).lfsck_layout |
2040                          awk '/^repaired_orphan/ { print $2 }')
2041         [ $repaired -eq $expected ] ||
2042                 error "(4) Expect $expected fixed on mds1, but got: $repaired"
2043
2044         if [ $MDSCOUNT -ge 2 ]; then
2045                 repaired=$(do_facet mds2 $LCTL get_param -n \
2046                            mdd.$(facet_svc mds2).lfsck_layout |
2047                            awk '/^repaired_orphan/ { print $2 }')
2048                 [ $repaired -eq 0 ] ||
2049                         error "(5) Expect 0 fixed on mds2, but got: $repaired"
2050         fi
2051
2052         ls -ail $MOUNT/.lustre/lost+found/
2053
2054         echo "There should NOT be some stub under .lustre/lost+found/MDT0001/"
2055         if [ -d $MOUNT/.lustre/lost+found/MDT0001 ]; then
2056                 cname=$(find $MOUNT/.lustre/lost+found/MDT0001/ -name *-N-*)
2057                 [ -z "$cname" ] ||
2058                         error "(6) .lustre/lost+found/MDT0001/ should be empty"
2059         fi
2060
2061         echo "There should be some stub under .lustre/lost+found/MDT0000/"
2062         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
2063                 error "(7) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
2064
2065         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-N-*)
2066         [ ! -z "$cname" ] ||
2067                 error "(8) .lustre/lost+found/MDT0000/ should not be empty"
2068 }
2069 run_test 18c "Find out orphan OST-object and repair it (3)"
2070
2071 test_18d() {
2072         echo "#####"
2073         echo "The target MDT-object layout EA slot is occpuied by some new"
2074         echo "created OST-object when repair dangling reference case. Such"
2075         echo "conflict OST-object has never been modified. Then when found"
2076         echo "the orphan OST-object, LFSCK will replace it with the orphan"
2077         echo "OST-object."
2078         echo "#####"
2079
2080         check_mount_and_prep
2081         mkdir $DIR/$tdir/a1
2082         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
2083         echo "guard" > $DIR/$tdir/a1/f1
2084         echo "foo" > $DIR/$tdir/a1/f2
2085         local saved_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2086         $LFS path2fid $DIR/$tdir/a1/f1
2087         $LFS getstripe $DIR/$tdir/a1/f1
2088         $LFS path2fid $DIR/$tdir/a1/f2
2089         $LFS getstripe $DIR/$tdir/a1/f2
2090         cancel_lru_locks osc
2091
2092         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
2093         echo "to reference the same OST-object (which is f1's OST-obejct)."
2094         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
2095         echo "dangling reference case, but f2's old OST-object is there."
2096         echo
2097
2098         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
2099         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
2100         chown 1.1 $DIR/$tdir/a1/f2
2101         rm -f $DIR/$tdir/a1/f1
2102         sync
2103         sleep 2
2104         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2105
2106         echo "stopall to cleanup object cache"
2107         stopall > /dev/null
2108         echo "setupall"
2109         setupall > /dev/null
2110
2111         echo "The file size should be incorrect since dangling referenced"
2112         local cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2113         [ "$cur_size" != "$saved_size" ] ||
2114                 error "(1) Expect incorrect file2 size"
2115
2116         #define OBD_FAIL_LFSCK_DELAY3           0x1602
2117         do_facet $SINGLEMDS $LCTL set_param fail_val=5 fail_loc=0x1602
2118
2119         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2120         $START_LAYOUT -r -o -c || error "(2) Fail to start LFSCK for layout!"
2121
2122         wait_update_facet mds1 "$LCTL get_param -n \
2123                 mdd.$(facet_svc mds1).lfsck_layout |
2124                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" $LTIME ||
2125                 error "(3.0) MDS1 is not the expected 'scanning-phase2'"
2126
2127         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
2128
2129         for k in $(seq $MDSCOUNT); do
2130                 # The LFSCK status query internal is 30 seconds. For the case
2131                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2132                 # time to guarantee the status sync up.
2133                 wait_update_facet mds${k} "$LCTL get_param -n \
2134                         mdd.$(facet_svc mds${k}).lfsck_layout |
2135                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2136                         error "(3) MDS${k} is not the expected 'completed'"
2137         done
2138
2139         for k in $(seq $OSTCOUNT); do
2140                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2141                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2142                                 awk '/^status/ { print $2 }')
2143                 [ "$cur_status" == "completed" ] ||
2144                 error "(4) OST${k} Expect 'completed', but got '$cur_status'"
2145         done
2146
2147         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
2148                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
2149                          awk '/^repaired_orphan/ { print $2 }')
2150         [ $repaired -eq 1 ] ||
2151                 error "(5) Expect 1 orphan has been fixed, but got: $repaired"
2152
2153         echo "The file size should be correct after layout LFSCK scanning"
2154         cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2155         [ "$cur_size" == "$saved_size" ] ||
2156                 error "(6) Expect file2 size $saved_size, but got $cur_size"
2157
2158         echo "The LFSCK should find back the original data."
2159         cat $DIR/$tdir/a1/f2
2160         $LFS path2fid $DIR/$tdir/a1/f2
2161         $LFS getstripe $DIR/$tdir/a1/f2
2162 }
2163 run_test 18d "Find out orphan OST-object and repair it (4)"
2164
2165 test_18e() {
2166         echo "#####"
2167         echo "The target MDT-object layout EA slot is occpuied by some new"
2168         echo "created OST-object when repair dangling reference case. Such"
2169         echo "conflict OST-object has been modified by others. To keep the"
2170         echo "new data, the LFSCK will create a new file to refernece this"
2171         echo "old orphan OST-object."
2172         echo "#####"
2173
2174         check_mount_and_prep
2175         mkdir $DIR/$tdir/a1
2176         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
2177         echo "guard" > $DIR/$tdir/a1/f1
2178         echo "foo" > $DIR/$tdir/a1/f2
2179         local saved_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2180         $LFS path2fid $DIR/$tdir/a1/f1
2181         $LFS getstripe $DIR/$tdir/a1/f1
2182         $LFS path2fid $DIR/$tdir/a1/f2
2183         $LFS getstripe $DIR/$tdir/a1/f2
2184         cancel_lru_locks osc
2185
2186         echo "Inject failure to make $DIR/$tdir/a1/f1 and $DIR/$tdir/a1/f2"
2187         echo "to reference the same OST-object (which is f1's OST-obejct)."
2188         echo "Then drop $DIR/$tdir/a1/f1 and its OST-object, so f2 becomes"
2189         echo "dangling reference case, but f2's old OST-object is there."
2190         echo
2191
2192         #define OBD_FAIL_LFSCK_CHANGE_STRIPE    0x1618
2193         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1618
2194         chown 1.1 $DIR/$tdir/a1/f2
2195         rm -f $DIR/$tdir/a1/f1
2196         sync
2197         sleep 2
2198         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2199
2200         echo "stopall to cleanup object cache"
2201         stopall > /dev/null
2202         echo "setupall"
2203         setupall > /dev/null
2204
2205         echo "The file size should be incorrect since dangling referenced"
2206         local cur_size=$(ls -il $DIR/$tdir/a1/f2 | awk '{ print $6 }')
2207         [ "$cur_size" != "$saved_size" ] ||
2208                 error "(1) Expect incorrect file2 size"
2209
2210         #define OBD_FAIL_LFSCK_DELAY3           0x1602
2211         do_facet $SINGLEMDS $LCTL set_param fail_val=10 fail_loc=0x1602
2212
2213         start_full_debug_logging
2214
2215         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2216         $START_LAYOUT -r -o -c || error "(2) Fail to start LFSCK for layout!"
2217
2218         wait_update_facet mds1 "$LCTL get_param -n \
2219                 mdd.$(facet_svc mds1).lfsck_layout |
2220                 awk '/^status/ { print \\\$2 }'" "scanning-phase2" $LTIME ||
2221                 error "(3) MDS1 is not the expected 'scanning-phase2'"
2222
2223         # to guarantee all updates are synced.
2224         sync
2225         sleep 2
2226
2227         echo "Write new data to f2 to modify the new created OST-object."
2228         echo "dummy" >> $DIR/$tdir/a1/f2
2229
2230         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
2231
2232         for k in $(seq $MDSCOUNT); do
2233                 # The LFSCK status query internal is 30 seconds. For the case
2234                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2235                 # time to guarantee the status sync up.
2236                 wait_update_facet mds${k} "$LCTL get_param -n \
2237                         mdd.$(facet_svc mds${k}).lfsck_layout |
2238                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2239                         error "(4) MDS${k} is not the expected 'completed'"
2240         done
2241
2242         for k in $(seq $OSTCOUNT); do
2243                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2244                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2245                                 awk '/^status/ { print $2 }')
2246                 [ "$cur_status" == "completed" ] ||
2247                 error "(5) OST${k} Expect 'completed', but got '$cur_status'"
2248         done
2249
2250         stop_full_debug_logging
2251
2252         local repaired=$(do_facet $SINGLEMDS $LCTL get_param -n \
2253                          mdd.$(facet_svc $SINGLEMDS).lfsck_layout |
2254                          awk '/^repaired_orphan/ { print $2 }')
2255         [ $repaired -eq 1 ] ||
2256                 error "(6) Expect 1 orphan has been fixed, but got: $repaired"
2257
2258         echo "There should be stub file under .lustre/lost+found/MDT0000/"
2259         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
2260                 error "(7) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
2261
2262         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-C-*)
2263         [ ! -z "$cname" ] ||
2264                 error "(8) .lustre/lost+found/MDT0000/ should not be empty"
2265
2266         echo "The stub file should keep the original f2 data"
2267         cur_size=$(ls -il $cname | awk '{ print $6 }')
2268         [ "$cur_size" == "$saved_size" ] ||
2269                 error "(9) Expect file2 size $saved_size, but got $cur_size"
2270
2271         cat $cname
2272         $LFS path2fid $cname
2273         $LFS getstripe $cname
2274
2275         echo "The f2 should contains new data."
2276         cat $DIR/$tdir/a1/f2
2277         $LFS path2fid $DIR/$tdir/a1/f2
2278         $LFS getstripe $DIR/$tdir/a1/f2
2279 }
2280 run_test 18e "Find out orphan OST-object and repair it (5)"
2281
2282 test_18f() {
2283         [ $OSTCOUNT -lt 2 ] &&
2284                 skip "The test needs at least 2 OSTs" && return
2285
2286         echo "#####"
2287         echo "The target MDT-object is lost. The LFSCK should re-create the"
2288         echo "MDT-object under .lustre/lost+found/MDTxxxx. If some OST fail"
2289         echo "to verify some OST-object(s) during the first stage-scanning,"
2290         echo "the LFSCK should skip orphan OST-objects for such OST. Others"
2291         echo "should not be affected."
2292         echo "#####"
2293
2294         check_mount_and_prep
2295         $LFS mkdir -i 0 $DIR/$tdir/a1
2296         $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a1
2297         dd if=/dev/zero of=$DIR/$tdir/a1/guard bs=1M count=2
2298         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=1M count=2
2299         $LFS mkdir -i 0 $DIR/$tdir/a2
2300         $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a2
2301         dd if=/dev/zero of=$DIR/$tdir/a2/f2 bs=1M count=2
2302         $LFS getstripe $DIR/$tdir/a1/f1
2303         $LFS getstripe $DIR/$tdir/a2/f2
2304
2305         if [ $MDSCOUNT -ge 2 ]; then
2306                 $LFS mkdir -i 1 $DIR/$tdir/a3
2307                 $LFS setstripe -c 1 -i 0 -S 1M $DIR/$tdir/a3
2308                 dd if=/dev/zero of=$DIR/$tdir/a3/guard bs=1M count=2
2309                 dd if=/dev/zero of=$DIR/$tdir/a3/f3 bs=1M count=2
2310                 $LFS mkdir -i 1 $DIR/$tdir/a4
2311                 $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a4
2312                 dd if=/dev/zero of=$DIR/$tdir/a4/f4 bs=1M count=2
2313                 $LFS getstripe $DIR/$tdir/a3/f3
2314                 $LFS getstripe $DIR/$tdir/a4/f4
2315         fi
2316
2317         cancel_lru_locks osc
2318
2319         echo "Inject failure, to simulate the case of missing the MDT-object"
2320         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2321         do_facet mds1 $LCTL set_param fail_loc=0x1616
2322         rm -f $DIR/$tdir/a1/f1
2323         rm -f $DIR/$tdir/a2/f2
2324
2325         if [ $MDSCOUNT -ge 2 ]; then
2326                 do_facet mds2 $LCTL set_param fail_loc=0x1616
2327                 rm -f $DIR/$tdir/a3/f3
2328                 rm -f $DIR/$tdir/a4/f4
2329         fi
2330
2331         sync
2332         sleep 2
2333
2334         do_facet mds1 $LCTL set_param fail_loc=0
2335         if [ $MDSCOUNT -ge 2 ]; then
2336                 do_facet mds2 $LCTL set_param fail_loc=0
2337         fi
2338
2339         cancel_lru_locks mdc
2340         cancel_lru_locks osc
2341
2342         echo "Inject failure, to simulate the OST0 fail to handle"
2343         echo "MDT0 LFSCK request during the first-stage scanning."
2344         #define OBD_FAIL_LFSCK_BAD_NETWORK      0x161c
2345         do_facet mds1 $LCTL set_param fail_loc=0x161c fail_val=0
2346
2347         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2348         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2349
2350         for k in $(seq $MDSCOUNT); do
2351                 # The LFSCK status query internal is 30 seconds. For the case
2352                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2353                 # time to guarantee the status sync up.
2354                 wait_update_facet mds${k} "$LCTL get_param -n \
2355                         mdd.$(facet_svc mds${k}).lfsck_layout |
2356                         awk '/^status/ { print \\\$2 }'" "partial" $LTIME ||
2357                         error "(2) MDS${k} is not the expected 'partial'"
2358         done
2359
2360         wait_update_facet ost1 "$LCTL get_param -n \
2361                 obdfilter.$(facet_svc ost1).lfsck_layout |
2362                 awk '/^status/ { print \\\$2 }'" "partial" $LTIME || {
2363                 error "(3) OST1 is not the expected 'partial'"
2364         }
2365
2366         wait_update_facet ost2 "$LCTL get_param -n \
2367                 obdfilter.$(facet_svc ost2).lfsck_layout |
2368                 awk '/^status/ { print \\\$2 }'" "completed" $LTIME || {
2369                 error "(4) OST2 is not the expected 'completed'"
2370         }
2371
2372         do_facet mds1 $LCTL set_param fail_loc=0 fail_val=0
2373
2374         local repaired=$(do_facet mds1 $LCTL get_param -n \
2375                          mdd.$(facet_svc mds1).lfsck_layout |
2376                          awk '/^repaired_orphan/ { print $2 }')
2377         [ $repaired -eq 1 ] ||
2378                 error "(5) Expect 1 fixed on mds{1}, but got: $repaired"
2379
2380         if [ $MDSCOUNT -ge 2 ]; then
2381                 repaired=$(do_facet mds2 $LCTL get_param -n \
2382                          mdd.$(facet_svc mds2).lfsck_layout |
2383                          awk '/^repaired_orphan/ { print $2 }')
2384                 [ $repaired -eq 1 ] ||
2385                 error "(6) Expect 1 fixed on mds{2}, but got: $repaired"
2386         fi
2387
2388         echo "Trigger layout LFSCK on all devices again to cleanup"
2389         $START_LAYOUT -r -o || error "(7) Fail to start LFSCK for layout!"
2390
2391         for k in $(seq $MDSCOUNT); do
2392                 # The LFSCK status query internal is 30 seconds. For the case
2393                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2394                 # time to guarantee the status sync up.
2395                 wait_update_facet mds${k} "$LCTL get_param -n \
2396                         mdd.$(facet_svc mds${k}).lfsck_layout |
2397                         awk '/^status/ { print \\\$2 }'" "completed" $LTIME ||
2398                         error "(8) MDS${k} is not the expected 'completed'"
2399         done
2400
2401         for k in $(seq $OSTCOUNT); do
2402                 cur_status=$(do_facet ost${k} $LCTL get_param -n \
2403                              obdfilter.$(facet_svc ost${k}).lfsck_layout |
2404                              awk '/^status/ { print $2 }')
2405                 [ "$cur_status" == "completed" ] ||
2406                 error "(9) OST${k} Expect 'completed', but got '$cur_status'"
2407
2408         done
2409
2410         local repaired=$(do_facet mds1 $LCTL get_param -n \
2411                          mdd.$(facet_svc mds1).lfsck_layout |
2412                          awk '/^repaired_orphan/ { print $2 }')
2413         [ $repaired -eq 2 ] ||
2414                 error "(10) Expect 2 fixed on mds{1}, but got: $repaired"
2415
2416         if [ $MDSCOUNT -ge 2 ]; then
2417                 repaired=$(do_facet mds2 $LCTL get_param -n \
2418                          mdd.$(facet_svc mds2).lfsck_layout |
2419                          awk '/^repaired_orphan/ { print $2 }')
2420                 [ $repaired -eq 2 ] ||
2421                 error "(11) Expect 2 fixed on mds{2}, but got: $repaired"
2422         fi
2423 }
2424 run_test 18f "Skip the failed OST(s) when handle orphan OST-objects"
2425
2426 $LCTL set_param debug=-cache > /dev/null
2427
2428 test_19a() {
2429         check_mount_and_prep
2430         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2431
2432         echo "foo" > $DIR/$tdir/a0
2433         echo "guard" > $DIR/$tdir/a1
2434         cancel_lru_locks osc
2435
2436         echo "Inject failure, then client will offer wrong parent FID when read"
2437         do_facet ost1 $LCTL set_param -n \
2438                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2439         #define OBD_FAIL_LFSCK_INVALID_PFID     0x1619
2440         $LCTL set_param fail_loc=0x1619
2441
2442         echo "Read RPC with wrong parent FID should be denied"
2443         cat $DIR/$tdir/a0 && error "(3) Read should be denied!"
2444         $LCTL set_param fail_loc=0
2445 }
2446 run_test 19a "OST-object inconsistency self detect"
2447
2448 test_19b() {
2449         check_mount_and_prep
2450         $LFS setstripe -c 1 -i 0 $DIR/$tdir
2451
2452         echo "Inject failure stub to make the OST-object to back point to"
2453         echo "non-exist MDT-object"
2454
2455         #define OBD_FAIL_LFSCK_UNMATCHED_PAIR1  0x1611
2456         do_facet ost1 $LCTL set_param fail_loc=0x1611
2457         echo "foo" > $DIR/$tdir/f0
2458         cancel_lru_locks osc
2459         do_facet ost1 $LCTL set_param fail_loc=0
2460
2461         echo "Nothing should be fixed since self detect and repair is disabled"
2462         local repaired=$(do_facet ost1 $LCTL get_param -n \
2463                         obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2464                         awk '/^repaired/ { print $2 }')
2465         [ $repaired -eq 0 ] ||
2466                 error "(1) Expected 0 repaired, but got $repaired"
2467
2468         echo "Read RPC with right parent FID should be accepted,"
2469         echo "and cause parent FID on OST to be fixed"
2470
2471         do_facet ost1 $LCTL set_param -n \
2472                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid 1
2473         cat $DIR/$tdir/f0 || error "(2) Read should not be denied!"
2474
2475         repaired=$(do_facet ost1 $LCTL get_param -n \
2476                 obdfilter.${FSNAME}-OST0000.lfsck_verify_pfid |
2477                 awk '/^repaired/ { print $2 }')
2478         [ $repaired -eq 1 ] ||
2479                 error "(3) Expected 1 repaired, but got $repaired"
2480 }
2481 run_test 19b "OST-object inconsistency self repair"
2482
2483 test_20() {
2484         [ $OSTCOUNT -lt 2 ] &&
2485                 skip "The test needs at least 2 OSTs" && return
2486
2487         echo "#####"
2488         echo "The target MDT-object and some of its OST-object are lost."
2489         echo "The LFSCK should find out the left OST-objects and re-create"
2490         echo "the MDT-object under the direcotry .lustre/lost+found/MDTxxxx/"
2491         echo "with the partial OST-objects (LOV EA hole)."
2492
2493         echo "New client can access the file with LOV EA hole via normal"
2494         echo "system tools or commands without crash the system."
2495
2496         echo "For old client, even though it cannot access the file with"
2497         echo "LOV EA hole, it should not cause the system crash."
2498         echo "#####"
2499
2500         check_mount_and_prep
2501         $LFS mkdir -i 0 $DIR/$tdir/a1
2502         if [ $OSTCOUNT -gt 2 ]; then
2503                 $LFS setstripe -c 3 -i 0 -S 1M $DIR/$tdir/a1
2504                 bcount=513
2505         else
2506                 $LFS setstripe -c 2 -i 0 -S 1M $DIR/$tdir/a1
2507                 bcount=257
2508         fi
2509
2510         # 256 blocks on the stripe0.
2511         # 1 block on the stripe1 for 2 OSTs case.
2512         # 256 blocks on the stripe1 for other cases.
2513         # 1 block on the stripe2 if OSTs > 2
2514         dd if=/dev/zero of=$DIR/$tdir/a1/f0 bs=4096 count=$bcount
2515         dd if=/dev/zero of=$DIR/$tdir/a1/f1 bs=4096 count=$bcount
2516         dd if=/dev/zero of=$DIR/$tdir/a1/f2 bs=4096 count=$bcount
2517
2518         local fid0=$($LFS path2fid $DIR/$tdir/a1/f0)
2519         local fid1=$($LFS path2fid $DIR/$tdir/a1/f1)
2520         local fid2=$($LFS path2fid $DIR/$tdir/a1/f2)
2521
2522         echo ${fid0}
2523         $LFS getstripe $DIR/$tdir/a1/f0
2524         echo ${fid1}
2525         $LFS getstripe $DIR/$tdir/a1/f1
2526         echo ${fid2}
2527         $LFS getstripe $DIR/$tdir/a1/f2
2528
2529         if [ $OSTCOUNT -gt 2 ]; then
2530                 dd if=/dev/zero of=$DIR/$tdir/a1/f3 bs=4096 count=$bcount
2531                 fid3=$($LFS path2fid $DIR/$tdir/a1/f3)
2532                 echo ${fid3}
2533                 $LFS getstripe $DIR/$tdir/a1/f3
2534         fi
2535
2536         cancel_lru_locks osc
2537
2538         echo "Inject failure..."
2539         echo "To simulate f0 lost MDT-object"
2540         #define OBD_FAIL_LFSCK_LOST_MDTOBJ      0x1616
2541         do_facet mds1 $LCTL set_param fail_loc=0x1616
2542         rm -f $DIR/$tdir/a1/f0
2543
2544         echo "To simulate f1 lost MDT-object and OST-object0"
2545         #define OBD_FAIL_LFSCK_LOST_SPEOBJ      0x161a
2546         do_facet mds1 $LCTL set_param fail_loc=0x161a
2547         rm -f $DIR/$tdir/a1/f1
2548
2549         echo "To simulate f2 lost MDT-object and OST-object1"
2550         do_facet mds1 $LCTL set_param fail_val=1
2551         rm -f $DIR/$tdir/a1/f2
2552
2553         if [ $OSTCOUNT -gt 2 ]; then
2554                 echo "To simulate f3 lost MDT-object and OST-object2"
2555                 do_facet mds1 $LCTL set_param fail_val=2
2556                 rm -f $DIR/$tdir/a1/f3
2557         fi
2558
2559         umount_client $MOUNT
2560         sync
2561         sleep 2
2562         do_facet mds1 $LCTL set_param fail_loc=0 fail_val=0
2563
2564         echo "Inject failure to slow down the LFSCK on OST0"
2565         #define OBD_FAIL_LFSCK_DELAY5           0x161b
2566         do_facet ost1 $LCTL set_param fail_loc=0x161b
2567
2568         echo "Trigger layout LFSCK on all devices to find out orphan OST-object"
2569         $START_LAYOUT -r -o || error "(1) Fail to start LFSCK for layout!"
2570
2571         sleep 3
2572         do_facet ost1 $LCTL set_param fail_loc=0
2573
2574         for k in $(seq $MDSCOUNT); do
2575                 # The LFSCK status query internal is 30 seconds. For the case
2576                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
2577                 # time to guarantee the status sync up.
2578                 wait_update_facet mds${k} "$LCTL get_param -n \
2579                         mdd.$(facet_svc mds${k}).lfsck_layout |
2580                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
2581                         error "(2) MDS${k} is not the expected 'completed'"
2582         done
2583
2584         for k in $(seq $OSTCOUNT); do
2585                 local cur_status=$(do_facet ost${k} $LCTL get_param -n \
2586                                 obdfilter.$(facet_svc ost${k}).lfsck_layout |
2587                                 awk '/^status/ { print $2 }')
2588                 [ "$cur_status" == "completed" ] ||
2589                 error "(3) OST${k} Expect 'completed', but got '$cur_status'"
2590         done
2591
2592         local repaired=$(do_facet mds1 $LCTL get_param -n \
2593                          mdd.$(facet_svc mds1).lfsck_layout |
2594                          awk '/^repaired_orphan/ { print $2 }')
2595         if [ $OSTCOUNT -gt 2 ]; then
2596                 [ $repaired -eq 9 ] ||
2597                         error "(4.1) Expect 9 fixed on mds1, but got: $repaired"
2598         else
2599                 [ $repaired -eq 4 ] ||
2600                         error "(4.2) Expect 4 fixed on mds1, but got: $repaired"
2601         fi
2602
2603         mount_client $MOUNT || error "(5.0) Fail to start client!"
2604
2605         LOV_PATTERN_F_HOLE=0x40000000
2606
2607         #
2608         # ${fid0}-R-0 is the old f0
2609         #
2610         local name="$MOUNT/.lustre/lost+found/MDT0000/${fid0}-R-0"
2611         echo "Check $name, which is the old f0"
2612
2613         $LFS getstripe -v $name || error "(5.1) cannot getstripe on $name"
2614
2615         local pattern=0x$($LFS getstripe -L $name)
2616         [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2617                 error "(5.2) NOT expect pattern flag hole, but got $pattern"
2618
2619         local stripes=$($LFS getstripe -c $name)
2620         if [ $OSTCOUNT -gt 2 ]; then
2621                 [ $stripes -eq 3 ] ||
2622                 error "(5.3.1) expect the stripe count is 3, but got $stripes"
2623         else
2624                 [ $stripes -eq 2 ] ||
2625                 error "(5.3.2) expect the stripe count is 2, but got $stripes"
2626         fi
2627
2628         local size=$(stat $name | awk '/Size:/ { print $2 }')
2629         [ $size -eq $((4096 * $bcount)) ] ||
2630                 error "(5.4) expect the size $((4096 * $bcount)), but got $size"
2631
2632         cat $name > /dev/null || error "(5.5) cannot read $name"
2633
2634         echo "dummy" >> $name || error "(5.6) cannot write $name"
2635
2636         chown $RUNAS_ID:$RUNAS_GID $name || error "(5.7) cannot chown on $name"
2637
2638         touch $name || error "(5.8) cannot touch $name"
2639
2640         rm -f $name || error "(5.9) cannot unlink $name"
2641
2642         #
2643         # ${fid1}-R-0 contains the old f1's stripe1 (and stripe2 if OSTs > 2)
2644         #
2645         name="$MOUNT/.lustre/lost+found/MDT0000/${fid1}-R-0"
2646         if [ $OSTCOUNT -gt 2 ]; then
2647                 echo "Check $name, it contains the old f1's stripe1 and stripe2"
2648         else
2649                 echo "Check $name, it contains the old f1's stripe1"
2650         fi
2651
2652         $LFS getstripe -v $name || error "(6.1) cannot getstripe on $name"
2653
2654         pattern=0x$($LFS getstripe -L $name)
2655         [[ $((pattern & LOV_PATTERN_F_HOLE)) -ne 0 ]] ||
2656                 error "(6.2) expect pattern flag hole, but got $pattern"
2657
2658         stripes=$($LFS getstripe -c $name)
2659         if [ $OSTCOUNT -gt 2 ]; then
2660                 [ $stripes -eq 3 ] ||
2661                 error "(6.3.1) expect the stripe count is 3, but got $stripes"
2662         else
2663                 [ $stripes -eq 2 ] ||
2664                 error "(6.3.2) expect the stripe count is 2, but got $stripes"
2665         fi
2666
2667         size=$(stat $name | awk '/Size:/ { print $2 }')
2668         [ $size -eq $((4096 * $bcount)) ] ||
2669                 error "(6.4) expect the size $((4096 * $bcount)), but got $size"
2670
2671         cat $name > /dev/null && error "(6.5) normal read $name should fail"
2672
2673         local failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
2674                          bs=4096 2>&1 | grep "Input/output error" | wc -l)
2675
2676         # stripe0 is dummy
2677         [ $failures -eq 256 ] ||
2678                 error "(6.6) expect 256 IO failures, but get $failures"
2679
2680         size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
2681         [ $size -eq $((4096 * $bcount)) ] ||
2682                 error "(6.7) expect the size $((4096 * $bcount)), but got $size"
2683
2684         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 &&
2685                 error "(6.8) write to the LOV EA hole should fail"
2686
2687         dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 seek=300 ||
2688                 error "(6.9) write to normal stripe should NOT fail"
2689
2690         echo "foo" >> $name && error "(6.10) append write $name should fail"
2691
2692         chown $RUNAS_ID:$RUNAS_GID $name || error "(6.11) cannot chown on $name"
2693
2694         touch $name || error "(6.12) cannot touch $name"
2695
2696         rm -f $name || error "(6.13) cannot unlink $name"
2697
2698         #
2699         # ${fid2}-R-0 it contains the old f2's stripe0 (and stripe2 if OSTs > 2)
2700         #
2701         name="$MOUNT/.lustre/lost+found/MDT0000/${fid2}-R-0"
2702         if [ $OSTCOUNT -gt 2 ]; then
2703                 echo "Check $name, it contains the old f2's stripe0 and stripe2"
2704         else
2705                 echo "Check $name, it contains the old f2's stripe0"
2706         fi
2707
2708         $LFS getstripe -v $name || error "(7.1) cannot getstripe on $name"
2709
2710         pattern=0x$($LFS getstripe -L $name)
2711         stripes=$($LFS getstripe -c $name)
2712         size=$(stat $name | awk '/Size:/ { print $2 }')
2713         if [ $OSTCOUNT -gt 2 ]; then
2714                 [[ $((pattern & LOV_PATTERN_F_HOLE)) -ne 0 ]] ||
2715                 error "(7.2.1) expect pattern flag hole, but got $pattern"
2716
2717                 [ $stripes -eq 3 ] ||
2718                 error "(7.3.1) expect the stripe count is 3, but got $stripes"
2719
2720                 [ $size -eq $((4096 * $bcount)) ] ||
2721                 error "(7.4.1) expect size $((4096 * $bcount)), but got $size"
2722
2723                 cat $name > /dev/null &&
2724                         error "(7.5.1) normal read $name should fail"
2725
2726                 failures=$(dd if=$name of=$DIR/$tdir/dump conv=sync,noerror \
2727                            bs=4096 2>&1 | grep "Input/output error" | wc -l)
2728                 # stripe1 is dummy
2729                 [ $failures -eq 256 ] ||
2730                         error "(7.6) expect 256 IO failures, but get $failures"
2731
2732                 size=$(stat $DIR/$tdir/dump | awk '/Size:/ { print $2 }')
2733                 [ $size -eq $((4096 * $bcount)) ] ||
2734                 error "(7.7) expect the size $((4096 * $bcount)), but got $size"
2735
2736                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 \
2737                 seek=300 && error "(7.8.0) write to the LOV EA hole should fail"
2738
2739                 dd if=/dev/zero of=$name conv=sync,notrunc bs=4096 count=1 ||
2740                 error "(7.8.1) write to normal stripe should NOT fail"
2741
2742                 echo "foo" >> $name &&
2743                         error "(7.8.3) append write $name should fail"
2744
2745                 chown $RUNAS_ID:$RUNAS_GID $name ||
2746                         error "(7.9.1) cannot chown on $name"
2747
2748                 touch $name || error "(7.10.1) cannot touch $name"
2749         else
2750                 [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2751                 error "(7.2.2) NOT expect pattern flag hole, but got $pattern"
2752
2753                 [ $stripes -eq 1 ] ||
2754                 error "(7.3.2) expect the stripe count is 1, but got $stripes"
2755
2756                 # stripe1 is dummy
2757                 [ $size -eq $((4096 * (256 + 0))) ] ||
2758                 error "(7.4.2) expect the size $((4096 * 256)), but got $size"
2759
2760                 cat $name > /dev/null || error "(7.5.2) cannot read $name"
2761
2762                 echo "dummy" >> $name || error "(7.8.2) cannot write $name"
2763
2764                 chown $RUNAS_ID:$RUNAS_GID $name ||
2765                         error "(7.9.2) cannot chown on $name"
2766
2767                 touch $name || error "(7.10.2) cannot touch $name"
2768         fi
2769
2770         rm -f $name || error "(7.11) cannot unlink $name"
2771
2772         [ $OSTCOUNT -le 2 ] && return
2773
2774         #
2775         # ${fid3}-R-0 should contains the old f3's stripe0 and stripe1
2776         #
2777         name="$MOUNT/.lustre/lost+found/MDT0000/${fid3}-R-0"
2778         echo "Check $name, which contains the old f3's stripe0 and stripe1"
2779
2780         $LFS getstripe -v $name || error "(8.1) cannot getstripe on $name"
2781
2782         pattern=0x$($LFS getstripe -L $name)
2783         [[ $((pattern & LOV_PATTERN_F_HOLE)) -eq 0 ]] ||
2784                 error "(8.2) NOT expect pattern flag hole, but got $pattern"
2785
2786         stripes=$($LFS getstripe -c $name)
2787         # LFSCK does not know the old f3 had 3 stripes.
2788         # It only tries to find as much as possible.
2789         # The stripe count depends on the last stripe's offset.
2790         [ $stripes -eq 2 ] ||
2791                 error "(8.3) expect the stripe count is 2, but got $stripes"
2792
2793         size=$(stat $name | awk '/Size:/ { print $2 }')
2794         # stripe2 is lost
2795         [ $size -eq $((4096 * (256 + 256 + 0))) ] ||
2796                 error "(8.4) expect the size $((4096 * 512)), but got $size"
2797
2798         cat $name > /dev/null || error "(8.5) cannot read $name"
2799
2800         echo "dummy" >> $name || error "(8.6) cannot write $name"
2801
2802         chown $RUNAS_ID:$RUNAS_GID $name ||
2803                 error "(8.7) cannot chown on $name"
2804
2805         touch $name || error "(8.8) cannot touch $name"
2806
2807         rm -f $name || error "(8.9) cannot unlink $name"
2808 }
2809 run_test 20 "Handle the orphan with dummy LOV EA slot properly"
2810
2811 test_21() {
2812         [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.5.59) ]] &&
2813                 skip "ignore the test if MDS is older than 2.5.59" && return
2814
2815         check_mount_and_prep
2816         createmany -o $DIR/$tdir/f 100 || error "(0) Fail to create 100 files"
2817
2818         echo "Start all LFSCK components by default (-s 1)"
2819         do_facet mds1 $LCTL lfsck_start -M ${FSNAME}-MDT0000 -s 1 -r ||
2820                 error "Fail to start LFSCK"
2821
2822         echo "namespace LFSCK should be in 'scanning-phase1' status"
2823         local STATUS=$($SHOW_NAMESPACE | awk '/^status/ { print $2 }')
2824         [ "$STATUS" == "scanning-phase1" ] ||
2825                 error "Expect namespace 'scanning-phase1', but got '$STATUS'"
2826
2827         echo "layout LFSCK should be in 'scanning-phase1' status"
2828         STATUS=$($SHOW_LAYOUT | awk '/^status/ { print $2 }')
2829         [ "$STATUS" == "scanning-phase1" ] ||
2830                 error "Expect layout 'scanning-phase1', but got '$STATUS'"
2831
2832         echo "Stop all LFSCK components by default"
2833         do_facet mds1 $LCTL lfsck_stop -M ${FSNAME}-MDT0000 ||
2834                 error "Fail to stop LFSCK"
2835 }
2836 run_test 21 "run all LFSCK components by default"
2837
2838 test_22a() {
2839         [ $MDSCOUNT -lt 2 ] &&
2840                 skip "We need at least 2 MDSes for this test" && return
2841
2842         echo "#####"
2843         echo "The parent_A references the child directory via some name entry,"
2844         echo "but the child directory back references another parent_B via its"
2845         echo "".." name entry. The parent_B does not exist. Then the namespace"
2846         echo "LFSCK will repair the child directory's ".." name entry."
2847         echo "#####"
2848
2849         check_mount_and_prep
2850
2851         $LFS mkdir -i 1 $DIR/$tdir/guard || error "(1) Fail to mkdir on MDT1"
2852         $LFS mkdir -i 1 $DIR/$tdir/foo || error "(2) Fail to mkdir on MDT1"
2853
2854         echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
2855         echo "The dummy's dotdot name entry references the guard."
2856         #define OBD_FAIL_LFSCK_BAD_PARENT       0x161e
2857         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161e
2858         $LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
2859                 error "(3) Fail to mkdir on MDT0"
2860         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2861
2862         rmdir $DIR/$tdir/guard || error "(4) Fail to rmdir $DIR/$tdir/guard"
2863
2864         echo "Trigger namespace LFSCK to repair unmatched pairs"
2865         $START_NAMESPACE -A -r ||
2866                 error "(5) Fail to start LFSCK for namespace"
2867
2868         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
2869                 mdd.${MDT_DEV}.lfsck_namespace |
2870                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
2871                 $SHOW_NAMESPACE
2872                 error "(6) unexpected status"
2873         }
2874
2875         local repaired=$($SHOW_NAMESPACE |
2876                          awk '/^unmatched_pairs_repaired/ { print $2 }')
2877         [ $repaired -eq 1 ] ||
2878                 error "(7) Fail to repair unmatched pairs: $repaired"
2879
2880         echo "'ls' should success after namespace LFSCK repairing"
2881         ls -ail $DIR/$tdir/foo/dummy > /dev/null ||
2882                 error "(8) ls should success."
2883 }
2884 run_test 22a "LFSCK can repair unmatched pairs (1)"
2885
2886 test_22b() {
2887         [ $MDSCOUNT -lt 2 ] &&
2888                 skip "We need at least 2 MDSes for this test" && return
2889
2890         echo "#####"
2891         echo "The parent_A references the child directory via the name entry_B,"
2892         echo "but the child directory back references another parent_C via its"
2893         echo "".." name entry. The parent_C exists, but there is no the name"
2894         echo "entry_B under the parent_C. Then the namespace LFSCK will repair"
2895         echo "the child directory's ".." name entry and its linkEA."
2896         echo "#####"
2897
2898         check_mount_and_prep
2899
2900         $LFS mkdir -i 1 $DIR/$tdir/guard || error "(1) Fail to mkdir on MDT1"
2901         $LFS mkdir -i 1 $DIR/$tdir/foo || error "(2) Fail to mkdir on MDT1"
2902
2903         echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
2904         echo "and bad linkEA. The dummy's dotdot name entry references the"
2905         echo "guard. The dummy's linkEA references n non-exist name entry."
2906         #define OBD_FAIL_LFSCK_BAD_PARENT       0x161e
2907         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161e
2908         $LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
2909                 error "(3) Fail to mkdir on MDT0"
2910         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
2911
2912         local dummyfid=$($LFS path2fid $DIR/$tdir/foo/dummy)
2913         echo "fid2path should NOT work on the dummy's FID $dummyfid"
2914         local dummyname=$($LFS fid2path $DIR $dummyfid)
2915         [ "$dummyname" != "$DIR/$tdir/foo/dummy" ] ||
2916                 error "(4) fid2path works unexpectedly."
2917
2918         echo "Trigger namespace LFSCK to repair unmatched pairs"
2919         $START_NAMESPACE -A -r ||
2920                 error "(5) Fail to start LFSCK for namespace"
2921
2922         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
2923                 mdd.${MDT_DEV}.lfsck_namespace |
2924                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
2925                 $SHOW_NAMESPACE
2926                 error "(6) unexpected status"
2927         }
2928
2929         local repaired=$($SHOW_NAMESPACE |
2930                          awk '/^unmatched_pairs_repaired/ { print $2 }')
2931         [ $repaired -eq 1 ] ||
2932                 error "(7) Fail to repair unmatched pairs: $repaired"
2933
2934         echo "fid2path should work on the dummy's FID $dummyfid after LFSCK"
2935         local dummyname=$($LFS fid2path $DIR $dummyfid)
2936         [ "$dummyname" == "$DIR/$tdir/foo/dummy" ] ||
2937                 error "(8) fid2path does not work"
2938 }
2939 run_test 22b "LFSCK can repair unmatched pairs (2)"
2940
2941 test_23a() {
2942         [ $MDSCOUNT -lt 2 ] &&
2943                 skip "We need at least 2 MDSes for this test" && return
2944
2945         echo "#####"
2946         echo "The name entry is there, but the MDT-object for such name "
2947         echo "entry does not exist. The namespace LFSCK should find out "
2948         echo "and repair the inconsistency as required."
2949         echo "#####"
2950
2951         check_mount_and_prep
2952
2953         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
2954         $LFS mkdir -i 1 $DIR/$tdir/d0/d1 || error "(2) Fail to mkdir d1 on MDT1"
2955
2956         echo "Inject failure stub on MDT1 to simulate dangling name entry"
2957         #define OBD_FAIL_LFSCK_DANGLING2        0x1620
2958         do_facet mds2 $LCTL set_param fail_loc=0x1620
2959         rmdir $DIR/$tdir/d0/d1 || error "(3) Fail to rmdir d1"
2960         do_facet mds2 $LCTL set_param fail_loc=0
2961
2962         echo "'ls' should fail because of dangling name entry"
2963         ls -ail $DIR/$tdir/d0/d1 > /dev/null 2>&1 && error "(4) ls should fail."
2964
2965         echo "Trigger namespace LFSCK to find out dangling name entry"
2966         $START_NAMESPACE -A -r ||
2967                 error "(5) Fail to start LFSCK for namespace"
2968
2969         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
2970                 mdd.${MDT_DEV}.lfsck_namespace |
2971                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
2972                 $SHOW_NAMESPACE
2973                 error "(6) unexpected status"
2974         }
2975
2976         local repaired=$($SHOW_NAMESPACE |
2977                          awk '/^dangling_repaired/ { print $2 }')
2978         [ $repaired -eq 1 ] ||
2979                 error "(7) Fail to repair dangling name entry: $repaired"
2980
2981         echo "'ls' should fail because not re-create MDT-object by default"
2982         ls -ail $DIR/$tdir/d0/d1 > /dev/null 2>&1 && error "(8) ls should fail."
2983
2984         echo "Trigger namespace LFSCK again to repair dangling name entry"
2985         $START_NAMESPACE -A -r -C ||
2986                 error "(9) Fail to start LFSCK for namespace"
2987
2988         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
2989                 mdd.${MDT_DEV}.lfsck_namespace |
2990                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
2991                 $SHOW_NAMESPACE
2992                 error "(10) unexpected status"
2993         }
2994
2995         repaired=$($SHOW_NAMESPACE |
2996                    awk '/^dangling_repaired/ { print $2 }')
2997         [ $repaired -eq 1 ] ||
2998                 error "(11) Fail to repair dangling name entry: $repaired"
2999
3000         echo "'ls' should success after namespace LFSCK repairing"
3001         ls -ail $DIR/$tdir/d0/d1 > /dev/null || error "(12) ls should success."
3002 }
3003 run_test 23a "LFSCK can repair dangling name entry (1)"
3004
3005 test_23b() {
3006         echo "#####"
3007         echo "The objectA has multiple hard links, one of them corresponding"
3008         echo "to the name entry_B. But there is something wrong for the name"
3009         echo "entry_B and cause entry_B to references non-exist object_C."
3010         echo "In the first-stage scanning, the LFSCK will think the entry_B"
3011         echo "as dangling, and re-create the lost object_C. When the LFSCK"
3012         echo "comes to the second-stage scanning, it will find that the"
3013         echo "former re-creating object_C is not proper, and will try to"
3014         echo "replace the object_C with the real object_A."
3015         echo "#####"
3016
3017         check_mount_and_prep
3018
3019         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
3020         echo "dummy" > $DIR/$tdir/d0/f0 || error "(2) Fail to touch on MDT0"
3021         echo "dead" > $DIR/$tdir/d0/f1 || error "(3) Fail to touch on MDT0"
3022
3023         echo "Inject failure stub on MDT0 to simulate dangling name entry"
3024         #define OBD_FAIL_LFSCK_DANGLING3        0x1621
3025         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1621
3026         ln $DIR/$tdir/d0/f0 $DIR/$tdir/d0/foo || error "(4) Fail to hard link"
3027         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3028
3029         rm -f $DIR/$tdir/d0/f1 || error "(5) Fail to unlink $DIR/$tdir/d0/f1"
3030
3031         echo "'ls' should fail because of dangling name entry"
3032         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
3033                 error "(6) ls should fail."
3034
3035         echo "Trigger namespace LFSCK to find out dangling name entry"
3036         $START_NAMESPACE -r -C ||
3037                 error "(7) Fail to start LFSCK for namespace"
3038
3039         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3040                 mdd.${MDT_DEV}.lfsck_namespace |
3041                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3042                 $SHOW_NAMESPACE
3043                 error "(8) unexpected status"
3044         }
3045
3046         local repaired=$($SHOW_NAMESPACE |
3047                          awk '/^dangling_repaired/ { print $2 }')
3048         [ $repaired -eq 1 ] ||
3049                 error "(9) Fail to repair dangling name entry: $repaired"
3050
3051         repaired=$($SHOW_NAMESPACE |
3052                    awk '/^multiple_linked_repaired/ { print $2 }')
3053         [ $repaired -eq 1 ] ||
3054                 error "(10) Fail to drop the former created object: $repaired"
3055
3056         local data=$(cat $DIR/$tdir/d0/foo)
3057         [ "$data" == "dummy" ] ||
3058                 error "(11) The $DIR/$tdir/d0/foo is not recovered: $data"
3059 }
3060 run_test 23b "LFSCK can repair dangling name entry (2)"
3061
3062 test_23c() {
3063         echo "#####"
3064         echo "The objectA has multiple hard links, one of them corresponding"
3065         echo "to the name entry_B. But there is something wrong for the name"
3066         echo "entry_B and cause entry_B to references non-exist object_C."
3067         echo "In the first-stage scanning, the LFSCK will think the entry_B"
3068         echo "as dangling, and re-create the lost object_C. And then others"
3069         echo "modified the re-created object_C. When the LFSCK comes to the"
3070         echo "second-stage scanning, it will find that the former re-creating"
3071         echo "object_C maybe wrong and try to replace the object_C with the"
3072         echo "real object_A. But because object_C has been modified, so the"
3073         echo "LFSCK cannot replace it."
3074         echo "#####"
3075
3076         check_mount_and_prep
3077
3078         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0 on MDT0"
3079         echo "dummy" > $DIR/$tdir/d0/f0 || error "(2) Fail to touch on MDT0"
3080         echo "dead" > $DIR/$tdir/d0/f1 || error "(3) Fail to touch on MDT0"
3081
3082         echo "Inject failure stub on MDT0 to simulate dangling name entry"
3083         #define OBD_FAIL_LFSCK_DANGLING3        0x1621
3084         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1621
3085         ln $DIR/$tdir/d0/f0 $DIR/$tdir/d0/foo || error "(4) Fail to hard link"
3086         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3087
3088         rm -f $DIR/$tdir/d0/f1 || error "(5) Fail to unlink $DIR/$tdir/d0/f1"
3089
3090         echo "'ls' should fail because of dangling name entry"
3091         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 &&
3092                 error "(6) ls should fail."
3093
3094         #define OBD_FAIL_LFSCK_DELAY3           0x1602
3095         do_facet $SINGLEMDS $LCTL set_param fail_val=10 fail_loc=0x1602
3096
3097         echo "Trigger namespace LFSCK to find out dangling name entry"
3098         $START_NAMESPACE -r -C ||
3099                 error "(7) Fail to start LFSCK for namespace"
3100
3101         wait_update_facet client "stat $DIR/$tdir/d0/foo |
3102                 awk '/Size/ { print \\\$2 }'" "0" 32 || {
3103                 stat $DIR/$tdir/guard
3104                 $SHOW_NAMESPACE
3105                 error "(8) unexpected size"
3106         }
3107
3108         echo "data" >> $DIR/$tdir/d0/foo || error "(9) Fail to write"
3109         cancel_lru_locks osc
3110
3111         do_facet $SINGLEMDS $LCTL set_param fail_val=0 fail_loc=0
3112         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3113                 mdd.${MDT_DEV}.lfsck_namespace |
3114                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3115                 $SHOW_NAMESPACE
3116                 error "(10) unexpected status"
3117         }
3118
3119         local repaired=$($SHOW_NAMESPACE |
3120                          awk '/^dangling_repaired/ { print $2 }')
3121         [ $repaired -eq 1 ] ||
3122                 error "(11) Fail to repair dangling name entry: $repaired"
3123
3124         local data=$(cat $DIR/$tdir/d0/foo)
3125         [ "$data" != "dummy" ] ||
3126                 error "(12) The $DIR/$tdir/d0/foo should not be recovered"
3127 }
3128 run_test 23c "LFSCK can repair dangling name entry (3)"
3129
3130 test_24() {
3131         [ $MDSCOUNT -lt 2 ] &&
3132                 skip "We need at least 2 MDSes for this test" && return
3133
3134         echo "#####"
3135         echo "Two MDT-objects back reference the same name entry via their"
3136         echo "each own linkEA entry, but the name entry only references one"
3137         echo "MDT-object. The namespace LFSCK will remove the linkEA entry"
3138         echo "for the MDT-object that is not recognized. If such MDT-object"
3139         echo "has no other linkEA entry after the removing, then the LFSCK"
3140         echo "will add it as orphan under the .lustre/lost+found/MDTxxxx/."
3141         echo "#####"
3142
3143         check_mount_and_prep
3144
3145         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3146
3147         mkdir $DIR/$tdir/d0/guard || error "(1) Fail to mkdir guard"
3148         $LFS path2fid $DIR/$tdir/d0/guard
3149
3150         mkdir $DIR/$tdir/d0/dummy || error "(2) Fail to mkdir dummy"
3151         $LFS path2fid $DIR/$tdir/d0/dummy
3152
3153         local pfid
3154         if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
3155                 pfid=$($LFS path2fid $DIR/$tdir/d0/guard)
3156         else
3157                 pfid=$($LFS path2fid $DIR/$tdir/d0/dummy)
3158         fi
3159
3160         touch $DIR/$tdir/d0/guard/foo ||
3161                 error "(3) Fail to touch $DIR/$tdir/d0/guard/foo"
3162
3163         echo "Inject failure stub on MDT0 to simulate the case that"
3164         echo "the $DIR/$tdir/d0/dummy/foo has the 'bad' linkEA entry"
3165         echo "that references $DIR/$tdir/d0/guard/foo."
3166         echo "Then remove the name entry $DIR/$tdir/d0/dummy/foo."
3167         echo "So the MDT-object $DIR/$tdir/d0/dummy/foo will be left"
3168         echo "there with the same linkEA entry as another MDT-object"
3169         echo "$DIR/$tdir/d0/guard/foo has"
3170
3171         #define OBD_FAIL_LFSCK_MUL_REF          0x1622
3172         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1622
3173         $LFS mkdir -i 0 $DIR/$tdir/d0/dummy/foo ||
3174                 error "(4) Fail to mkdir $DIR/$tdir/d0/dummy/foo"
3175         $LFS path2fid $DIR/$tdir/d0/dummy/foo
3176         local cfid=$($LFS path2fid $DIR/$tdir/d0/dummy/foo)
3177         rmdir $DIR/$tdir/d0/dummy/foo ||
3178                 error "(5) Fail to remove $DIR/$tdir/d0/dummy/foo name entry"
3179         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3180
3181         echo "stat $DIR/$tdir/d0/dummy/foo should fail"
3182         stat $DIR/$tdir/d0/dummy/foo > /dev/null 2>&1 &&
3183                 error "(6) stat successfully unexpectedly"
3184
3185         echo "Trigger namespace LFSCK to repair multiple-referenced name entry"
3186         $START_NAMESPACE -A -r ||
3187                 error "(7) Fail to start LFSCK for namespace"
3188
3189         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3190                 mdd.${MDT_DEV}.lfsck_namespace |
3191                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3192                 $SHOW_NAMESPACE
3193                 error "(8) unexpected status"
3194         }
3195
3196         local repaired=$($SHOW_NAMESPACE |
3197                          awk '/^multiple_referenced_repaired/ { print $2 }')
3198         [ $repaired -eq 1 ] ||
3199         error "(9) Fail to repair multiple referenced name entry: $repaired"
3200
3201         echo "There should be an orphan under .lustre/lost+found/MDT0000/"
3202         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
3203                 error "(10) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
3204
3205         local cname="$cfid-$pfid-D-0"
3206         ls -ail $MOUNT/.lustre/lost+found/MDT0000/$cname ||
3207                 error "(11) .lustre/lost+found/MDT0000/ should not be empty"
3208 }
3209 run_test 24 "LFSCK can repair multiple-referenced name entry"
3210
3211 test_25() {
3212         [ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
3213                 skip "Only support to inject failure on ldiskfs" && return
3214
3215         echo "#####"
3216         echo "The file type in the name entry does not match the file type"
3217         echo "claimed by the referenced object. Then the LFSCK will update"
3218         echo "the file type in the name entry."
3219         echo "#####"
3220
3221         check_mount_and_prep
3222
3223         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3224
3225         echo "Inject failure stub on MDT0 to simulate the case that"
3226         echo "the file type stored in the name entry is wrong."
3227
3228         #define OBD_FAIL_LFSCK_BAD_TYPE         0x1623
3229         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1623
3230         touch $DIR/$tdir/d0/foo || error "(2) Fail to touch $DIR/$tdir/d0/foo"
3231         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3232
3233         echo "Trigger namespace LFSCK to repair bad file type in the name entry"
3234         $START_NAMESPACE -r || error "(3) Fail to start LFSCK for namespace"
3235
3236         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3237                 mdd.${MDT_DEV}.lfsck_namespace |
3238                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3239                 $SHOW_NAMESPACE
3240                 error "(4) unexpected status"
3241         }
3242
3243         local repaired=$($SHOW_NAMESPACE |
3244                          awk '/^bad_file_type_repaired/ { print $2 }')
3245         [ $repaired -eq 1 ] ||
3246         error "(5) Fail to repair bad file type in name entry: $repaired"
3247
3248         ls -ail $DIR/$tdir/d0 || error "(6) Fail to 'ls' the $DIR/$tdir/d0"
3249 }
3250 run_test 25 "LFSCK can repair bad file type in the name entry"
3251
3252 test_26a() {
3253         echo "#####"
3254         echo "The local name entry back referenced by the MDT-object is lost."
3255         echo "The namespace LFSCK will add the missing local name entry back"
3256         echo "to the normal namespace."
3257         echo "#####"
3258
3259         check_mount_and_prep
3260
3261         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3262         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
3263         local foofid=$($LFS path2fid $DIR/$tdir/d0/foo)
3264
3265         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/dummy ||
3266                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
3267
3268         echo "Inject failure stub on MDT0 to simulate the case that"
3269         echo "foo's name entry will be removed, but the foo's object"
3270         echo "and its linkEA are kept in the system."
3271
3272         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
3273         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
3274         rm -f $DIR/$tdir/d0/foo || error "(4) Fail to unlink $DIR/$tdir/d0/foo"
3275         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3276
3277         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 && "(5) 'ls' should fail"
3278
3279         echo "Trigger namespace LFSCK to repair the missing remote name entry"
3280         $START_NAMESPACE -r -A ||
3281                 error "(6) Fail to start LFSCK for namespace"
3282
3283         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3284                 mdd.${MDT_DEV}.lfsck_namespace |
3285                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3286                 $SHOW_NAMESPACE
3287                 error "(7) unexpected status"
3288         }
3289
3290         local repaired=$($SHOW_NAMESPACE |
3291                          awk '/^lost_dirent_repaired/ { print $2 }')
3292         [ $repaired -eq 1 ] ||
3293                 error "(8) Fail to repair lost dirent: $repaired"
3294
3295         ls -ail $DIR/$tdir/d0/foo ||
3296                 error "(9) Fail to 'ls' $DIR/$tdir/d0/foo"
3297
3298         local foofid2=$($LFS path2fid $DIR/$tdir/d0/foo)
3299         [ "$foofid" == "$foofid2" ] ||
3300                 error "(10) foo's FID changed: $foofid, $foofid2"
3301 }
3302 run_test 26a "LFSCK can add the missing local name entry back to the namespace"
3303
3304 test_26b() {
3305         [ $MDSCOUNT -lt 2 ] &&
3306                 skip "We need at least 2 MDSes for this test" && return
3307
3308         echo "#####"
3309         echo "The remote name entry back referenced by the MDT-object is lost."
3310         echo "The namespace LFSCK will add the missing remote name entry back"
3311         echo "to the normal namespace."
3312         echo "#####"
3313
3314         check_mount_and_prep
3315
3316         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3317         $LFS mkdir -i 0 $DIR/$tdir/d0/foo || error "(2) Fail to mkdir foo"
3318         local foofid=$($LFS path2fid $DIR/$tdir/d0/foo)
3319
3320         echo "Inject failure stub on MDT0 to simulate the case that"
3321         echo "foo's name entry will be removed, but the foo's object"
3322         echo "and its linkEA are kept in the system."
3323
3324         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
3325         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
3326         rmdir $DIR/$tdir/d0/foo || error "(3) Fail to rmdir $DIR/$tdir/d0/foo"
3327         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3328
3329         ls -ail $DIR/$tdir/d0/foo > /dev/null 2>&1 && "(4) 'ls' should fail"
3330
3331         echo "Trigger namespace LFSCK to repair the missing remote name entry"
3332         $START_NAMESPACE -r -A ||
3333                 error "(5) Fail to start LFSCK for namespace"
3334
3335         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3336                 mdd.${MDT_DEV}.lfsck_namespace |
3337                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3338                 $SHOW_NAMESPACE
3339                 error "(6) unexpected status"
3340         }
3341
3342         local repaired=$($SHOW_NAMESPACE |
3343                          awk '/^lost_dirent_repaired/ { print $2 }')
3344         [ $repaired -eq 1 ] ||
3345                 error "(7) Fail to repair lost dirent: $repaired"
3346
3347         ls -ail $DIR/$tdir/d0/foo ||
3348                 error "(8) Fail to 'ls' $DIR/$tdir/d0/foo"
3349
3350         local foofid2=$($LFS path2fid $DIR/$tdir/d0/foo)
3351         [ "$foofid" == "$foofid2" ] ||
3352                 error "(9) foo's FID changed: $foofid, $foofid2"
3353 }
3354 run_test 26b "LFSCK can add the missing remote name entry back to the namespace"
3355
3356 test_27a() {
3357         echo "#####"
3358         echo "The local parent referenced by the MDT-object linkEA is lost."
3359         echo "The namespace LFSCK will re-create the lost parent as orphan."
3360         echo "#####"
3361
3362         check_mount_and_prep
3363
3364         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3365         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
3366         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/dummy ||
3367                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
3368
3369         echo "Inject failure stub on MDT0 to simulate the case that"
3370         echo "foo's name entry will be removed, but the foo's object"
3371         echo "and its linkEA are kept in the system. And then remove"
3372         echo "another hard link and the parent directory."
3373
3374         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
3375         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
3376         rm -f $DIR/$tdir/d0/foo ||
3377                 error "(4) Fail to unlink $DIR/$tdir/d0/foo"
3378         rm -f $DIR/$tdir/d0/dummy ||
3379                 error "(5) Fail to unlink $DIR/$tdir/d0/dummy"
3380         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3381
3382         rm -rf $DIR/$tdir/d0 || error "(5) Fail to unlink the dir d0"
3383         ls -ail $DIR/$tdir/d0 > /dev/null 2>&1 && "(6) 'ls' should fail"
3384
3385         echo "Trigger namespace LFSCK to repair the lost parent"
3386         $START_NAMESPACE -r -A ||
3387                 error "(6) Fail to start LFSCK for namespace"
3388
3389         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3390                 mdd.${MDT_DEV}.lfsck_namespace |
3391                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3392                 $SHOW_NAMESPACE
3393                 error "(7) unexpected status"
3394         }
3395
3396         local repaired=$($SHOW_NAMESPACE |
3397                          awk '/^lost_dirent_repaired/ { print $2 }')
3398         [ $repaired -eq 1 ] ||
3399                 error "(8) Fail to repair lost dirent: $repaired"
3400
3401         echo "There should be an orphan under .lustre/lost+found/MDT0000/"
3402         [ -d $MOUNT/.lustre/lost+found/MDT0000 ] ||
3403                 error "(9) $MOUNT/.lustre/lost+found/MDT0000/ should be there"
3404
3405         ls -ail $MOUNT/.lustre/lost+found/MDT0000/
3406
3407         cname=$(find $MOUNT/.lustre/lost+found/MDT0000/ -name *-P-*)
3408         [ ! -z "$cname" ] ||
3409                 error "(10) .lustre/lost+found/MDT0000/ should not be empty"
3410 }
3411 run_test 27a "LFSCK can recreate the lost local parent directory as orphan"
3412
3413 test_27b() {
3414         [ $MDSCOUNT -lt 2 ] &&
3415                 skip "We need at least 2 MDSes for this test" && return
3416
3417         echo "#####"
3418         echo "The remote parent referenced by the MDT-object linkEA is lost."
3419         echo "The namespace LFSCK will re-create the lost parent as orphan."
3420         echo "#####"
3421
3422         check_mount_and_prep
3423
3424         $LFS mkdir -i 1 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3425         $LFS mkdir -i 0 $DIR/$tdir/d0/foo || error "(2) Fail to mkdir foo"
3426
3427         $LFS path2fid $DIR/$tdir/d0
3428
3429         echo "Inject failure stub on MDT0 to simulate the case that"
3430         echo "foo's name entry will be removed, but the foo's object"
3431         echo "and its linkEA are kept in the system. And then remove"
3432         echo "the parent directory."
3433
3434         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
3435         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1624
3436         rmdir $DIR/$tdir/d0/foo || error "(3) Fail to rmdir $DIR/$tdir/d0/foo"
3437         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3438
3439         rmdir $DIR/$tdir/d0 || error "(4) Fail to unlink the dir d0"
3440         ls -ail $DIR/$tdir/d0 > /dev/null 2>&1 && "(5) 'ls' should fail"
3441
3442         echo "Trigger namespace LFSCK to repair the missing remote name entry"
3443         $START_NAMESPACE -r -A ||
3444                 error "(6) Fail to start LFSCK for namespace"
3445
3446         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3447                 mdd.${MDT_DEV}.lfsck_namespace |
3448                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3449                 $SHOW_NAMESPACE
3450                 error "(7) unexpected status"
3451         }
3452
3453         local repaired=$($SHOW_NAMESPACE |
3454                          awk '/^lost_dirent_repaired/ { print $2 }')
3455         [ $repaired -eq 1 ] ||
3456                 error "(8) Fail to repair lost dirent: $repaired"
3457
3458         ls -ail $MOUNT/.lustre/lost+found/
3459
3460         echo "There should be an orphan under .lustre/lost+found/MDT0001/"
3461         [ -d $MOUNT/.lustre/lost+found/MDT0001 ] ||
3462                 error "(9) $MOUNT/.lustre/lost+found/MDT0001/ should be there"
3463
3464         ls -ail $MOUNT/.lustre/lost+found/MDT0001/
3465
3466         cname=$(find $MOUNT/.lustre/lost+found/MDT0001/ -name *-P-*)
3467         [ ! -z "$cname" ] ||
3468                 error "(10) .lustre/lost+found/MDT0001/ should not be empty"
3469 }
3470 run_test 27b "LFSCK can recreate the lost remote parent directory as orphan"
3471
3472 test_28() {
3473         [ $MDSCOUNT -lt 2 ] &&
3474                 skip "The test needs at least 2 MDTs" && return
3475
3476         echo "#####"
3477         echo "The target name entry is lost. The LFSCK should insert the"
3478         echo "orphan MDT-object under .lustre/lost+found/MDTxxxx. But if"
3479         echo "the MDT (on which the orphan MDT-object resides) has ever"
3480         echo "failed to respond some name entry verification during the"
3481         echo "first stage-scanning, then the LFSCK should skip to handle"
3482         echo "orphan MDT-object on this MDT. But other MDTs should not"
3483         echo "be affected."
3484         echo "#####"
3485
3486         check_mount_and_prep
3487         $LFS mkdir -i 0 $DIR/$tdir/d1
3488         $LFS mkdir -i 1 $DIR/$tdir/d1/a1
3489         $LFS mkdir -i 1 $DIR/$tdir/d1/a2
3490
3491         $LFS mkdir -i 1 $DIR/$tdir/d2
3492         $LFS mkdir -i 0 $DIR/$tdir/d2/a1
3493         $LFS mkdir -i 0 $DIR/$tdir/d2/a2
3494
3495         echo "Inject failure stub on MDT0 to simulate the case that"
3496         echo "d1/a1's name entry will be removed, but the d1/a1's object"
3497         echo "and its linkEA are kept in the system. And the case that"
3498         echo "d2/a2's name entry will be removed, but the d2/a2's object"
3499         echo "and its linkEA are kept in the system."
3500
3501         #define OBD_FAIL_LFSCK_NO_NAMEENTRY     0x1624
3502         do_facet mds1 $LCTL set_param fail_loc=0x1624
3503         do_facet mds2 $LCTL set_param fail_loc=0x1624
3504         rmdir $DIR/$tdir/d1/a1 || error "(1) Fail to rmdir $DIR/$tdir/d1/a1"
3505         rmdir $DIR/$tdir/d2/a2 || error "(2) Fail to rmdir $DIR/$tdir/d2/a2"
3506         do_facet mds1 $LCTL set_param fail_loc=0
3507         do_facet mds2 $LCTL set_param fail_loc=0
3508
3509         cancel_lru_locks mdc
3510         cancel_lru_locks osc
3511
3512         echo "Inject failure, to simulate the MDT0 fail to handle"
3513         echo "MDT1 LFSCK request during the first-stage scanning."
3514         #define OBD_FAIL_LFSCK_BAD_NETWORK      0x161c
3515         do_facet mds2 $LCTL set_param fail_loc=0x161c fail_val=0
3516
3517         echo "Trigger namespace LFSCK on all devices to find out orphan object"
3518         $START_NAMESPACE -r -A ||
3519                 error "(3) Fail to start LFSCK for namespace"
3520
3521         wait_update_facet mds1 "$LCTL get_param -n \
3522                 mdd.$(facet_svc mds1).lfsck_namespace |
3523                 awk '/^status/ { print \\\$2 }'" "partial" 32 || {
3524                 error "(4) mds1 is not the expected 'partial'"
3525         }
3526
3527         wait_update_facet mds2 "$LCTL get_param -n \
3528                 mdd.$(facet_svc mds2).lfsck_namespace |
3529                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3530                 error "(5) mds2 is not the expected 'completed'"
3531         }
3532
3533         do_facet mds2 $LCTL set_param fail_loc=0 fail_val=0
3534
3535         local repaired=$(do_facet mds1 $LCTL get_param -n \
3536                          mdd.$(facet_svc mds1).lfsck_namespace |
3537                          awk '/^lost_dirent_repaired/ { print $2 }')
3538         [ $repaired -eq 0 ] ||
3539                 error "(6) Expect 0 fixed on mds1, but got: $repaired"
3540
3541         repaired=$(do_facet mds2 $LCTL get_param -n \
3542                    mdd.$(facet_svc mds2).lfsck_namespace |
3543                    awk '/^lost_dirent_repaired/ { print $2 }')
3544         [ $repaired -eq 1 ] ||
3545                 error "(7) Expect 1 fixed on mds2, but got: $repaired"
3546
3547         echo "Trigger namespace LFSCK on all devices again to cleanup"
3548         $START_NAMESPACE -r -A ||
3549                 error "(8) Fail to start LFSCK for namespace"
3550
3551         for k in $(seq $MDSCOUNT); do
3552                 # The LFSCK status query internal is 30 seconds. For the case
3553                 # of some LFSCK_NOTIFY RPCs failure/lost, we will wait enough
3554                 # time to guarantee the status sync up.
3555                 wait_update_facet mds${k} "$LCTL get_param -n \
3556                         mdd.$(facet_svc mds${k}).lfsck_namespace |
3557                         awk '/^status/ { print \\\$2 }'" "completed" 32 ||
3558                         error "(9) MDS${k} is not the expected 'completed'"
3559         done
3560
3561         local repaired=$(do_facet mds1 $LCTL get_param -n \
3562                          mdd.$(facet_svc mds1).lfsck_namespace |
3563                          awk '/^lost_dirent_repaired/ { print $2 }')
3564         [ $repaired -eq 1 ] ||
3565                 error "(10) Expect 1 fixed on mds1, but got: $repaired"
3566
3567         repaired=$(do_facet mds2 $LCTL get_param -n \
3568                    mdd.$(facet_svc mds2).lfsck_namespace |
3569                    awk '/^lost_dirent_repaired/ { print $2 }')
3570         [ $repaired -eq 0 ] ||
3571                 error "(11) Expect 0 fixed on mds2, but got: $repaired"
3572 }
3573 run_test 28 "Skip the failed MDT(s) when handle orphan MDT-objects"
3574
3575 test_29a() {
3576         echo "#####"
3577         echo "The object's nlink attribute is larger than the object's known"
3578         echo "name entries count. The LFSCK will repair the object's nlink"
3579         echo "attribute to match the known name entries count"
3580         echo "#####"
3581
3582         check_mount_and_prep
3583
3584         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3585         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
3586
3587         echo "Inject failure stub on MDT0 to simulate the case that foo's"
3588         echo "nlink attribute is larger than its name entries count."
3589
3590         #define OBD_FAIL_LFSCK_MORE_NLINK       0x1625
3591         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1625
3592         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/h1 ||
3593                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
3594         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3595
3596         cancel_lru_locks mdc
3597         local count=$(stat --format=%h $DIR/$tdir/d0/foo)
3598         [ $count -eq 3 ] || error "(4) Cannot inject error: $count"
3599
3600         echo "Trigger namespace LFSCK to repair the nlink count"
3601         $START_NAMESPACE -r -A ||
3602                 error "(5) Fail to start LFSCK for namespace"
3603
3604         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3605                 mdd.${MDT_DEV}.lfsck_namespace |
3606                 awk '/^status/ { print \\\$2 }'" "completed" 32 || {
3607                 $SHOW_NAMESPACE
3608                 error "(6) unexpected status"
3609         }
3610
3611         local repaired=$($SHOW_NAMESPACE |
3612                          awk '/^nlinks_repaired/ { print $2 }')
3613         [ $repaired -eq 1 ] ||
3614                 error "(7) Fail to repair nlink count: $repaired"
3615
3616         cancel_lru_locks mdc
3617         count=$(stat --format=%h $DIR/$tdir/d0/foo)
3618         [ $count -eq 2 ] || error "(8) Fail to repair nlink count: $count"
3619 }
3620 run_test 29a "LFSCK can repair bad nlink count (1)"
3621
3622 test_29b() {
3623         echo "#####"
3624         echo "The object's nlink attribute is smaller than the object's known"
3625         echo "name entries count. The LFSCK will repair the object's nlink"
3626         echo "attribute to match the known name entries count"
3627         echo "#####"
3628
3629         check_mount_and_prep
3630
3631         $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
3632         touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
3633
3634         echo "Inject failure stub on MDT0 to simulate the case that foo's"
3635         echo "nlink attribute is smaller than its name entries count."
3636
3637         #define OBD_FAIL_LFSCK_LESS_NLINK       0x1626
3638         do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1626
3639         ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/h1 ||
3640                 error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
3641         do_facet $SINGLEMDS $LCTL set_param fail_loc=0
3642
3643         cancel_lru_locks mdc
3644         local count=$(stat --format=%h $DIR/$tdir/d0/foo)
3645         [ $count -eq 1 ] || error "(4) Cannot inject error: $count"
3646
3647         echo "Trigger namespace LFSCK to repair the nlink count"
3648         $START_NAMESPACE -r -A ||
3649                 error "(5) Fail to start LFSCK for namespace"
3650
3651         wait_update_facet $SINGLEMDS "$LCTL get_param -n \
3652                 mdd.${MDT_DEV}.lfsck_namespace |
3653                 awk '/