@@ -261,8 +261,9 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
HBitmap **backup, Error **errp)
{
BlockDriverState *bs;
- BdrvDirtyBitmap *dst, *src, *anon;
+ BdrvDirtyBitmap *dst, *src;
BlockDirtyBitmapOrStrList *lst;
+ HBitmap *local_backup = NULL;
GLOBAL_STATE_CODE();
@@ -271,12 +272,6 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
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) {
switch (lst->value->type) {
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);
if (!src) {
error_setg(errp, "Dirty bitmap '%s' not found", name);
- dst = NULL;
- goto out;
+ goto fail;
}
break;
case QTYPE_QDICT:
@@ -294,29 +288,36 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
name = lst->value->u.external.name;
src = block_dirty_bitmap_lookup(node, name, NULL, errp);
if (!src) {
- dst = NULL;
- goto out;
+ goto fail;
}
break;
default:
abort();
}
- if (!bdrv_merge_dirty_bitmap(anon, src, NULL, errp)) {
- dst = NULL;
- goto out;
+ /* We do backup only for first merge operation */
+ if (!bdrv_merge_dirty_bitmap(dst, src,
+ local_backup ? NULL : &local_backup,
+ errp))
+ {
+ goto fail;
}
}
- /* Merge into dst; dst is unchanged on failure. */
- if (!bdrv_merge_dirty_bitmap(dst, anon, backup, errp)) {
- dst = NULL;
- goto out;
+ if (backup) {
+ *backup = local_backup;
+ } else {
+ hbitmap_free(local_backup);
}
- out:
- bdrv_release_dirty_bitmap(anon);
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,