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 <f...@redhat.com> --- block.c | 17 ++++++++++++++--- include/block/block.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) 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); -- 1.8.5.2