From e73a265e9f0fe4dfa376bffe78f121b85c7a5a03 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 13 Mar 2018 15:33:59 -0400 Subject: block/dirty-bitmap: add bdrv_dirty_bitmap_enable_successor() Enabling bitmap successor is necessary to enable successors of bitmaps being migrated before target vm start. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Reviewed-by: Fam Zheng Message-id: 20180207155837.92351-2-vsementsov@virtuozzo.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'block') diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 909f0517f8..0d0e807216 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -234,6 +234,14 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, return 0; } +/* Called with BQL taken. */ +void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) +{ + qemu_mutex_lock(bitmap->mutex); + bdrv_enable_dirty_bitmap(bitmap->successor); + qemu_mutex_unlock(bitmap->mutex); +} + /** * For a bitmap with a successor, yield our name to the successor, * delete the old bitmap, and return a handle to the new bitmap. -- cgit v1.2.3 From 604ab74bb5cfb48ca67bef7537b38faf142f67dc Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 13 Mar 2018 15:34:00 -0400 Subject: block/dirty-bitmap: fix locking in bdrv_reclaim_dirty_bitmap Like other setters here these functions should take a lock. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Fam Zheng Reviewed-by: John Snow Message-id: 20180207155837.92351-3-vsementsov@virtuozzo.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 85 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 32 deletions(-) (limited to 'block') diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 0d0e807216..75435f6c2f 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -242,6 +242,51 @@ void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) qemu_mutex_unlock(bitmap->mutex); } +/* Called within bdrv_dirty_bitmap_lock..unlock */ +static void bdrv_do_release_matching_dirty_bitmap_locked( + BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + bool (*cond)(BdrvDirtyBitmap *bitmap)) +{ + BdrvDirtyBitmap *bm, *next; + + QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { + if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { + assert(!bm->active_iterators); + assert(!bdrv_dirty_bitmap_frozen(bm)); + assert(!bm->meta); + QLIST_REMOVE(bm, list); + hbitmap_free(bm->bitmap); + g_free(bm->name); + g_free(bm); + + if (bitmap) { + return; + } + } + } + + if (bitmap) { + abort(); + } +} + +/* Called with BQL taken. */ +static void bdrv_do_release_matching_dirty_bitmap( + BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + bool (*cond)(BdrvDirtyBitmap *bitmap)) +{ + bdrv_dirty_bitmaps_lock(bs); + bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, cond); + bdrv_dirty_bitmaps_unlock(bs); +} + +/* Called within bdrv_dirty_bitmap_lock..unlock */ +static void bdrv_release_dirty_bitmap_locked(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap) +{ + bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, NULL); +} + /** * For a bitmap with a successor, yield our name to the successor, * delete the old bitmap, and return a handle to the new bitmap. @@ -281,7 +326,11 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *parent, Error **errp) { - BdrvDirtyBitmap *successor = parent->successor; + BdrvDirtyBitmap *successor; + + qemu_mutex_lock(parent->mutex); + + successor = parent->successor; if (!successor) { error_setg(errp, "Cannot reclaim a successor when none is present"); @@ -292,9 +341,11 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, error_setg(errp, "Merging of parent and successor bitmap failed"); return NULL; } - bdrv_release_dirty_bitmap(bs, successor); + bdrv_release_dirty_bitmap_locked(bs, successor); parent->successor = NULL; + qemu_mutex_unlock(parent->mutex); + return parent; } @@ -321,36 +372,6 @@ static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap) return !!bdrv_dirty_bitmap_name(bitmap); } -/* Called with BQL taken. */ -static void bdrv_do_release_matching_dirty_bitmap( - BlockDriverState *bs, BdrvDirtyBitmap *bitmap, - bool (*cond)(BdrvDirtyBitmap *bitmap)) -{ - BdrvDirtyBitmap *bm, *next; - bdrv_dirty_bitmaps_lock(bs); - QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { - if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { - assert(!bm->active_iterators); - assert(!bdrv_dirty_bitmap_frozen(bm)); - assert(!bm->meta); - QLIST_REMOVE(bm, list); - hbitmap_free(bm->bitmap); - g_free(bm->name); - g_free(bm); - - if (bitmap) { - goto out; - } - } - } - if (bitmap) { - abort(); - } - -out: - bdrv_dirty_bitmaps_unlock(bs); -} - /* Called with BQL taken. */ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) { -- cgit v1.2.3 From 044ee8e143576abd72acf452080e8da531fb13c8 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 13 Mar 2018 15:34:00 -0400 Subject: block/dirty-bitmap: add _locked version of bdrv_reclaim_dirty_bitmap Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Message-id: 20180207155837.92351-4-vsementsov@virtuozzo.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'block') diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 75435f6c2f..ce00ff3474 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -320,17 +320,13 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, * In cases of failure where we can no longer safely delete the parent, * we may wish to re-join the parent and child/successor. * The merged parent will be un-frozen, but not explicitly re-enabled. - * Called with BQL taken. + * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. */ -BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, - BdrvDirtyBitmap *parent, - Error **errp) +BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs, + BdrvDirtyBitmap *parent, + Error **errp) { - BdrvDirtyBitmap *successor; - - qemu_mutex_lock(parent->mutex); - - successor = parent->successor; + BdrvDirtyBitmap *successor = parent->successor; if (!successor) { error_setg(errp, "Cannot reclaim a successor when none is present"); @@ -344,9 +340,21 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, bdrv_release_dirty_bitmap_locked(bs, successor); parent->successor = NULL; + return parent; +} + +/* Called with BQL taken. */ +BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, + BdrvDirtyBitmap *parent, + Error **errp) +{ + BdrvDirtyBitmap *ret; + + qemu_mutex_lock(parent->mutex); + ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp); qemu_mutex_unlock(parent->mutex); - return parent; + return ret; } /** -- cgit v1.2.3 From 4f43e9535bdd768bff4e30e229404407d44ad4c8 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 13 Mar 2018 15:34:00 -0400 Subject: dirty-bitmap: add locked state Add special state, when qmp operations on the bitmap are disabled. It is needed during bitmap migration. "Frozen" state is not appropriate here, because it looks like bitmap is unchanged. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Message-id: 20180207155837.92351-5-vsementsov@virtuozzo.com Signed-off-by: John Snow --- block/dirty-bitmap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'block') diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index ce00ff3474..967159479d 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -40,6 +40,8 @@ struct BdrvDirtyBitmap { QemuMutex *mutex; HBitmap *bitmap; /* Dirty bitmap implementation */ HBitmap *meta; /* Meta dirty bitmap */ + bool qmp_locked; /* Bitmap is locked, it can't be modified + through QMP */ BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */ char *name; /* Optional non-empty unique ID */ int64_t size; /* Size of the bitmap, in bytes */ @@ -183,6 +185,18 @@ bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) return bitmap->successor; } +void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked) +{ + qemu_mutex_lock(bitmap->mutex); + bitmap->qmp_locked = qmp_locked; + qemu_mutex_unlock(bitmap->mutex); +} + +bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap) +{ + return bitmap->qmp_locked; +} + /* Called with BQL taken. */ bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) { @@ -194,6 +208,8 @@ DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) { if (bdrv_dirty_bitmap_frozen(bitmap)) { return DIRTY_BITMAP_STATUS_FROZEN; + } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) { + return DIRTY_BITMAP_STATUS_LOCKED; } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { return DIRTY_BITMAP_STATUS_DISABLED; } else { -- cgit v1.2.3