Skip to content

Commit d2727ce

Browse files
committed
svcrdma: Post WRs for Write chunks in svc_rdma_sendto()
Refactor to eventually enable svcrdma to post the Write WRs for each RPC response using the same ib_post_send() as the Send WR (ie, as a single WR chain). svc_rdma_result_payload (originally svc_rdma_read_payload) was added so that the upper layer XDR encoder could identify a range of bytes to be possibly conveyed by RDMA (if a Write chunk was provided by the client). The purpose of commit f6ad775 ("svcrdma: Post RDMA Writes while XDR encoding replies") was to post as much of the result payload outside of svc_rdma_sendto() as possible because svc_rdma_sendto() used to be called with the xpt_mutex held. However, since commit ca4faf5 ("SUNRPC: Move xpt_mutex into socket xpo_sendto methods"), the xpt_mutex is no longer held when calling svc_rdma_sendto(). Thus, that benefit is no longer an issue. Signed-off-by: Chuck Lever <[email protected]>
1 parent 10e6fc1 commit d2727ce

File tree

3 files changed

+51
-41
lines changed

3 files changed

+51
-41
lines changed

include/linux/sunrpc/svc_rdma.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,9 @@ extern void svc_rdma_cc_release(struct svcxprt_rdma *rdma,
272272
enum dma_data_direction dir);
273273
extern void svc_rdma_reply_chunk_release(struct svcxprt_rdma *rdma,
274274
struct svc_rdma_send_ctxt *ctxt);
275-
extern int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
276-
const struct svc_rdma_chunk *chunk,
277-
const struct xdr_buf *xdr);
275+
extern int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
276+
const struct svc_rdma_recv_ctxt *rctxt,
277+
const struct xdr_buf *xdr);
278278
extern int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma,
279279
const struct svc_rdma_pcl *write_pcl,
280280
const struct svc_rdma_pcl *reply_pcl,

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -601,47 +601,65 @@ static int svc_rdma_xb_write(const struct xdr_buf *xdr, void *data)
601601
return xdr->len;
602602
}
603603

604-
/**
605-
* svc_rdma_send_write_chunk - Write all segments in a Write chunk
606-
* @rdma: controlling RDMA transport
607-
* @chunk: Write chunk provided by the client
608-
* @xdr: xdr_buf containing the data payload
609-
*
610-
* Returns a non-negative number of bytes the chunk consumed, or
611-
* %-E2BIG if the payload was larger than the Write chunk,
612-
* %-EINVAL if client provided too many segments,
613-
* %-ENOMEM if rdma_rw context pool was exhausted,
614-
* %-ENOTCONN if posting failed (connection is lost),
615-
* %-EIO if rdma_rw initialization failed (DMA mapping, etc).
616-
*/
617-
int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
618-
const struct svc_rdma_chunk *chunk,
619-
const struct xdr_buf *xdr)
604+
static int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
605+
const struct svc_rdma_chunk *chunk,
606+
const struct xdr_buf *xdr)
620607
{
621608
struct svc_rdma_write_info *info;
622609
struct svc_rdma_chunk_ctxt *cc;
610+
struct xdr_buf payload;
623611
int ret;
624612

613+
if (xdr_buf_subsegment(xdr, &payload, chunk->ch_position,
614+
chunk->ch_payload_length))
615+
return -EMSGSIZE;
616+
625617
info = svc_rdma_write_info_alloc(rdma, chunk);
626618
if (!info)
627619
return -ENOMEM;
628620
cc = &info->wi_cc;
629621

630-
ret = svc_rdma_xb_write(xdr, info);
631-
if (ret != xdr->len)
622+
ret = svc_rdma_xb_write(&payload, info);
623+
if (ret != payload.len)
632624
goto out_err;
633625

634626
trace_svcrdma_post_write_chunk(&cc->cc_cid, cc->cc_sqecount);
635627
ret = svc_rdma_post_chunk_ctxt(rdma, cc);
636628
if (ret < 0)
637629
goto out_err;
638-
return xdr->len;
630+
return 0;
639631

640632
out_err:
641633
svc_rdma_write_info_free(info);
642634
return ret;
643635
}
644636

