mirror of
https://github.com/xemu-project/xemu.git
synced 2025-04-02 11:11:48 -04:00
With the experimental x-nbd-server-add-bitmap command, there was a window of time where an NBD client could see the export but not the associated dirty bitmap, which can cause a client that planned on using the dirty bitmap to be forced to treat the entire image as dirty as a safety fallback. Furthermore, if the QMP client successfully exports a disk but then fails to add the bitmap, it has to take on the burden of removing the export. Since we don't allow changing the exposed dirty bitmap (whether to a different bitmap, or removing advertisement of the bitmap), it is nicer to make the bitmap tied to the export at the time the export is created, with automatic failure to export if the bitmap is not available. The experimental command included an optional 'bitmap-export-name' field for remapping the name exposed over NBD to be different from the bitmap name stored on disk. However, my libvirt demo code for implementing differential backups on top of persistent bitmaps did not need to take advantage of that feature (it is instead possible to create a new temporary bitmap with the desired name, use block-dirty-bitmap-merge to merge one or more persistent bitmaps into the temporary, then associate the temporary with the NBD export, if control is needed over the exported bitmap name). Hence, I'm not copying that part of the experiment over to the stable addition. For more details on the libvirt demo, see https://www.redhat.com/archives/libvir-list/2018-October/msg01254.html, https://kvmforum2018.sched.com/event/FzuB/facilitating-incremental-backup-eric-blake-red-hat This patch focuses on the user interface, and reduces (but does not completely eliminate) the window where an NBD client can see the export but not the dirty bitmap, with less work to clean up after errors. Later patches will add further cleanups now that this interface is declared stable via a single QMP command, including removing the race window. Update test 223 to use the new interface. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <20190111194720.15671-6-eblake@redhat.com>
182 lines
5.6 KiB
Bash
Executable file
182 lines
5.6 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# Test reading dirty bitmap over NBD
|
|
#
|
|
# Copyright (C) 2018 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
|
|
rm -f "$TEST_DIR/nbd"
|
|
}
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
# get standard environment, filters and checks
|
|
. ./common.rc
|
|
. ./common.filter
|
|
. ./common.qemu
|
|
|
|
_supported_fmt qcow2
|
|
_supported_proto file # uses NBD as well
|
|
_supported_os Linux
|
|
# Persistent dirty bitmaps require compat=1.1
|
|
_unsupported_imgopts 'compat=0.10'
|
|
|
|
do_run_qemu()
|
|
{
|
|
echo Testing: "$@"
|
|
$QEMU -nographic -qmp stdio -serial none "$@"
|
|
echo
|
|
}
|
|
|
|
run_qemu()
|
|
{
|
|
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
|
|
| _filter_qemu | _filter_imgfmt \
|
|
| _filter_actual_image_size
|
|
}
|
|
|
|
echo
|
|
echo "=== Create partially sparse image, then add dirty bitmaps ==="
|
|
echo
|
|
|
|
# Two bitmaps, to contrast granularity issues
|
|
# Also note that b will be disabled, while b2 is left enabled, to
|
|
# check for read-only interactions
|
|
_make_test_img -o cluster_size=4k 4M
|
|
$QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io
|
|
run_qemu <<EOF
|
|
{ "execute": "qmp_capabilities" }
|
|
{ "execute": "blockdev-add",
|
|
"arguments": {
|
|
"driver": "$IMGFMT",
|
|
"node-name": "n",
|
|
"file": {
|
|
"driver": "file",
|
|
"filename": "$TEST_IMG"
|
|
}
|
|
}
|
|
}
|
|
{ "execute": "block-dirty-bitmap-add",
|
|
"arguments": {
|
|
"node": "n",
|
|
"name": "b",
|
|
"persistent": true,
|
|
"granularity": 65536
|
|
}
|
|
}
|
|
{ "execute": "block-dirty-bitmap-add",
|
|
"arguments": {
|
|
"node": "n",
|
|
"name": "b2",
|
|
"persistent": true,
|
|
"granularity": 512
|
|
}
|
|
}
|
|
{ "execute": "quit" }
|
|
EOF
|
|
|
|
echo
|
|
echo "=== Write part of the file under active bitmap ==="
|
|
echo
|
|
|
|
$QEMU_IO -c 'w -P 0x22 512 512' -c 'w -P 0x33 2M 2M' "$TEST_IMG" \
|
|
| _filter_qemu_io
|
|
|
|
echo
|
|
echo "=== End dirty bitmaps, and start serving image over NBD ==="
|
|
echo
|
|
|
|
_launch_qemu 2> >(_filter_nbd)
|
|
|
|
# Intentionally provoke some errors as well, to check error handling
|
|
silent=
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"qmp_capabilities"}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"blockdev-add",
|
|
"arguments":{"driver":"qcow2", "node-name":"n",
|
|
"file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"block-dirty-bitmap-disable",
|
|
"arguments":{"node":"n", "name":"b"}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n"}}' "error" # Attempt add without server
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
|
|
"arguments":{"addr":{"type":"unix",
|
|
"data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
|
|
"arguments":{"addr":{"type":"unix",
|
|
"data":{"path":"'"$TEST_DIR/nbd"1'"}}}}' "error" # Attempt second server
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n", "bitmap":"b"}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"nosuch"}}' "error" # Attempt to export missing node
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n"}}' "error" # Attempt to export same name twice
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n", "name":"n2",
|
|
"bitmap":"b2"}}' "error" # enabled vs. read-only
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n", "name":"n2",
|
|
"bitmap":"b3"}}' "error" # Missing bitmap
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
|
"arguments":{"device":"n", "name":"n2", "writable":true,
|
|
"bitmap":"b2"}}' "return"
|
|
|
|
echo
|
|
echo "=== Contrast normal status to large granularity dirty-bitmap ==="
|
|
echo
|
|
|
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
|
IMG="driver=nbd,export=n,server.type=unix,server.path=$TEST_DIR/nbd"
|
|
$QEMU_IO -r -c 'r -P 0x22 512 512' -c 'r -P 0 512k 512k' -c 'r -P 0x11 1m 1m' \
|
|
-c 'r -P 0x33 2m 2m' --image-opts "$IMG" | _filter_qemu_io
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG" | _filter_qemu_img_map
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b" | _filter_qemu_img_map
|
|
|
|
echo
|
|
echo "=== Contrast to small granularity dirty-bitmap ==="
|
|
echo
|
|
|
|
IMG="driver=nbd,export=n2,server.type=unix,server.path=$TEST_DIR/nbd"
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
|
|
|
|
echo
|
|
echo "=== End NBD server ==="
|
|
echo
|
|
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
|
"arguments":{"name":"n"}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
|
"arguments":{"name":"n2"}}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
|
"arguments":{"name":"n2"}}' "error" # Attempt duplicate clean
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return"
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "error" # Again
|
|
_send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return"
|
|
|
|
# success, all done
|
|
echo '*** done'
|
|
rm -f $seq.full
|
|
status=0
|