@@ -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));
-}
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 <kwolf@redhat.com> --- block/io.c | 69 ++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 36 deletions(-)