diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtsock.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index cd7c18b24527..8295ae28391a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1261,6 +1261,39 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | |||
1261 | return err; | 1261 | return err; |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | ||
1265 | { | ||
1266 | struct sockaddr_in6 myaddr = { | ||
1267 | .sin6_family = AF_INET6, | ||
1268 | }; | ||
1269 | struct sockaddr_in6 *sa; | ||
1270 | int err; | ||
1271 | unsigned short port = transport->port; | ||
1272 | |||
1273 | if (!transport->xprt.resvport) | ||
1274 | port = 0; | ||
1275 | sa = (struct sockaddr_in6 *)&transport->addr; | ||
1276 | myaddr.sin6_addr = sa->sin6_addr; | ||
1277 | do { | ||
1278 | myaddr.sin6_port = htons(port); | ||
1279 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | ||
1280 | sizeof(myaddr)); | ||
1281 | if (!transport->xprt.resvport) | ||
1282 | break; | ||
1283 | if (err == 0) { | ||
1284 | transport->port = port; | ||
1285 | break; | ||
1286 | } | ||
1287 | if (port <= xprt_min_resvport) | ||
1288 | port = xprt_max_resvport; | ||
1289 | else | ||
1290 | port--; | ||
1291 | } while (err == -EADDRINUSE && port != transport->port); | ||
1292 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", | ||
1293 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); | ||
1294 | return err; | ||
1295 | } | ||
1296 | |||
1264 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 1297 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
1265 | static struct lock_class_key xs_key[2]; | 1298 | static struct lock_class_key xs_key[2]; |
1266 | static struct lock_class_key xs_slock_key[2]; | 1299 | static struct lock_class_key xs_slock_key[2]; |