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
{
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
_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
}
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
fi
;;
*)
- if [ -z "$TEST_DEV" -o "`_is_block_dev $TEST_DEV`" = "" ]
+ 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`" ]
+ if [ "`_is_block_dev "$SCRATCH_DEV"`" = "`_is_block_dev "$TEST_DEV"`" ]
then
_notrun "this test requires a valid \$TEST_DEV"
fi
# 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
echo "Usage: _require_block_device <dev>" 1>&2
exit 1
fi
- if [ "`_is_block_dev $SCRATCH_DEV`" == "" ]; then
+ 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 SCRATCH_DEV to be a valid block device
- _require_block_device $SCRATCH_DEV
- _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.
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()
"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`
;;
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
_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()
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 $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
grep `_short_dev $1` /proc/partitions | awk '{print $3}'
}
+# check dmesg log for WARNING/Oops/etc.
+_check_dmesg()
+{
+ if [ ! -f ${RESULT_DIR}/check_dmesg ]; then
+ return 0
+ fi
+ rm -f ${RESULT_DIR}/check_dmesg
+
+ # default filter is a simple cat command, caller could provide a
+ # customized filter and pass the name through the first argument, to
+ # filter out intentional WARNINGs or Oopses
+ filter=${1:-cat}
+
+ # search the dmesg log of last run of $seqnum for possible failures
+ # use sed \cregexpc address type, since $seqnum contains "/"
+ dmesg | tac | sed -ne "0,\#run fstests $seqnum at $date_time#p" | \
+ tac | $filter >$seqres.dmesg
+ grep -q -e "kernel BUG at" \
+ -e "WARNING:" \
+ -e "BUG:" \
+ -e "Oops:" \
+ -e "possible recursive locking detected" \
+ -e "Internal error" \
+ $seqres.dmesg
+ if [ $? -eq 0 ]; then
+ echo "_check_dmesg: something found in dmesg (see $seqres.dmesg)"
+ return 1
+ else
+ rm -f $seqres.dmesg
+ return 0
+ fi
+}
+
# don't check dmesg log after test
_disable_dmesg_check()
{
# 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