提交 260c1d12 编写于 作者: T Tom Tucker 提交者: J. Bruce Fields

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: NTom Tucker <tom@opengridcomputing.com>
Acked-by: NNeil Brown <neilb@suse.de>
Reviewed-by: NChuck Lever <chuck.lever@oracle.com>
Reviewed-by: NGreg Banks <gnb@sgi.com>
Signed-off-by: NJ. Bruce Fields <bfields@citi.umich.edu>
上级 0f0257ea
...@@ -217,6 +217,7 @@ struct svc_rqst { ...@@ -217,6 +217,7 @@ struct svc_rqst {
void * rq_xprt_ctxt; /* transport specific context ptr */ void * rq_xprt_ctxt; /* transport specific context ptr */
struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */ 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_arg;
struct xdr_buf rq_res; struct xdr_buf rq_res;
struct page * rq_pages[RPCSVC_MAXPAGES]; struct page * rq_pages[RPCSVC_MAXPAGES];
...@@ -322,6 +323,7 @@ struct svc_deferred_req { ...@@ -322,6 +323,7 @@ struct svc_deferred_req {
size_t addrlen; size_t addrlen;
union svc_addr_u daddr; /* where reply must come from */ union svc_addr_u daddr; /* where reply must come from */
struct cache_deferred_req handle; struct cache_deferred_req handle;
size_t xprt_hlen;
int argslen; int argslen;
__be32 args[0]; __be32 args[0];
}; };
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/sunrpc/types.h> #include <linux/sunrpc/types.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/stats.h> #include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svc_xprt.h> #include <linux/sunrpc/svc_xprt.h>
...@@ -859,10 +858,18 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many) ...@@ -859,10 +858,18 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
svc_xprt_put(xprt); 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) static struct cache_deferred_req *svc_defer(struct cache_req *req)
{ {
struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle); 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; struct svc_deferred_req *dr;
if (rqstp->rq_arg.page_len) if (rqstp->rq_arg.page_len)
...@@ -871,8 +878,10 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req) ...@@ -871,8 +878,10 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
dr = rqstp->rq_deferred; dr = rqstp->rq_deferred;
rqstp->rq_deferred = NULL; rqstp->rq_deferred = NULL;
} else { } 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 */ /* FIXME maybe discard if size too large */
size = sizeof(struct svc_deferred_req) + rqstp->rq_arg.len;
dr = kmalloc(size, GFP_KERNEL); dr = kmalloc(size, GFP_KERNEL);
if (dr == NULL) if (dr == NULL)
return NULL; return NULL;
...@@ -883,8 +892,12 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req) ...@@ -883,8 +892,12 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
dr->addrlen = rqstp->rq_addrlen; dr->addrlen = rqstp->rq_addrlen;
dr->daddr = rqstp->rq_daddr; dr->daddr = rqstp->rq_daddr;
dr->argslen = rqstp->rq_arg.len >> 2; dr->argslen = rqstp->rq_arg.len >> 2;
memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->xprt_hlen = rqstp->rq_xprt_hlen;
dr->argslen<<2);
/* 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); svc_xprt_get(rqstp->rq_xprt);
dr->xprt = rqstp->rq_xprt; dr->xprt = rqstp->rq_xprt;
...@@ -900,16 +913,21 @@ static int svc_deferred_recv(struct svc_rqst *rqstp) ...@@ -900,16 +913,21 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
{ {
struct svc_deferred_req *dr = rqstp->rq_deferred; struct svc_deferred_req *dr = rqstp->rq_deferred;
rqstp->rq_arg.head[0].iov_base = dr->args; /* setup iov_base past transport header */
rqstp->rq_arg.head[0].iov_len = dr->argslen<<2; 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.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; rqstp->rq_prot = dr->prot;
memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen); memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
rqstp->rq_addrlen = 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_daddr = dr->daddr;
rqstp->rq_respages = rqstp->rq_pages; rqstp->rq_respages = rqstp->rq_pages;
return dr->argslen<<2; return (dr->argslen<<2) - dr->xprt_hlen;
} }
......
...@@ -315,6 +315,8 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, ...@@ -315,6 +315,8 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr,
}; };
int len; int len;
rqstp->rq_xprt_hlen = 0;
len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
msg.msg_flags); msg.msg_flags);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册