Skip to content

Commit 3988ac1

Browse files
Ruozhu Likeithbusch
authored andcommitted
nvmet-rdma: recheck queue state is LIVE in state lock in recv done
The queue state checking in nvmet_rdma_recv_done is not in queue state lock.Queue state can transfer to LIVE in cm establish handler between state checking and state lock here, cause a silent drop of nvme connect cmd. Recheck queue state whether in LIVE state in state lock to prevent this issue. Signed-off-by: Ruozhu Li <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 4082326 commit 3988ac1

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

drivers/nvme/target/rdma.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,27 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
996996
nvmet_req_complete(&cmd->req, status);
997997
}
998998

999+
static bool nvmet_rdma_recv_not_live(struct nvmet_rdma_queue *queue,
1000+
struct nvmet_rdma_rsp *rsp)
1001+
{
1002+
unsigned long flags;
1003+
bool ret = true;
1004+
1005+
spin_lock_irqsave(&queue->state_lock, flags);
1006+
/*
1007+
* recheck queue state is not live to prevent a race condition
1008+
* with RDMA_CM_EVENT_ESTABLISHED handler.
1009+
*/
1010+
if (queue->state == NVMET_RDMA_Q_LIVE)
1011+
ret = false;
1012+
else if (queue->state == NVMET_RDMA_Q_CONNECTING)
1013+
list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
1014+
else
1015+
nvmet_rdma_put_rsp(rsp);
1016+
spin_unlock_irqrestore(&queue->state_lock, flags);
1017+
return ret;
1018+
}
1019+
9991020
static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
10001021
{
10011022
struct nvmet_rdma_cmd *cmd =
@@ -1038,17 +1059,9 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
10381059
rsp->n_rdma = 0;
10391060
rsp->invalidate_rkey = 0;
10401061

1041-
if (unlikely(queue->state != NVMET_RDMA_Q_LIVE)) {
1042-
unsigned long flags;
1043-
1044-
spin_lock_irqsave(&queue->state_lock, flags);
1045-
if (queue->state == NVMET_RDMA_Q_CONNECTING)
1046-
list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
1047-
else
1048-
nvmet_rdma_put_rsp(rsp);
1049-
spin_unlock_irqrestore(&queue->state_lock, flags);
1062+
if (unlikely(queue->state != NVMET_RDMA_Q_LIVE) &&
1063+
nvmet_rdma_recv_not_live(queue, rsp))
10501064
return;
1051-
}
10521065

10531066
nvmet_rdma_handle_command(queue, rsp);
10541067
}

0 commit comments

Comments
 (0)