mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 20:33:54 -06:00

The point of 'qemu-img convert --bitmaps' is to be a convenience for actions that are already possible through a string of smaller 'qemu-img bitmap' sub-commands. One situation not accounted for already is that if a source image contains an inconsistent bitmap (for example, because a qemu process died abruptly before flushing bitmap state), the user MUST delete those inconsistent bitmaps before anything else useful can be done with the image. We don't want to delete inconsistent bitmaps by default: although a corrupt bitmap is only a loss of optimization rather than a corruption of user-visible data, it is still nice to require the user to opt in to the fact that they are aware of the loss of the bitmap. Still, requiring the user to check 'qemu-img info' to see whether bitmaps are consistent, then use 'qemu-img bitmap --remove' to remove offenders, all before using 'qemu-img convert', is a lot more work than just adding a knob 'qemu-img convert --bitmaps --skip-broken-bitmaps' which opts in to skipping the broken bitmaps. After testing the new option, also demonstrate the way to manually fix things (either deleting bad bitmaps, or re-creating them as empty) so that it is possible to convert without the option. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1946084 Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20210709153951.2801666-4-eblake@redhat.com> [eblake: warning message tweak, test enhancements] Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
167 lines
5.6 KiB
Bash
Executable file
167 lines
5.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# group: rw quick
|
|
#
|
|
# Test qemu-img bitmap handling
|
|
#
|
|
# Copyright (C) 2018-2021 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
|
|
_rm_test_img "$TEST_IMG.copy"
|
|
nbd_server_stop
|
|
}
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
# get standard environment, filters and checks
|
|
cd ..
|
|
. ./common.rc
|
|
. ./common.filter
|
|
. ./common.nbd
|
|
|
|
_supported_fmt qcow2
|
|
_supported_proto file fuse
|
|
_supported_os Linux
|
|
_require_command QEMU_NBD
|
|
# compat=0.10 does not support bitmaps
|
|
_unsupported_imgopts 'compat=0.10'
|
|
|
|
# Filter irrelevant format-specific information from the qemu-img info
|
|
# output (we only want the bitmaps, basically)
|
|
_filter_irrelevant_img_info()
|
|
{
|
|
grep -v -e 'compat' -e 'compression type' -e 'data file' -e 'extended l2' \
|
|
-e 'lazy refcounts' -e 'refcount bits'
|
|
}
|
|
|
|
echo
|
|
echo "=== Initial image setup ==="
|
|
echo
|
|
|
|
# Create backing image with one bitmap
|
|
TEST_IMG="$TEST_IMG.base" _make_test_img 10M
|
|
$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG.base" b0
|
|
$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io
|
|
|
|
# Create initial image and populate two bitmaps: one active, one inactive.
|
|
ORIG_IMG=$TEST_IMG
|
|
TEST_IMG=$TEST_IMG.orig
|
|
_make_test_img -b "$ORIG_IMG.base" -F $IMGFMT 10M
|
|
$QEMU_IO -c 'w 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
|
|
$QEMU_IMG bitmap --add -g 512k -f $IMGFMT "$TEST_IMG" b1
|
|
$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b2
|
|
$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
|
|
$QEMU_IMG bitmap --clear -f $IMGFMT "$TEST_IMG" b1
|
|
$QEMU_IO -c 'w 1M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
|
|
$QEMU_IMG bitmap --disable -f $IMGFMT "$TEST_IMG" b1
|
|
$QEMU_IMG bitmap --enable -f $IMGFMT "$TEST_IMG" b2
|
|
$QEMU_IO -c 'w 2M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
|
|
|
|
echo
|
|
echo "=== Bitmap preservation not possible to non-qcow2 ==="
|
|
echo
|
|
|
|
TEST_IMG=$ORIG_IMG
|
|
$QEMU_IMG convert --bitmaps -O raw "$TEST_IMG.orig" "$TEST_IMG" &&
|
|
echo "unexpected success"
|
|
|
|
echo
|
|
echo "=== Convert with bitmap preservation ==="
|
|
echo
|
|
|
|
# Only bitmaps from the active layer are copied
|
|
$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG.orig" "$TEST_IMG"
|
|
_img_info --format-specific | _filter_irrelevant_img_info
|
|
# But we can also merge in bitmaps from other layers. This test is a bit
|
|
# contrived to cover more code paths, in reality, you could merge directly
|
|
# into b0 without going through tmp
|
|
$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b0
|
|
$QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \
|
|
-f $IMGFMT "$TEST_IMG" tmp
|
|
$QEMU_IMG bitmap --merge tmp -f $IMGFMT "$TEST_IMG" b0
|
|
$QEMU_IMG bitmap --remove --image-opts \
|
|
driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG" tmp
|
|
_img_info --format-specific | _filter_irrelevant_img_info
|
|
|
|
echo
|
|
echo "=== Merge from top layer into backing image ==="
|
|
echo
|
|
|
|
$QEMU_IMG rebase -u -F qcow2 -b "$TEST_IMG.base" "$TEST_IMG"
|
|
$QEMU_IMG bitmap --add --merge b2 -b "$TEST_IMG" -F $IMGFMT \
|
|
-f $IMGFMT "$TEST_IMG.base" b3
|
|
_img_info --format-specific --backing-chain | _filter_irrelevant_img_info
|
|
|
|
echo
|
|
echo "=== Check bitmap contents ==="
|
|
echo
|
|
|
|
# x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to
|
|
# report "data":false for portions of the bitmap which are set
|
|
IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket"
|
|
nbd_server_start_unix_socket -r -f qcow2 \
|
|
-B b0 -B b1 -B b2 -B b3 "$TEST_IMG"
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
|
|
$QEMU_IMG map --output=json --image-opts \
|
|
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b3" | _filter_qemu_img_map
|
|
|
|
nbd_server_stop
|
|
|
|
echo
|
|
echo "=== Check handling of inconsistent bitmap ==="
|
|
echo
|
|
|
|
# Prepare image with corrupted bitmap
|
|
$QEMU_IO -c abort "$TEST_IMG" 2>/dev/null
|
|
$QEMU_IMG bitmap --add "$TEST_IMG" b4
|
|
$QEMU_IMG bitmap --remove "$TEST_IMG" b1
|
|
_img_info --format-specific | _filter_irrelevant_img_info
|
|
# Proof that we fail fast if bitmaps can't be copied
|
|
echo
|
|
$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG" "$TEST_IMG.copy" &&
|
|
echo "unexpected success"
|
|
TEST_IMG="$TEST_IMG.copy" _img_info --format-specific \
|
|
| _filter_irrelevant_img_info
|
|
# Skipping the broken bitmaps works,...
|
|
echo
|
|
$QEMU_IMG convert --bitmaps --skip-broken-bitmaps \
|
|
-O qcow2 "$TEST_IMG" "$TEST_IMG.copy"
|
|
TEST_IMG="$TEST_IMG.copy" _img_info --format-specific \
|
|
| _filter_irrelevant_img_info
|
|
# ...as does removing them
|
|
echo
|
|
_rm_test_img "$TEST_IMG.copy"
|
|
$QEMU_IMG bitmap --remove "$TEST_IMG" b0
|
|
$QEMU_IMG bitmap --remove --add "$TEST_IMG" b2
|
|
$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG" "$TEST_IMG.copy"
|
|
TEST_IMG="$TEST_IMG.copy" _img_info --format-specific \
|
|
| _filter_irrelevant_img_info
|
|
|
|
# success, all done
|
|
echo '*** done'
|
|
rm -f $seq.full
|
|
status=0
|