[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 6/7] block: Fix blk->in_flight during blk_wait_while_drained()
From: |
Kevin Wolf |
Subject: |
[PULL 6/7] block: Fix blk->in_flight during blk_wait_while_drained() |
Date: |
Tue, 7 Apr 2020 16:26:15 +0200 |
Waiting in blk_wait_while_drained() while blk->in_flight is increased
for the current request is wrong because it will cause the drain
operation to deadlock.
This patch makes sure that blk_wait_while_drained() is called with
blk->in_flight increased exactly once for the current request, and that
it temporarily decreases the counter while it waits.
Fixes: cf3129323f900ef5ddbccbe86e4fa801e88c566e
Signed-off-by: Kevin Wolf <address@hidden>
Reviewed-by: Vladimir Sementsov-Ogievskiy <address@hidden>
Reviewed-by: Max Reitz <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block/block-backend.c | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index 610dbfa0b2..38ae413826 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1140,10 +1140,15 @@ static int blk_check_byte_request(BlockBackend *blk,
int64_t offset,
return 0;
}
+/* To be called between exactly one pair of blk_inc/dec_in_flight() */
static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
{
+ assert(blk->in_flight > 0);
+
if (blk->quiesce_counter && !blk->disable_request_queuing) {
+ blk_dec_in_flight(blk);
qemu_co_queue_wait(&blk->queued_requests, NULL);
+ blk_inc_in_flight(blk);
}
}
@@ -1418,12 +1423,6 @@ static void blk_aio_read_entry(void *opaque)
BlkRwCo *rwco = &acb->rwco;
QEMUIOVector *qiov = rwco->iobuf;
- if (rwco->blk->quiesce_counter) {
- blk_dec_in_flight(rwco->blk);
- blk_wait_while_drained(rwco->blk);
- blk_inc_in_flight(rwco->blk);
- }
-
assert(qiov->size == acb->bytes);
rwco->ret = blk_do_preadv(rwco->blk, rwco->offset, acb->bytes,
qiov, rwco->flags);
@@ -1436,12 +1435,6 @@ static void blk_aio_write_entry(void *opaque)
BlkRwCo *rwco = &acb->rwco;
QEMUIOVector *qiov = rwco->iobuf;
- if (rwco->blk->quiesce_counter) {
- blk_dec_in_flight(rwco->blk);
- blk_wait_while_drained(rwco->blk);
- blk_inc_in_flight(rwco->blk);
- }
-
assert(!qiov || qiov->size == acb->bytes);
rwco->ret = blk_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
qiov, 0, rwco->flags);
--
2.20.1
- [PULL 0/7] Block layer patches, Kevin Wolf, 2020/04/07
- [PULL 1/7] job: take each job's lock individually in job_txn_apply, Kevin Wolf, 2020/04/07
- [PULL 4/7] block-backend: Reorder flush/pdiscard function definitions, Kevin Wolf, 2020/04/07
- [PULL 3/7] backup: don't acquire aio_context in backup_clean, Kevin Wolf, 2020/04/07
- [PULL 5/7] block: Increase BB.in_flight for coroutine and sync interfaces, Kevin Wolf, 2020/04/07
- [PULL 7/7] vpc: Don't round up already aligned BAT sizes, Kevin Wolf, 2020/04/07
- [PULL 6/7] block: Fix blk->in_flight during blk_wait_while_drained(),
Kevin Wolf <=
- [PULL 2/7] replication: assert we own context before job_cancel_sync, Kevin Wolf, 2020/04/07
- Re: [PULL 0/7] Block layer patches, Peter Maydell, 2020/04/07