mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
nfsd41: sunrpc: svc_tcp_recv_record()
Factor functionality out of svc_tcp_recvfrom() to simplify routine Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
parent
fbf4665f41
commit
8f55f3c0a0
1 changed files with 51 additions and 28 deletions
|
@ -854,21 +854,15 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receive data from a TCP socket.
|
* Receive data.
|
||||||
|
* If we haven't gotten the record length yet, get the next four bytes.
|
||||||
|
* Otherwise try to gobble up as much as possible up to the complete
|
||||||
|
* record length.
|
||||||
*/
|
*/
|
||||||
static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
|
||||||
{
|
{
|
||||||
struct svc_sock *svsk =
|
|
||||||
container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
|
|
||||||
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
|
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
|
||||||
int len;
|
int len;
|
||||||
struct kvec *vec;
|
|
||||||
int pnum, vlen;
|
|
||||||
|
|
||||||
dprintk("svc: tcp_recv %p data %d conn %d close %d\n",
|
|
||||||
svsk, test_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags),
|
|
||||||
test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags),
|
|
||||||
test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
|
|
||||||
|
|
||||||
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
|
if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
|
||||||
/* sndbuf needs to have room for one request
|
/* sndbuf needs to have room for one request
|
||||||
|
@ -889,10 +883,6 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
|
|
||||||
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
||||||
|
|
||||||
/* Receive data. If we haven't got the record length yet, get
|
|
||||||
* the next four bytes. Otherwise try to gobble up as much as
|
|
||||||
* possible up to the complete record length.
|
|
||||||
*/
|
|
||||||
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
|
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
|
||||||
int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
|
int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
|
||||||
struct kvec iov;
|
struct kvec iov;
|
||||||
|
@ -907,7 +897,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
dprintk("svc: short recvfrom while reading record "
|
dprintk("svc: short recvfrom while reading record "
|
||||||
"length (%d of %d)\n", len, want);
|
"length (%d of %d)\n", len, want);
|
||||||
svc_xprt_received(&svsk->sk_xprt);
|
svc_xprt_received(&svsk->sk_xprt);
|
||||||
return -EAGAIN; /* record header not complete */
|
goto err_again; /* record header not complete */
|
||||||
}
|
}
|
||||||
|
|
||||||
svsk->sk_reclen = ntohl(svsk->sk_reclen);
|
svsk->sk_reclen = ntohl(svsk->sk_reclen);
|
||||||
|
@ -922,6 +912,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
"per record not supported\n");
|
"per record not supported\n");
|
||||||
goto err_delete;
|
goto err_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
|
svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
|
||||||
dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
|
dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
|
||||||
if (svsk->sk_reclen > serv->sv_max_mesg) {
|
if (svsk->sk_reclen > serv->sv_max_mesg) {
|
||||||
|
@ -942,11 +933,45 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
dprintk("svc: incomplete TCP record (%d of %d)\n",
|
dprintk("svc: incomplete TCP record (%d of %d)\n",
|
||||||
len, svsk->sk_reclen);
|
len, svsk->sk_reclen);
|
||||||
svc_xprt_received(&svsk->sk_xprt);
|
svc_xprt_received(&svsk->sk_xprt);
|
||||||
return -EAGAIN; /* record not complete */
|
goto err_again; /* record not complete */
|
||||||
}
|
}
|
||||||
len = svsk->sk_reclen;
|
len = svsk->sk_reclen;
|
||||||
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
error:
|
||||||
|
if (len == -EAGAIN) {
|
||||||
|
dprintk("RPC: TCP recv_record got EAGAIN\n");
|
||||||
|
svc_xprt_received(&svsk->sk_xprt);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
err_delete:
|
||||||
|
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
||||||
|
err_again:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive data from a TCP socket.
|
||||||
|
*/
|
||||||
|
static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
|
{
|
||||||
|
struct svc_sock *svsk =
|
||||||
|
container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
|
||||||
|
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
|
||||||
|
int len;
|
||||||
|
struct kvec *vec;
|
||||||
|
int pnum, vlen;
|
||||||
|
|
||||||
|
dprintk("svc: tcp_recv %p data %d conn %d close %d\n",
|
||||||
|
svsk, test_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags),
|
||||||
|
test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags),
|
||||||
|
test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
|
||||||
|
|
||||||
|
len = svc_tcp_recv_record(svsk, rqstp);
|
||||||
|
if (len < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
vec = rqstp->rq_vec;
|
vec = rqstp->rq_vec;
|
||||||
vec[0] = rqstp->rq_arg.head[0];
|
vec[0] = rqstp->rq_arg.head[0];
|
||||||
vlen = PAGE_SIZE;
|
vlen = PAGE_SIZE;
|
||||||
|
@ -962,7 +987,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
/* Now receive data */
|
/* Now receive data */
|
||||||
len = svc_recvfrom(rqstp, vec, pnum, len);
|
len = svc_recvfrom(rqstp, vec, pnum, len);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto error;
|
goto err_again;
|
||||||
|
|
||||||
dprintk("svc: TCP complete record (%d bytes)\n", len);
|
dprintk("svc: TCP complete record (%d bytes)\n", len);
|
||||||
rqstp->rq_arg.len = len;
|
rqstp->rq_arg.len = len;
|
||||||
|
@ -988,21 +1013,19 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
err_delete:
|
err_again:
|
||||||
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (len == -EAGAIN) {
|
if (len == -EAGAIN) {
|
||||||
dprintk("RPC: TCP recvfrom got EAGAIN\n");
|
dprintk("RPC: TCP recvfrom got EAGAIN\n");
|
||||||
svc_xprt_received(&svsk->sk_xprt);
|
svc_xprt_received(&svsk->sk_xprt);
|
||||||
} else {
|
return len;
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
if (len != -EAGAIN) {
|
||||||
printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
|
printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
|
||||||
svsk->sk_xprt.xpt_server->sv_name, -len);
|
svsk->sk_xprt.xpt_server->sv_name, -len);
|
||||||
goto err_delete;
|
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
||||||
}
|
}
|
||||||
|
return -EAGAIN;
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue