Whamcloud - gitweb
- cleanups in sanity-gns.sh
[fs/lustre-release.git] / lustre / tests / sanity-gns.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 ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""}
11 [ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
12
13 SRCDIR=`dirname $0`
14 export PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$PATH
15 export SECURITY=${SECURITY:-"null"}
16
17 TMP=${TMP:-/tmp}
18 FSTYPE=${FSTYPE:-ext3}
19
20 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
21 CREATETEST=${CREATETEST:-createtest}
22 LFS=${LFS:-lfs}
23 LSTRIPE=${LSTRIPE:-"$LFS setstripe"}
24 LFIND=${LFIND:-"$LFS find"}
25 LVERIFY=${LVERIFY:-ll_dirstripe_verify}
26 LCTL=${LCTL:-lctl}
27 MCREATE=${MCREATE:-mcreate}
28 OPENFILE=${OPENFILE:-openfile}
29 OPENUNLINK=${OPENUNLINK:-openunlink}
30 TOEXCL=${TOEXCL:-toexcl}
31 TRUNCATE=${TRUNCATE:-truncate}
32 MUNLINK=${MUNLINK:-munlink}
33 SOCKETSERVER=${SOCKETSERVER:-socketserver}
34 SOCKETCLIENT=${SOCKETCLIENT:-socketclient}
35 IOPENTEST1=${IOPENTEST1:-iopentest1}
36 IOPENTEST2=${IOPENTEST2:-iopentest2}
37 PTLDEBUG=${PTLDEBUG:-0}
38
39 . krb5_env.sh
40
41 if [ $UID -ne 0 ]; then
42         RUNAS_ID="$UID"
43         RUNAS=""
44 else
45         RUNAS_ID=${RUNAS_ID:-500}
46         RUNAS=${RUNAS:-"runas -u $RUNAS_ID"}
47 fi
48
49 if [ `using_krb5_sec $SECURITY` == 'y' ] ; then
50     start_krb5_kdc || exit 1
51     if [ $RUNAS_ID -ne $UID ]; then
52         $RUNAS ./krb5_refresh_cache.sh || exit 2
53     fi
54 fi
55
56 export NAME=${NAME:-local}
57
58 SAVE_PWD=$PWD
59
60 clean() {
61         echo -n "cln.."
62         sh llmountcleanup.sh > /dev/null || exit 20
63         I_MOUNTED=no
64 }
65 CLEAN=${CLEAN:-clean}
66
67 start() {
68         echo -n "mnt.."
69         sh llrmount.sh > /dev/null || exit 10
70         I_MOUNTED=yes
71         echo "done"
72 }
73 START=${START:-start}
74
75 log() {
76         echo "$*"
77         lctl mark "$*" 2> /dev/null || true
78 }
79
80 trace() {
81         log "STARTING: $*"
82         strace -o $TMP/$1.strace -ttt $*
83         RC=$?
84         log "FINISHED: $*: rc $RC"
85         return 1
86 }
87 TRACE=${TRACE:-""}
88
89 check_kernel_version() {
90         VERSION_FILE=/proc/fs/lustre/kernel_version
91         WANT_VER=$1
92         [ ! -f $VERSION_FILE ] && echo "can't find kernel version" && return 1
93         GOT_VER=`cat $VERSION_FILE`
94         [ $GOT_VER -ge $WANT_VER ] && return 0
95         log "test needs at least kernel version $WANT_VER, running $GOT_VER"
96         return 1
97 }
98
99 run_one() {
100         if ! mount | grep -q $DIR; then
101                 $START
102         fi
103         echo $PTLDEBUG >/proc/sys/portals/debug 
104         log "== test $1: $2"
105         export TESTNAME=test_$1
106         test_$1 || error "test_$1: exit with rc=$?"
107         unset TESTNAME
108         pass
109         cd $SAVE_PWD
110         $CLEAN
111 }
112
113 build_test_filter() {
114         for O in $ONLY; do
115             eval ONLY_${O}=true
116         done
117         for E in $EXCEPT $ALWAYS_EXCEPT; do
118             eval EXCEPT_${E}=true
119         done
120 }
121
122 _basetest() {
123     echo $*
124 }
125
126 basetest() {
127     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
128 }
129
130 run_test() {
131          base=`basetest $1`
132          if [ "$ONLY" ]; then
133                  testname=ONLY_$1
134                  if [ ${!testname}x != x ]; then
135                         run_one $1 "$2"
136                         return $?
137                  fi
138                  testname=ONLY_$base
139                  if [ ${!testname}x != x ]; then
140                          run_one $1 "$2"
141                          return $?
142                  fi
143                  echo -n "."
144                  return 0
145         fi
146         testname=EXCEPT_$1
147         if [ ${!testname}x != x ]; then
148                  echo "skipping excluded test $1"
149                  return 0
150         fi
151         testname=EXCEPT_$base
152         if [ ${!testname}x != x ]; then
153                  echo "skipping excluded test $1 (base $base)"
154                  return 0
155         fi
156         run_one $1 "$2"
157         return $?
158 }
159
160 [ "$SANITYLOG" ] && rm -f $SANITYLOG || true
161
162 error() { 
163         log "FAIL: $@"
164         if [ "$SANITYLOG" ]; then
165                 echo "FAIL: $TESTNAME $@" >> $SANITYLOG
166         else
167                 exit 1
168         fi
169 }
170
171 pass() { 
172         echo PASS
173 }
174
175 MOUNT="`mount | awk '/^'$NAME' .* lustre_lite / { print $3 }'`"
176 if [ -z "$MOUNT" ]; then
177         sh llmount.sh
178         MOUNT="`mount | awk '/^'$NAME' .* lustre_lite / { print $3 }'`"
179         [ -z "$MOUNT" ] && error "NAME=$NAME not mounted"
180         I_MOUNTED=yes
181 fi
182
183 [ `echo $MOUNT | wc -w` -gt 1 ] && error "NAME=$NAME mounted more than once"
184
185 DIR=${DIR:-$MOUNT}
186 [ -z "`echo $DIR | grep $MOUNT`" ] && echo "$DIR not in $MOUNT" && exit 99
187
188 rm -rf $DIR/[Rdfs][1-9]*
189 build_test_filter
190
191 echo preparing for tests involving mounts
192 EXT2_DEV=${EXT2_DEV:-/tmp/SANITY.LOOP}
193 touch $EXT2_DEV
194 mke2fs -j -F $EXT2_DEV 8000 >/dev/null 2>&1
195
196 find_free_loop() {
197     local LOOP_DEV=""
198     test -b /dev/loop0 && 
199         base="/dev/loop" || base="/dev/loop/"
200
201     for ((i=0;i<256;i++)); do
202         test -b $base$i || continue
203         
204         losetup $base$i >/dev/null 2>&1 || {
205             LOOP_DEV="$base$i"
206             break
207         }
208     done
209     echo $LOOP_DEV
210 }
211
212 setup_loop() {
213     local LOOP_DEV=$1
214     local LOOP_FILE=$2
215     
216     dd if=/dev/zero of=$LOOP_FILE bs=1M count=10 2>/dev/null || return $?
217
218     losetup $LOOP_DEV $LOOP_FILE || {
219         rc=$?
220         cleanup_loop $LOOP_DEV $LOOP_FILE
221         return $rc
222     }
223     
224     mke2fs -F $LOOP_DEV >/dev/null 2>&1 || {
225         rc=$?
226         cleanup_loop $LOOP_DEV $LOOP_FILE
227         echo "cannot create test ext2 fs on $LOOP_DEV"
228         return $?
229     }
230     return 0
231 }
232
233 cleanup_loop() {
234     local LOOP_DEV=$1
235     local LOOP_FILE=$2
236     
237     losetup -d $LOOP_DEV >/dev/null 2>&1
238     rm -fr $LOOP_FILE >/dev/null 2>&1
239 }
240
241 setup_upcall() {
242     local INJECTION=""
243     local UPCALL=$1
244     local MODE=$2
245     local LOG=$3
246
247     test "x$MODE" = "xDEADLOCK" &&
248     INJECTION="touch \$MNTPATH/file"
249     
250     cat > $UPCALL <<- EOF
251 #!/bin/sh
252
253 MOUNT=\`which mount 2>/dev/null\`
254 test "x\$MOUNT" = "x" && MOUNT="/bin/mount"
255
256 OPTIONS=\$1
257 MNTPATH=\$2
258
259 test "x\$OPTIONS" = "x" || "x\$MNTPATH" = "x" &&
260 exit 1
261
262 $INJECTION
263 \$MOUNT \$OPTIONS \$MNTPATH > $LOG 2>&1
264 exit \$?
265 EOF
266     chmod +x $UPCALL
267     return $?
268 }
269
270 cleanup_upcall() {
271     local UPCALL=$1
272     rm -fr $UPCALL
273 }
274
275 check_gns() {
276     local LOG="/tmp/gns-log"
277     local UPCALL_PATH=""
278     
279     local UPCALL=$1
280     local OBJECT=$2
281     local TIMOUT=$3
282     local TICK=$4
283     local MODE=$5
284     
285     rm -fr $LOG >/dev/null 2>&1
286     UPCALL_PATH="/tmp/gns-upcall-$UPCALL.sh"
287     
288     echo "generating upcall $UPCALL_PATH"
289     setup_upcall $UPCALL_PATH $UPCALL $LOG || return $rc
290     echo "======================== upcall script ==========================="
291     cat $UPCALL_PATH 2>/dev/null || return $?
292     echo "=================================================================="
293    
294     echo "$UPCALL_PATH" > /proc/fs/lustre/llite/fs0/gns_upcall || return $?
295     echo "upcall:  $(cat /proc/fs/lustre/llite/fs0/gns_upcall)"
296
297     test "x$MODE" = "xGENERIC" && {
298         echo -n "mount on open $OBJECT/test_file1 (generic): "
299         
300         echo -n "test data" > $OBJECT/test_file1 >/dev/null 2>&1 || return $?
301     } || {
302         local i=1
303         local nr=20
304         
305         echo -n "mount on open $OBJECT/test_file1 ($nr threads): "
306         
307         for ((;i<=$nr;i++)); do 
308             echo -n "test data" > $OBJECT/test_file$i >/dev/null 2>&1 &
309         done
310         
311         wait
312     }
313
314     local ENTRY="`basename $OBJECT`"
315     
316     cat /proc/mounts | grep -q "$ENTRY" || {
317         echo "fail"
318         test -f $LOG && {
319             echo "======================== upcall log ==========================="
320             cat $LOG
321             echo "==============================================================="
322         } || {
323             echo "upcall log file $LOG is not found"
324         }
325         cleanup_upcall $UPCALL_PATH
326         return 1
327     }
328     echo "success"
329
330     local sleep_time=$TIMOUT
331     let sleep_time+=$TICK*2
332     echo -n "waiting for umount ${sleep_time}s (timeout + tick*2): "
333     sleep $sleep_time
334
335     cat /proc/mounts | grep -q "$ENTRY" && {
336         echo "failed"
337         cleanup_upcall $UPCALL_PATH
338         return 2
339     }
340     echo "success"
341     cleanup_upcall $UPCALL_PATH
342     return 0
343 }
344
345 setup_object() {
346     local OBJPATH=$1
347     local OBJECT=$2
348     local CONTENT=$3
349     
350     mkdir -p $OBJPATH || return $?
351     echo -n $CONTENT > $OBJPATH/$OBJECT || return $?
352     
353     echo "======================== mount object ==========================="
354     cat $OBJPATH/$OBJECT
355     echo ""
356     echo "================================================================="
357     
358     chmod u+s $OBJPATH
359     return $?
360 }
361
362 cleanup_object() {
363     local OBJPATH=$1
364
365     chmod u-s $OBJPATH >/dev/null 2>&1
366     umount $OBJPATH >/dev/null 2>&1
367     rm -fr $OBJPATH >/dev/null 2>&1
368 }
369
370 setup_gns() {
371     local OBJECT=$1
372     local TIMOUT=$2
373     local TICK=$3
374
375     echo "$OBJECT" > /proc/fs/lustre/llite/fs0/gns_object_name || error
376     echo "$TIMOUT" > /proc/fs/lustre/llite/fs0/gns_timeout || error
377     echo "$TICK" > /proc/fs/lustre/llite/fs0/gns_tick || error
378
379     echo ""
380     echo "timeout: $(cat /proc/fs/lustre/llite/fs0/gns_timeout)s"
381     echo "object:  $(cat /proc/fs/lustre/llite/fs0/gns_object_name)"
382     echo "tick:    $(cat /proc/fs/lustre/llite/fs0/gns_tick)s"
383     echo ""
384
385 }
386
387 test_1a() {
388     local LOOP_DEV=$(find_free_loop 2>/dev/null)
389     local UPCALL="/tmp/gns-upcall.sh"
390     local LOOP_FILE="/tmp/gns_loop_1a"
391     local OBJECT=".mntinfo"
392     local TIMOUT=5
393     local TICK=1
394
395     test "x$LOOP_DEV" != "x" && test -b $LOOP_DEV ||
396         error "can't find free loop device"
397
398     echo "preparing loop device $LOOP_DEV <-> $LOOP_FILE..."
399     cleanup_loop $LOOP_DEV $LOOP_FILE
400     setup_loop $LOOP_DEV $LOOP_FILE || error
401
402     echo "setting up GNS timeouts and mount object..."
403     setup_gns $OBJECT $TIMOUT $TICK || error
404
405     echo "preparing mount object at $DIR/gns_test_1a/$OBJECT..."
406     setup_object $DIR/gns_test_1a $OBJECT "-t ext2 $LOOP_DEV" || error
407
408     echo ""
409     echo "testing GNS with GENERIC upcall 3 times on the row"
410     for ((i=0;i<3;i++)); do
411         check_gns GENERIC $DIR/gns_test_1a $TIMOUT $TICK GENERIC || {
412             cleanup_object $DIR/gns_test_1a
413             cleanup_loop $LOOP_DEV $LOOP_FILE
414             error
415         }
416     done
417     
418     cleanup_object $DIR/gns_test_1a
419     cleanup_loop $LOOP_DEV $LOOP_FILE
420 }
421
422 run_test 1a " general GNS test - mount/umount (GENERIC) ================"
423
424 test_2a() {
425     local LOOP_DEV=$(find_free_loop 2>/dev/null)
426     local UPCALL="/tmp/gns-upcall.sh"
427     local LOOP_FILE="/tmp/gns_loop_2a"
428     local OBJECT=".mntinfo"
429     local TIMOUT=5
430     local TICK=1
431
432     test "x$LOOP_DEV" != "x" && test -b $LOOP_DEV ||
433         error "can't find free loop device"
434
435     echo "preparing loop device $LOOP_DEV <-> $LOOP_FILE..."
436     cleanup_loop $LOOP_DEV $LOOP_FILE
437     setup_loop $LOOP_DEV $LOOP_FILE || error
438
439     echo "setting up GNS timeouts and mount object..."
440     setup_gns $OBJECT $TIMOUT $TICK || error
441
442     echo "preparing mount object at $DIR/gns_test_2a/$OBJECT..."
443     setup_object $DIR/gns_test_2a $OBJECT "-t ext2 $LOOP_DEV" || error
444
445     echo ""
446     echo "testing GNS with DEADLOCK upcall 3 times on the row"
447     for ((i=0;i<3;i++)); do
448         check_gns DEADLOCK $DIR/gns_test_2a $TIMOUT $TICK GENERIC || {
449             cleanup_object $DIR/gns_test_2a
450             cleanup_loop $LOOP_DEV $LOOP_FILE
451             error
452         }
453     done
454     
455     cleanup_object $DIR/gns_test_2a
456     cleanup_loop $LOOP_DEV $LOOP_FILE
457 }
458
459 run_test 2a " general GNS test - mount/umount (DEADLOCK) ==============="
460
461 test_3a() {
462     local LOOP_DEV=$(find_free_loop 2>/dev/null)
463     local UPCALL="/tmp/gns-upcall.sh"
464     local LOOP_FILE="/tmp/gns_loop_3a"
465     local OBJECT=".mntinfo"
466     local TIMOUT=5
467     local TICK=1
468
469     test "x$LOOP_DEV" != "x" && test -b $LOOP_DEV ||
470         error "can't find free loop device"
471
472     echo "preparing loop device $LOOP_DEV <-> $LOOP_FILE..."
473     cleanup_loop $LOOP_DEV $LOOP_FILE
474     setup_loop $LOOP_DEV $LOOP_FILE || error
475
476     echo "setting up GNS timeouts and mount object..."
477     setup_gns $OBJECT $TIMOUT $TICK || error
478
479     echo "preparing mount object at $DIR/gns_test_3a/$OBJECT..."
480     setup_object $DIR/gns_test_3a $OBJECT "-t ext2 $LOOP_DEV" || error
481
482     echo ""
483     echo "testing GNS with DEADLOCK upcall 4 times on the row"
484     local i=0
485     
486     for ((;i<4;i++)); do
487         local MODE="GENERIC"
488         
489         test $(($i%2)) -eq 1 && MODE="DEADLOCK"
490         
491         check_gns $MODE $DIR/gns_test_3a $TIMOUT $TICK GENERIC || {
492             cleanup_object $DIR/gns_test_3a
493             cleanup_loop $LOOP_DEV $LOOP_FILE
494             error
495         }
496     done
497     
498     cleanup_object $DIR/gns_test_3a
499     cleanup_loop $LOOP_DEV $LOOP_FILE
500 }
501
502 run_test 3a " general GNS test - mount/umount (GENERIC/DEADLOCK) ========"
503
504 test_4a() {
505     local LOOP_DEV=$(find_free_loop 2>/dev/null)
506     local UPCALL="/tmp/gns-upcall.sh"
507     local LOOP_FILE="/tmp/gns_loop_4a"
508     local OBJECT=".mntinfo"
509     local TIMOUT=5
510     local TICK=1
511
512     test "x$LOOP_DEV" != "x" && test -b $LOOP_DEV ||
513         error "can't find free loop device"
514
515     echo "preparing loop device $LOOP_DEV <-> $LOOP_FILE..."
516     cleanup_loop $LOOP_DEV $LOOP_FILE
517     setup_loop $LOOP_DEV $LOOP_FILE || error
518
519     echo "setting up GNS timeouts and mount object..."
520     setup_gns $OBJECT $TIMOUT $TICK || error
521
522     echo "preparing mount object at $DIR/gns_test_4a/$OBJECT..."
523     setup_object $DIR/gns_test_4a $OBJECT "-t ext2 $LOOP_DEV" || error
524
525     echo ""
526     echo "testing GNS with DEADLOCK upcall 4 times on the row"
527     local i=0
528     
529     for ((;i<4;i++)); do
530         local MODE="GENERIC"
531         
532         test $(($i%2)) -eq 1 && MODE="DEADLOCK"
533         
534         check_gns $MODE $DIR/gns_test_4a $TIMOUT $TICK CONCURRENT || {
535             cleanup_object $DIR/gns_test_4a
536             cleanup_loop $LOOP_DEV $LOOP_FILE
537             error
538         }
539     done
540     
541     cleanup_object $DIR/gns_test_4a
542     cleanup_loop $LOOP_DEV $LOOP_FILE
543 }
544
545 run_test 4a " general GNS test - concurrent mount ======================="
546
547 test_5a() {
548     echo "Not implemented yet!"
549 }
550
551 run_test 5a " general GNS test - concurrent mount of 2 GNS mounts ======="
552
553 TMPDIR=$OLDTMPDIR
554 TMP=$OLDTMP
555 HOME=$OLDHOME
556
557 log "cleanup: ==========================================================="
558 if [ "`mount | grep ^$NAME`" ]; then
559         rm -rf $DIR/[Rdfs][1-9]*
560         if [ "$I_MOUNTED" = "yes" ]; then
561                 sh llmountcleanup.sh || error
562         fi
563 fi
564
565 echo '=========================== finished ==============================='
566 [ -f "$SANITYLOG" ] && cat $SANITYLOG && exit 1 || true