|
|
@@ -231,7 +231,8 @@ rpcrdma_convert_kvec(struct kvec *vec, struct rpcrdma_mr_seg *seg, int n)
|
|
|
|
|
|
static int
|
|
|
rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
|
|
|
- enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg)
|
|
|
+ enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg,
|
|
|
+ bool reminv_expected)
|
|
|
{
|
|
|
int len, n, p, page_base;
|
|
|
struct page **ppages;
|
|
|
@@ -273,6 +274,13 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
|
|
|
if (type == rpcrdma_readch)
|
|
|
return n;
|
|
|
|
|
|
+ /* When encoding the Write list, some servers need to see an extra
|
|
|
+ * segment for odd-length Write chunks. The upper layer provides
|
|
|
+ * space in the tail iovec for this purpose.
|
|
|
+ */
|
|
|
+ if (type == rpcrdma_writech && reminv_expected)
|
|
|
+ return n;
|
|
|
+
|
|
|
if (xdrbuf->tail[0].iov_len) {
|
|
|
/* the rpcrdma protocol allows us to omit any trailing
|
|
|
* xdr pad bytes, saving the server an RDMA operation. */
|
|
|
@@ -329,7 +337,7 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt,
|
|
|
if (rtype == rpcrdma_areadch)
|
|
|
pos = 0;
|
|
|
seg = req->rl_segments;
|
|
|
- nsegs = rpcrdma_convert_iovs(&rqst->rq_snd_buf, pos, rtype, seg);
|
|
|
+ nsegs = rpcrdma_convert_iovs(&rqst->rq_snd_buf, pos, rtype, seg, false);
|
|
|
if (nsegs < 0)
|
|
|
return ERR_PTR(nsegs);
|
|
|
|
|
|
@@ -393,7 +401,8 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
|
|
|
seg = req->rl_segments;
|
|
|
nsegs = rpcrdma_convert_iovs(&rqst->rq_rcv_buf,
|
|
|
rqst->rq_rcv_buf.head[0].iov_len,
|
|
|
- wtype, seg);
|
|
|
+ wtype, seg,
|
|
|
+ r_xprt->rx_ia.ri_reminv_expected);
|
|
|
if (nsegs < 0)
|
|
|
return ERR_PTR(nsegs);
|
|
|
|
|
|
@@ -458,7 +467,8 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt,
|
|
|
}
|
|
|
|
|
|
seg = req->rl_segments;
|
|
|
- nsegs = rpcrdma_convert_iovs(&rqst->rq_rcv_buf, 0, wtype, seg);
|
|
|
+ nsegs = rpcrdma_convert_iovs(&rqst->rq_rcv_buf, 0, wtype, seg,
|
|
|
+ r_xprt->rx_ia.ri_reminv_expected);
|
|
|
if (nsegs < 0)
|
|
|
return ERR_PTR(nsegs);
|
|
|
|