mirror of https://gitee.com/openkylin/qemu.git
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;
|
int nb_sectors;
|
||||||
bool is_write;
|
bool is_write;
|
||||||
QLIST_ENTRY(BdrvTrackedRequest) list;
|
QLIST_ENTRY(BdrvTrackedRequest) list;
|
||||||
|
Coroutine *co; /* owner, used for deadlock detection */
|
||||||
CoQueue wait_queue; /* coroutines blocked on this request */
|
CoQueue wait_queue; /* coroutines blocked on this request */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1126,6 +1127,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||||
.sector_num = sector_num,
|
.sector_num = sector_num,
|
||||||
.nb_sectors = nb_sectors,
|
.nb_sectors = nb_sectors,
|
||||||
.is_write = is_write,
|
.is_write = is_write,
|
||||||
|
.co = qemu_coroutine_self(),
|
||||||
};
|
};
|
||||||
|
|
||||||
qemu_co_queue_init(&req->wait_queue);
|
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) {
|
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
||||||
if (tracked_request_overlaps(req, cluster_sector_num,
|
if (tracked_request_overlaps(req, cluster_sector_num,
|
||||||
cluster_nb_sectors)) {
|
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);
|
qemu_co_queue_wait(&req->wait_queue);
|
||||||
retry = true;
|
retry = true;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue