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

Commit 529b33c6 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

[PATCH] RPC: allow RPC client's port range to be adjustable



 Select an RPC client source port between 650 and 1023 instead of between
 1 and 800.  The old range conflicts with a number of network services.
 Provide sysctls to allow admins to select a different port range.

 Note that this doesn't affect user-level RPC library behavior, which
 still uses 1 to 800.

 Based on a suggestion by Olaf Kirch <okir@suse.de>.

 Test-plan:
 Repeated mount and unmount.  Destructive testing.  Idle timeouts.

 Signed-off-by: default avatarChuck Lever <cel@netapp.com>
 Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 555ee3af
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,8 @@ enum {
	CTL_NLMDEBUG,
	CTL_SLOTTABLE_UDP,
	CTL_SLOTTABLE_TCP,
	CTL_MIN_RESVPORT,
	CTL_MAX_RESVPORT,
};

#endif /* _LINUX_SUNRPC_DEBUG_H_ */
+14 −3
Original line number Diff line number Diff line
@@ -51,6 +51,17 @@ extern unsigned int xprt_tcp_slot_table_entries;
#define RPC_CALLHDRSIZE		6
#define RPC_REPHDRSIZE		4

/*
 * Parameters for choosing a free port
 */
extern unsigned int xprt_min_resvport;
extern unsigned int xprt_max_resvport;

#define RPC_MIN_RESVPORT	(1U)
#define RPC_MAX_RESVPORT	(65535U)
#define RPC_DEF_MIN_RESVPORT	(650U)
#define RPC_DEF_MAX_RESVPORT	(1023U)

/*
 * This describes a timeout strategy
 */
@@ -62,6 +73,9 @@ struct rpc_timeout {
	unsigned char		to_exponential;
};

struct rpc_task;
struct rpc_xprt;

/*
 * This describes a complete RPC request
 */
@@ -107,9 +121,6 @@ struct rpc_rqst {
#define rq_svec			rq_snd_buf.head
#define rq_slen			rq_snd_buf.len

struct rpc_task;
struct rpc_xprt;

struct rpc_xprt_ops {
	void		(*set_buffer_size)(struct rpc_xprt *xprt);
	int		(*reserve_xprt)(struct rpc_task *task);
+29 −0
Original line number Diff line number Diff line
@@ -121,9 +121,16 @@ done:

unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
EXPORT_SYMBOL(xprt_min_resvport);
unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
EXPORT_SYMBOL(xprt_max_resvport);


static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;

static ctl_table debug_table[] = {
	{
@@ -180,6 +187,28 @@ static ctl_table debug_table[] = {
		.extra1		= &min_slot_table_size,
		.extra2		= &max_slot_table_size
	},
	{
		.ctl_name	= CTL_MIN_RESVPORT,
		.procname	= "min_resvport",
		.data		= &xprt_min_resvport,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_minmax,
		.strategy	= &sysctl_intvec,
		.extra1		= &xprt_min_resvport_limit,
		.extra2		= &xprt_max_resvport_limit
	},
	{
		.ctl_name	= CTL_MAX_RESVPORT,
		.procname	= "max_resvport",
		.data		= &xprt_max_resvport,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_minmax,
		.strategy	= &sysctl_intvec,
		.extra1		= &xprt_min_resvport_limit,
		.extra2		= &xprt_max_resvport_limit
	},
	{ .ctl_name = 0 }
};

+8 −15
Original line number Diff line number Diff line
@@ -35,11 +35,6 @@
#include <net/udp.h>
#include <net/tcp.h>

/*
 * Maximum port number to use when requesting a reserved port.
 */
#define XS_MAX_RESVPORT		(800U)

/*
 * How many times to try sending a request on a socket before waiting
 * for the socket buffer to clear.
@@ -873,10 +868,9 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
	struct sockaddr_in myaddr = {
		.sin_family = AF_INET,
	};
	int err, port;
	int err;
	unsigned short port = xprt->port;

	/* Were we already bound to a given port? Try to reuse it */
	port = xprt->port;
	do {
		myaddr.sin_port = htons(port);
		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
@@ -887,8 +881,10 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
					port);
			return 0;
		}
		if (--port == 0)
			port = XS_MAX_RESVPORT;
		if (port <= xprt_min_resvport)
			port = xprt_max_resvport;
		else
			port--;
	} while (err == -EADDRINUSE && port != xprt->port);

	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
@@ -1075,9 +1071,6 @@ static struct rpc_xprt_ops xs_tcp_ops = {
	.destroy		= xs_destroy,
};

extern unsigned int xprt_udp_slot_table_entries;
extern unsigned int xprt_tcp_slot_table_entries;

/**
 * xs_setup_udp - Set up transport to use a UDP socket
 * @xprt: transport to set up
@@ -1098,7 +1091,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
	memset(xprt->slot, 0, slot_table_size);

	xprt->prot = IPPROTO_UDP;
	xprt->port = XS_MAX_RESVPORT;
	xprt->port = xprt_max_resvport;
	xprt->tsh_size = 0;
	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
	/* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1136,7 +1129,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
	memset(xprt->slot, 0, slot_table_size);

	xprt->prot = IPPROTO_TCP;
	xprt->port = XS_MAX_RESVPORT;
	xprt->port = xprt_max_resvport;
	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;