aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/block.c b/block.c
index a9c7ea600c..a2d6238b82 100644
--- a/block.c
+++ b/block.c
@@ -1985,6 +1985,8 @@ static void bdrv_rebind(BlockDriverState *bs)
}
}
+/* Fields that need to stay with the top-level BDS, no matter whether the
+ * address of the top-level BDS stays the same or not. */
static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
BlockDriverState *bs_src)
{
@@ -2020,7 +2022,13 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
/* dirty bitmap */
bs_dest->dirty_bitmaps = bs_src->dirty_bitmaps;
+}
+/* Fields that only need to be swapped if the contents of BDSes is swapped
+ * rather than pointers being changed in the parents. */
+static void bdrv_move_reference_fields(BlockDriverState *bs_dest,
+ BlockDriverState *bs_src)
+{
/* reference count */
bs_dest->refcnt = bs_src->refcnt;
@@ -2091,6 +2099,10 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
bdrv_move_feature_fields(bs_old, bs_new);
bdrv_move_feature_fields(bs_new, &tmp);
+ bdrv_move_reference_fields(&tmp, bs_old);
+ bdrv_move_reference_fields(bs_old, bs_new);
+ bdrv_move_reference_fields(bs_new, &tmp);
+
/* bs_new must remain unattached */
assert(!bs_new->blk);