Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=cd123012d99fde4759500fee611e724e4f3016e3
Commit:     cd123012d99fde4759500fee611e724e4f3016e3
Parent:     669716433598a1498049e75a84a5aaf69c8da173
Author:     Jeff Layton <[EMAIL PROTECTED]>
AuthorDate: Wed May 9 02:34:50 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed May 9 12:30:54 2007 -0700

    RPC: add wrapper for svc_reserve to account for checksum
    
    When the kernel calls svc_reserve to downsize the expected size of an RPC
    reply, it fails to account for the possibility of a checksum at the end of
    the packet.  If a client mounts a NFSv2/3 with sec=krb5i/p, and does I/O
    then you'll generally see messages similar to this in the server's ring
    buffer:
    
    RPC request reserved 164 but used 208
    
    While I was never able to verify it, I suspect that this problem is also
    the root cause of some oopses I've seen under these conditions:
    
    https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=227726
    
    This is probably also a problem for other sec= types and for NFSv4.  The
    large reserved size for NFSv4 compound packets seems to generally paper
    over the problem, however.
    
    This patch adds a wrapper for svc_reserve that accounts for the possibility
    of a checksum.  It also fixes up the appropriate callers of svc_reserve to
    call the wrapper.  For now, it just uses a hardcoded value that I
    determined via testing.  That value may need to be revised upward as things
    change, or we may want to eventually add a new auth_op that attempts to
    calculate this somehow.
    
    Unfortunately, there doesn't seem to be a good way to reliably determine
    the expected checksum length prior to actually calculating it, particularly
    with schemes like spkm3.
    
    Signed-off-by: Jeff Layton <[EMAIL PROTECTED]>
    Acked-by: Neil Brown <[EMAIL PROTECTED]>
    Cc: Trond Myklebust <[EMAIL PROTECTED]>
    Acked-by: J. Bruce Fields <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/nfsd/nfs3proc.c         |    2 +-
 fs/nfsd/nfsproc.c          |    2 +-
 include/linux/sunrpc/svc.h |   19 +++++++++++++++++++
 net/sunrpc/svc.c           |    2 +-
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 7f5bad0..eac8283 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -177,7 +177,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct 
nfsd3_readargs *argp,
        if (max_blocksize < resp->count)
                resp->count = max_blocksize;
 
-       svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count 
+4);
+       svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + 
resp->count +4);
 
        fh_copy(&resp->fh, &argp->fh);
        nfserr = nfsd_read(rqstp, &resp->fh, NULL,
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 5cc2eec..b2c7147 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -155,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs 
*argp,
                                argp->count);
                argp->count = NFSSVC_MAXBLKSIZE_V2;
        }
-       svc_reserve(rqstp, (19<<2) + argp->count + 4);
+       svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
 
        resp->count = argp->count;
        nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 35fa4d5..4a7ae8a 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -396,4 +396,23 @@ char *                svc_print_addr(struct svc_rqst *, 
char *, size_t);
 
 #define        RPC_MAX_ADDRBUFLEN      (63U)
 
+/*
+ * When we want to reduce the size of the reserved space in the response
+ * buffer, we need to take into account the size of any checksum data that
+ * may be at the end of the packet. This is difficult to determine exactly
+ * for all cases without actually generating the checksum, so we just use a
+ * static value.
+ */
+static inline void
+svc_reserve_auth(struct svc_rqst *rqstp, int space)
+{
+       int                     added_space = 0;
+
+       switch(rqstp->rq_authop->flavour) {
+               case RPC_AUTH_GSS:
+                       added_space = RPC_MAX_AUTH_SIZE;
+       }
+       return svc_reserve(rqstp, space + added_space);
+}
+
 #endif /* SUNRPC_SVC_H */
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index b7503c1..e673ef9 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -907,7 +907,7 @@ svc_process(struct svc_rqst *rqstp)
         * better idea of reply size
         */
        if (procp->pc_xdrressize)
-               svc_reserve(rqstp, procp->pc_xdrressize<<2);
+               svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
 
        /* Call the function that processes the request. */
        if (!versp->vs_dispatch) {
-
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