提交 2f122e4f 编写于 作者: S Sagi Grimberg 提交者: Christoph Hellwig

nvme-rdma: wait for local invalidation before completing a request

We must not complete a request before the host memory region is
invalidated.  Luckily we have send with invalidate protocol support so
we usually don't need to execute it, but in case the target did not
invalidate a memory region for us, we must wait for the invalidation to
complete before unmapping host memory and completing the I/O.
Signed-off-by: NSagi Grimberg <sagi@grimberg.me>
Reviewed-by: NMax Gurtovoy <maxg@mellanox.com>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
上级 4af7f7ff
...@@ -1019,8 +1019,18 @@ static void nvme_rdma_memreg_done(struct ib_cq *cq, struct ib_wc *wc) ...@@ -1019,8 +1019,18 @@ static void nvme_rdma_memreg_done(struct ib_cq *cq, struct ib_wc *wc)
static void nvme_rdma_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc) static void nvme_rdma_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc)
{ {
if (unlikely(wc->status != IB_WC_SUCCESS)) struct nvme_rdma_request *req =
container_of(wc->wr_cqe, struct nvme_rdma_request, reg_cqe);
struct request *rq = blk_mq_rq_from_pdu(req);
if (unlikely(wc->status != IB_WC_SUCCESS)) {
nvme_rdma_wr_error(cq, wc, "LOCAL_INV"); nvme_rdma_wr_error(cq, wc, "LOCAL_INV");
return;
}
if (refcount_dec_and_test(&req->ref))
nvme_end_request(rq, req->status, req->result);
} }
static int nvme_rdma_inv_rkey(struct nvme_rdma_queue *queue, static int nvme_rdma_inv_rkey(struct nvme_rdma_queue *queue,
...@@ -1031,7 +1041,7 @@ static int nvme_rdma_inv_rkey(struct nvme_rdma_queue *queue, ...@@ -1031,7 +1041,7 @@ static int nvme_rdma_inv_rkey(struct nvme_rdma_queue *queue,
.opcode = IB_WR_LOCAL_INV, .opcode = IB_WR_LOCAL_INV,
.next = NULL, .next = NULL,
.num_sge = 0, .num_sge = 0,
.send_flags = 0, .send_flags = IB_SEND_SIGNALED,
.ex.invalidate_rkey = req->mr->rkey, .ex.invalidate_rkey = req->mr->rkey,
}; };
...@@ -1045,24 +1055,12 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue, ...@@ -1045,24 +1055,12 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue,
struct request *rq) struct request *rq)
{ {
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
struct nvme_rdma_ctrl *ctrl = queue->ctrl;
struct nvme_rdma_device *dev = queue->device; struct nvme_rdma_device *dev = queue->device;
struct ib_device *ibdev = dev->dev; struct ib_device *ibdev = dev->dev;
int res;
if (!blk_rq_bytes(rq)) if (!blk_rq_bytes(rq))
return; return;
if (req->mr->need_inval && test_bit(NVME_RDMA_Q_LIVE, &req->queue->flags)) {
res = nvme_rdma_inv_rkey(queue, req);
if (unlikely(res < 0)) {
dev_err(ctrl->ctrl.device,
"Queueing INV WR for rkey %#x failed (%d)\n",
req->mr->rkey, res);
nvme_rdma_error_recovery(queue->ctrl);
}
}
ib_dma_unmap_sg(ibdev, req->sg_table.sgl, ib_dma_unmap_sg(ibdev, req->sg_table.sgl,
req->nents, rq_data_dir(rq) == req->nents, rq_data_dir(rq) ==
WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE); WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
...@@ -1337,8 +1335,19 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue, ...@@ -1337,8 +1335,19 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
req->result = cqe->result; req->result = cqe->result;
if ((wc->wc_flags & IB_WC_WITH_INVALIDATE) && if ((wc->wc_flags & IB_WC_WITH_INVALIDATE) &&
wc->ex.invalidate_rkey == req->mr->rkey) wc->ex.invalidate_rkey == req->mr->rkey) {
req->mr->need_inval = false; req->mr->need_inval = false;
} else if (req->mr->need_inval) {
ret = nvme_rdma_inv_rkey(queue, req);
if (unlikely(ret < 0)) {
dev_err(queue->ctrl->ctrl.device,
"Queueing INV WR for rkey %#x failed (%d)\n",
req->mr->rkey, ret);
nvme_rdma_error_recovery(queue->ctrl);
}
/* the local invalidation completion will end the request */
return 0;
}
if (refcount_dec_and_test(&req->ref)) { if (refcount_dec_and_test(&req->ref)) {
if (rq->tag == tag) if (rq->tag == tag)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册