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