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