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