Whamcloud - gitweb
LU-3409 llite: silence lockdep warning in ll_md_blocking_ast
[fs/lustre-release.git] / lustre / tests / lfsck.sh
1 #!/bin/bash
2 # -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*-
3 # vim:shiftwidth=4:softtabstop=4:tabstop=4:
4 #
5 # test e2fsck and lfsck to detect and fix filesystem corruption
6 #
7 #set -vx
8 set -e
9
10 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
11 . $LUSTRE/tests/test-framework.sh
12 init_test_env $@
13 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
14
15 NUMFILES=${NUMFILES:-10}
16 NUMDIRS=${NUMDIRS:-4}
17 OSTIDX=${OSTIDX:-0} # the OST index in LOV
18 OBJGRP=${OBJGRP:-0} # the OST object group
19
20 [ -d "$SHARED_DIRECTORY" ] || \
21     { skip "SHARED_DIRECTORY should be specified with a shared directory \
22 which can be accessable on all of the nodes" && exit 0; }
23 [[ $(facet_fstype $SINGLEMDS) != ldiskfs ]] &&
24         skip "Only applicable to ldiskfs-based MDTs" && exit 0
25 [[ $(facet_fstype OST) != ldiskfs ]] &&
26         skip "Only applicable to ldiskfs-based OST" && exit 0
27
28 which getfattr &>/dev/null || { skip_env "could not find getfattr" && exit 0; }
29 which setfattr &>/dev/null || { skip_env "could not find setfattr" && exit 0; }
30
31 MOUNT_2=""
32 check_and_setup_lustre
33
34 assert_DIR
35
36 SAMPLE_FILE=$TMP/$TESTSUITE.junk
37 dd if=/dev/urandom of=$SAMPLE_FILE bs=1M count=1
38
39 # Create some dirs and files on the filesystem.
40 create_files_sub() {
41     local test_dir=$1
42     local num_dirs=$2
43     local file_name=$3
44     local first_num=$4
45     local last_num=$5
46     local d e f
47
48     for d in $(seq -f d%g $first_num $last_num); do
49         echo "creating files in $test_dir/$d"
50         for e in $(seq -f d%g $num_dirs); do
51             mkdir -p $test_dir/$d/$e || error "mkdir $test_dir/$d/$e failed"
52             for f in $(seq -f test%g $num_dirs); do
53                 cp $file_name $test_dir/$d/$e/$f || \
54                     error "cp $file_name $test_dir/$d/$e/$f failed"
55             done
56         done
57     done
58 }
59
60 create_files() {
61     local test_dir=$1
62     local num_dirs=$2
63     local num_files=$3
64     local f
65
66     # create some files on the filesystem
67     local first_num=1
68     local last_num=$num_dirs
69     create_files_sub $test_dir $num_dirs /etc/fstab $first_num $last_num
70
71     # create files to be modified
72     for f in $(seq -f $test_dir/testfile.%g $((num_files * 3))); do
73         echo "creating $f"
74         cp $SAMPLE_FILE $f || error "cp $SAMPLE_FILE $f failed"
75     done
76
77     # create some more files
78     first_num=$((num_dirs * 2 + 1))
79     last_num=$((num_dirs * 2 + 3))
80     create_files_sub $test_dir $num_dirs /etc/hosts $first_num $last_num
81
82     # these should NOT be taken as duplicates
83     for f in $(seq -f $test_dir/d$last_num/linkfile.%g $num_files); do
84         echo "linking files in $test_dir/d$last_num"
85         cp /etc/hosts $f || error "cp /etc/hosts $f failed"
86         ln $f $f.link || error "ln $f $f.link failed"
87     done
88 }
89
90 # Get the objids for files on the OST (given the OST index and object group).
91 get_objects() {
92     local obdidx=$1
93     shift
94     local group=$1
95     shift
96     local ost_files="$@"
97     local ost_objids
98     ost_objids=$($LFS getstripe $ost_files | \
99                 awk '{if ($1 == '$obdidx' && $4 == '$group') print $2 }')
100     echo $ost_objids
101 }
102
103 # Get the OST nodet name (given the OST index).
104 get_ost_node() {
105     local obdidx=$1
106     local ost_uuid
107     local ost_node
108     local node
109
110     ost_uuid=$(ostuuid_from_index $obdidx)
111
112     for node in $(osts_nodes); do
113         do_node $node "lctl get_param -n obdfilter.*.uuid" | grep -q $ost_uuid
114         [ ${PIPESTATUS[1]} -eq 0 ] && ost_node=$node && break
115     done
116     [ -z "$ost_node" ] && \
117         echo "failed to find the OST with index $obdidx" && return 1
118     echo $ost_node
119 }
120
121 # Get the OST target device (given the OST facet name and OST index).
122 get_ost_dev() {
123         local node=$1
124         local obdidx=$2
125         local ost_name
126         local ost_dev
127
128         ost_name=$(ostname_from_index $obdidx)
129         ost_dev=$(get_osd_param $node $ost_name mntdev)
130         if [ $? -ne 0 ]; then
131                 printf "unable to find OST%04x on $facet\n" $obdidx
132                 return 1
133         fi
134
135         if [[ $ost_dev = *loop* ]]; then
136                 ost_dev=$(do_node $node "losetup $ost_dev" | \
137                           sed -e "s/.*(//" -e "s/).*//")
138         fi
139
140         echo $ost_dev
141 }
142
143 # Get the file names to be duplicated or removed on the MDS.
144 get_files() {
145     local flavor=$1
146     local test_dir=$2
147     local num_files=$3
148     local first last
149     local test_file
150
151     case $flavor in
152     dup)
153         first=$((num_files + 1))
154         last=$((num_files * 2))
155         ;;
156     remove)
157         first=$((num_files * 2 + 1))
158         last=$((num_files * 3))
159         ;;
160     *) echo "get_files(): invalid flavor" && return 1 ;;
161     esac
162
163     local files=""
164     local f
165     for f in $(seq -f testfile.%g $first $last); do
166         test_file=$test_dir/$f
167         files="$files $test_file"
168     done
169     files=$(echo $files | sed "s#$DIR/##g")
170     echo $files
171 }
172
173 # Remove objects associated with files.
174 remove_objects() {
175         do_rpc_nodes $1 remove_ost_objects $@
176 }
177
178 # Remove files from MDS.
179 remove_files() {
180     do_rpc_nodes $(facet_host $1) remove_mdt_files $@
181 }
182
183 # Create EAs on files so objects are referenced from different files.
184 duplicate_files() {
185     do_rpc_nodes $(facet_host $1) duplicate_mdt_files $@
186 }
187
188 #********************************* Main Flow **********************************#
189
190 init_logging
191
192 # get the server target devices
193 get_svr_devs
194
195 TESTDIR=$DIR/d0.$TESTSUITE
196 if is_empty_fs $MOUNT; then
197     # create test directory
198     mkdir -p $TESTDIR || error "mkdir $TESTDIR failed"
199
200     # create some dirs and files on the filesystem
201     create_files $TESTDIR $NUMDIRS $NUMFILES
202
203     # get the objids for files in group $OBJGRP on the OST with index $OSTIDX
204     OST_REMOVE=$(get_objects $OSTIDX $OBJGRP \
205                 $(seq -f $TESTDIR/testfile.%g $NUMFILES))
206
207     # get the node name and target device for the OST with index $OSTIDX
208     OSTNODE=$(get_ost_node $OSTIDX) || error "get_ost_node by index $OSTIDX failed"
209     OSTDEV=$(get_ost_dev $OSTNODE $OSTIDX) ||
210         error "get_ost_dev $OSTNODE $OSTIDX failed"
211
212     # get the file names to be duplicated on the MDS
213     MDS_DUPE=$(get_files dup $TESTDIR $NUMFILES) || error "$MDS_DUPE"
214     # get the file names to be removed from the MDS
215     MDS_REMOVE=$(get_files remove $TESTDIR $NUMFILES) || error "$MDS_REMOVE"
216
217     stopall -f || error "cleanupall failed"
218
219     # remove objects associated with files in group $OBJGRP
220     # on the OST with index $OSTIDX
221         remove_objects $OSTNODE $OSTDEV $OBJGRP $OST_REMOVE ||
222         error "removing objects failed"
223
224     # remove files from MDS
225     remove_files $SINGLEMDS $MDTDEV $MDS_REMOVE || error "removing files failed"
226
227     # create EAs on files so objects are referenced from different files
228     duplicate_files $SINGLEMDS $MDTDEV $MDS_DUPE ||
229         error "duplicating files failed"
230     FSCK_MAX_ERR=1   # file system errors corrected
231 else # is_empty_fs $MOUNT
232     FSCK_MAX_ERR=4   # file system errors left uncorrected
233 fi
234
235 # Test 1a - check and repair the filesystem
236 # lfsck will return 1 if the filesystem had errors fixed
237 # run e2fsck to generate databases used for lfsck
238 generate_db
239
240 # remount filesystem
241 ORIG_REFORMAT=$REFORMAT
242 REFORMAT=""
243 check_and_setup_lustre
244 REFORMAT=$ORIG_REFORMAT
245
246 # run lfsck
247 rc=0
248 run_lfsck || rc=$?
249 if [ $rc -eq 0 ]; then
250     echo "clean after the first check"
251 else
252     # run e2fsck again to generate databases used for lfsck
253     generate_db
254
255     # run lfsck again
256     rc=0
257     run_lfsck || rc=$?
258     if [ $rc -eq 0 ]; then
259         echo "clean after the second check"
260     else
261         error "lfsck test 2 - finished with rc=$rc"
262     fi
263 fi
264
265 complete $SECONDS
266 # The test directory contains some files referencing to some object
267 # which could cause error when removing the directory.
268 RMCNT=0
269 while [ -d $TESTDIR ]; do
270         RMCNT=$((RMCNT + 1))
271         rm -fr $TESTDIR || echo "$RMCNT round: rm $TESTDIR failed"
272         [ $RMCNT -ge 10 ] && error "cleanup $TESTDIR failed $RMCNT times"
273         remount_client $MOUNT
274 done
275 check_and_cleanup_lustre
276 exit_status