mirror of https://github.com/proxmox/mirror_qemu
block: improve block_dirty_bitmap_merge(): don't allocate extra bitmap
We don't need extra bitmap. All we need is to backup the original bitmap when we do first merge. So, drop extra temporary bitmap and work directly with target and backup. Still to keep old semantics, that on failure target is unchanged and user don't need to restore, we need a local_backup variable and do restore ourselves on failure path. Signed-off-by: Vladimir Sementsov-Ogievskiy <v.sementsov-og@mail.ru> Message-Id: <20220517111206.23585-3-v.sementsov-og@mail.ru> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>master
parent
775b30b305
commit
58cbfbdf73
|
@ -261,8 +261,9 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
|
||||||
HBitmap **backup, Error **errp)
|
HBitmap **backup, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BdrvDirtyBitmap *dst, *src, *anon;
|
BdrvDirtyBitmap *dst, *src;
|
||||||
BlockDirtyBitmapOrStrList *lst;
|
BlockDirtyBitmapOrStrList *lst;
|
||||||
|
HBitmap *local_backup = NULL;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
|
@ -271,12 +272,6 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
|
|
||||||
NULL, errp);
|
|
||||||
if (!anon) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (lst = bms; lst; lst = lst->next) {
|
for (lst = bms; lst; lst = lst->next) {
|
||||||
switch (lst->value->type) {
|
switch (lst->value->type) {
|
||||||
const char *name, *node;
|
const char *name, *node;
|
||||||
|
@ -285,8 +280,7 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
|
||||||
src = bdrv_find_dirty_bitmap(bs, name);
|
src = bdrv_find_dirty_bitmap(bs, name);
|
||||||
if (!src) {
|
if (!src) {
|
||||||
error_setg(errp, "Dirty bitmap '%s' not found", name);
|
error_setg(errp, "Dirty bitmap '%s' not found", name);
|
||||||
dst = NULL;
|
goto fail;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QTYPE_QDICT:
|
case QTYPE_QDICT:
|
||||||
|
@ -294,29 +288,36 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
|
||||||
name = lst->value->u.external.name;
|
name = lst->value->u.external.name;
|
||||||
src = block_dirty_bitmap_lookup(node, name, NULL, errp);
|
src = block_dirty_bitmap_lookup(node, name, NULL, errp);
|
||||||
if (!src) {
|
if (!src) {
|
||||||
dst = NULL;
|
goto fail;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bdrv_merge_dirty_bitmap(anon, src, NULL, errp)) {
|
/* We do backup only for first merge operation */
|
||||||
dst = NULL;
|
if (!bdrv_merge_dirty_bitmap(dst, src,
|
||||||
goto out;
|
local_backup ? NULL : &local_backup,
|
||||||
|
errp))
|
||||||
|
{
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Merge into dst; dst is unchanged on failure. */
|
if (backup) {
|
||||||
if (!bdrv_merge_dirty_bitmap(dst, anon, backup, errp)) {
|
*backup = local_backup;
|
||||||
dst = NULL;
|
} else {
|
||||||
goto out;
|
hbitmap_free(local_backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
bdrv_release_dirty_bitmap(anon);
|
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (local_backup) {
|
||||||
|
bdrv_restore_dirty_bitmap(dst, local_backup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
|
void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
|
||||||
|
|
Loading…
Reference in New Issue