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>
This commit is contained in:
parent
0f0257eaa5
commit
260c1d1298
|
@ -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 {
|
||||||
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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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,
|
||||||
};
|
};
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue