Commit 8f55f3c0 authored by Alexandros Batsakis's avatar Alexandros Batsakis Committed by J. Bruce Fields

nfsd41: sunrpc: svc_tcp_recv_record()

Factor functionality out of svc_tcp_recvfrom() to simplify routine
Signed-off-by: default avatarAlexandros Batsakis <batsakis@netapp.com>
Signed-off-by: default avatarRicardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent fbf4665f
...@@ -854,21 +854,15 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment