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