Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=260c1d1298f6703d38fdccd3dd5a310766327340
Commit:     260c1d1298f6703d38fdccd3dd5a310766327340
Parent:     0f0257eaa5d29b80f6ab2c40ed21aa65bb4527f6
Author:     Tom Tucker <[EMAIL PROTECTED]>
AuthorDate: Sun Dec 30 21:08:29 2007 -0600
Committer:  J. Bruce Fields <[EMAIL PROTECTED]>
CommitDate: Fri Feb 1 16:42:13 2008 -0500

    svc: Add transport hdr size for defer/revisit
    
    Some transports have a header in front of the RPC header. The current
    defer/revisit processing considers only the iov_len and arg_len to
    determine how much to back up when saving the original request
    to revisit. Add a field to the rqstp structure to save the size
    of the transport header so svc_defer can correctly compute
    the start of a request.
    
    Signed-off-by: Tom Tucker <[EMAIL PROTECTED]>
    Acked-by: Neil Brown <[EMAIL PROTECTED]>
    Reviewed-by: Chuck Lever <[EMAIL PROTECTED]>
    Reviewed-by: Greg Banks <[EMAIL PROTECTED]>
    Signed-off-by: J. Bruce Fields <[EMAIL PROTECTED]>
---
 include/linux/sunrpc/svc.h |    2 ++
 net/sunrpc/svc_xprt.c      |   36 +++++++++++++++++++++++++++---------
 net/sunrpc/svcsock.c       |    2 ++
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 04eb20e..742ab46 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -217,6 +217,7 @@ struct svc_rqst {
        void *                  rq_xprt_ctxt;   /* transport specific context 
ptr */
        struct svc_deferred_req*rq_deferred;    /* deferred request we are 
replaying */
 
+       size_t                  rq_xprt_hlen;   /* xprt header len */
        struct xdr_buf          rq_arg;
        struct xdr_buf          rq_res;
        struct page *           rq_pages[RPCSVC_MAXPAGES];
@@ -322,6 +323,7 @@ struct svc_deferred_req {
        size_t                  addrlen;
        union svc_addr_u        daddr;  /* where reply must come from */
        struct cache_deferred_req handle;
+       size_t                  xprt_hlen;
        int                     argslen;
        __be32                  args[0];
 };
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 23165ae..000c7dc 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -29,7 +29,6 @@
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/stats.h>
 #include <linux/sunrpc/svc_xprt.h>
 
@@ -859,10 +858,18 @@ static void svc_revisit(struct cache_deferred_req *dreq, 
int too_many)
        svc_xprt_put(xprt);
 }
 
+/*
+ * Save the request off for later processing. The request buffer looks
+ * like this:
+ *
+ * <xprt-header><rpc-header><rpc-pagelist><rpc-tail>
+ *
+ * This code can only handle requests that consist of an xprt-header
+ * and rpc-header.
+ */
 static struct cache_deferred_req *svc_defer(struct cache_req *req)
 {
        struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle);
-       int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.len);
        struct svc_deferred_req *dr;
 
        if (rqstp->rq_arg.page_len)
@@ -871,8 +878,10 @@ static struct cache_deferred_req *svc_defer(struct 
cache_req *req)
                dr = rqstp->rq_deferred;
                rqstp->rq_deferred = NULL;
        } else {
-               int skip  = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
+               size_t skip;
+               size_t size;
                /* FIXME maybe discard if size too large */
+               size = sizeof(struct svc_deferred_req) + rqstp->rq_arg.len;
                dr = kmalloc(size, GFP_KERNEL);
                if (dr == NULL)
                        return NULL;
@@ -883,8 +892,12 @@ static struct cache_deferred_req *svc_defer(struct 
cache_req *req)
                dr->addrlen = rqstp->rq_addrlen;
                dr->daddr = rqstp->rq_daddr;
                dr->argslen = rqstp->rq_arg.len >> 2;
-               memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip,
-                      dr->argslen<<2);
+               dr->xprt_hlen = rqstp->rq_xprt_hlen;
+
+               /* back up head to the start of the buffer and copy */
+               skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
+               memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip,
+                      dr->argslen << 2);
        }
        svc_xprt_get(rqstp->rq_xprt);
        dr->xprt = rqstp->rq_xprt;
@@ -900,16 +913,21 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
 {
        struct svc_deferred_req *dr = rqstp->rq_deferred;
 
-       rqstp->rq_arg.head[0].iov_base = dr->args;
-       rqstp->rq_arg.head[0].iov_len = dr->argslen<<2;
+       /* setup iov_base past transport header */
+       rqstp->rq_arg.head[0].iov_base = dr->args + (dr->xprt_hlen>>2);
+       /* The iov_len does not include the transport header bytes */
+       rqstp->rq_arg.head[0].iov_len = (dr->argslen<<2) - dr->xprt_hlen;
        rqstp->rq_arg.page_len = 0;
-       rqstp->rq_arg.len = dr->argslen<<2;
+       /* The rq_arg.len includes the transport header bytes */
+       rqstp->rq_arg.len     = dr->argslen<<2;
        rqstp->rq_prot        = dr->prot;
        memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
        rqstp->rq_addrlen     = dr->addrlen;
+       /* Save off transport header len in case we get deferred again */
+       rqstp->rq_xprt_hlen   = dr->xprt_hlen;
        rqstp->rq_daddr       = dr->daddr;
        rqstp->rq_respages    = rqstp->rq_pages;
-       return dr->argslen<<2;
+       return (dr->argslen<<2) - dr->xprt_hlen;
 }
 
 
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 343a85b..1d3e5fc 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -315,6 +315,8 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec 
*iov, int nr,
        };
        int len;
 
+       rqstp->rq_xprt_hlen = 0;
+
        len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
                                msg.msg_flags);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to