Skip to content

Commit ecba85e

Browse files
committed
svcrdma: Copy construction of svc_rqst::rq_arg to rdma_read_complete()
Once a set of RDMA Reads are complete, the Read completion handler will poke the transport to trigger a second call to svc_rdma_recvfrom(). recvfrom() will then merge the RDMA Read payloads with the previously received RPC header to form a completed RPC Call message. The new code is copied from the svc_rdma_process_read_list() path. A subsequent patch will make use of this code and remove the code that this was copied from (svc_rdma_rw.c). Signed-off-by: Chuck Lever <[email protected]>
1 parent a937693 commit ecba85e

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

include/trace/events/rpcrdma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,7 @@ TRACE_EVENT(svcrdma_wc_read,
21122112

21132113
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_read_flush);
21142114
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_read_err);
2115+
DEFINE_SIMPLE_CID_EVENT(svcrdma_read_finished);
21152116

21162117
DEFINE_SIMPLE_CID_EVENT(svcrdma_wc_write);
21172118
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_write_flush);

net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,10 +767,86 @@ static bool svc_rdma_is_reverse_direction_reply(struct svc_xprt *xprt,
767767
return true;
768768
}
769769

770+
/* Finish constructing the RPC Call message in rqstp::rq_arg.
771+
*
772+
* The incoming RPC/RDMA message is an RDMA_MSG type message
773+
* with a single Read chunk (only the upper layer data payload
774+
* was conveyed via RDMA Read).
775+
*/
776+
static void svc_rdma_read_complete_one(struct svc_rqst *rqstp,
777+
struct svc_rdma_recv_ctxt *ctxt)
778+
{
779+
struct svc_rdma_chunk *chunk = pcl_first_chunk(&ctxt->rc_read_pcl);
780+
struct xdr_buf *buf = &rqstp->rq_arg;
781+
unsigned int length;
782+
783+
/* Split the Receive buffer between the head and tail
784+
* buffers at Read chunk's position. XDR roundup of the
785+
* chunk is not included in either the pagelist or in
786+
* the tail.
787+
*/
788+
buf->tail[0].iov_base = buf->head[0].iov_base + chunk->ch_position;
789+
buf->tail[0].iov_len = buf->head[0].iov_len - chunk->ch_position;
790+
buf->head[0].iov_len = chunk->ch_position;
791+
792+
/* Read chunk may need XDR roundup (see RFC 8166, s. 3.4.5.2).
793+
*
794+
* If the client already rounded up the chunk length, the
795+
* length does not change. Otherwise, the length of the page
796+
* list is increased to include XDR round-up.
797+
*
798+
* Currently these chunks always start at page offset 0,
799+
* thus the rounded-up length never crosses a page boundary.
800+
*/
801+
buf->pages = &rqstp->rq_pages[0];
802+
length = xdr_align_size(chunk->ch_length);
803+
buf->page_len = length;
804+
buf->len += length;
805+
buf->buflen += length;
806+
}
807+
808+
/* Finish constructing the RPC Call message in rqstp::rq_arg.
809+
*
810+
* The incoming RPC/RDMA message is an RDMA_MSG type message
811+
* with payload in multiple Read chunks and no PZRC.
812+
*/
813+
static void svc_rdma_read_complete_multiple(struct svc_rqst *rqstp,
814+
struct svc_rdma_recv_ctxt *ctxt)
815+
{
816+
struct xdr_buf *buf = &rqstp->rq_arg;
817+
818+
buf->len += ctxt->rc_readbytes;
819+
buf->buflen += ctxt->rc_readbytes;
820+
821+
buf->head[0].iov_base = page_address(rqstp->rq_pages[0]);
822+
buf->head[0].iov_len = min_t(size_t, PAGE_SIZE, ctxt->rc_readbytes);
823+
buf->pages = &rqstp->rq_pages[1];
824+
buf->page_len = ctxt->rc_readbytes - buf->head[0].iov_len;
825+
}
826+
827+
/* Finish constructing the RPC Call message in rqstp::rq_arg.
828+
*
829+
* The incoming RPC/RDMA message is an RDMA_NOMSG type message
830+
* (the RPC message body was conveyed via RDMA Read).
831+
*/
832+
static void svc_rdma_read_complete_pzrc(struct svc_rqst *rqstp,
833+
struct svc_rdma_recv_ctxt *ctxt)
834+
{
835+
struct xdr_buf *buf = &rqstp->rq_arg;
836+
837+
buf->len += ctxt->rc_readbytes;
838+
buf->buflen += ctxt->rc_readbytes;
839+
840+
buf->head[0].iov_base = page_address(rqstp->rq_pages[0]);
841+
buf->head[0].iov_len = min_t(size_t, PAGE_SIZE, ctxt->rc_readbytes);
842+
buf->pages = &rqstp->rq_pages[1];
843+
buf->page_len = ctxt->rc_readbytes - buf->head[0].iov_len;
844+
}
845+
770846
static noinline void svc_rdma_read_complete(struct svc_rqst *rqstp,
771847
struct svc_rdma_recv_ctxt *ctxt)
772848
{
773-
int i;
849+
unsigned int i;
774850

775851
/* Transfer the Read chunk pages into @rqstp.rq_pages, replacing
776852
* the rq_pages that were already allocated for this rqstp.
@@ -789,6 +865,21 @@ static noinline void svc_rdma_read_complete(struct svc_rqst *rqstp,
789865
* pages in ctxt::rc_pages a second time.
790866
*/
791867
ctxt->rc_page_count = 0;
868+
869+
/* Finish constructing the RPC Call message. The exact
870+
* procedure for that depends on what kind of RPC/RDMA
871+
* chunks were provided by the client.
872+
*/
873+
if (pcl_is_empty(&ctxt->rc_call_pcl)) {
874+
if (ctxt->rc_read_pcl.cl_count == 1)
875+
svc_rdma_read_complete_one(rqstp, ctxt);
876+
else
877+
svc_rdma_read_complete_multiple(rqstp, ctxt);
878+
} else {
879+
svc_rdma_read_complete_pzrc(rqstp, ctxt);
880+
}
881+
882+
trace_svcrdma_read_finished(&ctxt->rc_cid);
792883
}
793884

794885
/**

0 commit comments

Comments
 (0)