common: Enhance the scratch dev pool and deletable device check
[xfstests-dev.git] / common / rc
1 ##/bin/bash
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 BC=$(which bc 2> /dev/null) || BC=
24
25 _require_math()
26 {
27         if [ -z "$BC" ]; then
28                 _notrun "this test requires 'bc' tool for doing math operations"
29         fi
30 }
31
32 _math()
33 {
34         [ $# -le 0 ] && return
35         if [ "$BC" ]; then
36                 result=$(LANG=C echo "scale=0; $@" | "$BC" -q 2> /dev/null)
37         else
38                 _notrun "this test requires 'bc' tool for doing math operations"
39         fi
40         echo "$result"
41 }
42
43 dd()
44 {
45    if [ "$HOSTOS" == "Linux" ]
46    then 
47         command dd --help | grep noxfer > /dev/null 2>&1
48         
49         if [ "$?" -eq 0 ]
50             then
51                 command dd status=noxfer $@
52             else
53                 command dd $@
54         fi
55    else
56         command dd $@
57    fi
58 }
59
60 _btrfs_get_subvolid()
61 {
62         mnt=$1
63         name=$2
64
65         $BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
66 }
67
68 # Prints the md5 checksum of a given file
69 _md5_checksum()
70 {
71         md5sum $1 | cut -d ' ' -f1
72 }
73
74
75 # ls -l w/ selinux sometimes puts a dot at the end:
76 # -rwxrw-r--. id1 id2 file1
77 # Also filter out lost+found directory on extN file system if present
78
79 _ls_l()
80 {
81         ls -l $* | sed "s/\(^[-rwxdlbcpsStT]*\)\. /\1 /" | grep -v 'lost+found'
82 }
83
84 _mount_opts()
85 {
86     # SELinux adds extra xattrs which can mess up our expected output.
87     # So, mount with a context, and they won't be created
88     # nfs_t is a "liberal" context so we can use it.
89     if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
90         SELINUX_MOUNT_OPTIONS="-o context=system_u:object_r:nfs_t:s0"
91         export SELINUX_MOUNT_OPTIONS
92     fi
93
94     case $FSTYP in
95     xfs)
96         export MOUNT_OPTIONS=$XFS_MOUNT_OPTIONS
97         ;;
98     udf)
99         export MOUNT_OPTIONS=$UDF_MOUNT_OPTIONS
100         ;;
101     nfs)
102         export MOUNT_OPTIONS=$NFS_MOUNT_OPTIONS
103         ;;
104     ext2|ext3|ext4|ext4dev)
105         # acls & xattrs aren't turned on by default on ext$FOO
106         export MOUNT_OPTIONS="-o acl,user_xattr $EXT_MOUNT_OPTIONS"
107         ;;
108     reiserfs)
109         # acls & xattrs aren't turned on by default on reiserfs
110         export MOUNT_OPTIONS="-o acl,user_xattr $REISERFS_MOUNT_OPTIONS"
111         ;;
112     gfs2)
113         # acls aren't turned on by default on gfs2
114         export MOUNT_OPTIONS="-o acl $GFS2_MOUNT_OPTIONS"
115         ;;
116     tmpfs)
117         # We need to specify the size at mount, use 512 MB by default
118         export MOUNT_OPTIONS="-o size=512M $TMPFS_MOUNT_OPTIONS"
119         ;;
120     *)
121         ;;
122     esac
123 }
124
125 _mkfs_opts()
126 {
127     case $FSTYP in
128     xfs)
129         export MKFS_OPTIONS=$XFS_MKFS_OPTIONS
130         ;;
131     udf)
132         [ ! -z "$udf_fsize" ] && \
133             UDF_MKFS_OPTIONS="$UDF_MKFS_OPTIONS -s $udf_fsize"
134         export MKFS_OPTIONS=$UDF_MKFS_OPTIONS
135         ;;
136     nfs)
137         export MKFS_OPTIONS=$NFS_MKFS_OPTIONS
138         ;;
139     reiserfs)
140         export MKFS_OPTIONS="$REISERFS_MKFS_OPTIONS -q"
141         ;;
142     gfs2)
143         export MKFS_OPTIONS="$GFS2_MKFS_OPTIONS -O -p lock_nolock"
144         ;;
145     jfs)
146         export MKFS_OPTIONS="$JFS_MKFS_OPTIONS -q"
147         ;;
148     tmpfs)
149         export MKFS_OPTIONS="$TMPFS_MKFS_OPTIONS"
150         ;;
151     *)
152         ;;
153     esac
154 }
155
156 _fsck_opts()
157 {
158     case $FSTYP in
159     ext2|ext3|ext4|ext4dev)
160         export FSCK_OPTIONS="-nf"
161         ;;
162     reiserfs)
163         export FSCK_OPTIONS="--yes"
164         ;;
165     *)
166         export FSCK_OPTIONS="-n"
167         ;;
168     esac
169 }
170
171 [ -z "$FSTYP" ] && FSTYP=xfs
172 [ -z "$MOUNT_OPTIONS" ] && _mount_opts
173 [ -z "$MKFS_OPTIONS" ] && _mkfs_opts
174 [ -z "$FSCK_OPTIONS" ] && _fsck_opts
175
176
177 # we need common/config
178 if [ "$iam" != "check" ]
179 then
180     if ! . ./common/config
181         then
182         echo "$iam: failed to source common/config"
183         exit 1
184     fi
185 fi
186
187 # check for correct setup
188 case "$FSTYP" in
189     xfs)
190          [ "$XFS_LOGPRINT_PROG" = "" ] && _fatal "xfs_logprint not found"
191          [ "$XFS_REPAIR_PROG" = "" ] && _fatal "xfs_repair not found"
192          [ "$XFS_DB_PROG" = "" ] && _fatal "xfs_db not found"
193          [ "$MKFS_XFS_PROG" = "" ] && _fatal "mkfs_xfs not found"
194          ;;
195     udf)
196          [ "$MKFS_UDF_PROG" = "" ] && _fatal "mkfs_udf/mkudffs not found"
197          ;;
198     btrfs)
199          [ "$MKFS_BTRFS_PROG" = "" ] && _fatal "mkfs.btrfs not found"
200          ;;
201     nfs)
202          ;;
203 esac
204
205 # make sure we have a standard umask
206 umask 022
207
208 _mount()
209 {
210     $MOUNT_PROG `_mount_ops_filter $*`
211 }
212
213 _scratch_options()
214 {
215     type=$1
216     SCRATCH_OPTIONS=""
217
218     if [ "$FSTYP" != "xfs" ]; then
219         return
220     fi
221
222     case $type in
223     mkfs)
224         [ "$HOSTOS" != "IRIX" ] && SCRATCH_OPTIONS="$SCRATCH_OPTIONS -f"
225         rt_opt="-r"
226         log_opt="-l"
227         ;;
228     mount)
229         rt_opt="-o"
230         log_opt="-o"
231         ;;
232     esac
233     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
234         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${rt_opt}rtdev=$SCRATCH_RTDEV"
235     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
236         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${log_opt}logdev=$SCRATCH_LOGDEV"
237 }
238
239 _test_options()
240 {
241     type=$1
242     TEST_OPTIONS=""
243
244     if [ "$FSTYP" != "xfs" ]; then
245         return
246     fi
247
248     case $type in
249     mkfs)
250         rt_opt="-r"
251         log_opt="-l"
252         ;;
253     mount)
254         rt_opt="-o"
255         log_opt="-o"
256         ;;
257     esac
258     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
259         TEST_OPTIONS="$TEST_OPTIONS ${rt_opt}rtdev=$TEST_RTDEV"
260     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
261         TEST_OPTIONS="$TEST_OPTIONS ${log_opt}logdev=$TEST_LOGDEV"
262 }
263
264 _mount_ops_filter()
265 {
266     params="$*"
267     
268     #get mount point to handle dmapi mtpt option correctly
269     let last_index=$#-1
270     [ $last_index -gt 0 ] && shift $last_index
271     FS_ESCAPED=$1
272     
273     # irix is fussy about how it is fed its mount options
274     # - multiple -o's are not allowed
275     # - no spaces between comma delimitered options
276     # the sed script replaces all -o's (except the first) with a comma
277     # not required for linux, but won't hurt
278     
279     echo $params | sed -e 's/[[:space:]]\+-o[[:space:]]*/UnIqUe/1; s/[[:space:]]\+-o[[:space:]]*/,/g; s/UnIqUe/ -o /1' \
280         | sed -e 's/dmapi/dmi/' \
281         | $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$FS_ESCAPED\1\2#; print;"
282
283 }
284
285 _scratch_mount_options()
286 {
287     _scratch_options mount
288
289     echo $SCRATCH_OPTIONS $MOUNT_OPTIONS $SELINUX_MOUNT_OPTIONS $* $SCRATCH_DEV $SCRATCH_MNT
290 }
291
292 _scratch_mount()
293 {
294     _mount -t $FSTYP `_scratch_mount_options $*`
295 }
296
297 _scratch_unmount()
298 {
299     $UMOUNT_PROG $SCRATCH_DEV
300 }
301
302 _scratch_remount()
303 {
304     _scratch_unmount
305     _scratch_mount
306 }
307
308 _test_mount()
309 {
310     _test_options mount
311     _mount -t $FSTYP $TEST_OPTIONS $TEST_FS_MOUNT_OPTS $SELINUX_MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR
312 }
313
314 _scratch_mkfs_options()
315 {
316     _scratch_options mkfs
317     echo $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
318 }
319
320
321 _setup_large_xfs_fs()
322 {
323         fs_size=$1
324         local tmp_dir=/tmp/
325
326         [ "$LARGE_SCRATCH_DEV" != yes ] && return 0
327         [ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0
328         [ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0
329
330         # calculate the size of the file we need to allocate.
331         # Default free space in the FS is 50GB, but you can specify more via
332         # SCRATCH_DEV_EMPTY_SPACE
333         file_size=$(($fs_size - 50*1024*1024*1024))
334         file_size=$(($file_size - $SCRATCH_DEV_EMPTY_SPACE))
335
336         # mount the filesystem, create the file, unmount it
337         _scratch_mount 2>&1 >$tmp_dir/mnt.err
338         local status=$?
339         if [ $status -ne 0 ]; then
340                 echo "mount failed"
341                 cat $tmp_dir/mnt.err >&2
342                 rm -f $tmp_dir/mnt.err
343                 return $status
344         fi
345         rm -f $tmp_dir/mnt.err
346
347         xfs_io -F -f \
348                 -c "truncate $file_size" \
349                 -c "falloc -k 0 $file_size" \
350                 -c "chattr +d" \
351                 $SCRATCH_MNT/.use_space 2>&1 > /dev/null
352         export NUM_SPACE_FILES=1
353         status=$?
354         umount $SCRATCH_MNT
355         if [ $status -ne 0 ]; then
356                 echo "large file prealloc failed"
357                 cat $tmp_dir/mnt.err >&2
358                 return $status
359         fi
360         return 0
361 }
362
363 _scratch_mkfs_xfs()
364 {
365     # extra mkfs options can be added by tests
366     local extra_mkfs_options=$*
367
368     local tmp_dir=/tmp/
369
370     _scratch_options mkfs
371
372     # save mkfs output in case conflict means we need to run again.
373     # only the output for the mkfs that applies should be shown
374     $MKFS_XFS_PROG $SCRATCH_OPTIONS $MKFS_OPTIONS $extra_mkfs_options $SCRATCH_DEV \
375         2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
376     local mkfs_status=$?
377
378     # a mkfs failure may be caused by conflicts between
379     # $MKFS_OPTIONS and $extra_mkfs_options
380
381     if [ $mkfs_status -ne 0 -a ! -z "$extra_mkfs_options" ]; then
382         echo "** mkfs failed with extra mkfs options added to \"$MKFS_OPTIONS\" by test $seq **" \
383             >>$seqres.full
384         echo "** attempting to mkfs using only test $seq options: $extra_mkfs_options **" \
385             >>$seqres.full
386         # running mkfs again. overwrite previous mkfs output files
387         $MKFS_XFS_PROG $SCRATCH_OPTIONS $extra_mkfs_options $SCRATCH_DEV \
388             2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
389         mkfs_status=$?
390     fi
391
392     if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
393         # manually parse the mkfs output to get the fs size in bytes
394         local fs_size
395         fs_size=`cat $tmp_dir.mkfsstd | perl -ne '
396             if (/^data\s+=\s+bsize=(\d+)\s+blocks=(\d+)/) {
397                 my $size = $1 * $2;
398                 print STDOUT "$size\n";
399             }'`
400         _setup_large_xfs_fs $fs_size
401         mkfs_status=$?
402     fi
403
404     # output stored mkfs output
405     cat $tmp_dir.mkfserr >&2
406     cat $tmp_dir.mkfsstd
407     rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
408
409     return $mkfs_status
410 }
411
412 # xfs_check script is planned to be deprecated. But, we want to
413 # be able to invoke "xfs_check" behavior in xfstests in order to
414 # maintain the current verification levels.
415 _xfs_check()
416 {
417     OPTS=" "
418     DBOPTS=" "
419     USAGE="Usage: xfs_check [-fsvV] [-l logdev] [-i ino]... [-b bno]... special"
420
421     while getopts "b:fi:l:stvV" c
422     do
423         case $c in
424             s) OPTS=$OPTS"-s ";;
425             t) OPTS=$OPTS"-t ";;
426             v) OPTS=$OPTS"-v ";;
427             i) OPTS=$OPTS"-i "$OPTARG" ";;
428             b) OPTS=$OPTS"-b "$OPTARG" ";;
429             f) DBOPTS=$DBOPTS" -f";;
430             l) DBOPTS=$DBOPTS" -l "$OPTARG" ";;
431             V) $XFS_DB_PROG -p xfs_check -V
432                 return $?
433                 ;;
434         esac
435     done
436     set -- extra $@
437     shift $OPTIND
438     case $# in
439         1)    ${XFS_DB_PROG}${DBOPTS} -F -i -p xfs_check -c "check$OPTS" $1
440                status=$?
441                ;;
442         2)    echo $USAGE 1>&1
443               status=2
444               ;;
445     esac
446     return $status
447 }
448
449 _setup_large_ext4_fs()
450 {
451         fs_size=$1
452         local tmp_dir=/tmp/
453
454         [ "$LARGE_SCRATCH_DEV" != yes ] && return 0
455         [ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0
456         [ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0
457
458         # Default free space in the FS is 50GB, but you can specify more via
459         # SCRATCH_DEV_EMPTY_SPACE
460         space_to_consume=$(($fs_size - 50*1024*1024*1024 - $SCRATCH_DEV_EMPTY_SPACE))
461
462         # mount the filesystem and create 16TB - 4KB files until we consume
463         # all the necessary space.
464         _scratch_mount 2>&1 >$tmp_dir/mnt.err
465         local status=$?
466         if [ $status -ne 0 ]; then
467                 echo "mount failed"
468                 cat $tmp_dir/mnt.err >&2
469                 rm -f $tmp_dir/mnt.err
470                 return $status
471         fi
472         rm -f $tmp_dir/mnt.err
473
474         file_size=$((16*1024*1024*1024*1024 - 4096))
475         nfiles=0
476         while [ $space_to_consume -gt $file_size ]; do
477
478                 xfs_io -F -f \
479                         -c "truncate $file_size" \
480                         -c "falloc -k 0 $file_size" \
481                         $SCRATCH_MNT/.use_space.$nfiles 2>&1
482                 status=$?
483                 if [ $status -ne 0 ]; then
484                         break;
485                 fi
486
487                 space_to_consume=$(( $space_to_consume - $file_size ))
488                 nfiles=$(($nfiles + 1))
489         done
490
491         # consume the remaining space.
492         if [ $space_to_consume -gt 0 ]; then
493                 xfs_io -F -f \
494                         -c "truncate $space_to_consume" \
495                         -c "falloc -k 0 $space_to_consume" \
496                         $SCRATCH_MNT/.use_space.$nfiles 2>&1
497                 status=$?
498         fi
499         export NUM_SPACE_FILES=$nfiles
500
501         umount $SCRATCH_MNT
502         if [ $status -ne 0 ]; then
503                 echo "large file prealloc failed"
504                 cat $tmp_dir/mnt.err >&2
505                 return $status
506         fi
507         return 0
508 }
509 _scratch_mkfs_ext4()
510 {
511         local tmp_dir=/tmp/
512
513         /sbin/mkfs -t $FSTYP -- -F $MKFS_OPTIONS $* $SCRATCH_DEV \
514                         2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
515         local mkfs_status=$?
516
517         if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
518                 # manually parse the mkfs output to get the fs size in bytes
519                 fs_size=`cat $tmp_dir.mkfsstd | awk ' \
520                         /^Block size/ { split($2, a, "="); bs = a[2] ; } \
521                         / inodes, / { blks = $3 } \
522                         /reserved for the super user/ { resv = $1 } \
523                         END { fssize = bs * blks - resv; print fssize }'`
524
525                 _setup_large_ext4_fs $fs_size
526                 mkfs_status=$?
527         fi
528
529         # output stored mkfs output
530         cat $tmp_dir.mkfserr >&2
531         cat $tmp_dir.mkfsstd
532         rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
533
534         return $mkfs_status
535 }
536
537 _scratch_mkfs()
538 {
539     case $FSTYP in
540     xfs)
541         _scratch_mkfs_xfs $*
542         ;;
543     nfs*)
544         # do nothing for nfs
545         ;;
546     udf)
547         $MKFS_UDF_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
548         ;;
549     btrfs)
550         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
551         ;;
552     ext4)
553         _scratch_mkfs_ext4 $*
554         ;;
555     tmpfs)
556         # do nothing for tmpfs
557         ;;
558     *)
559         yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $SCRATCH_DEV
560         ;;
561     esac
562 }
563
564 _scratch_pool_mkfs()
565 {
566     case $FSTYP in
567     btrfs)
568         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV_POOL > /dev/null
569         ;;
570     *)
571         echo "_scratch_pool_mkfs is not implemented for $FSTYP" 1>&2
572         ;;
573     esac
574 }
575
576 # Create fs of certain size on scratch device
577 # _scratch_mkfs_sized <size in bytes> [optional blocksize]
578 _scratch_mkfs_sized()
579 {
580     fssize=$1
581     blocksize=$2
582     [ -z "$blocksize" ] && blocksize=4096
583
584     re='^[0-9]+$'
585     if ! [[ $fssize =~ $re ]] ; then
586         _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
587     fi
588     if ! [[ $blocksize =~ $re ]] ; then
589         _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
590     fi
591
592     blocks=`expr $fssize / $blocksize`
593
594     if [ "$HOSTOS" == "Linux" ]; then
595         devsize=`blockdev --getsize64 $SCRATCH_DEV`
596         [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
597     fi
598
599     case $FSTYP in
600     xfs)
601         # don't override MKFS_OPTIONS that set a block size.
602         echo $MKFS_OPTIONS |egrep -q "b?size="
603         if [ $? -eq 0 ]; then
604                 _scratch_mkfs_xfs -d size=$fssize
605         else
606                 _scratch_mkfs_xfs -d size=$fssize -b size=$blocksize
607         fi
608         ;;
609     ext2|ext3|ext4|ext4dev)
610         yes | ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
611         ;;
612     udf)
613         $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
614         ;;
615     btrfs)
616         $MKFS_BTRFS_PROG $MKFS_OPTIONS -b $fssize $SCRATCH_DEV
617         ;;
618     *)
619         _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
620         ;;
621     esac
622 }
623
624 # Emulate an N-data-disk stripe w/ various stripe units
625 # _scratch_mkfs_geom <sunit bytes> <swidth multiplier> [optional blocksize]
626 _scratch_mkfs_geom()
627 {
628     sunit_bytes=$1
629     swidth_mult=$2
630     blocksize=$3
631     [ -z "$blocksize" ] && blocksize=4096
632
633     let sunit_blocks=$sunit_bytes/$blocksize
634     let swidth_blocks=$sunit_blocks*$swidth_mult
635
636     case $FSTYP in
637     xfs)
638         MKFS_OPTIONS+=" -b size=$blocksize, -d su=$sunit_bytes,sw=$swidth_mult"
639         ;;
640     ext4|ext4dev)
641         MKFS_OPTIONS+=" -b $blocksize -E stride=$sunit_blocks,stripe_width=$swidth_blocks"
642         ;;
643     *)
644         _notrun "can't mkfs $FSTYP with geometry"
645         ;;
646     esac
647     _scratch_mkfs
648 }
649
650 _scratch_resvblks()
651 {
652         case $FSTYP in
653         xfs)
654                 xfs_io -x -c "resblks $1" $SCRATCH_MNT
655                 ;;
656         *)
657                 ;;
658         esac
659 }
660
661 _scratch_xfs_db_options()
662 {
663     SCRATCH_OPTIONS=""
664     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
665         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
666     echo $SCRATCH_OPTIONS $* $SCRATCH_DEV
667 }
668
669 _scratch_xfs_logprint()
670 {
671     SCRATCH_OPTIONS=""
672     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
673         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
674     $XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
675 }
676
677 _scratch_xfs_check()
678 {
679     SCRATCH_OPTIONS=""
680     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
681         SCRATCH_OPTIONS="-l $SCRATCH_LOGDEV"
682     [ "$LARGE_SCRATCH_DEV" = yes ] && \
683         SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
684     _xfs_check $SCRATCH_OPTIONS $* $SCRATCH_DEV
685 }
686
687 _scratch_xfs_repair()
688 {
689     SCRATCH_OPTIONS=""
690     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
691         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
692     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
693         SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -r$SCRATCH_RTDEV"
694     [ "$LARGE_SCRATCH_DEV" = yes ] && SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
695     $XFS_REPAIR_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
696 }
697
698 _get_pids_by_name()
699 {
700     if [ $# -ne 1 ]
701     then
702         echo "Usage: _get_pids_by_name process-name" 1>&2
703         exit 1
704     fi
705
706     # Algorithm ... all ps(1) variants have a time of the form MM:SS or
707     # HH:MM:SS before the psargs field, use this as the search anchor.
708     #
709     # Matches with $1 (process-name) occur if the first psarg is $1
710     # or ends in /$1 ... the matching uses sed's regular expressions,
711     # so passing a regex into $1 will work.
712
713     ps $PS_ALL_FLAGS \
714     | sed -n \
715         -e 's/$/ /' \
716         -e 's/[         ][      ]*/ /g' \
717         -e 's/^ //' \
718         -e 's/^[^ ]* //' \
719         -e "/[0-9]:[0-9][0-9]  *[^ ]*\/$1 /s/ .*//p" \
720         -e "/[0-9]:[0-9][0-9]  *$1 /s/ .*//p"
721 }
722
723 # fix malloc libs output
724 #
725 _fix_malloc()
726 {
727     # filter out the Electric Fence notice
728     $PERL_PROG -e '
729         while (<>) {
730             if (defined $o && /^\s+Electric Fence/) {
731                 chomp($o);
732                 print "$o";
733                 undef $o;
734                 next;
735             }
736             print $o if (defined $o);
737
738             $o=$_;
739         }
740         print $o if (defined $o);
741     '
742 }
743
744 # check if run as root
745 #
746 _need_to_be_root()
747 {
748     id=`id | $SED_PROG -e 's/(.*//' -e 's/.*=//'`
749     if [ "$id" -ne 0 ]
750     then
751         echo "Arrgh ... you need to be root (not uid=$id) to run this test"
752         exit 1
753     fi
754 }
755
756
757 #
758 # _df_device : get an IRIX style df line for a given device
759 #
760 #       - returns "" if not mounted
761 #       - returns fs type in field two (ala IRIX)
762 #       - joins line together if split by fancy df formatting
763 #       - strips header etc
764 #
765
766 _df_device()
767 {
768     if [ $# -ne 1 ]
769     then
770         echo "Usage: _df_device device" 1>&2
771         exit 1
772     fi
773
774     $DF_PROG 2>/dev/null | $AWK_PROG -v what=$1 '
775         match($1,what) && NF==1 {
776             v=$1
777             getline
778             print v, $0
779             exit
780         }
781         match($1,what) {
782             print
783             exit
784         }
785     '
786 }
787
788 #
789 # _df_dir : get an IRIX style df line for device where a directory resides
790 #
791 #       - returns fs type in field two (ala IRIX)
792 #       - joins line together if split by fancy df formatting
793 #       - strips header etc
794 #
795
796 _df_dir()
797 {
798     if [ $# -ne 1 ]
799     then
800         echo "Usage: _df_dir device" 1>&2
801         exit 1
802     fi
803
804     $DF_PROG $1 2>/dev/null | $AWK_PROG -v what=$1 '
805         NR == 2 && NF==1 {
806             v=$1
807             getline
808             print v, $0;
809             exit 0
810         }
811         NR == 2 {
812             print;
813             exit 0
814         }
815         {}
816     '
817     # otherwise, nada
818 }
819
820 # return percentage used disk space for mounted device
821
822 _used()
823 {
824     if [ $# -ne 1 ]
825     then
826         echo "Usage: _used device" 1>&2
827         exit 1
828     fi
829
830     _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
831 }
832
833 # return the FS type of a mounted device
834 #
835 _fs_type()
836 {
837     if [ $# -ne 1 ]
838     then
839         echo "Usage: _fs_type device" 1>&2
840         exit 1
841     fi
842
843     #
844     # The Linux kernel shows NFSv4 filesystems in df output as
845     # filesystem type nfs4, although we mounted it as nfs earlier.
846     # Fix the filesystem type up here so that the callers don't
847     # have to bother with this quirk.
848     #
849     _df_device $1 | $AWK_PROG '{ print $2 }' | sed -e 's/nfs4/nfs/'
850 }
851
852 # return the FS mount options of a mounted device
853 #
854 # should write a version which just parses the output of mount for IRIX
855 # compatibility, but since this isn't used at all, at the moment I'll leave
856 # this for now
857 #
858 _fs_options()
859 {
860     if [ $# -ne 1 ]
861     then
862         echo "Usage: _fs_options device" 1>&2
863         exit 1
864     fi
865
866     $AWK_PROG -v dev=$1 '
867         match($1,dev) { print $4 }
868     ' </proc/mounts
869 }
870
871 # returns device number if a file is a block device
872 #
873 _is_block_dev()
874 {
875     if [ $# -ne 1 ]
876     then
877         echo "Usage: _is_block_dev dev" 1>&2
878         exit 1
879     fi
880
881     _dev=$1
882     if [ -L "${_dev}" ]; then
883         _dev=`readlink -f ${_dev}`
884     fi
885
886     if [ -b "${_dev}" ]; then
887         src/lstat64 ${_dev} | $AWK_PROG '/Device type:/ { print $9 }'
888     fi
889 }
890
891 # Do a command, log it to $seqres.full, optionally test return status
892 # and die if command fails. If called with one argument _do executes the
893 # command, logs it, and returns its exit status. With two arguments _do
894 # first prints the message passed in the first argument, and then "done"
895 # or "fail" depending on the return status of the command passed in the
896 # second argument. If the command fails and the variable _do_die_on_error
897 # is set to "always" or the two argument form is used and _do_die_on_error
898 # is set to "message_only" _do will print an error message to
899 # $seqres.out and exit.
900
901 _do()
902 {
903     if [ $# -eq 1 ]; then
904         _cmd=$1
905     elif [ $# -eq 2 ]; then
906         _note=$1
907         _cmd=$2
908         echo -n "$_note... "
909     else
910         echo "Usage: _do [note] cmd" 1>&2
911         status=1; exit
912     fi
913
914     (eval "echo '---' \"$_cmd\"") >>$seqres.full
915     (eval "$_cmd") >$tmp._out 2>&1; ret=$?
916     cat $tmp._out | _fix_malloc >>$seqres.full
917     if [ $# -eq 2 ]; then
918         if [ $ret -eq 0 ]; then
919             echo "done"
920         else
921             echo "fail"
922         fi
923     fi
924     if [ $ret -ne 0  ] \
925         && [ "$_do_die_on_error" = "always" \
926             -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ]
927     then
928         [ $# -ne 2 ] && echo
929         eval "echo \"$_cmd\" failed \(returned $ret\): see $seqres.full"
930         status=1; exit
931     fi
932
933     return $ret
934 }
935
936 # bail out, setting up .notrun file
937 #
938 _notrun()
939 {
940     echo "$*" > $seqres.notrun
941     echo "$seq not run: $*"
942     status=0
943     exit
944 }
945
946 # just plain bail out
947 #
948 _fail()
949 {
950     echo "$*" | tee -a $seqres.full
951     echo "(see $seqres.full for details)"
952     status=1
953     exit 1
954 }
955
956 # tests whether $FSTYP is one of the supported filesystems for a test
957 #
958 _supported_fs()
959 {
960     for f
961     do
962         if [ "$f" = "$FSTYP" -o "$f" = "generic" ]
963         then
964             return
965         fi
966     done
967
968     _notrun "not suitable for this filesystem type: $FSTYP"
969 }
970
971 # tests whether $FSTYP is one of the supported OSes for a test
972 #
973 _supported_os()
974 {
975     for h
976     do
977         if [ "$h" = "$HOSTOS" ]
978         then
979             return
980         fi
981     done
982
983     _notrun "not suitable for this OS: $HOSTOS"
984 }
985
986 # this test needs a scratch partition - check we're ok & unmount it
987 #
988 _require_scratch()
989 {
990     case "$FSTYP" in
991         nfs*)
992                  _notrun "requires a scratch device"
993                  ;;
994         tmpfs)
995                 if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
996                 then
997                     _notrun "this test requires a valid \$SCRATCH_MNT and unique $SCRATCH_DEV"
998                 fi
999                 ;;
1000         *)
1001                  if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
1002                  then
1003                      _notrun "this test requires a valid \$SCRATCH_DEV"
1004                  fi
1005                  if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
1006                  then
1007                      _notrun "this test requires a valid \$SCRATCH_DEV"
1008                  fi
1009                 if [ ! -d "$SCRATCH_MNT" ]
1010                 then
1011                      _notrun "this test requires a valid \$SCRATCH_MNT"
1012                 fi
1013                  ;;
1014     esac
1015
1016     # mounted?
1017     if _mount | grep -q $SCRATCH_DEV
1018     then
1019         # if it's mounted, make sure its on $SCRATCH_MNT
1020         if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
1021         then
1022             echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
1023             exit 1
1024         fi
1025         # and then unmount it
1026         if ! $UMOUNT_PROG $SCRATCH_DEV
1027         then
1028             echo "failed to unmount $SCRATCH_DEV"
1029             exit 1
1030         fi
1031     fi
1032 }
1033
1034 # this test needs a logdev
1035 #
1036 _require_logdev()
1037 {
1038     [ -z "$SCRATCH_LOGDEV" -o ! -b "$SCRATCH_LOGDEV" ] && \
1039         _notrun "This test requires a valid \$SCRATCH_LOGDEV"
1040     [ "$USE_EXTERNAL" != yes ] && \
1041         _notrun "This test requires USE_EXTERNAL to be enabled"
1042
1043     # ensure its not mounted
1044     $UMOUNT_PROG $SCRATCH_LOGDEV 2>/dev/null
1045 }
1046
1047 # this test requires loopback device support
1048 #
1049 _require_loop()
1050 {
1051     if [ "$HOSTOS" != "Linux" ]
1052     then
1053         _notrun "This test requires linux for loopback device support"
1054     fi
1055
1056     modprobe loop >/dev/null 2>&1
1057     if grep loop /proc/devices >/dev/null 2>&1
1058     then
1059         :
1060     else
1061         _notrun "This test requires loopback device support"
1062     fi
1063 }
1064
1065 # this test requires ext2 filesystem support
1066 #
1067 _require_ext2()
1068 {
1069     if [ "$HOSTOS" != "Linux" ]
1070     then
1071         _notrun "This test requires linux for ext2 filesystem support"
1072     fi
1073
1074     modprobe ext2 >/dev/null 2>&1
1075     if grep ext2 /proc/filesystems >/dev/null 2>&1
1076     then
1077         :
1078     else
1079         _notrun "This test requires ext2 filesystem support"
1080     fi
1081 }
1082
1083 # this test requires that (large) loopback device files are not in use
1084 #
1085 _require_no_large_scratch_dev()
1086 {
1087     [ "$LARGE_SCRATCH_DEV" = yes ] && \
1088         _notrun "Large filesystem testing in progress, skipped this test"
1089 }
1090
1091 # this test requires that a realtime subvolume is in use, and
1092 # that the kernel supports realtime as well.
1093 #
1094 _require_realtime()
1095 {
1096     [ "$USE_EXTERNAL" = yes ] || \
1097         _notrun "External volumes not in use, skipped this test"
1098     [ "$SCRATCH_RTDEV" = "" ] && \
1099         _notrun "Realtime device required, skipped this test"
1100 }
1101
1102 # this test requires that a specified command (executable) exists
1103 # $1 - command, $2 - name for error message
1104 #
1105 _require_command()
1106 {
1107     [ -n "$1" ] && _cmd="$1" || _cmd="$2"
1108     [ -n "$1" -a -x "$1" ] || _notrun "$_cmd utility required, skipped this test"
1109 }
1110
1111 # this test requires the device mapper flakey target
1112 #
1113 _require_dm_flakey()
1114 {
1115     _require_command $DMSETUP_PROG
1116
1117     modprobe dm-flakey >/dev/null 2>&1
1118     $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
1119     if [ $? -eq 0 ]
1120     then
1121         :
1122     else
1123         _notrun "This test requires dm flakey support"
1124     fi
1125 }
1126
1127 # this test requires the projid32bit feature to be available in
1128 # mkfs.xfs
1129 #
1130 _require_projid32bit()
1131 {
1132         _scratch_mkfs_xfs -f -i projid32bit=0 2>&1 >/dev/null \
1133            || _notrun "mkfs.xfs doesn't have projid32bit feature"
1134 }
1135
1136 # this test requires the crc feature to be available in mkfs.xfs
1137 #
1138 _require_xfs_mkfs_crc()
1139 {
1140         _scratch_mkfs_xfs -f -m crc=1 >/dev/null 2>&1 \
1141            || _notrun "mkfs.xfs doesn't have crc feature"
1142 }
1143
1144 # this test requires the xfs kernel support crc feature
1145 #
1146 _require_xfs_crc()
1147 {
1148         _scratch_mount >/dev/null 2>&1 \
1149            || _notrun "Kernel doesn't support crc feature"
1150         umount $SCRATCH_MNT
1151 }
1152
1153 # this test requires that external log/realtime devices are not in use
1154 #
1155 _require_nonexternal()
1156 {
1157     [ "$USE_EXTERNAL" = yes ] && \
1158         _notrun "External device testing in progress, skipped this test"
1159 }
1160
1161 # this test requires that a (specified) aio-dio executable exists
1162 # $1 - command (optional)
1163 #
1164 _require_aiodio()
1165 {
1166     if [ -z "$1" ]
1167     then
1168         AIO_TEST=src/aio-dio-regress/aiodio_sparse2
1169         [ -x $AIO_TEST ] || _notrun "aio-dio utilities required"
1170     else
1171         AIO_TEST=src/aio-dio-regress/$1
1172         [ -x $AIO_TEST ] || _notrun "$AIO_TEST not built"
1173     fi
1174 }
1175
1176 # run an aio-dio program
1177 # $1 - command
1178 _run_aiodio()
1179 {
1180     if [ -z "$1" ]
1181     then
1182         echo "usage: _run_aiodio command_name" 2>&1
1183         status=1; exit 1
1184     fi
1185
1186     _require_aiodio $1
1187
1188     local testtemp=$TEST_DIR/aio-testfile
1189     rm -f $testtemp
1190     $AIO_TEST $testtemp 2>&1
1191     status=$?
1192     rm -f $testtemp
1193
1194     return $status
1195 }
1196
1197 # indicate whether YP/NIS is active or not
1198 #
1199 _yp_active()
1200 {
1201         local dn
1202         dn=$(domainname 2>/dev/null)
1203         test -n "${dn}" -a "${dn}" != "(none)"
1204         echo $?
1205 }
1206
1207 # cat the password file
1208 #
1209 _cat_passwd()
1210 {
1211         [ $(_yp_active) -eq 0 ] && ypcat passwd
1212         cat /etc/passwd
1213 }
1214
1215 # cat the group file
1216 #
1217 _cat_group()
1218 {
1219         [ $(_yp_active) -eq 0 ] && ypcat group
1220         cat /etc/group
1221 }
1222
1223 # check for the fsgqa user on the machine
1224 #
1225 _require_user()
1226 {
1227     qa_user=fsgqa
1228     _cat_passwd | grep -q $qa_user
1229     [ "$?" == "0" ] || _notrun "$qa_user user not defined."
1230     echo /bin/true | su $qa_user
1231     [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
1232 }
1233
1234 # check for the fsgqa group on the machine
1235 #
1236 _require_group()
1237 {
1238     qa_group=fsgqa
1239     _cat_group | grep -q $qa_group
1240     [ "$?" == "0" ] || _notrun "$qa_group user not defined."
1241 }
1242
1243 _filter_user_do()
1244 {
1245         perl -ne "
1246 s,.*Permission\sdenied.*,Permission denied,;
1247 s,.*no\saccess\sto\stty.*,,;
1248 s,.*no\sjob\scontrol\sin\sthis\sshell.*,,;
1249 s,^\s*$,,;
1250         print;"
1251 }
1252
1253 _user_do()
1254 {
1255     if [ "$HOSTOS" == "IRIX" ]
1256         then
1257         echo $1 | /bin/bash "su $qa_user 2>&1" | _filter_user_do
1258     else
1259         echo $1 | su $qa_user 2>&1 | _filter_user_do
1260     fi
1261 }
1262
1263 # check that xfs_io, kernel, and filesystem all support zero
1264 _require_xfs_io_zero()
1265 {
1266         testio=`$XFS_IO_PROG -c "zero help" 2>&1`
1267         echo $testio | grep -q 'command "zero" not found' && \
1268                 _notrun "zero command not supported"
1269 }
1270
1271 # check that xfs_io, glibc, kernel, and filesystem all (!) support
1272 # fallocate
1273 #
1274 _require_xfs_io_falloc()
1275 {
1276         testfile=$TEST_DIR/$$.falloc
1277         testio=`$XFS_IO_PROG -F -f -c "falloc 0 1m" $testfile 2>&1`
1278         rm -f $testfile 2>&1 > /dev/null
1279         echo $testio | grep -q "not found" && \
1280                 _notrun "xfs_io fallocate support is missing"
1281         echo $testio | grep -q "Operation not supported" && \
1282                 _notrun "xfs_io fallocate command failed (old kernel/wrong fs?)"
1283 }
1284
1285 # check that xfs_io, kernel and filesystem all support fallocate with hole
1286 # punching
1287 _require_xfs_io_falloc_punch()
1288 {
1289         testfile=$TEST_DIR/$$.falloc
1290         testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
1291                 -c "fpunch 4k 8k" $testfile 2>&1`
1292         rm -f $testfile 2>&1 > /dev/null
1293         echo $testio | grep -q "not found" && \
1294                 _notrun "xfs_io fallocate punch support is missing"
1295         echo $testio | grep -q "Operation not supported" && \
1296                 _notrun "xfs_io fallocate punch command failed (no fs support?)"
1297 }
1298
1299 # check that xfs_io, kernel and filesystem support fiemap
1300 _require_xfs_io_fiemap()
1301 {
1302         testfile=$TEST_DIR/$$.fiemap
1303         testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
1304                 -c "fiemap -v" $testfile 2>&1`
1305         rm -f $testfile 2>&1 > /dev/null
1306         echo $testio | grep -q "not found" && \
1307                 _notrun "xfs_io fiemap support is missing"
1308         echo $testio | grep -q "Operation not supported" && \
1309                 _notrun "xfs_io fiemap command failed (no fs support?)"
1310 }
1311
1312 # Check that a fs has enough free space (in 1024b blocks)
1313 #
1314 _require_fs_space()
1315 {
1316         MNT=$1
1317         BLOCKS=$2       # in units of 1024
1318         let GB=$BLOCKS/1024/1024
1319
1320         FREE_BLOCKS=`df -klP $MNT | grep -v Filesystem | awk '{print $4}'`
1321         [ $FREE_BLOCKS -lt $BLOCKS ] && \
1322                 _notrun "This test requires at least ${GB}GB free on $MNT to run"
1323 }
1324
1325 #
1326 # Check if the filesystem supports sparse files.
1327 #
1328 # Unfortunately there is no better way to do this than a manual black list.
1329 #
1330 _require_sparse_files()
1331 {
1332     case $FSTYP in
1333     hfsplus)
1334         _notrun "Sparse files not supported by this filesystem type: $FSTYP"
1335         ;;
1336     *)
1337         ;;
1338     esac
1339 }
1340
1341 _require_debugfs()
1342 {
1343     #boot_params always present in debugfs
1344     [ -d "$DEBUGFS_MNT/boot_params" ] || _notrun "Debugfs not mounted"
1345 }
1346
1347 _require_fail_make_request()
1348 {
1349     [ -f "$DEBUGFS_MNT/fail_make_request/probability" ] \
1350         || _notrun "$DEBUGFS_MNT/fail_make_request \
1351  not found. Seems that CONFIG_FAIL_MAKE_REQUEST kernel config option not enabled"
1352 }
1353
1354 #
1355 # Check if the file system supports seek_data/hole
1356 #
1357 _require_seek_data_hole()
1358 {
1359     testfile=$TEST_DIR/$$.seek
1360     testseek=`$here/src/seek_sanity_test -t $testfile 2>&1`
1361     rm -f $testfile &>/dev/null
1362     echo $testseek | grep -q "Kernel does not support" && \
1363         _notrun "File system does not support llseek(2) SEEK_DATA/HOLE"
1364 }
1365
1366 # check that a FS on a device is mounted
1367 # if so, return mount point
1368 #
1369 _is_mounted()
1370 {
1371     if [ $# -ne 1 ]
1372     then
1373         echo "Usage: _is_mounted device" 1>&2
1374         exit 1
1375     fi
1376
1377     device=$1
1378
1379     if _mount | grep "$device " | $AWK_PROG -v pattern="type $FSTYP" '
1380         pattern        { print $3 ; exit 0 }
1381         END            { exit 1 }
1382     '
1383     then
1384         echo "_is_mounted: $device is not a mounted $FSTYP FS"
1385         exit 1
1386     fi
1387 }
1388
1389 # remount a FS to a new mode (ro or rw)
1390 #
1391 _remount()
1392 {
1393     if [ $# -ne 2 ]
1394     then
1395         echo "Usage: _remount device ro/rw" 1>&2
1396         exit 1
1397     fi
1398     device=$1
1399     mode=$2
1400
1401     if ! mount -o remount,$mode $device
1402     then
1403         echo "_remount: failed to remount filesystem on $device as $mode"
1404         exit 1
1405     fi
1406 }
1407
1408 # Run the appropriate repair/check on a filesystem
1409 #
1410 # if the filesystem is mounted, it's either remounted ro before being
1411 # checked or it's unmounted and then remounted
1412 #
1413
1414 # If set, we remount ro instead of unmounting for fsck
1415 USE_REMOUNT=0
1416
1417 _umount_or_remount_ro()
1418 {
1419     if [ $# -ne 1 ]
1420     then
1421         echo "Usage: _umount_or_remount_ro <device>" 1>&2
1422         exit 1
1423     fi
1424
1425     device=$1
1426     mountpoint=`_is_mounted $device`
1427
1428     if [ $USE_REMOUNT -eq 0 ]; then
1429         $UMOUNT_PROG $device
1430     else
1431         _remount $device ro
1432     fi
1433     echo "$mountpoint"
1434 }
1435
1436 _mount_or_remount_rw()
1437 {
1438     if [ $# -ne 3 ]
1439     then
1440         echo "Usage: _mount_or_remount_rw <opts> <device> <mountpoint>" 1>&2
1441         exit 1
1442     fi
1443     mount_opts=$1
1444     device=$2
1445     mountpoint=$3
1446
1447     if [ $USE_REMOUNT -eq 0 ]
1448     then
1449         if ! _mount -t $FSTYP $mount_opts $device $mountpoint
1450         then
1451             echo "!!! failed to remount $device on $mountpoint"
1452             return 0 # ok=0
1453         fi
1454     else
1455         _remount $device rw
1456     fi
1457
1458     return 1 # ok=1
1459 }
1460
1461 # Check a generic filesystem in no-op mode; this assumes that the
1462 # underlying fsck program accepts "-n" for a no-op (check-only) run,
1463 # and that it will still return an errno for corruption in this mode.
1464 #
1465 # Filesystems which don't support this will need to define their
1466 # own check routine.
1467 #
1468 _check_generic_filesystem()
1469 {
1470     device=$1
1471
1472     # If type is set, we're mounted
1473     type=`_fs_type $device`
1474     ok=1
1475
1476     if [ "$type" = "$FSTYP" ]
1477     then
1478         # mounted ...
1479         mountpoint=`_umount_or_remount_ro $device`
1480     fi
1481
1482     fsck -t $FSTYP $FSCK_OPTIONS $device >$tmp.fsck 2>&1
1483     if [ $? -ne 0 ]
1484     then
1485         echo "_check_generic_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1486
1487         echo "_check_generic filesystem: filesystem on $device is inconsistent" >>$seqres.full
1488         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1489         cat $tmp.fsck                           >>$seqres.full
1490         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1491
1492         ok=0
1493     fi
1494     rm -f $tmp.fsck
1495
1496     if [ $ok -eq 0 ]
1497     then
1498         echo "*** mount output ***"             >>$seqres.full
1499         _mount                                  >>$seqres.full
1500         echo "*** end mount output"             >>$seqres.full
1501     elif [ "$type" = "$FSTYP" ]
1502     then
1503         # was mounted ...
1504         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1505         ok=$?
1506     fi
1507
1508     if [ $ok -eq 0 ]; then
1509         status=1
1510         exit 1
1511     fi
1512
1513     return 0
1514 }
1515
1516 # run xfs_check and friends on a FS.
1517
1518 _check_xfs_filesystem()
1519 {
1520     if [ $# -ne 3 ]
1521     then
1522         echo "Usage: _check_xfs_filesystem device <logdev>|none <rtdev>|none" 1>&2
1523         exit 1
1524     fi
1525
1526     extra_mount_options=""
1527     device=$1
1528     if [ "$2" != "none" ]; then
1529         extra_log_options="-l$2"
1530         extra_mount_options="-ologdev=$2"
1531     fi
1532
1533     if [ "$3" != "none" ]; then
1534         extra_rt_options="-r$3"
1535         extra_mount_options=$extra_mount_options" -ortdev=$3"
1536     fi
1537     extra_mount_options=$extra_mount_options" $MOUNT_OPTIONS"
1538
1539     [ "$FSTYP" != xfs ] && return 0
1540
1541     type=`_fs_type $device`
1542     ok=1
1543
1544     if [ "$type" = "xfs" ]
1545     then
1546         # mounted ...
1547         mountpoint=`_umount_or_remount_ro $device`
1548     fi
1549
1550     $XFS_LOGPRINT_PROG -t $extra_log_options $device 2>&1 \
1551                 | tee $tmp.logprint | grep -q "<CLEAN>"
1552     if [ $? -ne 0 -a "$HOSTOS" = "Linux" ]
1553     then
1554         echo "_check_xfs_filesystem: filesystem on $device has dirty log (see $seqres.full)"
1555
1556         echo "_check_xfs_filesystem: filesystem on $device has dirty log"   >>$seqres.full
1557         echo "*** xfs_logprint -t output ***"   >>$seqres.full
1558         cat $tmp.logprint                       >>$seqres.full
1559         echo "*** end xfs_logprint output"      >>$seqres.full
1560
1561         ok=0
1562     fi
1563
1564     # xfs_check runs out of memory on large files, so even providing the test
1565     # option (-t) to avoid indexing the free space trees doesn't make it pass on
1566     # large filesystems. Avoid it.
1567     if [ "$LARGE_SCRATCH_DEV" != yes ]; then
1568             _xfs_check $extra_log_options $device 2>&1 |\
1569                  _fix_malloc >$tmp.fs_check
1570     fi
1571     if [ -s $tmp.fs_check ]
1572     then
1573         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (c) (see $seqres.full)"
1574
1575         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1576         echo "*** xfs_check output ***"         >>$seqres.full
1577         cat $tmp.fs_check                       >>$seqres.full
1578         echo "*** end xfs_check output"         >>$seqres.full
1579
1580         ok=0
1581     fi
1582
1583     $XFS_REPAIR_PROG -n $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
1584     if [ $? -ne 0 ]
1585     then
1586         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (r) (see $seqres.full)"
1587
1588         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1589         echo "*** xfs_repair -n output ***"     >>$seqres.full
1590         cat $tmp.repair | _fix_malloc           >>$seqres.full
1591         echo "*** end xfs_repair output"        >>$seqres.full
1592
1593         ok=0
1594     fi
1595     rm -f $tmp.fs_check $tmp.logprint $tmp.repair
1596
1597     if [ $ok -eq 0 ]
1598     then
1599         echo "*** mount output ***"             >>$seqres.full
1600         _mount                                  >>$seqres.full
1601         echo "*** end mount output"             >>$seqres.full
1602     elif [ "$type" = "xfs" ]
1603     then
1604         _mount_or_remount_rw "$extra_mount_options" $device $mountpoint
1605     fi
1606
1607     if [ $ok -eq 0 ]; then
1608         status=1
1609         exit 1
1610     fi
1611
1612     return 0
1613 }
1614
1615 # Filter the knowen errors the UDF Verifier reports.
1616 _udf_test_known_error_filter()
1617 {
1618         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."
1619
1620 }
1621
1622 _check_udf_filesystem()
1623 {
1624     [ "$DISABLE_UDF_TEST" == "1" ] && return
1625
1626     if [ $# -ne 1 -a $# -ne 2 ]
1627     then
1628         echo "Usage: _check_udf_filesystem device [last_block]" 1>&2
1629         exit 1
1630     fi
1631
1632     if [ ! -x $here/src/udf_test ]
1633     then
1634         echo "udf_test not installed, please download and build the Philips"
1635         echo "UDF Verification Software from http://www.extra.research.philips.com/udf/."
1636         echo "Then copy the udf_test binary to $here/src/."
1637         echo "If you do not wish to run udf_test then set environment variable DISABLE_UDF_TEST"
1638         echo "to 1."
1639         return
1640     fi
1641
1642     device=$1
1643     if [ $# -eq 2 ];
1644     then
1645         LAST_BLOCK=`expr \( $2 - 1 \)`
1646         OPT_ARG="-lastvalidblock $LAST_BLOCK"
1647     fi
1648
1649     rm -f $seqres.checkfs
1650     sleep 1 # Due to a problem with time stamps in udf_test
1651     $here/src/udf_test $OPT_ARG $device | tee $seqres.checkfs | egrep "Error|Warning" | \
1652         _udf_test_known_error_filter | \
1653         egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" && \
1654         echo "Warning UDF Verifier reported errors see $seqres.checkfs."
1655 }
1656
1657 _check_xfs_test_fs()
1658 {
1659     TEST_LOG="none"
1660     TEST_RT="none"
1661     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
1662         TEST_LOG="$TEST_LOGDEV"
1663
1664     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
1665         TEST_RT="$TEST_RTDEV"
1666
1667     _check_xfs_filesystem $TEST_DEV $TEST_LOG $TEST_RT
1668
1669     # check for ipath consistency
1670     if $XFS_GROWFS_PROG -n $TEST_DIR | grep -q 'inode-paths=1'; then
1671         # errors go to stderr
1672         xfs_check_ipaths $TEST_DIR >/dev/null
1673         xfs_repair_ipaths -n $TEST_DIR >/dev/null
1674     fi
1675 }
1676
1677 _check_btrfs_filesystem()
1678 {
1679     device=$1
1680
1681     # If type is set, we're mounted
1682     type=`_fs_type $device`
1683     ok=1
1684
1685     if [ "$type" = "$FSTYP" ]
1686     then
1687         # mounted ...
1688         mountpoint=`_umount_or_remount_ro $device`
1689     fi
1690
1691     btrfsck $device >$tmp.fsck 2>&1
1692     if [ $? -ne 0 ]
1693     then
1694         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1695
1696         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1697         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1698         cat $tmp.fsck                           >>$seqres.full
1699         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1700
1701         ok=0
1702     fi
1703     rm -f $tmp.fsck
1704
1705     if [ $ok -eq 0 ]
1706     then
1707         echo "*** mount output ***"             >>$seqres.full
1708         _mount                                  >>$seqres.full
1709         echo "*** end mount output"             >>$seqres.full
1710     elif [ "$type" = "$FSTYP" ]
1711     then
1712         # was mounted ...
1713         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1714         ok=$?
1715     fi
1716
1717     if [ $ok -eq 0 ]; then
1718         status=1
1719         exit 1
1720     fi
1721
1722     return 0
1723 }
1724
1725 _check_test_fs()
1726 {
1727     case $FSTYP in
1728     xfs)
1729         _check_xfs_test_fs
1730         ;;
1731     nfs)
1732         # no way to check consistency for nfs
1733         ;;
1734     udf)
1735         # do nothing for now
1736         ;;
1737     btrfs)
1738         _check_btrfs_filesystem $TEST_DEV
1739         ;;
1740     tmpfs)
1741         # no way to check consistency for tmpfs
1742         ;;
1743     *)
1744         _check_generic_filesystem $TEST_DEV
1745         ;;
1746     esac
1747 }
1748
1749 _check_scratch_fs()
1750 {
1751     device=$SCRATCH_DEV
1752     [ $# -eq 1 ] && device=$1
1753
1754     case $FSTYP in
1755     xfs)
1756         SCRATCH_LOG="none"
1757         SCRATCH_RT="none"
1758         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
1759             SCRATCH_LOG="$SCRATCH_LOGDEV"
1760
1761         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
1762             SCRATCH_RT="$SCRATCH_RTDEV"
1763
1764         _check_xfs_filesystem $device $SCRATCH_LOG $SCRATCH_RT
1765         ;;
1766     udf)
1767         _check_udf_filesystem $device $udf_fsize
1768         ;;
1769     nfs*)
1770         # Don't know how to check an NFS filesystem, yet.
1771         ;;
1772     btrfs)
1773         _check_btrfs_filesystem $device
1774         ;;
1775     tmpfs)
1776         # no way to check consistency for tmpfs
1777         ;;
1778     *)
1779         _check_generic_filesystem $device
1780         ;;
1781     esac
1782 }
1783
1784 _full_fstyp_details()
1785 {
1786      [ -z "$FSTYP" ] && FSTYP=xfs
1787      if [ $FSTYP = xfs ]; then
1788         if [ -d /proc/fs/xfs ]; then
1789             if grep -q 'debug 0' /proc/fs/xfs/stat; then
1790                 FSTYP="$FSTYP (non-debug)"
1791             elif grep -q 'debug 1' /proc/fs/xfs/stat; then
1792                 FSTYP="$FSTYP (debug)"
1793             fi
1794         else
1795             if uname -a | grep -qi 'debug'; then
1796                 FSTYP="$FSTYP (debug)"
1797             else
1798                 FSTYP="$FSTYP (non-debug)"
1799             fi
1800         fi
1801      fi
1802      echo $FSTYP
1803 }
1804
1805 _full_platform_details()
1806 {
1807      os=`uname -s`
1808      host=`hostname -s`
1809      kernel=`uname -r`
1810      platform=`uname -m`
1811      echo "$os/$platform $host $kernel"
1812 }
1813
1814 _link_out_file()
1815 {
1816         if [ -z "$1" -o -z "$2" ]; then
1817                 echo Error must pass src and dst.
1818                 exit
1819         fi
1820         rm -f $2
1821         if [ "`uname`" == "IRIX64" ] || [ "`uname`" == "IRIX" ]; then
1822                 ln -s $1.irix $2
1823         elif [ "`uname`" == "Linux" ]; then
1824                 ln -s $1.linux $2
1825         else
1826                 echo Error test $seq does not run on the operating system: `uname`
1827                 exit
1828         fi
1829 }
1830
1831 _die()
1832 {
1833         echo $@
1834         exit 1
1835 }
1836
1837 #takes files, randomdata
1838 _nfiles()
1839 {
1840         f=0
1841         while [ $f -lt $1 ]
1842         do
1843                 file=f$f
1844                 echo > $file
1845                 if [ $size -gt 0 ]; then
1846                     if [ "$2" == "false" ]; then
1847                         dd if=/dev/zero of=$file bs=1024 count=$size 2>&1 | _filter_dd
1848                     else
1849                         dd if=/dev/urandom of=$file bs=1024 count=$size 2>&1 | _filter_dd
1850                     fi
1851                 fi
1852                 let f=$f+1
1853         done
1854 }
1855
1856 # takes dirname, depth, randomdata
1857 _descend()
1858 {
1859         dirname=$1; depth=$2; randomdata=$3
1860         mkdir $dirname  || die "mkdir $dirname failed"
1861         cd $dirname
1862
1863         _nfiles $files $randomdata          # files for this dir and data type
1864
1865         [ $depth -eq 0 ] && return
1866         let deep=$depth-1 # go 1 down
1867
1868         [ $verbose = true ] && echo "descending, depth from leaves = $deep"
1869
1870         d=0
1871         while [ $d -lt $dirs ]
1872         do
1873                 _descend d$d $deep &
1874                 let d=$d+1
1875                 wait
1876         done
1877 }
1878
1879 # Populate a filesystem with inodes for performance experiments
1880 #
1881 # usage: populate [-v] [-n ndirs] [-f nfiles] [-d depth] [-r root] [-s size] [-x]
1882 #
1883 _populate_fs()
1884 {
1885     here=`pwd`
1886     dirs=5          # ndirs in each subdir till leaves
1887     size=0          # sizeof files in K
1888     files=100       # num files in _each_ subdir
1889     depth=2         # depth of tree from root to leaves
1890     verbose=false
1891     root=root       # path of initial root of directory tree
1892     randomdata=false # -x data type urandom or zero
1893
1894     OPTIND=1
1895     while getopts "d:f:n:r:s:v:x" c
1896     do
1897         case $c in
1898         d)      depth=$OPTARG;;
1899         n)      dirs=$OPTARG;;
1900         f)      files=$OPTARG;;
1901         s)      size=$OPTARG;;
1902         v)      verbose=true;;
1903         r)      root=$OPTARG;;
1904         x)      randomdata=true;;
1905         esac
1906     done
1907
1908     _descend $root $depth $randomdata
1909     wait
1910
1911     cd $here
1912
1913     [ $verbose = true ] && echo done
1914 }
1915
1916 # query whether the given file has the given inode flag set
1917 #
1918 _test_inode_flag()
1919 {
1920     flag=$1
1921     file=$2
1922
1923     if which $XFS_IO_PROG >/dev/null; then
1924         if $XFS_IO_PROG -r -c 'lsattr -v' "$file" | grep -q "$flag" ; then
1925             return 0
1926         fi
1927     fi
1928     return 1
1929 }
1930
1931 # query the given files extsize allocator hint in bytes (if any)
1932 #
1933 _test_inode_extsz()
1934 {
1935     file=$1
1936     blocks=""
1937
1938     if which $XFS_IO_PROG >/dev/null; then
1939         blocks=`$XFS_IO_PROG -r -c 'stat' "$file" | \
1940                 awk '/^xattr.extsize =/ { print $3 }'`
1941     fi
1942     [ -z "$blocks" ] && blocks="0"
1943     echo $blocks
1944 }
1945
1946 # scratch_dev_pool should contain the disks pool for the btrfs raid
1947 _require_scratch_dev_pool()
1948 {
1949         local i
1950         local ndevs
1951
1952         if [ -z "$SCRATCH_DEV_POOL" ]; then
1953                 _notrun "this test requires a valid \$SCRATCH_DEV_POOL"
1954         fi
1955
1956         if [ -z "$1" ]; then
1957                 ndevs=2
1958         else
1959                 ndevs=$1
1960         fi
1961
1962         # btrfs test case needs ndevs or more scratch_dev_pool; other FS not sure
1963         # so fail it
1964         case $FSTYP in
1965         btrfs)
1966                 if [ "`echo $SCRATCH_DEV_POOL|wc -w`" -lt $ndevs ]; then
1967                         _notrun "btrfs and this test needs $ndevs or more disks in SCRATCH_DEV_POOL"
1968                 fi
1969         ;;
1970         *)
1971                 _notrun "dev_pool is not supported by fstype \"$FSTYP\""
1972         ;;
1973         esac
1974
1975         for i in $SCRATCH_DEV_POOL; do
1976                 if [ "`_is_block_dev $i`" = "" ]; then
1977                         _notrun "this test requires valid block disk $i"
1978                 fi
1979                 if [ "`_is_block_dev $i`" = "`_is_block_dev $TEST_DEV`" ]; then
1980                         _notrun "$i is part of TEST_DEV, this test requires unique disks"
1981                 fi
1982                 if _mount | grep -q $i; then
1983                         if ! $UMOUNT_PROG $i; then
1984                             echo "failed to unmount $i - aborting"
1985                             exit 1
1986                         fi
1987                 fi
1988                 # to help better debug when something fails, we remove
1989                 # traces of previous btrfs FS on the dev.
1990                 dd if=/dev/zero of=$i bs=4096 count=100 > /dev/null 2>&1
1991         done
1992 }
1993
1994 # We will check if the device is deletable
1995 _require_deletable_scratch_dev_pool()
1996 {
1997         local i
1998         local x
1999         for i in $SCRATCH_DEV_POOL; do
2000                 x=`echo $i | cut -d"/" -f 3`
2001                 if [ ! -f /sys/class/block/${x}/device/delete ]; then
2002                         _notrun "$i is a device which is not deletable"
2003                 fi
2004         done
2005 }
2006
2007 # We check for btrfs and (optionally) features of the btrfs command
2008 _require_btrfs()
2009 {
2010         cmd=$1
2011         _require_command $BTRFS_UTIL_PROG btrfs
2012         if [ -z "$1" ]; then
2013                 return 1;
2014         fi
2015         $BTRFS_UTIL_PROG $cmd --help >/dev/null 2>&1
2016         [ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd)"
2017 }
2018
2019 # Check that fio is present, and it is able to execute given jobfile
2020 _require_fio()
2021 {
2022         job=$1
2023
2024         _require_command $FIO_PROG
2025         if [ -z "$1" ]; then
2026                 return 1;
2027         fi
2028
2029         $FIO_PROG --warnings-fatal --showcmd $job >> $seqres.full 2>&1
2030         [ $? -eq 0 ] || _notrun "$FIO_PROG too old, see $seqres.full"
2031 }
2032
2033 # Does freeze work on this fs?
2034 _require_freeze()
2035 {
2036         xfs_freeze -f "$TEST_DIR" >/dev/null 2>&1
2037         result=$? 
2038         xfs_freeze -u "$TEST_DIR" >/dev/null 2>&1
2039         [ $result -eq 0 ] || _notrun "$FSTYP does not support freezing"
2040 }
2041
2042 # arg 1 is dev to remove and is output of the below eg.
2043 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2044 _devmgt_remove()
2045 {
2046         local lun=$1
2047         local disk=$2
2048
2049         echo 1 > /sys/class/scsi_device/${lun}/device/delete || _fail "Remove disk failed"
2050
2051         stat $disk > /dev/null 2>&1
2052         while [ $? -eq 0 ]; do
2053                 sleep 1
2054                 stat $disk > /dev/null 2>&1
2055         done
2056 }
2057
2058 # arg 1 is dev to add and is output of the below eg.
2059 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2060 _devmgt_add()
2061 {
2062         local h
2063         local tdl
2064         # arg 1 will be in h:t:d:l format now in the h and "t d l" format
2065         h=`echo ${1} | cut -d":" -f 1`
2066         tdl=`echo ${1} | cut -d":" -f 2-|sed 's/:/ /g'`
2067
2068         echo ${tdl} >  /sys/class/scsi_host/host${h}/scan || _fail "Add disk failed"
2069 }
2070
2071 _require_fstrim()
2072 {
2073         if [ -z "$FSTRIM_PROG" ]; then
2074                 _notrun "This test requires fstrim utility."
2075         fi
2076 }
2077
2078 _test_batched_discard()
2079 {
2080         if [ $# -ne 1 ]; then
2081                 echo "Usage: _test_batched_discard mnt_point" 1>&2
2082                 exit 1
2083         fi
2084         _require_fstrim
2085         $FSTRIM_PROG ${1} &>/dev/null
2086 }
2087
2088 _require_dumpe2fs()
2089 {
2090         if [ -z "$DUMPE2FS_PROG" ]; then
2091                 _notrun "This test requires dumpe2fs utility."
2092         fi
2093 }
2094
2095 _require_ugid_map()
2096 {
2097         if [ ! -e /proc/self/uid_map ]; then
2098                 _notrun "This test requires procfs uid_map support."
2099         fi
2100         if [ ! -e /proc/self/gid_map ]; then
2101                 _notrun "This test requires procfs gid_map support."
2102         fi
2103 }
2104
2105 _create_loop_device()
2106 {
2107         file=$1
2108         dev=`losetup -f --show $file` || _fail "Cannot assign $file to a loop device"
2109         echo $dev
2110 }
2111
2112 _destroy_loop_device()
2113 {
2114         dev=$1
2115         losetup -d $dev || _fail "Cannot destroy loop device $dev"
2116 }
2117
2118 _scale_fsstress_args()
2119 {
2120     args=""
2121     while [ $# -gt 0 ]; do
2122         case "$1" in
2123             -n) args="$args $1 $(($2 * $TIME_FACTOR))"; shift ;;
2124             -p) args="$args $1 $(($2 * $LOAD_FACTOR))"; shift ;;
2125             *) args="$args $1" ;;
2126         esac
2127         shift
2128     done
2129     echo $args
2130 }
2131
2132 #
2133 # Return the logical block size if running on a block device,
2134 # else substitute the page size.
2135 #
2136 _min_dio_alignment()
2137 {
2138     dev=$1
2139
2140     if [ -b "$dev" ]; then
2141         blockdev --getss $dev
2142     else
2143         $here/src/feature -s
2144     fi
2145 }
2146
2147 run_check()
2148 {
2149         echo "# $@" >> $seqres.full 2>&1
2150         "$@" >> $seqres.full 2>&1 || _fail "failed: '$@'"
2151 }
2152
2153 init_rc()
2154 {
2155         if [ "$iam" == new ]
2156         then
2157                 return
2158         fi
2159         # make some further configuration checks here
2160         if [ "$TEST_DEV" = ""  ]
2161         then
2162                 echo "common/rc: Error: \$TEST_DEV is not set"
2163                 exit 1
2164         fi
2165
2166         # if $TEST_DEV is not mounted, mount it now as XFS
2167         if [ -z "`_fs_type $TEST_DEV`" ]
2168         then
2169                 # $TEST_DEV is not mounted
2170                 if ! _test_mount
2171                 then
2172                         echo "common/rc: retrying test device mount with external set"
2173                         [ "$USE_EXTERNAL" != "yes" ] && export USE_EXTERNAL=yes
2174                         if ! _test_mount
2175                         then
2176                                 echo "common/rc: could not mount $TEST_DEV on $TEST_DIR"
2177                                 exit 1
2178                         fi
2179                 fi
2180         fi
2181
2182         if [ "`_fs_type $TEST_DEV`" != "$FSTYP" ]
2183         then
2184                 echo "common/rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED $FSTYP filesystem"
2185                 $DF_PROG $TEST_DEV
2186                 exit 1
2187         fi
2188         # Figure out if we need to add -F ("foreign", deprecated) option to xfs_io
2189         xfs_io -c stat $TEST_DIR 2>&1 | grep -q "is not on an XFS filesystem" && \
2190         export XFS_IO_PROG="$XFS_IO_PROG -F"
2191 }
2192
2193 init_rc
2194
2195 ################################################################################
2196 # make sure this script returns success
2197 /bin/true