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