mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
e11c519918
Save testcase data which later may be used by report generators - Save failure reason to $err_msg variable - Save number of notrun tests to $n_notrun counter, similar to $n_try,$n_bad Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> Reviewed-by: Eryu Guan <eguan@redhat.com> Signed-off-by: Eryu Guan <eguan@redhat.com>
371 lines
9.8 KiB
Plaintext
371 lines
9.8 KiB
Plaintext
#
|
|
# Common btrfs specific functions
|
|
#
|
|
|
|
_btrfs_get_subvolid()
|
|
{
|
|
mnt=$1
|
|
name=$2
|
|
|
|
$BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
|
|
}
|
|
|
|
# _require_btrfs_command <command> [<subcommand>|<option>]
|
|
# We check for btrfs and (optionally) features of the btrfs command
|
|
# It can both subfunction like "inspect-internal dump-tree" and
|
|
# options like "check --qgroup-report"
|
|
_require_btrfs_command()
|
|
{
|
|
local cmd=$1
|
|
local param=$2
|
|
local safe_param
|
|
|
|
_require_command "$BTRFS_UTIL_PROG" btrfs
|
|
if [ -z "$1" ]; then
|
|
return 1;
|
|
fi
|
|
$BTRFS_UTIL_PROG $cmd --help &> /dev/null
|
|
[ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd)"
|
|
|
|
test -z "$param" && return
|
|
|
|
# If $param is an option, replace leading "-"s for grep
|
|
if [ ${param:0:1} == "-" ]; then
|
|
safe_param=$(echo $param | sed 's/^-*//')
|
|
$BTRFS_UTIL_PROG $cmd --help | grep -wq $safe_param || \
|
|
_notrun "$BTRFS_UTIL_PROG too old (must support $cmd $param)"
|
|
return
|
|
fi
|
|
|
|
$BTRFS_UTIL_PROG $cmd $param --help &> /dev/null
|
|
[ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd $param)"
|
|
}
|
|
|
|
# Require extra check on btrfs qgroup numbers
|
|
_require_btrfs_qgroup_report()
|
|
{
|
|
_require_btrfs_command check --qgroup-report
|
|
touch ${RESULT_DIR}/require_scratch.require_qgroup_report
|
|
}
|
|
|
|
_require_btrfs_dump_super()
|
|
{
|
|
if [ ! -x "$BTRFS_SHOW_SUPER_PROG" ]; then
|
|
_require_command "$BTRFS_UTIL_PROG" btrfs
|
|
if ! $BTRFS_UTIL_PROG inspect-internal dump-super --help >& /dev/null; then
|
|
_notrun "Missing btrfs-show-super or inspect-internal dump-super"
|
|
fi
|
|
BTRFS_SHOW_SUPER_PROG="$BTRFS_UTIL_PROG inspect-internal dump-super"
|
|
fi
|
|
}
|
|
|
|
_run_btrfs_util_prog()
|
|
{
|
|
run_check $BTRFS_UTIL_PROG $*
|
|
}
|
|
|
|
_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"
|
|
}
|
|
|
|
_check_btrfs_filesystem()
|
|
{
|
|
device=$1
|
|
|
|
# If type is set, we're mounted
|
|
type=`_fs_type $device`
|
|
ok=1
|
|
|
|
if [ "$type" = "$FSTYP" ]; then
|
|
# mounted ...
|
|
mountpoint=`_umount_or_remount_ro $device`
|
|
fi
|
|
|
|
if [ -f ${RESULT_DIR}/require_scratch.require_qgroup_report ]; then
|
|
$BTRFS_UTIL_PROG check $device --qgroup-report > $tmp.qgroup_report 2>&1
|
|
if grep -qE "Counts for qgroup.*are different" $tmp.qgroup_report ; then
|
|
_log_err "_check_btrfs_filesystem: filesystem on $device has wrong qgroup numbers"
|
|
echo "*** qgroup_report.$FSTYP output ***" >>$seqres.full
|
|
cat $tmp.qgroup_report >>$seqres.full
|
|
echo "*** qgroup_report.$FSTYP output ***" >>$seqres.full
|
|
fi
|
|
rm -f $tmp.qgroup_report
|
|
fi
|
|
|
|
$BTRFS_UTIL_PROG check $device >$tmp.fsck 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
_log_err "_check_btrfs_filesystem: filesystem on $device is inconsistent"
|
|
echo "*** fsck.$FSTYP output ***" >>$seqres.full
|
|
cat $tmp.fsck >>$seqres.full
|
|
echo "*** end fsck.$FSTYP output" >>$seqres.full
|
|
|
|
ok=0
|
|
fi
|
|
rm -f $tmp.fsck
|
|
|
|
if [ $ok -eq 0 ]; then
|
|
echo "*** mount output ***" >>$seqres.full
|
|
_mount >>$seqres.full
|
|
echo "*** end mount output" >>$seqres.full
|
|
elif [ "$type" = "$FSTYP" ]; then
|
|
# was mounted ...
|
|
_mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
|
|
ok=$?
|
|
fi
|
|
|
|
if [ $ok -eq 0 ]; then
|
|
status=1
|
|
if [ "$iam" != "check" ]; then
|
|
exit 1
|
|
fi
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
_require_btrfs_dev_del_by_devid()
|
|
{
|
|
$BTRFS_UTIL_PROG device delete --help | egrep devid > /dev/null 2>&1
|
|
[ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old "\
|
|
"(must support 'btrfs device delete <devid> /<mnt>')"
|
|
}
|
|
|
|
# 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
|
|
|
|
if [ -z "$BTRFS_PROFILE_CONFIGS" ]; then
|
|
# Default configurations to test.
|
|
local configs=(
|
|
"single:single"
|
|
"dup:single"
|
|
"raid0:raid0"
|
|
"raid1:raid0"
|
|
"raid1:raid1"
|
|
"raid10:raid10"
|
|
"raid5:raid5"
|
|
"raid6:raid6"
|
|
)
|
|
else
|
|
# User-provided configurations.
|
|
local configs=(${BTRFS_PROFILE_CONFIGS[@]})
|
|
fi
|
|
|
|
_btrfs_profile_configs=()
|
|
for cfg in "${configs[@]}"; do
|
|
local supported=true
|
|
local profiles=(${cfg/:/ })
|
|
if [ "$1" == "replace" ]; then
|
|
# We can't do replace with these profiles because they
|
|
# imply only one device ($SCRATCH_DEV), and we need to
|
|
# keep $SCRATCH_DEV around for _scratch_mount
|
|
# and _check_scratch_fs.
|
|
local unsupported=(
|
|
"dup"
|
|
)
|
|
elif [ "$1" == "replace-missing" ]; then
|
|
# We can't replace missing devices with these profiles
|
|
# because there isn't enough redundancy.
|
|
local unsupported=(
|
|
"single"
|
|
"dup"
|
|
"raid0"
|
|
)
|
|
else
|
|
local unsupported=()
|
|
fi
|
|
for unsupp in "${unsupported[@]}"; do
|
|
if [ "${profiles[0]}" == "$unsupp" -o "${profiles[1]}" == "$unsupp" ]; then
|
|
if [ -z "$BTRFS_PROFILE_CONFIGS" ]; then
|
|
# For the default config, just omit it.
|
|
supported=false
|
|
else
|
|
# For user-provided config, don't run the test.
|
|
_notrun "Profile $unsupp not supported for $1"
|
|
fi
|
|
fi
|
|
done
|
|
if "$supported"; then
|
|
_btrfs_profile_configs+=("-m ${profiles[0]} -d ${profiles[1]}")
|
|
fi
|
|
done
|
|
export _btrfs_profile_configs
|
|
}
|
|
|
|
# stress btrfs by running balance operation in a loop
|
|
_btrfs_stress_balance()
|
|
{
|
|
local options=$@
|
|
while true; do
|
|
$BTRFS_UTIL_PROG balance start $options
|
|
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
|
|
local stop_file=$5
|
|
|
|
mkdir -p $subvol_mnt
|
|
while [ ! -e $stop_file ]; 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"
|
|
}
|
|
|
|
_require_btrfs_loadable()
|
|
{
|
|
modprobe -r btrfs || _notrun "btrfs unloadable"
|
|
modprobe btrfs || _notrun "Can't load btrfs"
|
|
}
|
|
|
|
_reload_btrfs_ko()
|
|
{
|
|
modprobe -r btrfs || _fail "btrfs unload failed"
|
|
modprobe btrfs || _fail "btrfs load failed"
|
|
}
|
|
|
|
_btrfs_compression_algos()
|
|
{
|
|
echo zlib
|
|
for feature in /sys/fs/btrfs/features/compress_*; do
|
|
echo "${feature#/sys/fs/btrfs/features/compress_}"
|
|
done
|
|
}
|