Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

authored by

Chuck Lever and committed by
Trond Myklebust
529b33c6 555ee3af

+53 -18
+2
include/linux/sunrpc/debug.h
··· 95 95 CTL_NLMDEBUG, 96 96 CTL_SLOTTABLE_UDP, 97 97 CTL_SLOTTABLE_TCP, 98 + CTL_MIN_RESVPORT, 99 + CTL_MAX_RESVPORT, 98 100 }; 99 101 100 102 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
+14 -3
include/linux/sunrpc/xprt.h
··· 52 52 #define RPC_REPHDRSIZE 4 53 53 54 54 /* 55 + * Parameters for choosing a free port 56 + */ 57 + extern unsigned int xprt_min_resvport; 58 + extern unsigned int xprt_max_resvport; 59 + 60 + #define RPC_MIN_RESVPORT (1U) 61 + #define RPC_MAX_RESVPORT (65535U) 62 + #define RPC_DEF_MIN_RESVPORT (650U) 63 + #define RPC_DEF_MAX_RESVPORT (1023U) 64 + 65 + /* 55 66 * This describes a timeout strategy 56 67 */ 57 68 struct rpc_timeout { ··· 72 61 unsigned int to_retries; /* max # of retries */ 73 62 unsigned char to_exponential; 74 63 }; 64 + 65 + struct rpc_task; 66 + struct rpc_xprt; 75 67 76 68 /* 77 69 * This describes a complete RPC request ··· 120 106 }; 121 107 #define rq_svec rq_snd_buf.head 122 108 #define rq_slen rq_snd_buf.len 123 - 124 - struct rpc_task; 125 - struct rpc_xprt; 126 109 127 110 struct rpc_xprt_ops { 128 111 void (*set_buffer_size)(struct rpc_xprt *xprt);
+29
net/sunrpc/sysctl.c
··· 121 121 122 122 unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; 123 123 unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE; 124 + unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; 125 + EXPORT_SYMBOL(xprt_min_resvport); 126 + unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; 127 + EXPORT_SYMBOL(xprt_max_resvport); 128 + 124 129 125 130 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE; 126 131 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE; 132 + static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT; 133 + static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT; 127 134 128 135 static ctl_table debug_table[] = { 129 136 { ··· 186 179 .strategy = &sysctl_intvec, 187 180 .extra1 = &min_slot_table_size, 188 181 .extra2 = &max_slot_table_size 182 + }, 183 + { 184 + .ctl_name = CTL_MIN_RESVPORT, 185 + .procname = "min_resvport", 186 + .data = &xprt_min_resvport, 187 + .maxlen = sizeof(unsigned int), 188 + .mode = 0644, 189 + .proc_handler = &proc_dointvec_minmax, 190 + .strategy = &sysctl_intvec, 191 + .extra1 = &xprt_min_resvport_limit, 192 + .extra2 = &xprt_max_resvport_limit 193 + }, 194 + { 195 + .ctl_name = CTL_MAX_RESVPORT, 196 + .procname = "max_resvport", 197 + .data = &xprt_max_resvport, 198 + .maxlen = sizeof(unsigned int), 199 + .mode = 0644, 200 + .proc_handler = &proc_dointvec_minmax, 201 + .strategy = &sysctl_intvec, 202 + .extra1 = &xprt_min_resvport_limit, 203 + .extra2 = &xprt_max_resvport_limit 189 204 }, 190 205 { .ctl_name = 0 } 191 206 };
+8 -15
net/sunrpc/xprtsock.c
··· 36 36 #include <net/tcp.h> 37 37 38 38 /* 39 - * Maximum port number to use when requesting a reserved port. 40 - */ 41 - #define XS_MAX_RESVPORT (800U) 42 - 43 - /* 44 39 * How many times to try sending a request on a socket before waiting 45 40 * for the socket buffer to clear. 46 41 */ ··· 868 873 struct sockaddr_in myaddr = { 869 874 .sin_family = AF_INET, 870 875 }; 871 - int err, port; 876 + int err; 877 + unsigned short port = xprt->port; 872 878 873 - /* Were we already bound to a given port? Try to reuse it */ 874 - port = xprt->port; 875 879 do { 876 880 myaddr.sin_port = htons(port); 877 881 err = sock->ops->bind(sock, (struct sockaddr *) &myaddr, ··· 881 887 port); 882 888 return 0; 883 889 } 884 - if (--port == 0) 885 - port = XS_MAX_RESVPORT; 890 + if (port <= xprt_min_resvport) 891 + port = xprt_max_resvport; 892 + else 893 + port--; 886 894 } while (err == -EADDRINUSE && port != xprt->port); 887 895 888 896 dprintk("RPC: can't bind to reserved port (%d).\n", -err); ··· 1071 1075 .destroy = xs_destroy, 1072 1076 }; 1073 1077 1074 - extern unsigned int xprt_udp_slot_table_entries; 1075 - extern unsigned int xprt_tcp_slot_table_entries; 1076 - 1077 1078 /** 1078 1079 * xs_setup_udp - Set up transport to use a UDP socket 1079 1080 * @xprt: transport to set up ··· 1091 1098 memset(xprt->slot, 0, slot_table_size); 1092 1099 1093 1100 xprt->prot = IPPROTO_UDP; 1094 - xprt->port = XS_MAX_RESVPORT; 1101 + xprt->port = xprt_max_resvport; 1095 1102 xprt->tsh_size = 0; 1096 1103 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1097 1104 /* XXX: header size can vary due to auth type, IPv6, etc. */ ··· 1129 1136 memset(xprt->slot, 0, slot_table_size); 1130 1137 1131 1138 xprt->prot = IPPROTO_TCP; 1132 - xprt->port = XS_MAX_RESVPORT; 1139 + xprt->port = xprt_max_resvport; 1133 1140 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); 1134 1141 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1135 1142 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;