diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 798 |
1 files changed, 551 insertions, 247 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index fe9306bf10cc..72abb7358933 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/string.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
@@ -28,6 +29,7 @@ | |||
28 | #include <linux/in.h> | 29 | #include <linux/in.h> |
29 | #include <linux/net.h> | 30 | #include <linux/net.h> |
30 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/un.h> | ||
31 | #include <linux/udp.h> | 33 | #include <linux/udp.h> |
32 | #include <linux/tcp.h> | 34 | #include <linux/tcp.h> |
33 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
@@ -45,6 +47,9 @@ | |||
45 | #include <net/tcp.h> | 47 | #include <net/tcp.h> |
46 | 48 | ||
47 | #include "sunrpc.h" | 49 | #include "sunrpc.h" |
50 | |||
51 | static void xs_close(struct rpc_xprt *xprt); | ||
52 | |||
48 | /* | 53 | /* |
49 | * xprtsock tunables | 54 | * xprtsock tunables |
50 | */ | 55 | */ |
@@ -261,6 +266,11 @@ static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | |||
261 | return (struct sockaddr *) &xprt->addr; | 266 | return (struct sockaddr *) &xprt->addr; |
262 | } | 267 | } |
263 | 268 | ||
269 | static inline struct sockaddr_un *xs_addr_un(struct rpc_xprt *xprt) | ||
270 | { | ||
271 | return (struct sockaddr_un *) &xprt->addr; | ||
272 | } | ||
273 | |||
264 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) | 274 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) |
265 | { | 275 | { |
266 | return (struct sockaddr_in *) &xprt->addr; | 276 | return (struct sockaddr_in *) &xprt->addr; |
@@ -276,23 +286,34 @@ static void xs_format_common_peer_addresses(struct rpc_xprt *xprt) | |||
276 | struct sockaddr *sap = xs_addr(xprt); | 286 | struct sockaddr *sap = xs_addr(xprt); |
277 | struct sockaddr_in6 *sin6; | 287 | struct sockaddr_in6 *sin6; |
278 | struct sockaddr_in *sin; | 288 | struct sockaddr_in *sin; |
289 | struct sockaddr_un *sun; | ||
279 | char buf[128]; | 290 | char buf[128]; |
280 | 291 | ||
281 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
282 | xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); | ||
283 | |||
284 | switch (sap->sa_family) { | 292 | switch (sap->sa_family) { |
293 | case AF_LOCAL: | ||
294 | sun = xs_addr_un(xprt); | ||
295 | strlcpy(buf, sun->sun_path, sizeof(buf)); | ||
296 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
297 | kstrdup(buf, GFP_KERNEL); | ||
298 | break; | ||
285 | case AF_INET: | 299 | case AF_INET: |
300 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
301 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
302 | kstrdup(buf, GFP_KERNEL); | ||
286 | sin = xs_addr_in(xprt); | 303 | sin = xs_addr_in(xprt); |
287 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); | 304 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); |
288 | break; | 305 | break; |
289 | case AF_INET6: | 306 | case AF_INET6: |
307 | (void)rpc_ntop(sap, buf, sizeof(buf)); | ||
308 | xprt->address_strings[RPC_DISPLAY_ADDR] = | ||
309 | kstrdup(buf, GFP_KERNEL); | ||
290 | sin6 = xs_addr_in6(xprt); | 310 | sin6 = xs_addr_in6(xprt); |
291 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); | 311 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); |
292 | break; | 312 | break; |
293 | default: | 313 | default: |
294 | BUG(); | 314 | BUG(); |
295 | } | 315 | } |
316 | |||
296 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); | 317 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); |
297 | } | 318 | } |
298 | 319 | ||
@@ -495,6 +516,70 @@ static int xs_nospace(struct rpc_task *task) | |||
495 | return ret; | 516 | return ret; |
496 | } | 517 | } |
497 | 518 | ||
519 | /* | ||
520 | * Construct a stream transport record marker in @buf. | ||
521 | */ | ||
522 | static inline void xs_encode_stream_record_marker(struct xdr_buf *buf) | ||
523 | { | ||
524 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | ||
525 | rpc_fraghdr *base = buf->head[0].iov_base; | ||
526 | *base = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | reclen); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * xs_local_send_request - write an RPC request to an AF_LOCAL socket | ||
531 | * @task: RPC task that manages the state of an RPC request | ||
532 | * | ||
533 | * Return values: | ||
534 | * 0: The request has been sent | ||
535 | * EAGAIN: The socket was blocked, please call again later to | ||
536 | * complete the request | ||
537 | * ENOTCONN: Caller needs to invoke connect logic then call again | ||
538 | * other: Some other error occured, the request was not sent | ||
539 | */ | ||
540 | static int xs_local_send_request(struct rpc_task *task) | ||
541 | { | ||
542 | struct rpc_rqst *req = task->tk_rqstp; | ||
543 | struct rpc_xprt *xprt = req->rq_xprt; | ||
544 | struct sock_xprt *transport = | ||
545 | container_of(xprt, struct sock_xprt, xprt); | ||
546 | struct xdr_buf *xdr = &req->rq_snd_buf; | ||
547 | int status; | ||
548 | |||
549 | xs_encode_stream_record_marker(&req->rq_snd_buf); | ||
550 | |||
551 | xs_pktdump("packet data:", | ||
552 | req->rq_svec->iov_base, req->rq_svec->iov_len); | ||
553 | |||
554 | status = xs_sendpages(transport->sock, NULL, 0, | ||
555 | xdr, req->rq_bytes_sent); | ||
556 | dprintk("RPC: %s(%u) = %d\n", | ||
557 | __func__, xdr->len - req->rq_bytes_sent, status); | ||
558 | if (likely(status >= 0)) { | ||
559 | req->rq_bytes_sent += status; | ||
560 | req->rq_xmit_bytes_sent += status; | ||
561 | if (likely(req->rq_bytes_sent >= req->rq_slen)) { | ||
562 | req->rq_bytes_sent = 0; | ||
563 | return 0; | ||
564 | } | ||
565 | status = -EAGAIN; | ||
566 | } | ||
567 | |||
568 | switch (status) { | ||
569 | case -EAGAIN: | ||
570 | status = xs_nospace(task); | ||
571 | break; | ||
572 | default: | ||
573 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | ||
574 | -status); | ||
575 | case -EPIPE: | ||
576 | xs_close(xprt); | ||
577 | status = -ENOTCONN; | ||
578 | } | ||
579 | |||
580 | return status; | ||
581 | } | ||
582 | |||
498 | /** | 583 | /** |
499 | * xs_udp_send_request - write an RPC request to a UDP socket | 584 | * xs_udp_send_request - write an RPC request to a UDP socket |
500 | * @task: address of RPC task that manages the state of an RPC request | 585 | * @task: address of RPC task that manages the state of an RPC request |
@@ -504,7 +589,7 @@ static int xs_nospace(struct rpc_task *task) | |||
504 | * EAGAIN: The socket was blocked, please call again later to | 589 | * EAGAIN: The socket was blocked, please call again later to |
505 | * complete the request | 590 | * complete the request |
506 | * ENOTCONN: Caller needs to invoke connect logic then call again | 591 | * ENOTCONN: Caller needs to invoke connect logic then call again |
507 | * other: Some other error occured, the request was not sent | 592 | * other: Some other error occurred, the request was not sent |
508 | */ | 593 | */ |
509 | static int xs_udp_send_request(struct rpc_task *task) | 594 | static int xs_udp_send_request(struct rpc_task *task) |
510 | { | 595 | { |
@@ -574,13 +659,6 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) | |||
574 | kernel_sock_shutdown(sock, SHUT_WR); | 659 | kernel_sock_shutdown(sock, SHUT_WR); |
575 | } | 660 | } |
576 | 661 | ||
577 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | ||
578 | { | ||
579 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | ||
580 | rpc_fraghdr *base = buf->head[0].iov_base; | ||
581 | *base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen); | ||
582 | } | ||
583 | |||
584 | /** | 662 | /** |
585 | * xs_tcp_send_request - write an RPC request to a TCP socket | 663 | * xs_tcp_send_request - write an RPC request to a TCP socket |
586 | * @task: address of RPC task that manages the state of an RPC request | 664 | * @task: address of RPC task that manages the state of an RPC request |
@@ -590,7 +668,7 @@ static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | |||
590 | * EAGAIN: The socket was blocked, please call again later to | 668 | * EAGAIN: The socket was blocked, please call again later to |
591 | * complete the request | 669 | * complete the request |
592 | * ENOTCONN: Caller needs to invoke connect logic then call again | 670 | * ENOTCONN: Caller needs to invoke connect logic then call again |
593 | * other: Some other error occured, the request was not sent | 671 | * other: Some other error occurred, the request was not sent |
594 | * | 672 | * |
595 | * XXX: In the case of soft timeouts, should we eventually give up | 673 | * XXX: In the case of soft timeouts, should we eventually give up |
596 | * if sendmsg is not able to make progress? | 674 | * if sendmsg is not able to make progress? |
@@ -603,7 +681,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
603 | struct xdr_buf *xdr = &req->rq_snd_buf; | 681 | struct xdr_buf *xdr = &req->rq_snd_buf; |
604 | int status; | 682 | int status; |
605 | 683 | ||
606 | xs_encode_tcp_record_marker(&req->rq_snd_buf); | 684 | xs_encode_stream_record_marker(&req->rq_snd_buf); |
607 | 685 | ||
608 | xs_pktdump("packet data:", | 686 | xs_pktdump("packet data:", |
609 | req->rq_svec->iov_base, | 687 | req->rq_svec->iov_base, |
@@ -710,6 +788,8 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
710 | if (sk == NULL) | 788 | if (sk == NULL) |
711 | return; | 789 | return; |
712 | 790 | ||
791 | transport->srcport = 0; | ||
792 | |||
713 | write_lock_bh(&sk->sk_callback_lock); | 793 | write_lock_bh(&sk->sk_callback_lock); |
714 | transport->inet = NULL; | 794 | transport->inet = NULL; |
715 | transport->sock = NULL; | 795 | transport->sock = NULL; |
@@ -770,12 +850,11 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
770 | 850 | ||
771 | dprintk("RPC: xs_destroy xprt %p\n", xprt); | 851 | dprintk("RPC: xs_destroy xprt %p\n", xprt); |
772 | 852 | ||
773 | cancel_rearming_delayed_work(&transport->connect_worker); | 853 | cancel_delayed_work_sync(&transport->connect_worker); |
774 | 854 | ||
775 | xs_close(xprt); | 855 | xs_close(xprt); |
776 | xs_free_peer_addresses(xprt); | 856 | xs_free_peer_addresses(xprt); |
777 | kfree(xprt->slot); | 857 | xprt_free(xprt); |
778 | kfree(xprt); | ||
779 | module_put(THIS_MODULE); | 858 | module_put(THIS_MODULE); |
780 | } | 859 | } |
781 | 860 | ||
@@ -784,6 +863,88 @@ static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | |||
784 | return (struct rpc_xprt *) sk->sk_user_data; | 863 | return (struct rpc_xprt *) sk->sk_user_data; |
785 | } | 864 | } |
786 | 865 | ||
866 | static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | ||
867 | { | ||
868 | struct xdr_skb_reader desc = { | ||
869 | .skb = skb, | ||
870 | .offset = sizeof(rpc_fraghdr), | ||
871 | .count = skb->len - sizeof(rpc_fraghdr), | ||
872 | }; | ||
873 | |||
874 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0) | ||
875 | return -1; | ||
876 | if (desc.count) | ||
877 | return -1; | ||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | /** | ||
882 | * xs_local_data_ready - "data ready" callback for AF_LOCAL sockets | ||
883 | * @sk: socket with data to read | ||
884 | * @len: how much data to read | ||
885 | * | ||
886 | * Currently this assumes we can read the whole reply in a single gulp. | ||
887 | */ | ||
888 | static void xs_local_data_ready(struct sock *sk, int len) | ||
889 | { | ||
890 | struct rpc_task *task; | ||
891 | struct rpc_xprt *xprt; | ||
892 | struct rpc_rqst *rovr; | ||
893 | struct sk_buff *skb; | ||
894 | int err, repsize, copied; | ||
895 | u32 _xid; | ||
896 | __be32 *xp; | ||
897 | |||
898 | read_lock_bh(&sk->sk_callback_lock); | ||
899 | dprintk("RPC: %s...\n", __func__); | ||
900 | xprt = xprt_from_sock(sk); | ||
901 | if (xprt == NULL) | ||
902 | goto out; | ||
903 | |||
904 | skb = skb_recv_datagram(sk, 0, 1, &err); | ||
905 | if (skb == NULL) | ||
906 | goto out; | ||
907 | |||
908 | if (xprt->shutdown) | ||
909 | goto dropit; | ||
910 | |||
911 | repsize = skb->len - sizeof(rpc_fraghdr); | ||
912 | if (repsize < 4) { | ||
913 | dprintk("RPC: impossible RPC reply size %d\n", repsize); | ||
914 | goto dropit; | ||
915 | } | ||
916 | |||
917 | /* Copy the XID from the skb... */ | ||
918 | xp = skb_header_pointer(skb, sizeof(rpc_fraghdr), sizeof(_xid), &_xid); | ||
919 | if (xp == NULL) | ||
920 | goto dropit; | ||
921 | |||
922 | /* Look up and lock the request corresponding to the given XID */ | ||
923 | spin_lock(&xprt->transport_lock); | ||
924 | rovr = xprt_lookup_rqst(xprt, *xp); | ||
925 | if (!rovr) | ||
926 | goto out_unlock; | ||
927 | task = rovr->rq_task; | ||
928 | |||
929 | copied = rovr->rq_private_buf.buflen; | ||
930 | if (copied > repsize) | ||
931 | copied = repsize; | ||
932 | |||
933 | if (xs_local_copy_to_xdr(&rovr->rq_private_buf, skb)) { | ||
934 | dprintk("RPC: sk_buff copy failed\n"); | ||
935 | goto out_unlock; | ||
936 | } | ||
937 | |||
938 | xprt_complete_rqst(task, copied); | ||
939 | |||
940 | out_unlock: | ||
941 | spin_unlock(&xprt->transport_lock); | ||
942 | dropit: | ||
943 | skb_free_datagram(sk, skb); | ||
944 | out: | ||
945 | read_unlock_bh(&sk->sk_callback_lock); | ||
946 | } | ||
947 | |||
787 | /** | 948 | /** |
788 | * xs_udp_data_ready - "data ready" callback for UDP sockets | 949 | * xs_udp_data_ready - "data ready" callback for UDP sockets |
789 | * @sk: socket with data to read | 950 | * @sk: socket with data to read |
@@ -1343,7 +1504,6 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1343 | case TCP_CLOSE_WAIT: | 1504 | case TCP_CLOSE_WAIT: |
1344 | /* The server initiated a shutdown of the socket */ | 1505 | /* The server initiated a shutdown of the socket */ |
1345 | xprt_force_disconnect(xprt); | 1506 | xprt_force_disconnect(xprt); |
1346 | case TCP_SYN_SENT: | ||
1347 | xprt->connect_cookie++; | 1507 | xprt->connect_cookie++; |
1348 | case TCP_CLOSING: | 1508 | case TCP_CLOSING: |
1349 | /* | 1509 | /* |
@@ -1516,7 +1676,7 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | |||
1516 | xs_update_peer_port(xprt); | 1676 | xs_update_peer_port(xprt); |
1517 | } | 1677 | } |
1518 | 1678 | ||
1519 | static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket *sock) | 1679 | static unsigned short xs_get_srcport(struct sock_xprt *transport) |
1520 | { | 1680 | { |
1521 | unsigned short port = transport->srcport; | 1681 | unsigned short port = transport->srcport; |
1522 | 1682 | ||
@@ -1525,7 +1685,7 @@ static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket | |||
1525 | return port; | 1685 | return port; |
1526 | } | 1686 | } |
1527 | 1687 | ||
1528 | static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket *sock, unsigned short port) | 1688 | static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port) |
1529 | { | 1689 | { |
1530 | if (transport->srcport != 0) | 1690 | if (transport->srcport != 0) |
1531 | transport->srcport = 0; | 1691 | transport->srcport = 0; |
@@ -1535,23 +1695,18 @@ static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket | |||
1535 | return xprt_max_resvport; | 1695 | return xprt_max_resvport; |
1536 | return --port; | 1696 | return --port; |
1537 | } | 1697 | } |
1538 | 1698 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |
1539 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | ||
1540 | { | 1699 | { |
1541 | struct sockaddr_in myaddr = { | 1700 | struct sockaddr_storage myaddr; |
1542 | .sin_family = AF_INET, | ||
1543 | }; | ||
1544 | struct sockaddr_in *sa; | ||
1545 | int err, nloop = 0; | 1701 | int err, nloop = 0; |
1546 | unsigned short port = xs_get_srcport(transport, sock); | 1702 | unsigned short port = xs_get_srcport(transport); |
1547 | unsigned short last; | 1703 | unsigned short last; |
1548 | 1704 | ||
1549 | sa = (struct sockaddr_in *)&transport->srcaddr; | 1705 | memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen); |
1550 | myaddr.sin_addr = sa->sin_addr; | ||
1551 | do { | 1706 | do { |
1552 | myaddr.sin_port = htons(port); | 1707 | rpc_set_port((struct sockaddr *)&myaddr, port); |
1553 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1708 | err = kernel_bind(sock, (struct sockaddr *)&myaddr, |
1554 | sizeof(myaddr)); | 1709 | transport->xprt.addrlen); |
1555 | if (port == 0) | 1710 | if (port == 0) |
1556 | break; | 1711 | break; |
1557 | if (err == 0) { | 1712 | if (err == 0) { |
@@ -1559,52 +1714,47 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | |||
1559 | break; | 1714 | break; |
1560 | } | 1715 | } |
1561 | last = port; | 1716 | last = port; |
1562 | port = xs_next_srcport(transport, sock, port); | 1717 | port = xs_next_srcport(transport, port); |
1563 | if (port > last) | 1718 | if (port > last) |
1564 | nloop++; | 1719 | nloop++; |
1565 | } while (err == -EADDRINUSE && nloop != 2); | 1720 | } while (err == -EADDRINUSE && nloop != 2); |
1566 | dprintk("RPC: %s %pI4:%u: %s (%d)\n", | 1721 | |
1567 | __func__, &myaddr.sin_addr, | 1722 | if (myaddr.ss_family == AF_INET) |
1568 | port, err ? "failed" : "ok", err); | 1723 | dprintk("RPC: %s %pI4:%u: %s (%d)\n", __func__, |
1724 | &((struct sockaddr_in *)&myaddr)->sin_addr, | ||
1725 | port, err ? "failed" : "ok", err); | ||
1726 | else | ||
1727 | dprintk("RPC: %s %pI6:%u: %s (%d)\n", __func__, | ||
1728 | &((struct sockaddr_in6 *)&myaddr)->sin6_addr, | ||
1729 | port, err ? "failed" : "ok", err); | ||
1569 | return err; | 1730 | return err; |
1570 | } | 1731 | } |
1571 | 1732 | ||
1572 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | 1733 | /* |
1734 | * We don't support autobind on AF_LOCAL sockets | ||
1735 | */ | ||
1736 | static void xs_local_rpcbind(struct rpc_task *task) | ||
1573 | { | 1737 | { |
1574 | struct sockaddr_in6 myaddr = { | 1738 | xprt_set_bound(task->tk_xprt); |
1575 | .sin6_family = AF_INET6, | 1739 | } |
1576 | }; | ||
1577 | struct sockaddr_in6 *sa; | ||
1578 | int err, nloop = 0; | ||
1579 | unsigned short port = xs_get_srcport(transport, sock); | ||
1580 | unsigned short last; | ||
1581 | 1740 | ||
1582 | sa = (struct sockaddr_in6 *)&transport->srcaddr; | 1741 | static void xs_local_set_port(struct rpc_xprt *xprt, unsigned short port) |
1583 | myaddr.sin6_addr = sa->sin6_addr; | 1742 | { |
1584 | do { | ||
1585 | myaddr.sin6_port = htons(port); | ||
1586 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | ||
1587 | sizeof(myaddr)); | ||
1588 | if (port == 0) | ||
1589 | break; | ||
1590 | if (err == 0) { | ||
1591 | transport->srcport = port; | ||
1592 | break; | ||
1593 | } | ||
1594 | last = port; | ||
1595 | port = xs_next_srcport(transport, sock, port); | ||
1596 | if (port > last) | ||
1597 | nloop++; | ||
1598 | } while (err == -EADDRINUSE && nloop != 2); | ||
1599 | dprintk("RPC: xs_bind6 %pI6:%u: %s (%d)\n", | ||
1600 | &myaddr.sin6_addr, port, err ? "failed" : "ok", err); | ||
1601 | return err; | ||
1602 | } | 1743 | } |
1603 | 1744 | ||
1604 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 1745 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
1605 | static struct lock_class_key xs_key[2]; | 1746 | static struct lock_class_key xs_key[2]; |
1606 | static struct lock_class_key xs_slock_key[2]; | 1747 | static struct lock_class_key xs_slock_key[2]; |
1607 | 1748 | ||
1749 | static inline void xs_reclassify_socketu(struct socket *sock) | ||
1750 | { | ||
1751 | struct sock *sk = sock->sk; | ||
1752 | |||
1753 | BUG_ON(sock_owned_by_user(sk)); | ||
1754 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", | ||
1755 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); | ||
1756 | } | ||
1757 | |||
1608 | static inline void xs_reclassify_socket4(struct socket *sock) | 1758 | static inline void xs_reclassify_socket4(struct socket *sock) |
1609 | { | 1759 | { |
1610 | struct sock *sk = sock->sk; | 1760 | struct sock *sk = sock->sk; |
@@ -1622,7 +1772,26 @@ static inline void xs_reclassify_socket6(struct socket *sock) | |||
1622 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", | 1772 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
1623 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); | 1773 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
1624 | } | 1774 | } |
1775 | |||
1776 | static inline void xs_reclassify_socket(int family, struct socket *sock) | ||
1777 | { | ||
1778 | switch (family) { | ||
1779 | case AF_LOCAL: | ||
1780 | xs_reclassify_socketu(sock); | ||
1781 | break; | ||
1782 | case AF_INET: | ||
1783 | xs_reclassify_socket4(sock); | ||
1784 | break; | ||
1785 | case AF_INET6: | ||
1786 | xs_reclassify_socket6(sock); | ||
1787 | break; | ||
1788 | } | ||
1789 | } | ||
1625 | #else | 1790 | #else |
1791 | static inline void xs_reclassify_socketu(struct socket *sock) | ||
1792 | { | ||
1793 | } | ||
1794 | |||
1626 | static inline void xs_reclassify_socket4(struct socket *sock) | 1795 | static inline void xs_reclassify_socket4(struct socket *sock) |
1627 | { | 1796 | { |
1628 | } | 1797 | } |
@@ -1630,11 +1799,42 @@ static inline void xs_reclassify_socket4(struct socket *sock) | |||
1630 | static inline void xs_reclassify_socket6(struct socket *sock) | 1799 | static inline void xs_reclassify_socket6(struct socket *sock) |
1631 | { | 1800 | { |
1632 | } | 1801 | } |
1802 | |||
1803 | static inline void xs_reclassify_socket(int family, struct socket *sock) | ||
1804 | { | ||
1805 | } | ||
1633 | #endif | 1806 | #endif |
1634 | 1807 | ||
1635 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 1808 | static struct socket *xs_create_sock(struct rpc_xprt *xprt, |
1809 | struct sock_xprt *transport, int family, int type, int protocol) | ||
1636 | { | 1810 | { |
1637 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1811 | struct socket *sock; |
1812 | int err; | ||
1813 | |||
1814 | err = __sock_create(xprt->xprt_net, family, type, protocol, &sock, 1); | ||
1815 | if (err < 0) { | ||
1816 | dprintk("RPC: can't create %d transport socket (%d).\n", | ||
1817 | protocol, -err); | ||
1818 | goto out; | ||
1819 | } | ||
1820 | xs_reclassify_socket(family, sock); | ||
1821 | |||
1822 | err = xs_bind(transport, sock); | ||
1823 | if (err) { | ||
1824 | sock_release(sock); | ||
1825 | goto out; | ||
1826 | } | ||
1827 | |||
1828 | return sock; | ||
1829 | out: | ||
1830 | return ERR_PTR(err); | ||
1831 | } | ||
1832 | |||
1833 | static int xs_local_finish_connecting(struct rpc_xprt *xprt, | ||
1834 | struct socket *sock) | ||
1835 | { | ||
1836 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, | ||
1837 | xprt); | ||
1638 | 1838 | ||
1639 | if (!transport->inet) { | 1839 | if (!transport->inet) { |
1640 | struct sock *sk = sock->sk; | 1840 | struct sock *sk = sock->sk; |
@@ -1644,13 +1844,12 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1644 | xs_save_old_callbacks(transport, sk); | 1844 | xs_save_old_callbacks(transport, sk); |
1645 | 1845 | ||
1646 | sk->sk_user_data = xprt; | 1846 | sk->sk_user_data = xprt; |
1647 | sk->sk_data_ready = xs_udp_data_ready; | 1847 | sk->sk_data_ready = xs_local_data_ready; |
1648 | sk->sk_write_space = xs_udp_write_space; | 1848 | sk->sk_write_space = xs_udp_write_space; |
1649 | sk->sk_error_report = xs_error_report; | 1849 | sk->sk_error_report = xs_error_report; |
1650 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1651 | sk->sk_allocation = GFP_ATOMIC; | 1850 | sk->sk_allocation = GFP_ATOMIC; |
1652 | 1851 | ||
1653 | xprt_set_connected(xprt); | 1852 | xprt_clear_connected(xprt); |
1654 | 1853 | ||
1655 | /* Reset to new socket */ | 1854 | /* Reset to new socket */ |
1656 | transport->sock = sock; | 1855 | transport->sock = sock; |
@@ -1658,85 +1857,113 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1658 | 1857 | ||
1659 | write_unlock_bh(&sk->sk_callback_lock); | 1858 | write_unlock_bh(&sk->sk_callback_lock); |
1660 | } | 1859 | } |
1661 | xs_udp_do_set_buffer_size(xprt); | 1860 | |
1861 | /* Tell the socket layer to start connecting... */ | ||
1862 | xprt->stat.connect_count++; | ||
1863 | xprt->stat.connect_start = jiffies; | ||
1864 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, 0); | ||
1662 | } | 1865 | } |
1663 | 1866 | ||
1664 | /** | 1867 | /** |
1665 | * xs_udp_connect_worker4 - set up a UDP socket | 1868 | * xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint |
1666 | * @work: RPC transport to connect | 1869 | * @xprt: RPC transport to connect |
1870 | * @transport: socket transport to connect | ||
1871 | * @create_sock: function to create a socket of the correct type | ||
1667 | * | 1872 | * |
1668 | * Invoked by a work queue tasklet. | 1873 | * Invoked by a work queue tasklet. |
1669 | */ | 1874 | */ |
1670 | static void xs_udp_connect_worker4(struct work_struct *work) | 1875 | static void xs_local_setup_socket(struct work_struct *work) |
1671 | { | 1876 | { |
1672 | struct sock_xprt *transport = | 1877 | struct sock_xprt *transport = |
1673 | container_of(work, struct sock_xprt, connect_worker.work); | 1878 | container_of(work, struct sock_xprt, connect_worker.work); |
1674 | struct rpc_xprt *xprt = &transport->xprt; | 1879 | struct rpc_xprt *xprt = &transport->xprt; |
1675 | struct socket *sock = transport->sock; | 1880 | struct socket *sock; |
1676 | int err, status = -EIO; | 1881 | int status = -EIO; |
1677 | 1882 | ||
1678 | if (xprt->shutdown) | 1883 | if (xprt->shutdown) |
1679 | goto out; | 1884 | goto out; |
1680 | 1885 | ||
1681 | /* Start by resetting any existing state */ | 1886 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
1682 | xs_reset_transport(transport); | 1887 | status = __sock_create(xprt->xprt_net, AF_LOCAL, |
1683 | 1888 | SOCK_STREAM, 0, &sock, 1); | |
1684 | err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); | 1889 | if (status < 0) { |
1685 | if (err < 0) { | 1890 | dprintk("RPC: can't create AF_LOCAL " |
1686 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1891 | "transport socket (%d).\n", -status); |
1687 | goto out; | 1892 | goto out; |
1688 | } | 1893 | } |
1689 | xs_reclassify_socket4(sock); | 1894 | xs_reclassify_socketu(sock); |
1690 | 1895 | ||
1691 | if (xs_bind4(transport, sock)) { | 1896 | dprintk("RPC: worker connecting xprt %p via AF_LOCAL to %s\n", |
1692 | sock_release(sock); | 1897 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1693 | goto out; | ||
1694 | } | ||
1695 | 1898 | ||
1696 | dprintk("RPC: worker connecting xprt %p via %s to " | 1899 | status = xs_local_finish_connecting(xprt, sock); |
1697 | "%s (port %s)\n", xprt, | 1900 | switch (status) { |
1698 | xprt->address_strings[RPC_DISPLAY_PROTO], | 1901 | case 0: |
1699 | xprt->address_strings[RPC_DISPLAY_ADDR], | 1902 | dprintk("RPC: xprt %p connected to %s\n", |
1700 | xprt->address_strings[RPC_DISPLAY_PORT]); | 1903 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1904 | xprt_set_connected(xprt); | ||
1905 | break; | ||
1906 | case -ENOENT: | ||
1907 | dprintk("RPC: xprt %p: socket %s does not exist\n", | ||
1908 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
1909 | break; | ||
1910 | default: | ||
1911 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", | ||
1912 | __func__, -status, | ||
1913 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
1914 | } | ||
1701 | 1915 | ||
1702 | xs_udp_finish_connecting(xprt, sock); | ||
1703 | status = 0; | ||
1704 | out: | 1916 | out: |
1705 | xprt_clear_connecting(xprt); | 1917 | xprt_clear_connecting(xprt); |
1706 | xprt_wake_pending_tasks(xprt, status); | 1918 | xprt_wake_pending_tasks(xprt, status); |
1707 | } | 1919 | } |
1708 | 1920 | ||
1709 | /** | 1921 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
1710 | * xs_udp_connect_worker6 - set up a UDP socket | 1922 | { |
1711 | * @work: RPC transport to connect | 1923 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
1712 | * | 1924 | |
1713 | * Invoked by a work queue tasklet. | 1925 | if (!transport->inet) { |
1714 | */ | 1926 | struct sock *sk = sock->sk; |
1715 | static void xs_udp_connect_worker6(struct work_struct *work) | 1927 | |
1928 | write_lock_bh(&sk->sk_callback_lock); | ||
1929 | |||
1930 | xs_save_old_callbacks(transport, sk); | ||
1931 | |||
1932 | sk->sk_user_data = xprt; | ||
1933 | sk->sk_data_ready = xs_udp_data_ready; | ||
1934 | sk->sk_write_space = xs_udp_write_space; | ||
1935 | sk->sk_error_report = xs_error_report; | ||
1936 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
1937 | sk->sk_allocation = GFP_ATOMIC; | ||
1938 | |||
1939 | xprt_set_connected(xprt); | ||
1940 | |||
1941 | /* Reset to new socket */ | ||
1942 | transport->sock = sock; | ||
1943 | transport->inet = sk; | ||
1944 | |||
1945 | write_unlock_bh(&sk->sk_callback_lock); | ||
1946 | } | ||
1947 | xs_udp_do_set_buffer_size(xprt); | ||
1948 | } | ||
1949 | |||
1950 | static void xs_udp_setup_socket(struct work_struct *work) | ||
1716 | { | 1951 | { |
1717 | struct sock_xprt *transport = | 1952 | struct sock_xprt *transport = |
1718 | container_of(work, struct sock_xprt, connect_worker.work); | 1953 | container_of(work, struct sock_xprt, connect_worker.work); |
1719 | struct rpc_xprt *xprt = &transport->xprt; | 1954 | struct rpc_xprt *xprt = &transport->xprt; |
1720 | struct socket *sock = transport->sock; | 1955 | struct socket *sock = transport->sock; |
1721 | int err, status = -EIO; | 1956 | int status = -EIO; |
1722 | 1957 | ||
1723 | if (xprt->shutdown) | 1958 | if (xprt->shutdown) |
1724 | goto out; | 1959 | goto out; |
1725 | 1960 | ||
1726 | /* Start by resetting any existing state */ | 1961 | /* Start by resetting any existing state */ |
1727 | xs_reset_transport(transport); | 1962 | xs_reset_transport(transport); |
1728 | 1963 | sock = xs_create_sock(xprt, transport, | |
1729 | err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock); | 1964 | xs_addr(xprt)->sa_family, SOCK_DGRAM, IPPROTO_UDP); |
1730 | if (err < 0) { | 1965 | if (IS_ERR(sock)) |
1731 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | ||
1732 | goto out; | ||
1733 | } | ||
1734 | xs_reclassify_socket6(sock); | ||
1735 | |||
1736 | if (xs_bind6(transport, sock) < 0) { | ||
1737 | sock_release(sock); | ||
1738 | goto out; | 1966 | goto out; |
1739 | } | ||
1740 | 1967 | ||
1741 | dprintk("RPC: worker connecting xprt %p via %s to " | 1968 | dprintk("RPC: worker connecting xprt %p via %s to " |
1742 | "%s (port %s)\n", xprt, | 1969 | "%s (port %s)\n", xprt, |
@@ -1755,12 +1982,12 @@ out: | |||
1755 | * We need to preserve the port number so the reply cache on the server can | 1982 | * We need to preserve the port number so the reply cache on the server can |
1756 | * find our cached RPC replies when we get around to reconnecting. | 1983 | * find our cached RPC replies when we get around to reconnecting. |
1757 | */ | 1984 | */ |
1758 | static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transport) | 1985 | static void xs_abort_connection(struct sock_xprt *transport) |
1759 | { | 1986 | { |
1760 | int result; | 1987 | int result; |
1761 | struct sockaddr any; | 1988 | struct sockaddr any; |
1762 | 1989 | ||
1763 | dprintk("RPC: disconnecting xprt %p to reuse port\n", xprt); | 1990 | dprintk("RPC: disconnecting xprt %p to reuse port\n", transport); |
1764 | 1991 | ||
1765 | /* | 1992 | /* |
1766 | * Disconnect the transport socket by doing a connect operation | 1993 | * Disconnect the transport socket by doing a connect operation |
@@ -1770,13 +1997,13 @@ static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transpo | |||
1770 | any.sa_family = AF_UNSPEC; | 1997 | any.sa_family = AF_UNSPEC; |
1771 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 1998 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
1772 | if (!result) | 1999 | if (!result) |
1773 | xs_sock_mark_closed(xprt); | 2000 | xs_sock_mark_closed(&transport->xprt); |
1774 | else | 2001 | else |
1775 | dprintk("RPC: AF_UNSPEC connect return code %d\n", | 2002 | dprintk("RPC: AF_UNSPEC connect return code %d\n", |
1776 | result); | 2003 | result); |
1777 | } | 2004 | } |
1778 | 2005 | ||
1779 | static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *transport) | 2006 | static void xs_tcp_reuse_connection(struct sock_xprt *transport) |
1780 | { | 2007 | { |
1781 | unsigned int state = transport->inet->sk_state; | 2008 | unsigned int state = transport->inet->sk_state; |
1782 | 2009 | ||
@@ -1799,12 +2026,13 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra | |||
1799 | "sk_shutdown set to %d\n", | 2026 | "sk_shutdown set to %d\n", |
1800 | __func__, transport->inet->sk_shutdown); | 2027 | __func__, transport->inet->sk_shutdown); |
1801 | } | 2028 | } |
1802 | xs_abort_connection(xprt, transport); | 2029 | xs_abort_connection(transport); |
1803 | } | 2030 | } |
1804 | 2031 | ||
1805 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 2032 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
1806 | { | 2033 | { |
1807 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 2034 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
2035 | int ret = -ENOTCONN; | ||
1808 | 2036 | ||
1809 | if (!transport->inet) { | 2037 | if (!transport->inet) { |
1810 | struct sock *sk = sock->sk; | 2038 | struct sock *sk = sock->sk; |
@@ -1836,12 +2064,22 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1836 | } | 2064 | } |
1837 | 2065 | ||
1838 | if (!xprt_bound(xprt)) | 2066 | if (!xprt_bound(xprt)) |
1839 | return -ENOTCONN; | 2067 | goto out; |
1840 | 2068 | ||
1841 | /* Tell the socket layer to start connecting... */ | 2069 | /* Tell the socket layer to start connecting... */ |
1842 | xprt->stat.connect_count++; | 2070 | xprt->stat.connect_count++; |
1843 | xprt->stat.connect_start = jiffies; | 2071 | xprt->stat.connect_start = jiffies; |
1844 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); | 2072 | ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); |
2073 | switch (ret) { | ||
2074 | case 0: | ||
2075 | case -EINPROGRESS: | ||
2076 | /* SYN_SENT! */ | ||
2077 | xprt->connect_cookie++; | ||
2078 | if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) | ||
2079 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
2080 | } | ||
2081 | out: | ||
2082 | return ret; | ||
1845 | } | 2083 | } |
1846 | 2084 | ||
1847 | /** | 2085 | /** |
@@ -1852,12 +2090,12 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1852 | * | 2090 | * |
1853 | * Invoked by a work queue tasklet. | 2091 | * Invoked by a work queue tasklet. |
1854 | */ | 2092 | */ |
1855 | static void xs_tcp_setup_socket(struct rpc_xprt *xprt, | 2093 | static void xs_tcp_setup_socket(struct work_struct *work) |
1856 | struct sock_xprt *transport, | ||
1857 | struct socket *(*create_sock)(struct rpc_xprt *, | ||
1858 | struct sock_xprt *)) | ||
1859 | { | 2094 | { |
2095 | struct sock_xprt *transport = | ||
2096 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1860 | struct socket *sock = transport->sock; | 2097 | struct socket *sock = transport->sock; |
2098 | struct rpc_xprt *xprt = &transport->xprt; | ||
1861 | int status = -EIO; | 2099 | int status = -EIO; |
1862 | 2100 | ||
1863 | if (xprt->shutdown) | 2101 | if (xprt->shutdown) |
@@ -1865,7 +2103,8 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, | |||
1865 | 2103 | ||
1866 | if (!sock) { | 2104 | if (!sock) { |
1867 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 2105 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
1868 | sock = create_sock(xprt, transport); | 2106 | sock = xs_create_sock(xprt, transport, |
2107 | xs_addr(xprt)->sa_family, SOCK_STREAM, IPPROTO_TCP); | ||
1869 | if (IS_ERR(sock)) { | 2108 | if (IS_ERR(sock)) { |
1870 | status = PTR_ERR(sock); | 2109 | status = PTR_ERR(sock); |
1871 | goto out; | 2110 | goto out; |
@@ -1876,7 +2115,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, | |||
1876 | abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, | 2115 | abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, |
1877 | &xprt->state); | 2116 | &xprt->state); |
1878 | /* "close" the socket, preserving the local port */ | 2117 | /* "close" the socket, preserving the local port */ |
1879 | xs_tcp_reuse_connection(xprt, transport); | 2118 | xs_tcp_reuse_connection(transport); |
1880 | 2119 | ||
1881 | if (abort_and_exit) | 2120 | if (abort_and_exit) |
1882 | goto out_eagain; | 2121 | goto out_eagain; |
@@ -1925,84 +2164,6 @@ out: | |||
1925 | xprt_wake_pending_tasks(xprt, status); | 2164 | xprt_wake_pending_tasks(xprt, status); |
1926 | } | 2165 | } |
1927 | 2166 | ||
1928 | static struct socket *xs_create_tcp_sock4(struct rpc_xprt *xprt, | ||
1929 | struct sock_xprt *transport) | ||
1930 | { | ||
1931 | struct socket *sock; | ||
1932 | int err; | ||
1933 | |||
1934 | /* start from scratch */ | ||
1935 | err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); | ||
1936 | if (err < 0) { | ||
1937 | dprintk("RPC: can't create TCP transport socket (%d).\n", | ||
1938 | -err); | ||
1939 | goto out_err; | ||
1940 | } | ||
1941 | xs_reclassify_socket4(sock); | ||
1942 | |||
1943 | if (xs_bind4(transport, sock) < 0) { | ||
1944 | sock_release(sock); | ||
1945 | goto out_err; | ||
1946 | } | ||
1947 | return sock; | ||
1948 | out_err: | ||
1949 | return ERR_PTR(-EIO); | ||
1950 | } | ||
1951 | |||
1952 | /** | ||
1953 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint | ||
1954 | * @work: RPC transport to connect | ||
1955 | * | ||
1956 | * Invoked by a work queue tasklet. | ||
1957 | */ | ||
1958 | static void xs_tcp_connect_worker4(struct work_struct *work) | ||
1959 | { | ||
1960 | struct sock_xprt *transport = | ||
1961 | container_of(work, struct sock_xprt, connect_worker.work); | ||
1962 | struct rpc_xprt *xprt = &transport->xprt; | ||
1963 | |||
1964 | xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock4); | ||
1965 | } | ||
1966 | |||
1967 | static struct socket *xs_create_tcp_sock6(struct rpc_xprt *xprt, | ||
1968 | struct sock_xprt *transport) | ||
1969 | { | ||
1970 | struct socket *sock; | ||
1971 | int err; | ||
1972 | |||
1973 | /* start from scratch */ | ||
1974 | err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock); | ||
1975 | if (err < 0) { | ||
1976 | dprintk("RPC: can't create TCP transport socket (%d).\n", | ||
1977 | -err); | ||
1978 | goto out_err; | ||
1979 | } | ||
1980 | xs_reclassify_socket6(sock); | ||
1981 | |||
1982 | if (xs_bind6(transport, sock) < 0) { | ||
1983 | sock_release(sock); | ||
1984 | goto out_err; | ||
1985 | } | ||
1986 | return sock; | ||
1987 | out_err: | ||
1988 | return ERR_PTR(-EIO); | ||
1989 | } | ||
1990 | |||
1991 | /** | ||
1992 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint | ||
1993 | * @work: RPC transport to connect | ||
1994 | * | ||
1995 | * Invoked by a work queue tasklet. | ||
1996 | */ | ||
1997 | static void xs_tcp_connect_worker6(struct work_struct *work) | ||
1998 | { | ||
1999 | struct sock_xprt *transport = | ||
2000 | container_of(work, struct sock_xprt, connect_worker.work); | ||
2001 | struct rpc_xprt *xprt = &transport->xprt; | ||
2002 | |||
2003 | xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock6); | ||
2004 | } | ||
2005 | |||
2006 | /** | 2167 | /** |
2007 | * xs_connect - connect a socket to a remote endpoint | 2168 | * xs_connect - connect a socket to a remote endpoint |
2008 | * @task: address of RPC task that manages state of connect request | 2169 | * @task: address of RPC task that manages state of connect request |
@@ -2041,6 +2202,32 @@ static void xs_connect(struct rpc_task *task) | |||
2041 | } | 2202 | } |
2042 | 2203 | ||
2043 | /** | 2204 | /** |
2205 | * xs_local_print_stats - display AF_LOCAL socket-specifc stats | ||
2206 | * @xprt: rpc_xprt struct containing statistics | ||
2207 | * @seq: output file | ||
2208 | * | ||
2209 | */ | ||
2210 | static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | ||
2211 | { | ||
2212 | long idle_time = 0; | ||
2213 | |||
2214 | if (xprt_connected(xprt)) | ||
2215 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | ||
2216 | |||
2217 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " | ||
2218 | "%llu %llu\n", | ||
2219 | xprt->stat.bind_count, | ||
2220 | xprt->stat.connect_count, | ||
2221 | xprt->stat.connect_time, | ||
2222 | idle_time, | ||
2223 | xprt->stat.sends, | ||
2224 | xprt->stat.recvs, | ||
2225 | xprt->stat.bad_xids, | ||
2226 | xprt->stat.req_u, | ||
2227 | xprt->stat.bklog_u); | ||
2228 | } | ||
2229 | |||
2230 | /** | ||
2044 | * xs_udp_print_stats - display UDP socket-specifc stats | 2231 | * xs_udp_print_stats - display UDP socket-specifc stats |
2045 | * @xprt: rpc_xprt struct containing statistics | 2232 | * @xprt: rpc_xprt struct containing statistics |
2046 | * @seq: output file | 2233 | * @seq: output file |
@@ -2138,10 +2325,7 @@ static int bc_sendto(struct rpc_rqst *req) | |||
2138 | unsigned long headoff; | 2325 | unsigned long headoff; |
2139 | unsigned long tailoff; | 2326 | unsigned long tailoff; |
2140 | 2327 | ||
2141 | /* | 2328 | xs_encode_stream_record_marker(xbufp); |
2142 | * Set up the rpc header and record marker stuff | ||
2143 | */ | ||
2144 | xs_encode_tcp_record_marker(xbufp); | ||
2145 | 2329 | ||
2146 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; | 2330 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; |
2147 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; | 2331 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; |
@@ -2213,6 +2397,21 @@ static void bc_destroy(struct rpc_xprt *xprt) | |||
2213 | { | 2397 | { |
2214 | } | 2398 | } |
2215 | 2399 | ||
2400 | static struct rpc_xprt_ops xs_local_ops = { | ||
2401 | .reserve_xprt = xprt_reserve_xprt, | ||
2402 | .release_xprt = xs_tcp_release_xprt, | ||
2403 | .rpcbind = xs_local_rpcbind, | ||
2404 | .set_port = xs_local_set_port, | ||
2405 | .connect = xs_connect, | ||
2406 | .buf_alloc = rpc_malloc, | ||
2407 | .buf_free = rpc_free, | ||
2408 | .send_request = xs_local_send_request, | ||
2409 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | ||
2410 | .close = xs_close, | ||
2411 | .destroy = xs_destroy, | ||
2412 | .print_stats = xs_local_print_stats, | ||
2413 | }; | ||
2414 | |||
2216 | static struct rpc_xprt_ops xs_udp_ops = { | 2415 | static struct rpc_xprt_ops xs_udp_ops = { |
2217 | .set_buffer_size = xs_udp_set_buffer_size, | 2416 | .set_buffer_size = xs_udp_set_buffer_size, |
2218 | .reserve_xprt = xprt_reserve_xprt_cong, | 2417 | .reserve_xprt = xprt_reserve_xprt_cong, |
@@ -2262,6 +2461,33 @@ static struct rpc_xprt_ops bc_tcp_ops = { | |||
2262 | .print_stats = xs_tcp_print_stats, | 2461 | .print_stats = xs_tcp_print_stats, |
2263 | }; | 2462 | }; |
2264 | 2463 | ||
2464 | static int xs_init_anyaddr(const int family, struct sockaddr *sap) | ||
2465 | { | ||
2466 | static const struct sockaddr_in sin = { | ||
2467 | .sin_family = AF_INET, | ||
2468 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
2469 | }; | ||
2470 | static const struct sockaddr_in6 sin6 = { | ||
2471 | .sin6_family = AF_INET6, | ||
2472 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
2473 | }; | ||
2474 | |||
2475 | switch (family) { | ||
2476 | case AF_LOCAL: | ||
2477 | break; | ||
2478 | case AF_INET: | ||
2479 | memcpy(sap, &sin, sizeof(sin)); | ||
2480 | break; | ||
2481 | case AF_INET6: | ||
2482 | memcpy(sap, &sin6, sizeof(sin6)); | ||
2483 | break; | ||
2484 | default: | ||
2485 | dprintk("RPC: %s: Bad address family\n", __func__); | ||
2486 | return -EAFNOSUPPORT; | ||
2487 | } | ||
2488 | return 0; | ||
2489 | } | ||
2490 | |||
2265 | static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | 2491 | static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, |
2266 | unsigned int slot_table_size) | 2492 | unsigned int slot_table_size) |
2267 | { | 2493 | { |
@@ -2273,31 +2499,93 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | |||
2273 | return ERR_PTR(-EBADF); | 2499 | return ERR_PTR(-EBADF); |
2274 | } | 2500 | } |
2275 | 2501 | ||
2276 | new = kzalloc(sizeof(*new), GFP_KERNEL); | 2502 | xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size); |
2277 | if (new == NULL) { | 2503 | if (xprt == NULL) { |
2278 | dprintk("RPC: xs_setup_xprt: couldn't allocate " | 2504 | dprintk("RPC: xs_setup_xprt: couldn't allocate " |
2279 | "rpc_xprt\n"); | 2505 | "rpc_xprt\n"); |
2280 | return ERR_PTR(-ENOMEM); | 2506 | return ERR_PTR(-ENOMEM); |
2281 | } | 2507 | } |
2282 | xprt = &new->xprt; | ||
2283 | |||
2284 | xprt->max_reqs = slot_table_size; | ||
2285 | xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL); | ||
2286 | if (xprt->slot == NULL) { | ||
2287 | kfree(xprt); | ||
2288 | dprintk("RPC: xs_setup_xprt: couldn't allocate slot " | ||
2289 | "table\n"); | ||
2290 | return ERR_PTR(-ENOMEM); | ||
2291 | } | ||
2292 | 2508 | ||
2509 | new = container_of(xprt, struct sock_xprt, xprt); | ||
2293 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); | 2510 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); |
2294 | xprt->addrlen = args->addrlen; | 2511 | xprt->addrlen = args->addrlen; |
2295 | if (args->srcaddr) | 2512 | if (args->srcaddr) |
2296 | memcpy(&new->srcaddr, args->srcaddr, args->addrlen); | 2513 | memcpy(&new->srcaddr, args->srcaddr, args->addrlen); |
2514 | else { | ||
2515 | int err; | ||
2516 | err = xs_init_anyaddr(args->dstaddr->sa_family, | ||
2517 | (struct sockaddr *)&new->srcaddr); | ||
2518 | if (err != 0) | ||
2519 | return ERR_PTR(err); | ||
2520 | } | ||
2297 | 2521 | ||
2298 | return xprt; | 2522 | return xprt; |
2299 | } | 2523 | } |
2300 | 2524 | ||
2525 | static const struct rpc_timeout xs_local_default_timeout = { | ||
2526 | .to_initval = 10 * HZ, | ||
2527 | .to_maxval = 10 * HZ, | ||
2528 | .to_retries = 2, | ||
2529 | }; | ||
2530 | |||
2531 | /** | ||
2532 | * xs_setup_local - Set up transport to use an AF_LOCAL socket | ||
2533 | * @args: rpc transport creation arguments | ||
2534 | * | ||
2535 | * AF_LOCAL is a "tpi_cots_ord" transport, just like TCP | ||
2536 | */ | ||
2537 | static struct rpc_xprt *xs_setup_local(struct xprt_create *args) | ||
2538 | { | ||
2539 | struct sockaddr_un *sun = (struct sockaddr_un *)args->dstaddr; | ||
2540 | struct sock_xprt *transport; | ||
2541 | struct rpc_xprt *xprt; | ||
2542 | struct rpc_xprt *ret; | ||
2543 | |||
2544 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); | ||
2545 | if (IS_ERR(xprt)) | ||
2546 | return xprt; | ||
2547 | transport = container_of(xprt, struct sock_xprt, xprt); | ||
2548 | |||
2549 | xprt->prot = 0; | ||
2550 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | ||
2551 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | ||
2552 | |||
2553 | xprt->bind_timeout = XS_BIND_TO; | ||
2554 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
2555 | xprt->idle_timeout = XS_IDLE_DISC_TO; | ||
2556 | |||
2557 | xprt->ops = &xs_local_ops; | ||
2558 | xprt->timeout = &xs_local_default_timeout; | ||
2559 | |||
2560 | switch (sun->sun_family) { | ||
2561 | case AF_LOCAL: | ||
2562 | if (sun->sun_path[0] != '/') { | ||
2563 | dprintk("RPC: bad AF_LOCAL address: %s\n", | ||
2564 | sun->sun_path); | ||
2565 | ret = ERR_PTR(-EINVAL); | ||
2566 | goto out_err; | ||
2567 | } | ||
2568 | xprt_set_bound(xprt); | ||
2569 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
2570 | xs_local_setup_socket); | ||
2571 | xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL); | ||
2572 | break; | ||
2573 | default: | ||
2574 | ret = ERR_PTR(-EAFNOSUPPORT); | ||
2575 | goto out_err; | ||
2576 | } | ||
2577 | |||
2578 | dprintk("RPC: set up xprt to %s via AF_LOCAL\n", | ||
2579 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
2580 | |||
2581 | if (try_module_get(THIS_MODULE)) | ||
2582 | return xprt; | ||
2583 | ret = ERR_PTR(-EINVAL); | ||
2584 | out_err: | ||
2585 | xprt_free(xprt); | ||
2586 | return ret; | ||
2587 | } | ||
2588 | |||
2301 | static const struct rpc_timeout xs_udp_default_timeout = { | 2589 | static const struct rpc_timeout xs_udp_default_timeout = { |
2302 | .to_initval = 5 * HZ, | 2590 | .to_initval = 5 * HZ, |
2303 | .to_maxval = 30 * HZ, | 2591 | .to_maxval = 30 * HZ, |
@@ -2341,7 +2629,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
2341 | xprt_set_bound(xprt); | 2629 | xprt_set_bound(xprt); |
2342 | 2630 | ||
2343 | INIT_DELAYED_WORK(&transport->connect_worker, | 2631 | INIT_DELAYED_WORK(&transport->connect_worker, |
2344 | xs_udp_connect_worker4); | 2632 | xs_udp_setup_socket); |
2345 | xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP); | 2633 | xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP); |
2346 | break; | 2634 | break; |
2347 | case AF_INET6: | 2635 | case AF_INET6: |
@@ -2349,7 +2637,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
2349 | xprt_set_bound(xprt); | 2637 | xprt_set_bound(xprt); |
2350 | 2638 | ||
2351 | INIT_DELAYED_WORK(&transport->connect_worker, | 2639 | INIT_DELAYED_WORK(&transport->connect_worker, |
2352 | xs_udp_connect_worker6); | 2640 | xs_udp_setup_socket); |
2353 | xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6); | 2641 | xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6); |
2354 | break; | 2642 | break; |
2355 | default: | 2643 | default: |
@@ -2371,8 +2659,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
2371 | return xprt; | 2659 | return xprt; |
2372 | ret = ERR_PTR(-EINVAL); | 2660 | ret = ERR_PTR(-EINVAL); |
2373 | out_err: | 2661 | out_err: |
2374 | kfree(xprt->slot); | 2662 | xprt_free(xprt); |
2375 | kfree(xprt); | ||
2376 | return ret; | 2663 | return ret; |
2377 | } | 2664 | } |
2378 | 2665 | ||
@@ -2416,7 +2703,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
2416 | xprt_set_bound(xprt); | 2703 | xprt_set_bound(xprt); |
2417 | 2704 | ||
2418 | INIT_DELAYED_WORK(&transport->connect_worker, | 2705 | INIT_DELAYED_WORK(&transport->connect_worker, |
2419 | xs_tcp_connect_worker4); | 2706 | xs_tcp_setup_socket); |
2420 | xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP); | 2707 | xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP); |
2421 | break; | 2708 | break; |
2422 | case AF_INET6: | 2709 | case AF_INET6: |
@@ -2424,7 +2711,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
2424 | xprt_set_bound(xprt); | 2711 | xprt_set_bound(xprt); |
2425 | 2712 | ||
2426 | INIT_DELAYED_WORK(&transport->connect_worker, | 2713 | INIT_DELAYED_WORK(&transport->connect_worker, |
2427 | xs_tcp_connect_worker6); | 2714 | xs_tcp_setup_socket); |
2428 | xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6); | 2715 | xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6); |
2429 | break; | 2716 | break; |
2430 | default: | 2717 | default: |
@@ -2447,8 +2734,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
2447 | return xprt; | 2734 | return xprt; |
2448 | ret = ERR_PTR(-EINVAL); | 2735 | ret = ERR_PTR(-EINVAL); |
2449 | out_err: | 2736 | out_err: |
2450 | kfree(xprt->slot); | 2737 | xprt_free(xprt); |
2451 | kfree(xprt); | ||
2452 | return ret; | 2738 | return ret; |
2453 | } | 2739 | } |
2454 | 2740 | ||
@@ -2465,6 +2751,15 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2465 | struct svc_sock *bc_sock; | 2751 | struct svc_sock *bc_sock; |
2466 | struct rpc_xprt *ret; | 2752 | struct rpc_xprt *ret; |
2467 | 2753 | ||
2754 | if (args->bc_xprt->xpt_bc_xprt) { | ||
2755 | /* | ||
2756 | * This server connection already has a backchannel | ||
2757 | * export; we can't create a new one, as we wouldn't be | ||
2758 | * able to match replies based on xid any more. So, | ||
2759 | * reuse the already-existing one: | ||
2760 | */ | ||
2761 | return args->bc_xprt->xpt_bc_xprt; | ||
2762 | } | ||
2468 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); | 2763 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); |
2469 | if (IS_ERR(xprt)) | 2764 | if (IS_ERR(xprt)) |
2470 | return xprt; | 2765 | return xprt; |
@@ -2481,16 +2776,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2481 | xprt->reestablish_timeout = 0; | 2776 | xprt->reestablish_timeout = 0; |
2482 | xprt->idle_timeout = 0; | 2777 | xprt->idle_timeout = 0; |
2483 | 2778 | ||
2484 | /* | ||
2485 | * The backchannel uses the same socket connection as the | ||
2486 | * forechannel | ||
2487 | */ | ||
2488 | xprt->bc_xprt = args->bc_xprt; | ||
2489 | bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt); | ||
2490 | bc_sock->sk_bc_xprt = xprt; | ||
2491 | transport->sock = bc_sock->sk_sock; | ||
2492 | transport->inet = bc_sock->sk_sk; | ||
2493 | |||
2494 | xprt->ops = &bc_tcp_ops; | 2779 | xprt->ops = &bc_tcp_ops; |
2495 | 2780 | ||
2496 | switch (addr->sa_family) { | 2781 | switch (addr->sa_family) { |
@@ -2507,15 +2792,24 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2507 | goto out_err; | 2792 | goto out_err; |
2508 | } | 2793 | } |
2509 | 2794 | ||
2510 | if (xprt_bound(xprt)) | 2795 | dprintk("RPC: set up xprt to %s (port %s) via %s\n", |
2511 | dprintk("RPC: set up xprt to %s (port %s) via %s\n", | 2796 | xprt->address_strings[RPC_DISPLAY_ADDR], |
2512 | xprt->address_strings[RPC_DISPLAY_ADDR], | 2797 | xprt->address_strings[RPC_DISPLAY_PORT], |
2513 | xprt->address_strings[RPC_DISPLAY_PORT], | 2798 | xprt->address_strings[RPC_DISPLAY_PROTO]); |
2514 | xprt->address_strings[RPC_DISPLAY_PROTO]); | 2799 | |
2515 | else | 2800 | /* |
2516 | dprintk("RPC: set up xprt to %s (autobind) via %s\n", | 2801 | * Once we've associated a backchannel xprt with a connection, |
2517 | xprt->address_strings[RPC_DISPLAY_ADDR], | 2802 | * we want to keep it around as long as long as the connection |
2518 | xprt->address_strings[RPC_DISPLAY_PROTO]); | 2803 | * lasts, in case we need to start using it for a backchannel |
2804 | * again; this reference won't be dropped until bc_xprt is | ||
2805 | * destroyed. | ||
2806 | */ | ||
2807 | xprt_get(xprt); | ||
2808 | args->bc_xprt->xpt_bc_xprt = xprt; | ||
2809 | xprt->bc_xprt = args->bc_xprt; | ||
2810 | bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt); | ||
2811 | transport->sock = bc_sock->sk_sock; | ||
2812 | transport->inet = bc_sock->sk_sk; | ||
2519 | 2813 | ||
2520 | /* | 2814 | /* |
2521 | * Since we don't want connections for the backchannel, we set | 2815 | * Since we don't want connections for the backchannel, we set |
@@ -2526,13 +2820,21 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2526 | 2820 | ||
2527 | if (try_module_get(THIS_MODULE)) | 2821 | if (try_module_get(THIS_MODULE)) |
2528 | return xprt; | 2822 | return xprt; |
2823 | xprt_put(xprt); | ||
2529 | ret = ERR_PTR(-EINVAL); | 2824 | ret = ERR_PTR(-EINVAL); |
2530 | out_err: | 2825 | out_err: |
2531 | kfree(xprt->slot); | 2826 | xprt_free(xprt); |
2532 | kfree(xprt); | ||
2533 | return ret; | 2827 | return ret; |
2534 | } | 2828 | } |
2535 | 2829 | ||
2830 | static struct xprt_class xs_local_transport = { | ||
2831 | .list = LIST_HEAD_INIT(xs_local_transport.list), | ||
2832 | .name = "named UNIX socket", | ||
2833 | .owner = THIS_MODULE, | ||
2834 | .ident = XPRT_TRANSPORT_LOCAL, | ||
2835 | .setup = xs_setup_local, | ||
2836 | }; | ||
2837 | |||
2536 | static struct xprt_class xs_udp_transport = { | 2838 | static struct xprt_class xs_udp_transport = { |
2537 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | 2839 | .list = LIST_HEAD_INIT(xs_udp_transport.list), |
2538 | .name = "udp", | 2840 | .name = "udp", |
@@ -2568,6 +2870,7 @@ int init_socket_xprt(void) | |||
2568 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 2870 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
2569 | #endif | 2871 | #endif |
2570 | 2872 | ||
2873 | xprt_register_transport(&xs_local_transport); | ||
2571 | xprt_register_transport(&xs_udp_transport); | 2874 | xprt_register_transport(&xs_udp_transport); |
2572 | xprt_register_transport(&xs_tcp_transport); | 2875 | xprt_register_transport(&xs_tcp_transport); |
2573 | xprt_register_transport(&xs_bc_tcp_transport); | 2876 | xprt_register_transport(&xs_bc_tcp_transport); |
@@ -2588,6 +2891,7 @@ void cleanup_socket_xprt(void) | |||
2588 | } | 2891 | } |
2589 | #endif | 2892 | #endif |
2590 | 2893 | ||
2894 | xprt_unregister_transport(&xs_local_transport); | ||
2591 | xprt_unregister_transport(&xs_udp_transport); | 2895 | xprt_unregister_transport(&xs_udp_transport); |
2592 | xprt_unregister_transport(&xs_tcp_transport); | 2896 | xprt_unregister_transport(&xs_tcp_transport); |
2593 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2897 | xprt_unregister_transport(&xs_bc_tcp_transport); |