[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