aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:08:29 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:13 -0500
commit260c1d1298f6703d38fdccd3dd5a310766327340 (patch)
tree95bf71a81a9bba5d1e69940ccba99943682029c5 /net
parent0f0257eaa5d29b80f6ab2c40ed21aa65bb4527f6 (diff)
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 <tom@opengridcomputing.com> Acked-by: Neil Brown <neilb@suse.de> Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Greg Banks <gnb@sgi.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/svc_xprt.c36
-rw-r--r--net/sunrpc/svcsock.c2
2 files changed, 29 insertions, 9 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 23165aef59d9..000c7dc3b82c 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -29,7 +29,6 @@
29#include <linux/sunrpc/types.h> 29#include <linux/sunrpc/types.h>
30#include <linux/sunrpc/clnt.h> 30#include <linux/sunrpc/clnt.h>
31#include <linux/sunrpc/xdr.h> 31#include <linux/sunrpc/xdr.h>
32#include <linux/sunrpc/svcsock.h>
33#include <linux/sunrpc/stats.h> 32#include <linux/sunrpc/stats.h>
34#include <linux/sunrpc/svc_xprt.h> 33#include <linux/sunrpc/svc_xprt.h>
35 34
@@ -859,10 +858,18 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
859 svc_xprt_put(xprt); 858 svc_xprt_put(xprt);
860} 859}
861 860
861/*
862 * Save the request off for later processing. The request buffer looks
863 * like this:
864 *
865 * <xprt-header><rpc-header><rpc-pagelist><rpc-tail>
866 *
867 * This code can only handle requests that consist of an xprt-header
868 * and rpc-header.
869 */
862static struct cache_deferred_req *svc_defer(struct cache_req *req) 870static struct cache_deferred_req *svc_defer(struct cache_req *req)
863{ 871{
864 struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle); 872 struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle);
865 int size = sizeof(struct svc_deferred_req) + (rqstp->rq_arg.len);
866 struct svc_deferred_req *dr; 873 struct svc_deferred_req *dr;
867 874
868 if (rqstp->rq_arg.page_len) 875 if (rqstp->rq_arg.page_len)
@@ -871,8 +878,10 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
871 dr = rqstp->rq_deferred; 878 dr = rqstp->rq_deferred;
872 rqstp->rq_deferred = NULL; 879 rqstp->rq_deferred = NULL;
873 } else { 880 } else {
874 int skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len; 881 size_t skip;
882 size_t size;
875 /* FIXME maybe discard if size too large */ 883 /* FIXME maybe discard if size too large */
884 size = sizeof(struct svc_deferred_req) + rqstp->rq_arg.len;
876 dr = kmalloc(size, GFP_KERNEL); 885 dr = kmalloc(size, GFP_KERNEL);
877 if (dr == NULL) 886 if (dr == NULL)
878 return NULL; 887 return NULL;
@@ -883,8 +892,12 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
883 dr->addrlen = rqstp->rq_addrlen; 892 dr->addrlen = rqstp->rq_addrlen;
884 dr->daddr = rqstp->rq_daddr; 893 dr->daddr = rqstp->rq_daddr;
885 dr->argslen = rqstp->rq_arg.len >> 2; 894 dr->argslen = rqstp->rq_arg.len >> 2;
886 memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, 895 dr->xprt_hlen = rqstp->rq_xprt_hlen;
887 dr->argslen<<2); 896
897 /* back up head to the start of the buffer and copy */
898 skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
899 memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip,
900 dr->argslen << 2);
888 } 901 }
889 svc_xprt_get(rqstp->rq_xprt); 902 svc_xprt_get(rqstp->rq_xprt);
890 dr->xprt = rqstp->rq_xprt; 903 dr->xprt = rqstp->rq_xprt;
@@ -900,16 +913,21 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
900{ 913{
901 struct svc_deferred_req *dr = rqstp->rq_deferred; 914 struct svc_deferred_req *dr = rqstp->rq_deferred;
902 915
903 rqstp->rq_arg.head[0].iov_base = dr->args; 916 /* setup iov_base past transport header */
904 rqstp->rq_arg.head[0].iov_len = dr->argslen<<2; 917 rqstp->rq_arg.head[0].iov_base = dr->args + (dr->xprt_hlen>>2);
918 /* The iov_len does not include the transport header bytes */
919 rqstp->rq_arg.head[0].iov_len = (dr->argslen<<2) - dr->xprt_hlen;
905 rqstp->rq_arg.page_len = 0; 920 rqstp->rq_arg.page_len = 0;
906 rqstp->rq_arg.len = dr->argslen<<2; 921 /* The rq_arg.len includes the transport header bytes */
922 rqstp->rq_arg.len = dr->argslen<<2;
907 rqstp->rq_prot = dr->prot; 923 rqstp->rq_prot = dr->prot;
908 memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen); 924 memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
909 rqstp->rq_addrlen = dr->addrlen; 925 rqstp->rq_addrlen = dr->addrlen;
926 /* Save off transport header len in case we get deferred again */
927 rqstp->rq_xprt_hlen = dr->xprt_hlen;
910 rqstp->rq_daddr = dr->daddr; 928 rqstp->rq_daddr = dr->daddr;
911 rqstp->rq_respages = rqstp->rq_pages; 929 rqstp->rq_respages = rqstp->rq_pages;
912 return dr->argslen<<2; 930 return (dr->argslen<<2) - dr->xprt_hlen;
913} 931}
914 932
915 933
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 343a85b700f0..1d3e5fcc2cc4 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,
315 }; 315 };
316 int len; 316 int len;
317 317
318 rqstp->rq_xprt_hlen = 0;
319
318 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, 320 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
319 msg.msg_flags); 321 msg.msg_flags);
320 322