aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 62150ae2dc09..1dd48f269986 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -96,6 +96,42 @@ static bool rpcrdma_results_inline(struct rpc_rqst *rqst)
96 return repsize <= RPCRDMA_INLINE_READ_THRESHOLD(rqst); 96 return repsize <= RPCRDMA_INLINE_READ_THRESHOLD(rqst);
97} 97}
98 98
99static int
100rpcrdma_tail_pullup(struct xdr_buf *buf)
101{
102 size_t tlen = buf->tail[0].iov_len;
103 size_t skip = tlen & 3;
104
105 /* Do not include the tail if it is only an XDR pad */
106 if (tlen < 4)
107 return 0;
108
109 /* xdr_write_pages() adds a pad at the beginning of the tail
110 * if the content in "buf->pages" is unaligned. Force the
111 * tail's actual content to land at the next XDR position
112 * after the head instead.
113 */
114 if (skip) {
115 unsigned char *src, *dst;
116 unsigned int count;
117
118 src = buf->tail[0].iov_base;
119 dst = buf->head[0].iov_base;
120 dst += buf->head[0].iov_len;
121
122 src += skip;
123 tlen -= skip;
124
125 dprintk("RPC: %s: skip=%zu, memmove(%p, %p, %zu)\n",
126 __func__, skip, dst, src, tlen);
127
128 for (count = tlen; count; count--)
129 *dst++ = *src++;
130 }
131
132 return tlen;
133}
134
99/* 135/*
100 * Chunk assembly from upper layer xdr_buf. 136 * Chunk assembly from upper layer xdr_buf.
101 * 137 *
@@ -147,6 +183,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
147 if (len && n == nsegs) 183 if (len && n == nsegs)
148 return -EIO; 184 return -EIO;
149 185
186 /* When encoding the read list, the tail is always sent inline */
187 if (type == rpcrdma_readch)
188 return n;
189
150 if (xdrbuf->tail[0].iov_len) { 190 if (xdrbuf->tail[0].iov_len) {
151 /* the rpcrdma protocol allows us to omit any trailing 191 /* the rpcrdma protocol allows us to omit any trailing
152 * xdr pad bytes, saving the server an RDMA operation. */ 192 * xdr pad bytes, saving the server an RDMA operation. */
@@ -476,8 +516,8 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
476 headerp->rm_body.rm_nochunks.rm_empty[2] = xdr_zero; 516 headerp->rm_body.rm_nochunks.rm_empty[2] = xdr_zero;
477 /* new length after pullup */ 517 /* new length after pullup */
478 rpclen = rqst->rq_svec[0].iov_len; 518 rpclen = rqst->rq_svec[0].iov_len;
479 } 519 } else if (rtype == rpcrdma_readch)
480 520 rpclen += rpcrdma_tail_pullup(&rqst->rq_snd_buf);
481 if (rtype != rpcrdma_noch) { 521 if (rtype != rpcrdma_noch) {
482 hdrlen = rpcrdma_create_chunks(rqst, &rqst->rq_snd_buf, 522 hdrlen = rpcrdma_create_chunks(rqst, &rqst->rq_snd_buf,
483 headerp, rtype); 523 headerp, rtype);