637+
/**
638+
* svc_rdma_send_write_list - Send all chunks on the Write list
639+
* @rdma: controlling RDMA transport
640+
* @rctxt: Write list provisioned by the client
641+
* @xdr: xdr_buf containing an RPC Reply message
642+
*
643+
* Returns zero on success, or a negative errno if one or more
644+
* Write chunks could not be sent.
645+
*/
646+
int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
647+
const struct svc_rdma_recv_ctxt *rctxt,
648+
const struct xdr_buf *xdr)
649+
{
650+
struct svc_rdma_chunk *chunk;
651+
int ret;
652+
653+
pcl_for_each_chunk(chunk, &rctxt->rc_write_pcl) {
654+
if (!chunk->ch_payload_length)
655+
break;
656+
ret = svc_rdma_send_write_chunk(rdma, chunk, xdr);
657+
if (ret < 0)
658+
return ret;
659+
}
660+
return 0;
661+
}
662+
645663
/**
646664
* svc_rdma_prepare_reply_chunk - Construct WR chain for writing the Reply chunk
647665
* @rdma: controlling RDMA transport

net/sunrpc/xprtrdma/svc_rdma_sendto.c

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,10 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
10131013
if (!p)
10141014
goto put_ctxt;
10151015

1016+
ret = svc_rdma_send_write_list(rdma, rctxt, &rqstp->rq_res);
1017+
if (ret < 0)
1018+
goto put_ctxt;
1019+
10161020
rc_size = 0;
10171021
if (!pcl_is_empty(&rctxt->rc_reply_pcl)) {
10181022
ret = svc_rdma_prepare_reply_chunk(rdma, &rctxt->rc_write_pcl,
@@ -1064,45 +1068,33 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
10641068

10651069
/**
10661070
* svc_rdma_result_payload - special processing for a result payload
1067-
* @rqstp: svc_rqst to operate on
1068-
* @offset: payload's byte offset in @xdr
1071+
* @rqstp: RPC transaction context
1072+
* @offset: payload's byte offset in @rqstp->rq_res
10691073
* @length: size of payload, in bytes
10701074
*
1075+
* Assign the passed-in result payload to the current Write chunk,
1076+
* and advance to cur_result_payload to the next Write chunk, if
1077+
* there is one.
1078+
*
10711079
* Return values:
10721080
* %0 if successful or nothing needed to be done
1073-
* %-EMSGSIZE on XDR buffer overflow
10741081
* %-E2BIG if the payload was larger than the Write chunk
1075-
* %-EINVAL if client provided too many segments
1076-
* %-ENOMEM if rdma_rw context pool was exhausted
1077-
* %-ENOTCONN if posting failed (connection is lost)
1078-
* %-EIO if rdma_rw initialization failed (DMA mapping, etc)
10791082
*/
10801083
int svc_rdma_result_payload(struct svc_rqst *rqstp, unsigned int offset,
10811084
unsigned int length)
10821085
{
10831086
struct svc_rdma_recv_ctxt *rctxt = rqstp->rq_xprt_ctxt;
10841087
struct svc_rdma_chunk *chunk;
1085-
struct svcxprt_rdma *rdma;
1086-
struct xdr_buf subbuf;
1087-
int ret;
10881088

10891089
chunk = rctxt->rc_cur_result_payload;
10901090
if (!length || !chunk)
10911091
return 0;
10921092
rctxt->rc_cur_result_payload =
10931093
pcl_next_chunk(&rctxt->rc_write_pcl, chunk);
1094+
10941095
if (length > chunk->ch_length)
10951096
return -E2BIG;
1096-
10971097
chunk->ch_position = offset;
10981098
chunk->ch_payload_length = length;
1099-
1100-
if (xdr_buf_subsegment(&rqstp->rq_res, &subbuf, offset, length))
1101-
return -EMSGSIZE;
1102-
1103-
rdma = container_of(rqstp->rq_xprt, struct svcxprt_rdma, sc_xprt);
1104-
ret = svc_rdma_send_write_chunk(rdma, chunk, &subbuf);
1105-
if (ret < 0)
1106-
return ret;
11071099
return 0;
11081100
}

0 commit comments

Comments
 (0)