From 38475269d4d9efcc5f1a5aae4834d165248ea13d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 6 May 2019 19:18:01 +0200 Subject: [PATCH] block: Implement .(can_)set_aio_ctx for BlockBackend bdrv_try_set_aio_context() currently fails if a BlockBackend is attached to a node because it doesn't implement the BdrvChildRole callbacks for AioContext management. We can allow changing the AioContext of monitor-owned BlockBackends as long as no device is attached to them. When setting the AioContext of the root node of a BlockBackend, we now need to pass blk->root as an ignored child because we don't want the root node to recursively call back into BlockBackend and execute blk_do_set_aio_context() a second time. Signed-off-by: Kevin Wolf --- block/block-backend.c | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index f78e82a707..0e75fc8849 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -124,6 +124,11 @@ static void blk_root_drained_end(BdrvChild *child); static void blk_root_change_media(BdrvChild *child, bool load); static void blk_root_resize(BdrvChild *child); +static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx, + GSList **ignore, Error **errp); +static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx, + GSList **ignore); + static char *blk_root_get_parent_desc(BdrvChild *child) { BlockBackend *blk = child->opaque; @@ -300,6 +305,9 @@ static const BdrvChildRole child_root = { .attach = blk_root_attach, .detach = blk_root_detach, + + .can_set_aio_ctx = blk_root_can_set_aio_ctx, + .set_aio_ctx = blk_root_set_aio_ctx, }; /* @@ -1852,7 +1860,8 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb) return blk_get_aio_context(blk_acb->blk); } -void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) +static void blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context, + bool update_root_node) { BlockDriverState *bs = blk_bs(blk); ThrottleGroupMember *tgm = &blk->public.throttle_group_member; @@ -1864,10 +1873,42 @@ void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) throttle_group_attach_aio_context(tgm, new_context); bdrv_drained_end(bs); } - bdrv_set_aio_context(bs, new_context); + if (update_root_node) { + GSList *ignore = g_slist_prepend(NULL, blk->root); + bdrv_set_aio_context_ignore(bs, new_context, &ignore); + g_slist_free(ignore); + } } } +void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) +{ + blk_do_set_aio_context(blk, new_context, true); +} + +static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx, + GSList **ignore, Error **errp) +{ + BlockBackend *blk = child->opaque; + + /* Only manually created BlockBackends that are not attached to anything + * can change their AioContext without updating their user. */ + if (!blk->name || blk->dev) { + /* TODO Add BB name/QOM path */ + error_setg(errp, "Cannot change iothread of active block backend"); + return false; + } + + return true; +} + +static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx, + GSList **ignore) +{ + BlockBackend *blk = child->opaque; + blk_do_set_aio_context(blk, ctx, false); +} + void blk_add_aio_context_notifier(BlockBackend *blk, void (*attached_aio_context)(AioContext *new_context, void *opaque), void (*detach_aio_context)(void *opaque), void *opaque)