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

Commit c0401ea0 authored by Chuck Lever's avatar Chuck Lever Committed by J. Bruce Fields
Browse files

SUNRPC: Update RPC server's TCP record marker decoder



Clean up: Update the RPC server's TCP record marker decoder to match the
constructs used by the RPC client's TCP socket transport.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent b7872fe8
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -26,8 +26,8 @@ struct svc_sock {
	void			(*sk_owspace)(struct sock *);
	void			(*sk_owspace)(struct sock *);


	/* private TCP part */
	/* private TCP part */
	int			sk_reclen;	/* length of record */
	u32			sk_reclen;	/* length of record */
	int			sk_tcplen;	/* current read length */
	u32			sk_tcplen;	/* current read length */
};
};


/*
/*
+12 −12
Original line number Original line Diff line number Diff line
@@ -46,6 +46,7 @@
#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/msg_prot.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/stats.h>


@@ -823,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
	 * the next four bytes. Otherwise try to gobble up as much as
	 * the next four bytes. Otherwise try to gobble up as much as
	 * possible up to the complete record length.
	 * possible up to the complete record length.
	 */
	 */
	if (svsk->sk_tcplen < 4) {
	if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
		unsigned long	want = 4 - svsk->sk_tcplen;
		int		want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
		struct kvec	iov;
		struct kvec	iov;


		iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
		iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
@@ -834,31 +835,30 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
		svsk->sk_tcplen += len;
		svsk->sk_tcplen += len;


		if (len < want) {
		if (len < want) {
			dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
			dprintk("svc: short recvfrom while reading record "
				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 */
			return -EAGAIN; /* record header not complete */
		}
		}


		svsk->sk_reclen = ntohl(svsk->sk_reclen);
		svsk->sk_reclen = ntohl(svsk->sk_reclen);
		if (!(svsk->sk_reclen & 0x80000000)) {
		if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) {
			/* FIXME: technically, a record can be fragmented,
			/* FIXME: technically, a record can be fragmented,
			 *  and non-terminal fragments will not have the top
			 *  and non-terminal fragments will not have the top
			 *  bit set in the fragment length header.
			 *  bit set in the fragment length header.
			 *  But apparently no known nfs clients send fragmented
			 *  But apparently no known nfs clients send fragmented
			 *  records. */
			 *  records. */
			if (net_ratelimit())
			if (net_ratelimit())
				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
				printk(KERN_NOTICE "RPC: multiple fragments "
				       " (non-terminal)\n",
					"per record not supported\n");
				       (unsigned long) svsk->sk_reclen);
			goto err_delete;
			goto err_delete;
		}
		}
		svsk->sk_reclen &= 0x7fffffff;
		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) {
			if (net_ratelimit())
			if (net_ratelimit())
				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
				printk(KERN_NOTICE "RPC: "
				       " (large)\n",
					"fragment too large: 0x%08lx\n",
					(unsigned long)svsk->sk_reclen);
					(unsigned long)svsk->sk_reclen);
			goto err_delete;
			goto err_delete;
		}
		}