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