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