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 <jc...@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(-)

diff --git a/block.c b/block.c
index 53f7b08..1567cc2 100644
--- a/block.c
+++ b/block.c
@@ -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;
         }
     }
diff --git a/block/mirror.c b/block/mirror.c
index a258926..8b3e89b 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -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);
diff --git a/blockdev.c b/blockdev.c
index 32b04b4..cb9f78d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -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);
diff --git a/include/block/block.h b/include/block/block.h
index ef67353..2ec1e20 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -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,
diff --git a/migration/block.c b/migration/block.c
index ed865ed..c3e2b86 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -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;
-- 
1.9.3


Reply via email to