Commit 6946f823 authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker

xprtrdma: Fix ri_max_segs and the result of ro_maxpages

With certain combinations of krb5i/p, MR size, and r/wsize, I/O can
fail with EMSGSIZE. This is because the calculated value of
ri_max_segs (the max number of MRs per RPC) exceeded
RPCRDMA_MAX_HDR_SEGS, which caused Read or Write list encoding to
walk off the end of the transport header.

Once that was addressed, the ro_maxpages result has to be corrected
to account for the number of MRs needed for Reply chunks, which is
2 MRs smaller than a normal Read or Write chunk.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 0c0829bc
...@@ -176,7 +176,10 @@ fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, ...@@ -176,7 +176,10 @@ fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS / ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
RPCRDMA_MAX_FMR_SGES); RPCRDMA_MAX_FMR_SGES);
ia->ri_max_segs += 2; /* segments for head and tail buffers */ /* Reply chunks require segments for head and tail buffers */
ia->ri_max_segs += 2;
if (ia->ri_max_segs > RPCRDMA_MAX_HDR_SEGS)
ia->ri_max_segs = RPCRDMA_MAX_HDR_SEGS;
return 0; return 0;
} }
...@@ -186,7 +189,7 @@ static size_t ...@@ -186,7 +189,7 @@ static size_t
fmr_op_maxpages(struct rpcrdma_xprt *r_xprt) fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
{ {
return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS, return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
RPCRDMA_MAX_HDR_SEGS * RPCRDMA_MAX_FMR_SGES); (r_xprt->rx_ia.ri_max_segs - 2) * RPCRDMA_MAX_FMR_SGES);
} }
/* Use the ib_map_phys_fmr() verb to register a memory region /* Use the ib_map_phys_fmr() verb to register a memory region
......
...@@ -244,7 +244,10 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, ...@@ -244,7 +244,10 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS / ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
ia->ri_max_frwr_depth); ia->ri_max_frwr_depth);
ia->ri_max_segs += 2; /* segments for head and tail buffers */ /* Reply chunks require segments for head and tail buffers */
ia->ri_max_segs += 2;
if (ia->ri_max_segs > RPCRDMA_MAX_HDR_SEGS)
ia->ri_max_segs = RPCRDMA_MAX_HDR_SEGS;
return 0; return 0;
} }
...@@ -257,7 +260,7 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt) ...@@ -257,7 +260,7 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
struct rpcrdma_ia *ia = &r_xprt->rx_ia; struct rpcrdma_ia *ia = &r_xprt->rx_ia;
return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS, return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
RPCRDMA_MAX_HDR_SEGS * ia->ri_max_frwr_depth); (ia->ri_max_segs - 2) * ia->ri_max_frwr_depth);
} }
static void static void
......
...@@ -703,8 +703,10 @@ xprt_rdma_free(struct rpc_task *task) ...@@ -703,8 +703,10 @@ xprt_rdma_free(struct rpc_task *task)
* %-ENOTCONN if the caller should reconnect and call again * %-ENOTCONN if the caller should reconnect and call again
* %-EAGAIN if the caller should call again * %-EAGAIN if the caller should call again
* %-ENOBUFS if the caller should call again after a delay * %-ENOBUFS if the caller should call again after a delay
* %-EIO if a permanent error occurred and the request was not * %-EMSGSIZE if encoding ran out of buffer space. The request
* sent. Do not try to send this message again. * was not sent. Do not try to send this message again.
* %-EIO if an I/O error occurred. The request was not sent.
* Do not try to send this message again.
*/ */
static int static int
xprt_rdma_send_request(struct rpc_rqst *rqst) xprt_rdma_send_request(struct rpc_rqst *rqst)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment