diff options
| -rw-r--r-- | include/linux/sunrpc/msg_prot.h | 1 | ||||
| -rw-r--r-- | include/linux/sunrpc/xprt.h | 3 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 8 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 395 |
4 files changed, 403 insertions, 4 deletions
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index 77e624883393..c68a147939a6 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h | |||
| @@ -145,6 +145,7 @@ typedef __be32 rpc_fraghdr; | |||
| 145 | #define RPCBIND_NETID_TCP "tcp" | 145 | #define RPCBIND_NETID_TCP "tcp" |
| 146 | #define RPCBIND_NETID_UDP6 "udp6" | 146 | #define RPCBIND_NETID_UDP6 "udp6" |
| 147 | #define RPCBIND_NETID_TCP6 "tcp6" | 147 | #define RPCBIND_NETID_TCP6 "tcp6" |
| 148 | #define RPCBIND_NETID_LOCAL "local" | ||
| 148 | 149 | ||
| 149 | /* | 150 | /* |
| 150 | * Note that RFC 1833 does not put any size restrictions on the | 151 | * Note that RFC 1833 does not put any size restrictions on the |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a0f998c07c65..81cce3b3ee66 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
| @@ -141,7 +141,8 @@ enum xprt_transports { | |||
| 141 | XPRT_TRANSPORT_UDP = IPPROTO_UDP, | 141 | XPRT_TRANSPORT_UDP = IPPROTO_UDP, |
| 142 | XPRT_TRANSPORT_TCP = IPPROTO_TCP, | 142 | XPRT_TRANSPORT_TCP = IPPROTO_TCP, |
| 143 | XPRT_TRANSPORT_BC_TCP = IPPROTO_TCP | XPRT_TRANSPORT_BC, | 143 | XPRT_TRANSPORT_BC_TCP = IPPROTO_TCP | XPRT_TRANSPORT_BC, |
| 144 | XPRT_TRANSPORT_RDMA = 256 | 144 | XPRT_TRANSPORT_RDMA = 256, |
| 145 | XPRT_TRANSPORT_LOCAL = 257, | ||
| 145 | }; | 146 | }; |
| 146 | 147 | ||
| 147 | struct rpc_xprt { | 148 | struct rpc_xprt { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 08ed49629b86..b84d7395535e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -28,7 +28,9 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| 31 | #include <linux/in.h> | ||
| 31 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 33 | #include <linux/un.h> | ||
| 32 | 34 | ||
| 33 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
| 34 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| @@ -294,6 +296,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 294 | * up a string representation of the passed-in address. | 296 | * up a string representation of the passed-in address. |
| 295 | */ | 297 | */ |
| 296 | if (args->servername == NULL) { | 298 | if (args->servername == NULL) { |
| 299 | struct sockaddr_un *sun = | ||
| 300 | (struct sockaddr_un *)args->address; | ||
| 297 | struct sockaddr_in *sin = | 301 | struct sockaddr_in *sin = |
| 298 | (struct sockaddr_in *)args->address; | 302 | (struct sockaddr_in *)args->address; |
| 299 | struct sockaddr_in6 *sin6 = | 303 | struct sockaddr_in6 *sin6 = |
| @@ -301,6 +305,10 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 301 | 305 | ||
| 302 | servername[0] = '\0'; | 306 | servername[0] = '\0'; |
| 303 | switch (args->address->sa_family) { | 307 | switch (args->address->sa_family) { |
| 308 | case AF_LOCAL: | ||
| 309 | snprintf(servername, sizeof(servername), "%s", | ||
| 310 | sun->sun_path); | ||
| 311 | break; | ||
| 304 | case AF_INET: | 312 | case AF_INET: |
| 305 | snprintf(servername, sizeof(servername), "%pI4", | 313 | snprintf(servername, sizeof(servername), "%pI4", |
| 306 | &sin->sin_addr.s_addr); | 314 | &sin->sin_addr.s_addr); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 079366974e1f..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 | ||
| @@ -506,6 +527,60 @@ static inline void xs_encode_stream_record_marker(struct xdr_buf *buf) | |||
| 506 | } | 527 | } |
| 507 | 528 | ||
| 508 | /** | 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 | |||
| 583 | /** | ||
| 509 | * 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 |
| 510 | * @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 |
| 511 | * | 586 | * |
| @@ -788,6 +863,88 @@ static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | |||
| 788 | return (struct rpc_xprt *) sk->sk_user_data; | 863 | return (struct rpc_xprt *) sk->sk_user_data; |
| 789 | } | 864 | } |
| 790 | 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 | |||
| 791 | /** | 948 | /** |
| 792 | * xs_udp_data_ready - "data ready" callback for UDP sockets | 949 | * xs_udp_data_ready - "data ready" callback for UDP sockets |
| 793 | * @sk: socket with data to read | 950 | * @sk: socket with data to read |
| @@ -1573,11 +1730,31 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
| 1573 | return err; | 1730 | return err; |
| 1574 | } | 1731 | } |
| 1575 | 1732 | ||
| 1733 | /* | ||
| 1734 | * We don't support autobind on AF_LOCAL sockets | ||
| 1735 | */ | ||
| 1736 | static void xs_local_rpcbind(struct rpc_task *task) | ||
| 1737 | { | ||
| 1738 | xprt_set_bound(task->tk_xprt); | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | static void xs_local_set_port(struct rpc_xprt *xprt, unsigned short port) | ||
| 1742 | { | ||
| 1743 | } | ||
| 1576 | 1744 | ||
| 1577 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 1745 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 1578 | static struct lock_class_key xs_key[2]; | 1746 | static struct lock_class_key xs_key[2]; |
| 1579 | static struct lock_class_key xs_slock_key[2]; | 1747 | static struct lock_class_key xs_slock_key[2]; |
| 1580 | 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 | |||
| 1581 | static inline void xs_reclassify_socket4(struct socket *sock) | 1758 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1582 | { | 1759 | { |
| 1583 | struct sock *sk = sock->sk; | 1760 | struct sock *sk = sock->sk; |
| @@ -1599,6 +1776,9 @@ static inline void xs_reclassify_socket6(struct socket *sock) | |||
| 1599 | static inline void xs_reclassify_socket(int family, struct socket *sock) | 1776 | static inline void xs_reclassify_socket(int family, struct socket *sock) |
| 1600 | { | 1777 | { |
| 1601 | switch (family) { | 1778 | switch (family) { |
| 1779 | case AF_LOCAL: | ||
| 1780 | xs_reclassify_socketu(sock); | ||
| 1781 | break; | ||
| 1602 | case AF_INET: | 1782 | case AF_INET: |
| 1603 | xs_reclassify_socket4(sock); | 1783 | xs_reclassify_socket4(sock); |
| 1604 | break; | 1784 | break; |
| @@ -1608,6 +1788,10 @@ static inline void xs_reclassify_socket(int family, struct socket *sock) | |||
| 1608 | } | 1788 | } |
| 1609 | } | 1789 | } |
| 1610 | #else | 1790 | #else |
| 1791 | static inline void xs_reclassify_socketu(struct socket *sock) | ||
| 1792 | { | ||
| 1793 | } | ||
| 1794 | |||
| 1611 | static inline void xs_reclassify_socket4(struct socket *sock) | 1795 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1612 | { | 1796 | { |
| 1613 | } | 1797 | } |
| @@ -1646,6 +1830,94 @@ out: | |||
| 1646 | return ERR_PTR(err); | 1830 | return ERR_PTR(err); |
| 1647 | } | 1831 | } |
| 1648 | 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); | ||
| 1838 | |||
| 1839 | if (!transport->inet) { | ||
| 1840 | struct sock *sk = sock->sk; | ||
| 1841 | |||
| 1842 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1843 | |||
| 1844 | xs_save_old_callbacks(transport, sk); | ||
| 1845 | |||
| 1846 | sk->sk_user_data = xprt; | ||
| 1847 | sk->sk_data_ready = xs_local_data_ready; | ||
| 1848 | sk->sk_write_space = xs_udp_write_space; | ||
| 1849 | sk->sk_error_report = xs_error_report; | ||
| 1850 | sk->sk_allocation = GFP_ATOMIC; | ||
| 1851 | |||
| 1852 | xprt_clear_connected(xprt); | ||
| 1853 | |||
| 1854 | /* Reset to new socket */ | ||
| 1855 | transport->sock = sock; | ||
| 1856 | transport->inet = sk; | ||
| 1857 | |||
| 1858 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1859 | } | ||
| 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); | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | /** | ||
| 1868 | * xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint | ||
| 1869 | * @xprt: RPC transport to connect | ||
| 1870 | * @transport: socket transport to connect | ||
| 1871 | * @create_sock: function to create a socket of the correct type | ||
| 1872 | * | ||
| 1873 | * Invoked by a work queue tasklet. | ||
| 1874 | */ | ||
| 1875 | static void xs_local_setup_socket(struct work_struct *work) | ||
| 1876 | { | ||
| 1877 | struct sock_xprt *transport = | ||
| 1878 | container_of(work, struct sock_xprt, connect_worker.work); | ||
| 1879 | struct rpc_xprt *xprt = &transport->xprt; | ||
| 1880 | struct socket *sock; | ||
| 1881 | int status = -EIO; | ||
| 1882 | |||
| 1883 | if (xprt->shutdown) | ||
| 1884 | goto out; | ||
| 1885 | |||
| 1886 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
| 1887 | status = __sock_create(xprt->xprt_net, AF_LOCAL, | ||
| 1888 | SOCK_STREAM, 0, &sock, 1); | ||
| 1889 | if (status < 0) { | ||
| 1890 | dprintk("RPC: can't create AF_LOCAL " | ||
| 1891 | "transport socket (%d).\n", -status); | ||
| 1892 | goto out; | ||
| 1893 | } | ||
| 1894 | xs_reclassify_socketu(sock); | ||
| 1895 | |||
| 1896 | dprintk("RPC: worker connecting xprt %p via AF_LOCAL to %s\n", | ||
| 1897 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 1898 | |||
| 1899 | status = xs_local_finish_connecting(xprt, sock); | ||
| 1900 | switch (status) { | ||
| 1901 | case 0: | ||
| 1902 | dprintk("RPC: xprt %p connected to %s\n", | ||
| 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 | } | ||
| 1915 | |||
| 1916 | out: | ||
| 1917 | xprt_clear_connecting(xprt); | ||
| 1918 | xprt_wake_pending_tasks(xprt, status); | ||
| 1919 | } | ||
| 1920 | |||
| 1649 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 1921 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
| 1650 | { | 1922 | { |
| 1651 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1923 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| @@ -1930,6 +2202,32 @@ static void xs_connect(struct rpc_task *task) | |||
| 1930 | } | 2202 | } |
| 1931 | 2203 | ||
| 1932 | /** | 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 | /** | ||
| 1933 | * xs_udp_print_stats - display UDP socket-specifc stats | 2231 | * xs_udp_print_stats - display UDP socket-specifc stats |
| 1934 | * @xprt: rpc_xprt struct containing statistics | 2232 | * @xprt: rpc_xprt struct containing statistics |
| 1935 | * @seq: output file | 2233 | * @seq: output file |
| @@ -2099,6 +2397,21 @@ static void bc_destroy(struct rpc_xprt *xprt) | |||
| 2099 | { | 2397 | { |
| 2100 | } | 2398 | } |
| 2101 | 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 | |||
| 2102 | static struct rpc_xprt_ops xs_udp_ops = { | 2415 | static struct rpc_xprt_ops xs_udp_ops = { |
| 2103 | .set_buffer_size = xs_udp_set_buffer_size, | 2416 | .set_buffer_size = xs_udp_set_buffer_size, |
| 2104 | .reserve_xprt = xprt_reserve_xprt_cong, | 2417 | .reserve_xprt = xprt_reserve_xprt_cong, |
| @@ -2160,6 +2473,8 @@ static int xs_init_anyaddr(const int family, struct sockaddr *sap) | |||
| 2160 | }; | 2473 | }; |
| 2161 | 2474 | ||
| 2162 | switch (family) { | 2475 | switch (family) { |
| 2476 | case AF_LOCAL: | ||
| 2477 | break; | ||
| 2163 | case AF_INET: | 2478 | case AF_INET: |
| 2164 | memcpy(sap, &sin, sizeof(sin)); | 2479 | memcpy(sap, &sin, sizeof(sin)); |
| 2165 | break; | 2480 | break; |
| @@ -2207,6 +2522,70 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | |||
| 2207 | return xprt; | 2522 | return xprt; |
| 2208 | } | 2523 | } |
| 2209 | 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 | |||
| 2210 | static const struct rpc_timeout xs_udp_default_timeout = { | 2589 | static const struct rpc_timeout xs_udp_default_timeout = { |
| 2211 | .to_initval = 5 * HZ, | 2590 | .to_initval = 5 * HZ, |
| 2212 | .to_maxval = 30 * HZ, | 2591 | .to_maxval = 30 * HZ, |
| @@ -2448,6 +2827,14 @@ out_err: | |||
| 2448 | return ret; | 2827 | return ret; |
| 2449 | } | 2828 | } |
| 2450 | 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 | |||
| 2451 | static struct xprt_class xs_udp_transport = { | 2838 | static struct xprt_class xs_udp_transport = { |
| 2452 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | 2839 | .list = LIST_HEAD_INIT(xs_udp_transport.list), |
| 2453 | .name = "udp", | 2840 | .name = "udp", |
| @@ -2483,6 +2870,7 @@ int init_socket_xprt(void) | |||
| 2483 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 2870 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
| 2484 | #endif | 2871 | #endif |
| 2485 | 2872 | ||
| 2873 | xprt_register_transport(&xs_local_transport); | ||
| 2486 | xprt_register_transport(&xs_udp_transport); | 2874 | xprt_register_transport(&xs_udp_transport); |
| 2487 | xprt_register_transport(&xs_tcp_transport); | 2875 | xprt_register_transport(&xs_tcp_transport); |
| 2488 | xprt_register_transport(&xs_bc_tcp_transport); | 2876 | xprt_register_transport(&xs_bc_tcp_transport); |
| @@ -2503,6 +2891,7 @@ void cleanup_socket_xprt(void) | |||
| 2503 | } | 2891 | } |
| 2504 | #endif | 2892 | #endif |
| 2505 | 2893 | ||
| 2894 | xprt_unregister_transport(&xs_local_transport); | ||
| 2506 | xprt_unregister_transport(&xs_udp_transport); | 2895 | xprt_unregister_transport(&xs_udp_transport); |
| 2507 | xprt_unregister_transport(&xs_tcp_transport); | 2896 | xprt_unregister_transport(&xs_tcp_transport); |
| 2508 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2897 | xprt_unregister_transport(&xs_bc_tcp_transport); |
