From cb53bf1e28eed6de3d3d94da913b1bbc3e2f9947 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sun, 17 May 2020 19:58:00 -0400 Subject: [PATCH] nvme_disk: Fix nvme_qpair_submit_queued_requests. I added this function to make the queued requests logic more robust, but I failed to notice that since it is called from nvme_qpair_submit_request, it would just result in a deadlock of any qpair that had requests queued. May help with some of the "qpair lockup" tickets. Change-Id: I5ff63b509ae8812356d0d33f019027d3159b6685 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2735 Reviewed-by: waddlesplash --- .../kernel/drivers/disk/nvme/libnvme/nvme_qpair.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/drivers/disk/nvme/libnvme/nvme_qpair.c b/src/add-ons/kernel/drivers/disk/nvme/libnvme/nvme_qpair.c index cc96162aaf..fe2f601f8b 100644 --- a/src/add-ons/kernel/drivers/disk/nvme/libnvme/nvme_qpair.c +++ b/src/add-ons/kernel/drivers/disk/nvme/libnvme/nvme_qpair.c @@ -412,22 +412,30 @@ done: static void nvme_qpair_submit_queued_requests(struct nvme_qpair *qpair) { + STAILQ_HEAD(, nvme_request) req_queue; + STAILQ_INIT(&req_queue); + pthread_mutex_lock(&qpair->lock); + STAILQ_CONCAT(&req_queue, &qpair->queued_req); + /* * If the controller is in the middle of a reset, don't * try to submit queued requests - let the reset logic * handle that instead. */ - while (!STAILQ_EMPTY(&qpair->queued_req) && !qpair->ctrlr->resetting) { - struct nvme_request *req = STAILQ_FIRST(&qpair->queued_req); - STAILQ_REMOVE_HEAD(&qpair->queued_req, stailq); + while (!qpair->ctrlr->resetting && LIST_FIRST(&qpair->free_tr) + && !STAILQ_EMPTY(&req_queue)) { + struct nvme_request *req = STAILQ_FIRST(&req_queue); + STAILQ_REMOVE_HEAD(&req_queue, stailq); pthread_mutex_unlock(&qpair->lock); nvme_qpair_submit_request(qpair, req); pthread_mutex_lock(&qpair->lock); } + STAILQ_CONCAT(&qpair->queued_req, &req_queue); + pthread_mutex_unlock(&qpair->lock); }