summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/debug.h2
-rw-r--r--include/linux/sunrpc/xprt.h17
-rw-r--r--net/sunrpc/sysctl.c29
-rw-r--r--net/sunrpc/xprtsock.c23
4 files changed, 53 insertions, 18 deletions
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 42d299747956..1a42d902bc11 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -95,6 +95,8 @@ enum {
CTL_NLMDEBUG,
CTL_SLOTTABLE_UDP,
CTL_SLOTTABLE_TCP,
+ CTL_MIN_RESVPORT,
+ CTL_MAX_RESVPORT,
};
#endif /* _LINUX_SUNRPC_DEBUG_H_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index dcf0326bda01..9d9266cf8a36 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -52,6 +52,17 @@ extern unsigned int xprt_tcp_slot_table_entries;
#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
*/
struct rpc_timeout {
@@ -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);
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index ef483262f17f..d0c9f460e411 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -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 }
};
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 26402c063f00..62c2e7caa345 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -36,11 +36,6 @@
#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;