aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagi@grimberg.me>2017-11-23 10:35:22 -0500
committerChristoph Hellwig <hch@lst.de>2017-11-26 09:33:32 -0500
commit4af7f7ff92a42b6c713293c99e7982bcfcf51a70 (patch)
tree49ab3f97188e32b101fd008db4205024ff8109fd
parentb4b591c87f2b0f4ebaf3a68d4f13873b241aa584 (diff)
nvme-rdma: don't complete requests before a send work request has completed
In order to guarantee that the HCA will never get an access violation (either from invalidated rkey or from iommu) when retrying a send operation we must complete a request only when both send completion and the nvme cqe has arrived. We need to set the send/recv completions flags atomically because we might have more than a single context accessing the request concurrently (one is cq irq-poll context and the other is user-polling used in IOCB_HIPRI). Only then we are safe to invalidate the rkey (if needed), unmap the host buffers, and complete the IO. Signed-off-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/nvme/host/rdma.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 61511bed8aca..502f7c515a99 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -59,6 +59,9 @@ struct nvme_rdma_request {
59 struct nvme_request req; 59 struct nvme_request req;
60 struct ib_mr *mr; 60 struct ib_mr *mr;
61 struct nvme_rdma_qe sqe; 61 struct nvme_rdma_qe sqe;
62 union nvme_result result;
63 __le16 status;
64 refcount_t ref;
62 struct ib_sge sge[1 + NVME_RDMA_MAX_INLINE_SEGMENTS]; 65 struct ib_sge sge[1 + NVME_RDMA_MAX_INLINE_SEGMENTS];
63 u32 num_sge; 66 u32 num_sge;
64 int nents; 67 int nents;
@@ -1162,6 +1165,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
1162 req->num_sge = 1; 1165 req->num_sge = 1;
1163 req->inline_data = false; 1166 req->inline_data = false;
1164 req->mr->need_inval = false; 1167 req->mr->need_inval = false;
1168 refcount_set(&req->ref, 2); /* send and recv completions */
1165 1169
1166 c->common.flags |= NVME_CMD_SGL_METABUF; 1170 c->common.flags |= NVME_CMD_SGL_METABUF;
1167 1171
@@ -1198,8 +1202,19 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
1198 1202
1199static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc) 1203static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
1200{ 1204{
1201 if (unlikely(wc->status != IB_WC_SUCCESS)) 1205 struct nvme_rdma_qe *qe =
1206 container_of(wc->wr_cqe, struct nvme_rdma_qe, cqe);
1207 struct nvme_rdma_request *req =
1208 container_of(qe, struct nvme_rdma_request, sqe);
1209 struct request *rq = blk_mq_rq_from_pdu(req);
1210
1211 if (unlikely(wc->status != IB_WC_SUCCESS)) {
1202 nvme_rdma_wr_error(cq, wc, "SEND"); 1212 nvme_rdma_wr_error(cq, wc, "SEND");
1213 return;
1214 }
1215
1216 if (refcount_dec_and_test(&req->ref))
1217 nvme_end_request(rq, req->status, req->result);
1203} 1218}
1204 1219
1205static int nvme_rdma_post_send(struct nvme_rdma_queue *queue, 1220static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
@@ -1318,14 +1333,19 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
1318 } 1333 }
1319 req = blk_mq_rq_to_pdu(rq); 1334 req = blk_mq_rq_to_pdu(rq);
1320 1335
1321 if (rq->tag == tag) 1336 req->status = cqe->status;
1322 ret = 1; 1337 req->result = cqe->result;
1323 1338
1324 if ((wc->wc_flags & IB_WC_WITH_INVALIDATE) && 1339 if ((wc->wc_flags & IB_WC_WITH_INVALIDATE) &&
1325 wc->ex.invalidate_rkey == req->mr->rkey) 1340 wc->ex.invalidate_rkey == req->mr->rkey)
1326 req->mr->need_inval = false; 1341 req->mr->need_inval = false;
1327 1342
1328 nvme_end_request(rq, cqe->status, cqe->result); 1343 if (refcount_dec_and_test(&req->ref)) {
1344 if (rq->tag == tag)
1345 ret = 1;
1346 nvme_end_request(rq, req->status, req->result);
1347 }
1348
1329 return ret; 1349 return ret;
1330} 1350}
1331 1351