common: Remove unused functions
[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 support fiemap
1292 _require_xfs_io_fiemap()
1293 {
1294         _require_xfs_io_command "fiemap"
1295 }
1296
1297 # Check that a fs has enough free space (in 1024b blocks)
1298 #
1299 _require_fs_space()
1300 {
1301         MNT=$1
1302         BLOCKS=$2       # in units of 1024
1303         let GB=$BLOCKS/1024/1024
1304
1305         FREE_BLOCKS=`df -klP $MNT | grep -v Filesystem | awk '{print $4}'`
1306         [ $FREE_BLOCKS -lt $BLOCKS ] && \
1307                 _notrun "This test requires at least ${GB}GB free on $MNT to run"
1308 }
1309
1310 #
1311 # Check if the filesystem supports sparse files.
1312 #
1313 # Unfortunately there is no better way to do this than a manual black list.
1314 #
1315 _require_sparse_files()
1316 {
1317     case $FSTYP in
1318     hfsplus)
1319         _notrun "Sparse files not supported by this filesystem type: $FSTYP"
1320         ;;
1321     *)
1322         ;;
1323     esac
1324 }
1325
1326 _require_debugfs()
1327 {
1328     #boot_params always present in debugfs
1329     [ -d "$DEBUGFS_MNT/boot_params" ] || _notrun "Debugfs not mounted"
1330 }
1331
1332 _require_fail_make_request()
1333 {
1334     [ -f "$DEBUGFS_MNT/fail_make_request/probability" ] \
1335         || _notrun "$DEBUGFS_MNT/fail_make_request \
1336  not found. Seems that CONFIG_FAIL_MAKE_REQUEST kernel config option not enabled"
1337 }
1338
1339 #
1340 # Check if the file system supports seek_data/hole
1341 #
1342 _require_seek_data_hole()
1343 {
1344     testfile=$TEST_DIR/$$.seek
1345     testseek=`$here/src/seek_sanity_test -t $testfile 2>&1`
1346     rm -f $testfile &>/dev/null
1347     echo $testseek | grep -q "Kernel does not support" && \
1348         _notrun "File system does not support llseek(2) SEEK_DATA/HOLE"
1349 }
1350
1351 # check that a FS on a device is mounted
1352 # if so, return mount point
1353 #
1354 _is_mounted()
1355 {
1356     if [ $# -ne 1 ]
1357     then
1358         echo "Usage: _is_mounted device" 1>&2
1359         exit 1
1360     fi
1361
1362     device=$1
1363
1364     if _mount | grep "$device " | $AWK_PROG -v pattern="type $FSTYP" '
1365         pattern        { print $3 ; exit 0 }
1366         END            { exit 1 }
1367     '
1368     then
1369         echo "_is_mounted: $device is not a mounted $FSTYP FS"
1370         exit 1
1371     fi
1372 }
1373
1374 # remount a FS to a new mode (ro or rw)
1375 #
1376 _remount()
1377 {
1378     if [ $# -ne 2 ]
1379     then
1380         echo "Usage: _remount device ro/rw" 1>&2
1381         exit 1
1382     fi
1383     device=$1
1384     mode=$2
1385
1386     if ! mount -o remount,$mode $device
1387     then
1388         echo "_remount: failed to remount filesystem on $device as $mode"
1389         exit 1
1390     fi
1391 }
1392
1393 # Run the appropriate repair/check on a filesystem
1394 #
1395 # if the filesystem is mounted, it's either remounted ro before being
1396 # checked or it's unmounted and then remounted
1397 #
1398
1399 # If set, we remount ro instead of unmounting for fsck
1400 USE_REMOUNT=0
1401
1402 _umount_or_remount_ro()
1403 {
1404     if [ $# -ne 1 ]
1405     then
1406         echo "Usage: _umount_or_remount_ro <device>" 1>&2
1407         exit 1
1408     fi
1409
1410     device=$1
1411     mountpoint=`_is_mounted $device`
1412
1413     if [ $USE_REMOUNT -eq 0 ]; then
1414         $UMOUNT_PROG $device
1415     else
1416         _remount $device ro
1417     fi
1418     echo "$mountpoint"
1419 }
1420
1421 _mount_or_remount_rw()
1422 {
1423     if [ $# -ne 3 ]
1424     then
1425         echo "Usage: _mount_or_remount_rw <opts> <device> <mountpoint>" 1>&2
1426         exit 1
1427     fi
1428     mount_opts=$1
1429     device=$2
1430     mountpoint=$3
1431
1432     if [ $USE_REMOUNT -eq 0 ]
1433     then
1434         if ! _mount -t $FSTYP $mount_opts $device $mountpoint
1435         then
1436             echo "!!! failed to remount $device on $mountpoint"
1437             return 0 # ok=0
1438         fi
1439     else
1440         _remount $device rw
1441     fi
1442
1443     return 1 # ok=1
1444 }
1445
1446 # Check a generic filesystem in no-op mode; this assumes that the
1447 # underlying fsck program accepts "-n" for a no-op (check-only) run,
1448 # and that it will still return an errno for corruption in this mode.
1449 #
1450 # Filesystems which don't support this will need to define their
1451 # own check routine.
1452 #
1453 _check_generic_filesystem()
1454 {
1455     device=$1
1456
1457     # If type is set, we're mounted
1458     type=`_fs_type $device`
1459     ok=1
1460
1461     if [ "$type" = "$FSTYP" ]
1462     then
1463         # mounted ...
1464         mountpoint=`_umount_or_remount_ro $device`
1465     fi
1466
1467     fsck -t $FSTYP $FSCK_OPTIONS $device >$tmp.fsck 2>&1
1468     if [ $? -ne 0 ]
1469     then
1470         echo "_check_generic_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1471
1472         echo "_check_generic filesystem: filesystem on $device is inconsistent" >>$seqres.full
1473         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1474         cat $tmp.fsck                           >>$seqres.full
1475         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1476
1477         ok=0
1478     fi
1479     rm -f $tmp.fsck
1480
1481     if [ $ok -eq 0 ]
1482     then
1483         echo "*** mount output ***"             >>$seqres.full
1484         _mount                                  >>$seqres.full
1485         echo "*** end mount output"             >>$seqres.full
1486     elif [ "$type" = "$FSTYP" ]
1487     then
1488         # was mounted ...
1489         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1490         ok=$?
1491     fi
1492
1493     if [ $ok -eq 0 ]; then
1494         status=1
1495         exit 1
1496     fi
1497
1498     return 0
1499 }
1500
1501 # run xfs_check and friends on a FS.
1502
1503 _check_xfs_filesystem()
1504 {
1505     if [ $# -ne 3 ]
1506     then
1507         echo "Usage: _check_xfs_filesystem device <logdev>|none <rtdev>|none" 1>&2
1508         exit 1
1509     fi
1510
1511     extra_mount_options=""
1512     device=$1
1513     if [ "$2" != "none" ]; then
1514         extra_log_options="-l$2"
1515         extra_mount_options="-ologdev=$2"
1516     fi
1517
1518     if [ "$3" != "none" ]; then
1519         extra_rt_options="-r$3"
1520         extra_mount_options=$extra_mount_options" -ortdev=$3"
1521     fi
1522     extra_mount_options=$extra_mount_options" $MOUNT_OPTIONS"
1523
1524     [ "$FSTYP" != xfs ] && return 0
1525
1526     type=`_fs_type $device`
1527     ok=1
1528
1529     if [ "$type" = "xfs" ]
1530     then
1531         # mounted ...
1532         mountpoint=`_umount_or_remount_ro $device`
1533     fi
1534
1535     $XFS_LOGPRINT_PROG -t $extra_log_options $device 2>&1 \
1536                 | tee $tmp.logprint | grep -q "<CLEAN>"
1537     if [ $? -ne 0 -a "$HOSTOS" = "Linux" ]
1538     then
1539         echo "_check_xfs_filesystem: filesystem on $device has dirty log (see $seqres.full)"
1540
1541         echo "_check_xfs_filesystem: filesystem on $device has dirty log"   >>$seqres.full
1542         echo "*** xfs_logprint -t output ***"   >>$seqres.full
1543         cat $tmp.logprint                       >>$seqres.full
1544         echo "*** end xfs_logprint output"      >>$seqres.full
1545
1546         ok=0
1547     fi
1548
1549     # xfs_check runs out of memory on large files, so even providing the test
1550     # option (-t) to avoid indexing the free space trees doesn't make it pass on
1551     # large filesystems. Avoid it.
1552     if [ "$LARGE_SCRATCH_DEV" != yes ]; then
1553             _xfs_check $extra_log_options $device 2>&1 |\
1554                  _fix_malloc >$tmp.fs_check
1555     fi
1556     if [ -s $tmp.fs_check ]
1557     then
1558         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (c) (see $seqres.full)"
1559
1560         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1561         echo "*** xfs_check output ***"         >>$seqres.full
1562         cat $tmp.fs_check                       >>$seqres.full
1563         echo "*** end xfs_check output"         >>$seqres.full
1564
1565         ok=0
1566     fi
1567
1568     $XFS_REPAIR_PROG -n $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
1569     if [ $? -ne 0 ]
1570     then
1571         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (r) (see $seqres.full)"
1572
1573         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1574         echo "*** xfs_repair -n output ***"     >>$seqres.full
1575         cat $tmp.repair | _fix_malloc           >>$seqres.full
1576         echo "*** end xfs_repair output"        >>$seqres.full
1577
1578         ok=0
1579     fi
1580     rm -f $tmp.fs_check $tmp.logprint $tmp.repair
1581
1582     if [ $ok -eq 0 ]
1583     then
1584         echo "*** mount output ***"             >>$seqres.full
1585         _mount                                  >>$seqres.full
1586         echo "*** end mount output"             >>$seqres.full
1587     elif [ "$type" = "xfs" ]
1588     then
1589         _mount_or_remount_rw "$extra_mount_options" $device $mountpoint
1590     fi
1591
1592     if [ $ok -eq 0 ]; then
1593         status=1
1594         exit 1
1595     fi
1596
1597     return 0
1598 }
1599
1600 # Filter the knowen errors the UDF Verifier reports.
1601 _udf_test_known_error_filter()
1602 {
1603         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."
1604
1605 }
1606
1607 _check_udf_filesystem()
1608 {
1609     [ "$DISABLE_UDF_TEST" == "1" ] && return
1610
1611     if [ $# -ne 1 -a $# -ne 2 ]
1612     then
1613         echo "Usage: _check_udf_filesystem device [last_block]" 1>&2
1614         exit 1
1615     fi
1616
1617     if [ ! -x $here/src/udf_test ]
1618     then
1619         echo "udf_test not installed, please download and build the Philips"
1620         echo "UDF Verification Software from http://www.extra.research.philips.com/udf/."
1621         echo "Then copy the udf_test binary to $here/src/."
1622         echo "If you do not wish to run udf_test then set environment variable DISABLE_UDF_TEST"
1623         echo "to 1."
1624         return
1625     fi
1626
1627     device=$1
1628     if [ $# -eq 2 ];
1629     then
1630         LAST_BLOCK=`expr \( $2 - 1 \)`
1631         OPT_ARG="-lastvalidblock $LAST_BLOCK"
1632     fi
1633
1634     rm -f $seqres.checkfs
1635     sleep 1 # Due to a problem with time stamps in udf_test
1636     $here/src/udf_test $OPT_ARG $device | tee $seqres.checkfs | egrep "Error|Warning" | \
1637         _udf_test_known_error_filter | \
1638         egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" && \
1639         echo "Warning UDF Verifier reported errors see $seqres.checkfs."
1640 }
1641
1642 _check_xfs_test_fs()
1643 {
1644     TEST_LOG="none"
1645     TEST_RT="none"
1646     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
1647         TEST_LOG="$TEST_LOGDEV"
1648
1649     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
1650         TEST_RT="$TEST_RTDEV"
1651
1652     _check_xfs_filesystem $TEST_DEV $TEST_LOG $TEST_RT
1653
1654     # check for ipath consistency
1655     if $XFS_GROWFS_PROG -n $TEST_DIR | grep -q 'inode-paths=1'; then
1656         # errors go to stderr
1657         xfs_check_ipaths $TEST_DIR >/dev/null
1658         xfs_repair_ipaths -n $TEST_DIR >/dev/null
1659     fi
1660 }
1661
1662 _check_btrfs_filesystem()
1663 {
1664     device=$1
1665
1666     # If type is set, we're mounted
1667     type=`_fs_type $device`
1668     ok=1
1669
1670     if [ "$type" = "$FSTYP" ]
1671     then
1672         # mounted ...
1673         mountpoint=`_umount_or_remount_ro $device`
1674     fi
1675
1676     btrfsck $device >$tmp.fsck 2>&1
1677     if [ $? -ne 0 ]
1678     then
1679         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1680
1681         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1682         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1683         cat $tmp.fsck                           >>$seqres.full
1684         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1685
1686         ok=0
1687     fi
1688     rm -f $tmp.fsck
1689
1690     if [ $ok -eq 0 ]
1691     then
1692         echo "*** mount output ***"             >>$seqres.full
1693         _mount                                  >>$seqres.full
1694         echo "*** end mount output"             >>$seqres.full
1695     elif [ "$type" = "$FSTYP" ]
1696     then
1697         # was mounted ...
1698         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1699         ok=$?
1700     fi
1701
1702     if [ $ok -eq 0 ]; then
1703         status=1
1704         exit 1
1705     fi
1706
1707     return 0
1708 }
1709
1710 _check_test_fs()
1711 {
1712     case $FSTYP in
1713     xfs)
1714         _check_xfs_test_fs
1715         ;;
1716     nfs)
1717         # no way to check consistency for nfs
1718         ;;
1719     udf)
1720         # do nothing for now
1721         ;;
1722     btrfs)
1723         _check_btrfs_filesystem $TEST_DEV
1724         ;;
1725     tmpfs)
1726         # no way to check consistency for tmpfs
1727         ;;
1728     *)
1729         _check_generic_filesystem $TEST_DEV
1730         ;;
1731     esac
1732 }
1733
1734 _check_scratch_fs()
1735 {
1736     device=$SCRATCH_DEV
1737     [ $# -eq 1 ] && device=$1
1738
1739     case $FSTYP in
1740     xfs)
1741         SCRATCH_LOG="none"
1742         SCRATCH_RT="none"
1743         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
1744             SCRATCH_LOG="$SCRATCH_LOGDEV"
1745
1746         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
1747             SCRATCH_RT="$SCRATCH_RTDEV"
1748
1749         _check_xfs_filesystem $device $SCRATCH_LOG $SCRATCH_RT
1750         ;;
1751     udf)
1752         _check_udf_filesystem $device $udf_fsize
1753         ;;
1754     nfs*)
1755         # Don't know how to check an NFS filesystem, yet.
1756         ;;
1757     btrfs)
1758         _check_btrfs_filesystem $device
1759         ;;
1760     tmpfs)
1761         # no way to check consistency for tmpfs
1762         ;;
1763     *)
1764         _check_generic_filesystem $device
1765         ;;
1766     esac
1767 }
1768
1769 _full_fstyp_details()
1770 {
1771      [ -z "$FSTYP" ] && FSTYP=xfs
1772      if [ $FSTYP = xfs ]; then
1773         if [ -d /proc/fs/xfs ]; then
1774             if grep -q 'debug 0' /proc/fs/xfs/stat; then
1775                 FSTYP="$FSTYP (non-debug)"
1776             elif grep -q 'debug 1' /proc/fs/xfs/stat; then
1777                 FSTYP="$FSTYP (debug)"
1778             fi
1779         else
1780             if uname -a | grep -qi 'debug'; then
1781                 FSTYP="$FSTYP (debug)"
1782             else
1783                 FSTYP="$FSTYP (non-debug)"
1784             fi
1785         fi
1786      fi
1787      echo $FSTYP
1788 }
1789
1790 _full_platform_details()
1791 {
1792      os=`uname -s`
1793      host=`hostname -s`
1794      kernel=`uname -r`
1795      platform=`uname -m`
1796      echo "$os/$platform $host $kernel"
1797 }
1798
1799 _link_out_file()
1800 {
1801         if [ -z "$1" -o -z "$2" ]; then
1802                 echo Error must pass src and dst.
1803                 exit
1804         fi
1805         rm -f $2
1806         if [ "`uname`" == "IRIX64" ] || [ "`uname`" == "IRIX" ]; then
1807                 ln -s $1.irix $2
1808         elif [ "`uname`" == "Linux" ]; then
1809                 ln -s $1.linux $2
1810         else
1811                 echo Error test $seq does not run on the operating system: `uname`
1812                 exit
1813         fi
1814 }
1815
1816 _die()
1817 {
1818         echo $@
1819         exit 1
1820 }
1821
1822 #takes files, randomdata
1823 _nfiles()
1824 {
1825         f=0
1826         while [ $f -lt $1 ]
1827         do
1828                 file=f$f
1829                 echo > $file
1830                 if [ $size -gt 0 ]; then
1831                     if [ "$2" == "false" ]; then
1832                         dd if=/dev/zero of=$file bs=1024 count=$size 2>&1 | _filter_dd
1833                     else
1834                         dd if=/dev/urandom of=$file bs=1024 count=$size 2>&1 | _filter_dd
1835                     fi
1836                 fi
1837                 let f=$f+1
1838         done
1839 }
1840
1841 # takes dirname, depth, randomdata
1842 _descend()
1843 {
1844         dirname=$1; depth=$2; randomdata=$3
1845         mkdir $dirname  || die "mkdir $dirname failed"
1846         cd $dirname
1847
1848         _nfiles $files $randomdata          # files for this dir and data type
1849
1850         [ $depth -eq 0 ] && return
1851         let deep=$depth-1 # go 1 down
1852
1853         [ $verbose = true ] && echo "descending, depth from leaves = $deep"
1854
1855         d=0
1856         while [ $d -lt $dirs ]
1857         do
1858                 _descend d$d $deep &
1859                 let d=$d+1
1860                 wait
1861         done
1862 }
1863
1864 # Populate a filesystem with inodes for performance experiments
1865 #
1866 # usage: populate [-v] [-n ndirs] [-f nfiles] [-d depth] [-r root] [-s size] [-x]
1867 #
1868 _populate_fs()
1869 {
1870     here=`pwd`
1871     dirs=5          # ndirs in each subdir till leaves
1872     size=0          # sizeof files in K
1873     files=100       # num files in _each_ subdir
1874     depth=2         # depth of tree from root to leaves
1875     verbose=false
1876     root=root       # path of initial root of directory tree
1877     randomdata=false # -x data type urandom or zero
1878
1879     OPTIND=1
1880     while getopts "d:f:n:r:s:v:x" c
1881     do
1882         case $c in
1883         d)      depth=$OPTARG;;
1884         n)      dirs=$OPTARG;;
1885         f)      files=$OPTARG;;
1886         s)      size=$OPTARG;;
1887         v)      verbose=true;;
1888         r)      root=$OPTARG;;
1889         x)      randomdata=true;;
1890         esac
1891     done
1892
1893     _descend $root $depth $randomdata
1894     wait
1895
1896     cd $here
1897
1898     [ $verbose = true ] && echo done
1899 }
1900
1901 # query whether the given file has the given inode flag set
1902 #
1903 _test_inode_flag()
1904 {
1905     flag=$1
1906     file=$2
1907
1908     if which $XFS_IO_PROG >/dev/null; then
1909         if $XFS_IO_PROG -r -c 'lsattr -v' "$file" | grep -q "$flag" ; then
1910             return 0
1911         fi
1912     fi
1913     return 1
1914 }
1915
1916 # query the given files extsize allocator hint in bytes (if any)
1917 #
1918 _test_inode_extsz()
1919 {
1920     file=$1
1921     blocks=""
1922
1923     if which $XFS_IO_PROG >/dev/null; then
1924         blocks=`$XFS_IO_PROG -r -c 'stat' "$file" | \
1925                 awk '/^xattr.extsize =/ { print $3 }'`
1926     fi
1927     [ -z "$blocks" ] && blocks="0"
1928     echo $blocks
1929 }
1930
1931 # scratch_dev_pool should contain the disks pool for the btrfs raid
1932 _require_scratch_dev_pool()
1933 {
1934         local i
1935         local ndevs
1936
1937         if [ -z "$SCRATCH_DEV_POOL" ]; then
1938                 _notrun "this test requires a valid \$SCRATCH_DEV_POOL"
1939         fi
1940
1941         if [ -z "$1" ]; then
1942                 ndevs=2
1943         else
1944                 ndevs=$1
1945         fi
1946
1947         # btrfs test case needs ndevs or more scratch_dev_pool; other FS not sure
1948         # so fail it
1949         case $FSTYP in
1950         btrfs)
1951                 if [ "`echo $SCRATCH_DEV_POOL|wc -w`" -lt $ndevs ]; then
1952                         _notrun "btrfs and this test needs $ndevs or more disks in SCRATCH_DEV_POOL"
1953                 fi
1954         ;;
1955         *)
1956                 _notrun "dev_pool is not supported by fstype \"$FSTYP\""
1957         ;;
1958         esac
1959
1960         for i in $SCRATCH_DEV_POOL; do
1961                 if [ "`_is_block_dev $i`" = "" ]; then
1962                         _notrun "this test requires valid block disk $i"
1963                 fi
1964                 if [ "`_is_block_dev $i`" = "`_is_block_dev $TEST_DEV`" ]; then
1965                         _notrun "$i is part of TEST_DEV, this test requires unique disks"
1966                 fi
1967                 if _mount | grep -q $i; then
1968                         if ! $UMOUNT_PROG $i; then
1969                             echo "failed to unmount $i - aborting"
1970                             exit 1
1971                         fi
1972                 fi
1973                 # to help better debug when something fails, we remove
1974                 # traces of previous btrfs FS on the dev.
1975                 dd if=/dev/zero of=$i bs=4096 count=100 > /dev/null 2>&1
1976         done
1977 }
1978
1979 # We will check if the device is deletable
1980 _require_deletable_scratch_dev_pool()
1981 {
1982         local i
1983         local x
1984         for i in $SCRATCH_DEV_POOL; do
1985                 x=`echo $i | cut -d"/" -f 3`
1986                 if [ ! -f /sys/class/block/${x}/device/delete ]; then
1987                         _notrun "$i is a device which is not deletable"
1988                 fi
1989         done
1990 }
1991
1992 # We check for btrfs and (optionally) features of the btrfs command
1993 _require_btrfs()
1994 {
1995         cmd=$1
1996         _require_command $BTRFS_UTIL_PROG btrfs
1997         if [ -z "$1" ]; then
1998                 return 1;
1999         fi
2000         $BTRFS_UTIL_PROG $cmd --help >/dev/null 2>&1
2001         [ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd)"
2002 }
2003
2004 # Check that fio is present, and it is able to execute given jobfile
2005 _require_fio()
2006 {
2007         job=$1
2008
2009         _require_command $FIO_PROG
2010         if [ -z "$1" ]; then
2011                 return 1;
2012         fi
2013
2014         $FIO_PROG --warnings-fatal --showcmd $job >> $seqres.full 2>&1
2015         [ $? -eq 0 ] || _notrun "$FIO_PROG too old, see $seqres.full"
2016 }
2017
2018 # Does freeze work on this fs?
2019 _require_freeze()
2020 {
2021         xfs_freeze -f "$TEST_DIR" >/dev/null 2>&1
2022         result=$? 
2023         xfs_freeze -u "$TEST_DIR" >/dev/null 2>&1
2024         [ $result -eq 0 ] || _notrun "$FSTYP does not support freezing"
2025 }
2026
2027 # arg 1 is dev to remove and is output of the below eg.
2028 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2029 _devmgt_remove()
2030 {
2031         local lun=$1
2032         local disk=$2
2033
2034         echo 1 > /sys/class/scsi_device/${lun}/device/delete || _fail "Remove disk failed"
2035
2036         stat $disk > /dev/null 2>&1
2037         while [ $? -eq 0 ]; do
2038                 sleep 1
2039                 stat $disk > /dev/null 2>&1
2040         done
2041 }
2042
2043 # arg 1 is dev to add and is output of the below eg.
2044 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2045 _devmgt_add()
2046 {
2047         local h
2048         local tdl
2049         # arg 1 will be in h:t:d:l format now in the h and "t d l" format
2050         h=`echo ${1} | cut -d":" -f 1`
2051         tdl=`echo ${1} | cut -d":" -f 2-|sed 's/:/ /g'`
2052
2053         echo ${tdl} >  /sys/class/scsi_host/host${h}/scan || _fail "Add disk failed"
2054 }
2055
2056 _require_fstrim()
2057 {
2058         if [ -z "$FSTRIM_PROG" ]; then
2059                 _notrun "This test requires fstrim utility."
2060         fi
2061 }
2062
2063 _test_batched_discard()
2064 {
2065         if [ $# -ne 1 ]; then
2066                 echo "Usage: _test_batched_discard mnt_point" 1>&2
2067                 exit 1
2068         fi
2069         _require_fstrim
2070         $FSTRIM_PROG ${1} &>/dev/null
2071 }
2072
2073 _require_dumpe2fs()
2074 {
2075         if [ -z "$DUMPE2FS_PROG" ]; then
2076                 _notrun "This test requires dumpe2fs utility."
2077         fi
2078 }
2079
2080 _require_ugid_map()
2081 {
2082         if [ ! -e /proc/self/uid_map ]; then
2083                 _notrun "This test requires procfs uid_map support."
2084         fi
2085         if [ ! -e /proc/self/gid_map ]; then
2086                 _notrun "This test requires procfs gid_map support."
2087         fi
2088 }
2089
2090 _require_cp_reflink()
2091 {
2092        cp --help | grep -q reflink || \
2093                _notrun "This test requires a cp with --reflink support."
2094 }
2095
2096 _require_fssum()
2097 {
2098         FSSUM_PROG=$here/src/fssum
2099         [ -x $FSSUM_PROG ] || _notrun "fssum not built"
2100 }
2101
2102 # Given 2 files, verify that they have the same mapping but different
2103 # inodes - i.e. an undisturbed reflink
2104 # Silent if so, make noise if not
2105 _verify_reflink()
2106 {
2107        # not a hard link or symlink?
2108        cmp -s  <(stat -c '%i' $1) <(stat -c '%i' $2) \
2109                && echo "$1 and $2 are not reflinks: same inode number"
2110
2111        # same mapping?
2112        diff -u <($XFS_IO_PROG -c "fiemap" $1 | grep -v $1) \
2113                <($XFS_IO_PROG -c "fiemap" $2 | grep -v $2) \
2114                || echo "$1 and $2 are not reflinks: different extents"
2115 }
2116
2117 _require_relatime()
2118 {
2119         _scratch_mkfs > /dev/null 2>&1
2120         _mount -t $FSTYP -o relatime $SCRATCH_DEV $SCRATCH_MNT || \
2121                 _notrun "relatime not supported by the current kernel"
2122         _scratch_unmount
2123 }
2124
2125 _create_loop_device()
2126 {
2127         file=$1
2128         dev=`losetup -f --show $file` || _fail "Cannot assign $file to a loop device"
2129         echo $dev
2130 }
2131
2132 _destroy_loop_device()
2133 {
2134         dev=$1
2135         losetup -d $dev || _fail "Cannot destroy loop device $dev"
2136 }
2137
2138 _scale_fsstress_args()
2139 {
2140     args=""
2141     while [ $# -gt 0 ]; do
2142         case "$1" in
2143             -n) args="$args $1 $(($2 * $TIME_FACTOR))"; shift ;;
2144             -p) args="$args $1 $(($2 * $LOAD_FACTOR))"; shift ;;
2145             *) args="$args $1" ;;
2146         esac
2147         shift
2148     done
2149     echo $args
2150 }
2151
2152 #
2153 # Return the logical block size if running on a block device,
2154 # else substitute the page size.
2155 #
2156 _min_dio_alignment()
2157 {
2158     dev=$1
2159
2160     if [ -b "$dev" ]; then
2161         blockdev --getss $dev
2162     else
2163         $here/src/feature -s
2164     fi
2165 }
2166
2167 run_check()
2168 {
2169         echo "# $@" >> $seqres.full 2>&1
2170         "$@" >> $seqres.full 2>&1 || _fail "failed: '$@'"
2171 }
2172
2173 _run_btrfs_util_prog()
2174 {
2175         run_check $BTRFS_UTIL_PROG $*
2176 }
2177
2178 _require_btrfs_send_stream_version()
2179 {
2180         $BTRFS_UTIL_PROG send 2>&1 | \
2181                 grep '^[ \t]*\-\-stream\-version <version>' > /dev/null 2>&1
2182         if [ $? -ne 0 ]; then
2183                 _notrun "Missing btrfs-progs send --stream-version command line option, skipped this test"
2184         fi
2185 }
2186
2187 init_rc()
2188 {
2189         if [ "$iam" == new ]
2190         then
2191                 return
2192         fi
2193         # make some further configuration checks here
2194         if [ "$TEST_DEV" = ""  ]
2195         then
2196                 echo "common/rc: Error: \$TEST_DEV is not set"
2197                 exit 1
2198         fi
2199
2200         # if $TEST_DEV is not mounted, mount it now as XFS
2201         if [ -z "`_fs_type $TEST_DEV`" ]
2202         then
2203                 # $TEST_DEV is not mounted
2204                 if ! _test_mount
2205                 then
2206                         echo "common/rc: retrying test device mount with external set"
2207                         [ "$USE_EXTERNAL" != "yes" ] && export USE_EXTERNAL=yes
2208                         if ! _test_mount
2209                         then
2210                                 echo "common/rc: could not mount $TEST_DEV on $TEST_DIR"
2211                                 exit 1
2212                         fi
2213                 fi
2214         fi
2215
2216         if [ "`_fs_type $TEST_DEV`" != "$FSTYP" ]
2217         then
2218                 echo "common/rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED $FSTYP filesystem"
2219                 $DF_PROG $TEST_DEV
2220                 exit 1
2221         fi
2222         # Figure out if we need to add -F ("foreign", deprecated) option to xfs_io
2223         xfs_io -c stat $TEST_DIR 2>&1 | grep -q "is not on an XFS filesystem" && \
2224         export XFS_IO_PROG="$XFS_IO_PROG -F"
2225 }
2226
2227 init_rc
2228
2229 ################################################################################
2230 # make sure this script returns success
2231 /bin/true