#include "qemu/osdep.h"
+#include "block/block-io.h"
#include "block/block_int.h"
+#include "block/dirty-bitmap.h"
#include "qapi/qapi-commands-block.h"
#include "qapi/error.h"
BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
+ GLOBAL_STATE_CODE();
+
if (!node) {
error_setg(errp, "Node cannot be NULL");
return NULL;
BdrvDirtyBitmap *bitmap;
AioContext *aio_context;
+ GLOBAL_STATE_CODE();
+
bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
if (!bitmap || !bs) {
return NULL;
}
BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
- BlockDirtyBitmapMergeSourceList *bms,
+ BlockDirtyBitmapOrStrList *bms,
HBitmap **backup, Error **errp)
{
BlockDriverState *bs;
- BdrvDirtyBitmap *dst, *src, *anon;
- BlockDirtyBitmapMergeSourceList *lst;
- Error *local_err = NULL;
+ BdrvDirtyBitmap *dst, *src;
+ BlockDirtyBitmapOrStrList *lst;
+ HBitmap *local_backup = NULL;
+
+ GLOBAL_STATE_CODE();
dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
if (!dst) {
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;
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:
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();
}
- bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- 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. */
- bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
+ 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,
- BlockDirtyBitmapMergeSourceList *bitmaps,
+ BlockDirtyBitmapOrStrList *bitmaps,
Error **errp)
{
block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);