Blame SOURCES/kvm-block-Poll-after-drain-on-attaching-a-node.patch

357786
From b0c7fc7fbe64b234272db8316f81b92fe675a65a Mon Sep 17 00:00:00 2001
357786
From: Kevin Wolf <kwolf@redhat.com>
357786
Date: Fri, 14 Sep 2018 10:55:19 +0200
357786
Subject: [PATCH 28/49] block: Poll after drain on attaching a node
357786
357786
RH-Author: Kevin Wolf <kwolf@redhat.com>
357786
Message-id: <20180914105540.18077-22-kwolf@redhat.com>
357786
Patchwork-id: 82173
357786
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 21/42] block: Poll after drain on attaching a node
357786
Bugzilla: 1601212
357786
RH-Acked-by: John Snow <jsnow@redhat.com>
357786
RH-Acked-by: Max Reitz <mreitz@redhat.com>
357786
RH-Acked-by: Fam Zheng <famz@redhat.com>
357786
357786
Commit dcf94a23b1 ('block: Don't poll in parent drain callbacks')
357786
removed polling in bdrv_child_cb_drained_begin() on the grounds that the
357786
original bdrv_drain() already will poll and BdrvChildRole.drained_begin
357786
calls must not cause graph changes (and therefore must not call
357786
aio_poll() or the recursion through the graph will break.
357786
357786
This reasoning is correct for calls through bdrv_do_drained_begin().
357786
However, BdrvChildRole.drained_begin is also called when a node that is
357786
already in a drained section (i.e. bdrv_do_drained_begin() has already
357786
returned and therefore can't poll any more) is attached to a new parent.
357786
In this case, we must explicitly poll to have all requests completed
357786
before the drained new child can be attached to the parent.
357786
357786
In bdrv_replace_child_noperm(), we know that we're not inside the
357786
recursion of bdrv_do_drained_begin() because graph changes are not
357786
allowed there, and bdrv_replace_child_noperm() is a graph change. The
357786
call of BdrvChildRole.drained_begin() must therefore be followed by a
357786
BDRV_POLL_WHILE() that waits for the completion of requests.
357786
357786
Reported-by: Max Reitz <mreitz@redhat.com>
357786
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
357786
(cherry picked from commit 4be6a6d118123340f16fb8b3bf45220d0f8ed6d4)
357786
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
357786
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
357786
---
357786
 block.c                   |  2 +-
357786
 block/io.c                | 26 ++++++++++++++++++++------
357786
 include/block/block.h     |  8 ++++++++
357786
 include/block/block_int.h |  3 +++
357786
 4 files changed, 32 insertions(+), 7 deletions(-)
357786
357786
diff --git a/block.c b/block.c
357786
index eea9c6f..e89b5e3 100644
357786
--- a/block.c
357786
+++ b/block.c
357786
@@ -2072,7 +2072,7 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
357786
             }
357786
             assert(num >= 0);
357786
             for (i = 0; i < num; i++) {
357786
-                child->role->drained_begin(child);
357786
+                bdrv_parent_drained_begin_single(child, true);
357786
             }
357786
         }
357786
 
357786
diff --git a/block/io.c b/block/io.c
357786
index 38ae299..d404088 100644
357786
--- a/block/io.c
357786
+++ b/block/io.c
357786
@@ -52,9 +52,7 @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
357786
         if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
357786
             continue;
357786
         }
357786
-        if (c->role->drained_begin) {
357786
-            c->role->drained_begin(c);
357786
-        }
357786
+        bdrv_parent_drained_begin_single(c, false);
357786
     }
357786
 }
357786
 
357786
@@ -73,6 +71,14 @@ void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
357786
     }
357786
 }
357786
 
357786
+static bool bdrv_parent_drained_poll_single(BdrvChild *c)
357786
+{
357786
+    if (c->role->drained_poll) {
357786
+        return c->role->drained_poll(c);
357786
+    }
357786
+    return false;
357786
+}
357786
+
357786
 static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
357786
                                      bool ignore_bds_parents)
357786
 {
357786
@@ -83,14 +89,22 @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
357786
         if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
357786
             continue;
357786
         }
357786
-        if (c->role->drained_poll) {
357786
-            busy |= c->role->drained_poll(c);
357786
-        }
357786
+        busy |= bdrv_parent_drained_poll_single(c);
357786
     }
357786
 
357786
     return busy;
357786
 }
357786
 
357786
+void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
357786
+{
357786
+    if (c->role->drained_begin) {
357786
+        c->role->drained_begin(c);
357786
+    }
357786
+    if (poll) {
357786
+        BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c));
357786
+    }
357786
+}
357786
+
357786
 static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
357786
 {
357786
     dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
357786
diff --git a/include/block/block.h b/include/block/block.h
357786
index f9079ac..356712c 100644
357786
--- a/include/block/block.h
357786
+++ b/include/block/block.h
357786
@@ -590,6 +590,14 @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
357786
                                bool ignore_bds_parents);
357786
 
357786
 /**
357786
+ * bdrv_parent_drained_begin_single:
357786
+ *
357786
+ * Begin a quiesced section for the parent of @c. If @poll is true, wait for
357786
+ * any pending activity to cease.
357786
+ */
357786
+void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll);
357786
+
357786
+/**
357786
  * bdrv_parent_drained_end:
357786
  *
357786
  * End a quiesced section of all users of @bs. This is part of
357786
diff --git a/include/block/block_int.h b/include/block/block_int.h
357786
index 9757d5e..b7806e3 100644
357786
--- a/include/block/block_int.h
357786
+++ b/include/block/block_int.h
357786
@@ -610,6 +610,9 @@ struct BdrvChildRole {
357786
      * requests after returning from .drained_begin() until .drained_end() is
357786
      * called.
357786
      *
357786
+     * These functions must not change the graph (and therefore also must not
357786
+     * call aio_poll(), which could change the graph indirectly).
357786
+     *
357786
      * Note that this can be nested. If drained_begin() was called twice, new
357786
      * I/O is allowed only after drained_end() was called twice, too.
357786
      */
357786
-- 
357786
1.8.3.1
357786