diff options
author | Kevin Wolf <kwolf@redhat.com> | 2019-02-18 15:33:08 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2019-02-25 15:03:19 +0100 |
commit | 28e0b2d2e13ef7c4dd645b1fd393f52009469803 (patch) | |
tree | c0223f2081b5d95e0431ea1a29347c30bffd9972 /block | |
parent | d3bd5b90890f6715bcee38e00745112157dfbe59 (diff) | |
download | qemu-28e0b2d2e13ef7c4dd645b1fd393f52009469803.zip qemu-28e0b2d2e13ef7c4dd645b1fd393f52009469803.tar.gz qemu-28e0b2d2e13ef7c4dd645b1fd393f52009469803.tar.bz2 |
nbd: Increase bs->in_flight during AioContext switch
bdrv_drain() must not leave connection_co scheduled, so bs->in_flight
needs to be increased while the coroutine is waiting to be scheduled
in the new AioContext after nbd_client_attach_aio_context().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/nbd-client.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/block/nbd-client.c b/block/nbd-client.c index 60f38f0..bfbaf7e 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -977,14 +977,30 @@ void nbd_client_detach_aio_context(BlockDriverState *bs) qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc)); } +static void nbd_client_attach_aio_context_bh(void *opaque) +{ + BlockDriverState *bs = opaque; + NBDClientSession *client = nbd_get_client_session(bs); + + /* The node is still drained, so we know the coroutine has yielded in + * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is + * entered for the first time. Both places are safe for entering the + * coroutine.*/ + qemu_aio_coroutine_enter(bs->aio_context, client->connection_co); + bdrv_dec_in_flight(bs); +} + void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context) { NBDClientSession *client = nbd_get_client_session(bs); qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context); - /* FIXME Really need a bdrv_inc_in_flight() here */ - aio_co_schedule(new_context, client->connection_co); + bdrv_inc_in_flight(bs); + + /* Need to wait here for the BH to run because the BH must run while the + * node is still drained. */ + aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs); } void nbd_client_close(BlockDriverState *bs) |