All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, eesposit@redhat.com, kwolf@redhat.com
Subject: [PATCH 07/15] block-backend: enter aio coroutine only after drain
Date: Mon, 12 Dec 2022 13:59:12 +0100	[thread overview]
Message-ID: <20221212125920.248567-8-pbonzini@redhat.com> (raw)
In-Reply-To: <20221212125920.248567-1-pbonzini@redhat.com>

When called from within (another) coroutine, aio_co_enter will not
enter a coroutine immediately; instead the new coroutine is scheduled
to run after qemu_coroutine_yield().  This however might cause the
currently-running coroutine to yield without having raised blk->in_flight.
If it was a ->drained_begin() callback who scheduled the coroutine,
bdrv_drained_begin() might exit without waiting for the I/O operation
to finish.  Right now, this is masked by unnecessary polling done by
bdrv_drained_begin() after the callbacks return, but it is wrong and
a latent bug.

So, ensure that blk_inc_in_flight() and blk_wait_while_drained()
are called before aio_co_enter().  To do so, pull the call to
blk_wait_while_drained() out of the blk_co_do_* functions, which are
called from the AIO coroutines, and place them separately in the public
blk_co_* functions and in blk_aio_prwv.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/block-backend.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 2852a892de6c..c4a884b86c2b 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1288,8 +1288,6 @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
     BlockDriverState *bs;
     IO_CODE();
 
-    blk_wait_while_drained(blk);
-
     /* Call blk_bs() only after waiting, the graph may have changed */
     bs = blk_bs(blk);
     trace_blk_co_preadv(blk, bs, offset, bytes, flags);
@@ -1332,6 +1330,7 @@ int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, 0, flags);
     blk_dec_in_flight(blk);
 
@@ -1346,6 +1345,7 @@ int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, qiov_offset, flags);
     blk_dec_in_flight(blk);
 
@@ -1362,8 +1362,6 @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
     BlockDriverState *bs;
     IO_CODE();
 
-    blk_wait_while_drained(blk);
-
     /* Call blk_bs() only after waiting, the graph may have changed */
     bs = blk_bs(blk);
     trace_blk_co_pwritev(blk, bs, offset, bytes, flags);
@@ -1399,6 +1397,7 @@ int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
     blk_dec_in_flight(blk);
 
@@ -1543,6 +1542,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
     Coroutine *co;
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
     acb->rwco = (BlkRwCo) {
         .blk    = blk,
@@ -1667,8 +1667,6 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
 {
     IO_CODE();
 
-    blk_wait_while_drained(blk);
-
     if (!blk_is_available(blk)) {
         return -ENOMEDIUM;
     }
@@ -1683,6 +1681,7 @@ int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_ioctl(blk, req, buf);
     blk_dec_in_flight(blk);
 
@@ -1713,8 +1712,6 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
     int ret;
     IO_CODE();
 
-    blk_wait_while_drained(blk);
-
     ret = blk_check_byte_request(blk, offset, bytes);
     if (ret < 0) {
         return ret;
@@ -1748,6 +1745,7 @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_pdiscard(blk, offset, bytes);
     blk_dec_in_flight(blk);
 
@@ -1757,7 +1755,6 @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
 /* To be called between exactly one pair of blk_inc/dec_in_flight() */
 static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
 {
-    blk_wait_while_drained(blk);
     IO_CODE();
 
     if (!blk_is_available(blk)) {
@@ -1789,6 +1786,7 @@ int coroutine_fn blk_co_flush(BlockBackend *blk)
     IO_OR_GS_CODE();
 
     blk_inc_in_flight(blk);
+    blk_wait_while_drained(blk);
     ret = blk_co_do_flush(blk);
     blk_dec_in_flight(blk);
 
-- 
2.38.1



  parent reply	other threads:[~2022-12-12 13:08 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-12 12:59 [PATCH 00/12] More cleanups and fixes for drain Paolo Bonzini
2022-12-12 12:59 ` [PATCH 01/15] Revert "block: Remove poll parameter from bdrv_parent_drained_begin_single()" Paolo Bonzini
2022-12-12 12:59 ` [PATCH 02/15] Revert "block: Don't poll in bdrv_replace_child_noperm()" Paolo Bonzini
2022-12-12 12:59 ` [PATCH 03/15] block: Pull polling out of bdrv_parent_drained_begin_single() Paolo Bonzini
2022-12-12 12:59 ` [PATCH 04/15] test-bdrv-drain.c: remove test_detach_by_parent_cb() Paolo Bonzini
2022-12-12 12:59 ` [PATCH 05/15] tests/unit/test-bdrv-drain.c: graph setup functions can't run in coroutines Paolo Bonzini
2022-12-12 12:59 ` [PATCH 06/15] tests/qemu-iotests/030: test_stream_parallel should use auto_finalize=False Paolo Bonzini
2022-12-12 12:59 ` Paolo Bonzini [this message]
2023-01-16 15:57   ` [PATCH 07/15] block-backend: enter aio coroutine only after drain Kevin Wolf
2022-12-12 12:59 ` [PATCH 08/15] nbd: a BlockExport always has a BlockBackend Paolo Bonzini
2022-12-12 12:59 ` [PATCH 09/15] block-backend: make global properties write-once Paolo Bonzini
2022-12-12 12:59 ` [PATCH 10/15] block-backend: always wait for drain before starting operation Paolo Bonzini
2023-01-16 16:48   ` Kevin Wolf
2022-12-12 12:59 ` [PATCH 11/15] block-backend: make queued_requests thread-safe Paolo Bonzini
2023-01-11 20:44   ` Stefan Hajnoczi
2023-01-16 16:55   ` Kevin Wolf
2022-12-12 12:59 ` [PATCH 12/15] block: limit bdrv_co_yield_to_drain to drain_begin Paolo Bonzini
2022-12-12 12:59 ` [PATCH 13/15] block: second argument of bdrv_do_drained_end is always NULL Paolo Bonzini
2022-12-12 12:59 ` [PATCH 14/15] block: second argument of bdrv_do_drained_begin and bdrv_drain_poll " Paolo Bonzini
2022-12-12 12:59 ` [PATCH 15/15] block: only get out of coroutine context for polling Paolo Bonzini
2023-01-16 15:51 ` [PATCH 00/12] More cleanups and fixes for drain Kevin Wolf
2023-01-16 17:25 ` 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=20221212125920.248567-8-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=eesposit@redhat.com \
    --cc=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.