yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-block-Don-t-manually-poll-in-bdrv_drain_all.patch

ae23c9
From 6fe050124f9433521227b5da8f560c7a3c248513 Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Wed, 10 Oct 2018 20:08:38 +0100
ae23c9
Subject: [PATCH 07/49] block: Don't manually poll in bdrv_drain_all()
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20181010200843.6710-5-kwolf@redhat.com>
ae23c9
Patchwork-id: 82584
ae23c9
O-Subject: [RHEL-8 qemu-kvm PATCH 04/44] block: Don't manually poll in bdrv_drain_all()
ae23c9
Bugzilla: 1637976
ae23c9
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ae23c9
RH-Acked-by: John Snow <jsnow@redhat.com>
ae23c9
RH-Acked-by: Thomas Huth <thuth@redhat.com>
ae23c9
ae23c9
All involved nodes are already idle, we called bdrv_do_drain_begin() on
ae23c9
them.
ae23c9
ae23c9
The comment in the code suggested that this was not correct because the
ae23c9
completion of a request on one node could spawn a new request on a
ae23c9
different node (which might have been drained before, so we wouldn't
ae23c9
drain the new request). In reality, new requests to different nodes
ae23c9
aren't spawned out of nothing, but only in the context of a parent
ae23c9
request, and they aren't submitted to random nodes, but only to child
ae23c9
nodes. As long as we still poll for the completion of the parent request
ae23c9
(which we do), draining each root node separately is good enough.
ae23c9
ae23c9
Remove the additional polling code from bdrv_drain_all_begin() and
ae23c9
replace it with an assertion that all nodes are already idle after we
ae23c9
drained them separately.
ae23c9
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
(cherry picked from commit c13ad59f012cbbccb866a10477458e69bc868dbb)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 block/io.c | 41 ++++++++++++-----------------------------
ae23c9
 1 file changed, 12 insertions(+), 29 deletions(-)
ae23c9
ae23c9
diff --git a/block/io.c b/block/io.c
ae23c9
index aa41f1e..e5fc42c 100644
ae23c9
--- a/block/io.c
ae23c9
+++ b/block/io.c
ae23c9
@@ -376,6 +376,16 @@ void bdrv_drain(BlockDriverState *bs)
ae23c9
     bdrv_drained_end(bs);
ae23c9
 }
ae23c9
 
ae23c9
+static void bdrv_drain_assert_idle(BlockDriverState *bs)
ae23c9
+{
ae23c9
+    BdrvChild *child, *next;
ae23c9
+
ae23c9
+    assert(atomic_read(&bs->in_flight) == 0);
ae23c9
+    QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
ae23c9
+        bdrv_drain_assert_idle(child->bs);
ae23c9
+    }
ae23c9
+}
ae23c9
+
ae23c9
 /*
ae23c9
  * Wait for pending requests to complete across all BlockDriverStates
ae23c9
  *
ae23c9
@@ -390,11 +400,8 @@ void bdrv_drain(BlockDriverState *bs)
ae23c9
  */
ae23c9
 void bdrv_drain_all_begin(void)
ae23c9
 {
ae23c9
-    /* Always run first iteration so any pending completion BHs run */
ae23c9
-    bool waited = true;
ae23c9
     BlockDriverState *bs;
ae23c9
     BdrvNextIterator it;
ae23c9
-    GSList *aio_ctxs = NULL, *ctx;
ae23c9
 
ae23c9
     /* BDRV_POLL_WHILE() for a node can only be called from its own I/O thread
ae23c9
      * or the main loop AioContext. We potentially use BDRV_POLL_WHILE() on
ae23c9
@@ -408,35 +415,11 @@ void bdrv_drain_all_begin(void)
ae23c9
         aio_context_acquire(aio_context);
ae23c9
         bdrv_do_drained_begin(bs, true, NULL);
ae23c9
         aio_context_release(aio_context);
ae23c9
-
ae23c9
-        if (!g_slist_find(aio_ctxs, aio_context)) {
ae23c9
-            aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
ae23c9
-        }
ae23c9
     }
ae23c9
 
ae23c9
-    /* Note that completion of an asynchronous I/O operation can trigger any
ae23c9
-     * number of other I/O operations on other devices---for example a
ae23c9
-     * coroutine can submit an I/O request to another device in response to
ae23c9
-     * request completion.  Therefore we must keep looping until there was no
ae23c9
-     * more activity rather than simply draining each device independently.
ae23c9
-     */
ae23c9
-    while (waited) {
ae23c9
-        waited = false;
ae23c9
-
ae23c9
-        for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
ae23c9
-            AioContext *aio_context = ctx->data;
ae23c9
-
ae23c9
-            aio_context_acquire(aio_context);
ae23c9
-            for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
ae23c9
-                if (aio_context == bdrv_get_aio_context(bs)) {
ae23c9
-                    waited |= bdrv_drain_recurse(bs);
ae23c9
-                }
ae23c9
-            }
ae23c9
-            aio_context_release(aio_context);
ae23c9
-        }
ae23c9
+    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
ae23c9
+        bdrv_drain_assert_idle(bs);
ae23c9
     }
ae23c9
-
ae23c9
-    g_slist_free(aio_ctxs);
ae23c9
 }
ae23c9
 
ae23c9
 void bdrv_drain_all_end(void)
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9