yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
ae23c9
From 6acc1d617c7db4c575dc56c6035ea00315dffa20 Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Wed, 10 Oct 2018 20:22:12 +0100
ae23c9
Subject: [PATCH 46/49] block: Use a single global AioWait
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20181010202213.7372-34-kwolf@redhat.com>
ae23c9
Patchwork-id: 82623
ae23c9
O-Subject: [RHEL-8 qemu-kvm PATCH 43/44] block: Use a single global AioWait
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
When draining a block node, we recurse to its parent and for subtree
ae23c9
drains also to its children. A single AIO_WAIT_WHILE() is then used to
ae23c9
wait for bdrv_drain_poll() to become true, which depends on all of the
ae23c9
nodes we recursed to. However, if the respective child or parent becomes
ae23c9
quiescent and calls bdrv_wakeup(), only the AioWait of the child/parent
ae23c9
is checked, while AIO_WAIT_WHILE() depends on the AioWait of the
ae23c9
original node.
ae23c9
ae23c9
Fix this by using a single AioWait for all callers of AIO_WAIT_WHILE().
ae23c9
ae23c9
This may mean that the draining thread gets a few more unnecessary
ae23c9
wakeups because an unrelated operation got completed, but we already
ae23c9
wake it up when something _could_ have changed rather than only if it
ae23c9
has certainly changed.
ae23c9
ae23c9
Apart from that, drain is a slow path anyway. In theory it would be
ae23c9
possible to use wakeups more selectively and still correctly, but the
ae23c9
gains are likely not worth the additional complexity. In fact, this
ae23c9
patch is a nice simplification for some places in the code.
ae23c9
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Reviewed-by: Eric Blake <eblake@redhat.com>
ae23c9
Reviewed-by: Max Reitz <mreitz@redhat.com>
ae23c9
(cherry picked from commit cfe29d8294e06420e15d4938421ae006c8ac49e7)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 block.c                   |  5 -----
ae23c9
 block/block-backend.c     | 11 ++++-------
ae23c9
 block/io.c                |  7 ++-----
ae23c9
 blockjob.c                | 13 +------------
ae23c9
 include/block/aio-wait.h  | 22 +++++++++++-----------
ae23c9
 include/block/block.h     |  6 +-----
ae23c9
 include/block/block_int.h |  3 ---
ae23c9
 include/block/blockjob.h  | 10 ----------
ae23c9
 job.c                     |  3 +--
ae23c9
 util/aio-wait.c           | 11 ++++++-----
ae23c9
 10 files changed, 26 insertions(+), 65 deletions(-)
ae23c9
ae23c9
diff --git a/block.c b/block.c
ae23c9
index e89b5e3..fbd569c 100644
ae23c9
--- a/block.c
ae23c9
+++ b/block.c
ae23c9
@@ -4847,11 +4847,6 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
ae23c9
     return bs ? bs->aio_context : qemu_get_aio_context();
ae23c9
 }
ae23c9
 
ae23c9
-AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
ae23c9
-{
ae23c9
-    return bs ? &bs->wait : NULL;
ae23c9
-}
ae23c9
-
ae23c9
 void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
ae23c9
 {
ae23c9
     aio_co_enter(bdrv_get_aio_context(bs), co);
ae23c9
diff --git a/block/block-backend.c b/block/block-backend.c
ae23c9
index b8ea286..91abfe6 100644
ae23c9
--- a/block/block-backend.c
ae23c9
+++ b/block/block-backend.c
ae23c9
@@ -88,7 +88,6 @@ struct BlockBackend {
ae23c9
      * Accessed with atomic ops.
ae23c9
      */
ae23c9
     unsigned int in_flight;
ae23c9
-    AioWait wait;
ae23c9
 };
ae23c9
 
ae23c9
 typedef struct BlockBackendAIOCB {
ae23c9
@@ -1300,7 +1299,7 @@ static void blk_inc_in_flight(BlockBackend *blk)
ae23c9
 static void blk_dec_in_flight(BlockBackend *blk)
ae23c9
 {
ae23c9
     atomic_dec(&blk->in_flight);
ae23c9
-    aio_wait_kick(&blk->wait);
ae23c9
+    aio_wait_kick();
ae23c9
 }
ae23c9
 
ae23c9
 static void error_callback_bh(void *opaque)
ae23c9
@@ -1601,9 +1600,8 @@ void blk_drain(BlockBackend *blk)
ae23c9
     }
ae23c9
 
ae23c9
     /* We may have -ENOMEDIUM completions in flight */
ae23c9
-    AIO_WAIT_WHILE(&blk->wait,
ae23c9
-            blk_get_aio_context(blk),
ae23c9
-            atomic_mb_read(&blk->in_flight) > 0);
ae23c9
+    AIO_WAIT_WHILE(blk_get_aio_context(blk),
ae23c9
+                   atomic_mb_read(&blk->in_flight) > 0);
ae23c9
 
ae23c9
     if (bs) {
ae23c9
         bdrv_drained_end(bs);
ae23c9
@@ -1622,8 +1620,7 @@ void blk_drain_all(void)
ae23c9
         aio_context_acquire(ctx);
ae23c9
 
ae23c9
         /* We may have -ENOMEDIUM completions in flight */
ae23c9
-        AIO_WAIT_WHILE(&blk->wait, ctx,
ae23c9
-                atomic_mb_read(&blk->in_flight) > 0);
ae23c9
+        AIO_WAIT_WHILE(ctx, atomic_mb_read(&blk->in_flight) > 0);
ae23c9
 
ae23c9
         aio_context_release(ctx);
ae23c9
     }
ae23c9
diff --git a/block/io.c b/block/io.c
ae23c9
index 3313958..7a99f7b 100644
ae23c9
--- a/block/io.c
ae23c9
+++ b/block/io.c
ae23c9
@@ -38,8 +38,6 @@
ae23c9
 /* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */
ae23c9
 #define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
ae23c9
 
ae23c9
-static AioWait drain_all_aio_wait;
ae23c9
-
ae23c9
 static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
ae23c9
     int64_t offset, int bytes, BdrvRequestFlags flags);
ae23c9
 
ae23c9
@@ -555,7 +553,7 @@ void bdrv_drain_all_begin(void)
ae23c9
     }
ae23c9
 
ae23c9
     /* Now poll the in-flight requests */
ae23c9
-    AIO_WAIT_WHILE(&drain_all_aio_wait, NULL, bdrv_drain_all_poll());
ae23c9
+    AIO_WAIT_WHILE(NULL, bdrv_drain_all_poll());
ae23c9
 
ae23c9
     while ((bs = bdrv_next_all_states(bs))) {
ae23c9
         bdrv_drain_assert_idle(bs);
ae23c9
@@ -709,8 +707,7 @@ void bdrv_inc_in_flight(BlockDriverState *bs)
ae23c9
 
ae23c9
 void bdrv_wakeup(BlockDriverState *bs)
ae23c9
 {
ae23c9
-    aio_wait_kick(bdrv_get_aio_wait(bs));
ae23c9
-    aio_wait_kick(&drain_all_aio_wait);
ae23c9
+    aio_wait_kick();
ae23c9
 }
ae23c9
 
ae23c9
 void bdrv_dec_in_flight(BlockDriverState *bs)
ae23c9
diff --git a/blockjob.c b/blockjob.c
ae23c9
index 617d86f..06f2429 100644
ae23c9
--- a/blockjob.c
ae23c9
+++ b/blockjob.c
ae23c9
@@ -221,20 +221,9 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
ae23c9
     return 0;
ae23c9
 }
ae23c9
 
ae23c9
-void block_job_wakeup_all_bdrv(BlockJob *job)
ae23c9
-{
ae23c9
-    GSList *l;
ae23c9
-
ae23c9
-    for (l = job->nodes; l; l = l->next) {
ae23c9
-        BdrvChild *c = l->data;
ae23c9
-        bdrv_wakeup(c->bs);
ae23c9
-    }
ae23c9
-}
ae23c9
-
ae23c9
 static void block_job_on_idle(Notifier *n, void *opaque)
ae23c9
 {
ae23c9
-    BlockJob *job = opaque;
ae23c9
-    block_job_wakeup_all_bdrv(job);
ae23c9
+    aio_wait_kick();
ae23c9
 }
ae23c9
 
ae23c9
 bool block_job_is_internal(BlockJob *job)
ae23c9
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
ae23c9
index 600fad1..afd0ff7 100644
ae23c9
--- a/include/block/aio-wait.h
ae23c9
+++ b/include/block/aio-wait.h
ae23c9
@@ -30,14 +30,15 @@
ae23c9
 /**
ae23c9
  * AioWait:
ae23c9
  *
ae23c9
- * An object that facilitates synchronous waiting on a condition.  The main
ae23c9
- * loop can wait on an operation running in an IOThread as follows:
ae23c9
+ * An object that facilitates synchronous waiting on a condition. A single
ae23c9
+ * global AioWait object (global_aio_wait) is used internally.
ae23c9
+ *
ae23c9
+ * The main loop can wait on an operation running in an IOThread as follows:
ae23c9
  *
ae23c9
- *   AioWait *wait = ...;
ae23c9
  *   AioContext *ctx = ...;
ae23c9
  *   MyWork work = { .done = false };
ae23c9
  *   schedule_my_work_in_iothread(ctx, &work);
ae23c9
- *   AIO_WAIT_WHILE(wait, ctx, !work.done);
ae23c9
+ *   AIO_WAIT_WHILE(ctx, !work.done);
ae23c9
  *
ae23c9
  * The IOThread must call aio_wait_kick() to notify the main loop when
ae23c9
  * work.done changes:
ae23c9
@@ -46,7 +47,7 @@
ae23c9
  *   {
ae23c9
  *       ...
ae23c9
  *       work.done = true;
ae23c9
- *       aio_wait_kick(wait);
ae23c9
+ *       aio_wait_kick();
ae23c9
  *   }
ae23c9
  */
