qemu/tests/qemu-iotests/tests/mirror-sparse
Eric Blake c49dda7254 iotests: Filter out ZFS in several tests
Fiona reported that ZFS makes sparse file testing awkward, since:
- it has asynchronous allocation (not even 'fsync $file' makes du see
  the desired size; it takes the slower 'fsync -f $file' which is not
  appropriate for the tests)
- for tests of fully allocated files, ZFS with compression enabled
  still reports smaller disk usage

Add a new _require_disk_usage that quickly probes whether an attempt
to create a sparse 5M file shows as less than 1M usage, while the same
file with -o preallocation=full shows as more than 4M usage without
sync, which should filter out ZFS behavior.  Then use it in various
affected tests.

This does not add the new filter on all tests that Fiona is seeing ZFS
failures on, but only those where I could quickly spot that there is
at least one place where the test depends on the output of 'du -b' or
'stat -c %b'.

Reported-by: Fiona Ebner <f.ebner@proxmox.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20250523163041.2548675-8-eblake@redhat.com>
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
Tested-by: Fiona Ebner <f.ebner@proxmox.com>
2025-05-29 16:40:00 -05:00

128 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# group: rw auto quick
#
# Test blockdev-mirror with raw sparse destination
#
# Copyright (C) 2025 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
seq="$(basename $0)"
echo "QA output created by $seq"
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
_cleanup_qemu
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
cd ..
. ./common.rc
. ./common.filter
. ./common.qemu
_supported_fmt qcow2 raw # Format of the source. dst is always raw file
_supported_proto file
_supported_os Linux
_require_disk_usage
echo
echo "=== Initial image setup ==="
echo
TEST_IMG="$TEST_IMG.base" _make_test_img 20M
$QEMU_IO -c 'w 8M 2M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io
_launch_qemu \
-blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false},
"filename":"'"$TEST_IMG.base"'", "node-name":"src-file"}' \
-blockdev '{"driver":"'$IMGFMT'", "node-name":"src", "file":"src-file"}'
h1=$QEMU_HANDLE
_send_qemu_cmd $h1 '{"execute": "qmp_capabilities"}' 'return'
# Check several combinations; most should result in a sparse destination;
# the destination should only be fully allocated if pre-allocated
# and not punching holes due to detect-zeroes
# do_test creation discard zeroes result
do_test() {
creation=$1
discard=$2
zeroes=$3
expected=$4
echo
echo "=== Testing creation=$creation discard=$discard zeroes=$zeroes ==="
echo
rm -f $TEST_IMG
if test $creation = external; then
truncate --size=20M $TEST_IMG
else
_send_qemu_cmd $h1 '{"execute": "blockdev-create", "arguments":
{"options": {"driver":"file", "filename":"'$TEST_IMG'",
"size":'$((20*1024*1024))', "preallocation":"'$creation'"},
"job-id":"job1"}}' 'concluded'
_send_qemu_cmd $h1 '{"execute": "job-dismiss", "arguments":
{"id": "job1"}}' 'return'
fi
_send_qemu_cmd $h1 '{"execute": "blockdev-add", "arguments":
{"node-name": "dst", "driver":"file",
"filename":"'$TEST_IMG'", "aio":"threads",
"auto-read-only":true, "discard":"'$discard'",
"detect-zeroes":"'$zeroes'"}}' 'return'
_send_qemu_cmd $h1 '{"execute":"blockdev-mirror", "arguments":
{"sync":"full", "device":"src", "target":"dst",
"job-id":"job2"}}' 'return'
_timed_wait_for $h1 '"ready"'
_send_qemu_cmd $h1 '{"execute": "job-complete", "arguments":
{"id":"job2"}}' 'return' \
| _filter_block_job_offset | _filter_block_job_len
_send_qemu_cmd $h1 '{"execute": "blockdev-del", "arguments":
{"node-name": "dst"}}' 'return' \
| _filter_block_job_offset | _filter_block_job_len
$QEMU_IMG compare -U -f $IMGFMT -F raw $TEST_IMG.base $TEST_IMG
# Some filesystems can fudge allocations for various reasons; rather
# than expecting precise 2M and 20M images, it is better to allow for slop.
result=$(disk_usage $TEST_IMG)
if test $result -lt $((4*1024*1024)); then
actual=sparse
elif test $result -gt $((19*1024*1024)); then
actual=full
else
actual="unexpected size ($result)"
fi
echo "Destination is $actual; expected $expected"
}
do_test external ignore off sparse
do_test external unmap off sparse
do_test external unmap unmap sparse
do_test off ignore off sparse
do_test off unmap off sparse
do_test off unmap unmap sparse
do_test full ignore off full
do_test full unmap off sparse
do_test full unmap unmap sparse
_send_qemu_cmd $h1 '{"execute":"quit"}' ''
# success, all done
echo '*** done'
rm -f $seq.full
status=0