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