2013-08-23 13:07:11 +00:00
|
|
|
#! /bin/bash
|
2018-06-09 11:35:50 +10:00
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
# Copyright (C) 2013 STRATO. All rights reserved.
|
|
|
|
|
#
|
2013-08-23 13:07:11 +00:00
|
|
|
# FSQA Test No. btrfs/011
|
|
|
|
|
#
|
|
|
|
|
# Test of the btrfs replace operation.
|
|
|
|
|
#
|
|
|
|
|
# The amount of tests done depends on the number of devices in the
|
|
|
|
|
# SCRATCH_DEV_POOL. For full test coverage, at least 5 devices should
|
|
|
|
|
# be available (e.g. 5 partitions).
|
|
|
|
|
#
|
|
|
|
|
# The source and target devices for the replace operation are
|
|
|
|
|
# arbitrarily chosen out of SCRATCH_DEV_POOl. Since the target device
|
|
|
|
|
# mustn't be smaller than the source device, the requirement for this
|
|
|
|
|
# test is that all devices have _exactly_ the same size. If this is
|
|
|
|
|
# not the case, this test is not run.
|
|
|
|
|
#
|
|
|
|
|
# To check the filesystems after replacing a device, a scrub run is
|
|
|
|
|
# performed, a btrfsck run, and finally the filesystem is remounted.
|
|
|
|
|
#
|
|
|
|
|
seq=`basename $0`
|
|
|
|
|
seqres=$RESULT_DIR/$seq
|
|
|
|
|
echo "QA output created by $seq"
|
|
|
|
|
|
|
|
|
|
here=`pwd`
|
|
|
|
|
tmp=/tmp/$$
|
|
|
|
|
status=1
|
|
|
|
|
noise_pid=0
|
|
|
|
|
|
|
|
|
|
_cleanup()
|
|
|
|
|
{
|
|
|
|
|
if [ $noise_pid -ne 0 ] && ps -p $noise_pid | grep -q $noise_pid; then
|
|
|
|
|
kill -TERM $noise_pid
|
|
|
|
|
fi
|
|
|
|
|
wait
|
|
|
|
|
rm -f $tmp.tmp
|
2018-01-16 13:10:17 -07:00
|
|
|
# we need this umount and couldn't rely on _require_scratch to umount
|
|
|
|
|
# it from next test, because we would replace SCRATCH_DEV, which is
|
|
|
|
|
# needed by _require_scratch, and make it umounted.
|
|
|
|
|
_scratch_unmount > /dev/null 2>&1
|
2013-08-23 13:07:11 +00:00
|
|
|
}
|
|
|
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
|
|
|
|
|
|
# get standard environment, filters and checks
|
|
|
|
|
. ./common/rc
|
|
|
|
|
. ./common/filter
|
|
|
|
|
|
|
|
|
|
# real QA test starts here
|
|
|
|
|
_supported_fs btrfs
|
2014-09-29 12:55:20 +10:00
|
|
|
_require_scratch_nocheck
|
2018-04-20 00:03:37 +08:00
|
|
|
_require_scratch_dev_pool 5
|
|
|
|
|
_require_scratch_dev_pool_equal_size
|
|
|
|
|
_require_command "$WIPEFS_PROG" wipefs
|
2013-08-23 13:07:11 +00:00
|
|
|
|
|
|
|
|
rm -f $seqres.full
|
|
|
|
|
rm -f $tmp.tmp
|
|
|
|
|
|
|
|
|
|
echo "*** test btrfs replace"
|
|
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
fill_scratch()
|
|
|
|
|
{
|
|
|
|
|
local fssize=$1
|
|
|
|
|
|
|
|
|
|
# Fill inline extents.
|
|
|
|
|
for i in `seq 1 500`; do
|
|
|
|
|
_ddt of=$SCRATCH_MNT/s$i bs=3800 count=1
|
|
|
|
|
done > /dev/null 2>&1
|
|
|
|
|
|
|
|
|
|
# Fill data extents.
|
|
|
|
|
for i in `seq 1 500`; do
|
|
|
|
|
_ddt of=$SCRATCH_MNT/l$i bs=16385 count=1
|
|
|
|
|
done > /dev/null 2>&1
|
|
|
|
|
_ddt of=$SCRATCH_MNT/t0 bs=1M count=1 > /dev/null 2>&1
|
|
|
|
|
for i in `seq $fssize`; do
|
|
|
|
|
cp $SCRATCH_MNT/t0 $SCRATCH_MNT/t$i || _fail "cp failed"
|
|
|
|
|
done > /dev/null 2>> $seqres.full
|
|
|
|
|
sync; sync
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-23 13:07:11 +00:00
|
|
|
workout()
|
|
|
|
|
{
|
|
|
|
|
local mkfs_options="$1"
|
|
|
|
|
local num_devs4raid="$2"
|
|
|
|
|
local with_cancel="$3"
|
2018-04-20 00:03:37 +08:00
|
|
|
local fssize="$4"
|
2013-08-23 13:07:11 +00:00
|
|
|
local source_dev="`echo ${SCRATCH_DEV_POOL} | awk '{print $1}'`"
|
2018-04-20 00:03:37 +08:00
|
|
|
local quick="quick"
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
[[ $fssize != 64 ]] && quick="thorough"
|
2016-02-22 08:37:15 +11:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
echo -e "\\n---------workout \"$1\" $2 $3 $4-----------" >> $seqres.full
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
$WIPEFS_PROG -a $SCRATCH_DEV_POOL > /dev/null 2>&1
|
|
|
|
|
_scratch_dev_pool_get $num_devs4raid
|
|
|
|
|
_spare_dev_get
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
_scratch_pool_mkfs $mkfs_options >> $seqres.full 2>&1 ||\
|
|
|
|
|
_fail "mkfs failed"
|
2013-09-13 10:27:21 +00:00
|
|
|
|
2013-08-23 13:07:11 +00:00
|
|
|
_scratch_mount
|
2018-04-20 00:03:37 +08:00
|
|
|
_require_fs_space $SCRATCH_MNT $((2 * 512 * 1024)) #2.5G
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
fill_scratch $fssize
|
|
|
|
|
_run_btrfs_util_prog filesystem show -m $SCRATCH_MNT
|
2016-02-22 08:37:15 +11:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
echo -e "Replace from $source_dev to $SPARE_DEV\\n" >> $seqres.full
|
|
|
|
|
btrfs_replace_test $source_dev $SPARE_DEV "" $with_cancel $quick
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
_run_btrfs_util_prog filesystem show -m $SCRATCH_MNT
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
# Skip -r test for configs without mirror OR replace cancel
|
2013-08-23 13:07:11 +00:00
|
|
|
if echo $mkfs_options | egrep -qv "raid1|raid5|raid6|raid10" || \
|
|
|
|
|
[ "${with_cancel}Q" = "cancelQ" ]; then
|
2018-04-20 00:03:37 +08:00
|
|
|
_scratch_unmount > /dev/null 2>&1
|
|
|
|
|
_scratch_dev_pool_put
|
|
|
|
|
_spare_dev_put
|
2013-08-23 13:07:11 +00:00
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
# Due to above replace, now SPARE_DEV is part of the FS, check that.
|
|
|
|
|
$BTRFS_UTIL_PROG filesystem show -m $SCRATCH_MNT |\
|
|
|
|
|
grep -qs $SPARE_DEV$ ||\
|
|
|
|
|
_fail "$SPARE_DEV is not part of SCRATCH_FS"
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
btrfs_replace_test $SPARE_DEV $source_dev "-r" $with_cancel $quick
|
2013-08-23 13:07:11 +00:00
|
|
|
|
2015-12-21 18:07:43 +11:00
|
|
|
_scratch_unmount > /dev/null 2>&1
|
2018-04-20 00:03:37 +08:00
|
|
|
_scratch_dev_pool_put
|
|
|
|
|
_spare_dev_put
|
2013-08-23 13:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
btrfs_replace_test()
|
|
|
|
|
{
|
|
|
|
|
local source_dev="$1"
|
|
|
|
|
local target_dev="$2"
|
|
|
|
|
local replace_options="$3"
|
|
|
|
|
local with_cancel="$4"
|
|
|
|
|
local quick="$5"
|
|
|
|
|
|
|
|
|
|
# generate some (slow) background traffic in parallel to the
|
|
|
|
|
# replace operation. It is not a problem if cat fails early
|
|
|
|
|
# with ENOSPC.
|
2017-02-06 15:55:39 +08:00
|
|
|
cat /dev/urandom | od > $SCRATCH_MNT/noise 2>> $seqres.full &
|
2013-08-23 13:07:11 +00:00
|
|
|
noise_pid=$!
|
|
|
|
|
|
|
|
|
|
if [ "${with_cancel}Q" = "cancelQ" ]; then
|
|
|
|
|
# background the replace operation (no '-B' option given)
|
2018-04-20 00:03:37 +08:00
|
|
|
_run_btrfs_util_prog replace start -f $replace_options $source_dev $target_dev $SCRATCH_MNT
|
2013-08-23 13:07:11 +00:00
|
|
|
sleep 1
|
2018-04-20 00:03:37 +08:00
|
|
|
_run_btrfs_util_prog replace cancel $SCRATCH_MNT
|
2013-08-23 13:07:11 +00:00
|
|
|
|
|
|
|
|
# 'replace status' waits for the replace operation to finish
|
|
|
|
|
# before the status is printed
|
|
|
|
|
$BTRFS_UTIL_PROG replace status $SCRATCH_MNT > $tmp.tmp 2>&1
|
|
|
|
|
cat $tmp.tmp >> $seqres.full
|
2013-09-13 10:27:21 +00:00
|
|
|
grep -q canceled $tmp.tmp || _fail "btrfs replace status (canceled) failed"
|
2013-08-23 13:07:11 +00:00
|
|
|
else
|
|
|
|
|
if [ "${quick}Q" = "thoroughQ" ]; then
|
|
|
|
|
# On current hardware, the thorough test runs
|
|
|
|
|
# more than a second. This is a chance to force
|
|
|
|
|
# a sync in the middle of the replace operation.
|
|
|
|
|
(sleep 1; sync) > /dev/null 2>&1 &
|
|
|
|
|
fi
|
2018-04-20 00:03:37 +08:00
|
|
|
_run_btrfs_util_prog replace start -Bf $replace_options $source_dev $target_dev $SCRATCH_MNT
|
2013-08-23 13:07:11 +00:00
|
|
|
|
|
|
|
|
$BTRFS_UTIL_PROG replace status $SCRATCH_MNT > $tmp.tmp 2>&1
|
|
|
|
|
cat $tmp.tmp >> $seqres.full
|
2013-09-13 10:27:21 +00:00
|
|
|
grep -q finished $tmp.tmp || _fail "btrfs replace status (finished) failed"
|
2013-08-23 13:07:11 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ps -p $noise_pid | grep -q $noise_pid; then
|
|
|
|
|
kill -TERM $noise_pid 2> /dev/null
|
|
|
|
|
fi
|
|
|
|
|
noise_pid=0
|
|
|
|
|
wait
|
|
|
|
|
|
|
|
|
|
# scrub tests on-disk data, that's the reason for the sync.
|
|
|
|
|
# With the '-B' option (don't background), any type of error causes
|
|
|
|
|
# exit values != 0, including detected correctable and uncorrectable
|
|
|
|
|
# errors on the device.
|
|
|
|
|
sync; sync
|
2018-04-20 00:03:37 +08:00
|
|
|
_run_btrfs_util_prog scrub start -B $SCRATCH_MNT
|
2013-08-23 13:07:11 +00:00
|
|
|
|
|
|
|
|
# Two tests are performed, the 1st is to btrfsck the filesystem,
|
|
|
|
|
# and the 2nd test is to mount the filesystem.
|
|
|
|
|
# Usually _check_btrfs_filesystem would perform the mount test,
|
|
|
|
|
# but it gets confused by the mount output that shows SCRATCH_MNT
|
|
|
|
|
# mounted but not being mounted to SCRATCH_DEV. This happens
|
|
|
|
|
# because in /proc/mounts the 2nd device of the filesystem is
|
|
|
|
|
# shown after the replace operation. Let's just do the mount
|
|
|
|
|
# test manually after _check_btrfs_filesystem is finished.
|
2015-12-21 18:07:43 +11:00
|
|
|
_scratch_unmount > /dev/null 2>&1
|
2013-08-23 13:07:11 +00:00
|
|
|
if [ "${with_cancel}Q" != "cancelQ" ]; then
|
|
|
|
|
# after the replace operation, use the target_dev for everything
|
2016-02-22 08:37:15 +11:00
|
|
|
echo "_check_btrfs_filesystem $target_dev" >> $seqres.full
|
2013-08-23 13:07:11 +00:00
|
|
|
_check_btrfs_filesystem $target_dev
|
|
|
|
|
_mount -t $FSTYP `_scratch_mount_options | sed "s&${SCRATCH_DEV}&${target_dev}&"`
|
|
|
|
|
else
|
|
|
|
|
_check_btrfs_filesystem $source_dev
|
|
|
|
|
_scratch_mount
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-20 00:03:37 +08:00
|
|
|
workout "-m single -d single" 1 no 64
|
|
|
|
|
workout "-m single -d single -M" 1 no 64
|
|
|
|
|
workout "-m dup -d single" 1 no 64
|
|
|
|
|
workout "-m dup -d single" 1 cancel 1024
|
|
|
|
|
workout "-m dup -d dup -M" 1 no 64
|
|
|
|
|
workout "-m raid0 -d raid0" 2 no 64
|
|
|
|
|
workout "-m raid1 -d raid1" 2 no 2048
|
|
|
|
|
workout "-m raid5 -d raid5" 2 no 64
|
|
|
|
|
workout "-m raid6 -d raid6" 3 no 64
|
|
|
|
|
workout "-m raid10 -d raid10" 4 no 64
|
2013-08-23 13:07:11 +00:00
|
|
|
|
|
|
|
|
echo "*** done"
|
|
|
|
|
status=0
|
|
|
|
|
exit
|