Skip to content

Commit

Permalink
xprtrdma: Fix ri_max_segs and the result of ro_maxpages
Browse files Browse the repository at this point in the history
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: Chuck Lever <[email protected]>
Signed-off-by: Anna Schumaker <[email protected]>
  • Loading branch information
chucklever authored and amschuma-ntap committed Jan 2, 2019
1 parent 0c0829b commit 6946f82
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 6 deletions.
7 changes: 5 additions & 2 deletions net/sunrpc/xprtrdma/fmr_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 /
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;
}

Expand All @@ -186,7 +189,7 @@ static size_t
fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
{
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
Expand Down
7 changes: 5 additions & 2 deletions net/sunrpc/xprtrdma/frwr_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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;
}

Expand All @@ -257,7 +260,7 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
struct rpcrdma_ia *ia = &r_xprt->rx_ia;

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
Expand Down
6 changes: 4 additions & 2 deletions net/sunrpc/xprtrdma/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,8 +703,10 @@ xprt_rdma_free(struct rpc_task *task)
* %-ENOTCONN if the caller should reconnect and call again
* %-EAGAIN if the caller should call again
* %-ENOBUFS if the caller should call again after a delay
* %-EIO if a permanent error occurred and the request was not
* sent. Do not try to send this message again.
* %-EMSGSIZE if encoding ran out of buffer space. The request
* 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
xprt_rdma_send_request(struct rpc_rqst *rqst)
Expand Down

0 comments on commit 6946f82

Please sign in to comment.