Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+51 −28
Original line number Diff line number Diff line
@@ -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;
	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))
		/* 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);

	/* 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)) {
		int		want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
		struct kvec	iov;
@@ -907,7 +897,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
			dprintk("svc: short recvfrom while reading record "
				"length (%d of %d)\n", len, want);
			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);
@@ -922,6 +912,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
					"per record not supported\n");
			goto err_delete;
		}

		svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
		dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
		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",
			len, svsk->sk_reclen);
		svc_xprt_received(&svsk->sk_xprt);
		return -EAGAIN;	/* record not complete */
		goto err_again;	/* record not complete */
	}
	len = svsk->sk_reclen;
	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[0] = rqstp->rq_arg.head[0];
	vlen = PAGE_SIZE;
@@ -962,7 +987,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
	/* Now receive data */
	len = svc_recvfrom(rqstp, vec, pnum, len);
	if (len < 0)
		goto error;
		goto err_again;

	dprintk("svc: TCP complete record (%d bytes)\n", len);
	rqstp->rq_arg.len = len;
@@ -988,21 +1013,19 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)

	return len;

 err_delete:
	set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
	return -EAGAIN;

 error:
err_again:
	if (len == -EAGAIN) {
		dprintk("RPC: TCP recvfrom got EAGAIN\n");
		svc_xprt_received(&svsk->sk_xprt);
	} else {
		return len;
	}
error:
	if (len != -EAGAIN) {
		printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
		       svsk->sk_xprt.xpt_server->sv_name, -len);
		goto err_delete;
		set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
	}

	return len;
	return -EAGAIN;
}

/*