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