Message ID | 20200227181804.15299-3-kwolf@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | block: bdrv_reopen() with backing file in different AioContext | expand |
On Thu 27 Feb 2020 07:18:04 PM CET, Kevin Wolf wrote: > /* > - * TODO: before removing the x- prefix from x-blockdev-reopen we > - * should move the new backing file into the right AioContext > - * instead of returning an error. > + * Check AioContext compatibility so that the bdrv_set_backing_hd() call in > + * bdrv_reopen_commit() won't fail. > */ > - if (new_backing_bs) { > - if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) { > - error_setg(errp, "Cannot use a new backing file " > - "with a different AioContext"); > - return -EINVAL; > - } > + if (!bdrv_reopen_can_attach(bs->backing, bs, new_backing_bs, errp)) { > + return -EINVAL; > } What happens here now if 'new_backing_bs' is NULL ? It seems that you would be calling bdrv_can_set_aio_context(NULL, ...), and it looks like that would crash. Berto
Am 05.03.2020 um 16:54 hat Alberto Garcia geschrieben: > On Thu 27 Feb 2020 07:18:04 PM CET, Kevin Wolf wrote: > > /* > > - * TODO: before removing the x- prefix from x-blockdev-reopen we > > - * should move the new backing file into the right AioContext > > - * instead of returning an error. > > + * Check AioContext compatibility so that the bdrv_set_backing_hd() call in > > + * bdrv_reopen_commit() won't fail. > > */ > > - if (new_backing_bs) { > > - if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) { > > - error_setg(errp, "Cannot use a new backing file " > > - "with a different AioContext"); > > - return -EINVAL; > > - } > > + if (!bdrv_reopen_can_attach(bs->backing, bs, new_backing_bs, errp)) { > > + return -EINVAL; > > } > > What happens here now if 'new_backing_bs' is NULL ? > > It seems that you would be calling bdrv_can_set_aio_context(NULL, ...), > and it looks like that would crash. Not sure why I thought that this check isn't needed any more... It actually works as long as everything runs in the main loop context (because bdrv_get_aio_context(NULL) return the main context, so there is nothing to do), which is why the test cases didn't fail. But as soon as you move things to a different AioContext, they will fail. Maybe even worse, the argument order for bdrv_reopen_can_attach() is wrong. Thanks for catching this, I'll send a v2. Kevin
diff --git a/block.c b/block.c index 202c67e1e8..5dbba6cf31 100644 --- a/block.c +++ b/block.c @@ -3781,6 +3781,29 @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs, *shared = cumulative_shared_perms; } +static bool bdrv_reopen_can_attach(BdrvChild *child, + BlockDriverState *new_child, + BlockDriverState *parent, + Error **errp) +{ + AioContext *parent_ctx = bdrv_get_aio_context(parent); + AioContext *child_ctx = bdrv_get_aio_context(new_child); + GSList *ignore; + bool ret; + + ignore = g_slist_prepend(NULL, child); + ret = bdrv_can_set_aio_context(new_child, parent_ctx, &ignore, NULL); + g_slist_free(ignore); + if (ret) { + return ret; + } + + ignore = g_slist_prepend(NULL, child); + ret = bdrv_can_set_aio_context(parent, child_ctx, &ignore, errp); + g_slist_free(ignore); + return ret; +} + /* * Take a BDRVReopenState and check if the value of 'backing' in the * reopen_state->options QDict is valid or not. @@ -3832,16 +3855,11 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state, } /* - * TODO: before removing the x- prefix from x-blockdev-reopen we - * should move the new backing file into the right AioContext - * instead of returning an error. + * Check AioContext compatibility so that the bdrv_set_backing_hd() call in + * bdrv_reopen_commit() won't fail. */ - if (new_backing_bs) { - if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) { - error_setg(errp, "Cannot use a new backing file " - "with a different AioContext"); - return -EINVAL; - } + if (!bdrv_reopen_can_attach(bs->backing, bs, new_backing_bs, errp)) { + return -EINVAL; } /* diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245 index 5a2cd5ed0e..d6135ec14d 100755 --- a/tests/qemu-iotests/245 +++ b/tests/qemu-iotests/245 @@ -1010,18 +1010,16 @@ class TestBlockdevReopen(iotests.QMPTestCase): # neither of them can switch to the other AioContext def test_iothreads_error(self): self.run_test_iothreads('iothread0', 'iothread1', - "Cannot use a new backing file with a different AioContext") + "Cannot change iothread of active block backend") def test_iothreads_compatible_users(self): self.run_test_iothreads('iothread0', 'iothread0') def test_iothreads_switch_backing(self): - self.run_test_iothreads('iothread0', None, - "Cannot use a new backing file with a different AioContext") + self.run_test_iothreads('iothread0', None) def test_iothreads_switch_overlay(self): - self.run_test_iothreads(None, 'iothread0', - "Cannot use a new backing file with a different AioContext") + self.run_test_iothreads(None, 'iothread0') if __name__ == '__main__': iotests.main(supported_fmts=["qcow2"],
This patch allows bdrv_reopen() (and therefore the x-blockdev-reopen QMP command) to attach a node as the new backing file even if the node is in a different AioContext than the parent if one of both nodes can be moved to the AioContext of the other node. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- block.c | 36 +++++++++++++++++++++++++++--------- tests/qemu-iotests/245 | 8 +++----- 2 files changed, 30 insertions(+), 14 deletions(-)