Commit 6460440f authored by Kevin Wolf's avatar Kevin Wolf

block: Allow wait_serialising_requests() at any point

We can only have a single wait_serialising_requests() call per request
because otherwise we can run into deadlocks where requests are waiting
for each other. The same is true when wait_serialising_requests() is not
at the very beginning of a request, so that other requests can be issued
between the start of the tracking and wait_serialising_requests().

Fix this by changing wait_serialising_requests() to ignore requests that
are already (directly or indirectly) waiting for the calling request.
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarMax Reitz <mreitz@redhat.com>
Reviewed-by: default avatarBenoit Canet <benoit@irqsave.net>
parent 7327145f
...@@ -2328,9 +2328,16 @@ static void coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self) ...@@ -2328,9 +2328,16 @@ static void coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
*/ */
assert(qemu_coroutine_self() != req->co); assert(qemu_coroutine_self() != req->co);
qemu_co_queue_wait(&req->wait_queue); /* If the request is already (indirectly) waiting for us, or
retry = true; * will wait for us as soon as it wakes up, then just go on
break; * (instead of producing a deadlock in the former case). */
if (!req->waiting_for) {
self->waiting_for = req;
qemu_co_queue_wait(&req->wait_queue);
self->waiting_for = NULL;
retry = true;
break;
}
} }
} }
} while (retry); } while (retry);
......
...@@ -68,6 +68,8 @@ typedef struct BdrvTrackedRequest { ...@@ -68,6 +68,8 @@ typedef struct BdrvTrackedRequest {
QLIST_ENTRY(BdrvTrackedRequest) list; QLIST_ENTRY(BdrvTrackedRequest) list;
Coroutine *co; /* owner, used for deadlock detection */ Coroutine *co; /* owner, used for deadlock detection */
CoQueue wait_queue; /* coroutines blocked on this request */ CoQueue wait_queue; /* coroutines blocked on this request */
struct BdrvTrackedRequest *waiting_for;
} BdrvTrackedRequest; } BdrvTrackedRequest;
struct BlockDriver { struct BlockDriver {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment