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