block: wait_for_overlapping_requests() deadlock detection
Debugging a reentrant request deadlock was fun but in the future we need a quick and obvious way of detecting such bugs. Add an assert that checks we are not about to deadlock when waiting for another request. Suggested-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
bd9533e36e
commit
5f8b6491f2
8
block.c
8
block.c
@ -1099,6 +1099,7 @@ struct BdrvTrackedRequest {
|
||||
int nb_sectors;
|
||||
bool is_write;
|
||||
QLIST_ENTRY(BdrvTrackedRequest) list;
|
||||
Coroutine *co; /* owner, used for deadlock detection */
|
||||
CoQueue wait_queue; /* coroutines blocked on this request */
|
||||
};
|
||||
|
||||
@ -1126,6 +1127,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||
.sector_num = sector_num,
|
||||
.nb_sectors = nb_sectors,
|
||||
.is_write = is_write,
|
||||
.co = qemu_coroutine_self(),
|
||||
};
|
||||
|
||||
qemu_co_queue_init(&req->wait_queue);
|
||||
@ -1189,6 +1191,12 @@ static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
|
||||
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
||||
if (tracked_request_overlaps(req, cluster_sector_num,
|
||||
cluster_nb_sectors)) {
|
||||
/* Hitting this means there was a reentrant request, for
|
||||
* example, a block driver issuing nested requests. This must
|
||||
* never happen since it means deadlock.
|
||||
*/
|
||||
assert(qemu_coroutine_self() != req->co);
|
||||
|
||||
qemu_co_queue_wait(&req->wait_queue);
|
||||
retry = true;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user