aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2018-01-31 12:34:05 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-02-02 13:29:57 -0500
commit1179e2c27efe21167ec9d882b14becefba2ee990 (patch)
tree171b9211a06cbf393b6fca279171ce52f56ae2bf
parent21ead9ff3dc72604d89499a1da5a18cc193ec4ff (diff)
xprtrdma: Fix calculation of ri_max_send_sges
Commit 16f906d66cd7 ("xprtrdma: Reduce required number of send SGEs") introduced the rpcrdma_ia::ri_max_send_sges field. This fixes a problem where xprtrdma would not work if the device's max_sge capability was small (low single digits). At least RPCRDMA_MIN_SEND_SGES are needed for the inline parts of each RPC. ri_max_send_sges is set to this value: ia->ri_max_send_sges = max_sge - RPCRDMA_MIN_SEND_SGES; Then when marshaling each RPC, rpcrdma_args_inline uses that value to determine whether the device has enough Send SGEs to convey an NFS WRITE payload inline, or whether instead a Read chunk is required. More recently, commit ae72950abf99 ("xprtrdma: Add data structure to manage RDMA Send arguments") used the ri_max_send_sges value to calculate the size of an array, but that commit erroneously assumed ri_max_send_sges contains a value similar to the device's max_sge, and not one that was reduced by the minimum SGE count. This assumption results in the calculated size of the sendctx's Send SGE array to be too small. When the array is used to marshal an RPC, the code can write Send SGEs into the following sendctx element in that array, corrupting it. When the device's max_sge is large, this issue is entirely harmless; but it results in an oops in the provider's post_send method, if dev.attrs.max_sge is small. So let's straighten this out: ri_max_send_sges will now contain a value with the same meaning as dev.attrs.max_sge, which makes the code easier to understand, and enables rpcrdma_sendctx_create to calculate the size of the SGE array correctly. Reported-by: Michal Kalderon <Michal.Kalderon@cavium.com> Fixes: 16f906d66cd7 ("xprtrdma: Reduce required number of send SGEs") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: Michal Kalderon <Michal.Kalderon@cavium.com> Cc: stable@vger.kernel.org # v4.10+ Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c2
-rw-r--r--net/sunrpc/xprtrdma/verbs.c2
2 files changed, 2 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 162e5dd82466..f0855a959a27 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -143,7 +143,7 @@ static bool rpcrdma_args_inline(struct rpcrdma_xprt *r_xprt,
143 if (xdr->page_len) { 143 if (xdr->page_len) {
144 remaining = xdr->page_len; 144 remaining = xdr->page_len;
145 offset = offset_in_page(xdr->page_base); 145 offset = offset_in_page(xdr->page_base);
146 count = 0; 146 count = RPCRDMA_MIN_SEND_SGES;
147 while (remaining) { 147 while (remaining) {
148 remaining -= min_t(unsigned int, 148 remaining -= min_t(unsigned int,
149 PAGE_SIZE - offset, remaining); 149 PAGE_SIZE - offset, remaining);
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index f4eb63e8e689..bb56b9d849c4 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -505,7 +505,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
505 pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge); 505 pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge);
506 return -ENOMEM; 506 return -ENOMEM;
507 } 507 }
508 ia->ri_max_send_sges = max_sge - RPCRDMA_MIN_SEND_SGES; 508 ia->ri_max_send_sges = max_sge;
509 509
510 if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) { 510 if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) {
511 dprintk("RPC: %s: insufficient wqe's available\n", 511 dprintk("RPC: %s: insufficient wqe's available\n",