aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2018-05-07 15:28:25 -0400
committerJ. Bruce Fields <bfields@redhat.com>2018-05-11 15:48:57 -0400
commit99722fe4d5a634707ced8d8f42b883b87a86b3c5 (patch)
treebc89587516be20f4c18330e63c28f087d8749896
parent3abb03facee06ea052be6e3a435f6dbb4e54fc04 (diff)
svcrdma: Persistently allocate and DMA-map Send buffers
While sending each RPC Reply, svc_rdma_sendto allocates and DMA- maps a separate buffer where the RPC/RDMA transport header is constructed. The buffer is unmapped and released in the Send completion handler. This is significant per-RPC overhead, especially for small RPCs. Instead, allocate and DMA-map a buffer, and cache it in each svc_rdma_send_ctxt. This buffer and its mapping can be re-used for each RPC, saving the cost of memory allocation and DMA mapping. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--include/linux/sunrpc/svc_rdma.h8
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_backchannel.c51
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c25
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c149
4 files changed, 105 insertions, 128 deletions
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h
index a8bfc214614b..96b14a72d359 100644
--- a/include/linux/sunrpc/svc_rdma.h
+++ b/include/linux/sunrpc/svc_rdma.h
@@ -162,6 +162,7 @@ struct svc_rdma_send_ctxt {
162 struct list_head sc_list; 162 struct list_head sc_list;
163 struct ib_send_wr sc_send_wr; 163 struct ib_send_wr sc_send_wr;
164 struct ib_cqe sc_cqe; 164 struct ib_cqe sc_cqe;
165 void *sc_xprt_buf;
165 int sc_page_count; 166 int sc_page_count;
166 int sc_cur_sge_no; 167 int sc_cur_sge_no;
167 struct page *sc_pages[RPCSVC_MAXPAGES]; 168 struct page *sc_pages[RPCSVC_MAXPAGES];
@@ -199,9 +200,12 @@ extern struct svc_rdma_send_ctxt *
199extern void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma, 200extern void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma,
200 struct svc_rdma_send_ctxt *ctxt); 201 struct svc_rdma_send_ctxt *ctxt);
201extern int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr); 202extern int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr);
202extern int svc_rdma_map_reply_hdr(struct svcxprt_rdma *rdma, 203extern void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
204 struct svc_rdma_send_ctxt *ctxt,
205 unsigned int len);
206extern int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
203 struct svc_rdma_send_ctxt *ctxt, 207 struct svc_rdma_send_ctxt *ctxt,
204 __be32 *rdma_resp, unsigned int len); 208 struct xdr_buf *xdr, __be32 *wr_lst);
205extern int svc_rdma_sendto(struct svc_rqst *); 209extern int svc_rdma_sendto(struct svc_rqst *);
206 210
207/* svc_rdma_transport.c */ 211/* svc_rdma_transport.c */
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
index 40f5e4afbcc8..343e7add672c 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
@@ -115,43 +115,21 @@ out_notfound:
115 * the adapter has a small maximum SQ depth. 115 * the adapter has a small maximum SQ depth.
116 */ 116 */
117static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma, 117static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma,
118 struct rpc_rqst *rqst) 118 struct rpc_rqst *rqst,
119 struct svc_rdma_send_ctxt *ctxt)
119{ 120{
120 struct svc_rdma_send_ctxt *ctxt;
121 int ret; 121 int ret;
122 122
123 ctxt = svc_rdma_send_ctxt_get(rdma); 123 ret = svc_rdma_map_reply_msg(rdma, ctxt, &rqst->rq_snd_buf, NULL);
124 if (!ctxt) {
125 ret = -ENOMEM;
126 goto out_err;
127 }
128
129 /* rpcrdma_bc_send_request builds the transport header and
130 * the backchannel RPC message in the same buffer. Thus only
131 * one SGE is needed to send both.
132 */
133 ret = svc_rdma_map_reply_hdr(rdma, ctxt, rqst->rq_buffer,
134 rqst->rq_snd_buf.len);
135 if (ret < 0) 124 if (ret < 0)
136 goto out_err; 125 return -EIO;
137 126
138 /* Bump page refcnt so Send completion doesn't release 127 /* Bump page refcnt so Send completion doesn't release
139 * the rq_buffer before all retransmits are complete. 128 * the rq_buffer before all retransmits are complete.
140 */ 129 */
141 get_page(virt_to_page(rqst->rq_buffer)); 130 get_page(virt_to_page(rqst->rq_buffer));
142 ctxt->sc_send_wr.opcode = IB_WR_SEND; 131 ctxt->sc_send_wr.opcode = IB_WR_SEND;
143 ret = svc_rdma_send(rdma, &ctxt->sc_send_wr); 132 return svc_rdma_send(rdma, &ctxt->sc_send_wr);
144 if (ret)
145 goto out_unmap;
146
147out_err:
148 dprintk("svcrdma: %s returns %d\n", __func__, ret);
149 return ret;
150
151out_unmap:
152 svc_rdma_send_ctxt_put(rdma, ctxt);
153 ret = -EIO;
154 goto out_err;
155} 133}
156 134
157/* Server-side transport endpoint wants a whole page for its send 135/* Server-side transport endpoint wants a whole page for its send
@@ -198,13 +176,15 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst)
198{ 176{
199 struct rpc_xprt *xprt = rqst->rq_xprt; 177 struct rpc_xprt *xprt = rqst->rq_xprt;
200 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); 178 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
179 struct svc_rdma_send_ctxt *ctxt;
201 __be32 *p; 180 __be32 *p;
202 int rc; 181 int rc;
203 182
204 /* Space in the send buffer for an RPC/RDMA header is reserved 183 ctxt = svc_rdma_send_ctxt_get(rdma);
205 * via xprt->tsh_size. 184 if (!ctxt)
206 */ 185 goto drop_connection;
207 p = rqst->rq_buffer; 186
187 p = ctxt->sc_xprt_buf;
208 *p++ = rqst->rq_xid; 188 *p++ = rqst->rq_xid;
209 *p++ = rpcrdma_version; 189 *p++ = rpcrdma_version;
210 *p++ = cpu_to_be32(r_xprt->rx_buf.rb_bc_max_requests); 190 *p++ = cpu_to_be32(r_xprt->rx_buf.rb_bc_max_requests);
@@ -212,14 +192,17 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst)
212 *p++ = xdr_zero; 192 *p++ = xdr_zero;
213 *p++ = xdr_zero; 193 *p++ = xdr_zero;
214 *p = xdr_zero; 194 *p = xdr_zero;
195 svc_rdma_sync_reply_hdr(rdma, ctxt, RPCRDMA_HDRLEN_MIN);
215 196
216#ifdef SVCRDMA_BACKCHANNEL_DEBUG 197#ifdef SVCRDMA_BACKCHANNEL_DEBUG
217 pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer); 198 pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer);
218#endif 199#endif
219 200
220 rc = svc_rdma_bc_sendto(rdma, rqst); 201 rc = svc_rdma_bc_sendto(rdma, rqst, ctxt);
221 if (rc) 202 if (rc) {
203 svc_rdma_send_ctxt_put(rdma, ctxt);
222 goto drop_connection; 204 goto drop_connection;
205 }
223 return rc; 206 return rc;
224 207
225drop_connection: 208drop_connection:
@@ -327,7 +310,7 @@ xprt_setup_rdma_bc(struct xprt_create *args)
327 xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; 310 xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO;
328 311
329 xprt->prot = XPRT_TRANSPORT_BC_RDMA; 312 xprt->prot = XPRT_TRANSPORT_BC_RDMA;
330 xprt->tsh_size = RPCRDMA_HDRLEN_MIN / sizeof(__be32); 313 xprt->tsh_size = 0;
331 xprt->ops = &xprt_rdma_bc_procs; 314 xprt->ops = &xprt_rdma_bc_procs;
332 315
333 memcpy(&xprt->addr, args->dstaddr, args->addrlen); 316 memcpy(&xprt->addr, args->dstaddr, args->addrlen);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 68648e6c5be2..09ce09b3ac6e 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -602,17 +602,15 @@ static void svc_rdma_send_error(struct svcxprt_rdma *xprt,
602 __be32 *rdma_argp, int status) 602 __be32 *rdma_argp, int status)
603{ 603{
604 struct svc_rdma_send_ctxt *ctxt; 604 struct svc_rdma_send_ctxt *ctxt;
605 __be32 *p, *err_msgp;
606 unsigned int length; 605 unsigned int length;
607 struct page *page; 606 __be32 *p;
608 int ret; 607 int ret;
609 608
610 page = alloc_page(GFP_KERNEL); 609 ctxt = svc_rdma_send_ctxt_get(xprt);
611 if (!page) 610 if (!ctxt)
612 return; 611 return;
613 err_msgp = page_address(page);
614 612
615 p = err_msgp; 613 p = ctxt->sc_xprt_buf;
616 *p++ = *rdma_argp; 614 *p++ = *rdma_argp;
617 *p++ = *(rdma_argp + 1); 615 *p++ = *(rdma_argp + 1);
618 *p++ = xprt->sc_fc_credits; 616 *p++ = xprt->sc_fc_credits;
@@ -628,19 +626,8 @@ static void svc_rdma_send_error(struct svcxprt_rdma *xprt,
628 *p++ = err_chunk; 626 *p++ = err_chunk;
629 trace_svcrdma_err_chunk(*rdma_argp); 627 trace_svcrdma_err_chunk(*rdma_argp);
630 } 628 }
631 length = (unsigned long)p - (unsigned long)err_msgp; 629 length = (unsigned long)p - (unsigned long)ctxt->sc_xprt_buf;
632 630 svc_rdma_sync_reply_hdr(xprt, ctxt, length);
633 /* Map transport header; no RPC message payload */
634 ctxt = svc_rdma_send_ctxt_get(xprt);
635 if (!ctxt)
636 return;
637
638 ret = svc_rdma_map_reply_hdr(xprt, ctxt, err_msgp, length);
639 if (ret) {
640 dprintk("svcrdma: Error %d mapping send for protocol error\n",
641 ret);
642 return;
643 }
644 631
645 ctxt->sc_send_wr.opcode = IB_WR_SEND; 632 ctxt->sc_send_wr.opcode = IB_WR_SEND;
646 ret = svc_rdma_send(xprt, &ctxt->sc_send_wr); 633 ret = svc_rdma_send(xprt, &ctxt->sc_send_wr);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index edfeca45ac1c..4a3efaea277c 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -127,6 +127,8 @@ static struct svc_rdma_send_ctxt *
127svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma) 127svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma)
128{ 128{
129 struct svc_rdma_send_ctxt *ctxt; 129 struct svc_rdma_send_ctxt *ctxt;
130 dma_addr_t addr;
131 void *buffer;
130 size_t size; 132 size_t size;
131 int i; 133 int i;
132 134
@@ -134,16 +136,33 @@ svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma)
134 size += rdma->sc_max_send_sges * sizeof(struct ib_sge); 136 size += rdma->sc_max_send_sges * sizeof(struct ib_sge);
135 ctxt = kmalloc(size, GFP_KERNEL); 137 ctxt = kmalloc(size, GFP_KERNEL);
136 if (!ctxt) 138 if (!ctxt)
137 return NULL; 139 goto fail0;
140 buffer = kmalloc(rdma->sc_max_req_size, GFP_KERNEL);
141 if (!buffer)
142 goto fail1;
143 addr = ib_dma_map_single(rdma->sc_pd->device, buffer,
144 rdma->sc_max_req_size, DMA_TO_DEVICE);
145 if (ib_dma_mapping_error(rdma->sc_pd->device, addr))
146 goto fail2;
138 147
139 ctxt->sc_cqe.done = svc_rdma_wc_send;
140 ctxt->sc_send_wr.next = NULL; 148 ctxt->sc_send_wr.next = NULL;
141 ctxt->sc_send_wr.wr_cqe = &ctxt->sc_cqe; 149 ctxt->sc_send_wr.wr_cqe = &ctxt->sc_cqe;
142 ctxt->sc_send_wr.sg_list = ctxt->sc_sges; 150 ctxt->sc_send_wr.sg_list = ctxt->sc_sges;
143 ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED; 151 ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED;
152 ctxt->sc_cqe.done = svc_rdma_wc_send;
153 ctxt->sc_xprt_buf = buffer;
154 ctxt->sc_sges[0].addr = addr;
155
144 for (i = 0; i < rdma->sc_max_send_sges; i++) 156 for (i = 0; i < rdma->sc_max_send_sges; i++)
145 ctxt->sc_sges[i].lkey = rdma->sc_pd->local_dma_lkey; 157 ctxt->sc_sges[i].lkey = rdma->sc_pd->local_dma_lkey;
146 return ctxt; 158 return ctxt;
159
160fail2:
161 kfree(buffer);
162fail1:
163 kfree(ctxt);
164fail0:
165 return NULL;
147} 166}
148 167
149/** 168/**
@@ -157,6 +176,11 @@ void svc_rdma_send_ctxts_destroy(struct svcxprt_rdma *rdma)
157 176
158 while ((ctxt = svc_rdma_next_send_ctxt(&rdma->sc_send_ctxts))) { 177 while ((ctxt = svc_rdma_next_send_ctxt(&rdma->sc_send_ctxts))) {
159 list_del(&ctxt->sc_list); 178 list_del(&ctxt->sc_list);
179 ib_dma_unmap_single(rdma->sc_pd->device,
180 ctxt->sc_sges[0].addr,
181 rdma->sc_max_req_size,
182 DMA_TO_DEVICE);
183 kfree(ctxt->sc_xprt_buf);
160 kfree(ctxt); 184 kfree(ctxt);
161 } 185 }
162} 186}
@@ -181,6 +205,7 @@ struct svc_rdma_send_ctxt *svc_rdma_send_ctxt_get(struct svcxprt_rdma *rdma)
181 205
182out: 206out:
183 ctxt->sc_send_wr.num_sge = 0; 207 ctxt->sc_send_wr.num_sge = 0;
208 ctxt->sc_cur_sge_no = 0;
184 ctxt->sc_page_count = 0; 209 ctxt->sc_page_count = 0;
185 return ctxt; 210 return ctxt;
186 211
@@ -205,7 +230,10 @@ void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma,
205 struct ib_device *device = rdma->sc_cm_id->device; 230 struct ib_device *device = rdma->sc_cm_id->device;
206 unsigned int i; 231 unsigned int i;
207 232
208 for (i = 0; i < ctxt->sc_send_wr.num_sge; i++) 233 /* The first SGE contains the transport header, which
234 * remains mapped until @ctxt is destroyed.
235 */
236 for (i = 1; i < ctxt->sc_send_wr.num_sge; i++)
209 ib_dma_unmap_page(device, 237 ib_dma_unmap_page(device,
210 ctxt->sc_sges[i].addr, 238 ctxt->sc_sges[i].addr,
211 ctxt->sc_sges[i].length, 239 ctxt->sc_sges[i].length,
@@ -519,35 +547,37 @@ static int svc_rdma_dma_map_buf(struct svcxprt_rdma *rdma,
519} 547}
520 548
521/** 549/**
522 * svc_rdma_map_reply_hdr - DMA map the transport header buffer 550 * svc_rdma_sync_reply_hdr - DMA sync the transport header buffer
523 * @rdma: controlling transport 551 * @rdma: controlling transport
524 * @ctxt: op_ctxt for the Send WR 552 * @ctxt: send_ctxt for the Send WR
525 * @rdma_resp: buffer containing transport header
526 * @len: length of transport header 553 * @len: length of transport header
527 * 554 *
528 * Returns:
529 * %0 if the header is DMA mapped,
530 * %-EIO if DMA mapping failed.
531 */ 555 */
532int svc_rdma_map_reply_hdr(struct svcxprt_rdma *rdma, 556void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
533 struct svc_rdma_send_ctxt *ctxt, 557 struct svc_rdma_send_ctxt *ctxt,
534 __be32 *rdma_resp, 558 unsigned int len)
535 unsigned int len)
536{ 559{
537 ctxt->sc_pages[0] = virt_to_page(rdma_resp); 560 ctxt->sc_sges[0].length = len;
538 ctxt->sc_page_count++; 561 ctxt->sc_send_wr.num_sge++;
539 ctxt->sc_cur_sge_no = 0; 562 ib_dma_sync_single_for_device(rdma->sc_pd->device,
540 return svc_rdma_dma_map_page(rdma, ctxt, ctxt->sc_pages[0], 0, len); 563 ctxt->sc_sges[0].addr, len,
564 DMA_TO_DEVICE);
541} 565}
542 566
543/* Load the xdr_buf into the ctxt's sge array, and DMA map each 567/* svc_rdma_map_reply_msg - Map the buffer holding RPC message
568 * @rdma: controlling transport
569 * @ctxt: send_ctxt for the Send WR
570 * @xdr: prepared xdr_buf containing RPC message
571 * @wr_lst: pointer to Call header's Write list, or NULL
572 *
573 * Load the xdr_buf into the ctxt's sge array, and DMA map each
544 * element as it is added. 574 * element as it is added.
545 * 575 *
546 * Returns zero on success, or a negative errno on failure. 576 * Returns zero on success, or a negative errno on failure.
547 */ 577 */
548static int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma, 578int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
549 struct svc_rdma_send_ctxt *ctxt, 579 struct svc_rdma_send_ctxt *ctxt,
550 struct xdr_buf *xdr, __be32 *wr_lst) 580 struct xdr_buf *xdr, __be32 *wr_lst)
551{ 581{
552 unsigned int len, remaining; 582 unsigned int len, remaining;
553 unsigned long page_off; 583 unsigned long page_off;
@@ -624,7 +654,7 @@ static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
624 654
625 ctxt->sc_page_count += pages; 655 ctxt->sc_page_count += pages;
626 for (i = 0; i < pages; i++) { 656 for (i = 0; i < pages; i++) {
627 ctxt->sc_pages[i + 1] = rqstp->rq_respages[i]; 657 ctxt->sc_pages[i] = rqstp->rq_respages[i];
628 rqstp->rq_respages[i] = NULL; 658 rqstp->rq_respages[i] = NULL;
629 } 659 }
630 rqstp->rq_next_page = rqstp->rq_respages + 1; 660 rqstp->rq_next_page = rqstp->rq_respages + 1;
@@ -649,27 +679,18 @@ static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
649 * - The Reply's transport header will never be larger than a page. 679 * - The Reply's transport header will never be larger than a page.
650 */ 680 */
651static int svc_rdma_send_reply_msg(struct svcxprt_rdma *rdma, 681static int svc_rdma_send_reply_msg(struct svcxprt_rdma *rdma,
652 __be32 *rdma_argp, __be32 *rdma_resp, 682 struct svc_rdma_send_ctxt *ctxt,
683 __be32 *rdma_argp,
653 struct svc_rqst *rqstp, 684 struct svc_rqst *rqstp,
654 __be32 *wr_lst, __be32 *rp_ch) 685 __be32 *wr_lst, __be32 *rp_ch)
655{ 686{
656 struct svc_rdma_send_ctxt *ctxt;
657 int ret; 687 int ret;
658 688
659 ctxt = svc_rdma_send_ctxt_get(rdma);
660 if (!ctxt)
661 return -ENOMEM;
662
663 ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp,
664 svc_rdma_reply_hdr_len(rdma_resp));
665 if (ret < 0)
666 goto err;
667
668 if (!rp_ch) { 689 if (!rp_ch) {
669 ret = svc_rdma_map_reply_msg(rdma, ctxt, 690 ret = svc_rdma_map_reply_msg(rdma, ctxt,
670 &rqstp->rq_res, wr_lst); 691 &rqstp->rq_res, wr_lst);
671 if (ret < 0) 692 if (ret < 0)
672 goto err; 693 return ret;
673 } 694 }
674 695
675 svc_rdma_save_io_pages(rqstp, ctxt); 696 svc_rdma_save_io_pages(rqstp, ctxt);
@@ -683,15 +704,7 @@ static int svc_rdma_send_reply_msg(struct svcxprt_rdma *rdma,
683 } 704 }
684 dprintk("svcrdma: posting Send WR with %u sge(s)\n", 705 dprintk("svcrdma: posting Send WR with %u sge(s)\n",
685 ctxt->sc_send_wr.num_sge); 706 ctxt->sc_send_wr.num_sge);
686 ret = svc_rdma_send(rdma, &ctxt->sc_send_wr); 707 return svc_rdma_send(rdma, &ctxt->sc_send_wr);
687 if (ret)
688 goto err;
689
690 return 0;
691
692err:
693 svc_rdma_send_ctxt_put(rdma, ctxt);
694 return ret;
695} 708}
696 709
697/* Given the client-provided Write and Reply chunks, the server was not 710/* Given the client-provided Write and Reply chunks, the server was not
@@ -702,40 +715,29 @@ err:
702 * Remote Invalidation is skipped for simplicity. 715 * Remote Invalidation is skipped for simplicity.
703 */ 716 */
704static int svc_rdma_send_error_msg(struct svcxprt_rdma *rdma, 717static int svc_rdma_send_error_msg(struct svcxprt_rdma *rdma,
705 __be32 *rdma_resp, struct svc_rqst *rqstp) 718 struct svc_rdma_send_ctxt *ctxt,
719 struct svc_rqst *rqstp)
706{ 720{
707 struct svc_rdma_send_ctxt *ctxt;
708 __be32 *p; 721 __be32 *p;
709 int ret; 722 int ret;
710 723
711 ctxt = svc_rdma_send_ctxt_get(rdma); 724 p = ctxt->sc_xprt_buf;
712 if (!ctxt) 725 trace_svcrdma_err_chunk(*p);
713 return -ENOMEM; 726 p += 3;
714
715 /* Replace the original transport header with an
716 * RDMA_ERROR response. XID etc are preserved.
717 */
718 trace_svcrdma_err_chunk(*rdma_resp);
719 p = rdma_resp + 3;
720 *p++ = rdma_error; 727 *p++ = rdma_error;
721 *p = err_chunk; 728 *p = err_chunk;
722 729 svc_rdma_sync_reply_hdr(rdma, ctxt, RPCRDMA_HDRLEN_ERR);
723 ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp, 20);
724 if (ret < 0)
725 goto err;
726 730
727 svc_rdma_save_io_pages(rqstp, ctxt); 731 svc_rdma_save_io_pages(rqstp, ctxt);
728 732
729 ctxt->sc_send_wr.opcode = IB_WR_SEND; 733 ctxt->sc_send_wr.opcode = IB_WR_SEND;
730 ret = svc_rdma_send(rdma, &ctxt->sc_send_wr); 734 ret = svc_rdma_send(rdma, &ctxt->sc_send_wr);
731 if (ret) 735 if (ret) {
732 goto err; 736 svc_rdma_send_ctxt_put(rdma, ctxt);
737 return ret;
738 }
733 739
734 return 0; 740 return 0;
735
736err:
737 svc_rdma_send_ctxt_put(rdma, ctxt);
738 return ret;
739} 741}
740 742
741void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp) 743void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp)
@@ -762,7 +764,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
762 struct svc_rdma_recv_ctxt *rctxt = rqstp->rq_xprt_ctxt; 764 struct svc_rdma_recv_ctxt *rctxt = rqstp->rq_xprt_ctxt;
763 __be32 *p, *rdma_argp, *rdma_resp, *wr_lst, *rp_ch; 765 __be32 *p, *rdma_argp, *rdma_resp, *wr_lst, *rp_ch;
764 struct xdr_buf *xdr = &rqstp->rq_res; 766 struct xdr_buf *xdr = &rqstp->rq_res;
765 struct page *res_page; 767 struct svc_rdma_send_ctxt *sctxt;
766 int ret; 768 int ret;
767 769
768 rdma_argp = rctxt->rc_recv_buf; 770 rdma_argp = rctxt->rc_recv_buf;
@@ -775,10 +777,10 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
775 * critical section. 777 * critical section.
776 */ 778 */
777 ret = -ENOMEM; 779 ret = -ENOMEM;
778 res_page = alloc_page(GFP_KERNEL); 780 sctxt = svc_rdma_send_ctxt_get(rdma);
779 if (!res_page) 781 if (!sctxt)
780 goto err0; 782 goto err0;
781 rdma_resp = page_address(res_page); 783 rdma_resp = sctxt->sc_xprt_buf;
782 784
783 p = rdma_resp; 785 p = rdma_resp;
784 *p++ = *rdma_argp; 786 *p++ = *rdma_argp;
@@ -805,10 +807,11 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
805 svc_rdma_xdr_encode_reply_chunk(rdma_resp, rp_ch, ret); 807 svc_rdma_xdr_encode_reply_chunk(rdma_resp, rp_ch, ret);
806 } 808 }
807 809
808 ret = svc_rdma_send_reply_msg(rdma, rdma_argp, rdma_resp, rqstp, 810 svc_rdma_sync_reply_hdr(rdma, sctxt, svc_rdma_reply_hdr_len(rdma_resp));
811 ret = svc_rdma_send_reply_msg(rdma, sctxt, rdma_argp, rqstp,
809 wr_lst, rp_ch); 812 wr_lst, rp_ch);
810 if (ret < 0) 813 if (ret < 0)
811 goto err0; 814 goto err1;
812 ret = 0; 815 ret = 0;
813 816
814out: 817out:
@@ -820,14 +823,14 @@ out:
820 if (ret != -E2BIG && ret != -EINVAL) 823 if (ret != -E2BIG && ret != -EINVAL)
821 goto err1; 824 goto err1;
822 825
823 ret = svc_rdma_send_error_msg(rdma, rdma_resp, rqstp); 826 ret = svc_rdma_send_error_msg(rdma, sctxt, rqstp);
824 if (ret < 0) 827 if (ret < 0)
825 goto err0; 828 goto err1;
826 ret = 0; 829 ret = 0;
827 goto out; 830 goto out;
828 831
829 err1: 832 err1:
830 put_page(res_page); 833 svc_rdma_send_ctxt_put(rdma, sctxt);
831 err0: 834 err0:
832 trace_svcrdma_send_failed(rqstp, ret); 835 trace_svcrdma_send_failed(rqstp, ret);
833 set_bit(XPT_CLOSE, &xprt->xpt_flags); 836 set_bit(XPT_CLOSE, &xprt->xpt_flags);