@@ -3334,6 +3334,7 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity,
const char *name,
+ bool detached,
Error **errp)
{
int64_t bitmap_size;
@@ -3342,7 +3343,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
assert((granularity & (granularity - 1)) == 0);
- if (name && bdrv_find_dirty_bitmap(bs, name)) {
+ if (name && !detached && bdrv_find_dirty_bitmap(bs, name)) {
error_setg(errp, "Bitmap already exists: %s", name);
return NULL;
}
@@ -3359,7 +3360,9 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
bitmap->size = bitmap_size;
bitmap->name = g_strdup(name);
bitmap->disabled = false;
- QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
+ if (!detached) {
+ QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
+ }
return bitmap;
}
@@ -3403,7 +3406,7 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
/* Create an anonymous successor */
granularity = bdrv_dirty_bitmap_granularity(bitmap);
- child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
+ child = bdrv_create_dirty_bitmap(bs, granularity, NULL, false, errp);
if (!child) {
return -1;
}
@@ -3483,16 +3486,27 @@ static void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
}
}
+static void bdrv_free_dirty_bitmap(BdrvDirtyBitmap *bitmap)
+{
+ hbitmap_free(bitmap->bitmap);
+ g_free(bitmap->name);
+ g_free(bitmap);
+}
+
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
{
BdrvDirtyBitmap *bm, *next;
+
+ if (bs == NULL) {
+ bdrv_free_dirty_bitmap(bitmap);
+ return;
+ }
+
QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
if (bm == bitmap) {
assert(!bdrv_dirty_bitmap_frozen(bm));
QLIST_REMOVE(bitmap, list);
- hbitmap_free(bitmap->bitmap);
- g_free(bitmap->name);
- g_free(bitmap);
+ bdrv_free_dirty_bitmap(bitmap);
return;
}
}
@@ -733,7 +733,8 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
s->buf_size = ROUND_UP(buf_size, granularity);
s->unmap = unmap;
- s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
+ s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, false,
+ errp);
if (!s->dirty_bitmap) {
g_free(s->replaces);
block_job_release(bs);
@@ -2069,7 +2069,7 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
granularity = bdrv_get_default_bitmap_granularity(bs);
}
- bdrv_create_dirty_bitmap(bs, granularity, name, errp);
+ bdrv_create_dirty_bitmap(bs, granularity, name, false, errp);
out:
aio_context_release(aio_context);
@@ -476,6 +476,7 @@ typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity,
const char *name,
+ bool detached,
Error **errp);
int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
BdrvDirtyBitmap *bitmap,
@@ -320,7 +320,7 @@ static int set_dirty_tracking(void)
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
- NULL, NULL);
+ NULL, false, NULL);
if (!bmds->dirty_bitmap) {
ret = -errno;
goto fail;
This allows the creation of detached dirty bitmaps, so that the block driver dirty bitmaps can be used without inserting the bitmap into the dirty bitmap list for a BDS. To free a bitmap that was created "detached = true", call bdrv_release_dirty_bitmap() with the BlockDriverState argument as NULL. Signed-off-by: Jeff Cody <jcody@redhat.com> --- block.c | 26 ++++++++++++++++++++------ block/mirror.c | 3 ++- blockdev.c | 2 +- include/block/block.h | 1 + migration/block.c | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-)