BC=$(which bc 2> /dev/null) || BC=
+# Valid test names start with 3 digits "NNN":
+# "[0-9]\{3\}"
+# followed by an optional "-":
+# "-\?"
+# followed by an optional combination of alphanumeric and "-" chars:
+# "[[:alnum:]-]*"
+# e.g. 999-the-mark-of-fstests
+#
+VALID_TEST_NAME="[0-9]\{3\}-\?[[:alnum:]-]*"
+
_require_math()
{
if [ -z "$BC" ]; then
{
if [ "$HOSTOS" == "Linux" ]
then
- command dd --help | grep noxfer > /dev/null 2>&1
+ command dd --help 2>&1 | grep noxfer >/dev/null
if [ "$?" -eq 0 ]
then
btrfs)
[ "$MKFS_BTRFS_PROG" = "" ] && _fatal "mkfs.btrfs not found"
;;
+ ext4)
+ [ "$MKFS_EXT4_PROG" = "" ] && _fatal "mkfs.ext4 not found"
+ ;;
+ f2fs)
+ [ "$MKFS_F2FS_PROG" = "" ] && _fatal "mkfs.f2fs not found"
+ ;;
nfs)
;;
+ cifs)
+ ;;
+ reiser4)
+ [ "$MKFS_REISER4_PROG" = "" ] && _fatal "mkfs.reiser4 not found"
+ ;;
esac
# make sure we have a standard umask
_mount -t $FSTYP $TEST_OPTIONS $TEST_FS_MOUNT_OPTS $SELINUX_MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR
}
+_test_remount()
+{
+ $UMOUNT_PROG $TEST_DEV
+ _test_mount
+}
+
_scratch_mkfs_options()
{
_scratch_options mkfs
{
mkfs_opts=$*
+ # remove crc related mkfs options if mkfs.xfs doesn't support v5 xfs
+ if [ -n "$XFS_MKFS_HAS_NO_META_SUPPORT" ]; then
+ mkfs_opts=`echo $mkfs_opts | sed "s/-m\s\+crc=.//"`
+ fi
+
_scratch_options mkfs
$MKFS_XFS_PROG $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
mkfs_status=$?
fi
- # output stored mkfs output
- cat $tmp_dir.mkfserr >&2
+ # output stored mkfs output, filtering unnecessary warnings from stderr
cat $tmp_dir.mkfsstd
+ cat $tmp_dir.mkfserr | sed \
+ -e '/less than device physical sector/d' \
+ -e '/switching to logical sector/d' \
+ >&2
rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
return $mkfs_status
_scratch_mkfs_ext4()
{
+ # extra mkfs options can be added by tests
+ local extra_mkfs_options=$*
+
local tmp_dir=/tmp/
- /sbin/mkfs -t $FSTYP -- -F $MKFS_OPTIONS $* $SCRATCH_DEV \
+ $MKFS_EXT4_PROG -F $MKFS_OPTIONS $extra_mkfs_options $SCRATCH_DEV \
2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
local mkfs_status=$?
+ # a mkfs failure may be caused by conflicts between
+ # $MKFS_OPTIONS and $extra_mkfs_options
+ if [ $mkfs_status -ne 0 -a ! -z "$extra_mkfs_options" ]; then
+ (
+ echo -n "** mkfs failed with extra mkfs options "
+ echo "added to \"$MKFS_OPTIONS\" by test $seq **"
+ echo -n "** attempting to mkfs using only test $seq "
+ echo "options: $extra_mkfs_options **"
+ ) >> $seqres.full
+
+ # running mkfs again. overwrite previous mkfs output files
+ $MKFS_EXT4_PROG -F $extra_mkfs_options $SCRATCH_DEV \
+ 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+ local mkfs_status=$?
+ fi
+
if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
# manually parse the mkfs output to get the fs size in bytes
fs_size=`cat $tmp_dir.mkfsstd | awk ' \
nfs*)
# do nothing for nfs
;;
+ cifs)
+ # do nothing for cifs
+ ;;
udf)
$MKFS_UDF_PROG $MKFS_OPTIONS $* $TEST_DEV > /dev/null
;;
btrfs)
$MKFS_BTRFS_PROG $MKFS_OPTIONS $* $TEST_DEV > /dev/null
;;
+ ext2|ext3|ext4)
+ $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $TEST_DEV
+ ;;
*)
yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
;;
esac
}
+_mkfs_dev()
+{
+ case $FSTYP in
+ nfs*)
+ # do nothing for nfs
+ ;;
+ udf)
+ $MKFS_UDF_PROG $MKFS_OPTIONS $* 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+ ;;
+ btrfs)
+ $MKFS_BTRFS_PROG $MKFS_OPTIONS $* 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+ ;;
+ ext2|ext3|ext4)
+ $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* \
+ 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+ ;;
+
+ *)
+ yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
+ 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+ ;;
+ esac
+
+ if [ $? -ne 0 ]; then
+ # output stored mkfs output
+ cat $tmp_dir.mkfserr >&2
+ cat $tmp_dir.mkfsstd
+ status=1
+ exit 1
+ fi
+ rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
+}
+
+# remove all files in $SCRATCH_MNT, useful when testing on NFS/CIFS
+_scratch_cleanup_files()
+{
+ _scratch_mount
+ rm -rf $SCRATCH_MNT/*
+ _scratch_unmount
+}
+
_scratch_mkfs()
{
case $FSTYP in
_scratch_mkfs_xfs $*
;;
nfs*)
- # do nothing for nfs
+ # unable to re-create NFS, just remove all files in $SCRATCH_MNT to
+ # avoid EEXIST caused by the leftover files created in previous runs
+ _scratch_cleanup_files
+ ;;
+ cifs)
+ # unable to re-create CIFS, just remove all files in $SCRATCH_MNT to
+ # avoid EEXIST caused by the leftover files created in previous runs
+ _scratch_cleanup_files
;;
udf)
$MKFS_UDF_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
btrfs)
$MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
;;
+ ext2|ext3)
+ $MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $SCRATCH_DEV
+ ;;
ext4)
_scratch_mkfs_ext4 $*
;;
tmpfs)
# do nothing for tmpfs
;;
+ f2fs)
+ $MKFS_F2FS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
+ ;;
*)
yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $SCRATCH_DEV
;;
{
case $FSTYP in
btrfs)
- $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV_POOL > /dev/null
- ;;
+ # if dup profile is in mkfs options call _scratch_mkfs instead
+ # because dup profile only works with single device
+ if [[ "$*" =~ dup ]]; then
+ _scratch_mkfs $*
+ else
+ $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV_POOL > /dev/null
+ fi
+ ;;
*)
- echo "_scratch_pool_mkfs is not implemented for $FSTYP" 1>&2
- ;;
+ echo "_scratch_pool_mkfs is not implemented for $FSTYP" 1>&2
+ ;;
esac
}
{
fssize=$1
blocksize=$2
+
+ case $FSTYP in
+ xfs)
+ def_blksz=`echo $MKFS_OPTIONS|sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
+ ;;
+ ext2|ext3|ext4|ext4dev|udf|btrfs|reiser4)
+ def_blksz=`echo $MKFS_OPTIONS| sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
+ ;;
+ esac
+
+ [ -n "$def_blksz" ] && blocksize=$def_blksz
[ -z "$blocksize" ] && blocksize=4096
+
re='^[0-9]+$'
if ! [[ $fssize =~ $re ]] ; then
_notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
fi
;;
ext2|ext3|ext4|ext4dev)
- yes | ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+ ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
;;
udf)
$MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
btrfs)
$MKFS_BTRFS_PROG $MKFS_OPTIONS -b $fssize $SCRATCH_DEV
;;
+ reiser4)
+ # mkfs.resier4 requires size in KB as input for creating filesystem
+ $MKFS_REISER4_PROG $MKFS_OPTIONS -y -b $blocksize $SCRATCH_DEV \
+ `expr $fssize / 1024`
+ ;;
*)
_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
;;
exit 1
fi
+ # Note that we use "==" here so awk doesn't try to interpret an NFS over
+ # IPv6 server as a regular expression.
$DF_PROG 2>/dev/null | $AWK_PROG -v what=$1 '
- match($1,what) && NF==1 {
+ ($1==what) && (NF==1) {
v=$1
getline
print v, $0
exit
}
- match($1,what) {
+ ($1==what) {
print
exit
}
_dev=$1
if [ -L "${_dev}" ]; then
- _dev=`readlink -f ${_dev}`
+ _dev=`readlink -f "${_dev}"`
fi
if [ -b "${_dev}" ]; then
- src/lstat64 ${_dev} | $AWK_PROG '/Device type:/ { print $9 }'
+ src/lstat64 "${_dev}" | $AWK_PROG '/Device type:/ { print $9 }'
fi
}
return $ret
}
-# bail out, setting up .notrun file
+# bail out, setting up .notrun file. Need to kill the filesystem check files
+# here, otherwise they are set incorrectly for the next test.
#
_notrun()
{
echo "$*" > $seqres.notrun
echo "$seq not run: $*"
+ rm -f ${RESULT_DIR}/require_test
+ rm -f ${RESULT_DIR}/require_scratch
status=0
exit
}
}
# this test needs a scratch partition - check we're ok & unmount it
-#
-_require_scratch()
+# No post-test check of the device is required. e.g. the test intentionally
+# finishes the test with the filesystem in a corrupt state
+_require_scratch_nocheck()
{
case "$FSTYP" in
nfs*)
- _notrun "requires a scratch device"
- ;;
+ echo $SCRATCH_DEV | grep -q ":/" > /dev/null 2>&1
+ if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$SCRATCH_DEV"
+ fi
+ if [ ! -d "$SCRATCH_MNT" ]; then
+ _notrun "this test requires a valid \$SCRATCH_MNT"
+ fi
+ ;;
+ cifs)
+ echo $SCRATCH_DEV | grep -q "//" > /dev/null 2>&1
+ if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$SCRATCH_DEV"
+ fi
+ if [ ! -d "$SCRATCH_MNT" ]; then
+ _notrun "this test requires a valid \$SCRATCH_MNT"
+ fi
+ ;;
tmpfs)
if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
then
fi
;;
*)
- if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
+ if [ -z "$SCRATCH_DEV" -o "`_is_block_dev "$SCRATCH_DEV"`" = "" ]
then
_notrun "this test requires a valid \$SCRATCH_DEV"
fi
- if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
+ if [ "`_is_block_dev "$SCRATCH_DEV"`" = "`_is_block_dev "$TEST_DEV"`" ]
then
_notrun "this test requires a valid \$SCRATCH_DEV"
fi
esac
# mounted?
- if _mount | grep -q $SCRATCH_DEV
+ # Note that we use -F here so grep doesn't try to interpret an NFS over
+ # IPv6 server as a regular expression.
+ if _mount | grep -F -q $SCRATCH_DEV
then
# if it's mounted, make sure its on $SCRATCH_MNT
- if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
+ if ! _mount | grep -F $SCRATCH_DEV | grep -q $SCRATCH_MNT
then
echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
exit 1
exit 1
fi
fi
+ rm -f ${RESULT_DIR}/require_scratch
+}
+
+# we need the scratch device and it should be checked post test.
+_require_scratch()
+{
+ _require_scratch_nocheck
+ touch ${RESULT_DIR}/require_scratch
+}
+
+
+# this test needs a test partition - check we're ok & mount it
+#
+_require_test()
+{
+ case "$FSTYP" in
+ nfs*)
+ echo $TEST_DEV | grep -q ":/" > /dev/null 2>&1
+ if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$TEST_DIR"
+ fi
+ if [ ! -d "$TEST_DIR" ]; then
+ _notrun "this test requires a valid \$TEST_DIR"
+ fi
+ ;;
+ cifs)
+ echo $TEST_DEV | grep -q "//" > /dev/null 2>&1
+ if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$TEST_DEV"
+ fi
+ if [ ! -d "$TEST_DIR" ]; then
+ _notrun "this test requires a valid \$TEST_DIR"
+ fi
+ ;;
+ tmpfs)
+ if [ -z "$TEST_DEV" -o ! -d "$TEST_DIR" ];
+ then
+ _notrun "this test requires a valid \$TEST_DIR and unique $TEST_DEV"
+ fi
+ ;;
+ *)
+ if [ -z "$TEST_DEV" ] || [ "`_is_block_dev "$TEST_DEV"`" = "" ]
+ then
+ _notrun "this test requires a valid \$TEST_DEV"
+ fi
+ if [ "`_is_block_dev "$SCRATCH_DEV"`" = "`_is_block_dev "$TEST_DEV"`" ]
+ then
+ _notrun "this test requires a valid \$TEST_DEV"
+ fi
+ if [ ! -d "$TEST_DIR" ]
+ then
+ _notrun "this test requires a valid \$TEST_DIR"
+ fi
+ ;;
+ esac
+
+ # mounted?
+ # Note that we use -F here so grep doesn't try to interpret an NFS over
+ # IPv6 server as a regular expression.
+ if _mount | grep -F -q $TEST_DEV
+ then
+ # if it's mounted, make sure its on $TEST_DIR
+ if ! _mount | grep -F $TEST_DEV | grep -q $TEST_DIR
+ then
+ echo "\$TEST_DEV is mounted but not on \$TEST_DIR - aborting"
+ exit 1
+ fi
+ else
+ out=`_mount_or_remount_rw "$MOUNT_OPTIONS" $TEST_DEV $TEST_DIR`
+ if [ $? -ne 1 ]; then
+ echo $out
+ exit 1
+ fi
+ fi
+ touch ${RESULT_DIR}/require_test
}
# this test needs a logdev
# this test requires that a specified command (executable) exists
# $1 - command, $2 - name for error message
#
+# Note: the command string might have parameters, so strip them before checking
+# whether it is executable.
_require_command()
{
- [ -n "$1" ] && _cmd="$1" || _cmd="$2"
- [ -n "$1" -a -x "$1" ] || _notrun "$_cmd utility required, skipped this test"
+ if [ $# -eq 2 ]; then
+ _name="$2"
+ elif [ $# -eq 1 ]; then
+ _name="$1"
+ else
+ _fail "usage: _require_command <command> [<name>]"
+ fi
+
+ _command=`echo "$1" | awk '{ print $1 }'`
+ if [ ! -x "$_command" ]; then
+ _notrun "$_name utility required, skipped this test"
+ fi
+}
+
+# this test requires the device to be valid block device
+# $1 - device
+_require_block_device()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _require_block_device <dev>" 1>&2
+ exit 1
+ fi
+ if [ "`_is_block_dev "$1"`" == "" ]; then
+ _notrun "require $1 to be valid block disk"
+ fi
+}
+
+# brd based ram disks erase the device when they receive a flush command when no
+# active references are present. This causes problems for DM devices sitting on
+# top of brd devices as DM doesn't hold active references to the brd device.
+_require_sane_bdev_flush()
+{
+ echo $1 | grep -q "^/dev/ram[0-9]\+$"
+ if [ $? -eq 0 ]; then
+ _notrun "This test requires a sane block device flush"
+ fi
}
# this test requires the device mapper flakey target
#
_require_dm_flakey()
{
- _require_command $DMSETUP_PROG
+ # require SCRATCH_DEV to be a valid block device with sane BLKFLSBUF
+ # behaviour
+ _require_block_device $SCRATCH_DEV
+ _require_sane_bdev_flush $SCRATCH_DEV
+ _require_command "$DMSETUP_PROG" dmsetup
- modprobe dm-flakey >/dev/null 2>&1
- $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
- if [ $? -eq 0 ]
- then
- :
- else
- _notrun "This test requires dm flakey support"
- fi
+ modprobe dm-flakey >/dev/null 2>&1
+ $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ _notrun "This test requires dm flakey support"
+ fi
+}
+
+_require_dm_snapshot()
+{
+ _require_block_device $SCRATCH_DEV
+ _require_sane_bdev_flush $SCRATCH_DEV
+ _require_command "$DMSETUP_PROG" dmsetup
+ modprobe dm-snapshot >/dev/null 2>&1
+ $DMSETUP_PROG targets | grep -q snapshot
+ if [ $? -ne 0 ]; then
+ _notrun "This test requires dm snapshot support"
+ fi
}
# this test requires the projid32bit feature to be available in mkfs.xfs.
umount $SCRATCH_MNT
}
+# this test requires the bigalloc feature to be available in mkfs.ext4
+#
+_require_ext4_mkfs_bigalloc()
+{
+ $MKFS_EXT4_PROG -F -O bigalloc -n $SCRATCH_DEV 512m >/dev/null 2>&1 \
+ || _notrun "mkfs.ext4 doesn't have bigalloc feature"
+}
+
+# this test requires the ext4 kernel support bigalloc feature
+#
+_require_ext4_bigalloc()
+{
+ $MKFS_EXT4_PROG -F -O bigalloc $SCRATCH_DEV 512m >/dev/null 2>&1
+ _scratch_mount >/dev/null 2>&1 \
+ || _notrun "Ext4 kernel doesn't support bigalloc feature"
+ umount $SCRATCH_MNT
+}
+
# this test requires the finobt feature to be available in mkfs.xfs
#
_require_xfs_mkfs_finobt()
umount $SCRATCH_MNT
}
+# this test requires xfs sysfs attribute support
+#
+_require_xfs_sysfs()
+{
+ attr=$1
+ sysfsdir=/sys/fs/xfs
+
+ if [ ! -e $sysfsdir ]; then
+ _notrun "no kernel support for XFS sysfs attributes"
+ fi
+
+ if [ ! -z $1 ] && [ ! -e $sysfsdir/$attr ]; then
+ _notrun "sysfs attribute '$attr' is not supported"
+ fi
+}
+
+# this test requires the xfs sparse inode feature
+#
+_require_xfs_sparse_inodes()
+{
+ _scratch_mkfs_xfs_supported -m crc=1 -i sparse > /dev/null 2>&1 \
+ || _notrun "mkfs.xfs does not support sparse inodes"
+ _scratch_mkfs_xfs -m crc=1 -i sparse > /dev/null 2>&1
+ _scratch_mount >/dev/null 2>&1 \
+ || _notrun "kernel does not support sparse inodes"
+ umount $SCRATCH_MNT
+}
+
# this test requires that external log/realtime devices are not in use
#
_require_nonexternal()
AIO_TEST=src/aio-dio-regress/$1
[ -x $AIO_TEST ] || _notrun "$AIO_TEST not built"
fi
+ _require_odirect
}
# run an aio-dio program
"falloc" )
testio=`$XFS_IO_PROG -F -f -c "falloc 0 1m" $testfile 2>&1`
;;
- "fpunch" | "fcollapse" | "zero" | "fzero" )
+ "fpunch" | "fcollapse" | "zero" | "fzero" | "finsert" )
testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
-c "$command 4k 8k" $testfile 2>&1`
;;
"flink" )
testio=`$XFS_IO_PROG -T -F -c "flink $testfile" \
$TEST_DIR 2>&1`
+ echo $testio | egrep -q "invalid option|Is a directory" && \
+ _notrun "xfs_io $command support is missing"
;;
*)
testio=`$XFS_IO_PROG -c "$command help" 2>&1`
_notrun "xfs_io $command failed (old kernel/wrong fs?)"
}
+# check that kernel and filesystem support direct I/O
+_require_odirect()
+{
+ testfile=$TEST_DIR/$$.direct
+ $XFS_IO_PROG -F -f -d -c "pwrite 0 20k" $testfile > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ _notrun "O_DIRECT is not supported"
+ fi
+ rm -f $testfile 2>&1 > /dev/null
+}
+
# Check that a fs has enough free space (in 1024b blocks)
#
_require_fs_space()
if [ $ok -eq 0 ]; then
status=1
- exit 1
+ if [ "$iam" != "check" ]; then
+ exit 1
+ fi
+ return 1
fi
return 0
if [ $ok -eq 0 ]; then
status=1
- exit 1
+ if [ "$iam" != "check" ]; then
+ exit 1
+ fi
+ return 1
fi
return 0
$here/src/udf_test $OPT_ARG $device | tee $seqres.checkfs | egrep "Error|Warning" | \
_udf_test_known_error_filter | \
egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" && \
- echo "Warning UDF Verifier reported errors see $seqres.checkfs."
+ echo "Warning UDF Verifier reported errors see $seqres.checkfs." && return 1
+ return 0
}
_check_xfs_test_fs()
if [ $ok -eq 0 ]; then
status=1
- exit 1
+ if [ "$iam" != "check" ]; then
+ exit 1
+ fi
+ return 1
fi
return 0
nfs)
# no way to check consistency for nfs
;;
+ cifs)
+ # no way to check consistency for cifs
+ ;;
udf)
# do nothing for now
;;
nfs*)
# Don't know how to check an NFS filesystem, yet.
;;
+ cifs)
+ # Don't know how to check a CIFS filesystem, yet.
+ ;;
btrfs)
_check_btrfs_filesystem $device
;;
esac
for i in $SCRATCH_DEV_POOL; do
- if [ "`_is_block_dev $i`" = "" ]; then
+ if [ "`_is_block_dev "$i"`" = "" ]; then
_notrun "this test requires valid block disk $i"
fi
- if [ "`_is_block_dev $i`" = "`_is_block_dev $TEST_DEV`" ]; then
+ if [ "`_is_block_dev "$i"`" = "`_is_block_dev "$TEST_DEV"`" ]; then
_notrun "$i is part of TEST_DEV, this test requires unique disks"
fi
if _mount | grep -q $i; then
done
}
+# ensure devices in SCRATCH_DEV_POOL are of the same size
+# must be called after _require_scratch_dev_pool
+_require_scratch_dev_pool_equal_size()
+{
+ local _size
+ local _newsize
+ local _dev
+
+ # SCRATCH_DEV has been set to the first device in SCRATCH_DEV_POOL
+ _size=`_get_device_size $SCRATCH_DEV`
+ for _dev in $SCRATCH_DEV_POOL; do
+ _newsize=`_get_device_size $_dev`
+ if [ $_size -ne $_newsize ]; then
+ _notrun "This test requires devices in SCRATCH_DEV_POOL have the same size"
+ fi
+ done
+}
+
# We will check if the device is deletable
_require_deletable_scratch_dev_pool()
{
_require_btrfs()
{
cmd=$1
- _require_command $BTRFS_UTIL_PROG btrfs
+ _require_command "$BTRFS_UTIL_PROG" btrfs
if [ -z "$1" ]; then
return 1;
fi
{
job=$1
- _require_command $FIO_PROG
+ _require_command "$FIO_PROG" fio
if [ -z "$1" ]; then
return 1;
fi
[ $result -eq 0 ] || _notrun "$FSTYP does not support freezing"
}
+# Does shutdown work on this fs?
+_require_scratch_shutdown()
+{
+ [ -x src/godown ] || _notrun "src/godown executable not found"
+
+ _scratch_mkfs > /dev/null 2>&1
+ _scratch_mount
+ src/godown -f $SCRATCH_MNT 2>&1 \
+ || _notrun "$FSTYP does not support shutdown"
+ _scratch_unmount
+}
+
+# Does norecovery support by this fs?
+_require_norecovery()
+{
+ _scratch_mount -o ro,norecovery || \
+ _notrun "$FSTYP does not support norecovery"
+ _scratch_unmount
+}
+
+# Does this filesystem support metadata journaling?
+# We exclude ones here that don't; otherwise we assume that it does, so the
+# test will run, fail, and motivate someone to update this test for a new
+# filesystem.
+#
+# It's possible that TEST_DEV and SCRATCH_DEV have different features (it'd be
+# odd, but possible) so check $TEST_DEV by default, but we can optionall pass
+# any dev we want.
+_require_metadata_journaling()
+{
+ if [ -z $1 ]; then
+ DEV=$TEST_DEV
+ else
+ DEV=$1
+ fi
+
+ case "$FSTYP" in
+ ext2|vfat|msdos)
+ _notrun "$FSTYP does not support metadata journaling"
+ ;;
+ ext4)
+ # ext4 could be mkfs'd without a journal...
+ _require_dumpe2fs
+ $DUMPE2FS_PROG -h $DEV 2>&1 | grep -q has_journal || \
+ _notrun "$FSTYP on $DEV not configured with metadata journaling"
+ ;;
+ *)
+ # by default we pass; if you need to, add your fs above!
+ ;;
+ esac
+}
+
+# Does fiemap support?
+_require_fiemap()
+{
+ _require_xfs_io_command "fiemap"
+}
+
+_count_extents()
+{
+ res=`$XFS_IO_PROG -c "fiemap" $1 | tail -n +2`
+ echo $res | grep -v hole | wc -l | $AWK_PROG '{print $1}'
+}
+
+_count_holes()
+{
+ res=`$XFS_IO_PROG -c "fiemap" $1 | tail -n +2`
+ echo $res | grep hole | wc -l | $AWK_PROG '{print $1}'
+}
+
# arg 1 is dev to remove and is output of the below eg.
# ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
_devmgt_remove()
tdl=`echo ${1} | cut -d":" -f 2-|sed 's/:/ /g'`
echo ${tdl} > /sys/class/scsi_host/host${h}/scan || _fail "Add disk failed"
+
+ # ensure the device comes online
+ dev_back_oneline=0
+ for i in `seq 1 10`; do
+ if [ -d /sys/class/scsi_device/${1}/device/block ]; then
+ dev=`ls /sys/class/scsi_device/${1}/device/block`
+ for j in `seq 1 10`;
+ do
+ stat /dev/$dev > /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ dev_back_oneline=1
+ break
+ fi
+ sleep 1
+ done
+ break
+ else
+ sleep 1
+ fi
+ done
+ if [ $dev_back_oneline -eq 0 ]; then
+ echo "/dev/$dev online failed" >> $seqres.full
+ else
+ echo "/dev/$dev is back online" >> $seqres.full
+ fi
}
_require_fstrim()
fi
}
-_test_batched_discard()
+_require_batched_discard()
{
if [ $# -ne 1 ]; then
- echo "Usage: _test_batched_discard mnt_point" 1>&2
+ echo "Usage: _require_batched_discard mnt_point" 1>&2
exit 1
fi
_require_fstrim
- $FSTRIM_PROG ${1} &>/dev/null
+ $FSTRIM_PROG $1 > /dev/null 2>&1 || _notrun "FITRIM not supported on $1"
}
_require_dumpe2fs()
[ -x $FSSUM_PROG ] || _notrun "fssum not built"
}
+_require_cloner()
+{
+ CLONER_PROG=$here/src/cloner
+ [ -x $CLONER_PROG ] || \
+ _notrun "cloner binary not present at $CLONER_PROG"
+}
+
# Given 2 files, verify that they have the same mapping but different
# inodes - i.e. an undisturbed reflink
# Silent if so, make noise if not
|| echo "$1 and $2 are not reflinks: different extents"
}
+_require_atime()
+{
+ if [ "$FSTYP" == "nfs" ]; then
+ _notrun "atime related mount options have no effect on NFS"
+ fi
+}
+
_require_relatime()
{
_scratch_mkfs > /dev/null 2>&1
- _mount -t $FSTYP -o relatime $SCRATCH_DEV $SCRATCH_MNT || \
+ _scratch_mount -o relatime || \
_notrun "relatime not supported by the current kernel"
_scratch_unmount
}
+_require_userns()
+{
+ [ -x src/nsexec ] || _notrun "src/nsexec executable not found"
+ src/nsexec -U true 2>/dev/null || _notrun "userns not supported by this kernel"
+}
+
_create_loop_device()
{
file=$1
if [ $? -ne 0 ]; then
_notrun "Missing btrfs-progs send --stream-version command line option, skipped this test"
fi
+
+ # test if btrfs kernel supports send stream version 2
+ if [ ! -f /sys/fs/btrfs/send/stream_version ]; then
+ _notrun "Missing btrfs kernel patch for send stream version 2, skipped this test"
+ fi
+}
+
+_require_btrfs_mkfs_feature()
+{
+ if [ -z $1 ]; then
+ echo "Missing feature name argument for _require_btrfs_mkfs_feature"
+ exit 1
+ fi
+ feat=$1
+ $MKFS_BTRFS_PROG -O list-all 2>&1 | \
+ grep '^[ \t]*'"$feat"'\b' > /dev/null 2>&1
+ [ $? -eq 0 ] || \
+ _notrun "Feature $feat not supported in the available version of mkfs.btrfs"
+}
+
+_require_btrfs_fs_feature()
+{
+ if [ -z $1 ]; then
+ echo "Missing feature name argument for _require_btrfs_fs_feature"
+ exit 1
+ fi
+ feat=$1
+ modprobe btrfs > /dev/null 2>&1
+ [ -e /sys/fs/btrfs/features/$feat ] || \
+ _notrun "Feature $feat not supported by the available btrfs version"
+}
+
+_require_test_symlinks()
+{
+ # IRIX UDF does not support symlinks
+ [ "$HOSTOS" = "IRIX" -a "$FSTYP" = 'udf' ] && \
+ _notrun "Require symlinks support"
+ target=`mktemp -p $TEST_DIR`
+ link=`mktemp -p $TEST_DIR -u`
+ ln -s `basename $target` $link
+ if [ "$?" -ne 0 ]; then
+ rm -f $target
+ _notrun "Require symlinks support"
+ fi
+ rm -f $target $link
+}
+
+_require_test_fcntl_advisory_locks()
+{
+ [ "$FSTYP" != "cifs" ] && return 0
+ cat /proc/mounts | grep $TEST_DEV | grep cifs | grep -q "nobrl" && return 0
+ cat /proc/mounts | grep $TEST_DEV | grep cifs | grep -qE "nounix|forcemand" && \
+ _notrun "Require fcntl advisory locks support"
+}
+
+_get_total_inode()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _get_total_inode <mnt>"
+ exit 1
+ fi
+ local nr_inode;
+ nr_inode=`$DF_PROG -i $1 | tail -1 | awk '{print $3}'`
+ echo $nr_inode
+}
+
+_get_used_inode()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _get_used_inode <mnt>"
+ exit 1
+ fi
+ local nr_inode;
+ nr_inode=`$DF_PROG -i $1 | tail -1 | awk '{print $4}'`
+ echo $nr_inode
+}
+
+_get_used_inode_percent()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _get_used_inode_percent <mnt>"
+ exit 1
+ fi
+ local pct_inode;
+ pct_inode=`$DF_PROG -i $1 | tail -1 | awk '{ print $6 }' | \
+ sed -e 's/%//'`
+ echo $pct_inode
+}
+
+_get_free_inode()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _get_free_inode <mnt>"
+ exit 1
+ fi
+ local nr_inode;
+ nr_inode=`$DF_PROG -i $1 | tail -1 | awk '{print $5}'`
+ echo $nr_inode
+}
+
+# get the available space in bytes
+#
+_get_available_space()
+{
+ if [ -z "$1" ]; then
+ echo "Usage: _get_available_space <mnt>"
+ exit 1
+ fi
+ local avail_kb;
+ avail_kb=`$DF_PROG $1 | tail -n1 | awk '{ print $5 }'`
+ echo $((avail_kb * 1024))
+}
+
+# get btrfs profile configs being tested
+#
+# A set of pre-set profile configs are exported via _btrfs_profile_configs
+# array. Default configs can be overridden by setting BTRFS_PROFILE_CONFIGS
+# var in the format "metadata_profile:data_profile", multiple configs can be
+# seperated by space, e.g.
+# export BTRFS_PROFILE_CONFIGS="raid0:raid0 raid1:raid1 dup:single"
+_btrfs_get_profile_configs()
+{
+ if [ "$FSTYP" != "btrfs" ]; then
+ return
+ fi
+
+ # no user specified btrfs profile configs, export the default configs
+ if [ -z "$BTRFS_PROFILE_CONFIGS" ]; then
+ # default configs
+ _btrfs_profile_configs=(
+ "-m single -d single"
+ "-m dup -d single"
+ "-m raid0 -d raid0"
+ "-m raid1 -d raid0"
+ "-m raid1 -d raid1"
+ "-m raid10 -d raid10"
+ "-m raid5 -d raid5"
+ "-m raid6 -d raid6"
+ )
+
+ # remove dup/raid5/raid6 profiles if we're doing device replace
+ # dup profile indicates only one device being used (SCRATCH_DEV),
+ # but we don't want to replace SCRATCH_DEV, which will be used in
+ # _scratch_mount/_check_scratch_fs etc.
+ # and raid5/raid6 doesn't support replace yet
+ if [ "$1" == "replace" ]; then
+ _btrfs_profile_configs=(
+ "-m single -d single"
+ "-m raid0 -d raid0"
+ "-m raid1 -d raid0"
+ "-m raid1 -d raid1"
+ "-m raid10 -d raid10"
+ # add these back when raid5/6 is working with replace
+ #"-m raid5 -d raid5"
+ #"-m raid6 -d raid6"
+ )
+ fi
+ export _btrfs_profile_configs
+ return
+ fi
+
+ # parse user specified btrfs profile configs
+ local i=0
+ local cfg=""
+ for cfg in $BTRFS_PROFILE_CONFIGS; do
+ # turn "metadata:data" format to "-m metadata -d data"
+ # and assign it to _btrfs_profile_configs array
+ cfg=`echo "$cfg" | sed -e 's/^/-m /' -e 's/:/ -d /'`
+ _btrfs_profile_configs[$i]="$cfg"
+ let i=i+1
+ done
+
+ if [ "$1" == "replace" ]; then
+ if echo ${_btrfs_profile_configs[*]} | grep -q raid[56]; then
+ _notrun "RAID5/6 doesn't support btrfs device replace yet"
+ fi
+ if echo ${_btrfs_profile_configs[*]} | grep -q dup; then
+ _notrun "Do not set dup profile in btrfs device replace test"
+ fi
+ fi
+ export _btrfs_profile_configs
+}
+
+# stress btrfs by running balance operation in a loop
+_btrfs_stress_balance()
+{
+ local btrfs_mnt=$1
+ while true; do
+ $BTRFS_UTIL_PROG balance start $btrfs_mnt
+ done
+}
+
+# stress btrfs by creating/mounting/umounting/deleting subvolume in a loop
+_btrfs_stress_subvolume()
+{
+ local btrfs_dev=$1
+ local btrfs_mnt=$2
+ local subvol_name=$3
+ local subvol_mnt=$4
+
+ mkdir -p $subvol_mnt
+ while true; do
+ $BTRFS_UTIL_PROG subvolume create $btrfs_mnt/$subvol_name
+ $MOUNT_PROG -o subvol=$subvol_name $btrfs_dev $subvol_mnt
+ $UMOUNT_PROG $subvol_mnt
+ $BTRFS_UTIL_PROG subvolume delete $btrfs_mnt/$subvol_name
+ done
+}
+
+# stress btrfs by running scrub in a loop
+_btrfs_stress_scrub()
+{
+ local btrfs_mnt=$1
+ while true; do
+ $BTRFS_UTIL_PROG scrub start -B $btrfs_mnt
+ done
+}
+
+# stress btrfs by defragmenting every file/dir in a loop and compress file
+# contents while defragmenting if second argument is not "nocompress"
+_btrfs_stress_defrag()
+{
+ local btrfs_mnt=$1
+ local compress=$2
+
+ while true; do
+ if [ "$compress" == "nocompress" ]; then
+ find $btrfs_mnt \( -type f -o -type d \) -exec \
+ $BTRFS_UTIL_PROG filesystem defrag {} \;
+ else
+ find $btrfs_mnt \( -type f -o -type d \) -exec \
+ $BTRFS_UTIL_PROG filesystem defrag -clzo {} \;
+ find $btrfs_mnt \( -type f -o -type d \) -exec \
+ $BTRFS_UTIL_PROG filesystem defrag -czlib {} \;
+ fi
+ done
+}
+
+# stress btrfs by remounting it with different compression algorithms in a loop
+# run this with fsstress running at background could exercise the compression
+# code path and ensure no race when switching compression algorithm with constant
+# I/O activity.
+_btrfs_stress_remount_compress()
+{
+ local btrfs_mnt=$1
+ while true; do
+ for algo in no zlib lzo; do
+ $MOUNT_PROG -o remount,compress=$algo $btrfs_mnt
+ done
+ done
+}
+
+# stress btrfs by replacing devices in a loop
+# Note that at least 3 devices are needed in SCRATCH_DEV_POOL and the last
+# device should be free(not used by btrfs)
+_btrfs_stress_replace()
+{
+ local btrfs_mnt=$1
+
+ # The device number in SCRATCH_DEV_POOL should be at least 3,
+ # one is SCRATCH_DEV, one is to be replaced, one is free device
+ # we won't replace SCRATCH_DEV, see below for reason
+ if [ "`echo $SCRATCH_DEV_POOL | wc -w`" -lt 3 ]; then
+ echo "_btrfs_stress_replace requires at least 3 devices in SCRATCH_DEV_POOL"
+ return
+ fi
+
+ # take the last device as the first free_dev
+ local free_dev="`echo $SCRATCH_DEV_POOL | $AWK_PROG '{print $NF}'`"
+
+ # free_dev should be really free
+ if $BTRFS_UTIL_PROG filesystem show $btrfs_mnt | grep -q "$free_dev"; then
+ echo "_btrfs_stress_replace: $free_dev is used by btrfs"
+ return
+ fi
+
+ # dev_pool is device list being currently used by btrfs (excluding SCRATCH_DEV)
+ # and can be replaced. We don't replace SCRATCH_DEV because it will be used in
+ # _scratch_mount and _check_scratch_fs etc.
+ local dev_pool=`echo $SCRATCH_DEV_POOL | sed -e "s# *$SCRATCH_DEV *##" \
+ -e "s# *$free_dev *##"`
+
+ # set the first device in dev_pool as the first src_dev to be replaced
+ local src_dev=`echo $dev_pool | $AWK_PROG '{print $1}'`
+
+ echo "dev_pool=$dev_pool"
+ echo "free_dev=$free_dev, src_dev=$src_dev"
+ while true; do
+ echo "Replacing $src_dev with $free_dev"
+ $BTRFS_UTIL_PROG replace start -fB $src_dev $free_dev $btrfs_mnt
+ if [ $? -ne 0 ]; then
+ # don't update src_dev and free_dev if replace failed
+ continue
+ fi
+ dev_pool="$dev_pool $free_dev"
+ dev_pool=`echo $dev_pool | sed -e "s# *$src_dev *##"`
+ free_dev=$src_dev
+ src_dev=`echo $dev_pool | $AWK_PROG '{print $1}'`
+ done
+}
+
+# find the right option to force output in bytes, older versions of btrfs-progs
+# print that by default, newer print human readable numbers with unit suffix
+_btrfs_qgroup_units()
+{
+ $BTRFS_UTIL_PROG qgroup show --help 2>&1 | grep -q -- --raw && echo "--raw"
+}
+
+# return device size in kb
+_get_device_size()
+{
+ grep `_short_dev $1` /proc/partitions | awk '{print $3}'
+}
+
+# don't check dmesg log after test
+_disable_dmesg_check()
+{
+ rm -f ${RESULT_DIR}/check_dmesg
}
init_rc()
# Figure out if we need to add -F ("foreign", deprecated) option to xfs_io
xfs_io -c stat $TEST_DIR 2>&1 | grep -q "is not on an XFS filesystem" && \
export XFS_IO_PROG="$XFS_IO_PROG -F"
+
+ # xfs_copy doesn't work on v5 xfs yet without -d option
+ if [ "$FSTYP" == "xfs" ] && [[ $MKFS_OPTIONS =~ crc=1 ]]; then
+ export XFS_COPY_PROG="$XFS_COPY_PROG -d"
+ fi
}
# get real device path name by following link
echo `basename $(_real_dev $1)`
}
+_sysfs_dev()
+{
+ local _dev=$1
+ local _maj=$(stat -c%t $_dev | tr [:lower:] [:upper:])
+ local _min=$(stat -c%T $_dev | tr [:lower:] [:upper:])
+ _maj=$(echo "ibase=16; $_maj" | bc)
+ _min=$(echo "ibase=16; $_min" | bc)
+ echo /sys/dev/block/$_maj:$_min
+}
+
+get_block_size()
+{
+ if [ -z $1 ] || [ ! -d $1 ]; then
+ echo "Missing mount point argument for get_block_size"
+ exit 1
+ fi
+ echo `stat -f -c %S $1`
+}
+
init_rc
################################################################################