ed5979
From 0e894c93cae97bb792dc483be8e295d097ebd7a1 Mon Sep 17 00:00:00 2001
ed5979
From: Kevin Wolf <kwolf@redhat.com>
ed5979
Date: Fri, 18 Nov 2022 18:40:58 +0100
ed5979
Subject: [PATCH 16/31] block: Revert .bdrv_drained_begin/end to
ed5979
 non-coroutine_fn
ed5979
ed5979
RH-Author: Stefano Garzarella <sgarzare@redhat.com>
ed5979
RH-MergeRequest: 135: block: Simplify drain to prevent QEMU from crashing during snapshot
ed5979
RH-Bugzilla: 2155112
ed5979
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
ed5979
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
ed5979
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
ed5979
RH-Commit: [4/16] 86d6049e40a99604e414c2572b67f74b85868832 (sgarzarella/qemu-kvm-c-9-s)
ed5979
ed5979
Polling during bdrv_drained_end() can be problematic (and in the future,
ed5979
we may get cases for bdrv_drained_begin() where polling is forbidden,
ed5979
and we don't care about already in-flight requests, but just want to
ed5979
prevent new requests from arriving).
ed5979
ed5979
The .bdrv_drained_begin/end callbacks running in a coroutine is the only
ed5979
reason why we have to do this polling, so make them non-coroutine
ed5979
callbacks again. None of the callers actually yield any more.
ed5979
ed5979
This means that bdrv_drained_end() effectively doesn't poll any more,
ed5979
even if AIO_WAIT_WHILE() loops are still there (their condition is false
ed5979
from the beginning). This is generally not a problem, but in
ed5979
test-bdrv-drain, some additional explicit aio_poll() calls need to be
ed5979
added because the test case wants to verify the final state after BHs
ed5979
have executed.
ed5979
ed5979
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ed5979
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
ed5979
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
ed5979
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
ed5979
Message-Id: <20221118174110.55183-4-kwolf@redhat.com>
ed5979
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ed5979
(cherry picked from commit 5e8ac21717373cbe96ef7a91e216bf5788815d63)
ed5979
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
ed5979
---
ed5979
 block.c                          |  4 +--
ed5979
 block/io.c                       | 49 +++++---------------------------
ed5979
 block/qed.c                      |  6 ++--
ed5979
 block/throttle.c                 |  8 +++---
ed5979
 include/block/block_int-common.h | 10 ++++---
ed5979
 tests/unit/test-bdrv-drain.c     | 18 ++++++------
ed5979
 6 files changed, 32 insertions(+), 63 deletions(-)
ed5979
ed5979
diff --git a/block.c b/block.c
ed5979
index ec184150a2..16a62a329c 100644
ed5979
--- a/block.c
ed5979
+++ b/block.c
ed5979
@@ -1713,8 +1713,8 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
ed5979
     assert(is_power_of_2(bs->bl.request_alignment));
ed5979
 
