diff options
| -rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 44 |
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 | ||
| 99 | static int | ||
| 100 | rpcrdma_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); |
