3 # test e2fsck and lfsck to detect and fix filesystem corruption
8 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
9 . $LUSTRE/tests/test-framework.sh
11 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
13 NUMFILES=${NUMFILES:-10}
15 OSTIDX=${OSTIDX:-0} # the OST index in LOV
16 OBJGRP=${OBJGRP:-0} # the OST object group
18 [ -d "$SHARED_DIRECTORY" ] || \
19 { skip "SHARED_DIRECTORY should be specified with a shared directory \
20 which can be accessable on all of the nodes" && exit 0; }
22 which getfattr > /dev/null 2>&1 || { skip "could not find getfattr" && exit 0; }
23 which setfattr > /dev/null 2>&1 || { skip "could not find setfattr" && exit 0; }
26 check_and_setup_lustre
30 # Create some dirs and files on the filesystem.
39 for d in $(seq -f d%g $first_num $last_num); do
40 echo "creating files in $test_dir/$d"
41 for e in $(seq -f d%g $num_dirs); do
42 mkdir -p $test_dir/$d/$e || error "mkdir $test_dir/$d/$e failed"
43 for f in $(seq -f test%g $num_dirs); do
44 cp $file_name $test_dir/$d/$e/$f || \
45 error "cp $file_name $test_dir/$d/$e/$f failed"
57 # create some files on the filesystem
59 local last_num=$num_dirs
60 create_files_sub $test_dir $num_dirs /etc/fstab $first_num $last_num
62 # create files to be modified
63 for f in $(seq -f $test_dir/testfile.%g $((num_files * 3))); do
65 cp /etc/termcap $f || error "cp /etc/termcap $f failed"
68 # create some more files
69 first_num=$((num_dirs * 2 + 1))
70 last_num=$((num_dirs * 2 + 3))
71 create_files_sub $test_dir $num_dirs /etc/hosts $first_num $last_num
73 # these should NOT be taken as duplicates
74 for f in $(seq -f $test_dir/d$last_num/linkfile.%g $num_files); do
75 echo "linking files in $test_dir/d$last_num"
76 cp /etc/hosts $f || error "cp /etc/hosts $f failed"
77 ln $f $f.link || error "ln $f $f.link failed"
81 # Get the objids for files on the OST (given the OST index and object group).
89 ost_objids=$($LFS getstripe $ost_files | \
90 awk '{if ($1 == '$obdidx' && $4 == '$group') print $2 }')
94 # Get the OST nodet name (given the OST index).
101 ost_uuid=$($LFS osts | grep "^$obdidx: " | cut -d' ' -f2 | head -n1)
103 for node in $(osts_nodes); do
104 do_node $node "lctl get_param -n obdfilter.*.uuid" | grep -q $ost_uuid
105 [ ${PIPESTATUS[1]} -eq 0 ] && ost_node=$node && break
107 [ -z "$ost_node" ] && \
108 echo "failed to find the OST with index $obdidx" && return 1
112 # Get the OST target device (given the OST facet name and OST index).
119 ost_name=$($LFS osts | grep "^$obdidx: " | cut -d' ' -f2 | \
120 head -n1 | sed -e 's/_UUID$//')
122 ost_dev=$(do_node $node "lctl get_param -n obdfilter.$ost_name.mntdev")
123 [ ${PIPESTATUS[0]} -ne 0 ] && \
124 echo "failed to find the OST device with index $obdidx on $facet" && \
127 if [[ $ost_dev = *loop* ]]; then
128 ost_dev=$(do_node $node "losetup $ost_dev" | \
129 sed -e "s/.*(//" -e "s/).*//")
135 # Get the file names to be duplicated or removed on the MDS.
145 first=$((num_files + 1))
146 last=$((num_files * 2))
149 first=$((num_files * 2 + 1))
150 last=$((num_files * 3))
152 *) echo "get_files(): invalid flavor" && return 1 ;;
157 for f in $(seq -f testfile.%g $first $last); do
158 test_file=$test_dir/$f
159 files="$files $test_file"
161 files=$(echo $files | sed "s#$DIR/##g")
165 # Remove objects associated with files.
178 echo "removing objects from $ostdev on $facet: $objids"
179 tmp=$(mktemp $SHARED_DIRECTORY/debugfs.XXXXXXXXXX)
181 echo "rm O/$group/d$((i % 32))/$i" >> $tmp
184 do_node $node "$DEBUGFS -w -f $tmp $ostdev"
191 # Remove files from MDS.
193 do_rpc_nodes $(facet_host $1) remove_mdt_files $@
196 # Create EAs on files so objects are referenced from different files.
198 do_rpc_nodes $(facet_host $1) duplicate_mdt_files $@
201 #********************************* Main Flow **********************************#
203 # get the server target devices
206 if [ "$SKIP_LFSCK" = "no" ] && is_empty_fs $MOUNT; then
207 # create test directory
208 TESTDIR=$DIR/d0.$TESTSUITE
209 mkdir -p $TESTDIR || error "mkdir $TESTDIR failed"
211 # create some dirs and files on the filesystem
212 create_files $TESTDIR $NUMDIRS $NUMFILES
214 # get the objids for files in group $OBJGRP on the OST with index $OSTIDX
215 OST_REMOVE=$(get_objects $OSTIDX $OBJGRP \
216 $(seq -f $TESTDIR/testfile.%g $NUMFILES))
218 # get the node name and target device for the OST with index $OSTIDX
219 OSTNODE=$(get_ost_node $OSTIDX) || error "get_ost_node by index $OSTIDX failed"
220 OSTDEV=$(get_ost_dev $OSTNODE $OSTIDX) || \
221 error "get_ost_dev $OSTNODE $OSTIDX failed"
223 # get the file names to be duplicated on the MDS
224 MDS_DUPE=$(get_files dup $TESTDIR $NUMFILES) || error "$MDS_DUPE"
225 # get the file names to be removed from the MDS
226 MDS_REMOVE=$(get_files remove $TESTDIR $NUMFILES) || error "$MDS_REMOVE"
228 stopall -f || error "cleanupall failed"
230 # remove objects associated with files in group $OBJGRP
231 # on the OST with index $OSTIDX
232 remove_objects $OSTNODE $OSTDEV $OBJGRP $OST_REMOVE || \
233 error "removing objects failed"
235 # remove files from MDS
236 remove_files mds $MDSDEV $MDS_REMOVE || error "removing files failed"
238 # create EAs on files so objects are referenced from different files
239 duplicate_files mds $MDSDEV $MDS_DUPE || \
240 error "duplicating files failed"
241 FSCK_MAX_ERR=1 # file system errors corrected
242 else # $SKIP_LFSCK = yes || !is_empty_fs $MOUNT
243 FSCK_MAX_ERR=4 # file system errors left uncorrected
246 # Test 1a - check and repair the filesystem
247 # lfsck will return 1 if the filesystem had errors fixed
248 # run e2fsck to generate databases used for lfsck
250 if [ "$SKIP_LFSCK" != "no" ]; then
255 check_and_setup_lustre
260 if [ $rc -eq 0 ]; then
261 echo "clean after the first check"
263 # run e2fsck again to generate databases used for lfsck
269 if [ $rc -eq 0 ]; then
270 echo "clean after the second check"
272 error "lfsck test 2 - finished with rc=$rc"
277 equals_msg $(basename $0): test complete, cleaning up
280 check_and_cleanup_lustre
281 [ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG && \
282 grep -q FAIL $TESTSUITELOG && exit 1 || true