mirror of https://github.com/xemu-project/xemu.git
block: bdrv_reopen() with backing file in different AioContext
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> Tested-by: Peter Krempa <pkrempa@redhat.com> Message-Id: <20200306141413.30705-3-kwolf@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
97518e11c3
commit
1de6b45fb5
32
block.c
32
block.c
|
@ -3787,6 +3787,29 @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
|
||||||
*shared = cumulative_shared_perms;
|
*shared = cumulative_shared_perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool bdrv_reopen_can_attach(BlockDriverState *parent,
|
||||||
|
BdrvChild *child,
|
||||||
|
BlockDriverState *new_child,
|
||||||
|
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
|
* Take a BDRVReopenState and check if the value of 'backing' in the
|
||||||
* reopen_state->options QDict is valid or not.
|
* reopen_state->options QDict is valid or not.
|
||||||
|
@ -3838,14 +3861,11 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: before removing the x- prefix from x-blockdev-reopen we
|
* Check AioContext compatibility so that the bdrv_set_backing_hd() call in
|
||||||
* should move the new backing file into the right AioContext
|
* bdrv_reopen_commit() won't fail.
|
||||||
* instead of returning an error.
|
|
||||||
*/
|
*/
|
||||||
if (new_backing_bs) {
|
if (new_backing_bs) {
|
||||||
if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) {
|
if (!bdrv_reopen_can_attach(bs, bs->backing, new_backing_bs, errp)) {
|
||||||
error_setg(errp, "Cannot use a new backing file "
|
|
||||||
"with a different AioContext");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1015,18 +1015,16 @@ class TestBlockdevReopen(iotests.QMPTestCase):
|
||||||
# neither of them can switch to the other AioContext
|
# neither of them can switch to the other AioContext
|
||||||
def test_iothreads_error(self):
|
def test_iothreads_error(self):
|
||||||
self.run_test_iothreads('iothread0', 'iothread1',
|
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):
|
def test_iothreads_compatible_users(self):
|
||||||
self.run_test_iothreads('iothread0', 'iothread0')
|
self.run_test_iothreads('iothread0', 'iothread0')
|
||||||
|
|
||||||
def test_iothreads_switch_backing(self):
|
def test_iothreads_switch_backing(self):
|
||||||
self.run_test_iothreads('iothread0', None,
|
self.run_test_iothreads('iothread0', None)
|
||||||
"Cannot use a new backing file with a different AioContext")
|
|
||||||
|
|
||||||
def test_iothreads_switch_overlay(self):
|
def test_iothreads_switch_overlay(self):
|
||||||
self.run_test_iothreads(None, 'iothread0',
|
self.run_test_iothreads(None, 'iothread0')
|
||||||
"Cannot use a new backing file with a different AioContext")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
iotests.main(supported_fmts=["qcow2"],
|
iotests.main(supported_fmts=["qcow2"],
|
||||||
|
|
Loading…
Reference in New Issue