From 5e8f99ea87409e1423c2e1c5e445003cf4a032a9 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 6 Aug 2021 15:07:48 -0400 Subject: [PATCH 25/39] qemu-img: Fail fast on convert --bitmaps with inconsistent bitmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Miroslav Rezanina RH-MergeRequest: 35: Synchronize with RHEL-AV 8.5 release 28 to RHEL 9 RH-Commit: [2/4] 3fd8d357c3a365d4bc142b3d339745e5b15c5894 (mrezanin/centos-src-qemu-kvm) RH-Bugzilla: 1957194 RH-Acked-by: Philippe Mathieu-Daudé Waiting until the end of the convert operation (a potentially time-consuming task) to finally detect that we can't copy a bitmap is bad, comparing to failing fast up front. Furthermore, this prevents us from leaving a file behind with a bitmap that is not marked as inconsistent even though it does not have sane contents. This fixes the problems exposed in the previous patch to the iotest: it adds a fast failure up front, and even if we don't fail early, it ensures that any bitmap we add but do not properly populate is removed again rather than left behind incomplete. Signed-off-by: Eric Blake Message-Id: <20210709153951.2801666-3-eblake@redhat.com> [eblake: add a hint to the warning message, simplify name computation] Reviewed-by: Nir Soffer Reviewed-by: Vladimir Sementsov-Ogievskiy (cherry picked from commit 74a4320f30632fa539507861b3835698282e462e) Signed-off-by: Eric Blake Signed-off-by: Danilo C. L. de Paula Signed-off-by: Miroslav Rezanina --- qemu-img.c | 29 +++++++++++++++++-- tests/qemu-iotests/tests/qemu-img-bitmaps | 3 +- tests/qemu-iotests/tests/qemu-img-bitmaps.out | 21 ++------------ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index babb5573ab..7684684bfa 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2098,6 +2098,29 @@ static int convert_do_copy(ImgConvertState *s) return s->ret; } +/* Check that bitmaps can be copied, or output an error */ +static int convert_check_bitmaps(BlockDriverState *src) +{ + BdrvDirtyBitmap *bm; + + if (!bdrv_supports_persistent_dirty_bitmap(src)) { + error_report("Source lacks bitmap support"); + return -1; + } + FOR_EACH_DIRTY_BITMAP(src, bm) { + if (!bdrv_dirty_bitmap_get_persistence(bm)) { + continue; + } + if (bdrv_dirty_bitmap_inconsistent(bm)) { + error_report("Cannot copy inconsistent bitmap '%s'", + bdrv_dirty_bitmap_name(bm)); + error_printf("Try 'qemu-img bitmap --remove' to delete it\n"); + return -1; + } + } + return 0; +} + static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst) { BdrvDirtyBitmap *bm; @@ -2124,6 +2147,7 @@ static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst) &err); if (err) { error_reportf_err(err, "Failed to populate bitmap %s: ", name); + qmp_block_dirty_bitmap_remove(dst->node_name, name, NULL); return -1; } } @@ -2549,9 +2573,8 @@ static int img_convert(int argc, char **argv) ret = -1; goto out; } - if (!bdrv_supports_persistent_dirty_bitmap(blk_bs(s.src[0]))) { - error_report("Source lacks bitmap support"); - ret = -1; + ret = convert_check_bitmaps(blk_bs(s.src[0])); + if (ret < 0) { goto out; } } diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps b/tests/qemu-iotests/tests/qemu-img-bitmaps index 409c4497a3..09c3d395d1 100755 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps @@ -140,11 +140,10 @@ $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" -# Bug - even though we failed at conversion, we left a file around with -# a bitmap marked as not corrupt TEST_IMG=$TEST_IMG.copy _img_info --format-specific \ | _filter_irrelevant_img_info diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps.out b/tests/qemu-iotests/tests/qemu-img-bitmaps.out index 543b028da6..1e32833bf1 100644 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps.out +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps.out @@ -144,22 +144,7 @@ Format specific information: granularity: 65536 corrupt: false -qemu-img: Failed to populate bitmap b0: Bitmap 'b0' is inconsistent and cannot be used -Try block-dirty-bitmap-remove to delete this bitmap from disk -image: TEST_DIR/t.IMGFMT.copy -file format: IMGFMT -virtual size: 10 MiB (10485760 bytes) -cluster_size: 65536 -Format specific information: - bitmaps: - [0]: - flags: - name: b0 - granularity: 65536 - [1]: - flags: - [0]: auto - name: b4 - granularity: 65536 - corrupt: false +qemu-img: Cannot copy inconsistent bitmap 'b0' +Try 'qemu-img bitmap --remove' to delete it +qemu-img: Could not open 'TEST_DIR/t.IMGFMT.copy': Could not open 'TEST_DIR/t.IMGFMT.copy': No such file or directory *** done -- 2.27.0