[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v5 2/5] qcow2: Expose bitmaps' size during measure
From: |
Nir Soffer |
Subject: |
Re: [PATCH v5 2/5] qcow2: Expose bitmaps' size during measure |
Date: |
Thu, 21 May 2020 02:00:37 +0300 |
On Thu, May 21, 2020 at 1:01 AM Eric Blake <address@hidden> wrote:
>
> It's useful to know how much space can be occupied by qcow2 persistent
> bitmaps, even though such metadata is unrelated to the guest-visible
> data. Report this value as an additional QMP field, present when
> measuring an existing image and output format that both support
> bitmaps. Update iotest 178 and 190 to updated output, as well as new
> coverage in 190 demonstrating non-zero values made possible with the
> recently-added qemu-img bitmap command.
>
> On the command-line side, 'qemu-img measure' gains a new --bitmaps
> flag. When present, the bitmap size is rolled into the two existing
> measures (or errors if either the source image or destination format
> lacks bitmaps); when absent, there is never an error (for
> back-compat), but the output will instead include a new line item for
> bitmaps (which you would have to manually add), with that line being
> omitted in the same cases where passing --bitmaps would error.
Supporting 2 ways to measure, one by specifying --bitmaps, and another
by adding bitmaps key is not a good idea. We really need one way.
Each one has advantages. adding --bitmaps flag is consistent with
"qemu-img convert"
and future extensions that may require new flag, and adding "bitmaps"
key is consistent
with "qmeu-img info", showing bitmaps when they exist.
Adding a "bitmaps" key has an advantage that we can use it to test if qemu-img
supports measuring and copying bitmaps (since both features are expected to
be delivered at the same time). So we can avoid checking --help learn about
the capabilities.
I'm ok with both options, can we have only one?
> The behavior chosen here is symmetrical with the upcoming 'qemu-img
> convert --bitmaps' being added in the next patch: that is, either both
> commands will succeed (your qemu-img was new enough to do bitmap
> manipulations, AND you correctly measured and copied the bitmaps, even
> if that measurement was 0 because there was nothing to copy) or both
> fail (either your qemu-img is too old to understand --bitmaps, or it
> understands it but your choice of images do not support seamless
> transition of bitmaps because either source, destination, or both lack
> bitmap support).
>
> The addition of a new field demonstrates why we should always
> zero-initialize qapi C structs; while the qcow2 driver still fully
> populates all fields, the raw and crypto drivers had to be tweaked to
> avoid uninitialized data.
>
> See also: https://bugzilla.redhat.com/1779904
>
> Reported-by: Nir Soffer <address@hidden>
> Signed-off-by: Eric Blake <address@hidden>
> ---
> docs/tools/qemu-img.rst | 12 ++++++-
> qapi/block-core.json | 15 ++++++---
> block/qcow2.h | 2 ++
> block/crypto.c | 2 +-
> block/qcow2-bitmap.c | 36 ++++++++++++++++++++
> block/qcow2.c | 14 ++++++--
> block/raw-format.c | 2 +-
> qemu-img.c | 25 ++++++++++++++
> qemu-img-cmds.hx | 4 +--
> tests/qemu-iotests/178.out.qcow2 | 16 +++++++++
> tests/qemu-iotests/190 | 58 ++++++++++++++++++++++++++++++--
> tests/qemu-iotests/190.out | 35 ++++++++++++++++++-
> 12 files changed, 205 insertions(+), 16 deletions(-)
>
> diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
> index 38d464ea3f23..9a8112fc9f58 100644
> --- a/docs/tools/qemu-img.rst
> +++ b/docs/tools/qemu-img.rst
> @@ -593,7 +593,7 @@ Command description:
> For more information, consult ``include/block/block.h`` in QEMU's
> source code.
>
> -.. option:: measure [--output=OFMT] [-O OUTPUT_FMT] [-o OPTIONS] [--size N |
> [--object OBJECTDEF] [--image-opts] [-f FMT] [-l SNAPSHOT_PARAM] FILENAME]
> +.. option:: measure [--output=OFMT] [-O OUTPUT_FMT] [-o OPTIONS] [--size N |
> [--object OBJECTDEF] [--image-opts] [-f FMT] [--bitmaps] [-l SNAPSHOT_PARAM]
> FILENAME]
>
> Calculate the file size required for a new image. This information
> can be used to size logical volumes or SAN LUNs appropriately for
> @@ -616,6 +616,7 @@ Command description:
>
> required size: 524288
> fully allocated size: 1074069504
> + bitmaps size: 0
>
> The ``required size`` is the file size of the new image. It may be smaller
> than the virtual disk size if the image format supports compact
> representation.
> @@ -625,6 +626,15 @@ Command description:
> occupy with the exception of internal snapshots, dirty bitmaps, vmstate
> data,
> and other advanced image format features.
>
> + The ``bitmaps size`` is the additional size required in order to
> + copy bitmaps from a source image in addition to the guest-visible
> + data; the line is omitted if either source or destination lacks
> + bitmap support, or 0 if bitmaps are supported but there is nothing
> + to copy. If the ``--bitmaps`` option is in use, the bitmap size is
> + instead folded into the required and fully-allocated size for
> + convenience, rather than being a separate line item; using the
> + option will raise an error if bitmaps are not supported.
> +
> .. option:: snapshot [--object OBJECTDEF] [--image-opts] [-U] [-q] [-l | -a
> SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
>
> List, apply, create or delete snapshots in image *FILENAME*.
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 6fbacddab2cc..d5049c309380 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -636,18 +636,23 @@
> # efficiently so file size may be smaller than virtual disk size.
> #
> # The values are upper bounds that are guaranteed to fit the new image file.
> -# Subsequent modification, such as internal snapshot or bitmap creation, may
> -# require additional space and is not covered here.
> +# Subsequent modification, such as internal snapshot or further bitmap
> +# creation, may require additional space and is not covered here.
> #
> -# @required: Size required for a new image file, in bytes.
> +# @required: Size required for a new image file, in bytes, when copying just
> +# allocated guest-visible contents.
> #
> # @fully-allocated: Image file size, in bytes, once data has been written
> -# to all sectors.
> +# to all sectors, when copying just guest-visible contents.
> +#
> +# @bitmaps: Additional size required if all the top-level bitmap metadata in
> +# the source image were to be copied to the destination, present
> +# when the destination supports persistent bitmaps. (since 5.1)
> #
> # Since: 2.10
> ##
> { 'struct': 'BlockMeasureInfo',
> - 'data': {'required': 'int', 'fully-allocated': 'int'} }
> + 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} }
>
> ##
> # @query-block:
> diff --git a/block/qcow2.h b/block/qcow2.h
> index 402e8acb1cb7..7ce2c23bdb7a 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -783,6 +783,8 @@ int
> qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
> const char *name,
> Error **errp);
> bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
> +uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
> + uint32_t cluster_size);
>
> ssize_t coroutine_fn
> qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
> diff --git a/block/crypto.c b/block/crypto.c
> index b216e12c3154..973b57b3eb74 100644
> --- a/block/crypto.c
> +++ b/block/crypto.c
> @@ -552,7 +552,7 @@ static BlockMeasureInfo *block_crypto_measure(QemuOpts
> *opts,
> * Unallocated blocks are still encrypted so allocation status makes no
> * difference to the file size.
> */
> - info = g_new(BlockMeasureInfo, 1);
> + info = g_new0(BlockMeasureInfo, 1);
> info->fully_allocated = luks_payload_size + size;
> info->required = luks_payload_size + size;
> return info;
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index 1cf6d2ab77a3..7bf12502da8c 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -1755,3 +1755,39 @@ bool
> qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
>
> return s->qcow_version >= 3;
> }
> +
> +/*
> + * Compute the space required for bitmaps in @bs.
> + *
> + * The computation is based as if copying to a new image with the
> + * given @cluster_size, which may differ from the cluster size in @bs.
> + */
> +uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
> + uint32_t cluster_size)
> +{
> + uint64_t bitmaps_size = 0;
> + BdrvDirtyBitmap *bm;
> + size_t bitmap_dir_size = 0;
> +
> + FOR_EACH_DIRTY_BITMAP(bs, bm) {
> + if (bdrv_dirty_bitmap_get_persistence(bm)) {
> + const char *name = bdrv_dirty_bitmap_name(bm);
> + uint32_t granularity = bdrv_dirty_bitmap_granularity(bm);
> + uint64_t bmbytes =
> + get_bitmap_bytes_needed(bdrv_dirty_bitmap_size(bm),
> + granularity);
> + uint64_t bmclusters = DIV_ROUND_UP(bmbytes, cluster_size);
> +
> + /* Assume the entire bitmap is allocated */
> + bitmaps_size += bmclusters * cluster_size;
> + /* Also reserve space for the bitmap table entries */
> + bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t),
> + cluster_size);
> + /* And space for contribution to bitmap directory size */
> + bitmap_dir_size += calc_dir_entry_size(strlen(name), 0);
> + }
> + }
> + bitmaps_size += ROUND_UP(bitmap_dir_size, cluster_size);
> +
> + return bitmaps_size;
> +}
> diff --git a/block/qcow2.c b/block/qcow2.c
> index dfab8d2f6cd8..0cd2e6757e8c 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -4953,16 +4953,24 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts
> *opts, BlockDriverState *in_bs,
> required = virtual_size;
> }
>
> - info = g_new(BlockMeasureInfo, 1);
> + info = g_new0(BlockMeasureInfo, 1);
> info->fully_allocated =
> qcow2_calc_prealloc_size(virtual_size, cluster_size,
> ctz32(refcount_bits)) + luks_payload_size;
>
> - /* Remove data clusters that are not required. This overestimates the
> + /*
> + * Remove data clusters that are not required. This overestimates the
> * required size because metadata needed for the fully allocated file is
> - * still counted.
> + * still counted. Show bitmaps only if both source and destination
> + * would support them.
> */
> info->required = info->fully_allocated - virtual_size + required;
> + info->has_bitmaps = version >= 3 && in_bs &&
> + bdrv_supports_persistent_dirty_bitmap(in_bs);
> + if (info->has_bitmaps) {
> + info->bitmaps = qcow2_get_persistent_dirty_bitmap_size(in_bs,
> + cluster_size);
> + }
> return info;
>
> err:
> diff --git a/block/raw-format.c b/block/raw-format.c
> index 018441bddf27..233d019ca338 100644
> --- a/block/raw-format.c
> +++ b/block/raw-format.c
> @@ -359,7 +359,7 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts,
> BlockDriverState *in_bs,
> BDRV_SECTOR_SIZE);
> }
>
> - info = g_new(BlockMeasureInfo, 1);
> + info = g_new0(BlockMeasureInfo, 1);
> info->required = required;
>
> /* Unallocated sectors count towards the file size in raw images */
> diff --git a/qemu-img.c b/qemu-img.c
> index 2d30682f129f..d719b9d35468 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -78,6 +78,7 @@ enum {
> OPTION_ENABLE = 272,
> OPTION_DISABLE = 273,
> OPTION_MERGE = 274,
> + OPTION_BITMAPS = 275,
> };
>
> typedef enum OutputFormat {
> @@ -5128,6 +5129,7 @@ static int img_measure(int argc, char **argv)
> {"output", required_argument, 0, OPTION_OUTPUT},
> {"size", required_argument, 0, OPTION_SIZE},
> {"force-share", no_argument, 0, 'U'},
> + {"bitmaps", no_argument, 0, OPTION_BITMAPS},
> {0, 0, 0, 0}
> };
> OutputFormat output_format = OFORMAT_HUMAN;
> @@ -5144,6 +5146,7 @@ static int img_measure(int argc, char **argv)
> QemuOpts *sn_opts = NULL;
> QemuOptsList *create_opts = NULL;
> bool image_opts = false;
> + bool bitmaps = false;
> uint64_t img_size = UINT64_MAX;
> BlockMeasureInfo *info = NULL;
> Error *local_err = NULL;
> @@ -5216,6 +5219,9 @@ static int img_measure(int argc, char **argv)
> img_size = (uint64_t)sval;
> }
> break;
> + case OPTION_BITMAPS:
> + bitmaps = true;
> + break;
> }
> }
>
> @@ -5244,6 +5250,10 @@ static int img_measure(int argc, char **argv)
> error_report("Either --size N or one filename must be specified.");
> goto out;
> }
> + if (!filename && bitmaps) {
> + error_report("--bitmaps is only supported with a filename.");
> + goto out;
> + }
>
> if (filename) {
> in_blk = img_open(image_opts, filename, fmt, 0,
> @@ -5299,9 +5309,24 @@ static int img_measure(int argc, char **argv)
> goto out;
> }
>
> + if (bitmaps) {
> + if (!info->has_bitmaps) {
> + error_report("no bitmaps measured, either source or destination "
> + "format lacks bitmap support");
> + goto out;
> + } else {
> + info->required += info->bitmaps;
> + info->fully_allocated += info->bitmaps;
> + info->has_bitmaps = false;
> + }
> + }
> +
> if (output_format == OFORMAT_HUMAN) {
> printf("required size: %" PRIu64 "\n", info->required);
> printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated);
> + if (info->has_bitmaps) {
> + printf("bitmaps size: %" PRIu64 "\n", info->bitmaps);
> + }
> } else {
> dump_json_block_measure_info(info);
> }
> diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
> index a87d3cb264ce..235cc5fffadc 100644
> --- a/qemu-img-cmds.hx
> +++ b/qemu-img-cmds.hx
> @@ -76,9 +76,9 @@ SRST
> ERST
>
> DEF("measure", img_measure,
> -"measure [--output=ofmt] [-O output_fmt] [-o options] [--size N | [--object
> objectdef] [--image-opts] [-f fmt] [-l snapshot_param] filename]")
> +"measure [--output=ofmt] [-O output_fmt] [-o options] [--size N | [--object
> objectdef] [--image-opts] [-f fmt] [--bitmaps] [-l snapshot_param] filename]")
> SRST
> -.. option:: measure [--output=OFMT] [-O OUTPUT_FMT] [-o OPTIONS] [--size N |
> [--object OBJECTDEF] [--image-opts] [-f FMT] [-l SNAPSHOT_PARAM] FILENAME]
> +.. option:: measure [--output=OFMT] [-O OUTPUT_FMT] [-o OPTIONS] [--size N |
> [--object OBJECTDEF] [--image-opts] [-f FMT] [--bitmaps] [-l SNAPSHOT_PARAM]
> FILENAME]
> ERST
>
> DEF("snapshot", img_snapshot,
> diff --git a/tests/qemu-iotests/178.out.qcow2
> b/tests/qemu-iotests/178.out.qcow2
> index 4b69524c80ee..c7997760fd6f 100644
> --- a/tests/qemu-iotests/178.out.qcow2
> +++ b/tests/qemu-iotests/178.out.qcow2
> @@ -37,6 +37,7 @@ qemu-img: The image size is too large (try using a larger
> cluster size)
> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
> required size: 196608
> fully allocated size: 196608
> +bitmaps size: 0
>
> converted image file size in bytes: 196608
>
> @@ -45,6 +46,7 @@ converted image file size in bytes: 196608
> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
> required size: 393216
> fully allocated size: 1074135040
> +bitmaps size: 0
> wrote 512/512 bytes at offset 512
> 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> wrote 65536/65536 bytes at offset 65536
> @@ -53,6 +55,7 @@ wrote 64512/64512 bytes at offset 134217728
> 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> required size: 589824
> fully allocated size: 1074135040
> +bitmaps size: 0
>
> converted image file size in bytes: 524288
>
> @@ -60,6 +63,7 @@ converted image file size in bytes: 524288
>
> required size: 524288
> fully allocated size: 1074135040
> +bitmaps size: 0
>
> converted image file size in bytes: 458752
>
> @@ -67,16 +71,19 @@ converted image file size in bytes: 458752
>
> required size: 1074135040
> fully allocated size: 1074135040
> +bitmaps size: 0
>
> == qcow2 input image and LUKS encryption ==
>
> required size: 2686976
> fully allocated size: 1076232192
> +bitmaps size: 0
>
> == qcow2 input image and preallocation (human) ==
>
> required size: 1074135040
> fully allocated size: 1074135040
> +bitmaps size: 0
>
> converted image file size in bytes: 1074135040
>
> @@ -87,6 +94,7 @@ wrote 8388608/8388608 bytes at offset 0
> 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> required size: 8716288
> fully allocated size: 8716288
> +bitmaps size: 0
>
> converted image file size in bytes: 8716288
>
> @@ -173,6 +181,7 @@ qemu-img: The image size is too large (try using a larger
> cluster size)
>
> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
> {
> + "bitmaps": 0,
> "required": 196608,
> "fully-allocated": 196608
> }
> @@ -183,6 +192,7 @@ converted image file size in bytes: 196608
>
> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
> {
> + "bitmaps": 0,
> "required": 393216,
> "fully-allocated": 1074135040
> }
> @@ -193,6 +203,7 @@ wrote 65536/65536 bytes at offset 65536
> wrote 64512/64512 bytes at offset 134217728
> 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> {
> + "bitmaps": 0,
> "required": 589824,
> "fully-allocated": 1074135040
> }
> @@ -202,6 +213,7 @@ converted image file size in bytes: 524288
> == qcow2 input image with internal snapshot (json) ==
>
> {
> + "bitmaps": 0,
> "required": 524288,
> "fully-allocated": 1074135040
> }
> @@ -211,6 +223,7 @@ converted image file size in bytes: 458752
> == qcow2 input image and a backing file (json) ==
>
> {
> + "bitmaps": 0,
> "required": 1074135040,
> "fully-allocated": 1074135040
> }
> @@ -218,6 +231,7 @@ converted image file size in bytes: 458752
> == qcow2 input image and LUKS encryption ==
>
> {
> + "bitmaps": 0,
> "required": 2686976,
> "fully-allocated": 1076232192
> }
> @@ -225,6 +239,7 @@ converted image file size in bytes: 458752
> == qcow2 input image and preallocation (json) ==
>
> {
> + "bitmaps": 0,
> "required": 1074135040,
> "fully-allocated": 1074135040
> }
> @@ -237,6 +252,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608
> wrote 8388608/8388608 bytes at offset 0
> 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> {
> + "bitmaps": 0,
> "required": 8716288,
> "fully-allocated": 8716288
> }
> diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
> index 6d41650438e1..acb23ebae44b 100755
> --- a/tests/qemu-iotests/190
> +++ b/tests/qemu-iotests/190
> @@ -2,7 +2,7 @@
> #
> # qemu-img measure sub-command tests on huge qcow2 files
> #
> -# Copyright (C) 2017 Red Hat, Inc.
> +# Copyright (C) 2017-2020 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
> @@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
> _supported_fmt qcow2
> _supported_proto file
>
> -echo "== Huge file =="
> +echo "== Huge file without bitmaps =="
> echo
>
> _make_test_img -o 'cluster_size=2M' 2T
> @@ -51,6 +51,60 @@ $QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG"
> $QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
> $QEMU_IMG measure -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG"
>
> +echo
> +echo "== Huge file with bitmaps =="
> +echo
> +
> +$QEMU_IMG bitmap --add --granularity 512 -f qcow2 "$TEST_IMG" b1
> +$QEMU_IMG bitmap --add -g 2M -f qcow2 "$TEST_IMG" b2
> +
> +# No bitmap without a source
> +$QEMU_IMG measure --bitmaps -O qcow2 --size 10M &&
> + echo "unexpected success"
> +# No bitmap output, since raw does not support it
> +$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG" ||
> + echo "unexpected failure"
> +$QEMU_IMG measure --bitmaps -O raw -f qcow2 "$TEST_IMG" &&
> + echo "unexpected success"
> +# No bitmap output, since no bitmaps on raw source
> +$QEMU_IMG measure -O qcow2 -f raw "$TEST_IMG" ||
> + echo "unexpected failure"
> +$QEMU_IMG measure --bitmaps -O qcow2 -f raw "$TEST_IMG" &&
> + echo "unexpected success"
> +# No bitmap output, since v2 does not support it
> +$QEMU_IMG measure -O qcow2 -o compat=0.10 -f qcow2 "$TEST_IMG" ||
> + echo "unexpected failure"
> +$QEMU_IMG measure --bitmaps -O qcow2 -o compat=0.10 -f qcow2 "$TEST_IMG" &&
> + echo "unexpected success"
> +
> +# Compute expected output: bitmap clusters + bitmap tables + bitmaps
> directory
> +echo
> +val2T=$((2*1024*1024*1024*1024))
> +cluster=$((64*1024))
> +b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster ))
> +b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster ))
> +echo expected bitmap $((b1clusters * cluster +
> + (b1clusters * 8 + cluster - 1) / cluster * cluster +
> + b2clusters * cluster +
> + (b2clusters * 8 + cluster - 1) / cluster * cluster +
> + cluster))
> +$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
> +$QEMU_IMG measure --bitmaps -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
> +
> +# Compute expected output: bitmap clusters + bitmap tables + bitmaps
> directory
> +echo
> +cluster=$((2*1024*1024))
> +b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster ))
> +b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster ))
> +echo expected bitmap $((b1clusters * cluster +
> + (b1clusters * 8 + cluster - 1) / cluster * cluster +
> + b2clusters * cluster +
> + (b2clusters * 8 + cluster - 1) / cluster * cluster +
> + cluster))
> +$QEMU_IMG measure --output=json -O qcow2 -o cluster_size=2M -f qcow2
> "$TEST_IMG"
> +$QEMU_IMG measure --output=json --bitmaps -O qcow2 -o cluster_size=2M \
> + -f qcow2 "$TEST_IMG"
> +
> # success, all done
> echo "*** done"
> rm -f $seq.full
> diff --git a/tests/qemu-iotests/190.out b/tests/qemu-iotests/190.out
> index d001942002db..5c35f9268068 100644
> --- a/tests/qemu-iotests/190.out
> +++ b/tests/qemu-iotests/190.out
> @@ -1,11 +1,44 @@
> QA output created by 190
> -== Huge file ==
> +== Huge file without bitmaps ==
>
> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2199023255552
> required size: 2199023255552
> fully allocated size: 2199023255552
> required size: 335806464
> fully allocated size: 2199359062016
> +bitmaps size: 0
> required size: 18874368
> fully allocated size: 2199042129920
> +bitmaps size: 0
> +
> +== Huge file with bitmaps ==
> +
> +qemu-img: --bitmaps is only supported with a filename.
> +required size: 2199023255552
> +fully allocated size: 2199023255552
> +qemu-img: no bitmaps measured, either source or destination format lacks
> bitmap support
> +required size: 7012352
> +fully allocated size: 17170432
> +qemu-img: no bitmaps measured, either source or destination format lacks
> bitmap support
> +required size: 335806464
> +fully allocated size: 2199359062016
> +qemu-img: no bitmaps measured, either source or destination format lacks
> bitmap support
> +
> +expected bitmap 537198592
> +required size: 335806464
> +fully allocated size: 2199359062016
> +bitmaps size: 537198592
> +required size: 873005056
> +fully allocated size: 2199896260608
> +
> +expected bitmap 545259520
> +{
> + "bitmaps": 545259520,
> + "required": 18874368,
> + "fully-allocated": 2199042129920
> +}
> +{
> + "required": 564133888,
> + "fully-allocated": 2199587389440
> +}
> *** done
> --
> 2.26.2
>
[PATCH v5 5/5] iotests: Add test 291 to for qemu-img bitmap coverage, Eric Blake, 2020/05/20
[PATCH v5 3/5] qemu-img: Factor out code for merging bitmaps, Eric Blake, 2020/05/20