+
+ region = g_new0(BlockDirtyRegion, 1);
+ entry = g_new0(BlockDirtyRegionList, 1);
+ region->start = begin;
+ region->count = end - begin;
+ entry->value = region;
+ *plist = entry;
+ plist = &entry->next;
+
+ begin = end;
+ }
+
+ return info;
+}
+
/**
* Advance an HBitmapIter to an arbitrary offset.
*/
diff --git a/blockdev.c b/blockdev.c
index 07cfe25..d2bc453 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2734,6 +2734,27 @@ void qmp_block_dirty_bitmap_clear(const char
*node, const char *name,
aio_context_release(aio_context);
}
+BlockDirtyBitmapInfo *qmp_query_block_dirty_bitmap(const char *node,
+ const char *name,
+ Error **errp)
+{
+ AioContext *aio_context;
+ BdrvDirtyBitmap *bitmap;
+ BlockDriverState *bs;
+ BlockDirtyBitmapInfo *ret = NULL;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs,
&aio_context, errp);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ ret = bdrv_query_dirty_bitmap(bs, bitmap);
+
+ aio_context_release(aio_context);
+
+ return ret;
+}
+
void hmp_drive_del(Monitor *mon, const QDict *qdict)
{
const char *id = qdict_get_str(qdict, "id");
diff --git a/include/block/block.h b/include/block/block.h
index 25f36dc..9d6bd33 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -505,6 +505,8 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
int64_t cur_sector, int nr_sectors);
void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
int64_t cur_sector, int nr_sectors);
+BlockDirtyBitmapInfo *bdrv_query_dirty_bitmap(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap);
void bdrv_dirty_iter_init(BdrvDirtyBitmap *bitmap, struct
HBitmapIter *hbi);
void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0a915ed..12ed759 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -414,6 +414,58 @@
##
{ 'command': 'query-block', 'returns': ['BlockInfo'] }
+##
+# @BlockDirtyRegion:
+#
+# Region in bytes.
+#
+# @start: first byte
+#
+# @count: number of bytes in the region
+#
+# Since: 2.3
+##
+{ 'struct': 'BlockDirtyRegion',
+ 'data': { 'start': 'int', 'count': 'int' } }
+
+##
+# @BlockDirtyBitmapInfo
+#
+# @name: the name of the dirty bitmap
+#
+# @size: size of the dirty bitmap in sectors
+#
+# @granularity: granularity of the dirty bitmap in bytes
+#
+# @disabled: whether the dirty bitmap is disabled
+#
+# @dirty-count: number of dirty bytes according to the dirty bitmap
+#
+# @dirty-regions: dirty regions of the bitmap
+#
+# Since 2.3
+##
+{ 'struct': 'BlockDirtyBitmapInfo',
+ 'data': { 'name': 'str',
+ 'size': 'int',
+ 'granularity': 'int',
+ 'disabled': 'bool',
+ 'dirty-count': 'int',
+ 'dirty-regions': ['BlockDirtyRegion'] } }
+
+##
+# @query-block-dirty-bitmap
+#
+# Get a description for specified dirty bitmap including it's dirty
regions.
+# This command is in general for testing purposes.
+#
+# Returns: @BlockDirtyBitmapInfo
+#
+# Since: 2.3
+##
+{ 'command': 'query-block-dirty-bitmap',
+ 'data': 'BlockDirtyBitmap',
+ 'returns': 'BlockDirtyBitmapInfo' }