diff options
author | Kevin Wolf <kwolf@redhat.com> | 2019-05-06 19:18:01 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2019-05-20 17:08:56 +0200 |
commit | 38475269d4d9efcc5f1a5aae4834d165248ea13d (patch) | |
tree | 8b882ecc72c392752bff349221e72e97b00f9447 | |
parent | 7e2f096a823f75ca3f1df1811c406b46254587fd (diff) | |
download | qemu-38475269d4d9efcc5f1a5aae4834d165248ea13d.zip qemu-38475269d4d9efcc5f1a5aae4834d165248ea13d.tar.gz qemu-38475269d4d9efcc5f1a5aae4834d165248ea13d.tar.bz2 |
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 <kwolf@redhat.com>
-rw-r--r-- | block/block-backend.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/block/block-backend.c b/block/block-backend.c index f78e82a..0e75fc8 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) |