Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / tests / sanity-lmv.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6 # e.g. ONLY="22 23" or ONLY="`seq 32 39`" or EXCEPT="31"
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10 # bug number for skipped test: 2108
11 ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""}
12 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
13 #case `uname -r` in
14 #2.6.*) ALWAYS_EXCEPT="$ALWAYS_EXCEPT 54c 55" # bug 3117
15 #esac
16
17 [ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
18
19 SRCDIR=`dirname $0`
20 export PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$PATH
21 export SECURITY=${SECURITY:-"null"}
22
23 TMP=${TMP:-/tmp}
24 FSTYPE=${FSTYPE:-ldiskfs}
25
26 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
27 CREATETEST=${CREATETEST:-createtest}
28 LFS=${LFS:-lfs}
29 LSTRIPE=${LSTRIPE:-"$LFS setstripe"}
30 LFIND=${LFIND:-"$LFS find"}
31 LVERIFY=${LVERIFY:-ll_dirstripe_verify}
32 LCTL=${LCTL:-lctl}
33 MCREATE=${MCREATE:-mcreate}
34 OPENFILE=${OPENFILE:-openfile}
35 OPENUNLINK=${OPENUNLINK:-openunlink}
36 TOEXCL=${TOEXCL:-toexcl}
37 TRUNCATE=${TRUNCATE:-truncate}
38 MUNLINK=${MUNLINK:-munlink}
39 SOCKETSERVER=${SOCKETSERVER:-socketserver}
40 SOCKETCLIENT=${SOCKETCLIENT:-socketclient}
41 IOPENTEST1=${IOPENTEST1:-iopentest1}
42 IOPENTEST2=${IOPENTEST2:-iopentest2}
43 PTLDEBUG=${PTLDEBUG:-0}
44
45 export NAME=${NAME:-lmv}
46
47 SAVE_PWD=$PWD
48
49 LUSTRE=${LUSTRE:-`dirname $0`/..}
50 . $LUSTRE/tests/test-framework.sh
51 init_test_env $@
52 . ${CONFIG:=$LUSTRE/tests/cfg/lmv.sh}
53
54 cleanup() {
55         echo -n "cln.."
56         cleanupall ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
57 }
58 CLEANUP=${CLEANUP:-:}
59
60 setup() {
61         echo -n "mnt.."
62         load_modules
63         setupall || exit 10
64         echo "done"
65 }
66
67 SETUP=${SETUP:-:}
68
69 log() {
70         echo "$*"
71         $LCTL mark "$*" 2> /dev/null || true
72 }
73
74 trace() {
75         log "STARTING: $*"
76         strace -o $TMP/$1.strace -ttt $*
77         RC=$?
78         log "FINISHED: $*: rc $RC"
79         return 1
80 }
81 TRACE=${TRACE:-""}
82
83 check_kernel_version() {
84         VERSION_FILE=$LPROC/version
85         WANT_VER=$1
86         [ ! -f $VERSION_FILE ] && echo "can't find kernel version" && return 1
87         GOT_VER=$(awk '/kernel:/ {print $2}' $VERSION_FILE)
88         [ $GOT_VER -ge $WANT_VER ] && return 0
89         log "test needs at least kernel version $WANT_VER, running $GOT_VER"
90         return 1
91 }
92
93 _basetest() {
94     echo $*
95 }
96
97 basetest() {
98     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
99 }
100
101 run_one() {
102         if ! grep -q $DIR /proc/mounts; then
103                 $SETUP
104         fi
105         testnum=$1
106         message=$2
107         BEFORE=`date +%s`
108         log "== test $testnum: $message= `date +%H:%M:%S` ($BEFORE)"
109         export TESTNAME=test_$testnum
110         export tfile=f${testnum}
111         export tdir=d${base}
112         test_${testnum} || error "exit with rc=$?"
113         unset TESTNAME
114         pass "($((`date +%s` - $BEFORE))s)"
115         cd $SAVE_PWD
116         $CLEANUP
117 }
118
119 build_test_filter() {
120         [ "$ALWAYS_EXCEPT$EXCEPT$SANITY_EXCEPT" ] && \
121             echo "Skipping tests: `echo $ALWAYS_EXCEPT $EXCEPT $SANITY_EXCEPT`"
122
123         for O in $ONLY; do
124             eval ONLY_${O}=true
125         done
126         for E in $EXCEPT $ALWAYS_EXCEPT $SANITY_EXCEPT; do
127             eval EXCEPT_${E}=true
128         done
129 }
130
131 _basetest() {
132         echo $*
133 }
134
135 basetest() {
136         IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
137 }
138
139 run_test() {
140          export base=`basetest $1`
141          if [ "$ONLY" ]; then
142                  testname=ONLY_$1
143                  if [ ${!testname}x != x ]; then
144                         run_one $1 "$2"
145                         return $?
146                  fi
147                  testname=ONLY_$base
148                  if [ ${!testname}x != x ]; then
149                          run_one $1 "$2"
150                          return $?
151                  fi
152                  echo -n "."
153                  return 0
154         fi
155         testname=EXCEPT_$1
156         if [ ${!testname}x != x ]; then
157                  echo "skipping excluded test $1"
158                  return 0
159         fi
160         testname=EXCEPT_$base
161         if [ ${!testname}x != x ]; then
162                  echo "skipping excluded test $1 (base $base)"
163                  return 0
164         fi
165         run_one $1 "$2"
166         return $?
167 }
168
169 [ "$SANITYLOG" ] && rm -f $SANITYLOG || true
170
171 error() { 
172         sysctl -w lustre.fail_loc=0
173         log "FAIL: $TESTNAME $@"
174         $LCTL dk $TMP/lustre-log-$TESTNAME.log
175         if [ "$SANITYLOG" ]; then
176                 echo "FAIL: $TESTNAME $@" >> $SANITYLOG
177         else
178                 exit 1
179         fi
180 }
181
182 pass() { 
183         echo PASS $@
184 }
185
186 mounted_lustre_filesystems() {
187     awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
188 }
189
190 MOUNTED="`mounted_lustre_filesystems`"
191 if [ -z "$MOUNTED" ]; then
192         formatall
193         setupall
194         MOUNTED="`mounted_lustre_filesystems`"
195         [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
196         I_MOUNTED=yes
197 fi
198
199 [ `echo $MOUNT | wc -w` -gt 1 ] && error "NAME=$NAME mounted more than once"
200
201 DIR=${DIR:-$MOUNT}
202 [ -z "`echo $DIR | grep $MOUNT`" ] && echo "$DIR not in $MOUNT" && exit 99
203
204 LOVNAME=`cat $LPROC/llite/*/lov/common_name | tail -n 1`
205 OSTCOUNT=`cat $LPROC/lov/$LOVNAME/numobd`
206 STRIPECOUNT=`cat $LPROC/lov/$LOVNAME/stripecount`
207 STRIPESIZE=`cat $LPROC/lov/$LOVNAME/stripesize`
208 ORIGFREE=`cat $LPROC/lov/$LOVNAME/kbytesavail`
209 MAXFREE=${MAXFREE:-$((200000 * $OSTCOUNT))}
210 MDS=$(\ls $LPROC/mdt 2> /dev/null | grep -v num_refs | tail -n 1)
211
212 [ -f $DIR/d52a/foo ] && chattr -a $DIR/d52a/foo
213 [ -f $DIR/d52b/foo ] && chattr -i $DIR/d52b/foo
214 rm -rf $DIR/[Rdfs][1-9]*
215
216 build_test_filter
217
218 if [ "${ONLY}" = "MOUNT" ] ; then
219         echo "Lustre is up, please go on"
220         exit
221 fi
222
223 echo "preparing for tests involving mounts"
224 EXT2_DEV=${EXT2_DEV:-$TMP/SANITY.LOOP}
225 touch $EXT2_DEV
226 mke2fs -j -F $EXT2_DEV 8000 > /dev/null
227 echo # add a newline after mke2fs.
228
229 umask 077
230
231 test_0a() {
232         mkdir $DIR/0a0 || error 
233         for ((i=0;i<5000;i++)); do
234                 mkdir $DIR/0a0/`uuidgen -t` || error
235         done
236         rm -rf $DIR/0a0 || error
237 }
238 #run_test 0a " create random names ============================="
239
240 test_1a() {
241         mkdir $DIR/1a0 || error 
242         createmany -o $DIR/1a0/f 5000 || error
243         rmdir $DIR/1a0 && error
244         rm -rf $DIR/1a0 || error
245 }
246 run_test 1a " remove splitted dir ============================="
247
248 test_1b() {
249         mkdir $DIR/1b0 || error
250         createmany -o $DIR/1b0/f 5000 || error
251         unlinkmany  $DIR/1b0/f 5000 || error
252         NUM=`ls $DIR/1b0 | wc -l`
253         if [ $NUM -ne 0 ] ; then
254                 echo "dir must be empty"
255                 error
256         fi
257
258         touch $DIR/1b0/file0 || error
259         touch $DIR/1b0/file1 || error
260         touch $DIR/1b0/file2 || error
261
262         echo "3 files left"
263         rmdir $DIR/1b0 && error
264         rm -f $DIR/1b0/file0
265
266         echo "2 files left"
267         rmdir $DIR/1b0 && error
268         rm -f $DIR/1b0/file1
269
270         echo "1 files left"
271         rmdir $DIR/1b0 && error
272         rm -f $DIR/1b0/file2
273
274         echo "0 files left"
275         rmdir $DIR/1b0 || error
276 }
277 run_test 1b " remove splitted dir ============================="
278
279 test_1c() {
280         mkdir $DIR/1b1 || error
281         createmany -o $DIR/1b1/f 5000 || error
282         unlinkmany $DIR/1b1/f 5000 || error
283         NUM=`ls $DIR/1b1 | wc -l`
284         if [ $NUM -ne 0 ] ; then
285                 echo "dir must be empty"
286                 error
287         fi
288         touch $DIR/1b1/file0 || error
289         touch $DIR/1b1/file1 || error
290         touch $DIR/1b1/file2 || error
291
292         ls $DIR/1b1/
293         log "3 files left"
294         rmdir $DIR/1b1 && error
295         rm -f $DIR/1b1/file0
296
297         ls $DIR/1b1/
298         log "2 files left"
299         rmdir $DIR/1b1 && error
300         rm -f $DIR/1b1/file1
301
302         ls $DIR/1b1/
303         log "1 files left"
304         rmdir $DIR/1b1 && error
305         rm -f $DIR/1b1/file2
306
307         ls $DIR/1b1/
308         log "0 files left"
309         rmdir $DIR/1b1 || error
310 }
311 run_test 1c " remove splitted cross-node dir ============================="
312
313 test_2a() {
314         mkdir $DIR/2a0 || error 
315         createmany -o $DIR/2a0/f 5000 || error
316         NUM=`ls $DIR/2a0 | wc -l`
317         echo "found $NUM files"
318         if [ $NUM -ne 5000 ]; then
319                 echo "wrong number of files: $NUM"
320                 error
321         fi
322         rm -rf $DIR/2a0 || error
323 }
324 run_test 2a " list splitted dir ============================="
325
326 test_2b() {
327         mkdir $DIR/2b1 || error 
328         createmany -o $DIR/2b1/f 5000 || error
329         $CLEAN
330         $START
331         statmany -l $DIR/2b1/f 5000 5000 || error
332         statmany -s $DIR/2b1/f 5000 5000 || error
333         rm -rf $DIR/2b1 || error
334 }
335 run_test 2b " list splitted dir after remount ============================="
336
337 test_3a() {
338         mkdir $DIR/3a0 || error
339         for i in `seq 100`; do
340                 mkdir $DIR/3a0/d${i} || error
341         done
342         createmany -o $DIR/3a0/f 5000 || error
343         rm -rf $DIR/3a0 || error
344 }
345 run_test 3a " dir splitting with cross-ref ============================="
346
347 test_3b() {
348         mkdir $DIR/3b1 || error
349         createmany -m $DIR/3b1/f 5000 || error
350         rm -rf $DIR/3b1 || error
351 }
352 run_test 3b " dir splitting via createmany -m ============================="
353
354 test_3c() {
355         mkdir $DIR/3c1 || error
356         echo "MDS nodes: $MDSCOUNT"
357         for j in `seq 3`; do
358                 for i in `seq 10`; do
359                         $LFS dirstripe $DIR/3c1/d-${j}-${i} $j || error
360                         createmany -m $DIR/3c1/d-${j}-${i}/m 200 || error
361                         createmany -o $DIR/3c1/d-${j}-${i}/o 200 || error
362                 done
363         done
364         rm -rf $DIR/3c1 || error
365 }
366
367 #run_test 3c " dir splitting via lfs stripe ============================="
368
369 test_4a() {
370         let rr=0
371         while let "rr < 33000"; do
372                 if let "rr % 2000 == 0"; then
373                         echo "$rr"
374                 fi
375                 mkdir $DIR/4a1 || error
376                 rm -rf $DIR/4a1
377                 let "rr = rr + 1"
378         done
379 }
380
381 ## this test is very time-consuming, don't run it by default
382 #run_test 4a " FIDS/ nlink overflow test  ============================="
383
384 test_5a() {
385         mount_client $MOUNT2
386         # create a cross-ref file
387         mkdir -p $MOUNT/$tdir/d1
388         mkdir -p $MOUNT2/$tdir/d2
389         dd if=/dev/zero of=$MOUNT/$tdir/d1/f1 count=1
390         mv $MOUNT2/$tdir/d1/f1 $MOUNT2/$tdir/d2/
391         # XXX: a check the file is a cross-ref one is needed.
392         cancel_lru_locks mdc
393         cancel_lru_locks osc
394         dd if=$MOUNT2/$tdir/d2/f1 of=/dev/null
395         stat $MOUNT2/$tdir/d2 $MOUNT2/$tdir/d2/f1 > /dev/null
396         can1=`awk '/ldlm_cancel/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_canceld/stats`
397         blk1=`awk '/ldlm_bl_callback/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_cbd/stats`
398         unlink $MOUNT2/$tdir/d2/f1
399         can2=`awk '/ldlm_cancel/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_canceld/stats`
400         blk2=`awk '/ldlm_bl_callback/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_cbd/stats`
401         umount $MOUNT2
402         [ $can1 -eq $can2 ] && error "It does not look like a cross-ref file."
403         [ $[$can1+1] -eq $can2 ] || error $[$[$can2-$can1]] "cancel RPC occured."
404         [ $blk1 -eq $blk2 ] || error $[$[$blk2-$blk1]] "blocking RPC occured."
405 }
406 run_test 5a "Early Lock Cancel: cross-ref unlink"
407
408 test_5b() {
409         mount_client $MOUNT2
410         # create a cross-ref file
411         mkdir -p $MOUNT/$tdir/d1
412         mkdir -p $MOUNT2/$tdir/d2
413         dd if=/dev/zero of=$MOUNT/$tdir/d1/f1 count=1
414         cancel_lru_locks mdc
415         cancel_lru_locks osc
416         dd if=$MOUNT2/$tdir/d1/f1 of=/dev/null
417         stat $MOUNT2/$tdir/d1/f1 $MOUNT2/$tdir/d2 > /dev/null
418         can1=`awk '/ldlm_cancel/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_canceld/stats`
419         blk1=`awk '/ldlm_bl_callback/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_cbd/stats`
420         ln $MOUNT2/$tdir/d1/f1 $MOUNT2/$tdir/d2/f2
421         can2=`awk '/ldlm_cancel/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_canceld/stats`
422         blk2=`awk '/ldlm_bl_callback/ {print $2}' /proc/fs/lustre/ldlm/services/ldlm_cbd/stats`
423         umount $MOUNT2
424         [ $can1 -eq $can2 ] && error "It does not look like a cross-ref file."
425         [ $[$can1+1] -eq $can2 ] || error $[$[$can2-$can1]] "cancel RPC occured."
426         [ $blk1 -eq $blk2 ] || error $[$[$blk2-$blk1]] "blocking RPC occured."
427 }
428 run_test 5b "Early Lock Cancel: cross-ref link"
429
430 TMPDIR=$OLDTMPDIR
431 TMP=$OLDTMP
432 HOME=$OLDHOME
433
434 log "cleanup: ======================================================"
435 if [ "`mount | grep ^$NAME`" ]; then
436     rm -rf $DIR/[Rdfs][1-9]*
437 fi
438 if [ "$I_MOUNTED" = "yes" ]; then
439     cleanupall -f || error "cleanup failed"
440 fi
441
442 echo '=========================== finished ==============================='
443 [ -f "$SANITYLOG" ] && cat $SANITYLOG && exit 1 || true