mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
tests: Add iotest mirror-sparse for recent patches
Prove that blockdev-mirror can now result in sparse raw destination files, regardless of whether the source is raw or qcow2. By making this a separate test, it was possible to test effects of individual patches for the various pieces that all have to work together for a sparse mirror to be successful. Note that ./check -file produces different job lengths than ./check -qcow2 (the test uses a filter to normalize); that's because when deciding how much of the image to be mirrored, the code looks at how much of the source image was allocated (for qcow2, this is only the written clusters; for raw, it is the entire file). But the important part is that the destination file ends up smaller than 3M, rather than the 20M it used to be before this patch series. Signed-off-by: Eric Blake <eblake@redhat.com> Message-ID: <20250509204341.3553601-28-eblake@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Executable
+125
@@ -0,0 +1,125 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
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
|
||||||
|
result=$(disk_usage $TEST_IMG)
|
||||||
|
if test $result -lt $((3*1024*1024)); then
|
||||||
|
actual=sparse
|
||||||
|
elif test $result = $((20*1024*1024)); then
|
||||||
|
actual=full
|
||||||
|
else
|
||||||
|
actual=unknown
|
||||||
|
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
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
QA output created by mirror-sparse
|
||||||
|
|
||||||
|
=== Initial image setup ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=20971520
|
||||||
|
wrote 2097152/2097152 bytes at offset 8388608
|
||||||
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
{"execute": "qmp_capabilities"}
|
||||||
|
{"return": {}}
|
||||||
|
|
||||||
|
=== Testing creation=external discard=ignore zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"ignore",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=external discard=unmap zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=external discard=unmap zeroes=unmap ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"unmap"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=off discard=ignore zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"off"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"ignore",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=off discard=unmap zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"off"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=off discard=unmap zeroes=unmap ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"off"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"unmap"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=full discard=ignore zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"full"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"ignore",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is full; expected full
|
||||||
|
|
||||||
|
=== Testing creation=full discard=unmap zeroes=off ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"full"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"off"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
|
||||||
|
=== Testing creation=full discard=unmap zeroes=unmap ===
|
||||||
|
|
||||||
|
{"execute": "blockdev-create", "arguments":
|
||||||
|
{"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT",
|
||||||
|
"size":20971520, "preallocation":"full"},
|
||||||
|
"job-id":"job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}}
|
||||||
|
{"execute": "job-dismiss", "arguments":
|
||||||
|
{"id": "job1"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-add", "arguments":
|
||||||
|
{"node-name": "dst", "driver":"file",
|
||||||
|
"filename":"TEST_DIR/t.IMGFMT", "aio":"threads",
|
||||||
|
"auto-read-only":true, "discard":"unmap",
|
||||||
|
"detect-zeroes":"unmap"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute":"blockdev-mirror", "arguments":
|
||||||
|
{"sync":"full", "device":"src", "target":"dst",
|
||||||
|
"job-id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}}
|
||||||
|
{"execute": "job-complete", "arguments":
|
||||||
|
{"id":"job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "blockdev-del", "arguments":
|
||||||
|
{"node-name": "dst"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}}
|
||||||
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}}
|
||||||
|
{"return": {}}
|
||||||
|
Images are identical.
|
||||||
|
Destination is sparse; expected sparse
|
||||||
|
{"execute":"quit"}
|
||||||
|
*** done
|
||||||
Reference in New Issue
Block a user