79 lines
2.8 KiB
Diff
79 lines
2.8 KiB
Diff
|
|
From ec96b9f64c239736003413d70dc3999ad0b8271c Mon Sep 17 00:00:00 2001
|
||
|
|
From: Kevin Wolf <kwolf@redhat.com>
|
||
|
|
Date: Tue, 10 Mar 2020 12:38:29 +0100
|
||
|
|
Subject: [PATCH] block: Fix cross-AioContext blockdev-snapshot
|
||
|
|
|
||
|
|
external_snapshot_prepare() tries to move the overlay to the AioContext
|
||
|
|
of the backing file (the snapshotted node). However, it's possible that
|
||
|
|
this doesn't work, but the backing file can instead be moved to the
|
||
|
|
overlay's AioContext (e.g. opening the backing chain for a mirror
|
||
|
|
target).
|
||
|
|
|
||
|
|
bdrv_append() already indirectly uses bdrv_attach_node(), which takes
|
||
|
|
care to move nodes to make sure they use the same AioContext and which
|
||
|
|
tries both directions.
|
||
|
|
|
||
|
|
So the problem has a simple fix: Just delete the unnecessary extra
|
||
|
|
bdrv_try_set_aio_context() call in external_snapshot_prepare() and
|
||
|
|
instead assert in bdrv_append() that both nodes were indeed moved to the
|
||
|
|
same AioContext.
|
||
|
|
|
||
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||
|
|
Message-Id: <20200310113831.27293-6-kwolf@redhat.com>
|
||
|
|
Tested-by: Peter Krempa <pkrempa@redhat.com>
|
||
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||
|
|
---
|
||
|
|
block.c | 1 +
|
||
|
|
blockdev.c | 16 ----------------
|
||
|
|
2 files changed, 1 insertion(+), 16 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/block.c b/block.c
|
||
|
|
index ba36b53a00..824025f781 100644
|
||
|
|
--- a/block.c
|
||
|
|
+++ b/block.c
|
||
|
|
@@ -4165,6 +4165,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
|
||
|
|
bdrv_ref(from);
|
||
|
|
|
||
|
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||
|
|
+ assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to));
|
||
|
|
bdrv_drained_begin(from);
|
||
|
|
|
||
|
|
/* Put all parents into @list and calculate their cumulative permissions */
|
||
|
|
diff --git a/blockdev.c b/blockdev.c
|
||
|
|
index 79112be2e6..d1a3b6a630 100644
|
||
|
|
--- a/blockdev.c
|
||
|
|
+++ b/blockdev.c
|
||
|
|
@@ -1578,8 +1578,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||
|
|
DO_UPCAST(ExternalSnapshotState, common, common);
|
||
|
|
TransactionAction *action = common->action;
|
||
|
|
AioContext *aio_context;
|
||
|
|
- AioContext *old_context;
|
||
|
|
- int ret;
|
||
|
|
|
||
|
|
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
|
||
|
|
* purpose but a different set of parameters */
|
||
|
|
@@ -1719,20 +1717,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
|
||
|
|
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
||
|
|
- old_context = bdrv_get_aio_context(state->new_bs);
|
||
|
|
- aio_context_release(aio_context);
|
||
|
|
- aio_context_acquire(old_context);
|
||
|
|
-
|
||
|
|
- ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
|
||
|
|
-
|
||
|
|
- aio_context_release(old_context);
|
||
|
|
- aio_context_acquire(aio_context);
|
||
|
|
-
|
||
|
|
- if (ret < 0) {
|
||
|
|
- goto out;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
/* This removes our old bs and adds the new bs. This is an operation that
|
||
|
|
* can fail, so we need to do it in .prepare; undoing it for abort is
|
||
|
|
* always possible. */
|
||
|
|
--
|
||
|
|
2.27.0
|
||
|
|
|