Add field 'persistent' to BdrvDirtyBitmap. Store all persistent bitmaps of the BDS in bdrv_close().
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block.c | 2 ++ block/dirty-bitmap.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/block/dirty-bitmap.h | 5 +++++ 3 files changed, 49 insertions(+) diff --git a/block.c b/block.c index 30d64e6..fdef1b2 100644 --- a/block.c +++ b/block.c @@ -2155,6 +2155,8 @@ static void bdrv_close(BlockDriverState *bs) bdrv_flush(bs); bdrv_drain(bs); /* in case flush left pending I/O */ + /* save and release persistent dirty bitmaps */ + bdrv_finalize_persistent_dirty_bitmaps(bs); bdrv_release_named_dirty_bitmaps(bs); assert(QLIST_EMPTY(&bs->dirty_bitmaps)); diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 83415e1..6df7fe1 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -44,6 +44,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; /* bitmap must be saved to owner disk image */ QLIST_ENTRY(BdrvDirtyBitmap) list; }; @@ -70,6 +71,8 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) assert(!bdrv_dirty_bitmap_frozen(bitmap)); g_free(bitmap->name); bitmap->name = NULL; + + bitmap->persistent = false; } BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, @@ -238,6 +241,8 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, bitmap->name = NULL; successor->name = name; bitmap->successor = NULL; + successor->persistent = bitmap->persistent; + bitmap->persistent = false; bdrv_release_dirty_bitmap(bs, bitmap); return successor; @@ -555,3 +560,40 @@ bool bdrv_load_check_dirty_bitmap(BlockDriverState *file, const char *name) } return false; } + +void bdrv_store_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + Error **errp) +{ + if (bs == NULL || bs->drv == NULL || + bs->drv->bdrv_dirty_bitmap_store == NULL) { + error_setg(errp, "Storing bitmap is unsupported for the format."); + return; + } + + bs->drv->bdrv_dirty_bitmap_store(bs, bitmap, errp); +} + +void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, + bool persistent) +{ + bitmap->persistent = persistent; +} + +void bdrv_finalize_persistent_dirty_bitmaps(BlockDriverState *bs) +{ + BdrvDirtyBitmap *bm, *bm_next; + + QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, bm_next) { + if (bm->persistent) { + if (!bdrv_is_read_only(bs) && + !(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) { + Error *local_err = NULL; + bdrv_store_dirty_bitmap(bs, bm, &local_err); + if (local_err) { + error_report_err(local_err); + } + } + bdrv_release_dirty_bitmap(bs, bm); + } + } +} diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 6007c64..05aa7f9 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -76,5 +76,10 @@ void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap); bool bdrv_load_check_dirty_bitmap(BlockDriverState *file, const char *name); +void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, + bool persistent); +void bdrv_store_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + Error **errp); +void bdrv_finalize_persistent_dirty_bitmaps(BlockDriverState *bs); #endif -- 1.8.3.1