diff mbox

[1/9] block: Introduce reference count for dirty bitmaps

Message ID 1389609588-32104-2-git-send-email-famz@redhat.com
State New
Headers show

Commit Message

Fam Zheng Jan. 13, 2014, 10:39 a.m. UTC
A dirty bitmap may be created by user via QMP, then reference by other
QMP commands, such as backup. We need reference count machanism to
manage the lifecycle of dirty bitmap.

This adds bdrv_release_dirty_bitmap and changes
bdrv_release_dirty_bitmap to only free the structure when refcnt goes to
0.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block.c               | 17 ++++++++++++++---
 include/block/block.h |  1 +
 2 files changed, 15 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/block.c b/block.c
index 64e7d22..6ad0368 100644
--- a/block.c
+++ b/block.c
@@ -51,6 +51,7 @@ 
 
 struct BdrvDirtyBitmap {
     HBitmap *bitmap;
+    int refcnt;
     QLIST_ENTRY(BdrvDirtyBitmap) list;
 };
 
@@ -4543,6 +4544,7 @@  BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
     bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
     bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
     bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
+    bitmap->refcnt = 1;
     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
     return bitmap;
 }
@@ -4552,14 +4554,23 @@  void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
     BdrvDirtyBitmap *bm, *next;
     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
         if (bm == bitmap) {
-            QLIST_REMOVE(bitmap, list);
-            hbitmap_free(bitmap->bitmap);
-            g_free(bitmap);
+            assert(bitmap->refcnt > 0);
+            bitmap->refcnt--;
+            if (bitmap->refcnt == 0) {
+                QLIST_REMOVE(bitmap, list);
+                hbitmap_free(bitmap->bitmap);
+                g_free(bitmap);
+            }
             return;
         }
     }
 }
 
+void bdrv_reference_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
+{
+    bitmap->refcnt++;
+}
+
 BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
 {
     BdrvDirtyBitmap *bm;
diff --git a/include/block/block.h b/include/block/block.h
index 36efaea..0c776e3 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -426,6 +426,7 @@  struct HBitmapIter;
 typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
 void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
+void bdrv_reference_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
 BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
 int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
 void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);