mirror of
https://github.com/mii443/qemu.git
synced 2025-08-22 15:15:46 +00:00
blockdev: n-ary bitmap merge
Especially outside of transactions, it is helpful to provide all-or-nothing semantics for bitmap merges. This facilitates the coalescing of multiple bitmaps into a single target for the "checkpoint" interpretation when assembling bitmaps that represent arbitrary points in time from component bitmaps. This is an incompatible change from the preliminary version of the API. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <20181221093529.23855-4-jsnow@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
75
blockdev.c
75
blockdev.c
@ -2119,33 +2119,28 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common)
|
||||
}
|
||||
}
|
||||
|
||||
static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
|
||||
const char *target,
|
||||
strList *bitmaps,
|
||||
HBitmap **backup,
|
||||
Error **errp);
|
||||
|
||||
static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDirtyBitmapMerge *action;
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
BdrvDirtyBitmap *merge_source;
|
||||
|
||||
if (action_check_completion_mode(common, errp) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
action = common->action->u.x_block_dirty_bitmap_merge.data;
|
||||
state->bitmap = block_dirty_bitmap_lookup(action->node,
|
||||
action->dst_name,
|
||||
&state->bs,
|
||||
errp);
|
||||
if (!state->bitmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
merge_source = bdrv_find_dirty_bitmap(state->bs, action->src_name);
|
||||
if (!merge_source) {
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_merge_dirty_bitmap(state->bitmap, merge_source, &state->backup, errp);
|
||||
state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target,
|
||||
action->bitmaps, &state->backup,
|
||||
errp);
|
||||
}
|
||||
|
||||
static void abort_prepare(BlkActionState *common, Error **errp)
|
||||
@ -2977,24 +2972,56 @@ 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)
|
||||
static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
|
||||
const char *target,
|
||||
strList *bitmaps,
|
||||
HBitmap **backup,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BdrvDirtyBitmap *dst, *src;
|
||||
BdrvDirtyBitmap *dst, *src, *anon;
|
||||
strList *lst;
|
||||
Error *local_err = NULL;
|
||||
|
||||
dst = block_dirty_bitmap_lookup(node, dst_name, &bs, errp);
|
||||
dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
|
||||
if (!dst) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = bdrv_find_dirty_bitmap(bs, src_name);
|
||||
if (!src) {
|
||||
error_setg(errp, "Dirty bitmap '%s' not found", src_name);
|
||||
return;
|
||||
anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
|
||||
NULL, errp);
|
||||
if (!anon) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_merge_dirty_bitmap(dst, src, NULL, errp);
|
||||
for (lst = bitmaps; lst; lst = lst->next) {
|
||||
src = bdrv_find_dirty_bitmap(bs, lst->value);
|
||||
if (!src) {
|
||||
error_setg(errp, "Dirty bitmap '%s' not found", lst->value);
|
||||
dst = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
dst = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Merge into dst; dst is unchanged on failure. */
|
||||
bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
|
||||
|
||||
out:
|
||||
bdrv_release_dirty_bitmap(bs, anon);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void qmp_x_block_dirty_bitmap_merge(const char *node, const char *target,
|
||||
strList *bitmaps, Error **errp)
|
||||
{
|
||||
do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
|
||||
}
|
||||
|
||||
BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
|
||||
|
Reference in New Issue
Block a user