[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] qapi: implementation of the block-dirty-bitmap-dump command
From: |
Patrik Janoušek |
Subject: |
[PATCH 2/2] qapi: implementation of the block-dirty-bitmap-dump command |
Date: |
Sat, 20 Mar 2021 10:32:35 +0100 |
Currently, dirty bitmaps are for internal use only and there is
no support for accessing their content from third party-apps.
This patch implements new command block-dirty-bitmap-dump, which
returns content of the dirty bitmap encoded in base64. This is
very useful especially in combination with a drive that uses raw
format because third-party apps can easily use it to create
incremental or differential backup.
Signed-off-by: Patrik Janoušek <pj@patrikjanousek.cz>
---
block/monitor/bitmap-qmp-cmds.c | 61 +++++++++++++++++++++++++++++++
qapi/block-core.json | 64 ++++++++++++++++++++++++++++++++-
2 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
index 9f11deec64..7f296e9ba7 100644
--- a/block/monitor/bitmap-qmp-cmds.c
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -146,6 +146,67 @@ out:
aio_context_release(aio_context);
}
+BlockDirtyBitmapContent *qmp_block_dirty_bitmap_dump(const char *node,
+ const char *name,
+ bool has_clear, bool
clear,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+ BlockDirtyBitmapContent *bdbc;
+ HBitmap *hb;
+ AioContext *aio_context;
+
+ if (!name || name[0] == '\0') {
+ error_setg(errp, "Bitmap name cannot be empty");
+ return NULL;
+ }
+
+ bs = bdrv_lookup_bs(node, node, errp);
+ if (!bs) {
+ return NULL;
+ }
+
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap || !bs) {
+ return NULL;
+ }
+
+ if (has_clear && clear) {
+ /**
+ * Transactions cannot return value, so "clear" functionality must be
+ * implemented here while holding AiO context
+ */
+
+ bdrv_clear_dirty_bitmap(bitmap, &hb);
+
+ uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
+ uint64_t tb_size = hbitmap_serialization_size(hb, 0, bm_size);
+ uint8_t *buf = g_malloc(tb_size);
+
+ hbitmap_serialize_part(hb, buf, 0, bm_size);
+
+ bdbc = g_new0(BlockDirtyBitmapContent, 1);
+ bdbc->content = g_base64_encode((guchar *) buf, tb_size);
+ } else {
+ uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
+ uint64_t tb_size = bdrv_dirty_bitmap_serialization_size(bitmap, 0,
bm_size);
+ uint8_t *buf = g_malloc(tb_size);
+
+ bdrv_dirty_bitmap_serialize_part(bitmap, buf, 0, bm_size);
+
+ bdbc = g_new0(BlockDirtyBitmapContent, 1);
+ bdbc->content = g_base64_encode((guchar *) buf, tb_size);
+ }
+
+ aio_context_release(aio_context);
+
+ return bdbc;
+}
+
BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
bool release,
BlockDriverState **bitmap_bs,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 04ad80bc1e..cbe3dac384 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2031,6 +2031,14 @@
{ 'struct': 'BlockDirtyBitmap',
'data': { 'node': 'str', 'name': 'str' } }
+##
+# @BlockDirtyBitmapContent:
+#
+# @content: content of dirty bitmap (encoded in base64)
+##
+{ 'struct': 'BlockDirtyBitmapContent',
+ 'data': { 'content': 'str' } }
+
##
# @BlockDirtyBitmapAdd:
#
@@ -2056,6 +2064,18 @@
'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
'*persistent': 'bool', '*disabled': 'bool' } }
+##
+# @BlockDirtyBitmapDump:
+#
+# @node: name of device/node which the bitmap is tracking
+#
+# @name: name of the dirty bitmap (must be less than 1024 bytes)
+#
+# @clear: true if bitmap should be cleared after dump
+##
+{ 'struct': 'BlockDirtyBitmapDump',
+ 'data': { 'node': 'str', 'name': 'str', '*clear': 'bool' } }
+
##
# @BlockDirtyBitmapMergeSource:
#
@@ -2086,6 +2106,26 @@
'data': { 'node': 'str', 'target': 'str',
'bitmaps': ['BlockDirtyBitmapMergeSource'] } }
+##
+# @block-dirty-bitmap-dump:
+#
+# Dump a dirty bitmap with a name on the node.
+#
+# Returns: - nothing on success
+# - If @node is not a valid block device or node, DeviceNotFound
+# - If @name is already taken, GenericError with an explanation
+#
+# Example:
+#
+# -> { "execute": "block-dirty-bitmap-dump",
+# "arguments": { "node": "drive0", "name": "bitmap0" } }
+# <- { "return": { "content": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFt... (trunc)" } }
+#
+##
+{ 'command': 'block-dirty-bitmap-dump',
+ 'data': 'BlockDirtyBitmapDump',
+ 'returns': 'BlockDirtyBitmapContent' }
+
##
# @block-dirty-bitmap-add:
#
@@ -3908,6 +3948,26 @@
'*x-dirty-bitmap': 'str',
'*reconnect-delay': 'uint32' } }
+##
+# @BlockdevOptionsRawDirtyBitmap:
+#
+# Dirty bitmap options for the raw driver.
+#
+# @name: the name of the dirty bitmap (Since 2.4)
+#
+# @filename: the filename of the dirty bitmap
+#
+# @granularity: granularity of the dirty bitmap in bytes (since 1.4)
+#
+# @persistent: true if the bitmap was stored on disk, is scheduled to be stored
+# on disk, or both. (since 4.0)
+#
+# @disabled: true if the bitmap should not be loaded (and saved) automatically
+##
+{ 'struct': 'BlockdevOptionsRawDirtyBitmap',
+ 'data': {'*name': 'str', 'filename': 'str', 'granularity': 'uint32',
+ 'persistent': 'bool', '*disabled': 'bool' } }
+
##
# @BlockdevOptionsRaw:
#
@@ -3915,12 +3975,14 @@
#
# @offset: position where the block device starts
# @size: the assumed size of the device
+# @dirty-bitmaps: dirty bitmaps of the raw block device
#
# Since: 2.9
##
{ 'struct': 'BlockdevOptionsRaw',
'base': 'BlockdevOptionsGenericFormat',
- 'data': { '*offset': 'int', '*size': 'int' } }
+ 'data': { '*offset': 'int', '*size': 'int' ,
+ '*dirty-bitmaps': ['BlockdevOptionsRawDirtyBitmap'] } }
##
# @BlockdevOptionsThrottle:
--
2.31.0
Re: [PATCH 1/2] block/raw: added support of persistent dirty bitmaps, Kevin Wolf, 2021/03/22
[PATCH 2/2] qapi: implementation of the block-dirty-bitmap-dump command,
Patrik Janoušek <=
Re: [PATCH 0/2] block/raw: implemented persistent dirty bitmap and ability to dump bitmap content via qapi, Vladimir Sementsov-Ogievskiy, 2021/03/22
Message not available