From 269ee27e99cfbff983a9ab067ae22f6182f11fe2 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 7 Feb 2019 13:13:57 -0600 Subject: [PATCH 1/4] nbd/server: Kill pointless shadowed variable lgtm.com pointed out that commit 678ba275 introduced a shadowed declaration of local variable 'bs'; thankfully, the inner 'bs' obtained by 'blk_bs(blk)' matches the outer one given that we had 'blk_insert_bs(blk, bs, errp)' a few lines earlier, and there are no later uses of 'bs' beyond the scope of the 'if (bitmap)' to care if we change the value stored in 'bs' while traveling the backing chain to find a bitmap. So simply get rid of the extra declaration. Reported-by: Peter Maydell Signed-off-by: Eric Blake Message-Id: <20190207191357.6665-1-eblake@redhat.com> Signed-off-by: Eric Blake --- nbd/server.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nbd/server.c b/nbd/server.c index 838c150d8c..0910d09a6d 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1495,7 +1495,6 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset, if (bitmap) { BdrvDirtyBitmap *bm = NULL; - BlockDriverState *bs = blk_bs(blk); while (true) { bm = bdrv_find_dirty_bitmap(bs, bitmap); From 1bf6e9ca9234e1dbcaa18baa06eca9d55cc2dbbb Mon Sep 17 00:00:00 2001 From: Andrey Shinkevich Date: Fri, 8 Feb 2019 18:06:06 +0300 Subject: [PATCH 2/4] bdrv_query_image_info Error parameter added Inform a user in case qcow2_get_specific_info fails to obtain QCOW2 image specific information. This patch is preliminary to the one "qcow2: Add list of bitmaps to ImageInfoSpecificQCow2". Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Kevin Wolf Message-Id: <1549638368-530182-2-git-send-email-andrey.shinkevich@virtuozzo.com> Signed-off-by: Eric Blake --- block.c | 5 +++-- block/crypto.c | 9 +++------ block/qapi.c | 7 ++++++- block/qcow2.c | 10 ++++++++-- block/vmdk.c | 3 ++- include/block/block.h | 3 ++- include/block/block_int.h | 3 ++- qemu-io-cmds.c | 7 ++++++- 8 files changed, 32 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index b67d9b7b65..4ad0e90d7e 100644 --- a/block.c +++ b/block.c @@ -4462,11 +4462,12 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return drv->bdrv_get_info(bs, bdi); } -ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs) +ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs, + Error **errp) { BlockDriver *drv = bs->drv; if (drv && drv->bdrv_get_specific_info) { - return drv->bdrv_get_specific_info(bs); + return drv->bdrv_get_specific_info(bs, errp); } return NULL; } diff --git a/block/crypto.c b/block/crypto.c index f0a5f6b987..d5b1da66a1 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -594,20 +594,17 @@ static int block_crypto_get_info_luks(BlockDriverState *bs, } static ImageInfoSpecific * -block_crypto_get_specific_info_luks(BlockDriverState *bs) +block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp) { BlockCrypto *crypto = bs->opaque; ImageInfoSpecific *spec_info; QCryptoBlockInfo *info; - info = qcrypto_block_get_info(crypto->block, NULL); + info = qcrypto_block_get_info(crypto->block, errp); if (!info) { return NULL; } - if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) { - qapi_free_QCryptoBlockInfo(info); - return NULL; - } + assert(info->format == Q_CRYPTO_BLOCK_FORMAT_LUKS); spec_info = g_new(ImageInfoSpecific, 1); spec_info->type = IMAGE_INFO_SPECIFIC_KIND_LUKS; diff --git a/block/qapi.c b/block/qapi.c index c66f949db8..00291f9105 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -282,7 +282,12 @@ void bdrv_query_image_info(BlockDriverState *bs, info->dirty_flag = bdi.is_dirty; info->has_dirty_flag = true; } - info->format_specific = bdrv_get_specific_info(bs); + info->format_specific = bdrv_get_specific_info(bs, &err); + if (err) { + error_propagate(errp, err); + qapi_free_ImageInfo(info); + goto out; + } info->has_format_specific = info->format_specific != NULL; backing_filename = bs->backing_file; diff --git a/block/qcow2.c b/block/qcow2.c index 8c91b92865..bcb80d0270 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4368,14 +4368,20 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } -static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) +static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, + Error **errp) { BDRVQcow2State *s = bs->opaque; ImageInfoSpecific *spec_info; QCryptoBlockInfo *encrypt_info = NULL; + Error *local_err = NULL; if (s->crypto != NULL) { - encrypt_info = qcrypto_block_get_info(s->crypto, &error_abort); + encrypt_info = qcrypto_block_get_info(s->crypto, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return NULL; + } } spec_info = g_new(ImageInfoSpecific, 1); diff --git a/block/vmdk.c b/block/vmdk.c index 682ad93aa1..096e8eb662 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2543,7 +2543,8 @@ static int coroutine_fn vmdk_co_check(BlockDriverState *bs, return ret; } -static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs) +static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs, + Error **errp) { int i; BDRVVmdkState *s = bs->opaque; diff --git a/include/block/block.h b/include/block/block.h index 57233cf2c0..73357c6c25 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -478,7 +478,8 @@ const char *bdrv_get_device_name(const BlockDriverState *bs); const char *bdrv_get_device_or_node_name(const BlockDriverState *bs); int bdrv_get_flags(BlockDriverState *bs); int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); -ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs); +ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs, + Error **errp); void bdrv_round_to_clusters(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *cluster_offset, diff --git a/include/block/block_int.h b/include/block/block_int.h index f605622216..0075bafd10 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -319,7 +319,8 @@ struct BlockDriver { const char *name, Error **errp); int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); - ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs); + ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs, + Error **errp); int coroutine_fn (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov, diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index ee8f56e46a..b9f189f09b 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1661,6 +1661,7 @@ static int info_f(BlockBackend *blk, int argc, char **argv) BlockDriverState *bs = blk_bs(blk); BlockDriverInfo bdi; ImageInfoSpecific *spec_info; + Error *local_err = NULL; char s1[64], s2[64]; int ret; @@ -1682,7 +1683,11 @@ static int info_f(BlockBackend *blk, int argc, char **argv) printf("cluster size: %s\n", s1); printf("vm state offset: %s\n", s2); - spec_info = bdrv_get_specific_info(bs); + spec_info = bdrv_get_specific_info(bs, &local_err); + if (local_err) { + error_report_err(local_err); + return -EIO; + } if (spec_info) { printf("Format specific information:\n"); bdrv_image_info_specific_dump(fprintf, stdout, spec_info); From b8968c875f4030dd6924d6971bb3d92dfa3d2f65 Mon Sep 17 00:00:00 2001 From: Andrey Shinkevich Date: Fri, 8 Feb 2019 18:06:07 +0300 Subject: [PATCH 3/4] qcow2: Add list of bitmaps to ImageInfoSpecificQCow2 In the 'Format specific information' section of the 'qemu-img info' command output, the supplemental information about existing QCOW2 bitmaps will be shown, such as a bitmap name, flags and granularity: image: /vz/vmprivate/VM1/harddisk.hdd file format: qcow2 virtual size: 64G (68719476736 bytes) disk size: 3.0M cluster_size: 1048576 Format specific information: compat: 1.1 lazy refcounts: true bitmaps: [0]: flags: [0]: in-use [1]: auto name: back-up1 granularity: 65536 [1]: flags: [0]: in-use [1]: auto name: back-up2 granularity: 65536 refcount bits: 16 corrupt: false Signed-off-by: Andrey Shinkevich Reviewed-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <1549638368-530182-3-git-send-email-andrey.shinkevich@virtuozzo.com> Signed-off-by: Eric Blake --- block/qcow2-bitmap.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ block/qcow2.c | 11 ++++++- block/qcow2.h | 2 ++ qapi/block-core.json | 41 +++++++++++++++++++++++- 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index b946301429..3ee524da4b 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1006,6 +1006,82 @@ fail: return false; } + +static Qcow2BitmapInfoFlagsList *get_bitmap_info_flags(uint32_t flags) +{ + Qcow2BitmapInfoFlagsList *list = NULL; + Qcow2BitmapInfoFlagsList **plist = &list; + int i; + + static const struct { + int bme; /* Bitmap directory entry flags */ + int info; /* The flags to report to the user */ + } map[] = { + { BME_FLAG_IN_USE, QCOW2_BITMAP_INFO_FLAGS_IN_USE }, + { BME_FLAG_AUTO, QCOW2_BITMAP_INFO_FLAGS_AUTO }, + }; + + int map_size = ARRAY_SIZE(map); + + for (i = 0; i < map_size; ++i) { + if (flags & map[i].bme) { + Qcow2BitmapInfoFlagsList *entry = + g_new0(Qcow2BitmapInfoFlagsList, 1); + entry->value = map[i].info; + *plist = entry; + plist = &entry->next; + flags &= ~map[i].bme; + } + } + /* Check if the BME_* mapping above is complete */ + assert(!flags); + + return list; +} + +/* + * qcow2_get_bitmap_info_list() + * Returns a list of QCOW2 bitmap details. + * In case of no bitmaps, the function returns NULL and + * the @errp parameter is not set. + * When bitmap information can not be obtained, the function returns + * NULL and the @errp parameter is set. + */ +Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + Qcow2BitmapInfoList *list = NULL; + Qcow2BitmapInfoList **plist = &list; + + if (s->nb_bitmaps == 0) { + return NULL; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + return NULL; + } + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + Qcow2BitmapInfo *info = g_new0(Qcow2BitmapInfo, 1); + Qcow2BitmapInfoList *obj = g_new0(Qcow2BitmapInfoList, 1); + info->granularity = 1U << bm->granularity_bits; + info->name = g_strdup(bm->name); + info->flags = get_bitmap_info_flags(bm->flags & ~BME_RESERVED_FLAGS); + obj->value = info; + *plist = obj; + plist = &obj->next; + } + + bitmap_list_free(bm_list); + + return list; +} + int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated, Error **errp) { diff --git a/block/qcow2.c b/block/qcow2.c index bcb80d0270..65a54c9ac6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4387,7 +4387,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, spec_info = g_new(ImageInfoSpecific, 1); *spec_info = (ImageInfoSpecific){ .type = IMAGE_INFO_SPECIFIC_KIND_QCOW2, - .u.qcow2.data = g_new(ImageInfoSpecificQCow2, 1), + .u.qcow2.data = g_new0(ImageInfoSpecificQCow2, 1), }; if (s->qcow_version == 2) { *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){ @@ -4395,6 +4395,13 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, .refcount_bits = s->refcount_bits, }; } else if (s->qcow_version == 3) { + Qcow2BitmapInfoList *bitmaps; + bitmaps = qcow2_get_bitmap_info_list(bs, &local_err); + if (local_err) { + error_propagate(errp, local_err); + qapi_free_ImageInfoSpecific(spec_info); + return NULL; + } *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){ .compat = g_strdup("1.1"), .lazy_refcounts = s->compatible_features & @@ -4404,6 +4411,8 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, QCOW2_INCOMPAT_CORRUPT, .has_corrupt = true, .refcount_bits = s->refcount_bits, + .has_bitmaps = !!bitmaps, + .bitmaps = bitmaps, }; } else { /* if this assertion fails, this probably means a new version was diff --git a/block/qcow2.h b/block/qcow2.h index 32cce9eee2..9dd02df831 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -684,6 +684,8 @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, int64_t *refcount_table_size); bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp); +Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs, + Error **errp); int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated, Error **errp); int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp); diff --git a/qapi/block-core.json b/qapi/block-core.json index 5f17d67d71..0f349d4603 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -69,6 +69,8 @@ # @encrypt: details about encryption parameters; only set if image # is encrypted (since 2.10) # +# @bitmaps: A list of qcow2 bitmap details (since 4.0) +# # Since: 1.7 ## { 'struct': 'ImageInfoSpecificQCow2', @@ -77,7 +79,8 @@ '*lazy-refcounts': 'bool', '*corrupt': 'bool', 'refcount-bits': 'int', - '*encrypt': 'ImageInfoSpecificQCow2Encryption' + '*encrypt': 'ImageInfoSpecificQCow2Encryption', + '*bitmaps': ['Qcow2BitmapInfo'] } } ## @@ -453,6 +456,42 @@ 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32', 'status': 'DirtyBitmapStatus'} } +## +# @Qcow2BitmapInfoFlags: +# +# An enumeration of flags that a bitmap can report to the user. +# +# @in-use: This flag is set by any process actively modifying the qcow2 file, +# and cleared when the updated bitmap is flushed to the qcow2 image. +# The presence of this flag in an offline image means that the bitmap +# was not saved correctly after its last usage, and may contain +# inconsistent data. +# +# @auto: The bitmap must reflect all changes of the virtual disk by any +# application that would write to this qcow2 file. +# +# Since: 4.0 +## +{ 'enum': 'Qcow2BitmapInfoFlags', + 'data': ['in-use', 'auto'] } + +## +# @Qcow2BitmapInfo: +# +# Qcow2 bitmap information. +# +# @name: the name of the bitmap +# +# @granularity: granularity of the bitmap in bytes +# +# @flags: flags of the bitmap +# +# Since: 4.0 +## +{ 'struct': 'Qcow2BitmapInfo', + 'data': {'name': 'str', 'granularity': 'uint32', + 'flags': ['Qcow2BitmapInfoFlags'] } } + ## # @BlockLatencyHistogramInfo: # From ddd113beedd22908e676d53803843d2f85bf91ab Mon Sep 17 00:00:00 2001 From: Andrey Shinkevich Date: Fri, 8 Feb 2019 18:06:08 +0300 Subject: [PATCH 4/4] qcow2: list of bitmaps new test 242 A new test file 242 added to the qemu-iotests set. It checks the format of qcow2 specific information for the new added section that lists details of bitmaps. Signed-off-by: Andrey Shinkevich Message-Id: <1549638368-530182-4-git-send-email-andrey.shinkevich@virtuozzo.com> Reviewed-by: Eric Blake [eblake: pep8 compliance, avoid trailing blank line] Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Eric Blake --- tests/qemu-iotests/242 | 104 +++++++++++++++++++++++ tests/qemu-iotests/242.out | 166 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 271 insertions(+) create mode 100755 tests/qemu-iotests/242 create mode 100644 tests/qemu-iotests/242.out diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242 new file mode 100755 index 0000000000..16c65edcd7 --- /dev/null +++ b/tests/qemu-iotests/242 @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# Test for qcow2 bitmap printed information +# +# Copyright (c) 2019 Virtuozzo International GmbH +# +# 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 . +# + +import iotests +import json +from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \ + file_path, img_info_log, log, filter_qemu_io + +iotests.verify_image_format(supported_fmts=['qcow2']) + +disk = file_path('disk') +chunk = 256 * 1024 +bitmap_flag_unknown = 1 << 2 +# flag_offset = 5*cluster_size + flag_offset_in_bitmap_directory_entry +flag_offset = 0x5000f + + +def print_bitmap(extra_args): + log('qemu-img info dump:\n') + img_info_log(disk, extra_args=extra_args) + result = json.loads(qemu_img_pipe('info', '--force-share', + '--output=json', disk)) + if 'bitmaps' in result['format-specific']['data']: + bitmaps = result['format-specific']['data']['bitmaps'] + log('The same bitmaps in JSON format:') + log(bitmaps, indent=2) + else: + log('No bitmap in JSON format output') + + +def add_bitmap(bitmap_number, persistent, disabled): + granularity = 1 << (13 + bitmap_number) + bitmap_name = 'bitmap-' + str(bitmap_number-1) + vm = iotests.VM().add_drive(disk) + vm.launch() + vm.qmp_log('block-dirty-bitmap-add', node='drive0', name=bitmap_name, + granularity=granularity, persistent=persistent, + disabled=disabled) + vm.shutdown() + + +def write_to_disk(offset, size): + write = 'write {} {}'.format(offset, size) + log(qemu_io('-c', write, disk), filters=[filter_qemu_io]) + + +def toggle_flag(offset): + with open(disk, "r+b") as f: + f.seek(offset, 0) + c = f.read(1) + toggled = chr(ord(c) ^ bitmap_flag_unknown) + f.seek(-1, 1) + f.write(toggled) + + +qemu_img_create('-f', iotests.imgfmt, disk, '1M') + +for num in range(1, 4): + disabled = False + if num == 2: + disabled = True + log('Test {}'.format(num)) + add_bitmap(num, num > 1, disabled) + write_to_disk((num-1) * chunk, chunk) + print_bitmap([]) + log('') + +vm = iotests.VM().add_drive(disk) +vm.launch() +num += 1 +log('Test {}\nChecking "in-use" flag...'.format(num)) +print_bitmap(['--force-share']) +vm.shutdown() + +num += 1 +log('\nTest {}'.format(num)) +qemu_img_create('-f', iotests.imgfmt, disk, '1M') +add_bitmap(1, True, False) +log('Write an unknown bitmap flag \'{}\' into a new QCOW2 image at offset {}' + .format(hex(bitmap_flag_unknown), flag_offset)) +toggle_flag(flag_offset) +img_info_log(disk) +toggle_flag(flag_offset) +log('Unset the unknown bitmap flag \'{}\' in the bitmap directory entry:\n' + .format(hex(bitmap_flag_unknown))) +img_info_log(disk) +log('Test complete') diff --git a/tests/qemu-iotests/242.out b/tests/qemu-iotests/242.out new file mode 100644 index 0000000000..fbe05d71c0 --- /dev/null +++ b/tests/qemu-iotests/242.out @@ -0,0 +1,166 @@ +Test 1 +{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 16384, "name": "bitmap-0", "node": "drive0", "persistent": false}} +{"return": {}} +wrote 262144/262144 bytes at offset 0 +256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +qemu-img info dump: + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0M (1048576 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + lazy refcounts: false + refcount bits: 16 + corrupt: false + +No bitmap in JSON format output + +Test 2 +{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": true, "granularity": 32768, "name": "bitmap-1", "node": "drive0", "persistent": true}} +{"return": {}} +wrote 262144/262144 bytes at offset 262144 +256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +qemu-img info dump: + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0M (1048576 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + lazy refcounts: false + bitmaps: + [0]: + flags: + name: bitmap-1 + granularity: 32768 + refcount bits: 16 + corrupt: false + +The same bitmaps in JSON format: +[ + { + "flags": [], + "granularity": 32768, + "name": "bitmap-1" + } +] + +Test 3 +{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 65536, "name": "bitmap-2", "node": "drive0", "persistent": true}} +{"return": {}} +wrote 262144/262144 bytes at offset 524288 +256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +qemu-img info dump: + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0M (1048576 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + lazy refcounts: false + bitmaps: + [0]: + flags: + name: bitmap-1 + granularity: 32768 + [1]: + flags: + [0]: auto + name: bitmap-2 + granularity: 65536 + refcount bits: 16 + corrupt: false + +The same bitmaps in JSON format: +[ + { + "flags": [], + "granularity": 32768, + "name": "bitmap-1" + }, + { + "flags": [ + "auto" + ], + "granularity": 65536, + "name": "bitmap-2" + } +] + +Test 4 +Checking "in-use" flag... +qemu-img info dump: + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0M (1048576 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + lazy refcounts: false + bitmaps: + [0]: + flags: + [0]: in-use + name: bitmap-1 + granularity: 32768 + [1]: + flags: + [0]: in-use + [1]: auto + name: bitmap-2 + granularity: 65536 + refcount bits: 16 + corrupt: false + +The same bitmaps in JSON format: +[ + { + "flags": [ + "in-use" + ], + "granularity": 32768, + "name": "bitmap-1" + }, + { + "flags": [ + "in-use", + "auto" + ], + "granularity": 65536, + "name": "bitmap-2" + } +] + +Test 5 +{"execute": "block-dirty-bitmap-add", "arguments": {"disabled": false, "granularity": 16384, "name": "bitmap-0", "node": "drive0", "persistent": true}} +{"return": {}} +Write an unknown bitmap flag '0x4' into a new QCOW2 image at offset 327695 +qemu-img: Could not open 'TEST_IMG': Bitmap 'bitmap-0' doesn't satisfy the constraints + +Unset the unknown bitmap flag '0x4' in the bitmap directory entry: + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0M (1048576 bytes) +cluster_size: 65536 +Format specific information: + compat: 1.1 + lazy refcounts: false + bitmaps: + [0]: + flags: + [0]: auto + name: bitmap-0 + granularity: 16384 + refcount bits: 16 + corrupt: false + +Test complete diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 959ffe85fc..fc4c416fa3 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -238,3 +238,4 @@ 238 auto quick 239 rw auto quick 240 auto quick +242 rw auto quick