diff options
-rw-r--r-- | include/linux/sunrpc/svc_rdma.h | 1 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_sendto.c | 58 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 12 |
3 files changed, 65 insertions, 6 deletions
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 3584bc8864c4..cc3ae16eac68 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h | |||
@@ -137,6 +137,7 @@ struct svcxprt_rdma { | |||
137 | int sc_ord; /* RDMA read limit */ | 137 | int sc_ord; /* RDMA read limit */ |
138 | int sc_max_sge; | 138 | int sc_max_sge; |
139 | int sc_max_sge_rd; /* max sge for read target */ | 139 | int sc_max_sge_rd; /* max sge for read target */ |
140 | bool sc_snd_w_inv; /* OK to use Send With Invalidate */ | ||
140 | 141 | ||
141 | atomic_t sc_sq_count; /* Number of SQ WR on queue */ | 142 | atomic_t sc_sq_count; /* Number of SQ WR on queue */ |
142 | unsigned int sc_sq_depth; /* Depth of SQ */ | 143 | unsigned int sc_sq_depth; /* Depth of SQ */ |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 3b95b19fcf72..f5a91edcd233 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
@@ -225,6 +225,48 @@ svc_rdma_get_reply_array(struct rpcrdma_msg *rmsgp, | |||
225 | return rp_ary; | 225 | return rp_ary; |
226 | } | 226 | } |
227 | 227 | ||
228 | /* RPC-over-RDMA Version One private extension: Remote Invalidation. | ||
229 | * Responder's choice: requester signals it can handle Send With | ||
230 | * Invalidate, and responder chooses one rkey to invalidate. | ||
231 | * | ||
232 | * Find a candidate rkey to invalidate when sending a reply. Picks the | ||
233 | * first rkey it finds in the chunks lists. | ||
234 | * | ||
235 | * Returns zero if RPC's chunk lists are empty. | ||
236 | */ | ||
237 | static u32 svc_rdma_get_inv_rkey(struct rpcrdma_msg *rdma_argp, | ||
238 | struct rpcrdma_write_array *wr_ary, | ||
239 | struct rpcrdma_write_array *rp_ary) | ||
240 | { | ||
241 | struct rpcrdma_read_chunk *rd_ary; | ||
242 | struct rpcrdma_segment *arg_ch; | ||
243 | u32 inv_rkey; | ||
244 | |||
245 | inv_rkey = 0; | ||
246 | |||
247 | rd_ary = svc_rdma_get_read_chunk(rdma_argp); | ||
248 | if (rd_ary) { | ||
249 | inv_rkey = be32_to_cpu(rd_ary->rc_target.rs_handle); | ||
250 | goto out; | ||
251 | } | ||
252 | |||
253 | if (wr_ary && be32_to_cpu(wr_ary->wc_nchunks)) { | ||
254 | arg_ch = &wr_ary->wc_array[0].wc_target; | ||
255 | inv_rkey = be32_to_cpu(arg_ch->rs_handle); | ||
256 | goto out; | ||
257 | } | ||
258 | |||
259 | if (rp_ary && be32_to_cpu(rp_ary->wc_nchunks)) { | ||
260 | arg_ch = &rp_ary->wc_array[0].wc_target; | ||
261 | inv_rkey = be32_to_cpu(arg_ch->rs_handle); | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | out: | ||
266 | dprintk("svcrdma: Send With Invalidate rkey=%08x\n", inv_rkey); | ||
267 | return inv_rkey; | ||
268 | } | ||
269 | |||
228 | /* Assumptions: | 270 | /* Assumptions: |
229 | * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE | 271 | * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE |
230 | */ | 272 | */ |
@@ -464,7 +506,8 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
464 | struct page *page, | 506 | struct page *page, |
465 | struct rpcrdma_msg *rdma_resp, | 507 | struct rpcrdma_msg *rdma_resp, |
466 | struct svc_rdma_req_map *vec, | 508 | struct svc_rdma_req_map *vec, |
467 | int byte_count) | 509 | int byte_count, |
510 | u32 inv_rkey) | ||
468 | { | 511 | { |
469 | struct svc_rdma_op_ctxt *ctxt; | 512 | struct svc_rdma_op_ctxt *ctxt; |
470 | struct ib_send_wr send_wr; | 513 | struct ib_send_wr send_wr; |
@@ -535,7 +578,11 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
535 | send_wr.wr_cqe = &ctxt->cqe; | 578 | send_wr.wr_cqe = &ctxt->cqe; |
536 | send_wr.sg_list = ctxt->sge; | 579 | send_wr.sg_list = ctxt->sge; |
537 | send_wr.num_sge = sge_no; | 580 | send_wr.num_sge = sge_no; |
538 | send_wr.opcode = IB_WR_SEND; | 581 | if (inv_rkey) { |
582 | send_wr.opcode = IB_WR_SEND_WITH_INV; | ||
583 | send_wr.ex.invalidate_rkey = inv_rkey; | ||
584 | } else | ||
585 | send_wr.opcode = IB_WR_SEND; | ||
539 | send_wr.send_flags = IB_SEND_SIGNALED; | 586 | send_wr.send_flags = IB_SEND_SIGNALED; |
540 | 587 | ||
541 | ret = svc_rdma_send(rdma, &send_wr); | 588 | ret = svc_rdma_send(rdma, &send_wr); |
@@ -567,6 +614,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) | |||
567 | int inline_bytes; | 614 | int inline_bytes; |
568 | struct page *res_page; | 615 | struct page *res_page; |
569 | struct svc_rdma_req_map *vec; | 616 | struct svc_rdma_req_map *vec; |
617 | u32 inv_rkey; | ||
570 | 618 | ||
571 | dprintk("svcrdma: sending response for rqstp=%p\n", rqstp); | 619 | dprintk("svcrdma: sending response for rqstp=%p\n", rqstp); |
572 | 620 | ||
@@ -577,6 +625,10 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) | |||
577 | wr_ary = svc_rdma_get_write_array(rdma_argp); | 625 | wr_ary = svc_rdma_get_write_array(rdma_argp); |
578 | rp_ary = svc_rdma_get_reply_array(rdma_argp, wr_ary); | 626 | rp_ary = svc_rdma_get_reply_array(rdma_argp, wr_ary); |
579 | 627 | ||
628 | inv_rkey = 0; | ||
629 | if (rdma->sc_snd_w_inv) | ||
630 | inv_rkey = svc_rdma_get_inv_rkey(rdma_argp, wr_ary, rp_ary); | ||
631 | |||
580 | /* Build an req vec for the XDR */ | 632 | /* Build an req vec for the XDR */ |
581 | vec = svc_rdma_get_req_map(rdma); | 633 | vec = svc_rdma_get_req_map(rdma); |
582 | ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec, wr_ary != NULL); | 634 | ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec, wr_ary != NULL); |
@@ -619,7 +671,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) | |||
619 | goto err1; | 671 | goto err1; |
620 | 672 | ||
621 | ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec, | 673 | ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec, |
622 | inline_bytes); | 674 | inline_bytes, inv_rkey); |
623 | if (ret < 0) | 675 | if (ret < 0) |
624 | goto err0; | 676 | goto err0; |
625 | 677 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index f51e98a25263..b2464fc4c455 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -657,9 +657,14 @@ svc_rdma_parse_connect_private(struct svcxprt_rdma *newxprt, | |||
657 | if (pmsg && | 657 | if (pmsg && |
658 | pmsg->cp_magic == rpcrdma_cmp_magic && | 658 | pmsg->cp_magic == rpcrdma_cmp_magic && |
659 | pmsg->cp_version == RPCRDMA_CMP_VERSION) { | 659 | pmsg->cp_version == RPCRDMA_CMP_VERSION) { |
660 | dprintk("svcrdma: client send_size %u, recv_size %u\n", | 660 | newxprt->sc_snd_w_inv = pmsg->cp_flags & |
661 | RPCRDMA_CMP_F_SND_W_INV_OK; | ||
662 | |||
663 | dprintk("svcrdma: client send_size %u, recv_size %u " | ||
664 | "remote inv %ssupported\n", | ||
661 | rpcrdma_decode_buffer_size(pmsg->cp_send_size), | 665 | rpcrdma_decode_buffer_size(pmsg->cp_send_size), |
662 | rpcrdma_decode_buffer_size(pmsg->cp_recv_size)); | 666 | rpcrdma_decode_buffer_size(pmsg->cp_recv_size), |
667 | newxprt->sc_snd_w_inv ? "" : "un"); | ||
663 | } | 668 | } |
664 | } | 669 | } |
665 | 670 | ||
@@ -1093,7 +1098,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
1093 | dev->attrs.max_fast_reg_page_list_len; | 1098 | dev->attrs.max_fast_reg_page_list_len; |
1094 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_FAST_REG; | 1099 | newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_FAST_REG; |
1095 | newxprt->sc_reader = rdma_read_chunk_frmr; | 1100 | newxprt->sc_reader = rdma_read_chunk_frmr; |
1096 | } | 1101 | } else |
1102 | newxprt->sc_snd_w_inv = false; | ||
1097 | 1103 | ||
1098 | /* | 1104 | /* |
1099 | * Determine if a DMA MR is required and if so, what privs are required | 1105 | * Determine if a DMA MR is required and if so, what privs are required |