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