From ab41fc4853cc0cf01ed4903ffe7c36e3768b538f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 11 Jun 2018 14:53:31 -0400 Subject: [PATCH 1/7] block: remove bdrv_dirty_bitmap_make_anon All this function is doing will be repeated by bdrv_do_release_matching_dirty_bitmap_locked, except resetting bm->persistent. But even that does not matter because the bitmap will be freed. Signed-off-by: Paolo Bonzini Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Message-id: 20180323164254.26487-1-pbonzini@redhat.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 9 --------- blockdev.c | 1 - include/block/dirty-bitmap.h | 1 - 3 files changed, 11 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 967159479d..ea82c06f07 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -97,15 +97,6 @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name) return NULL; } -/* Called with BQL taken. */ -void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) -{ - assert(!bdrv_dirty_bitmap_frozen(bitmap)); - g_free(bitmap->name); - bitmap->name = NULL; - bitmap->persistent = false; -} - /* Called with BQL taken. */ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, uint32_t granularity, diff --git a/blockdev.c b/blockdev.c index 8de95be8f4..266ecc06cc 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2881,7 +2881,6 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name, } } - bdrv_dirty_bitmap_make_anon(bitmap); bdrv_release_dirty_bitmap(bs, bitmap); } diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 1ff8949b1b..5a51a78b63 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -24,7 +24,6 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap); BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name); -void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs); void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs); From b133c27f5dc59969574b0715e5837d32c99caa86 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 11 Jun 2018 14:53:31 -0400 Subject: [PATCH 2/7] block: simplify code around releasing bitmaps QLIST_REMOVE does not require walking the list, and once the "bitmap" argument is removed from bdrv_do_release_matching_dirty_bitmap_locked the code simplifies a lot and it is worth inlining everything in the callers of bdrv_do_release_matching_dirty_bitmap. Signed-off-by: Paolo Bonzini Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Message-id: 20180326104037.6894-1-pbonzini@redhat.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 84 +++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 52 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index ea82c06f07..a7eaa1051d 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -249,49 +249,16 @@ void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) qemu_mutex_unlock(bitmap->mutex); } -/* Called within bdrv_dirty_bitmap_lock..unlock */ -static void bdrv_do_release_matching_dirty_bitmap_locked( - BlockDriverState *bs, BdrvDirtyBitmap *bitmap, - bool (*cond)(BdrvDirtyBitmap *bitmap)) +/* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. */ +static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) { - BdrvDirtyBitmap *bm, *next; - - QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { - if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { - assert(!bm->active_iterators); - assert(!bdrv_dirty_bitmap_frozen(bm)); - assert(!bm->meta); - QLIST_REMOVE(bm, list); - hbitmap_free(bm->bitmap); - g_free(bm->name); - g_free(bm); - - if (bitmap) { - return; - } - } - } - - if (bitmap) { - abort(); - } -} - -/* Called with BQL taken. */ -static void bdrv_do_release_matching_dirty_bitmap( - BlockDriverState *bs, BdrvDirtyBitmap *bitmap, - bool (*cond)(BdrvDirtyBitmap *bitmap)) -{ - bdrv_dirty_bitmaps_lock(bs); - bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, cond); - bdrv_dirty_bitmaps_unlock(bs); -} - -/* Called within bdrv_dirty_bitmap_lock..unlock */ -static void bdrv_release_dirty_bitmap_locked(BlockDriverState *bs, - BdrvDirtyBitmap *bitmap) -{ - bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, NULL); + assert(!bitmap->active_iterators); + assert(!bdrv_dirty_bitmap_frozen(bitmap)); + assert(!bitmap->meta); + QLIST_REMOVE(bitmap, list); + hbitmap_free(bitmap->bitmap); + g_free(bitmap->name); + g_free(bitmap); } /** @@ -344,7 +311,7 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs, error_setg(errp, "Merging of parent and successor bitmap failed"); return NULL; } - bdrv_release_dirty_bitmap_locked(bs, successor); + bdrv_release_dirty_bitmap_locked(successor); parent->successor = NULL; return parent; @@ -382,15 +349,12 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes) bdrv_dirty_bitmaps_unlock(bs); } -static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap) -{ - return !!bdrv_dirty_bitmap_name(bitmap); -} - /* Called with BQL taken. */ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) { - bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL); + bdrv_dirty_bitmaps_lock(bs); + bdrv_release_dirty_bitmap_locked(bitmap); + bdrv_dirty_bitmaps_unlock(bs); } /** @@ -401,7 +365,15 @@ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) */ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) { - bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name); + BdrvDirtyBitmap *bm, *next; + + bdrv_dirty_bitmaps_lock(bs); + QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { + if (bdrv_dirty_bitmap_name(bm)) { + bdrv_release_dirty_bitmap_locked(bm); + } + } + bdrv_dirty_bitmaps_unlock(bs); } /** @@ -409,11 +381,19 @@ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) * bdrv_inactivate_recurse()). * There must not be any frozen bitmaps attached. * This function does not remove persistent bitmaps from the storage. + * Called with BQL taken. */ void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) { - bdrv_do_release_matching_dirty_bitmap(bs, NULL, - bdrv_dirty_bitmap_get_persistance); + BdrvDirtyBitmap *bm, *next; + + bdrv_dirty_bitmaps_lock(bs); + QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { + if (bdrv_dirty_bitmap_get_persistance(bm)) { + bdrv_release_dirty_bitmap_locked(bm); + } + } + bdrv_dirty_bitmaps_unlock(bs); } /** From 8b1402ce80d74dc02802f101a0f6c340462380d1 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 11 Jun 2018 14:53:31 -0400 Subject: [PATCH 3/7] block/dirty-bitmap: add lock to bdrv_enable/disable_dirty_bitmap Add locks and remove comments about BQL accordingly to dirty_bitmap_mutex definition in block_int.h. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Jeff Cody Message-id: 20180606182449.1607-2-jsnow@redhat.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index a7eaa1051d..59b38b2671 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -413,18 +413,20 @@ void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, } } -/* Called with BQL taken. */ void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) { + bdrv_dirty_bitmap_lock(bitmap); assert(!bdrv_dirty_bitmap_frozen(bitmap)); bitmap->disabled = true; + bdrv_dirty_bitmap_unlock(bitmap); } -/* Called with BQL taken. */ void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) { + bdrv_dirty_bitmap_lock(bitmap); assert(!bdrv_dirty_bitmap_frozen(bitmap)); bitmap->disabled = false; + bdrv_dirty_bitmap_unlock(bitmap); } BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) From 5c5d2e50e5ac85234d793f0127a20ea3424a1229 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 11 Jun 2018 14:53:32 -0400 Subject: [PATCH 4/7] qapi: add x-block-dirty-bitmap-enable/disable Expose the ability to turn bitmaps "on" or "off". This is experimental and principally for the sake of the Libvirt Checkpoints API, and it may or may not be committed for 3.0. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Jeff Cody Message-id: 20180606182449.1607-3-jsnow@redhat.com Signed-off-by: John Snow --- blockdev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ qapi/block-core.json | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/blockdev.c b/blockdev.c index 266ecc06cc..4a353c934a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2922,6 +2922,48 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name, bdrv_clear_dirty_bitmap(bitmap, NULL); } +void qmp_x_block_dirty_bitmap_enable(const char *node, const char *name, + Error **errp) +{ + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; + + bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); + if (!bitmap) { + return; + } + + if (bdrv_dirty_bitmap_frozen(bitmap)) { + error_setg(errp, + "Bitmap '%s' is currently frozen and cannot be enabled", + name); + return; + } + + bdrv_enable_dirty_bitmap(bitmap); +} + +void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name, + Error **errp) +{ + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; + + bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); + if (!bitmap) { + return; + } + + if (bdrv_dirty_bitmap_frozen(bitmap)) { + error_setg(errp, + "Bitmap '%s' is currently frozen and cannot be disabled", + name); + return; + } + + bdrv_disable_dirty_bitmap(bitmap); +} + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, const char *name, Error **errp) diff --git a/qapi/block-core.json b/qapi/block-core.json index 4b1de474a9..02de674f5f 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1808,6 +1808,48 @@ { 'command': 'block-dirty-bitmap-clear', 'data': 'BlockDirtyBitmap' } +## +# @x-block-dirty-bitmap-enable: +# +# Enables a dirty bitmap so that it will begin tracking disk changes. +# +# Returns: nothing on success +# If @node is not a valid block device, DeviceNotFound +# If @name is not found, GenericError with an explanation +# +# Since: 3.0 +# +# Example: +# +# -> { "execute": "x-block-dirty-bitmap-enable", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## + { 'command': 'x-block-dirty-bitmap-enable', + 'data': 'BlockDirtyBitmap' } + +## +# @x-block-dirty-bitmap-disable: +# +# Disables a dirty bitmap so that it will stop tracking disk changes. +# +# Returns: nothing on success +# If @node is not a valid block device, DeviceNotFound +# If @name is not found, GenericError with an explanation +# +# Since: 3.0 +# +# Example: +# +# -> { "execute": "x-block-dirty-bitmap-disable", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## + { 'command': 'x-block-dirty-bitmap-disable', + 'data': 'BlockDirtyBitmap' } + ## # @BlockDirtyBitmapSha256: # From c6490447402f574bbe45f45c318e0bdd19121baf Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 11 Jun 2018 14:53:32 -0400 Subject: [PATCH 5/7] qmp: transaction support for x-block-dirty-bitmap-enable/disable Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Jeff Cody Message-id: 20180606182449.1607-4-jsnow@redhat.com [Added x- prefix. --js] Signed-off-by: John Snow --- blockdev.c | 81 ++++++++++++++++++++++++++++++++++++++++++- qapi/transaction.json | 4 +++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index 4a353c934a..2ac15601d9 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2052,6 +2052,7 @@ typedef struct BlockDirtyBitmapState { BlockDriverState *bs; HBitmap *backup; bool prepared; + bool was_enabled; } BlockDirtyBitmapState; static void block_dirty_bitmap_add_prepare(BlkActionState *common, @@ -2151,6 +2152,74 @@ static void block_dirty_bitmap_clear_commit(BlkActionState *common) hbitmap_free(state->backup); } +static void block_dirty_bitmap_enable_prepare(BlkActionState *common, + Error **errp) +{ + BlockDirtyBitmap *action; + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (action_check_completion_mode(common, errp) < 0) { + return; + } + + action = common->action->u.x_block_dirty_bitmap_enable.data; + state->bitmap = block_dirty_bitmap_lookup(action->node, + action->name, + NULL, + errp); + if (!state->bitmap) { + return; + } + + state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap); + bdrv_enable_dirty_bitmap(state->bitmap); +} + +static void block_dirty_bitmap_enable_abort(BlkActionState *common) +{ + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (!state->was_enabled) { + bdrv_disable_dirty_bitmap(state->bitmap); + } +} + +static void block_dirty_bitmap_disable_prepare(BlkActionState *common, + Error **errp) +{ + BlockDirtyBitmap *action; + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (action_check_completion_mode(common, errp) < 0) { + return; + } + + action = common->action->u.x_block_dirty_bitmap_disable.data; + state->bitmap = block_dirty_bitmap_lookup(action->node, + action->name, + NULL, + errp); + if (!state->bitmap) { + return; + } + + state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap); + bdrv_disable_dirty_bitmap(state->bitmap); +} + +static void block_dirty_bitmap_disable_abort(BlkActionState *common) +{ + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (state->was_enabled) { + bdrv_enable_dirty_bitmap(state->bitmap); + } +} + static void abort_prepare(BlkActionState *common, Error **errp) { error_setg(errp, "Transaction aborted using Abort action"); @@ -2211,7 +2280,17 @@ static const BlkActionOps actions[] = { .prepare = block_dirty_bitmap_clear_prepare, .commit = block_dirty_bitmap_clear_commit, .abort = block_dirty_bitmap_clear_abort, - } + }, + [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_ENABLE] = { + .instance_size = sizeof(BlockDirtyBitmapState), + .prepare = block_dirty_bitmap_enable_prepare, + .abort = block_dirty_bitmap_enable_abort, + }, + [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_DISABLE] = { + .instance_size = sizeof(BlockDirtyBitmapState), + .prepare = block_dirty_bitmap_disable_prepare, + .abort = block_dirty_bitmap_disable_abort, + } }; /** diff --git a/qapi/transaction.json b/qapi/transaction.json index bd312792da..d7e4274550 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -46,6 +46,8 @@ # - @abort: since 1.6 # - @block-dirty-bitmap-add: since 2.5 # - @block-dirty-bitmap-clear: since 2.5 +# - @x-block-dirty-bitmap-enable: since 3.0 +# - @x-block-dirty-bitmap-disable: since 3.0 # - @blockdev-backup: since 2.3 # - @blockdev-snapshot: since 2.5 # - @blockdev-snapshot-internal-sync: since 1.7 @@ -59,6 +61,8 @@ 'abort': 'Abort', 'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd', 'block-dirty-bitmap-clear': 'BlockDirtyBitmap', + 'x-block-dirty-bitmap-enable': 'BlockDirtyBitmap', + 'x-block-dirty-bitmap-disable': 'BlockDirtyBitmap', 'blockdev-backup': 'BlockdevBackup', 'blockdev-snapshot': 'BlockdevSnapshot', 'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal', From b598e531f1123d2fb72615f1161c66093be751ea Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 11 Jun 2018 14:53:32 -0400 Subject: [PATCH 6/7] qapi: add x-block-dirty-bitmap-merge Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Jeff Cody Message-id: 20180606182449.1607-5-jsnow@redhat.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 18 +++++++++++++++++ blockdev.c | 30 ++++++++++++++++++++++++++++ include/block/dirty-bitmap.h | 3 ++- qapi/block-core.json | 38 ++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 59b38b2671..383d742cdb 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -728,3 +728,21 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset) { return hbitmap_next_zero(bitmap->bitmap, offset); } + +void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, + Error **errp) +{ + /* only bitmaps from one bds are supported */ + assert(dest->mutex == src->mutex); + + qemu_mutex_lock(dest->mutex); + + assert(bdrv_dirty_bitmap_enabled(dest)); + assert(!bdrv_dirty_bitmap_readonly(dest)); + + if (!hbitmap_merge(dest->bitmap, src->bitmap)) { + error_setg(errp, "Bitmaps are incompatible and can't be merged"); + } + + qemu_mutex_unlock(dest->mutex); +} diff --git a/blockdev.c b/blockdev.c index 2ac15601d9..dcb7a6d54e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3043,6 +3043,36 @@ void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name, bdrv_disable_dirty_bitmap(bitmap); } +void qmp_x_block_dirty_bitmap_merge(const char *node, const char *dst_name, + const char *src_name, Error **errp) +{ + BlockDriverState *bs; + BdrvDirtyBitmap *dst, *src; + + dst = block_dirty_bitmap_lookup(node, dst_name, &bs, errp); + if (!dst) { + return; + } + + if (bdrv_dirty_bitmap_frozen(dst)) { + error_setg(errp, "Bitmap '%s' is frozen and cannot be modified", + dst_name); + return; + } else if (bdrv_dirty_bitmap_readonly(dst)) { + error_setg(errp, "Bitmap '%s' is readonly and cannot be modified", + dst_name); + return; + } + + src = bdrv_find_dirty_bitmap(bs, src_name); + if (!src) { + error_setg(errp, "Dirty bitmap '%s' not found", src_name); + return; + } + + bdrv_merge_dirty_bitmap(dst, src, errp); +} + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, const char *name, Error **errp) diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 5a51a78b63..02e0cbabd2 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -69,7 +69,8 @@ void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value); void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent); void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked); - +void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, + Error **errp); /* Functions that require manual locking. */ void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap); diff --git a/qapi/block-core.json b/qapi/block-core.json index 02de674f5f..9d4ab93190 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1740,6 +1740,20 @@ 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32', '*persistent': 'bool', '*autoload': 'bool' } } +## +# @BlockDirtyBitmapMerge: +# +# @node: name of device/node which the bitmap is tracking +# +# @dst_name: name of the destination dirty bitmap +# +# @src_name: name of the source dirty bitmap +# +# Since: 3.0 +## +{ 'struct': 'BlockDirtyBitmapMerge', + 'data': { 'node': 'str', 'dst_name': 'str', 'src_name': 'str' } } + ## # @block-dirty-bitmap-add: # @@ -1850,6 +1864,30 @@ { 'command': 'x-block-dirty-bitmap-disable', 'data': 'BlockDirtyBitmap' } +## +# @x-block-dirty-bitmap-merge: +# +# Merge @src_name dirty bitmap to @dst_name dirty bitmap. @src_name dirty +# bitmap is unchanged. On error, @dst_name is unchanged. +# +# Returns: nothing on success +# If @node is not a valid block device, DeviceNotFound +# If @dst_name or @src_name is not found, GenericError +# If bitmaps has different sizes or granularities, GenericError +# +# Since: 3.0 +# +# Example: +# +# -> { "execute": "x-block-dirty-bitmap-merge", +# "arguments": { "node": "drive0", "dst_name": "bitmap0", +# "src_name": "bitmap1" } } +# <- { "return": {} } +# +## + { 'command': 'x-block-dirty-bitmap-merge', + 'data': 'BlockDirtyBitmapMerge' } + ## # @BlockDirtyBitmapSha256: # From a6e2ca5f6521553681ae136578ec1cb67e1a7973 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 11 Jun 2018 14:53:32 -0400 Subject: [PATCH 7/7] qapi: add disabled parameter to block-dirty-bitmap-add This is needed, for example, to create a new bitmap and merge several disabled bitmaps into a new one. Without this flag we will have to put block-dirty-bitmap-add and block-dirty-bitmap-disable into one transaction. Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Jeff Cody Message-id: 20180606182449.1607-6-jsnow@redhat.com Signed-off-by: John Snow --- blockdev.c | 10 ++++++++++ qapi/block-core.json | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index dcb7a6d54e..4862323012 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2073,6 +2073,7 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common, action->has_granularity, action->granularity, action->has_persistent, action->persistent, action->has_autoload, action->autoload, + action->has_x_disabled, action->x_disabled, &local_err); if (!local_err) { @@ -2880,6 +2881,7 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, bool has_granularity, uint32_t granularity, bool has_persistent, bool persistent, bool has_autoload, bool autoload, + bool has_disabled, bool disabled, Error **errp) { BlockDriverState *bs; @@ -2914,6 +2916,10 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, warn_report("Autoload option is deprecated and its value is ignored"); } + if (!has_disabled) { + disabled = false; + } + if (persistent && !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) { @@ -2925,6 +2931,10 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, return; } + if (disabled) { + bdrv_disable_dirty_bitmap(bitmap); + } + bdrv_dirty_bitmap_set_persistance(bitmap, persistent); } diff --git a/qapi/block-core.json b/qapi/block-core.json index 9d4ab93190..fff23fc82b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1734,11 +1734,15 @@ # Currently, all dirty tracking bitmaps are loaded from Qcow2 on # open. # +# @x-disabled: the bitmap is created in the disabled state, which means that +# it will not track drive changes. The bitmap may be enabled with +# x-block-dirty-bitmap-enable. Default is false. (Since: 3.0) +# # Since: 2.4 ## { 'struct': 'BlockDirtyBitmapAdd', 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32', - '*persistent': 'bool', '*autoload': 'bool' } } + '*persistent': 'bool', '*autoload': 'bool', '*x-disabled': 'bool' } } ## # @BlockDirtyBitmapMerge: