All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 50/61] qed: Use CoQueue for serialising allocations
Date: Fri, 23 Jun 2017 18:21:48 +0200	[thread overview]
Message-ID: <1498234919-27316-51-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1498234919-27316-1-git-send-email-kwolf@redhat.com>

Now that we're running in coroutine context, the ad-hoc serialisation
code (which drops a request that has to wait out of coroutine context)
can be replaced by a CoQueue.

This means that when we resume a serialised request, it is running in
coroutine context again and its I/O isn't blocking any more.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/qed.c | 49 +++++++++++++++++--------------------------------
 block/qed.h |  3 ++-
 2 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/block/qed.c b/block/qed.c
index a5111fd..cd3ef55 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -269,16 +269,10 @@ static void qed_plug_allocating_write_reqs(BDRVQEDState *s)
 
 static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
 {
-    QEDAIOCB *acb;
-
     assert(s->allocating_write_reqs_plugged);
 
     s->allocating_write_reqs_plugged = false;
-
-    acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
-    if (acb) {
-        qed_aio_start_io(acb);
-    }
+    qemu_co_enter_next(&s->allocating_write_reqs);
 }
 
 static void qed_clear_need_check(void *opaque, int ret)
@@ -305,7 +299,7 @@ static void qed_need_check_timer_cb(void *opaque)
     BDRVQEDState *s = opaque;
 
     /* The timer should only fire when allocating writes have drained */
-    assert(!QSIMPLEQ_FIRST(&s->allocating_write_reqs));
+    assert(!s->allocating_acb);
 
     trace_qed_need_check_timer_cb(s);
 
@@ -388,7 +382,7 @@ static int bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags,
     int ret;
 
     s->bs = bs;
-    QSIMPLEQ_INIT(&s->allocating_write_reqs);
+    qemu_co_queue_init(&s->allocating_write_reqs);
 
     ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
     if (ret < 0) {
@@ -910,11 +904,6 @@ static void qed_aio_complete_bh(void *opaque)
     qed_release(s);
 }
 
-static void qed_resume_alloc_bh(void *opaque)
-{
-    qed_aio_start_io(opaque);
-}
-
 static void qed_aio_complete(QEDAIOCB *acb, int ret)
 {
     BDRVQEDState *s = acb_to_s(acb);
@@ -942,13 +931,10 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
      * next request in the queue.  This ensures that we don't cycle through
      * requests multiple times but rather finish one at a time completely.
      */
-    if (acb == QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
-        QEDAIOCB *next_acb;
-        QSIMPLEQ_REMOVE_HEAD(&s->allocating_write_reqs, next);
-        next_acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
-        if (next_acb) {
-            aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
-                                    qed_resume_alloc_bh, next_acb);
+    if (acb == s->allocating_acb) {
+        s->allocating_acb = NULL;
+        if (!qemu_co_queue_empty(&s->allocating_write_reqs)) {
+            qemu_co_enter_next(&s->allocating_write_reqs);
         } else if (s->header.features & QED_F_NEED_CHECK) {
             qed_start_need_check_timer(s);
         }
@@ -1124,17 +1110,18 @@ static int qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
     int ret;
 
     /* Cancel timer when the first allocating request comes in */
-    if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
+    if (s->allocating_acb == NULL) {
         qed_cancel_need_check_timer(s);
     }
 
     /* Freeze this request if another allocating write is in progress */
-    if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
-        QSIMPLEQ_INSERT_TAIL(&s->allocating_write_reqs, acb, next);
-    }
-    if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs) ||
-        s->allocating_write_reqs_plugged) {
-        return -EINPROGRESS; /* wait for existing request to finish */
+    if (s->allocating_acb != acb || s->allocating_write_reqs_plugged) {
+        if (s->allocating_acb != NULL) {
+            qemu_co_queue_wait(&s->allocating_write_reqs, NULL);
+            assert(s->allocating_acb == NULL);
+        }
+        s->allocating_acb = acb;
+        return -EAGAIN; /* start over with looking up table entries */
     }
 
     acb->cur_nclusters = qed_bytes_to_clusters(s,
@@ -1313,10 +1300,8 @@ static void qed_aio_next_io(QEDAIOCB *acb)
             ret = qed_aio_read_data(acb, ret, offset, len);
         }
 
-        if (ret < 0) {
-            if (ret != -EINPROGRESS) {
-                qed_aio_complete(acb, ret);
-            }
+        if (ret < 0 && ret != -EAGAIN) {
+            qed_aio_complete(acb, ret);
             return;
         }
     }
diff --git a/block/qed.h b/block/qed.h
index 8644fed..37558e4 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -163,7 +163,8 @@ typedef struct {
     uint32_t l2_mask;
 
     /* Allocating write request queue */
-    QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs;
+    QEDAIOCB *allocating_acb;
+    CoQueue allocating_write_reqs;
     bool allocating_write_reqs_plugged;
 
     /* Periodic flush and clear need check flag */
-- 
1.8.3.1

  parent reply	other threads:[~2017-06-23 16:23 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-23 16:20 [Qemu-devel] [PULL 00/61] Block layer patches Kevin Wolf
2017-06-23 16:20 ` [Qemu-devel] [PULL 01/61] commit: Fix completion with extra reference Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 02/61] qemu-iotests: Allow starting new qemu after cleanup Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 03/61] qemu-iotests: Test exiting qemu with running job Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 04/61] block: count bdrv_co_rw_vmstate() requests Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 05/61] block: use BDRV_POLL_WHILE() in bdrv_rw_vmstate() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 06/61] migration: avoid recursive AioContext locking in save_vmstate() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 07/61] migration: use bdrv_drain_all_begin/end() instead bdrv_drain_all() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 08/61] doc: Document generic -blockdev options Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 09/61] doc: Document driver-specific " Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 10/61] throttle: Update throttle-groups.c documentation Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 11/61] virtio-pci: use ioeventfd even when KVM is disabled Kevin Wolf
2017-06-28 10:11   ` [Qemu-devel] [Qemu-block] " QingFeng Hao
2017-06-28 10:22     ` Kevin Wolf
2017-06-28 13:07       ` QingFeng Hao
2017-07-03  6:01       ` QingFeng Hao
2017-06-23 16:21 ` [Qemu-devel] [PULL 12/61] migration: hold AioContext lock for loadvm qemu_fclose() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 13/61] qemu-iotests: 068: extract _qemu() function Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 14/61] qemu-iotests: 068: use -drive/-device instead of -hda Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 15/61] qemu-iotests: 068: test iothread mode Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 16/61] nvme: Add support for Read Data and Write Data in CMBs Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 17/61] qcow2: Remove unused Error variable in do_perform_cow() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 18/61] qcow2: Use unsigned int for both members of Qcow2COWRegion Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 19/61] qcow2: Make perform_cow() call do_perform_cow() twice Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 20/61] qcow2: Split do_perform_cow() into _read(), _encrypt() and _write() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 21/61] qcow2: Allow reading both COW regions with only one request Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 22/61] qcow2: Pass a QEMUIOVector to do_perform_cow_{read, write}() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 23/61] qcow2: Merge the writing of the COW regions with the guest data Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 24/61] qcow2: Use offset_into_cluster() and offset_to_l2_index() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 25/61] qed: Use bottom half to resume waiting requests Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 26/61] qed: Make qed_read_table() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 27/61] qed: Remove callback from qed_read_table() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 28/61] qed: Remove callback from qed_read_l2_table() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 29/61] qed: Remove callback from qed_find_cluster() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 30/61] qed: Make qed_read_backing_file() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 31/61] qed: Make qed_copy_from_backing_file() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 32/61] qed: Remove callback from qed_copy_from_backing_file() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 33/61] qed: Make qed_write_header() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 34/61] qed: Remove callback from qed_write_header() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 35/61] qed: Make qed_write_table() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 36/61] qed: Remove GenericCB Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 37/61] qed: Remove callback from qed_write_table() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 38/61] qed: Make qed_aio_read_data() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 39/61] qed: Make qed_aio_write_main() synchronous Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 40/61] qed: Inline qed_commit_l2_update() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 41/61] qed: Add return value to qed_aio_write_l1_update() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 42/61] qed: Add return value to qed_aio_write_l2_update() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 43/61] qed: Add return value to qed_aio_write_main() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 44/61] qed: Add return value to qed_aio_write_cow() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 45/61] qed: Add return value to qed_aio_write_inplace/alloc() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 46/61] qed: Add return value to qed_aio_read/write_data() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 47/61] qed: Remove ret argument from qed_aio_next_io() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 48/61] qed: Remove recursion in qed_aio_next_io() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 49/61] qed: Implement .bdrv_co_readv/writev Kevin Wolf
2017-06-23 16:21 ` Kevin Wolf [this message]
2017-06-23 16:21 ` [Qemu-devel] [PULL 51/61] qed: Simplify request handling Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 52/61] qed: Use a coroutine for need_check_timer Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 53/61] qed: Add coroutine_fn to I/O path functions Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 54/61] qed: Use bdrv_co_* for coroutine_fns Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 55/61] block: Remove bdrv_aio_readv/writev/flush() Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 56/61] block: change variable names in BlockDriverState Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 57/61] fix: avoid an infinite loop or a dangling pointer problem in img_commit Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 58/61] blkdebug: Catch bs->exact_filename overflow Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 59/61] blkverify: " Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 60/61] block: Do not strcmp() with NULL uri->scheme Kevin Wolf
2017-06-23 16:21 ` [Qemu-devel] [PULL 61/61] qemu-img: don't shadow opts variable in img_dd() Kevin Wolf
2017-06-26 10:23 ` [Qemu-devel] [PULL 00/61] Block layer patches Peter Maydell
2017-06-26 10:26   ` Peter Maydell
2017-06-26 12:50   ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1498234919-27316-51-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.