1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

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 <david.li@jaguarmicro.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
Ruozhu Li 2025-02-16 20:49:56 +08:00 committed by Keith Busch
parent 4082326807
commit 3988ac1c67

View file

@ -996,6 +996,27 @@ out_err:
nvmet_req_complete(&cmd->req, status);
}
static bool nvmet_rdma_recv_not_live(struct nvmet_rdma_queue *queue,
struct nvmet_rdma_rsp *rsp)
{
unsigned long flags;
bool ret = true;
spin_lock_irqsave(&queue->state_lock, flags);
/*
* recheck queue state is not live to prevent a race condition
* with RDMA_CM_EVENT_ESTABLISHED handler.
*/
if (queue->state == NVMET_RDMA_Q_LIVE)
ret = false;
else if (queue->state == NVMET_RDMA_Q_CONNECTING)
list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
else
nvmet_rdma_put_rsp(rsp);
spin_unlock_irqrestore(&queue->state_lock, flags);
return ret;
}
static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct nvmet_rdma_cmd *cmd =
@ -1038,17 +1059,9 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
rsp->n_rdma = 0;
rsp->invalidate_rkey = 0;
if (unlikely(queue->state != NVMET_RDMA_Q_LIVE)) {
unsigned long flags;
spin_lock_irqsave(&queue->state_lock, flags);
if (queue->state == NVMET_RDMA_Q_CONNECTING)
list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
else
nvmet_rdma_put_rsp(rsp);
spin_unlock_irqrestore(&queue->state_lock, flags);
if (unlikely(queue->state != NVMET_RDMA_Q_LIVE) &&
nvmet_rdma_recv_not_live(queue, rsp))
return;
}
nvmet_rdma_handle_command(queue, rsp);
}