3d2cd32f031531b43b874372a71153f0560e98ec
[xfstests-dev.git] / common.rc
1 ##/bin/sh
2
3 #
4 # Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
5
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of version 2 of the GNU General Public License as
8 # published by the Free Software Foundation.
9
10 # This program is distributed in the hope that it would be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 # Further, this software is distributed without any warranty that it is
15 # free of the rightful claim of any third person regarding infringement
16 # or the like.  Any license provided herein, whether implied or
17 # otherwise, applies only to this software file.  Patent licenses, if
18 # any, provided herein do not apply to combinations of this program with
19 # other software, or any other product whatsoever.
20
21 # You should have received a copy of the GNU General Public License along
22 # with this program; if not, write the Free Software Foundation, Inc., 59
23 # Temple Place - Suite 330, Boston MA 02111-1307, USA.
24
25 # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
26 # Mountain View, CA  94043, or:
27
28 # http://www.sgi.com 
29
30 # For further information regarding this notice, see: 
31
32 # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #
34
35 # we need common.config
36 if ! . ./common.config
37 then
38     echo "$iam: failed to source common.config"
39     exit 1
40 fi
41
42 # make sure we have a standard umask
43 umask 022
44
45 # awk
46 AWK_PROG=awk
47
48 # extra parameters for fsstress
49 FSSTRESS_AVOID="-f resvsp=0 -f unresvsp=0"
50
51 export AWK_PROG FSSTRESS_AVOID
52
53 # we override mount and mkfs.xfs so we can specify extra options
54
55 mount()
56 {
57     case "$*"
58     in
59         *remount*)
60             /bin/mount $*
61             ;;
62         *ext2*)
63             /bin/mount $*
64             ;;
65         *xfs*)
66             /bin/mount $* $MOUNT_OPTIONS
67             ;;
68         *)
69             /bin/mount $*
70             ;;
71     esac
72 }
73
74 _test_mount()
75 {
76     TEST_OPTIONS=""
77     [ -z "$TEST_RTDEV" ] || TEST_OPTIONS="$TEST_OPTIONS -ortdev=$TEST_RTDEV"
78     [ -z "$TEST_LOGDEV" ] || TEST_OPTIONS="$TEST_OPTIONS -ologdev=$TEST_LOGDEV"
79     mount -t xfs $TEST_OPTIONS $* $TEST_DEV $TEST_DIR
80 }
81
82 _scratch_mount_options()
83 {
84     SCRATCH_OPTIONS=""
85     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
86         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -ortdev=$SCRATCH_RTDEV"
87     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
88         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -ologdev=$SCRATCH_LOGDEV"
89     echo $SCRATCH_OPTIONS $* $SCRATCH_DEV $SCRATCH_MNT
90 }
91
92 _scratch_mount()
93 {
94     SCRATCH_OPTIONS=""
95     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
96         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -ortdev=$SCRATCH_RTDEV"
97     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
98         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -ologdev=$SCRATCH_LOGDEV"
99     mount -t xfs $SCRATCH_OPTIONS $* $SCRATCH_DEV $SCRATCH_MNT
100 }
101
102 _scratch_mkfs_options()
103 {
104     SCRATCH_OPTIONS=""
105     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
106         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -rrtdev=$SCRATCH_RTDEV"
107     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
108         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -llogdev=$SCRATCH_LOGDEV"
109     echo $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
110 }
111
112 _scratch_mkfs_xfs()
113 {
114     SCRATCH_OPTIONS=""
115     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
116         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -rrtdev=$SCRATCH_RTDEV"
117     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
118         SCRATCH_OPTIONS="$SCRATCH_OPTIONS -llogdev=$SCRATCH_LOGDEV"
119     /sbin/mkfs.xfs -f $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
120 }
121
122 _scratch_xfs_db_options()
123 {
124     SCRATCH_OPTIONS=""
125     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
126         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
127     echo $SCRATCH_OPTIONS $* $SCRATCH_DEV
128 }
129
130 _scratch_xfs_logprint()
131 {
132     SCRATCH_OPTIONS=""
133     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
134         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
135     /usr/sbin/xfs_logprint $SCRATCH_OPTIONS $* $SCRATCH_DEV
136 }
137
138 _scratch_xfs_repair()
139 {
140     SCRATCH_OPTIONS=""
141     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
142         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
143     /sbin/xfs_repair $SCRATCH_OPTIONS $* $SCRATCH_DEV
144 }
145
146 _get_pids_by_name()
147 {
148     if [ $# -ne 1 ]
149     then
150         echo "Usage: _get_pids_by_name process-name" 1>&2
151         exit 1
152     fi
153
154     # Algorithm ... all ps(1) variants have a time of the form MM:SS or
155     # HH:MM:SS before the psargs field, use this as the search anchor.
156     #
157     # Matches with $1 (process-name) occur if the first psarg is $1
158     # or ends in /$1 ... the matching uses sed's regular expressions,
159     # so passing a regex into $1 will work.
160
161     ps $PS_ALL_FLAGS \
162     | sed -n \
163         -e 's/$/ /' \
164         -e 's/[         ][      ]*/ /g' \
165         -e 's/^ //' \
166         -e 's/^[^ ]* //' \
167         -e "/[0-9]:[0-9][0-9]  *[^ ]*\/$1 /s/ .*//p" \
168         -e "/[0-9]:[0-9][0-9]  *$1 /s/ .*//p"
169 }
170
171 # fqdn for localhost
172 #
173 _get_fqdn()
174 {
175     host=`hostname`
176     nslookup $host | $AWK_PROG '{ if ($1 == "Name:") print $2 }'
177 }
178
179 # fix malloc libs output
180 #
181 _fix_malloc()
182 {
183     # filter out the Electric Fence notice
184     perl -e '
185         while (<>) {
186             if (defined $o && /^\s+Electric Fence/) {
187                 chomp($o);
188                 print "$o";
189                 undef $o;
190                 next;
191             }
192             print $o if (defined $o);
193
194             $o=$_;
195         }
196         print $o if (defined $o);
197     '
198 }
199
200 # check if run as root
201 #
202 _need_to_be_root()
203 {
204     id=`id | sed -e 's/(.*//' -e 's/.*=//'`
205     if [ "$id" -ne 0 ]
206     then
207         echo "Arrgh ... you need to be root (not uid=$id) to run this test"
208         exit 1
209     fi
210 }
211
212
213 #
214 # _df_device : get an IRIX style df line for a given device 
215 #
216 #       - returns "" if not mounted
217 #       - returns fs type in field two (ala IRIX)
218 #       - joins line together if split by fancy df formatting
219 #       - strips header etc
220 #
221
222 _df_device()
223 {
224     if [ $# -ne 1 ]
225     then
226         echo "Usage: _df_device device" 1>&2
227         exit 1
228     fi
229     
230     df -T 2>/dev/null | $AWK_PROG -v what=$1 '
231         match($1,what) && NF==1 { 
232             v=$1
233             getline
234             print v, $0
235             exit
236         }
237         match($1,what) {
238             print
239             exit
240         }
241     '
242 }
243
244 #
245 # _df_dir : get an IRIX style df line for device where a directory resides
246 #
247 #       - returns fs type in field two (ala IRIX)
248 #       - joins line together if split by fancy df formatting
249 #       - strips header etc
250 #
251
252 _df_dir()
253 {
254     if [ $# -ne 1 ]
255     then
256         echo "Usage: _df_dir device" 1>&2
257         exit 1
258     fi
259     
260     df -T $1 2>/dev/null | $AWK_PROG -v what=$1 '
261         NR == 2 && NF==1 { 
262             v=$1
263             getline 
264             print v, $0;
265             exit 0
266         }
267         NR == 2 {
268             print;
269             exit 0
270         }
271         {}
272     '
273     # otherwise, nada
274 }
275
276 # return percentage used disk space for mounted device
277
278 _used()
279 {
280     if [ $# -ne 1 ]
281     then
282         echo "Usage: _used device" 1>&2
283         exit 1
284     fi
285     
286     _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
287 }
288
289 # return the FS type of a mounted device
290 #
291 _fs_type()
292 {
293     if [ $# -ne 1 ]
294     then
295         echo "Usage: _fs_type device" 1>&2
296         exit 1
297     fi
298     
299     _df_device $1 | $AWK_PROG '{ print $2 }'
300 }
301
302 # return the FS mount options of a mounted device
303 #
304 _fs_options()
305 {
306     if [ $# -ne 1 ]
307     then
308         echo "Usage: _fs_options device" 1>&2
309         exit 1
310     fi
311     
312     $AWK_PROG -v dev=$1 '
313         match($1,dev) { print $4 }
314     ' </proc/mounts
315     
316 }
317
318 # returns device number if a file is a block device
319 #
320 _is_block_dev()
321 {
322     if [ $# -ne 1 ]
323     then
324         echo "Usage: _is_block_dev dev" 1>&2
325         exit 1
326     fi
327     
328     [ -b $1 ] && src/lstat64 $1 | $AWK_PROG '/Device type:/ { print $9 }'
329 }
330
331 # Do a command, log it to $seq.full, optionally test return status
332 # and die if command fails. If called with one argument _do executes the
333 # command, logs it, and returns its exit status. With two arguments _do
334 # first prints the message passed in the first argument, and then "done"
335 # or "fail" depending on the return status of the command passed in the
336 # second argument. If the command fails and the variable _do_die_on_error
337 # is set to "always" or the two argument form is used and _do_die_on_error
338 # is set to "message_only" _do will print an error message to
339 # $seq.out and exit.
340
341 _do()
342 {
343   if [ $# -eq 1 ]; then
344     _cmd=$1
345   elif [ $# -eq 2 ]; then
346     _note=$1
347     _cmd=$2
348     echo -n "$_note... "
349   else
350     echo "Usage: _do [note] cmd" 1>&2
351     status=1; exit
352   fi
353
354   (eval "echo '---' \"$_cmd\"") >>$seq.full
355   (eval "$_cmd") >$tmp._out 2>&1; ret=$?
356   cat $tmp._out | _fix_malloc >>$seq.full
357   if [ $# -eq 2 ]; then
358     if [ $ret -eq 0 ]; then
359       echo "done"
360     else
361       echo "fail"
362     fi
363   fi
364   if [ $ret -ne 0  ] \
365      && [ "$_do_die_on_error" = "always" \
366          -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ]
367   then
368       [ $# -ne 2 ] && echo
369       eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full"
370       status=1; exit
371   fi
372
373   return $ret
374 }
375
376 # bail out, setting up .notrun file
377
378 _notrun()
379 {
380     echo "$*" >$seq.notrun
381     echo "$seq not run: $*"
382     status=0
383     exit
384 }
385
386 # just plain bail out
387
388 _fail()
389 {
390     echo "$*" | tee -a $seq.full
391     echo "(see $seq.full for details)"
392     status=1
393     exit 1
394 }
395
396 # this test needs a scratch partition - check we're ok & unmount it
397
398 _require_scratch()
399 {
400     if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
401     then
402         _notrun "this test requires a valid \$SCRATCH_DEV"
403     fi
404     
405     if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
406     then
407         _notrun "this test requires a valid \$SCRATCH_DEV"
408     fi
409     
410     # mounted?
411     if mount | grep -q $SCRATCH_DEV
412     then 
413         # if it's mounted, make sure its on $SCRATCH_MNT
414         if ! mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
415         then 
416             echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
417             exit 1
418         fi
419         # and then unmount it
420         if ! umount $SCRATCH_DEV
421         then
422             echo "failed to unmount $SCRATCH_DEV"
423             exit 1
424         fi
425     fi
426 }
427
428 # this test needs a logdev 
429
430 _require_logdev()
431 {
432     [ -z "$SCRATCH_LOGDEV" -o ! -b "$SCRATCH_LOGDEV" ] && \
433         _notrun "This test requires a valid \$SCRATCH_LOGDEV" 
434     [ "$USE_EXTERNAL" != yes ] && \
435         _notrun "This test requires USE_EXTERNAL to be enabled"
436
437     # ensure its not mounted
438     umount $SCRATCH_LOGDEV 2>/dev/null
439 }
440
441 # this test requires loopback device support
442
443 _require_loop()
444 {
445     modprobe loop >/dev/null 2>&1
446     if grep loop /proc/devices >/dev/null 2>&1
447     then
448         :
449     else
450         _notrun "This test requires loopback device support"
451     fi
452 }
453
454 # check that a FS is mounted as XFS. if so, return mount point
455 #
456 _xfs_mounted()
457 {
458     if [ $# -ne 1 ]
459     then
460         echo "Usage: _xfs_mounted device" 1>&2
461         exit 1
462     fi
463     
464     device=$1
465     
466     if mount | grep $device | $AWK_PROG '
467         /type xfs/  { print $3 ; exit 0 }
468         END         { exit 1 }
469     '
470     then
471         echo "_xfs_mounted: $device is not a mounted XFS FS"
472         exit 1
473     fi
474 }
475
476
477 # setup the .out file link, depending on which form of quota is
478 # enabled as this often influences how the test output appears.
479 # [NB: SCRATCH_DEV must be mounted for this to work]
480
481 _setup_seq_out()
482 {
483     # this lets us phase use of this into the dump/restore tests easier...
484     [ -f $seq.ugquota -a -f $seq.noquota -a $seq.usrquota -a $seq.grpquota ] \
485         || return
486
487     rm -f $seq.out
488     if src/feature -U $SCRATCH_DEV
489     then
490         if src/feature -G $SCRATCH_DEV
491         then
492             ln $seq.ugquota $seq.out
493         else
494             ln $seq.usrquota $seq.out
495         fi
496     elif src/feature -G $SCRATCH_DEV
497     then
498         ln $seq.grpquota $seq.out
499     else
500         ln $seq.noquota $seq.out
501     fi
502 }
503
504
505 # remount a FS to a new mode (ro or rw)
506 #
507 _remount()
508 {
509     if [ $# -ne 2 ]
510     then
511         echo "Usage: _remount device ro/rw" 1>&2
512         exit 1
513     fi
514     device=$1
515     mode=$2
516     
517     if ! mount -o remount,$mode $device
518     then
519         echo "_remount: failed to remount filesystem on $device as $mode"
520         exit 1
521     fi
522     
523     # we might like to check here later
524     #options=`_fs_options $device`
525
526 }
527
528 # run xfs_check and friends on a FS. 
529 #
530 # if the filesystem is mounted, it's either remounted ro before being
531 # checked or it's unmounted and then remounted
532 #
533
534 USE_REMOUNT=0
535
536 _check_filesystem()
537 {
538     if [ $# -ne 1 -a $# -ne 2 ]
539     then
540         echo "Usage: _check_fs device [logdevice]" 1>&2
541         exit 1
542     fi
543     
544     device=$1
545     if [ $# -eq 2 -a "$2" != "" ]; then
546         extra_log_options="-l$2"
547         extra_mount_options="-ologdev=$2"
548     fi
549     type=`_fs_type $device`
550     ok=1
551     
552     if [ "$type" = "xfs" ]
553     then
554         # mounted... 
555         
556         if [ $USE_REMOUNT -eq 0 ]
557         then
558             mountpoint=`_xfs_mounted $device`
559             umount $device
560         else
561             _remount $device ro
562         fi
563     fi
564
565     /usr/sbin/xfs_logprint -t $device $extra_log_options 2>&1 \
566                 | tee $tmp.fs_check | grep -q "<CLEAN>"
567     if [ $? -ne 0 ]
568     then
569         echo "_check_fs: filesystem on $device has dirty log (see $seq.full)"
570         
571         echo "_check_fs: filesystem on $device has dirty log"   >>$seq.full
572         echo "*** xfs_logprint -t output ***"                   >>$seq.full
573         cat $tmp.fs_check                                       >>$seq.full
574         echo "*** end xfs_logprint output"                      >>$seq.full
575         
576         ok=0
577     fi
578
579     /usr/sbin/xfs_check $device 2>&1 | _fix_malloc >$tmp.fs_check 
580     if [ -s $tmp.fs_check ]
581     then
582         echo "_check_fs: filesystem on $device is inconsistent (c) (see $seq.full)"
583         
584         echo "_check_fs: filesystem on $device is inconsistent" >>$seq.full
585         echo "*** xfs_check output ***"                         >>$seq.full
586         cat $tmp.fs_check                                       >>$seq.full
587         echo "*** end xfs_check output"                         >>$seq.full
588         
589         ok=0
590     fi
591     
592     if ! /sbin/xfs_repair -n $device $extra_log_options >$tmp.fs_check 2>&1
593     then
594         echo "_check_fs: filesystem on $device is inconsistent (r) (see $seq.full)"
595         
596         echo "_check_fs: filesystem on $device is inconsistent" >>$seq.full
597         echo "*** xfs_repair -n output ***"                     >>$seq.full
598         cat $tmp.fs_check | _fix_malloc                         >>$seq.full
599         echo "*** end xfs_repair output"                        >>$seq.full
600         
601         ok=0
602     fi
603     rm -f $tmp.fs_check
604     
605     if [ $ok -eq 0 ]
606     then
607         echo "*** mount output ***"                             >>$seq.full
608         mount                                                   >>$seq.full
609         echo "*** end mount output"                             >>$seq.full
610     fi
611     
612     if [ "$type" = "xfs" ]
613     then
614         # mounted... 
615         if [ $USE_REMOUNT -eq 0 ]
616         then
617             if ! mount -t xfs $extra_mount_options $device $mountpoint
618             then
619                 echo "!!! failed to remount $device on $mountpoint"
620                 ok=0
621             fi
622         else
623             _remount $device rw
624         fi
625     fi
626     
627     [ $ok -eq 0 ] && exit 1
628     return 0    
629 }
630
631 _check_test_fs()
632 {
633     _check_filesystem $TEST_DEV $TEST_LOGDEV
634 }
635
636 _check_scratch_fs()
637 {
638     SCRATCH_LOG=""
639     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
640         SCRATCH_LOG="$SCRATCH_LOGDEV"
641     _check_filesystem $SCRATCH_DEV $SCRATCH_LOG
642 }
643
644 ################################################################################
645
646 [ -d /usr/bsd ] && PATH=$PATH:/usr/bsd
647 [ -d /usr/freeware/bin ] && PATH=$PATH:/usr/freeware/bin
648
649 if [ "$iam" != new ]
650 then
651
652     # make some further configuration checks here
653     
654     if [ "$TEST_DEV" = ""  ]
655     then
656         echo "common.rc: Error: \$TEST_DEV is not set"
657         exit 1
658     fi
659     
660     # if $TEST_DEV is not mounted, mount it now as XFS
661     if [ -z "`_fs_type $TEST_DEV`" ]
662     then
663         # $TEST_DEV is not mounted
664         if ! _test_mount
665         then
666             echo "common.rc: could not mount $TEST_DEV on $TEST_DIR"
667             exit 1
668         fi
669     fi
670     
671     if [ "`_fs_type $TEST_DEV`" != "xfs" ]
672     then
673         echo "common.rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED XFS filesystem"
674         df -T $TEST_DEV
675         exit 1
676     fi
677
678 fi
679
680 # check for some required binaries on our $PATH
681 #
682 for exec in mkfs.xfs xfs_logprint xfs_check xfs_repair xfs_db
683 do
684     if which $exec >/dev/null 2>&1 
685     then
686         :
687     else
688         echo "common.rc: cannot find $exec on \$PATH=$PATH"
689         exit 1
690     fi
691 done
692
693 # make sure this script returns success
694 /bin/true