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:
parent
4082326807
commit
3988ac1c67
1 changed files with 23 additions and 10 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue