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 ==
--
2.53.0