xprtrdma: Limit data payload size for ALLPHYSICAL
authorChuck Lever <chuck.lever@oracle.com>
Tue, 29 Jul 2014 21:23:34 +0000 (17:23 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 31 Jul 2014 20:22:52 +0000 (16:22 -0400)
When the client uses physical memory registration, each page in the
payload gets its own array entry in the RPC/RDMA header's chunk list.

Therefore, don't advertise a maximum payload size that would require
more array entries than can fit in the RPC buffer where RPC/RDMA
headers are built.

BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=248
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Tested-by: Shirley Ma <shirley.ma@oracle.com>
Tested-by: Devesh Sharma <devesh.sharma@emulex.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h

index 66f91f0d071a9bbdec3e440aaa09c94df57ffbe0..41851020291978f095cdb1d4725b476b348e8374 100644 (file)
@@ -296,7 +296,6 @@ xprt_setup_rdma(struct xprt_create *args)
 
        xprt->resvport = 0;             /* privileged port not needed */
        xprt->tsh_size = 0;             /* RPC-RDMA handles framing */
-       xprt->max_payload = RPCRDMA_MAX_DATA_SEGS * PAGE_SIZE;
        xprt->ops = &xprt_rdma_procs;
 
        /*
@@ -382,6 +381,9 @@ xprt_setup_rdma(struct xprt_create *args)
        new_ep->rep_xprt = xprt;
 
        xprt_rdma_format_addresses(xprt);
+       xprt->max_payload = rpcrdma_max_payload(new_xprt);
+       dprintk("RPC:       %s: transport data payload maximum: %zu bytes\n",
+               __func__, xprt->max_payload);
 
        if (!try_module_get(THIS_MODULE))
                goto out4;
index aa08de89de420e48ee67987f36cf32df46477583..13ff87400203fdc4a70f06057c090a62b1652a6f 100644 (file)
@@ -1825,3 +1825,44 @@ rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
                        rc);
        return rc;
 }
+
+/* Physical mapping means one Read/Write list entry per-page.
+ * All list entries must fit within an inline buffer
+ *
+ * NB: The server must return a Write list for NFS READ,
+ *     which has the same constraint. Factor in the inline
+ *     rsize as well.
+ */
+static size_t
+rpcrdma_physical_max_payload(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
+       unsigned int inline_size, pages;
+
+       inline_size = min_t(unsigned int,
+                           cdata->inline_wsize, cdata->inline_rsize);
+       inline_size -= RPCRDMA_HDRLEN_MIN;
+       pages = inline_size / sizeof(struct rpcrdma_segment);
+       return pages << PAGE_SHIFT;
+}
+
+static size_t
+rpcrdma_mr_max_payload(struct rpcrdma_xprt *r_xprt)
+{
+       return RPCRDMA_MAX_DATA_SEGS << PAGE_SHIFT;
+}
+
+size_t
+rpcrdma_max_payload(struct rpcrdma_xprt *r_xprt)
+{
+       size_t result;
+
+       switch (r_xprt->rx_ia.ri_memreg_strategy) {
+       case RPCRDMA_ALLPHYSICAL:
+               result = rpcrdma_physical_max_payload(r_xprt);
+               break;
+       default:
+               result = rpcrdma_mr_max_payload(r_xprt);
+       }
+       return result;
+}
index 97ca516ec6199cde7eb83757beddc150e1b5876b..f3d86b24a4af3cd198107c3fcbd761bc0258f610 100644 (file)
@@ -348,6 +348,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *);
  * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c
  */
 int rpcrdma_marshal_req(struct rpc_rqst *);
+size_t rpcrdma_max_payload(struct rpcrdma_xprt *);
 
 /* Temporary NFS request map cache. Created in svc_rdma.c  */
 extern struct kmem_cache *svc_rdma_map_cachep;