aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-03-18 20:46:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-28 15:55:28 -0400
commitfc28decdc93633a65d54e42498e9e819d466329c (patch)
tree19361a89093649d16c48e421ac2dfadc63c97fc6 /net
parent7d21c0f9845f0ce4e81baac3519fbb2c6c2cc908 (diff)
SUNRPC: Use IPv4 loopback for registering AF_INET6 kernel RPC services
The kernel uses an IPv6 loopback address when registering its AF_INET6 RPC services so that it can tell whether the local portmapper is actually IPv6-enabled. Since the legacy portmapper doesn't listen on IPv6, however, this causes a long timeout on older systems if the kernel happens to try creating and registering an AF_INET6 RPC service. Originally I wanted to use a connected transport (either TCP or connected UDP) so that the upcall would fail immediately if the portmapper wasn't listening on IPv6, but we never agreed on what transport to use. In the end, it's of little consequence to the kernel whether the local portmapper is listening on IPv6. It's only important whether the portmapper supports rpcbind v4. And the kernel can't tell that at all if it is sending requests via IPv6 -- the portmapper will just ignore them. So, send both rpcbind v2 and v4 SET/UNSET requests via IPv4 loopback to maintain better backwards compatibility between new kernels and legacy user space, and prevent multi-second hangs in some cases when the kernel attempts to register RPC services. This patch is part of a series that addresses http://bugzilla.kernel.org/show_bug.cgi?id=12256 Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/rpcb_clnt.c23
1 files changed, 6 insertions, 17 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 2caa7edeeaba..ebce7a5976c9 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -124,12 +124,6 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
124 .sin_port = htons(RPCBIND_PORT), 124 .sin_port = htons(RPCBIND_PORT),
125}; 125};
126 126
127static const struct sockaddr_in6 rpcb_in6addr_loopback = {
128 .sin6_family = AF_INET6,
129 .sin6_addr = IN6ADDR_LOOPBACK_INIT,
130 .sin6_port = htons(RPCBIND_PORT),
131};
132
133static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, 127static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr,
134 size_t addrlen, u32 version) 128 size_t addrlen, u32 version)
135{ 129{
@@ -176,9 +170,10 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
176 return rpc_create(&args); 170 return rpc_create(&args);
177} 171}
178 172
179static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, 173static int rpcb_register_call(u32 version, struct rpc_message *msg)
180 u32 version, struct rpc_message *msg)
181{ 174{
175 struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback;
176 size_t addrlen = sizeof(rpcb_inaddr_loopback);
182 struct rpc_clnt *rpcb_clnt; 177 struct rpc_clnt *rpcb_clnt;
183 int result, error = 0; 178 int result, error = 0;
184 179
@@ -254,9 +249,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
254 if (port) 249 if (port)
255 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; 250 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
256 251
257 return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, 252 return rpcb_register_call(RPCBVERS_2, &msg);
258 sizeof(rpcb_inaddr_loopback),
259 RPCBVERS_2, &msg);
260} 253}
261 254
262/* 255/*
@@ -284,9 +277,7 @@ static int rpcb_register_netid4(struct sockaddr_in *address_to_register,
284 if (port) 277 if (port)
285 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 278 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
286 279
287 return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, 280 return rpcb_register_call(RPCBVERS_4, msg);
288 sizeof(rpcb_inaddr_loopback),
289 RPCBVERS_4, msg);
290} 281}
291 282
292/* 283/*
@@ -318,9 +309,7 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
318 if (port) 309 if (port)
319 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 310 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
320 311
321 return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback, 312 return rpcb_register_call(RPCBVERS_4, msg);
322 sizeof(rpcb_in6addr_loopback),
323 RPCBVERS_4, msg);
324} 313}
325 314
326/** 315/**