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