| @@ -19,6 +19,7 @@ · 18 unmodified lines |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | 21 | #include <linux/types.h> |
| 22 | +#include <linux/string.h> |
| 22 | 23 | #include <linux/slab.h> |
| 23 | 24 | #include <linux/module.h> |
| 24 | 25 | #include <linux/capability.h> |
| @@ -28,6 +29,7 @@ · 3 unmodified lines |
| 28 | 29 | #include <linux/in.h> |
| 29 | 30 | #include <linux/net.h> |
| 30 | 31 | #include <linux/mm.h> |
| 32 | +#include <linux/un.h> |
| 31 | 33 | #include <linux/udp.h> |
| 32 | 34 | #include <linux/tcp.h> |
| 33 | 35 | #include <linux/sunrpc/clnt.h> |
| @@ -45,6 +47,9 @@ · 11 unmodified lines |
| 45 | 47 | #include <net/tcp.h> |
| 46 | 48 | |
| 47 | 49 | #include "sunrpc.h" |
| 50 | + |
| 51 | +static void xs_close(struct rpc_xprt *xprt); |
| 52 | + |
| 48 | 53 | /* |
| 49 | 54 | * xprtsock tunables |
| 50 | 55 | */ |
| @@ -261,6 +266,11 @@ static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) · 210 unmodified lines |
| 261 | 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 | 274 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) |
| 265 | 275 | { |
| 266 | 276 | return (struct sockaddr_in *) &xprt->addr; |
| @@ -276,23 +286,34 @@ static void xs_format_common_peer_addresses(struct rpc_xprt *xprt) · 9 unmodified lines |
| 276 | 286 | struct sockaddr *sap = xs_addr(xprt); |
| 277 | 287 | struct sockaddr_in6 *sin6; |
| 278 | 288 | struct sockaddr_in *sin; |
| 289 | + struct sockaddr_un *sun; |
| 279 | 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 | 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 | 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 | 303 | sin = xs_addr_in(xprt); |
| 287 | 304 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); |
| 288 | 305 | break; |
| 289 | 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 | 310 | sin6 = xs_addr_in6(xprt); |
| 291 | 311 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); |
| 292 | 312 | break; |
| 293 | 313 | default: |
| 294 | 314 | BUG(); |
| 295 | 315 | } |
| 316 | + |
| 296 | 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) · 196 unmodified lines |
| 495 | 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 | 584 | * xs_udp_send_request - write an RPC request to a UDP socket |
| 500 | 585 | * @task: address of RPC task that manages the state of an RPC request |
| @@ -574,13 +659,6 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) · 73 unmodified lines |
| 574 | 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 | 663 | * xs_tcp_send_request - write an RPC request to a TCP socket |
| 586 | 664 | * @task: address of RPC task that manages the state of an RPC request |
| @@ -603,7 +681,7 @@ static int xs_tcp_send_request(struct rpc_task *task) · 16 unmodified lines |
| 603 | 681 | struct xdr_buf *xdr = &req->rq_snd_buf; |
| 604 | 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 | 686 | xs_pktdump("packet data:", |
| 609 | 687 | req->rq_svec->iov_base, |
| @@ -785,6 +863,88 @@ static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) · 175 unmodified lines |
| 785 | 863 | return (struct rpc_xprt *) sk->sk_user_data; |
| 786 | 864 | } |
| 787 | 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 | + |
| 788 | 948 | /** |
| 789 | 949 | * xs_udp_data_ready - "data ready" callback for UDP sockets |
| 790 | 950 | * @sk: socket with data to read |
| @@ -1344,7 +1504,6 @@ static void xs_tcp_state_change(struct sock *sk) · 553 unmodified lines |
| 1344 | 1504 | case TCP_CLOSE_WAIT: |
| 1345 | 1505 | /* The server initiated a shutdown of the socket */ |
| 1346 | 1506 | xprt_force_disconnect(xprt); |
| 1347 | | − case TCP_SYN_SENT: |
| 1348 | 1507 | xprt->connect_cookie++; |
| 1349 | 1508 | case TCP_CLOSING: |
| 1350 | 1509 | /* |
| @@ -1571,11 +1730,31 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) · 220 unmodified lines |
| 1571 | 1730 | return err; |
| 1572 | 1731 | } |
| 1573 | 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 | +} |
| 1574 | 1744 | |
| 1575 | 1745 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 1576 | 1746 | static struct lock_class_key xs_key[2]; |
| 1577 | 1747 | static struct lock_class_key xs_slock_key[2]; |
| 1578 | 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 | + |
| 1579 | 1758 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1580 | 1759 | { |
| 1581 | 1760 | struct sock *sk = sock->sk; |
| @@ -1597,6 +1776,9 @@ static inline void xs_reclassify_socket6(struct socket *sock) · 15 unmodified lines |
| 1597 | 1776 | static inline void xs_reclassify_socket(int family, struct socket *sock) |
| 1598 | 1777 | { |
| 1599 | 1778 | switch (family) { |
| 1779 | + case AF_LOCAL: |
| 1780 | + xs_reclassify_socketu(sock); |
| 1781 | + break; |
| 1600 | 1782 | case AF_INET: |
| 1601 | 1783 | xs_reclassify_socket4(sock); |
| 1602 | 1784 | break; |
| @@ -1606,6 +1788,10 @@ static inline void xs_reclassify_socket(int family, struct socket *sock) · 3 unmodified lines |
| 1606 | 1788 | } |
| 1607 | 1789 | } |
| 1608 | 1790 | #else |
| 1791 | +static inline void xs_reclassify_socketu(struct socket *sock) |
| 1792 | +{ |
| 1793 | +} |
| 1794 | + |
| 1609 | 1795 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1610 | 1796 | { |
| 1611 | 1797 | } |
| @@ -1644,6 +1830,94 @@ out: · 32 unmodified lines |
| 1644 | 1830 | return ERR_PTR(err); |
| 1645 | 1831 | } |
| 1646 | 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 | + |
| 1647 | 1921 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
| 1648 | 1922 | { |
| 1649 | 1923 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| @@ -1758,6 +2032,7 @@ static void xs_tcp_reuse_connection(struct sock_xprt *transport) · 108 unmodified lines |
| 1758 | 2032 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
| 1759 | 2033 | { |
| 1760 | 2034 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| 2035 | + int ret = -ENOTCONN; |
| 1761 | 2036 | |
| 1762 | 2037 | if (!transport->inet) { |
| 1763 | 2038 | struct sock *sk = sock->sk; |
| @@ -1789,12 +2064,22 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) · 25 unmodified lines |
| 1789 | 2064 | } |
| 1790 | 2065 | |
| 1791 | 2066 | if (!xprt_bound(xprt)) |
| 1792 | | − return -ENOTCONN; |
| 2067 | + goto out; |
| 1793 | 2068 | |
| 1794 | 2069 | /* Tell the socket layer to start connecting... */ |
| 1795 | 2070 | xprt->stat.connect_count++; |
| 1796 | 2071 | xprt->stat.connect_start = jiffies; |
| 1797 | | − 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; |
| 1798 | 2083 | } |
| 1799 | 2084 | |
| 1800 | 2085 | /** |
| @@ -1916,6 +2201,32 @@ static void xs_connect(struct rpc_task *task) · 115 unmodified lines |
| 1916 | 2201 | } |
| 1917 | 2202 | } |
| 1918 | 2203 | |
| 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 | + |
| 1919 | 2230 | /** |
| 1920 | 2231 | * xs_udp_print_stats - display UDP socket-specifc stats |
| 1921 | 2232 | * @xprt: rpc_xprt struct containing statistics |
| @@ -2014,10 +2325,7 @@ static int bc_sendto(struct rpc_rqst *req) · 92 unmodified lines |
| 2014 | 2325 | unsigned long headoff; |
| 2015 | 2326 | unsigned long tailoff; |
| 2016 | 2327 | |
| 2017 | | − /* |
| 2018 | | − * Set up the rpc header and record marker stuff |
| 2019 | | − */ |
| 2020 | | − xs_encode_tcp_record_marker(xbufp); |
| 2328 | + xs_encode_stream_record_marker(xbufp); |
| 2021 | 2329 | |
| 2022 | 2330 | tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; |
| 2023 | 2331 | headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; |
| @@ -2089,6 +2397,21 @@ static void bc_destroy(struct rpc_xprt *xprt) · 65 unmodified lines |
| 2089 | 2397 | { |
| 2090 | 2398 | } |
| 2091 | 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 | + |
| 2092 | 2415 | static struct rpc_xprt_ops xs_udp_ops = { |
| 2093 | 2416 | .set_buffer_size = xs_udp_set_buffer_size, |
| 2094 | 2417 | .reserve_xprt = xprt_reserve_xprt_cong, |
| @@ -2150,6 +2473,8 @@ static int xs_init_anyaddr(const int family, struct sockaddr *sap) · 55 unmodified lines |
| 2150 | 2473 | }; |
| 2151 | 2474 | |
| 2152 | 2475 | switch (family) { |
| 2476 | + case AF_LOCAL: |
| 2477 | + break; |
| 2153 | 2478 | case AF_INET: |
| 2154 | 2479 | memcpy(sap, &sin, sizeof(sin)); |
| 2155 | 2480 | break; |
| @@ -2197,6 +2522,70 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, · 41 unmodified lines |
| 2197 | 2522 | return xprt; |
| 2198 | 2523 | } |
| 2199 | 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 | + |
| 2200 | 2589 | static const struct rpc_timeout xs_udp_default_timeout = { |
| 2201 | 2590 | .to_initval = 5 * HZ, |
| 2202 | 2591 | .to_maxval = 30 * HZ, |
| @@ -2438,6 +2827,14 @@ out_err: · 235 unmodified lines |
| 2438 | 2827 | return ret; |
| 2439 | 2828 | } |
| 2440 | 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 | + |
| 2441 | 2838 | static struct xprt_class xs_udp_transport = { |
| 2442 | 2839 | .list = LIST_HEAD_INIT(xs_udp_transport.list), |
| 2443 | 2840 | .name = "udp", |
| @@ -2473,6 +2870,7 @@ int init_socket_xprt(void) · 29 unmodified lines |
| 2473 | 2870 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
| 2474 | 2871 | #endif |
| 2475 | 2872 | |
| 2873 | + xprt_register_transport(&xs_local_transport); |
| 2476 | 2874 | xprt_register_transport(&xs_udp_transport); |
| 2477 | 2875 | xprt_register_transport(&xs_tcp_transport); |
| 2478 | 2876 | xprt_register_transport(&xs_bc_tcp_transport); |
| @@ -2493,6 +2891,7 @@ void cleanup_socket_xprt(void) · 14 unmodified lines |
| 2493 | 2891 | } |
| 2494 | 2892 | #endif |
| 2495 | 2893 | |
| 2894 | + xprt_unregister_transport(&xs_local_transport); |
| 2496 | 2895 | xprt_unregister_transport(&xs_udp_transport); |
| 2497 | 2896 | xprt_unregister_transport(&xs_tcp_transport); |
| 2498 | 2897 | xprt_unregister_transport(&xs_bc_tcp_transport); |