Keep packaging scripts in sync across all of the packages were maintaining here
[xfstests-dev.git] / common.rc
1 ##/bin/sh
2 #-----------------------------------------------------------------------
3 #  Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
4 #  This program is free software; you can redistribute it and/or modify
5 #  it under the terms of the GNU General Public License as published by
6 #  the Free Software Foundation; either version 2 of the License, or
7 #  (at your option) any later version.
8 #
9 #  This program is distributed in the hope that it will be useful,
10 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #  GNU General Public License for more details.
13 #
14 #  You should have received a copy of the GNU General Public License
15 #  along with this program; if not, write to the Free Software
16 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17 #  USA
18 #
19 #  Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
20 #  Mountain View, CA 94043, USA, or: http://www.sgi.com
21 #-----------------------------------------------------------------------
22
23 _mount_opts()
24 {
25     case $FSTYP in
26     xfs)
27         export MOUNT_OPTIONS=$XFS_MOUNT_OPTIONS
28         ;;
29     udf)
30         export MOUNT_OPTIONS=$UDF_MOUNT_OPTIONS
31         ;;
32     nfs)
33         export MOUNT_OPTIONS=$NFS_MOUNT_OPTIONS
34         ;;
35     *)
36         ;;
37     esac
38 }
39
40 _mkfs_opts()
41 {
42     case $FSTYP in
43     xfs)
44         export MKFS_OPTIONS=$XFS_MKFS_OPTIONS
45         ;;
46     udf)
47         [ ! -z "$udf_fsize" ] && \
48             UDF_MKFS_OPTIONS="$UDF_MKFS_OPTIONS -s $udf_fsize"
49         export MKFS_OPTIONS=$UDF_MKFS_OPTIONS
50         ;;
51     nfs)
52         export MKFS_OPTIONS=$NFS_MKFS_OPTIONS
53         ;;
54     *)
55         ;;
56     esac
57 }
58
59 [ -z "$FSTYP" ] && FSTYP=xfs
60 [ -z "$MOUNT_OPTIONS" ] && _mount_opts
61 [ -z "$MKFS_OPTIONS" ] && _mkfs_opts
62
63
64 # we need common.config
65 if ! . ./common.config
66 then
67     echo "$iam: failed to source common.config"
68     exit 1
69 fi
70
71 # make sure we have a standard umask
72 umask 022
73
74 _mount()
75 {
76     $MOUNT_PROG $*
77 }
78
79 _scratch_options()
80 {
81     type=$1
82     SCRATCH_OPTIONS=""
83
84     if [ $FSTYP != "xfs" ]; then
85         return
86     fi
87
88     case $type in
89     mkfs)
90         [ "$HOSTOS" != "IRIX" ] && SCRATCH_OPTIONS="$SCRATCH_OPTIONS -f"
91         rt_opt="-r"
92         log_opt="-l"
93         ;;
94     mount)
95         rt_opt="-o"
96         log_opt="-o"
97         ;;
98     esac
99     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
100         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${rt_opt}rtdev=$SCRATCH_RTDEV"
101     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
102         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${log_opt}logdev=$SCRATCH_LOGDEV"
103 }
104
105 _test_options()
106 {
107     type=$1
108     TEST_OPTIONS=""
109
110     if [ $FSTYP != "xfs" ]; then
111         return
112     fi
113
114     case $type in
115     mkfs)
116         rt_opt="-r"
117         log_opt="-l"
118         ;;
119     mount)
120         rt_opt="-o"
121         log_opt="-o"
122         ;;
123     esac
124     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
125         TEST_OPTIONS="$TEST_OPTIONS ${rt_opt}rtdev=$TEST_RTDEV"
126     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
127         TEST_OPTIONS="$TEST_OPTIONS ${log_opt}logdev=$TEST_LOGDEV"
128 }
129
130 _scratch_mount_options()
131 {
132     _scratch_options mount
133     echo $SCRATCH_OPTIONS $MOUNT_OPTIONS $* $SCRATCH_DEV $SCRATCH_MNT
134 }
135
136 _scratch_mount()
137 {
138     _mount -t $FSTYP `_scratch_mount_options $*`
139 }
140
141 _test_mount()
142 {
143     _test_options mount
144     _mount -t $FSTYP $TEST_OPTIONS $MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR
145 }
146
147 _scratch_mkfs_options()
148 {
149     _scratch_options mkfs
150     echo $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
151 }
152
153 _scratch_mkfs_xfs()
154 {
155     _scratch_options mkfs
156
157     $MKFS_XFS_PROG $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
158     mkfs_status=$?
159
160     if [ "$USE_BIG_LOOPFS" = yes ]; then
161         [ -z "$RETAIN_AG_BYTES" ] && RETAIN_AG_BYTES=0
162         ./tools/ag-wipe -q -r $RETAIN_AG_BYTES $SCRATCH_DEV
163     fi
164
165     return $mkfs_status
166 }
167
168 _scratch_mkfs()
169 {
170     case $FSTYP in
171     xfs)
172         _scratch_mkfs_xfs $*
173         ;;
174     nfs*)
175         # do nothing for nfs
176         ;;
177     udf)
178         $MKFS_UDF_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
179         ;;
180     *)
181         /sbin/mkfs -t $FSTYP -- $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
182         ;;
183     esac
184 }
185
186 _scratch_xfs_db_options()
187 {
188     SCRATCH_OPTIONS=""
189     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
190         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
191     echo $SCRATCH_OPTIONS $* $SCRATCH_DEV
192 }
193
194 _scratch_xfs_logprint()
195 {
196     SCRATCH_OPTIONS=""
197     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
198         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
199     $XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
200 }
201
202 _scratch_xfs_repair()
203 {
204     SCRATCH_OPTIONS=""
205     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
206         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
207     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
208         SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -r$SCRATCH_RTDEV"
209     [ "$USE_BIG_LOOPFS" = yes ] && SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
210     $XFS_REPAIR_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
211 }
212
213 _get_pids_by_name()
214 {
215     if [ $# -ne 1 ]
216     then
217         echo "Usage: _get_pids_by_name process-name" 1>&2
218         exit 1
219     fi
220
221     # Algorithm ... all ps(1) variants have a time of the form MM:SS or
222     # HH:MM:SS before the psargs field, use this as the search anchor.
223     #
224     # Matches with $1 (process-name) occur if the first psarg is $1
225     # or ends in /$1 ... the matching uses sed's regular expressions,
226     # so passing a regex into $1 will work.
227
228     ps $PS_ALL_FLAGS \
229     | sed -n \
230         -e 's/$/ /' \
231         -e 's/[         ][      ]*/ /g' \
232         -e 's/^ //' \
233         -e 's/^[^ ]* //' \
234         -e "/[0-9]:[0-9][0-9]  *[^ ]*\/$1 /s/ .*//p" \
235         -e "/[0-9]:[0-9][0-9]  *$1 /s/ .*//p"
236 }
237
238 # fqdn for localhost
239 #
240 _get_fqdn()
241 {
242     host=`hostname`
243     $NSLOOKUP_PROG $host | $AWK_PROG '{ if ($1 == "Name:") print $2 }'
244 }
245
246 # fix malloc libs output
247 #
248 _fix_malloc()
249 {
250     # filter out the Electric Fence notice
251     $PERL_PROG -e '
252         while (<>) {
253             if (defined $o && /^\s+Electric Fence/) {
254                 chomp($o);
255                 print "$o";
256                 undef $o;
257                 next;
258             }
259             print $o if (defined $o);
260
261             $o=$_;
262         }
263         print $o if (defined $o);
264     '
265 }
266
267 # check if run as root
268 #
269 _need_to_be_root()
270 {
271     id=`id | $SED_PROG -e 's/(.*//' -e 's/.*=//'`
272     if [ "$id" -ne 0 ]
273     then
274         echo "Arrgh ... you need to be root (not uid=$id) to run this test"
275         exit 1
276     fi
277 }
278
279
280 #
281 # _df_device : get an IRIX style df line for a given device
282 #
283 #       - returns "" if not mounted
284 #       - returns fs type in field two (ala IRIX)
285 #       - joins line together if split by fancy df formatting
286 #       - strips header etc
287 #
288
289 _df_device()
290 {
291     if [ $# -ne 1 ]
292     then
293         echo "Usage: _df_device device" 1>&2
294         exit 1
295     fi
296
297     $DF_PROG 2>/dev/null | $AWK_PROG -v what=$1 '
298         match($1,what) && NF==1 {
299             v=$1
300             getline
301             print v, $0
302             exit
303         }
304         match($1,what) {
305             print
306             exit
307         }
308     '
309 }
310
311 #
312 # _df_dir : get an IRIX style df line for device where a directory resides
313 #
314 #       - returns fs type in field two (ala IRIX)
315 #       - joins line together if split by fancy df formatting
316 #       - strips header etc
317 #
318
319 _df_dir()
320 {
321     if [ $# -ne 1 ]
322     then
323         echo "Usage: _df_dir device" 1>&2
324         exit 1
325     fi
326
327     $DF_PROG $1 2>/dev/null | $AWK_PROG -v what=$1 '
328         NR == 2 && NF==1 {
329             v=$1
330             getline
331             print v, $0;
332             exit 0
333         }
334         NR == 2 {
335             print;
336             exit 0
337         }
338         {}
339     '
340     # otherwise, nada
341 }
342
343 # return percentage used disk space for mounted device
344
345 _used()
346 {
347     if [ $# -ne 1 ]
348     then
349         echo "Usage: _used device" 1>&2
350         exit 1
351     fi
352
353     _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
354 }
355
356 # return the FS type of a mounted device
357 #
358 _fs_type()
359 {
360     if [ $# -ne 1 ]
361     then
362         echo "Usage: _fs_type device" 1>&2
363         exit 1
364     fi
365
366     _df_device $1 | $AWK_PROG '{ print $2 }'
367 }
368
369 # return the FS mount options of a mounted device
370 #
371 # should write a version which just parses the output of mount for IRIX
372 # compatibility, but since this isn't used at all, at the moment I'll leave
373 # this for now
374 #
375 _fs_options()
376 {
377     if [ $# -ne 1 ]
378     then
379         echo "Usage: _fs_options device" 1>&2
380         exit 1
381     fi
382
383     $AWK_PROG -v dev=$1 '
384         match($1,dev) { print $4 }
385     ' </proc/mounts
386 }
387
388 # returns device number if a file is a block device
389 #
390 _is_block_dev()
391 {
392     if [ $# -ne 1 ]
393     then
394         echo "Usage: _is_block_dev dev" 1>&2
395         exit 1
396     fi
397
398     [ -b $1 ] && src/lstat64 $1 | $AWK_PROG '/Device type:/ { print $9 }'
399 }
400
401 # Do a command, log it to $seq.full, optionally test return status
402 # and die if command fails. If called with one argument _do executes the
403 # command, logs it, and returns its exit status. With two arguments _do
404 # first prints the message passed in the first argument, and then "done"
405 # or "fail" depending on the return status of the command passed in the
406 # second argument. If the command fails and the variable _do_die_on_error
407 # is set to "always" or the two argument form is used and _do_die_on_error
408 # is set to "message_only" _do will print an error message to
409 # $seq.out and exit.
410
411 _do()
412 {
413     if [ $# -eq 1 ]; then
414         _cmd=$1
415     elif [ $# -eq 2 ]; then
416         _note=$1
417         _cmd=$2
418         echo -n "$_note... "
419     else
420         echo "Usage: _do [note] cmd" 1>&2
421         status=1; exit
422     fi
423
424     (eval "echo '---' \"$_cmd\"") >>$here/$seq.full
425     (eval "$_cmd") >$tmp._out 2>&1; ret=$?
426     cat $tmp._out | _fix_malloc >>$here/$seq.full
427     if [ $# -eq 2 ]; then
428         if [ $ret -eq 0 ]; then
429             echo "done"
430         else
431             echo "fail"
432         fi
433     fi
434     if [ $ret -ne 0  ] \
435         && [ "$_do_die_on_error" = "always" \
436             -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ]
437     then
438         [ $# -ne 2 ] && echo
439         eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full"
440         status=1; exit
441     fi
442
443     return $ret
444 }
445
446 # bail out, setting up .notrun file
447 #
448 _notrun()
449 {
450     echo "$*" >$seq.notrun
451     echo "$seq not run: $*"
452     status=0
453     exit
454 }
455
456 # just plain bail out
457 #
458 _fail()
459 {
460     echo "$*" | tee -a $here/$seq.full
461     echo "(see $seq.full for details)"
462     status=1
463     exit 1
464 }
465
466 # tests whether $FSTYP is one of the supported filesystems for a test
467 #
468 _supported_fs()
469 {
470     for f
471     do
472         if [ "$f" = "$FSTYP" ]
473         then
474             return
475         fi
476     done
477
478     _notrun "not suitable for this filesystem type: $FSTYP"
479 }
480
481 # tests whether $FSTYP is one of the supported OSes for a test
482 #
483 _supported_os()
484 {
485     for h
486     do
487         if [ "$h" = "$HOSTOS" ]
488         then
489             return
490         fi
491     done
492
493     _notrun "not suitable for this OS: $HOSTOS"
494 }
495
496 # this test needs a scratch partition - check we're ok & unmount it
497 #
498 _require_scratch()
499 {
500     case "$FSTYP" in
501         xfs|udf)
502                  if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
503                  then
504                      _notrun "this test requires a valid \$SCRATCH_DEV"
505                  fi
506                  if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
507                  then
508                      _notrun "this test requires a valid \$SCRATCH_DEV"
509                  fi
510                  ;;
511         nfs*|ext2|ext3|reiserfs)
512                  echo $SCRATCH_DEV | grep -q ":" > /dev/null 2>&1
513                  if [ ! -z "$SCRATCH_DEV" -a ! -b "$SCRATCH_DEV" -a "$?" != "0" ]
514                  then
515                      _notrun "this test requires a valid \$SCRATCH_DEV"
516                  fi
517                  ;;
518         *)
519                  _notrun "\$FSTYP ($FSTYP) unknown or not specified"
520                  ;;
521     esac
522
523     # mounted?
524     if _mount | grep -q $SCRATCH_DEV
525     then
526         # if it's mounted, make sure its on $SCRATCH_MNT
527         if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
528         then
529             echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
530             exit 1
531         fi
532         # and then unmount it
533         if ! $UMOUNT_PROG $SCRATCH_DEV
534         then
535             echo "failed to unmount $SCRATCH_DEV"
536             exit 1
537         fi
538     fi
539 }
540
541 # this test needs a logdev
542 #
543 _require_logdev()
544 {
545     [ -z "$SCRATCH_LOGDEV" -o ! -b "$SCRATCH_LOGDEV" ] && \
546         _notrun "This test requires a valid \$SCRATCH_LOGDEV"
547     [ "$USE_EXTERNAL" != yes ] && \
548         _notrun "This test requires USE_EXTERNAL to be enabled"
549
550     # ensure its not mounted
551     $UMOUNT_PROG $SCRATCH_LOGDEV 2>/dev/null
552 }
553
554 # this test requires loopback device support
555 #
556 _require_loop()
557 {
558     if [ "$HOSTOS" != "Linux" ]
559     then
560         _notrun "This test requires linux for loopback device support"
561     fi
562
563     modprobe loop >/dev/null 2>&1
564     if grep loop /proc/devices >/dev/null 2>&1
565     then
566         :
567     else
568         _notrun "This test requires loopback device support"
569     fi
570 }
571
572 # this test requires that (large) loopback device files are not in use
573 #
574 _require_nobigloopfs()
575 {
576     [ "$USE_BIG_LOOPFS" = yes ] && \
577         _notrun "Large filesystem testing in progress, skipped this test"
578 }
579
580 # this test requires that a realtime subvolume is in use, and
581 # that the kernel supports realtime as well.
582 #
583 _require_realtime()
584 {
585     [ "$USE_EXTERNAL" = yes ] || \
586         _notrun "External volumes not in use, skipped this test"
587     [ "$SCRATCH_RTDEV" = "" ] && \
588         _notrun "Realtime device required, skipped this test"
589 }
590
591 # this test requires that a specified command (executable) exists
592 #
593 _require_command()
594 {
595     [ -x "$1" ] || _notrun "$1 utility required, skipped this test"
596 }
597
598 # this test requires that external log/realtime devices are not in use
599 #
600 _require_nonexternal()
601 {
602     [ "$USE_EXTERNAL" = yes ] && \
603         _notrun "External device testing in progress, skipped this test"
604 }
605
606 # check that a FS is mounted as XFS. if so, return mount point
607 #
608 _xfs_mounted()
609 {
610     if [ $# -ne 1 ]
611     then
612         echo "Usage: _xfs_mounted device" 1>&2
613         exit 1
614     fi
615
616     device=$1
617
618     if _mount | grep $device | $AWK_PROG '
619         /type xfs/  { print $3 ; exit 0 }
620         END         { exit 1 }
621     '
622     then
623         echo "_xfs_mounted: $device is not a mounted XFS FS"
624         exit 1
625     fi
626 }
627
628
629 # remount a FS to a new mode (ro or rw)
630 #
631 _remount()
632 {
633     if [ $# -ne 2 ]
634     then
635         echo "Usage: _remount device ro/rw" 1>&2
636         exit 1
637     fi
638     device=$1
639     mode=$2
640
641     if ! mount -o remount,$mode $device
642     then
643         echo "_remount: failed to remount filesystem on $device as $mode"
644         exit 1
645     fi
646 }
647
648 # run xfs_check and friends on a FS.
649 #
650 # if the filesystem is mounted, it's either remounted ro before being
651 # checked or it's unmounted and then remounted
652 #
653
654 USE_REMOUNT=0
655
656 _check_xfs_filesystem()
657 {
658     if [ $# -ne 3 ]
659     then
660         echo "Usage: _check_xfs_filesystem device <logdev>|none <rtdev>|none" 1>&2
661         exit 1
662     fi
663
664     device=$1
665     if [ "$2" != "none" ]; then
666         extra_log_options="-l$2"
667         extra_mount_options="-ologdev=$2"
668     fi
669
670     if [ "$3" != "none" ]; then
671         extra_rt_options="-r$3"
672         extra_mount_options=$extra_mount_options" -ortdev=$3"
673     fi
674
675     [ "$FSTYP" != xfs ] && return 0
676     testoption=""
677     [ "$USE_BIG_LOOPFS" = yes ] && testoption=-t
678
679     type=`_fs_type $device`
680     ok=1
681
682     if [ "$type" = "xfs" ]
683     then
684         # mounted...
685
686         if [ $USE_REMOUNT -eq 0 ]
687         then
688             mountpoint=`_xfs_mounted $device`
689             $UMOUNT_PROG $device
690         else
691             _remount $device ro
692         fi
693     fi
694
695     $XFS_LOGPRINT_PROG -t $extra_log_options $device 2>&1 \
696                 | tee $tmp.logprint | grep -q "<CLEAN>"
697     if [ $? -ne 0 -a "$HOSTOS" = "Linux" ]
698     then
699         echo "_check_xfs_filesystem: filesystem on $device has dirty log (see $seq.full)"
700
701         echo "_check_xfs_filesystem: filesystem on $device has dirty log"   >>$here/$seq.full
702         echo "*** xfs_logprint -t output ***"                   >>$here/$seq.full
703         cat $tmp.logprint                                       >>$here/$seq.full
704         echo "*** end xfs_logprint output"                      >>$here/$seq.full
705
706         ok=0
707     fi
708
709     $XFS_CHECK_PROG $testoption $extra_log_options $device 2>&1 |\
710          _fix_malloc >$tmp.fs_check
711     if [ -s $tmp.fs_check ]
712     then
713         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (c) (see $seq.full)"
714
715         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$here/$seq.full
716         echo "*** xfs_check output ***"                         >>$here/$seq.full
717         cat $tmp.fs_check                                       >>$here/$seq.full
718         echo "*** end xfs_check output"                         >>$here/$seq.full
719
720         ok=0
721     fi
722     # repair doesn't scale massively at this stage, optionally skip it for now
723     [ "$USE_BIG_LOOPFS" = yes ] || \
724     $XFS_REPAIR_PROG -n $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
725     if [ $? -ne 0 ]
726     then
727         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (r) (see $seq.full)"
728
729         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$here/$seq.full
730         echo "*** xfs_repair -n output ***"                     >>$here/$seq.full
731         cat $tmp.repair | _fix_malloc                           >>$here/$seq.full
732         echo "*** end xfs_repair output"                        >>$here/$seq.full
733
734         ok=0
735     fi
736     rm -f $tmp.fs_check $tmp.logprint $tmp.repair
737
738     if [ $ok -eq 0 ]
739     then
740         echo "*** mount output ***"                             >>$here/$seq.full
741         _mount                                                  >>$here/$seq.full
742         echo "*** end mount output"                             >>$here/$seq.full
743     elif [ "$type" = "xfs" ]
744     then
745         # mounted...
746         if [ $USE_REMOUNT -eq 0 ]
747         then
748             if ! _mount -t xfs $extra_mount_options $device $mountpoint
749             then
750                 echo "!!! failed to remount $device on $mountpoint"
751                 ok=0
752             fi
753         else
754             _remount $device rw
755         fi
756     fi
757
758     [ $ok -eq 0 ] && exit 1
759     return 0
760 }
761
762 # Filter the knowen errors the UDF Verifier reports.
763 _udf_test_known_error_filter()
764 {
765         egrep -v "PVD  60  Error: Interchange Level: 1, Maximum Interchange Level: 0|FSD  28  Error: Interchange Level: 1, Maximum Interchange Level: 1,|PVD  72  Warning: Volume Set Identifier: \"\*IRIX UDF\",|Warning: [0-9]+ unused blocks NOT marked as unallocated."
766
767 }
768
769 _check_udf_filesystem()
770 {
771     [ "$DISABLE_UDF_TEST" == "1" ] && return
772
773     if [ $# -ne 1 -a $# -ne 2 ]
774     then
775         echo "Usage: _check_udf_filesystem device [last_block]" 1>&2
776         exit 1
777     fi
778
779     if [ ! -x $here/src/udf_test ]
780     then
781         echo "udf_test not installed, please download and build the Philips"
782         echo "UDF Verification Software from http://www.extra.research.philips.com/udf/."
783         echo "Then copy the udf_test binary to $here/src/."
784         echo "If you do not wish to run udf_test then set environment variable DISABLE_UDF_TEST"
785         echo "to 1."
786         return
787     fi
788
789     device=$1
790     if [ $# -eq 2 ];
791     then
792         LAST_BLOCK=`expr \( $2 - 1 \)`
793         OPT_ARG="-lastvalidblock $LAST_BLOCK"
794     fi
795
796     rm -f $seq.checkfs
797     sleep 1 # Due to a problem with time stamps in udf_test
798     $here/src/udf_test $OPT_ARG $device | tee $here/$seq.checkfs | egrep "Error|Warning" | \
799         _udf_test_known_error_filter | \
800         egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" | \
801         sed "s/^.*$/Warning UDF Verifier reported errors see $seq.checkfs./g"
802
803 }
804
805 _check_test_fs()
806 {
807     TEST_LOG="none"
808     TEST_RT="none"
809     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
810         TEST_LOG="$TEST_LOGDEV"
811
812     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
813         TEST_RT="$TEST_RTDEV"
814
815     _check_xfs_filesystem $TEST_DEV $TEST_LOG $TEST_RT
816
817     # check for ipath consistency
818     if $XFS_GROWFS_PROG -n $TEST_DIR | grep -q 'inode-paths=1'; then
819         # errors go to stderr
820         xfs_check_ipaths $TEST_DIR >/dev/null
821         xfs_repair_ipaths -n $TEST_DIR >/dev/null
822     fi
823 }
824
825 _check_scratch_fs()
826 {
827     case $FSTYP in
828     xfs)
829         SCRATCH_LOG="none"
830         SCRATCH_RT="none"
831         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
832             SCRATCH_LOG="$SCRATCH_LOGDEV"
833
834         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
835             SCRATCH_RT="$SCRATCH_RTDEV"
836
837         _check_xfs_filesystem $SCRATCH_DEV $SCRATCH_LOG $SCRATCH_RT
838         ;;
839     udf)
840         _check_udf_filesystem $SCRATCH_DEV $udf_fsize
841         ;;
842     nfs*)
843         # Don't know how to check an NFS filesystem, yet.
844         ;;
845     *)
846         ;;
847     esac
848 }
849
850 _full_fstyp_details()
851 {
852      [ -z "$FSTYP" ] && FSTYP=xfs
853      if [ $FSTYP = xfs ]; then
854         if [ -d /proc/fs/xfs ]; then
855             if grep -q 'debug 0' /proc/fs/xfs/stat; then
856                 FSTYP="$FSTYP (non-debug)"
857             elif grep -q 'debug 1' /proc/fs/xfs/stat; then
858                 FSTYP="$FSTYP (debug)"
859             fi
860         else
861             if uname -a | grep -qi 'debug'; then
862                 FSTYP="$FSTYP (debug)"
863             else
864                 FSTYP="$FSTYP (non-debug)"
865             fi
866         fi
867      fi
868      echo $FSTYP
869 }
870
871 _full_platform_details()
872 {
873      os=`uname -s`
874      host=`hostname -s`
875      kernel=`uname -r`
876      platform=`uname -m`
877      echo "$os/$platform $host $kernel"
878 }
879
880 _check_testdir()
881 {
882     case $FSTYP in
883     xfs)
884         _check_test_fs
885         ;;
886     udf)
887         _cleanup_testdir
888         _check_scratch_fs
889         _scratch_mount
890         ;;
891     nfs*)
892         # Don't know how to check an NFS filesystem, yet.
893         ;;
894     *)
895         ;;
896     esac
897 }
898
899
900 _setup_xfs_testdir()
901 {
902     [ "$FSTYP" != "xfs" ] \
903         && _fail "setup_xfs_testdir: \$FSTYP ($FSTYP) is not xfs"
904
905     testdir=$TEST_DIR
906 }
907
908 _setup_udf_scratchdir()
909 {
910     [ "$FSTYP" != "udf" ] \
911         && _fail "setup_udf_testdir: \$FSTYP is not udf"
912     [ -z "$SCRATCH_DEV" -o ! -b "$SCRATCH_DEV" ] \
913         && _notrun "this test requires a valid \$SCRATCH_DEV"
914     [ -z "$SCRATCH_MNT" ] \
915         && _notrun "this test requires a valid \$SCRATCH_MNT"
916
917     # mounted?
918     if _mount | grep -q $SCRATCH_DEV
919     then
920         # if it's mounted, make sure its on $TEST_RW_DIR
921         if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
922         then
923             _fail "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
924         fi
925         $UMOUNT_PROG $SCRATCH_DEV
926     fi
927
928     _scratch_mkfs
929     _scratch_mount
930
931     testdir=$SCRATCH_MNT
932 }
933
934 _setup_nfs_scratchdir()
935 {
936     [ "$FSTYP" != "nfs" ] \
937         && _fail "setup_nfs_testdir: \$FSTYP is not nfs"
938     [ -z "$SCRATCH_DEV" ] \
939         && _notrun "this test requires a valid host fs for \$SCRATCH_DEV"
940     [ -z "$SCRATCH_MNT" ] \
941         && _notrun "this test requires a valid \$SCRATCH_MNT"
942
943     # mounted?
944     if _mount | grep -q $SCRATCH_DEV
945     then
946         # if it's mounted, make sure its on $SCRATCH_MNT
947         if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
948         then
949             _fail "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
950         fi
951         $UMOUNT_PROG $SCRATCH_DEV
952     fi
953
954     _scratch_mkfs
955     _scratch_mount
956
957     testdir=$SCRATCH_MNT
958 }
959
960 #
961 # Warning for UDF and NFS this function calls _setup_udf_scratchdir and
962 # _setup_udf_scratchdir. This is done because testdir is a persistent
963 # XFS only partition.
964 #
965 _setup_testdir()
966 {
967     case $FSTYP in
968     xfs)
969         _setup_xfs_testdir
970         ;;
971     udf)
972         _setup_udf_scratchdir
973         ;;
974     nfs*)
975         _setup_nfs_scratchdir
976         ;;
977     *)
978         _fail "\$FSTYP is not xfs, udf or nfs"
979         ;;
980     esac
981 }
982
983 _cleanup_testdir()
984 {
985     case $FSTYP in
986     xfs)
987         # do nothing, testdir is $TEST_DIR
988         :
989         ;;
990     udf)
991         # umount testdir as it is $SCRATCH_MNT which could be used by xfs next
992         [ -n "$testdir" ] && $UMOUNT_PROG $testdir
993         ;;
994     nfs*)
995         # umount testdir as it is $SCRATCH_MNT which could be used by xfs next
996         [ -n "$testdir" ] && $UMOUNT_PROG $testdir
997         ;;
998     *)
999         _fail "\$FSTYP is not xfs, udf or nfs"
1000         ;;
1001     esac
1002 }
1003
1004 _link_out_file()
1005 {
1006    if [ -z "$1" ]; then
1007       echo Error must pass \$seq.
1008       exit
1009    fi
1010    rm -f $1
1011    if [ "`uname`" == "IRIX64" ] || [ "`uname`" == "IRIX" ]; then
1012       ln -s $1.irix $1
1013    elif [ "`uname`" == "Linux" ]; then
1014       ln -s $1.linux $1
1015    else
1016       echo Error test $seq does not run on the operating system: `uname`
1017       exit
1018    fi
1019 }
1020
1021 _die()
1022 {
1023         echo $@
1024         exit 1
1025 }
1026
1027 _nfiles()
1028 {
1029         f=0
1030         while [ $f -lt $1 ]
1031         do
1032                 file=f$f
1033                 touch $file
1034                 if [ $size -gt 0 ]; then
1035                     dd if=/dev/zero of=$file bs=1024 count=$size
1036                 fi
1037                 f=`expr $f + 1`
1038         done
1039 }
1040
1041 # takes dirname, depth
1042 _descend()
1043 {
1044         dirname=$1; depth=$2
1045         mkdir $dirname  || die "mkdir $dirname failed"
1046         cd $dirname
1047
1048         _nfiles $files           # files for this dir
1049
1050         [ $depth -eq 0 ] && return
1051         deep=`expr $depth - 1`  # go 1 down
1052
1053         [ $verbose = true ] && echo "descending, depth from leaves = $deep"
1054
1055         d=0
1056         while [ $d -lt $dirs ]
1057         do
1058                 _descend d$d $deep &
1059                 d=`expr $d + 1`
1060                 wait
1061         done
1062 }
1063
1064 # Populate a filesystem with inodes for performance experiments
1065 #
1066 # usage: populate [-v] [-n ndirs] [-f nfiles] [-d depth] [-r root] [-s size]
1067 #
1068 _populate_fs()
1069 {
1070
1071     here=`pwd`
1072     dirs=5          # ndirs in each subdir till leaves
1073     size=0          # sizeof files in K
1074     files=100       # num files in _each_ subdir
1075     depth=2         # depth of tree from root to leaves
1076     verbose=false
1077     root=root       # path of initial root of directory tree
1078
1079     while getopts "d:f:n:r:s:v" c
1080     do
1081         case $c in
1082         d)      depth=$OPTARG;;
1083         n)      dirs=$OPTARG;;
1084         f)      files=$OPTARG;;
1085         s)      size=$OPTARG;;
1086         v)      verbose=true;;
1087         r)      root=$OPTARG;;
1088         esac
1089     done
1090
1091
1092     _descend $root $depth
1093     wait
1094
1095     cd $here
1096
1097     [ $verbose = true ] && echo done
1098 }
1099
1100 # query whether the given file has the given inode flag set
1101 #
1102 _test_inode_flag()
1103 {
1104     flag=$1
1105     file=$2
1106
1107     if which $XFS_IO_PROG >/dev/null; then
1108         if $XFS_IO_PROG -r -c 'lsattr -v' "$file" | grep -q "$flag" ; then
1109             return 0
1110         fi
1111     fi
1112     return 1
1113 }
1114
1115
1116 ################################################################################
1117
1118 if [ "$iam" != new -a "$iam" != bench ]
1119 then
1120     # make some further configuration checks here
1121
1122     if [ "$TEST_DEV" = ""  ]
1123     then
1124         echo "common.rc: Error: \$TEST_DEV is not set"
1125         exit 1
1126     fi
1127
1128     # if $TEST_DEV is not mounted, mount it now as XFS
1129     if [ -z "`_fs_type $TEST_DEV`" ]
1130     then
1131         # $TEST_DEV is not mounted
1132         if ! _test_mount
1133         then
1134             echo "common.rc: retrying test device mount with external set"
1135             [ "$USE_EXTERNAL" != "yes" ] && export USE_EXTERNAL=yes
1136             if ! _test_mount
1137             then
1138                 echo "common.rc: could not mount $TEST_DEV on $TEST_DIR"
1139                 exit 1
1140             fi
1141         fi
1142     fi
1143
1144     if [ "`_fs_type $TEST_DEV`" != "xfs" ]
1145     then
1146         echo "common.rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED XFS filesystem"
1147         $DF_PROG $TEST_DEV
1148         exit 1
1149     fi
1150 fi
1151
1152 # make sure this script returns success
1153 /bin/true