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, ¶llels_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
