diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-08-06 11:57:48 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-10-09 17:16:18 -0400 |
commit | 68e220bd5c9fc52d8029275cd42e08f573ce3600 (patch) | |
tree | 57ecf6ca21530662ea1a857cd467964f2eaf219e /net/sunrpc/xprtsock.c | |
parent | 9c3d72de28eed3e882becd7054da2118f8a73131 (diff) |
SUNRPC: create connect workers for IPv6
Clone separate connect worker functions for connecting AF_INET6 sockets.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a0c26b9ebb34..cc4db1763aa4 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1393,6 +1393,47 @@ out: | |||
1393 | xprt_clear_connecting(xprt); | 1393 | xprt_clear_connecting(xprt); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | /** | ||
1397 | * xs_udp_connect_worker6 - set up a UDP socket | ||
1398 | * @work: RPC transport to connect | ||
1399 | * | ||
1400 | * Invoked by a work queue tasklet. | ||
1401 | */ | ||
1402 | static void xs_udp_connect_worker6(struct work_struct *work) | ||
1403 | { | ||
1404 | struct sock_xprt *transport = | ||
1405 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1406 | struct rpc_xprt *xprt = &transport->xprt; | ||
1407 | struct socket *sock = transport->sock; | ||
1408 | int err, status = -EIO; | ||
1409 | |||
1410 | if (xprt->shutdown || !xprt_bound(xprt)) | ||
1411 | goto out; | ||
1412 | |||
1413 | /* Start by resetting any existing state */ | ||
1414 | xs_close(xprt); | ||
1415 | |||
1416 | if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { | ||
1417 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | ||
1418 | goto out; | ||
1419 | } | ||
1420 | xs_reclassify_socket(sock); | ||
1421 | |||
1422 | if (xs_bind6(transport, sock) < 0) { | ||
1423 | sock_release(sock); | ||
1424 | goto out; | ||
1425 | } | ||
1426 | |||
1427 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1428 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1429 | |||
1430 | xs_udp_finish_connecting(xprt, sock); | ||
1431 | status = 0; | ||
1432 | out: | ||
1433 | xprt_wake_pending_tasks(xprt, status); | ||
1434 | xprt_clear_connecting(xprt); | ||
1435 | } | ||
1436 | |||
1396 | /* | 1437 | /* |
1397 | * We need to preserve the port number so the reply cache on the server can | 1438 | * We need to preserve the port number so the reply cache on the server can |
1398 | * find our cached RPC replies when we get around to reconnecting. | 1439 | * find our cached RPC replies when we get around to reconnecting. |
@@ -1519,6 +1560,66 @@ out_clear: | |||
1519 | } | 1560 | } |
1520 | 1561 | ||
1521 | /** | 1562 | /** |
1563 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint | ||
1564 | * @work: RPC transport to connect | ||
1565 | * | ||
1566 | * Invoked by a work queue tasklet. | ||
1567 | */ | ||
1568 | static void xs_tcp_connect_worker6(struct work_struct *work) | ||
1569 | { | ||
1570 | struct sock_xprt *transport = | ||
1571 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1572 | struct rpc_xprt *xprt = &transport->xprt; | ||
1573 | struct socket *sock = transport->sock; | ||
1574 | int err, status = -EIO; | ||
1575 | |||
1576 | if (xprt->shutdown || !xprt_bound(xprt)) | ||
1577 | goto out; | ||
1578 | |||
1579 | if (!sock) { | ||
1580 | /* start from scratch */ | ||
1581 | if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
1582 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | ||
1583 | goto out; | ||
1584 | } | ||
1585 | xs_reclassify_socket(sock); | ||
1586 | |||
1587 | if (xs_bind6(transport, sock) < 0) { | ||
1588 | sock_release(sock); | ||
1589 | goto out; | ||
1590 | } | ||
1591 | } else | ||
1592 | /* "close" the socket, preserving the local port */ | ||
1593 | xs_tcp_reuse_connection(xprt); | ||
1594 | |||
1595 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1596 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
1597 | |||
1598 | status = xs_tcp_finish_connecting(xprt, sock); | ||
1599 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | ||
1600 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); | ||
1601 | if (status < 0) { | ||
1602 | switch (status) { | ||
1603 | case -EINPROGRESS: | ||
1604 | case -EALREADY: | ||
1605 | goto out_clear; | ||
1606 | case -ECONNREFUSED: | ||
1607 | case -ECONNRESET: | ||
1608 | /* retry with existing socket, after a delay */ | ||
1609 | break; | ||
1610 | default: | ||
1611 | /* get rid of existing socket, and retry */ | ||
1612 | xs_close(xprt); | ||
1613 | break; | ||
1614 | } | ||
1615 | } | ||
1616 | out: | ||
1617 | xprt_wake_pending_tasks(xprt, status); | ||
1618 | out_clear: | ||
1619 | xprt_clear_connecting(xprt); | ||
1620 | } | ||
1621 | |||
1622 | /** | ||
1522 | * xs_connect - connect a socket to a remote endpoint | 1623 | * xs_connect - connect a socket to a remote endpoint |
1523 | * @task: address of RPC task that manages state of connect request | 1624 | * @task: address of RPC task that manages state of connect request |
1524 | * | 1625 | * |