[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for-5.0 2/2] block: Fix blk->in_flight during blk_wait_while_drai
From: |
Kevin Wolf |
Subject: |
[PATCH for-5.0 2/2] block: Fix blk->in_flight during blk_wait_while_drained() |
Date: |
Fri, 3 Apr 2020 12:44:15 +0200 |
Calling 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.
Many callers of blk_wait_while_drained() have already increased
blk->in_flight when called in a blk_aio_*() path, but can also be called
in synchonous code paths where blk->in_flight isn't increased. This
means that these calls of blk_wait_while_drained() are wrong at least in
some cases.
In order to fix this, increase blk->in_flight even for synchronous
operations and temporarily decrease the counter again in
blk_wait_while_drained().
Fixes: cf3129323f900ef5ddbccbe86e4fa801e88c566e
Signed-off-by: Kevin Wolf <address@hidden>
---
block/block-backend.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index 3124e367b3..7bd16402b8 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1143,7 +1143,9 @@ static int blk_check_byte_request(BlockBackend *blk,
int64_t offset,
static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
{
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);
}
}
@@ -1260,6 +1262,7 @@ static int blk_prw(BlockBackend *blk, int64_t offset,
uint8_t *buf,
.ret = NOT_DONE,
};
+ blk_inc_in_flight(blk);
if (qemu_in_coroutine()) {
/* Fast-path if already in coroutine context */
co_entry(&rwco);
@@ -1268,6 +1271,7 @@ static int blk_prw(BlockBackend *blk, int64_t offset,
uint8_t *buf,
bdrv_coroutine_enter(blk_bs(blk), co);
BDRV_POLL_WHILE(blk_bs(blk), rwco.ret == NOT_DONE);
}
+ blk_dec_in_flight(blk);
return rwco.ret;
}
@@ -1386,9 +1390,7 @@ static void blk_aio_read_entry(void *opaque)
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);
@@ -1404,9 +1406,7 @@ static void blk_aio_write_entry(void *opaque)
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);
--
2.20.1