[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 13/32] block-backend: split blk_do_set_aio_context()
From: |
Kevin Wolf |
Subject: |
[PULL 13/32] block-backend: split blk_do_set_aio_context() |
Date: |
Tue, 30 May 2023 18:32:20 +0200 |
From: Stefan Hajnoczi <stefanha@redhat.com>
blk_set_aio_context() is not fully transactional because
blk_do_set_aio_context() updates blk->ctx outside the transaction. Most
of the time this goes unnoticed but a BlockDevOps.drained_end() callback
that invokes blk_get_aio_context() fails assert(ctx == blk->ctx). This
happens because blk->ctx is only assigned after
BlockDevOps.drained_end() is called and we're in an intermediate state
where BlockDrvierState nodes already have the new context and the
BlockBackend still has the old context.
Making blk_set_aio_context() fully transactional solves this assertion
failure because the BlockBackend's context is updated as part of the
transaction (before BlockDevOps.drained_end() is called).
Split blk_do_set_aio_context() in order to solve this assertion failure.
This helper function actually serves two different purposes:
1. It drives blk_set_aio_context().
2. It responds to BdrvChildClass->change_aio_ctx().
Get rid of the helper function. Do #1 inside blk_set_aio_context() and
do #2 inside blk_root_set_aio_ctx_commit(). This simplifies the code.
The only drawback of the fully transactional approach is that
blk_set_aio_context() must contend with blk_root_set_aio_ctx_commit()
being invoked as part of the AioContext change propagation. This can be
solved by temporarily setting blk->allow_aio_context_change to true.
Future patches call blk_get_aio_context() from
BlockDevOps->drained_end(), so this patch will become necessary.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230516190238.8401-2-stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/block-backend.c | 61 ++++++++++++++++---------------------------
1 file changed, 23 insertions(+), 38 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index dde60e0f71..2074ac6760 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2433,52 +2433,31 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB
*acb)
return blk_get_aio_context(blk_acb->blk);
}
-static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
- bool update_root_node, Error **errp)
+int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
+ Error **errp)
{
+ bool old_allow_change;
BlockDriverState *bs = blk_bs(blk);
- ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
int ret;
- if (bs) {
- bdrv_ref(bs);
-
- if (update_root_node) {
- /*
- * update_root_node MUST be false for
blk_root_set_aio_ctx_commit(),
- * as we are already in the commit function of a transaction.
- */
- ret = bdrv_try_change_aio_context(bs, new_context, blk->root,
errp);
- if (ret < 0) {
- bdrv_unref(bs);
- return ret;
- }
- }
- /*
- * Make blk->ctx consistent with the root node before we invoke any
- * other operations like drain that might inquire blk->ctx
- */
- blk->ctx = new_context;
- if (tgm->throttle_state) {
- bdrv_drained_begin(bs);
- throttle_group_detach_aio_context(tgm);
- throttle_group_attach_aio_context(tgm, new_context);
- bdrv_drained_end(bs);
- }
+ GLOBAL_STATE_CODE();
- bdrv_unref(bs);
- } else {
+ if (!bs) {
blk->ctx = new_context;
+ return 0;
}
- return 0;
-}
+ bdrv_ref(bs);
-int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
- Error **errp)
-{
- GLOBAL_STATE_CODE();
- return blk_do_set_aio_context(blk, new_context, true, errp);
+ old_allow_change = blk->allow_aio_context_change;
+ blk->allow_aio_context_change = true;
+
+ ret = bdrv_try_change_aio_context(bs, new_context, NULL, errp);
+
+ blk->allow_aio_context_change = old_allow_change;
+
+ bdrv_unref(bs);
+ return ret;
}
typedef struct BdrvStateBlkRootContext {
@@ -2490,8 +2469,14 @@ static void blk_root_set_aio_ctx_commit(void *opaque)
{
BdrvStateBlkRootContext *s = opaque;
BlockBackend *blk = s->blk;
+ AioContext *new_context = s->new_ctx;
+ ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
- blk_do_set_aio_context(blk, s->new_ctx, false, &error_abort);
+ blk->ctx = new_context;
+ if (tgm->throttle_state) {
+ throttle_group_detach_aio_context(tgm);
+ throttle_group_attach_aio_context(tgm, new_context);
+ }
}
static TransactionActionDrv set_blk_root_context = {
--
2.40.1
- [PULL 22/32] block: drain from main loop thread in bdrv_co_yield_to_drain(), (continued)
- [PULL 22/32] block: drain from main loop thread in bdrv_co_yield_to_drain(), Kevin Wolf, 2023/05/30
- [PULL 30/32] virtio-scsi: implement BlockDevOps->drained_begin(), Kevin Wolf, 2023/05/30
- [PULL 07/32] raw-format: Fix open with 'file' in iothread, Kevin Wolf, 2023/05/30
- [PULL 11/32] iotests: Make verify_virtio_scsi_pci_or_ccw() public, Kevin Wolf, 2023/05/30
- [PULL 09/32] block: Take AioContext lock in bdrv_open_driver(), Kevin Wolf, 2023/05/30
- [PULL 14/32] hw/qdev: introduce qdev_is_realized() helper, Kevin Wolf, 2023/05/30
- [PULL 12/32] iotests: Test blockdev-create in iothread, Kevin Wolf, 2023/05/30
- [PULL 10/32] block: Fix AioContext locking in bdrv_insert_node(), Kevin Wolf, 2023/05/30
- [PULL 23/32] xen-block: implement BlockDevOps->drained_begin(), Kevin Wolf, 2023/05/30
- [PULL 21/32] block: add blk_in_drain() API, Kevin Wolf, 2023/05/30
- [PULL 13/32] block-backend: split blk_do_set_aio_context(),
Kevin Wolf <=
- [PULL 20/32] hw/xen: do not use aio_set_fd_handler(is_external=true) in xen_xenstore, Kevin Wolf, 2023/05/30
- [PULL 25/32] block/export: rewrite vduse-blk drain code, Kevin Wolf, 2023/05/30
- [PULL 27/32] block/fuse: do not set is_external=true on FUSE fd, Kevin Wolf, 2023/05/30
- [PULL 28/32] virtio: make it possible to detach host notifier from any thread, Kevin Wolf, 2023/05/30
- [PULL 31/32] virtio: do not set is_external=true on host notifiers, Kevin Wolf, 2023/05/30
- [PULL 29/32] virtio-blk: implement BlockDevOps->drained_begin(), Kevin Wolf, 2023/05/30
- [PULL 32/32] aio: remove aio_disable_external() API, Kevin Wolf, 2023/05/30
- Re: [PULL 00/32] Block layer patches, Richard Henderson, 2023/05/30