On 8/17/26 20:59, Denis V. Lunev wrote:
> This email originated from an IP that might not be authorized by the domain 
> it was sent from.
> Do not click links or open attachments unless it is an email you expected to 
> receive.
> From: Denis V. Lunev <[email protected]>
>
> Nothing tells which persistent bitmaps an image carries. qemu-img info
> says nothing about them, and the only other way to see one is to export
> the image over NBD and ask for a bitmap by name, which needs the name
> beforehand.
>
> Add ImageInfoSpecificParallels with the bitmaps and their granularity,
> as qcow2 reports the contents of its bitmap directory:
>
>     Format specific information:
>         bitmaps:
>             [0]:
>                 name: b2c9e1a4-5d3f-4e8b-9a7c-6f0d1e2b3a45
>                 granularity: 65536
>
> The list is built from the bitmaps loaded at open time rather than from
> a second pass over the Format Extension, as every bitmap the extension
> carries is loaded and marked persistent there. On a node which is open
> that also covers a bitmap which was created but not stored yet, which is
> what the field says: qemu-img info opens the image on its own, so there
> the two are the same thing.
>
> An image with no bitmaps leaves the structure empty, and
> bdrv_image_info_specific_dump() prints nothing for an empty one, so the
> output for such an image does not change.
>
> Cc: Stefan Hajnoczi <[email protected]>
> Cc: Eric Blake <[email protected]>
> Cc: Markus Armbruster <[email protected]>
> Signed-off-by: Denis V. Lunev <[email protected]>
> ---
>  block/parallels-ext.c                         | 22 ++++++++++
>  block/parallels.c                             | 20 ++++++++++
>  block/parallels.h                             |  3 ++
>  qapi/block-core.json                          | 40 ++++++++++++++++++-
>  tests/qemu-iotests/tests/parallels-checks     |  3 ++
>  tests/qemu-iotests/tests/parallels-checks.out |  9 +++++
>  6 files changed, 95 insertions(+), 2 deletions(-)
>
> diff --git a/block/parallels-ext.c b/block/parallels-ext.c
> index f687f2da7c..ad87ecfbc1 100644
> --- a/block/parallels-ext.c
> +++ b/block/parallels-ext.c
> @@ -736,3 +736,25 @@ 
> parallels_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
>  
>      return ret;
>  }
> +
> +void parallels_get_bitmap_info_list(BlockDriverState *bs,
> +                                    ParallelsBitmapInfoList **info_list)
> +{
> +    BdrvDirtyBitmap *bitmap;
> +    ParallelsBitmapInfoList **tail = info_list;
> +
> +    *info_list = NULL;
> +
> +    FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
> +        ParallelsBitmapInfo *info;
> +
> +        if (!bdrv_dirty_bitmap_get_persistence(bitmap)) {
> +            continue;
> +        }
> +
> +        info = g_new0(ParallelsBitmapInfo, 1);
> +        info->name = g_strdup(bdrv_dirty_bitmap_name(bitmap));
> +        info->granularity = bdrv_dirty_bitmap_granularity(bitmap);
> +        QAPI_LIST_APPEND(tail, info);
> +    }
> +}
> diff --git a/block/parallels.c b/block/parallels.c
> index 2a5ceb8978..e7d65d0458 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -1624,6 +1624,25 @@ static bool 
> parallels_is_support_dirty_bitmaps(BlockDriverState *bs)
>      return 1;
>  }
>  
> +static ImageInfoSpecific * GRAPH_RDLOCK
> +parallels_get_specific_info(BlockDriverState *bs, Error **errp)
> +{
> +    ImageInfoSpecificParallels *parallels_info;
> +    ImageInfoSpecific *spec_info;
> +
> +    parallels_info = g_new0(ImageInfoSpecificParallels, 1);
> +    parallels_get_bitmap_info_list(bs, &parallels_info->bitmaps);
> +    parallels_info->has_bitmaps = !!parallels_info->bitmaps;
> +
> +    spec_info = g_new(ImageInfoSpecific, 1);
> +    *spec_info = (ImageInfoSpecific){
> +        .type = IMAGE_INFO_SPECIFIC_KIND_PARALLELS,
> +        .u.parallels.data = parallels_info,
> +    };
> +
> +    return spec_info;
> +}
> +
>  static BlockDriver bdrv_parallels = {
>      .format_name                = "parallels",
>      .instance_size              = sizeof(BDRVParallelsState),
> @@ -1653,6 +1672,7 @@ static BlockDriver bdrv_parallels = {
>                                    parallels_co_can_store_new_dirty_bitmap,
>      .bdrv_co_remove_persistent_dirty_bitmap =
>                                    
> parallels_co_remove_persistent_dirty_bitmap,
> +    .bdrv_get_specific_info     = parallels_get_specific_info,
>  };
>  
>  static void bdrv_parallels_init(void)
> diff --git a/block/parallels.h b/block/parallels.h
> index 27d8c3ac83..012f47320b 100644
> --- a/block/parallels.h
> +++ b/block/parallels.h
> @@ -32,6 +32,7 @@
>  #ifndef BLOCK_PARALLELS_H
>  #define BLOCK_PARALLELS_H
>  #include "qemu/coroutine.h"
> +#include "qapi/qapi-types-block-core.h"
>  
>  #define HEADS_NUMBER 16
>  #define SEC_IN_CYL 32
> @@ -111,5 +112,7 @@ parallels_co_can_store_new_dirty_bitmap(BlockDriverState 
> *bs, const char *name,
>  int coroutine_fn GRAPH_RDLOCK
>  parallels_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
>                                              const char *name, Error **errp);
> +void parallels_get_bitmap_info_list(BlockDriverState *bs,
> +                                    ParallelsBitmapInfoList **info_list);
>  
>  #endif
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 1f87b07850..4bc8b45efe 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -200,7 +200,7 @@
>  # Since: 1.7
>  ##
>  { 'enum': 'ImageInfoSpecificKind',
> -  'data': [ 'qcow2', 'vmdk', 'luks', 'rbd', 'file' ] }
> +  'data': [ 'qcow2', 'vmdk', 'luks', 'rbd', 'file', 'parallels' ] }
>  
>  ##
>  # @ImageInfoSpecificQCow2Wrapper:
> @@ -255,6 +255,41 @@
>  { 'struct': 'ImageInfoSpecificFileWrapper',
>    'data': { 'data': 'ImageInfoSpecificFile' } }
>  
> +##
> +# @ParallelsBitmapInfo:
> +#
> +# Parallels dirty bitmap information.
> +#
> +# @name: the name of the bitmap
> +#
> +# @granularity: granularity of the bitmap in bytes
> +#
> +# Since: 11.2
> +##
> +{ 'struct': 'ParallelsBitmapInfo',
> +  'data': { 'name': 'str', 'granularity': 'uint32' } }
> +
> +##
> +# @ImageInfoSpecificParallels:
> +#
> +# @bitmaps: A list of the persistent dirty bitmaps of the image,
> +#     including the ones which are not written out yet
> +#
> +# Since: 11.2
> +##
> +{ 'struct': 'ImageInfoSpecificParallels',
> +  'data': { '*bitmaps': ['ParallelsBitmapInfo'] } }
> +
> +##
> +# @ImageInfoSpecificParallelsWrapper:
> +#
> +# @data: image information specific to Parallels
> +#
> +# Since: 11.2
> +##
> +{ 'struct': 'ImageInfoSpecificParallelsWrapper',
> +  'data': { 'data': 'ImageInfoSpecificParallels' } }
> +
>  ##
>  # @ImageInfoSpecific:
>  #
> @@ -273,7 +308,8 @@
>        'vmdk': 'ImageInfoSpecificVmdkWrapper',
>        'luks': 'ImageInfoSpecificLUKSWrapper',
>        'rbd': 'ImageInfoSpecificRbdWrapper',
> -      'file': 'ImageInfoSpecificFileWrapper'
> +      'file': 'ImageInfoSpecificFileWrapper',
> +      'parallels': 'ImageInfoSpecificParallelsWrapper'
>    } }
>  
>  ##
> diff --git a/tests/qemu-iotests/tests/parallels-checks 
> b/tests/qemu-iotests/tests/parallels-checks
> index 916d423a64..4c8fc17fa9 100755
> --- a/tests/qemu-iotests/tests/parallels-checks
> +++ b/tests/qemu-iotests/tests/parallels-checks
> @@ -382,6 +382,9 @@ echo "== dirty a single granule of the bitmap =="
>  file_size=`stat --printf="%s" "$TEST_IMG"`
>  echo "file size: $file_size"
>  
> +echo "== the bitmap is reported by qemu-img info =="
> +_img_info --format-specific
> +
>  echo "== the extension and its bitmap data are not a leak =="
>  _check_test_img
>  
> diff --git a/tests/qemu-iotests/tests/parallels-checks.out 
> b/tests/qemu-iotests/tests/parallels-checks.out
> index 4dfadd68d6..7aaa4636d7 100644
> --- a/tests/qemu-iotests/tests/parallels-checks.out
> +++ b/tests/qemu-iotests/tests/parallels-checks.out
> @@ -241,6 +241,15 @@ qemu-img: Operation add on bitmap bitmap0 failed: Bitmap 
> name must be a UUID to
>  wrote 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  file size: 4194304
> +== the bitmap is reported by qemu-img info ==
> +image: TEST_DIR/t.IMGFMT
> +file format: IMGFMT
> +virtual size: 4 MiB (4194304 bytes)
> +Format specific information:
> +    bitmaps:
> +        [0]:
> +            name: b2c9e1a4-5d3f-4e8b-9a7c-6f0d1e2b3a45
> +            granularity: 65536
>  == the extension and its bitmap data are not a leak ==
>  No errors were found on the image.
>  == extend image by 1 cluster ==
Eric, Marcus,

Can you pls take a look to QAPI changes? They are
pure technical to me.

Thank you in advance,
    Den

Reply via email to