[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/6] qmp: add query-block-dirty-bitmap-ranges
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
[Qemu-devel] [PATCH 2/6] qmp: add query-block-dirty-bitmap-ranges |
Date: |
Sat, 30 Jan 2016 13:56:30 +0300 |
Add qmp command to query dirty bitmap contents. This is needed for
external backup.
Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
---
block/dirty-bitmap.c | 55 +++++++++++++++++++++++++++++++++++++++
blockdev.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
include/block/dirty-bitmap.h | 7 +++++
qapi/block-core.json | 54 ++++++++++++++++++++++++++++++++++++++
qmp-commands.hx | 33 +++++++++++++++++++++++
5 files changed, 211 insertions(+)
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 6da27d9..4c108e4 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -495,3 +495,58 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap
*bitmap, uint64_t start)
{
return hbitmap_next_zero(bitmap->bitmap, start);
}
+
+/* bdrv_query_dirty_bitmap_ranges
+ * start, count and resulting ranges are all in bytes
+ */
+BlockDirtyRangeList *bdrv_query_dirty_bitmap_ranges(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap, uint64_t start, uint64_t count,
+ uint32_t max_ranges)
+{
+ BlockDirtyRangeList *list = NULL, *last_entry = NULL;
+ BlockDirtyRangeList **plist = &list;
+ uint64_t begin, end;
+ uint64_t start_sector = start >> BDRV_SECTOR_BITS;
+ uint64_t last_sector = (start + count - 1) >> BDRV_SECTOR_BITS;
+ uint32_t nb_ranges = 0;
+
+ BdrvDirtyBitmapIter *it = bdrv_dirty_iter_new(bitmap, start_sector);
+
+ while ((begin = bdrv_dirty_iter_next(it)) != -1 && nb_ranges < max_ranges)
{
+ BlockDirtyRange *region;
+ if (begin > last_sector) {
+ break;
+ }
+
+ end = bdrv_dirty_bitmap_next_zero(bitmap, begin + 1);
+
+ region = g_new0(BlockDirtyRange, 1);
+ region->start = begin << BDRV_SECTOR_BITS;
+ region->count = (end - begin) << BDRV_SECTOR_BITS;
+
+ last_entry = g_new0(BlockDirtyRangeList, 1);
+ last_entry->value = region;
+
+ *plist = last_entry;
+ plist = &last_entry->next;
+ nb_ranges++;
+
+ bdrv_set_dirty_iter(it, end + 1);
+ }
+
+ bdrv_dirty_iter_free(it);
+
+ if (list != NULL) {
+ if (list->value->start < start) {
+ list->value->count -= start - list->value->start;
+ list->value->start = start;
+ }
+
+ if (last_entry->value->start +
+ last_entry->value->count > start + count) {
+ last_entry->value->count = start + count -
last_entry->value->start;
+ }
+ }
+
+ return list;
+}
diff --git a/blockdev.c b/blockdev.c
index 1392fff..fa34cf6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2733,6 +2733,68 @@ void qmp_block_dirty_bitmap_clear(const char *node,
const char *name,
aio_context_release(aio_context);
}
+BlockDirtyRangeList *qmp_query_block_dirty_bitmap_ranges(const char *node,
+ const char *name, bool has_start, uint64_t start, bool has_count,
+ uint64_t count, uint32_t max_ranges, bool has_block_io, bool block_io,
+ Error **errp)
+{
+ AioContext *aio_context;
+ BdrvDirtyBitmap *bitmap;
+ BlockDriverState *bs;
+ BlockDirtyRangeList *ret = NULL;
+ int64_t disk_size;
+
+ if (!has_block_io) {
+ block_io = true;
+ }
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs,
+ block_io ? &aio_context : NULL,
+ errp);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ if (!block_io && bdrv_dirty_bitmap_enabled(bitmap)) {
+ error_setg(errp, "The bitmap is enabled, block-io must be on");
+ return NULL;
+ }
+
+ disk_size = bdrv_getlength(bs);
+ if (disk_size < 0) {
+ error_setg_errno(errp, -disk_size, "bdrv_getlength failed");
+ goto out;
+ }
+
+ if (has_start) {
+ if (start >= disk_size) {
+ error_setg(errp, "Start must be less than disk size");
+ goto out;
+ }
+ } else {
+ start = 0;
+ }
+
+ if (has_count) {
+ if (start + count > disk_size) {
+ error_setg(errp,
+ "(start + count) must not be greater than disk size");
+ goto out;
+ }
+ } else {
+ count = disk_size - start;
+ }
+
+ ret = bdrv_query_dirty_bitmap_ranges(bs, bitmap, start, count, max_ranges);
+
+out:
+ if (block_io) {
+ 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/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 0033942..7918310 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -70,4 +70,11 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap
*bitmap);
int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t start);
+/* bdrv_query_dirty_bitmap_ranges
+ * start, count and resulting ranges are all in bytes
+ */
+BlockDirtyRangeList *bdrv_query_dirty_bitmap_ranges(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap, uint64_t start, uint64_t count,
+ uint32_t max_ranges);
+
#endif
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0a915ed..89bdeaf 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -414,6 +414,60 @@
##
{ 'command': 'query-block', 'returns': ['BlockInfo'] }
+##
+# @BlockDirtyRegion:
+#
+# Region in bytes.
+#
+# @start: first byte
+#
+# @count: number of bytes in the region
+#
+# Since: 2.6
+##
+{ 'struct': 'BlockDirtyRange',
+ 'data': { 'start': 'uint64', 'count': 'uint64' } }
+
+##
+# @BlockDirtyBitmapQueryRanges
+#
+# @node: name of device/node which the bitmap is tracking
+#
+# @name: name of the dirty bitmap
+#
+# @start: #optional start of quered range, default is zero for
+# query-block-dirty-bitmap-ranges
+#
+# @count: #optional lenght of quered range, default is (disk-size - @start)
+# for query-block-dirty-bitmap-ranges
+#
+# @max-ranges: max dirty ranges to be returned. If there are more than
+# @max-ranges dirty ranges within quered range, then first
+# @max-ranges dirty ranges from quered range will be returned.
+#
+# @block-io: #optional wheter aio-context should be acquired while oparating.
+# False value is allowed only for frozen or disabled bitmaps.
+# Default is true for query-block-dirty-bitmap-ranges.
+#
+# Since 2.6
+##
+{ 'struct': 'BlockDirtyBitmapQueryRanges',
+ 'data': { 'node': 'str', 'name': 'str', '*start': 'uint64',
+ '*count': 'uint64', 'max-ranges': 'uint32', '*block-io': 'bool'} }
+
+##
+# @query-block-dirty-bitmap-ranges
+#
+# Get a description for specified dirty bitmap including it's dirty regions.
+# This command is in general for testing purposes.
+#
+# Returns: @BlockDirtyBitmapInfo
+#
+# Since: 2.6
+##
+{ 'command': 'query-block-dirty-bitmap-ranges',
+ 'data': 'BlockDirtyBitmapQueryRanges',
+ 'returns': ['BlockDirtyRange'] }
##
# @BlockDeviceTimedStats:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index db072a6..02de44c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1457,6 +1457,39 @@ Example:
EQMP
{
+ .name = "query-block-dirty-bitmap-ranges",
+ .args_type = "node:B,name:s,start:i?,count:i?,max-ranges:i,"
+ "block-io:b?",
+ .mhandler.cmd_new = qmp_marshal_query_block_dirty_bitmap_ranges,
+ },
+
+SQMP
+
+query-block-dirty-bitmap-ranges
+------------------------
+Since 2.6
+
+Get contens of specified dirty bitmap. Bitmap data is returned as array of
+dirty ranges.
+
+Arguments:
+
+- "node": device/node on which to remove dirty bitmap (json-string)
+- "name": name of the dirty bitmap (json-string)
+- "start": start of quered range in bytes (json-int, optional, default 0)
+- "count": lenght of quered range in bytes
+ (json-int, optional, default (disk-size - @start))
+- "max-ranges": max dirty ranges to be returned. If there are more than
+ @max-ranges dirty ranges within quered range, then first
+ @max-ranges dirty ranges from quered range will be returned.
+ (json-int)
+- "block-io": wheter aio-context should be acquired while oparating. False
+ value is allowed only for frozen or disabled bitmaps.
+ (json-bool, optional, default true)
+
+EQMP
+
+ {
.name = "blockdev-snapshot-sync",
.args_type =
"device:s?,node-name:s?,snapshot-file:s,snapshot-node-name:s?,format:s?,mode:s?",
.mhandler.cmd_new = qmp_marshal_blockdev_snapshot_sync,
--
1.8.3.1
- [Qemu-devel] [PATCH v2 0/6] external backup api, Vladimir Sementsov-Ogievskiy, 2016/01/30
- [Qemu-devel] [PATCH 1/6] block dirty bitmap: add next_zero function, Vladimir Sementsov-Ogievskiy, 2016/01/30
- [Qemu-devel] [PATCH 3/6] iotests: test query-block-dirty-bitmap-ranges, Vladimir Sementsov-Ogievskiy, 2016/01/30
- [Qemu-devel] [PATCH 2/6] qmp: add query-block-dirty-bitmap-ranges,
Vladimir Sementsov-Ogievskiy <=
- [Qemu-devel] [PATCH 4/6] qapi: add qmp commands for some dirty bitmap functions, Vladimir Sementsov-Ogievskiy, 2016/01/30
- [Qemu-devel] [PATCH 5/6] qapi: make block-dirty-bitmap-create-successor transaction-able, Vladimir Sementsov-Ogievskiy, 2016/01/30
- [Qemu-devel] [PATCH 6/6] iotests: test external backup api, Vladimir Sementsov-Ogievskiy, 2016/01/30