Files
apfstests/common/xfs
T
Darrick J. Wong 2fd273886b xfs: refactor minimum log size formatting code
Create a new helper function to discover the minimum log size that will
work with the mkfs options provided, then remove all the hardcoded block
sizes from various xfs tests.  This will be necessary when we turn on
reflink or rmap by default and the minimum log size increases.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Tested-by: Yang Xu<xuyang2018.jy@cn.fujitsu.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
2019-05-10 17:29:57 +08:00

853 lines
22 KiB
Plaintext

#
# XFS specific common functions.
#
_setup_large_xfs_fs()
{
fs_size=$1
local tmp_dir=/tmp/
[ "$LARGE_SCRATCH_DEV" != yes ] && return 0
[ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0
[ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0
# calculate the size of the file we need to allocate.
# Default free space in the FS is 50GB, but you can specify more via
# SCRATCH_DEV_EMPTY_SPACE
file_size=$(($fs_size - 50*1024*1024*1024))
file_size=$(($file_size - $SCRATCH_DEV_EMPTY_SPACE))
# mount the filesystem, create the file, unmount it
_try_scratch_mount 2>&1 >$tmp_dir/mnt.err
local status=$?
if [ $status -ne 0 ]; then
echo "mount failed"
cat $tmp_dir/mnt.err >&2
rm -f $tmp_dir/mnt.err
return $status
fi
rm -f $tmp_dir/mnt.err
xfs_io -F -f \
-c "truncate $file_size" \
-c "falloc -k 0 $file_size" \
-c "chattr +d" \
$SCRATCH_MNT/.use_space 2>&1 > /dev/null
export NUM_SPACE_FILES=1
status=$?
_scratch_unmount
if [ $status -ne 0 ]; then
echo "large file prealloc failed"
cat $tmp_dir/mnt.err >&2
return $status
fi
return 0
}
_scratch_mkfs_xfs_opts()
{
mkfs_opts=$*
# remove metadata related mkfs options if mkfs.xfs doesn't them
if [ -n "$XFS_MKFS_HAS_NO_META_SUPPORT" ]; then
mkfs_opts=`echo $mkfs_opts | sed "s/-m\s\+\S\+//g"`
fi
_scratch_options mkfs
echo "$MKFS_XFS_PROG $SCRATCH_OPTIONS $mkfs_opts"
}
_scratch_mkfs_xfs_supported()
{
local mkfs_opts=$*
_scratch_options mkfs
$MKFS_XFS_PROG -N $MKFS_OPTIONS $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
local mkfs_status=$?
# a mkfs failure may be caused by conflicts between $MKFS_OPTIONS and
# $mkfs_opts, try again without $MKFS_OPTIONS
if [ $mkfs_status -ne 0 -a -n "$mkfs_opts" ]; then
$MKFS_XFS_PROG -N $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
mkfs_status=$?
fi
return $mkfs_status
}
# Returns the minimum XFS log size, in units of log blocks.
_scratch_find_xfs_min_logblocks()
{
local mkfs_cmd="`_scratch_mkfs_xfs_opts`"
# The smallest log size we can specify is 2M (XFS_MIN_LOG_BYTES) so
# pass that in and see if mkfs succeeds or tells us what is the
# minimum log size.
local XFS_MIN_LOG_BYTES=2097152
_scratch_do_mkfs "$mkfs_cmd" "cat" $* -N -l size=$XFS_MIN_LOG_BYTES \
2>$tmp.mkfserr 1>$tmp.mkfsstd
local mkfs_status=$?
# mkfs suceeded, so we must pick out the log block size to do the
# unit conversion
if [ $mkfs_status -eq 0 ]; then
local blksz="$(grep '^log.*bsize' $tmp.mkfsstd | \
sed -e 's/log.*bsize=\([0-9]*\).*$/\1/g')"
echo $((XFS_MIN_LOG_BYTES / blksz))
return
fi
# Usually mkfs will tell us the minimum log size...
if grep -q 'minimum size is' $tmp.mkfserr; then
grep 'minimum size is' $tmp.mkfserr | \
sed -e 's/^.*minimum size is \([0-9]*\) blocks/\1/g'
return
fi
# Don't know what to do, so fail
echo "Cannot determine minimum log size" >&2
cat $tmp.mkfsstd >> $seqres.full
cat $tmp.mkfserr >> $seqres.full
}
_scratch_mkfs_xfs()
{
local mkfs_cmd="`_scratch_mkfs_xfs_opts`"
local mkfs_filter="sed -e '/less than device physical sector/d' \
-e '/switching to logical sector/d' \
-e '/Default configuration/d'"
local tmp=`mktemp -u`
local mkfs_status
_scratch_do_mkfs "$mkfs_cmd" "$mkfs_filter" $* 2>$tmp.mkfserr 1>$tmp.mkfsstd
mkfs_status=$?
grep -q crc=0 $tmp.mkfsstd && _force_xfsv4_mount_options
if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
# manually parse the mkfs output to get the fs size in bytes
local fs_size
fs_size=`cat $tmp.mkfsstd | perl -ne '
if (/^data\s+=\s+bsize=(\d+)\s+blocks=(\d+)/) {
my $size = $1 * $2;
print STDOUT "$size\n";
}'`
_setup_large_xfs_fs $fs_size
mkfs_status=$?
fi
# output mkfs stdout and stderr
cat $tmp.mkfsstd
cat $tmp.mkfserr >&2
rm -f $tmp.mkfserr $tmp.mkfsstd
return $mkfs_status
}
# xfs_check script is planned to be deprecated. But, we want to
# be able to invoke "xfs_check" behavior in xfstests in order to
# maintain the current verification levels.
_xfs_check()
{
OPTS=" "
DBOPTS=" "
USAGE="Usage: xfs_check [-fsvV] [-l logdev] [-i ino]... [-b bno]... special"
OPTIND=1
while getopts "b:fi:l:stvV" c; do
case $c in
s) OPTS=$OPTS"-s ";;
t) OPTS=$OPTS"-t ";;
v) OPTS=$OPTS"-v ";;
i) OPTS=$OPTS"-i "$OPTARG" ";;
b) OPTS=$OPTS"-b "$OPTARG" ";;
f) DBOPTS=$DBOPTS" -f";;
l) DBOPTS=$DBOPTS" -l "$OPTARG" ";;
V) $XFS_DB_PROG -p xfs_check -V
return $?
;;
esac
done
set -- extra $@
shift $OPTIND
case $# in
1) ${XFS_DB_PROG}${DBOPTS} -F -i -p xfs_check -c "check$OPTS" $1
status=$?
;;
2) echo $USAGE 1>&1
status=2
;;
esac
return $status
}
_scratch_xfs_db_options()
{
SCRATCH_OPTIONS=""
[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
echo $SCRATCH_OPTIONS $* $SCRATCH_DEV
}
_scratch_xfs_db()
{
$XFS_DB_PROG "$@" $(_scratch_xfs_db_options)
}
_scratch_xfs_logprint()
{
SCRATCH_OPTIONS=""
[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
$XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
}
_test_xfs_logprint()
{
TEST_OPTIONS=""
[ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
TEST_OPTIONS="-l$TEST_LOGDEV"
$XFS_LOGPRINT_PROG $TEST_OPTIONS $* $TEST_DEV
}
_scratch_xfs_check()
{
SCRATCH_OPTIONS=""
[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
SCRATCH_OPTIONS="-l $SCRATCH_LOGDEV"
[ "$LARGE_SCRATCH_DEV" = yes ] && \
SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
_xfs_check $SCRATCH_OPTIONS $* $SCRATCH_DEV
}
_scratch_xfs_repair()
{
SCRATCH_OPTIONS=""
[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
[ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -r$SCRATCH_RTDEV"
$XFS_REPAIR_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
}
# this test requires the projid32bit feature to be available in mkfs.xfs.
#
_require_projid32bit()
{
_scratch_mkfs_xfs_supported -i projid32bit=1 >/dev/null 2>&1 \
|| _notrun "mkfs.xfs doesn't have projid32bit feature"
}
_require_projid16bit()
{
_scratch_mkfs_xfs_supported -i projid32bit=0 >/dev/null 2>&1 \
|| _notrun "16 bit project IDs not supported on $SCRATCH_DEV"
}
# this test requires the crc feature to be available in mkfs.xfs
#
_require_xfs_mkfs_crc()
{
_scratch_mkfs_xfs_supported -m crc=1 >/dev/null 2>&1 \
|| _notrun "mkfs.xfs doesn't have crc feature"
}
# this test requires the xfs kernel support crc feature
#
_require_xfs_crc()
{
_scratch_mkfs_xfs -m crc=1 >/dev/null 2>&1
_try_scratch_mount >/dev/null 2>&1 \
|| _notrun "Kernel doesn't support crc feature"
_scratch_unmount
}
# this test requires the xfs kernel support crc feature on scratch device
#
_require_scratch_xfs_crc()
{
_scratch_mkfs_xfs >/dev/null 2>&1
_try_scratch_mount >/dev/null 2>&1 \
|| _notrun "Kernel doesn't support crc feature"
$XFS_INFO_PROG $SCRATCH_MNT | grep -q 'crc=1' || _notrun "crc feature not supported by this filesystem"
_scratch_unmount
}
# this test requires the finobt feature to be available in mkfs.xfs
#
_require_xfs_mkfs_finobt()
{
_scratch_mkfs_xfs_supported -m crc=1,finobt=1 >/dev/null 2>&1 \
|| _notrun "mkfs.xfs doesn't have finobt feature"
}
# this test requires the xfs kernel support finobt feature
#
_require_xfs_finobt()
{
_scratch_mkfs_xfs -m crc=1,finobt=1 >/dev/null 2>&1
_try_scratch_mount >/dev/null 2>&1 \
|| _notrun "Kernel doesn't support finobt feature"
_scratch_unmount
}
# 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
_try_scratch_mount >/dev/null 2>&1 \
|| _notrun "kernel does not support sparse inodes"
_scratch_unmount
}
# check that xfs_db supports a specific command
_require_xfs_db_command()
{
if [ $# -ne 1 ]; then
echo "Usage: _require_xfs_db_command command" 1>&2
exit 1
fi
command=$1
_scratch_mkfs_xfs >/dev/null 2>&1
_scratch_xfs_db -x -c "help" | grep $command > /dev/null || \
_notrun "xfs_db $command support is missing"
}
# Does the filesystem mounted from a particular device support scrub?
_supports_xfs_scrub()
{
local mountpoint="$1"
local device="$2"
if [ -z "$device" ] || [ -z "$mountpoint" ]; then
echo "Usage: _supports_xfs_scrub mountpoint device"
return 1
fi
if [ ! -b "$device" ] || [ ! -e "$mountpoint" ]; then
return 1
fi
test "$FSTYP" = "xfs" || return 1
test -x "$XFS_SCRUB_PROG" || return 1
# Probe for kernel support...
$XFS_IO_PROG -c 'help scrub' 2>&1 | grep -q 'types are:.*probe' || return 1
$XFS_IO_PROG -c "scrub probe" "$mountpoint" 2>&1 | grep -q "Inappropriate ioctl" && return 1
# Scrub can't run on norecovery mounts
_fs_options "$device" | grep -q "norecovery" && return 1
return 0
}
# run xfs_check and friends on a FS.
_check_xfs_filesystem()
{
if [ $# -ne 3 ]; then
echo "Usage: _check_xfs_filesystem device <logdev>|none <rtdev>|none" 1>&2
exit 1
fi
extra_mount_options=""
extra_log_options=""
extra_options=""
device=$1
if [ -f $device ]; then
extra_options="-f"
fi
if [ "$2" != "none" ]; then
extra_log_options="-l$2"
extra_mount_options="-ologdev=$2"
fi
if [ "$3" != "none" ]; then
extra_rt_options="-r$3"
extra_mount_options=$extra_mount_options" -ortdev=$3"
fi
extra_mount_options=$extra_mount_options" $MOUNT_OPTIONS"
[ "$FSTYP" != xfs ] && return 0
type=`_fs_type $device`
ok=1
# Run online scrub if we can.
mntpt="$(_is_dev_mounted $device)"
if [ -n "$mntpt" ] && _supports_xfs_scrub "$mntpt" "$device"; then
"$XFS_SCRUB_PROG" $scrubflag -v -d -n $mntpt > $tmp.scrub 2>&1
if [ $? -ne 0 ]; then
_log_err "_check_xfs_filesystem: filesystem on $device failed scrub"
echo "*** xfs_scrub $scrubflag -v -d -n output ***" >> $seqres.full
cat $tmp.scrub >> $seqres.full
echo "*** end xfs_scrub output" >> $serqres.full
ok=0
fi
rm -f $tmp.scrub
fi
if [ "$type" = "xfs" ]; then
# mounted ...
mountpoint=`_umount_or_remount_ro $device`
fi
$XFS_LOGPRINT_PROG -t $extra_log_options $device 2>&1 \
| tee $tmp.logprint | grep -q "<CLEAN>"
if [ $? -ne 0 -a "$HOSTOS" = "Linux" ]; then
_log_err "_check_xfs_filesystem: filesystem on $device has dirty log"
echo "*** xfs_logprint -t output ***" >>$seqres.full
cat $tmp.logprint >>$seqres.full
echo "*** end xfs_logprint output" >>$seqres.full
ok=0
fi
# xfs_check runs out of memory on large files, so even providing the test
# option (-t) to avoid indexing the free space trees doesn't make it pass on
# large filesystems. Avoid it.
if [ "$LARGE_SCRATCH_DEV" != yes ]; then
_xfs_check $extra_log_options $device 2>&1 > $tmp.fs_check
fi
if [ -s $tmp.fs_check ]; then
_log_err "_check_xfs_filesystem: filesystem on $device is inconsistent (c)"
echo "*** xfs_check output ***" >>$seqres.full
cat $tmp.fs_check >>$seqres.full
echo "*** end xfs_check output" >>$seqres.full
ok=0
fi
$XFS_REPAIR_PROG -n $extra_options $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
if [ $? -ne 0 ]; then
_log_err "_check_xfs_filesystem: filesystem on $device is inconsistent (r)"
echo "*** xfs_repair -n output ***" >>$seqres.full
cat $tmp.repair >>$seqres.full
echo "*** end xfs_repair output" >>$seqres.full
ok=0
fi
rm -f $tmp.fs_check $tmp.logprint $tmp.repair
# Optionally test the index rebuilding behavior.
if [ -n "$TEST_XFS_REPAIR_REBUILD" ]; then
$XFS_REPAIR_PROG $extra_options $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
if [ $? -ne 0 ]; then
_log_err "_check_xfs_filesystem: filesystem on $device is inconsistent (rebuild)"
echo "*** xfs_repair output ***" >>$seqres.full
cat $tmp.repair >>$seqres.full
echo "*** end xfs_repair output" >>$seqres.full
ok=0
fi
rm -f $tmp.repair
$XFS_REPAIR_PROG -n $extra_options $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
if [ $? -ne 0 ]; then
_log_err "_check_xfs_filesystem: filesystem on $device is inconsistent (rebuild-reverify)"
echo "*** xfs_repair -n output ***" >>$seqres.full
cat $tmp.repair >>$seqres.full
echo "*** end xfs_repair output" >>$seqres.full
ok=0
fi
rm -f $tmp.repair
fi
if [ $ok -eq 0 ]; then
echo "*** mount output ***" >>$seqres.full
_mount >>$seqres.full
echo "*** end mount output" >>$seqres.full
elif [ "$type" = "xfs" ]; then
_mount_or_remount_rw "$extra_mount_options" $device $mountpoint
fi
if [ $ok -eq 0 ]; then
status=1
if [ "$iam" != "check" ]; then
exit 1
fi
return 1
fi
return 0
}
_check_xfs_test_fs()
{
TEST_LOG="none"
TEST_RT="none"
[ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
TEST_LOG="$TEST_LOGDEV"
[ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
TEST_RT="$TEST_RTDEV"
_check_xfs_filesystem $TEST_DEV $TEST_LOG $TEST_RT
return $?
}
_require_xfs_test_rmapbt()
{
_require_test
if [ "$($XFS_INFO_PROG "$TEST_DIR" | grep -c "rmapbt=1")" -ne 1 ]; then
_notrun "rmapbt not supported by test filesystem type: $FSTYP"
fi
}
_require_xfs_scratch_rmapbt()
{
_require_scratch
_scratch_mkfs > /dev/null
_scratch_mount
if [ "$($XFS_INFO_PROG "$SCRATCH_MNT" | grep -c "rmapbt=1")" -ne 1 ]; then
_scratch_unmount
_notrun "rmapbt not supported by scratch filesystem type: $FSTYP"
fi
_scratch_unmount
}
_xfs_bmapx_find()
{
case "$1" in
"attr")
param="a"
;;
"cow")
param="c"
;;
*)
param="e"
;;
esac
shift
file="$1"
shift
$XFS_IO_PROG -c "bmap -${param}lpv" "$file" | grep -c "$@"
}
# Reset all xfs error handling attributes, set them to original
# status.
#
# Only one argument, and it's mandatory:
# - dev: device name, e.g. $SCRATCH_DEV
#
# Note: this function only works for XFS
_reset_xfs_sysfs_error_handling()
{
local dev=$1
if [ ! -b "$dev" -o "$FSTYP" != "xfs" ]; then
_fail "Usage: reset_xfs_sysfs_error_handling <device>"
fi
_set_fs_sysfs_attr $dev error/fail_at_unmount 1
echo -n "error/fail_at_unmount="
_get_fs_sysfs_attr $dev error/fail_at_unmount
# Make sure all will be configured to retry forever by default, except
# for ENODEV, which is an unrecoverable error, so it will be configured
# to not retry on error by default.
for e in default EIO ENOSPC; do
_set_fs_sysfs_attr $dev \
error/metadata/${e}/max_retries -1
echo -n "error/metadata/${e}/max_retries="
_get_fs_sysfs_attr $dev error/metadata/${e}/max_retries
_set_fs_sysfs_attr $dev \
error/metadata/${e}/retry_timeout_seconds 0
echo -n "error/metadata/${e}/retry_timeout_seconds="
_get_fs_sysfs_attr $dev \
error/metadata/${e}/retry_timeout_seconds
done
}
# Skip if we are running an older binary without the stricter input checks.
# Make multiple checks to be sure that there is no regression on the one
# selected feature check, which would skew the result.
#
# At first, make a common function that runs the tests and returns
# number of failed cases.
_xfs_mkfs_validation_check()
{
local tmpfile=`mktemp`
local cmd="$MKFS_XFS_PROG -f -N -d file,name=$tmpfile,size=1g"
$cmd -s size=8s >/dev/null 2>&1
local sum=$?
$cmd -l version=2,su=260k >/dev/null 2>&1
sum=`expr $sum + $?`
rm -f $tmpfile
return $sum
}
# Skip the test if all calls passed - mkfs accepts invalid input
_require_xfs_mkfs_validation()
{
_xfs_mkfs_validation_check
if [ "$?" -eq 0 ]; then
_notrun "Requires newer mkfs with stricter input checks: the oldest supported version of xfsprogs is 4.7."
fi
}
# The opposite of _require_xfs_mkfs_validation.
_require_xfs_mkfs_without_validation()
{
_xfs_mkfs_validation_check
if [ "$?" -ne 0 ]; then
_notrun "Requires older mkfs without strict input checks: the last supported version of xfsprogs is 4.5."
fi
}
# XFS ability to change UUIDs on V5/CRC filesystems
#
_require_meta_uuid()
{
# This will create a crc fs on $SCRATCH_DEV
_require_xfs_crc
_scratch_xfs_db -x -c "uuid restore" 2>&1 \
| grep -q "invalid UUID\|supported on V5 fs" \
&& _notrun "Userspace doesn't support meta_uuid feature"
_scratch_xfs_db -x -c "uuid generate" >/dev/null 2>&1
_try_scratch_mount >/dev/null 2>&1 \
|| _notrun "Kernel doesn't support meta_uuid feature"
_scratch_unmount
}
# this test requires mkfs.xfs have case-insensitive naming support
_require_xfs_mkfs_ciname()
{
_scratch_mkfs_xfs_supported -n version=ci >/dev/null 2>&1 \
|| _notrun "need case-insensitive naming support in mkfs.xfs"
}
# XFS_DEBUG requirements
_require_xfs_debug()
{
if grep -q "debug 0" /proc/fs/xfs/stat; then
_notrun "Require XFS built with CONFIG_XFS_DEBUG"
fi
}
_require_no_xfs_debug()
{
if grep -q "debug 1" /proc/fs/xfs/stat; then
_notrun "Require XFS built without CONFIG_XFS_DEBUG"
fi
}
# Require that assertions will not crash the system.
#
# Assertions would always crash the system if XFS assert fatal was enabled
# (CONFIG_XFS_ASSERT_FATAL=y). If a test is designed to trigger an assertion,
# skip the test on a CONFIG_XFS_ASSERT_FATAL built XFS by default. Note:
# CONFIG_XFS_ASSERT_FATAL can be disabled by setting bug_on_assert to zero if
# we want test to run.
_require_no_xfs_bug_on_assert()
{
if [ -f /sys/fs/xfs/debug/bug_on_assert ]; then
grep -q "1" /sys/fs/xfs/debug/bug_on_assert && \
_notrun "test requires XFS bug_on_assert to be off, turn it off to run the test"
else
# Note: Prior to the creation of CONFIG_XFS_ASSERT_FATAL (and
# the sysfs knob bug_on_assert), assertions would always crash
# the system if XFS debug was enabled (CONFIG_XFS_DEBUG=y). If
# a test is designed to trigger an assertion and the test
# designer does not want to hang fstests, skip the test.
_require_no_xfs_debug
fi
}
# Get a metadata field
# The first arg is the field name
# The rest of the arguments are xfs_db commands to find the metadata.
_scratch_xfs_get_metadata_field()
{
local key="$1"
shift
local grep_key="$(echo "${key}" | tr '[]()' '....')"
local cmds=()
local arg
for arg in "$@"; do
cmds+=("-c" "${arg}")
done
_scratch_xfs_db "${cmds[@]}" -c "print ${key}" | grep "^${grep_key}" | \
sed -e 's/^.* = //g'
}
# Set a metadata field
# The first arg is the field name
# The second arg is the new value
# The rest of the arguments are xfs_db commands to find the metadata.
_scratch_xfs_set_metadata_field()
{
local key="$1"
local value="$2"
shift; shift
local cmds=()
local arg
for arg in "$@"; do
cmds+=("-c" "${arg}")
done
local wr_cmd="write"
_scratch_xfs_db -x -c "help write" | egrep -q "(-c|-d)" && value="-- ${value}"
_scratch_xfs_db -x -c "help write" | egrep -q "(-d)" && wr_cmd="${wr_cmd} -d"
_scratch_xfs_db -x "${cmds[@]}" -c "${wr_cmd} ${key} ${value}"
}
_scratch_xfs_get_sb_field()
{
_scratch_xfs_get_metadata_field "$1" "sb 0"
}
_scratch_xfs_set_sb_field()
{
_scratch_xfs_set_metadata_field "$1" "$2" "sb 0"
}
# Before xfsprogs commit 4222d000ed("db: write via array indexing doesn't
# work"), xfs_db command to write a specific AGFL index doesn't work. It's a
# bug in a diagnostic tool that is only used by XFS developers as a test
# infrastructure, so it's fine to treat it as a infrastructure dependency as
# all other _require rules.
_require_xfs_db_write_array()
{
local supported=0
_require_test
touch $TEST_DIR/$seq.img
$MKFS_XFS_PROG -d file,name=$TEST_DIR/$seq.img,size=512m >/dev/null 2>&1
$XFS_DB_PROG -x -c "agfl 0" -c "write bno[32] 78" $TEST_DIR/$seq.img \
>/dev/null 2>&1
$XFS_DB_PROG -x -c "agfl 0" -c "print bno[32]" $TEST_DIR/$seq.img \
| grep -q "bno\[32\] = 78" && supported=1
rm -f $TEST_DIR/$seq.img
[ $supported -eq 0 ] && _notrun "xfs_db write can't support array"
}
_require_xfs_spaceman_command()
{
if [ -z "$1" ]; then
echo "Usage: _require_xfs_spaceman_command command [switch]" 1>&2
exit 1
fi
local command=$1
shift
local param="$*"
local param_checked=0
local opts=""
_require_command "$XFS_SPACEMAN_PROG" "xfs_spaceman"
testfile=$TEST_DIR/$$.xfs_spaceman
case $command in
*)
testio=`$XFS_SPACEMAN_PROG -c "help $command" $TEST_DIR 2>&1`
esac
rm -f $testfile 2>&1 > /dev/null
echo $testio | grep -q "not found" && \
_notrun "xfs_spaceman $command support is missing"
echo $testio | grep -q "Operation not supported" && \
_notrun "xfs_spaceman $command failed (old kernel/wrong fs?)"
echo $testio | grep -q "Invalid" && \
_notrun "xfs_spaceman $command failed (old kernel/wrong fs/bad args?)"
echo $testio | grep -q "foreign file active" && \
_notrun "xfs_spaceman $command not supported on $FSTYP"
echo $testio | grep -q "Function not implemented" && \
_notrun "xfs_spaceman $command support is missing (missing syscall?)"
[ -n "$param" ] || return
if [ $param_checked -eq 0 ]; then
$XFS_SPACEMAN_PROG -c "help $command" | grep -q "^ $param --" || \
_notrun "xfs_spaceman $command doesn't support $param"
fi
}
_scratch_get_sfdir_prefix() {
local dir_ino="$1"
for prefix in "u.sfdir3" "u.sfdir2" "u3.sfdir3"; do
if [ -n "$(_scratch_xfs_get_metadata_field \
"${prefix}.hdr.parent.i4" \
"inode ${dir_ino}")" ]; then
echo "${prefix}"
return 0
fi
done
_scratch_xfs_db -c "inode ${dir_ino}" -c 'p' >> $seqres.full
return 1
}
_scratch_get_bmx_prefix() {
local ino="$1"
for prefix in "u3.bmx" "u.bmx"; do
if [ -n "$(_scratch_xfs_get_metadata_field \
"${prefix}[0].startblock" \
"inode ${ino}")" ]; then
echo "${prefix}"
return 0
fi
done
_scratch_xfs_db -c "inode ${ino}" -c 'p' >> $seqres.full
return 1
}
#
# Ensures that we don't pass any mount options incompatible with XFS v4
#
_force_xfsv4_mount_options()
{
local gquota=0
local pquota=0
# Can't have group and project quotas in XFS v4
echo "$MOUNT_OPTIONS" | egrep -q "(gquota|grpquota|grpjquota=|gqnoenforce)" && gquota=1
echo "$MOUNT_OPTIONS" | egrep -q "(\bpquota|prjquota|pqnoenforce)" && pquota=1
if [ $gquota -gt 0 ] && [ $pquota -gt 0 ]; then
export MOUNT_OPTIONS=$(echo $MOUNT_OPTIONS \
| sed -e 's/gquota/QUOTA/g' \
-e 's/grpquota/QUOTA/g' \
-e 's/grpjquota=[^, ]/QUOTA/g' \
-e 's/gqnoenforce/QUOTA/g' \
-e "s/QUOTA/defaults/g")
fi
echo "MOUNT_OPTIONS = $MOUNT_OPTIONS" >>$seqres.full
}