Whamcloud - gitweb
b=22075 buffalo-v2 should detect test timeouts
[fs/lustre-release.git] / lustre / tests / lfsck.sh
1 #!/bin/bash
2 #set -vx
3 set -e
4
5 TESTNAME="lfsck"
6 TMP=${TMP:-/tmp}
7 MDSDB=${MDSDB:-$TMP/mdsdb}
8 OSTDB=${OSTDB:-$TMP/ostdb}
9 LOG=${LOG:-"$TMP/lfsck.log"}
10 L2FSCK_PATH=${L2FSCK_PATH:-""}
11 NUMFILES=${NUMFILES:-10}
12 NUMDIRS=${NUMDIRS:-4}
13 LFIND=${LFIND:-"lfs find"}
14 GETFATTR=${GETFATTR:-getfattr}
15 SETFATTR=${SETFATTR:-setfattr}
16 MAX_ERR=1
17
18 export PATH=$LFSCK_PATH:`dirname $0`:`dirname $0`/../utils:$PATH
19
20 [ -z "`which $GETFATTR`" ] && echo "$0: $GETFATTR not found" && exit 5
21 [ -z "`which $SETFATTR`" ] && echo "$0: $SETFATTR not found" && exit 6
22
23 LUSTRE=${LUSTRE:-`dirname $0`/..}
24 . $LUSTRE/tests/test-framework.sh
25 init_test_env $@
26 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
27 init_logging
28
29 require_dsh_mds || exit 0
30 require_dsh_ost || exit 0
31
32 if [ ! -x /usr/sbin/lfsck ]; then
33     log "$($E2FSCK -V)"
34     log "SKIP: $E2FSCK does not support lfsck"
35     exit 0
36 fi
37
38 # if nothing mounted, don't nuke MOUNT variable needed in llmount.sh
39 WAS_MOUNTED=$(mounted_lustre_filesystems | head -1)
40 if [ -z "$WAS_MOUNTED" ]; then
41        # This code doesn't handle multiple mounts well, so nuke MOUNT2 variable
42         MOUNT2="" sh llmount.sh
43         MOUNT=$(mounted_lustre_filesystems)
44         [ -z "$MOUNT" ] && echo "NAME=$NAME not mounted" && exit 2
45 else
46         MOUNT=${WAS_MOUNTED}
47 fi
48
49 DIR=${DIR:-$MOUNT/$TESTNAME}
50 [ -z "`echo $DIR | grep $MOUNT`" ] && echo "$DIR not in $MOUNT" && exit 3
51
52 if [ "$WAS_MOUNTED" ]; then
53         LFSCK_SETUP=no
54         MAX_ERR=4               # max expected error from e2fsck
55 fi
56
57 get_mnt_devs() {
58         DEVS=`lctl get_param -n $1.*.mntdev`
59         for DEV in $DEVS; do
60                 case $DEV in
61                 *loop*) losetup $DEV | sed -e "s/.*(//" -e "s/).*//" ;;
62                 *) echo $DEV ;;
63                 esac
64         done
65 }
66
67 if [ "$LFSCK_SETUP" != "no" ]; then
68         #Create test directory 
69         # -- can't remove the mountpoint...
70         [ -z "$DIR" ] && rm -rf $DIR/*
71         mkdir -p $DIR
72         OSTCOUNT=`$LFIND $MOUNT | grep -c "^[0-9]*: "`
73
74         # Create some files on the filesystem
75         for d in `seq -f d%g $NUMDIRS`; do
76                 echo "creating files in $DIR/$d"
77                 for e in `seq -f d%g $NUMDIRS`; do
78                         mkdir -p  $DIR/$d/$e
79                         for f in `seq -f test%g $NUMDIRS`; do
80                                 cp /etc/fstab $DIR/$d/$e/$f ||exit 5
81                         done
82                 done
83         done
84
85         # Create Files to be modified
86         for f in `seq -f $DIR/testfile.%g $((NUMFILES * 3))`; do
87                 echo "creating $f"
88                 cp /etc/termcap $f || exit 10
89         done
90
91         #Create some more files
92         for d in `seq -f d%g $((NUMDIRS * 2 + 1)) $((NUMDIRS * 2 + 3))`; do
93                 echo "creating files in $DIR/$d"
94                 for e in `seq -f d%g $NUMDIRS`; do
95                         mkdir -p  $DIR/$d/$e
96                         for f in `seq -f test%g $NUMDIRS`; do
97                                 cp /etc/hosts $DIR/$d/$e/$f ||exit 15
98                         done
99                 done
100         done
101
102         # these should NOT be taken as duplicates
103         for f in `seq -f $DIR/$d/linkfile.%g $NUMFILES`; do
104                 echo "linking files in $DIR/$d"
105                 cp /etc/hosts $f
106                 ln $f $f.link
107         done
108
109         # Get objids for a file on the OST
110         OST_FILES=`seq -f $DIR/testfile.%g $NUMFILES`
111         OST_REMOVE=`$LFIND $OST_FILES | awk '$1 == 0 { print $2 }' | head -n $NUMFILES`
112
113         export MDS_DUPE=""
114         for f in `seq -f testfile.%g $((NUMFILES + 1)) $((NUMFILES * 2))`; do
115                 TEST_FILE=$DIR/$f
116                 echo "DUPLICATING MDS file $TEST_FILE"
117                 $LFIND -v $TEST_FILE >> $LOG || exit 20
118                 MDS_DUPE="$MDS_DUPE $TEST_FILE"
119         done
120         MDS_DUPE=`echo $MDS_DUPE | sed "s#$MOUNT/##g"`
121
122         export MDS_REMOVE=""
123         for f in `seq -f testfile.%g $((NUMFILES * 2 + 1)) $((NUMFILES * 3))`; do
124                 TEST_FILE=$DIR/$f
125                 echo "REMOVING MDS file $TEST_FILE which has info:"
126                 $LFIND -v $TEST_FILE >> $LOG || exit 30
127                 MDS_REMOVE="$MDS_REMOVE $TEST_FILE"
128         done
129         MDS_REMOVE=`echo $MDS_REMOVE | sed "s#$MOUNT/##g"`
130
131         # when the OST is also using an OSD this needs to be fixed
132         MDTDEVS=`get_mnt_devs osd`
133         OSTDEVS=`get_mnt_devs obdfilter`
134         OSTCOUNT=`echo $OSTDEVS | wc -w`
135         sh llmountcleanup.sh || exit 40
136
137         # Remove objects associated with files
138         echo "removing objects: `echo $OST_REMOVE`"
139         DEBUGTMP=`mktemp $TMP/debugfs.XXXXXXXXXX`
140         for i in $OST_REMOVE; do
141                 echo "rm O/0/d$((i % 32))/$i" >> $DEBUGTMP
142         done
143         $DEBUGFS -w -f $DEBUGTMP `echo $OSTDEVS | cut -d' ' -f 1`
144         RET=$?
145         rm $DEBUGTMP
146         [ $RET -ne 0 ] && exit 50
147
148         SAVE_PWD=$PWD
149         mount -t $FSTYPE -o loop $MDSDEV $MOUNT || exit 60
150         do_umount() {
151                 trap 0
152                 cd $SAVE_PWD
153                 umount -f $MOUNT
154         }
155         trap do_umount EXIT
156
157         #Remove files from mds
158         for f in $MDS_REMOVE; do
159                 rm $MOUNT/ROOT/$f || exit 70
160         done
161
162         #Create EAs on files so objects are referenced from different files
163         ATTRTMP=`mktemp $TMP/setfattr.XXXXXXXXXX`
164         cd $MOUNT/ROOT || exit 78
165         for f in $MDS_DUPE; do
166                 touch $f.bad || exit 74
167                 getfattr -n trusted.lov $f | sed "s#$f#&.bad#" > $ATTRTMP
168                 setfattr --restore $ATTRTMP || exit 80
169         done
170         cd $SAVE_PWD
171         rm $ATTRTMP
172
173         do_umount
174 else
175         # when the OST is also using an OSD this needs to be fixed
176         MDTDEVS=`get_mnt_devs osd`
177         OSTDEVS=`get_mnt_devs obdfilter`
178         OSTCOUNT=`echo $OSTDEVS | wc -w`
179 fi # LFSCK_SETUP
180
181 # Run e2fsck to get mds and ost info
182 # a return status of 1 indicates e2fsck successfuly fixed problems found
183 set +e
184
185 echo "$E2FSCK -d -v -fn --mdsdb $MDSDB $MDSDEV"
186 df > /dev/null  # update statfs data on disk
187 $E2FSCK -d -v -fn --mdsdb $MDSDB $MDSDEV
188 RET=$?
189 [ $RET -gt $MAX_ERR ] && echo "$E2FSCK returned $RET" && exit 90 || true
190
191 export OSTDB_LIST=""
192 i=0
193 for OSTDEV in $OSTDEVS; do
194         df > /dev/null  # update statfs data on disk
195         $E2FSCK -d -v -fn --mdsdb $MDSDB --ostdb $OSTDB-$i $OSTDEV
196         RET=$?
197         [ $RET -gt $MAX_ERR ] && echo "$E2FSCK returned $RET" && exit 100
198         OSTDB_LIST="$OSTDB_LIST $OSTDB-$i"
199         i=$((i + 1))
200 done
201
202 #Remount filesystem
203 [ "`mount | grep $MOUNT`" ] || $SETUP
204
205 # need to turn off shell error detection to get proper error return
206 # lfsck will return 1 if the filesystem had errors fixed
207 echo "LFSCK TEST 1"
208 echo "lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
209 echo y | lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT
210 RET=$?
211 [ $RET -eq 0 ] && echo "clean after first check" && exit 0
212 echo "LFSCK TEST 1 - finished with rc=$RET"
213 [ $RET -gt $MAX_ERR ] && exit 110 || true
214
215 # make sure everything gets to the backing store
216 sync; sleep 2; sync
217
218 echo "LFSCK TEST 2"
219 echo "$E2FSCK -d -v -fn --mdsdb $MDSDB $MDSDEV"
220 df > /dev/null  # update statfs data on disk
221 $E2FSCK -d -v -fn --mdsdb $MDSDB $MDSDEV
222 RET=$?
223 [ $RET -gt $MAX_ERR ] && echo "$E2FSCK returned $RET" && exit 123 || true
224
225 i=0
226 export OSTDB_LIST=""
227 for OSTDEV in $OSTDEVS; do
228         df > /dev/null  # update statfs data on disk
229         $E2FSCK -d -v -fn --mdsdb $MDSDB --ostdb $OSTDB-$i $OSTDEV
230         RET=$?
231         [ $RET -gt $MAX_ERR ] && echo "$E2FSCK returned $RET" && exit 124
232         OSTDB_LIST="$OSTDB_LIST $OSTDB-$i"
233         i=$((i + 1))
234 done
235
236 echo "LFSCK TEST 2"
237 echo "lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT"
238 lfsck -c -l --mdsdb $MDSDB --ostdb $OSTDB_LIST $MOUNT
239 RET=$?
240 echo "LFSCK TEST 2 - finished with rc=$RET"
241 [ $RET -ne 0 ] && exit 125 || true
242 if [ -z "$WAS_MOUNTED" ]; then
243         sh llmountcleanup.sh || exit 120
244 fi
245
246 #Cleanup 
247 rm -f $MDSDB $OSTDB-* || true
248
249 echo "$0: completed"