[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH v2 04/20] block: Don't manually poll in bdrv_drain_a
From: |
Kevin Wolf |
Subject: |
[Qemu-block] [PATCH v2 04/20] block: Don't manually poll in bdrv_drain_all() |
Date: |
Tue, 29 May 2018 19:21:40 +0200 |
All involved nodes are already idle, we called bdrv_do_drain_begin() on
them.
The comment in the code suggested that this was not correct because the
completion of a request on one node could spawn a new request on a
different node (which might have been drained before, so we wouldn't
drain the new request). In reality, new requests to different nodes
aren't spawned out of nothing, but only in the context of a parent
request, and they aren't submitted to random nodes, but only to child
nodes. As long as we still poll for the completion of the parent request
(which we do), draining each root node separately is good enough.
Remove the additional polling code from bdrv_drain_all_begin() and
replace it with an assertion that all nodes are already idle after we
drained them separately.
Signed-off-by: Kevin Wolf <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
---
block/io.c | 41 ++++++++++++-----------------------------
1 file changed, 12 insertions(+), 29 deletions(-)
diff --git a/block/io.c b/block/io.c
index 48d4d4df22..58f50ba253 100644
--- a/block/io.c
+++ b/block/io.c
@@ -377,6 +377,16 @@ void bdrv_drain(BlockDriverState *bs)
bdrv_drained_end(bs);
}
+static void bdrv_drain_assert_idle(BlockDriverState *bs)
+{
+ BdrvChild *child, *next;
+
+ assert(atomic_read(&bs->in_flight) == 0);
+ QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
+ bdrv_drain_assert_idle(child->bs);
+ }
+}
+
/*
* Wait for pending requests to complete across all BlockDriverStates
*
@@ -391,11 +401,8 @@ void bdrv_drain(BlockDriverState *bs)
*/
void bdrv_drain_all_begin(void)
{
- /* Always run first iteration so any pending completion BHs run */
- bool waited = true;
BlockDriverState *bs;
BdrvNextIterator it;
- GSList *aio_ctxs = NULL, *ctx;
/* BDRV_POLL_WHILE() for a node can only be called from its own I/O thread
* or the main loop AioContext. We potentially use BDRV_POLL_WHILE() on
@@ -409,35 +416,11 @@ void bdrv_drain_all_begin(void)
aio_context_acquire(aio_context);
bdrv_do_drained_begin(bs, true, NULL);
aio_context_release(aio_context);
-
- if (!g_slist_find(aio_ctxs, aio_context)) {
- aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
- }
}
- /* Note that completion of an asynchronous I/O operation can trigger any
- * number of other I/O operations on other devices---for example a
- * coroutine can submit an I/O request to another device in response to
- * request completion. Therefore we must keep looping until there was no
- * more activity rather than simply draining each device independently.
- */
- while (waited) {
- waited = false;
-
- for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
- AioContext *aio_context = ctx->data;
-
- aio_context_acquire(aio_context);
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
- if (aio_context == bdrv_get_aio_context(bs)) {
- waited |= bdrv_drain_recurse(bs);
- }
- }
- aio_context_release(aio_context);
- }
+ for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
+ bdrv_drain_assert_idle(bs);
}
-
- g_slist_free(aio_ctxs);
}
void bdrv_drain_all_end(void)
--
2.13.6
- [Qemu-block] [PATCH v2 00/20] Drain fixes and cleanups, part 3, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 01/20] test-bdrv-drain: bdrv_drain() works with cross-AioContext events, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 02/20] block: Use bdrv_do_drain_begin/end in bdrv_drain_all(), Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 03/20] block: Remove 'recursive' parameter from bdrv_drain_invoke(), Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 04/20] block: Don't manually poll in bdrv_drain_all(),
Kevin Wolf <=
- [Qemu-block] [PATCH v2 05/20] tests/test-bdrv-drain: bdrv_drain_all() works in coroutines now, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 06/20] block: Avoid unnecessary aio_poll() in AIO_WAIT_WHILE(), Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 07/20] block: Really pause block jobs on drain, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 08/20] block: Remove bdrv_drain_recurse(), Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 09/20] test-bdrv-drain: Add test for node deletion, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 11/20] test-bdrv-drain: Test node deletion in subtree recursion, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 12/20] block: Don't poll in parent drain callbacks, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 10/20] block: Drain recursively with a single BDRV_POLL_WHILE(), Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 13/20] test-bdrv-drain: Graph change through parent callback, Kevin Wolf, 2018/05/29
- [Qemu-block] [PATCH v2 14/20] block: Defer .bdrv_drain_begin callback to polling phase, Kevin Wolf, 2018/05/29