ed5979
     for (i = 0; i < bs->quiesce_counter; i++) {
ed5979
-        if (drv->bdrv_co_drain_begin) {
ed5979
-            drv->bdrv_co_drain_begin(bs);
ed5979
+        if (drv->bdrv_drain_begin) {
ed5979
+            drv->bdrv_drain_begin(bs);
ed5979
         }
ed5979
     }
ed5979
 
ed5979
diff --git a/block/io.c b/block/io.c
ed5979
index b9424024f9..c2ed4b2af9 100644
ed5979
--- a/block/io.c
ed5979
+++ b/block/io.c
ed5979
@@ -252,55 +252,20 @@ typedef struct {
ed5979
     int *drained_end_counter;
ed5979
 } BdrvCoDrainData;
ed5979
 
ed5979
-static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
ed5979
-{
ed5979
-    BdrvCoDrainData *data = opaque;
ed5979
-    BlockDriverState *bs = data->bs;
ed5979
-
ed5979
-    if (data->begin) {
ed5979
-        bs->drv->bdrv_co_drain_begin(bs);
ed5979
-    } else {
ed5979
-        bs->drv->bdrv_co_drain_end(bs);
ed5979
-    }
ed5979
-
ed5979
-    /* Set data->done and decrement drained_end_counter before bdrv_wakeup() */
ed5979
-    qatomic_mb_set(&data->done, true);
ed5979
-    if (!data->begin) {
ed5979
-        qatomic_dec(data->drained_end_counter);
ed5979
-    }
ed5979
-    bdrv_dec_in_flight(bs);
ed5979
-
ed5979
-    g_free(data);
ed5979
-}
ed5979
-
ed5979
-/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
ed5979
+/* Recursively call BlockDriver.bdrv_drain_begin/end callbacks */
ed5979
 static void bdrv_drain_invoke(BlockDriverState *bs, bool begin,
ed5979
                               int *drained_end_counter)
ed5979
 {
ed5979
-    BdrvCoDrainData *data;
ed5979
-
ed5979
-    if (!bs->drv || (begin && !bs->drv->bdrv_co_drain_begin) ||
ed5979
-            (!begin && !bs->drv->bdrv_co_drain_end)) {
ed5979
+    if (!bs->drv || (begin && !bs->drv->bdrv_drain_begin) ||
ed5979
+            (!begin && !bs->drv->bdrv_drain_end)) {
ed5979
         return;
ed5979
     }
ed5979
 
ed5979
-    data = g_new(BdrvCoDrainData, 1);
ed5979
-    *data = (BdrvCoDrainData) {
ed5979
-        .bs = bs,
ed5979
-        .done = false,
ed5979
-        .begin = begin,
ed5979
-        .drained_end_counter = drained_end_counter,
ed5979
-    };
ed5979
-
ed5979
-    if (!begin) {
ed5979
-        qatomic_inc(drained_end_counter);
ed5979
+    if (begin) {
ed5979
+        bs->drv->bdrv_drain_begin(bs);
ed5979
+    } else {
ed5979
+        bs->drv->bdrv_drain_end(bs);
ed5979
     }
ed5979
-
ed5979
-    /* Make sure the driver callback completes during the polling phase for
ed5979
-     * drain_begin. */
ed5979
-    bdrv_inc_in_flight(bs);
ed5979
-    data->co = qemu_coroutine_create(bdrv_drain_invoke_entry, data);
ed5979
-    aio_co_schedule(bdrv_get_aio_context(bs), data->co);
ed5979
 }
ed5979
 
ed5979
 /* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */
ed5979
diff --git a/block/qed.c b/block/qed.c
ed5979
index 013f826c44..c2691a85b1 100644
ed5979
--- a/block/qed.c
ed5979
+++ b/block/qed.c
ed5979
@@ -262,7 +262,7 @@ static bool coroutine_fn qed_plug_allocating_write_reqs(BDRVQEDState *s)
ed5979
     assert(!s->allocating_write_reqs_plugged);
ed5979
     if (s->allocating_acb != NULL) {
ed5979
         /* Another allocating write came concurrently.  This cannot happen
ed5979
-         * from bdrv_qed_co_drain_begin, but it can happen when the timer runs.
ed5979
+         * from bdrv_qed_drain_begin, but it can happen when the timer runs.
ed5979
          */
ed5979
         qemu_co_mutex_unlock(&s->table_lock);
ed5979
         return false;
ed5979
@@ -365,7 +365,7 @@ static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
ed5979
     }
ed5979
 }
ed5979
 
ed5979
-static void coroutine_fn bdrv_qed_co_drain_begin(BlockDriverState *bs)
ed5979
+static void bdrv_qed_drain_begin(BlockDriverState *bs)
ed5979
 {
ed5979
     BDRVQEDState *s = bs->opaque;
ed5979
 
ed5979
@@ -1661,7 +1661,7 @@ static BlockDriver bdrv_qed = {
ed5979
     .bdrv_co_check            = bdrv_qed_co_check,
ed5979
     .bdrv_detach_aio_context  = bdrv_qed_detach_aio_context,
ed5979
     .bdrv_attach_aio_context  = bdrv_qed_attach_aio_context,
ed5979
-    .bdrv_co_drain_begin      = bdrv_qed_co_drain_begin,
ed5979
+    .bdrv_drain_begin         = bdrv_qed_drain_begin,
ed5979
 };
ed5979
 
ed5979
 static void bdrv_qed_init(void)
ed5979
diff --git a/block/throttle.c b/block/throttle.c
ed5979
index 131eba3ab4..88851c84f4 100644
ed5979
--- a/block/throttle.c
ed5979
+++ b/block/throttle.c
ed5979
@@ -214,7 +214,7 @@ static void throttle_reopen_abort(BDRVReopenState *reopen_state)
ed5979
     reopen_state->opaque = NULL;
ed5979
 }
ed5979
 
ed5979
-static void coroutine_fn throttle_co_drain_begin(BlockDriverState *bs)
ed5979
+static void throttle_drain_begin(BlockDriverState *bs)
ed5979
 {
ed5979
     ThrottleGroupMember *tgm = bs->opaque;
ed5979
     if (qatomic_fetch_inc(&tgm->io_limits_disabled) == 0) {
ed5979
@@ -222,7 +222,7 @@ static void coroutine_fn throttle_co_drain_begin(BlockDriverState *bs)
ed5979
     }
ed5979
 }
ed5979
 
ed5979
-static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs)
ed5979
+static void throttle_drain_end(BlockDriverState *bs)
ed5979
 {
ed5979
     ThrottleGroupMember *tgm = bs->opaque;
ed5979
     assert(tgm->io_limits_disabled);
ed5979
@@ -261,8 +261,8 @@ static BlockDriver bdrv_throttle = {
ed5979
     .bdrv_reopen_commit                 =   throttle_reopen_commit,
ed5979
     .bdrv_reopen_abort                  =   throttle_reopen_abort,
ed5979
 
ed5979
-    .bdrv_co_drain_begin                =   throttle_co_drain_begin,
ed5979
-    .bdrv_co_drain_end                  =   throttle_co_drain_end,
ed5979
+    .bdrv_drain_begin                   =   throttle_drain_begin,
ed5979
+    .bdrv_drain_end                     =   throttle_drain_end,
ed5979
 
ed5979
     .is_filter                          =   true,
ed5979
     .strong_runtime_opts                =   throttle_strong_runtime_opts,
ed5979
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
ed5979
index 31ae91e56e..40d646d1ed 100644
ed5979
--- a/include/block/block_int-common.h
ed5979
+++ b/include/block/block_int-common.h
ed5979
@@ -735,17 +735,19 @@ struct BlockDriver {
ed5979
     void (*bdrv_io_unplug)(BlockDriverState *bs);
ed5979
 
ed5979
     /**
ed5979
-     * bdrv_co_drain_begin is called if implemented in the beginning of a
ed5979
+     * bdrv_drain_begin is called if implemented in the beginning of a
ed5979
      * drain operation to drain and stop any internal sources of requests in
ed5979
      * the driver.
ed5979
-     * bdrv_co_drain_end is called if implemented at the end of the drain.
ed5979
+     * bdrv_drain_end is called if implemented at the end of the drain.
ed5979
      *
ed5979
      * They should be used by the driver to e.g. manage scheduled I/O
ed5979
      * requests, or toggle an internal state. After the end of the drain new
ed5979
      * requests will continue normally.
ed5979
+     *
ed5979
+     * Implementations of both functions must not call aio_poll().
ed5979
      */
ed5979
-    void coroutine_fn (*bdrv_co_drain_begin)(BlockDriverState *bs);
ed5979
-    void coroutine_fn (*bdrv_co_drain_end)(BlockDriverState *bs);
ed5979
+    void (*bdrv_drain_begin)(BlockDriverState *bs);
ed5979
+    void (*bdrv_drain_end)(BlockDriverState *bs);
ed5979
 
ed5979
     bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
ed5979
     bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
ed5979
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
ed5979
index 24f34e24ad..695519ee02 100644
ed5979
--- a/tests/unit/test-bdrv-drain.c
ed5979
+++ b/tests/unit/test-bdrv-drain.c
ed5979
@@ -46,7 +46,7 @@ static void coroutine_fn sleep_in_drain_begin(void *opaque)
ed5979
     bdrv_dec_in_flight(bs);
ed5979
 }
ed5979
 
ed5979
-static void coroutine_fn bdrv_test_co_drain_begin(BlockDriverState *bs)
ed5979
+static void bdrv_test_drain_begin(BlockDriverState *bs)
ed5979
 {
ed5979
     BDRVTestState *s = bs->opaque;
ed5979
     s->drain_count++;
ed5979
@@ -57,7 +57,7 @@ static void coroutine_fn bdrv_test_co_drain_begin(BlockDriverState *bs)
ed5979
     }
ed5979
 }
ed5979
 
ed5979
-static void coroutine_fn bdrv_test_co_drain_end(BlockDriverState *bs)
ed5979
+static void bdrv_test_drain_end(BlockDriverState *bs)
ed5979
 {
ed5979
     BDRVTestState *s = bs->opaque;
ed5979
     s->drain_count--;
ed5979
@@ -111,8 +111,8 @@ static BlockDriver bdrv_test = {
ed5979
     .bdrv_close             = bdrv_test_close,
ed5979
     .bdrv_co_preadv         = bdrv_test_co_preadv,
ed5979
 
ed5979
-    .bdrv_co_drain_begin    = bdrv_test_co_drain_begin,
ed5979
-    .bdrv_co_drain_end      = bdrv_test_co_drain_end,
ed5979
+    .bdrv_drain_begin       = bdrv_test_drain_begin,
ed5979
+    .bdrv_drain_end         = bdrv_test_drain_end,
ed5979
 
ed5979
     .bdrv_child_perm        = bdrv_default_perms,
ed5979
 
ed5979
@@ -1703,6 +1703,7 @@ static void test_blockjob_commit_by_drained_end(void)
ed5979
     bdrv_drained_begin(bs_child);
ed5979
     g_assert(!job_has_completed);
ed5979
     bdrv_drained_end(bs_child);
ed5979
+    aio_poll(qemu_get_aio_context(), false);
ed5979
     g_assert(job_has_completed);
ed5979
 
ed5979
     bdrv_unref(bs_parents[0]);
ed5979
@@ -1858,6 +1859,7 @@ static void test_drop_intermediate_poll(void)
ed5979
 
ed5979
     g_assert(!job_has_completed);
ed5979
     ret = bdrv_drop_intermediate(chain[1], chain[0], NULL);
ed5979
+    aio_poll(qemu_get_aio_context(), false);
ed5979
     g_assert(ret == 0);
ed5979
     g_assert(job_has_completed);
ed5979
 
ed5979
@@ -1946,7 +1948,7 @@ static void coroutine_fn bdrv_replace_test_drain_co(void *opaque)
ed5979
  * .was_drained.
ed5979
  * Increment .drain_count.
ed5979
  */
ed5979
-static void coroutine_fn bdrv_replace_test_co_drain_begin(BlockDriverState *bs)
ed5979
+static void bdrv_replace_test_drain_begin(BlockDriverState *bs)
ed5979
 {
ed5979
     BDRVReplaceTestState *s = bs->opaque;
ed5979
 
ed5979
@@ -1977,7 +1979,7 @@ static void coroutine_fn bdrv_replace_test_read_entry(void *opaque)
ed5979
  * If .drain_count reaches 0 and the node has a backing file, issue a
ed5979
  * read request.
ed5979
  */
ed5979
-static void coroutine_fn bdrv_replace_test_co_drain_end(BlockDriverState *bs)
ed5979
+static void bdrv_replace_test_drain_end(BlockDriverState *bs)
ed5979
 {
ed5979
     BDRVReplaceTestState *s = bs->opaque;
ed5979
 
ed5979
@@ -2002,8 +2004,8 @@ static BlockDriver bdrv_replace_test = {
ed5979
     .bdrv_close             = bdrv_replace_test_close,
ed5979
     .bdrv_co_preadv         = bdrv_replace_test_co_preadv,
ed5979
 
ed5979
-    .bdrv_co_drain_begin    = bdrv_replace_test_co_drain_begin,
ed5979
-    .bdrv_co_drain_end      = bdrv_replace_test_co_drain_end,
ed5979
+    .bdrv_drain_begin       = bdrv_replace_test_drain_begin,
ed5979
+    .bdrv_drain_end         = bdrv_replace_test_drain_end,
ed5979
 
ed5979
     .bdrv_child_perm        = bdrv_default_perms,
ed5979
 };
ed5979
-- 
ed5979
2.31.1
ed5979