Until now, bdrv_drained_begin() used bdrv_drain() internally to drain the queue. This is kind of backwards and caused quiescing code to be duplicated because bdrv_drained_begin() had to ensure that no new requests come in even after bdrv_drain() returns, whereas bdrv_drain() had to have them because it could be called from other places.
Instead move the bdrv_drain() code to bdrv_drained_begin() and make bdrv_drain() a simple wrapper around bdrv_drained_begin/end(). Signed-off-by: Kevin Wolf <kw...@redhat.com> Reviewed-by: Eric Blake <ebl...@redhat.com> Reviewed-by: Fam Zheng <f...@redhat.com> --- block/io.c | 69 ++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/block/io.c b/block/io.c index 2a28d63..9bc1d45 100644 --- a/block/io.c +++ b/block/io.c @@ -225,6 +225,34 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) assert(data.done); } +void bdrv_drained_begin(BlockDriverState *bs) +{ + if (!bs->quiesce_counter++) { + aio_disable_external(bdrv_get_aio_context(bs)); + bdrv_parent_drained_begin(bs); + } + + bdrv_io_unplugged_begin(bs); + bdrv_drain_recurse(bs); + if (qemu_in_coroutine()) { + bdrv_co_yield_to_drain(bs); + } else { + bdrv_drain_poll(bs); + } + bdrv_io_unplugged_end(bs); +} + +void bdrv_drained_end(BlockDriverState *bs) +{ + assert(bs->quiesce_counter > 0); + if (--bs->quiesce_counter > 0) { + return; + } + + bdrv_parent_drained_end(bs); + aio_enable_external(bdrv_get_aio_context(bs)); +} + /* * Wait for pending requests to complete on a single BlockDriverState subtree, * and suspend block driver's internal I/O until next request arrives. @@ -238,26 +266,15 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) */ void coroutine_fn bdrv_co_drain(BlockDriverState *bs) { - bdrv_parent_drained_begin(bs); - bdrv_io_unplugged_begin(bs); - bdrv_drain_recurse(bs); - bdrv_co_yield_to_drain(bs); - bdrv_io_unplugged_end(bs); - bdrv_parent_drained_end(bs); + assert(qemu_in_coroutine()); + bdrv_drained_begin(bs); + bdrv_drained_end(bs); } void bdrv_drain(BlockDriverState *bs) { - bdrv_parent_drained_begin(bs); - bdrv_io_unplugged_begin(bs); - bdrv_drain_recurse(bs); - if (qemu_in_coroutine()) { - bdrv_co_yield_to_drain(bs); - } else { - bdrv_drain_poll(bs); - } - bdrv_io_unplugged_end(bs); - bdrv_parent_drained_end(bs); + bdrv_drained_begin(bs); + bdrv_drained_end(bs); } /* @@ -2541,23 +2558,3 @@ void bdrv_io_unplugged_end(BlockDriverState *bs) } } } - -void bdrv_drained_begin(BlockDriverState *bs) -{ - if (!bs->quiesce_counter++) { - aio_disable_external(bdrv_get_aio_context(bs)); - } - bdrv_parent_drained_begin(bs); - bdrv_drain(bs); -} - -void bdrv_drained_end(BlockDriverState *bs) -{ - bdrv_parent_drained_end(bs); - - assert(bs->quiesce_counter > 0); - if (--bs->quiesce_counter > 0) { - return; - } - aio_enable_external(bdrv_get_aio_context(bs)); -} -- 1.8.3.1