ae23c9
 typedef struct {
ae23c9
@@ -54,9 +55,10 @@ typedef struct {
ae23c9
     unsigned num_waiters;
ae23c9
 } AioWait;
ae23c9
 
ae23c9
+extern AioWait global_aio_wait;
ae23c9
+
ae23c9
 /**
ae23c9
  * AIO_WAIT_WHILE:
ae23c9
- * @wait: the aio wait object
ae23c9
  * @ctx: the aio context, or NULL if multiple aio contexts (for which the
ae23c9
  *       caller does not hold a lock) are involved in the polling condition.
ae23c9
  * @cond: wait while this conditional expression is true
ae23c9
@@ -72,9 +74,9 @@ typedef struct {
ae23c9
  * wait on conditions between two IOThreads since that could lead to deadlock,
ae23c9
  * go via the main loop instead.
ae23c9
  */
ae23c9
-#define AIO_WAIT_WHILE(wait, ctx, cond) ({                         \
ae23c9
+#define AIO_WAIT_WHILE(ctx, cond) ({                               \
ae23c9
     bool waited_ = false;                                          \
ae23c9
-    AioWait *wait_ = (wait);                                       \
ae23c9
+    AioWait *wait_ = &global_aio_wait;                             \
ae23c9
     AioContext *ctx_ = (ctx);                                      \
ae23c9
     /* Increment wait_->num_waiters before evaluating cond. */     \
ae23c9
     atomic_inc(&wait_->num_waiters);                               \
ae23c9
@@ -102,14 +104,12 @@ typedef struct {
ae23c9
 
ae23c9
 /**
ae23c9
  * aio_wait_kick:
ae23c9
- * @wait: the aio wait object that should re-evaluate its condition
ae23c9
- *
ae23c9
  * Wake up the main thread if it is waiting on AIO_WAIT_WHILE().  During
ae23c9
  * synchronous operations performed in an IOThread, the main thread lets the
ae23c9
  * IOThread's event loop run, waiting for the operation to complete.  A
ae23c9
  * aio_wait_kick() call will wake up the main thread.
ae23c9
  */
ae23c9
-void aio_wait_kick(AioWait *wait);
ae23c9
+void aio_wait_kick(void);
ae23c9
 
ae23c9
 /**
ae23c9
  * aio_wait_bh_oneshot:
ae23c9
diff --git a/include/block/block.h b/include/block/block.h
ae23c9
index 356712c..8e78daf 100644
ae23c9
--- a/include/block/block.h
ae23c9
+++ b/include/block/block.h
ae23c9
@@ -406,13 +406,9 @@ void bdrv_drain_all_begin(void);
ae23c9
 void bdrv_drain_all_end(void);
ae23c9
 void bdrv_drain_all(void);
ae23c9
 
ae23c9
-/* Returns NULL when bs == NULL */
ae23c9
-AioWait *bdrv_get_aio_wait(BlockDriverState *bs);
ae23c9
-
ae23c9
 #define BDRV_POLL_WHILE(bs, cond) ({                       \
ae23c9
     BlockDriverState *bs_ = (bs);                          \
ae23c9
-    AIO_WAIT_WHILE(bdrv_get_aio_wait(bs_),                 \
ae23c9
-                   bdrv_get_aio_context(bs_),              \
ae23c9
+    AIO_WAIT_WHILE(bdrv_get_aio_context(bs_),              \
ae23c9
                    cond); })
ae23c9
 
ae23c9
 int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
ae23c9
diff --git a/include/block/block_int.h b/include/block/block_int.h
ae23c9
index b7806e3..ff923b7 100644
ae23c9
--- a/include/block/block_int.h
ae23c9
+++ b/include/block/block_int.h
ae23c9
@@ -782,9 +782,6 @@ struct BlockDriverState {
ae23c9
     unsigned int in_flight;
ae23c9
     unsigned int serialising_in_flight;
ae23c9
 
ae23c9
-    /* Kicked to signal main loop when a request completes. */
ae23c9
-    AioWait wait;
ae23c9
-
ae23c9
     /* counter for nested bdrv_io_plug.
ae23c9
      * Accessed with atomic ops.
ae23c9
     */
ae23c9
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
ae23c9
index 2290bbb..ede0bd8 100644
ae23c9
--- a/include/block/blockjob.h
ae23c9
+++ b/include/block/blockjob.h
ae23c9
@@ -122,16 +122,6 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
ae23c9
 void block_job_remove_all_bdrv(BlockJob *job);
ae23c9
 
ae23c9
 /**
ae23c9
- * block_job_wakeup_all_bdrv:
ae23c9
- * @job: The block job
ae23c9
- *
ae23c9
- * Calls bdrv_wakeup() for all BlockDriverStates that have been added to the
ae23c9
- * job. This function is to be called whenever child_job_drained_poll() would
ae23c9
- * go from true to false to notify waiting drain requests.
ae23c9
- */
ae23c9
-void block_job_wakeup_all_bdrv(BlockJob *job);
ae23c9
-
ae23c9
-/**
ae23c9
  * block_job_set_speed:
ae23c9
  * @job: The job to set the speed for.
ae23c9
  * @speed: The new value
ae23c9
diff --git a/job.c b/job.c
ae23c9
index 5b53e43..3a7db59 100644
ae23c9
--- a/job.c
ae23c9
+++ b/job.c
ae23c9
@@ -973,7 +973,6 @@ void job_complete(Job *job, Error **errp)
ae23c9
 int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
ae23c9
 {
ae23c9
     Error *local_err = NULL;
ae23c9
-    AioWait dummy_wait = {};
ae23c9
     int ret;
ae23c9
 
ae23c9
     job_ref(job);
ae23c9
@@ -987,7 +986,7 @@ int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
ae23c9
         return -EBUSY;
ae23c9
     }
ae23c9
 
ae23c9
-    AIO_WAIT_WHILE(&dummy_wait, job->aio_context,
ae23c9
+    AIO_WAIT_WHILE(job->aio_context,
ae23c9
                    (job_drain(job), !job_is_completed(job)));
ae23c9
 
ae23c9
     ret = (job_is_cancelled(job) && job->ret == 0) ? -ECANCELED : job->ret;
ae23c9
diff --git a/util/aio-wait.c b/util/aio-wait.c
ae23c9
index b8a8f86..b487749 100644
ae23c9
--- a/util/aio-wait.c
ae23c9
+++ b/util/aio-wait.c
ae23c9
@@ -26,21 +26,22 @@
ae23c9
 #include "qemu/main-loop.h"
ae23c9
 #include "block/aio-wait.h"
ae23c9
 
ae23c9
+AioWait global_aio_wait;
ae23c9
+
ae23c9
 static void dummy_bh_cb(void *opaque)
ae23c9
 {
ae23c9
     /* The point is to make AIO_WAIT_WHILE()'s aio_poll() return */
ae23c9
 }
ae23c9
 
ae23c9
-void aio_wait_kick(AioWait *wait)
ae23c9
+void aio_wait_kick(void)
ae23c9
 {
ae23c9
     /* The barrier (or an atomic op) is in the caller.  */
ae23c9
-    if (atomic_read(&wait->num_waiters)) {
ae23c9
+    if (atomic_read(&global_aio_wait.num_waiters)) {
ae23c9
         aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
ae23c9
     }
ae23c9
 }
ae23c9
 
ae23c9
 typedef struct {
ae23c9
-    AioWait wait;
ae23c9
     bool done;
ae23c9
     QEMUBHFunc *cb;
ae23c9
     void *opaque;
ae23c9
@@ -54,7 +55,7 @@ static void aio_wait_bh(void *opaque)
ae23c9
     data->cb(data->opaque);
ae23c9
 
ae23c9
     data->done = true;
ae23c9
-    aio_wait_kick(&data->wait);
ae23c9
+    aio_wait_kick();
ae23c9
 }
ae23c9
 
ae23c9
 void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
ae23c9
@@ -67,5 +68,5 @@ void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
ae23c9
     assert(qemu_get_current_aio_context() == qemu_get_aio_context());
ae23c9
 
ae23c9
     aio_bh_schedule_oneshot(ctx, aio_wait_bh, &data);
ae23c9
-    AIO_WAIT_WHILE(&data.wait, ctx, !data.done);
ae23c9
+    AIO_WAIT_WHILE(ctx, !data.done);
ae23c9
 }
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9