[PATCH] nvmet-rdma: process wr wait list from a non-atomic context

Sagi Grimberg sagi at grimberg.me
Tue Jun 22 00:42:57 PDT 2021


If we fail to post a rsp capsule, we release the rsp and
if we happen to have a work waiting on the wr_wait_list, hence
we need to process them, however the context can be softirq
hence we need to schedule this on a kthread as I/O submission
may schedule.

Reported-by: Michal Kalderon <mkalderon at marvell.com>
Tested-by: Michal Kalderon <mkalderon at marvell.com>
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/target/rdma.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 891174ccd44b..9684d8972a3e 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -102,6 +102,7 @@ struct nvmet_rdma_queue {
 
 	struct work_struct	release_work;
 	struct list_head	rsp_wait_list;
+	struct work_struct	wr_wait_work;
 	struct list_head	rsp_wr_wait_list;
 	spinlock_t		rsp_wr_wait_lock;
 
@@ -517,8 +518,10 @@ static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,
 	return ret;
 }
 
-static void nvmet_rdma_process_wr_wait_list(struct nvmet_rdma_queue *queue)
+static void nvmet_rdma_process_wr_wait_list(struct work_struct *w)
 {
+	struct nvmet_rdma_queue *queue =
+		container_of(w, struct nvmet_rdma_queue, wr_wait_work);
 	spin_lock(&queue->rsp_wr_wait_lock);
 	while (!list_empty(&queue->rsp_wr_wait_list)) {
 		struct nvmet_rdma_rsp *rsp;
@@ -677,7 +680,7 @@ static void nvmet_rdma_release_rsp(struct nvmet_rdma_rsp *rsp)
 		nvmet_req_free_sgls(&rsp->req);
 
 	if (unlikely(!list_empty_careful(&queue->rsp_wr_wait_list)))
-		nvmet_rdma_process_wr_wait_list(queue);
+		schedule_work(&queue->wr_wait_work);
 
 	nvmet_rdma_put_rsp(rsp);
 }
@@ -1445,6 +1448,7 @@ nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev,
 	 * inside a CM callback would trigger a deadlock. (great API design..)
 	 */
 	INIT_WORK(&queue->release_work, nvmet_rdma_release_queue_work);
+	INIT_WORK(&queue->wr_wait_work, nvmet_rdma_process_wr_wait_list);
 	queue->dev = ndev;
 	queue->cm_id = cm_id;
 	queue->port = port->nport;
-- 
2.27.0




More information about the Linux-nvme mailing list