- kvm-block-Expand-block-status-mode-from-bool-to-flags.patch [RHEL-88435 RHEL-88437] - kvm-file-posix-gluster-Handle-zero-block-status-hint-bet.patch [RHEL-88435 RHEL-88437] - kvm-block-Let-bdrv_co_is_zero_fast-consolidate-adjacent-.patch [RHEL-88435 RHEL-88437] - kvm-block-Add-new-bdrv_co_is_all_zeroes-function.patch [RHEL-88435 RHEL-88437] - kvm-iotests-Improve-iotest-194-to-mirror-data.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Minor-refactoring.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Pass-full-sync-mode-rather-than-bool-to-inter.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Allow-QMP-override-to-declare-target-already-.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Drop-redundant-zero_target-parameter.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Skip-pre-zeroing-destination-if-it-is-already.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Skip-writing-zeroes-when-target-is-already-ze.patch [RHEL-88435 RHEL-88437] - kvm-iotests-common.rc-add-disk_usage-function.patch [RHEL-88435 RHEL-88437] - kvm-tests-Add-iotest-mirror-sparse-for-recent-patches.patch [RHEL-88435 RHEL-88437] - kvm-mirror-Reduce-I-O-when-destination-is-detect-zeroes-.patch [RHEL-88435 RHEL-88437] - Resolves: RHEL-88435 (--migrate-disks-detect-zeroes doesn't take effect for disk migration [rhel-10.1]) - Resolves: RHEL-88437 (Disk size of target raw image is full allocated when doing mirror with default discard value [rhel-10.1])
546 lines
32 KiB
Diff
546 lines
32 KiB
Diff
From 2bb881df5b93f5534e5f0b91cf1ed3e0b524c2d3 Mon Sep 17 00:00:00 2001
|
|
From: Eric Blake <eblake@redhat.com>
|
|
Date: Fri, 9 May 2025 15:40:30 -0500
|
|
Subject: [PATCH 13/14] tests: Add iotest mirror-sparse for recent patches
|
|
|
|
RH-Author: Eric Blake <eblake@redhat.com>
|
|
RH-MergeRequest: 363: blockdev-mirror: More efficient handling of sparse mirrors
|
|
RH-Jira: RHEL-88435 RHEL-88437
|
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
RH-Commit: [13/14] 474f12dfe9161c7e9f59cafde203e5183e2fc3f5 (ebblake/centos-qemu-kvm)
|
|
|
|
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>
|
|
(cherry picked from commit c0ddcb2cbc146e64f666eaae4edc7b5db7e5814d)
|
|
Jira: https://issues.redhat.com/browse/RHEL-88435
|
|
Jira: https://issues.redhat.com/browse/RHEL-88437
|
|
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
---
|
|
tests/qemu-iotests/tests/mirror-sparse | 125 +++++++
|
|
tests/qemu-iotests/tests/mirror-sparse.out | 365 +++++++++++++++++++++
|
|
2 files changed, 490 insertions(+)
|
|
create mode 100755 tests/qemu-iotests/tests/mirror-sparse
|
|
create mode 100644 tests/qemu-iotests/tests/mirror-sparse.out
|
|
|
|
diff --git a/tests/qemu-iotests/tests/mirror-sparse b/tests/qemu-iotests/tests/mirror-sparse
|
|
new file mode 100755
|
|
index 0000000000..8c52a4e244
|
|
--- /dev/null
|
|
+++ b/tests/qemu-iotests/tests/mirror-sparse
|
|
@@ -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
|
|
diff --git a/tests/qemu-iotests/tests/mirror-sparse.out b/tests/qemu-iotests/tests/mirror-sparse.out
|
|
new file mode 100644
|
|
index 0000000000..2103b891c3
|
|
--- /dev/null
|
|
+++ b/tests/qemu-iotests/tests/mirror-sparse.out
|
|
@@ -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
|
|
--
|
|
2.39.3
|
|
|