Skip to content

Commit 31deaeb

Browse files
hreineckekeithbusch
authored andcommitted
nvmet-rdma: avoid circular locking dependency on install_queue()
nvmet_rdma_install_queue() is driven from the ->io_work workqueue function, but will call flush_workqueue() which might trigger ->release_work() which in itself calls flush_work on ->io_work. To avoid that check for pending queue in disconnecting status, and return 'controller busy' when we reached a certain threshold. Signed-off-by: Hannes Reinecke <[email protected]> Tested-by: Shin'ichiro Kawasaki <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 07a29b1 commit 31deaeb

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

drivers/nvme/target/rdma.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#define NVMET_RDMA_MAX_MDTS 8
3838
#define NVMET_RDMA_MAX_METADATA_MDTS 5
3939

40+
#define NVMET_RDMA_BACKLOG 128
41+
4042
struct nvmet_rdma_srq;
4143

4244
struct nvmet_rdma_cmd {
@@ -1583,8 +1585,19 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
15831585
}
15841586

15851587
if (queue->host_qid == 0) {
1586-
/* Let inflight controller teardown complete */
1587-
flush_workqueue(nvmet_wq);
1588+
struct nvmet_rdma_queue *q;
1589+
int pending = 0;
1590+
1591+
/* Check for pending controller teardown */
1592+
mutex_lock(&nvmet_rdma_queue_mutex);
1593+
list_for_each_entry(q, &nvmet_rdma_queue_list, queue_list) {
1594+
if (q->nvme_sq.ctrl == queue->nvme_sq.ctrl &&
1595+
q->state == NVMET_RDMA_Q_DISCONNECTING)
1596+
pending++;
1597+
}
1598+
mutex_unlock(&nvmet_rdma_queue_mutex);
1599+
if (pending > NVMET_RDMA_BACKLOG)
1600+
return NVME_SC_CONNECT_CTRL_BUSY;
15881601
}
15891602

15901603
ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);
@@ -1880,7 +1893,7 @@ static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port)
18801893
goto out_destroy_id;
18811894
}
18821895

1883-
ret = rdma_listen(cm_id, 128);
1896+
ret = rdma_listen(cm_id, NVMET_RDMA_BACKLOG);
18841897
if (ret) {
18851898
pr_err("listening to %pISpcs failed (%d)\n", addr, ret);
18861899
goto out_destroy_id;

0 commit comments

Comments
 (0)