By implementing bdrv_dirty_bitmap_set_persistent, a driver can support the persistent dirty bitmap feature.
Once a dirty bitmap is made persistent, the driver is responsible for saving the dirty bitmap when appropriate, for example before close; if a persistent bitmap is removed or made non-persistent, .bdrv_dirty_bitmap_set_persistent will be called, the driver should then remove the dirty bitmap from the disk. This operation is not recursed in block layer, a filter such as blkdebug needs to implement the callback and explicitly pass down to bs->file, etc. Signed-off-by: Fam Zheng <f...@redhat.com> --- block/dirty-bitmap.c | 38 ++++++++++++++++++++++++++++++++++++++ include/block/block_int.h | 8 ++++++++ include/block/dirty-bitmap.h | 4 ++++ 3 files changed, 50 insertions(+) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 1aa7f76..882a0db 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -43,6 +43,7 @@ struct BdrvDirtyBitmap { int64_t size; /* Size of the bitmap (Number of sectors) */ bool disabled; /* Bitmap is read-only */ int active_iterators; /* How many iterators are active */ + bool persistent; /* Whether this bitmap is persistent. */ QLIST_ENTRY(BdrvDirtyBitmap) list; }; @@ -71,6 +72,37 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) bitmap->name = NULL; } +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, bool flag_only, + Error **errp) +{ + int ret = 0; + + if (!bitmap->name) { + error_setg(errp, "Cannot change the persistent status of an anonymous" + "bitmap"); + return -EINVAL; + } + + if (persistent == bitmap->persistent) { + return 0; + } + + if (!flag_only) { + if (!bs->drv || !bs->drv->bdrv_dirty_bitmap_set_persistent) { + error_setg(errp, "Not supported in this format."); + return -ENOTSUP; + } + ret = bs->drv->bdrv_dirty_bitmap_set_persistent(bs, bitmap, persistent, + errp); + } + if (!ret) { + bitmap->persistent = persistent; + } + return ret; +} + BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, uint32_t granularity, const char *name, @@ -194,6 +226,12 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, uint64_t granularity; BdrvDirtyBitmap *child; + if (bitmap->persistent) { + error_setg(errp, "Cannot create a successor for a bitmap that is " + "persistent"); + return -1; + } + if (bdrv_dirty_bitmap_frozen(bitmap)) { error_setg(errp, "Cannot create a successor for a bitmap that is " "currently frozen"); diff --git a/include/block/block_int.h b/include/block/block_int.h index 5fa58e8..fbc34af 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -305,6 +305,14 @@ struct BlockDriver { */ void (*bdrv_drain)(BlockDriverState *bs); + /** + * Make the dirty bitmap persistent if persistent=true or transient + * otherwise. + */ + int (*bdrv_dirty_bitmap_set_persistent)(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, Error **errp); + QLIST_ENTRY(BlockDriver) list; }; diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index d14d923..5885720 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -24,6 +24,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name); void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); +int bdrv_dirty_bitmap_set_persistent(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + bool persistent, bool flag_only, + Error **errp); void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); -- 2.4.3