aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprtsock.c140
1 files changed, 72 insertions, 68 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 42222b4dd76d..f05a56e597ef 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1738,33 +1738,29 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
1738} 1738}
1739 1739
1740/** 1740/**
1741 * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint 1741 * xs_tcp_setup_socket - create a TCP socket and connect to a remote endpoint
1742 * @work: RPC transport to connect 1742 * @xprt: RPC transport to connect
1743 * @transport: socket transport to connect
1744 * @create_sock: function to create a socket of the correct type
1743 * 1745 *
1744 * Invoked by a work queue tasklet. 1746 * Invoked by a work queue tasklet.
1745 */ 1747 */
1746static void xs_tcp_connect_worker4(struct work_struct *work) 1748static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
1749 struct sock_xprt *transport,
1750 struct socket *(*create_sock)(struct rpc_xprt *,
1751 struct sock_xprt *))
1747{ 1752{
1748 struct sock_xprt *transport =
1749 container_of(work, struct sock_xprt, connect_worker.work);
1750 struct rpc_xprt *xprt = &transport->xprt;
1751 struct socket *sock = transport->sock; 1753 struct socket *sock = transport->sock;
1752 int err, status = -EIO; 1754 int status = -EIO;
1753 1755
1754 if (xprt->shutdown) 1756 if (xprt->shutdown)
1755 goto out; 1757 goto out;
1756 1758
1757 if (!sock) { 1759 if (!sock) {
1758 clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); 1760 clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
1759 /* start from scratch */ 1761 sock = create_sock(xprt, transport);
1760 if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { 1762 if (IS_ERR(sock)) {
1761 dprintk("RPC: can't create TCP transport socket (%d).\n", -err); 1763 status = PTR_ERR(sock);
1762 goto out;
1763 }
1764 xs_reclassify_socket4(sock);
1765
1766 if (xs_bind4(transport, sock) < 0) {
1767 sock_release(sock);
1768 goto out; 1764 goto out;
1769 } 1765 }
1770 } else { 1766 } else {
@@ -1808,74 +1804,82 @@ out:
1808 xprt_wake_pending_tasks(xprt, status); 1804 xprt_wake_pending_tasks(xprt, status);
1809} 1805}
1810 1806
1807static struct socket *xs_create_tcp_sock4(struct rpc_xprt *xprt,
1808 struct sock_xprt *transport)
1809{
1810 struct socket *sock;
1811 int err;
1812
1813 /* start from scratch */
1814 err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
1815 if (err < 0) {
1816 dprintk("RPC: can't create TCP transport socket (%d).\n",
1817 -err);
1818 goto out_err;
1819 }
1820 xs_reclassify_socket4(sock);
1821
1822 if (xs_bind4(transport, sock) < 0) {
1823 sock_release(sock);
1824 goto out_err;
1825 }
1826 return sock;
1827out_err:
1828 return ERR_PTR(-EIO);
1829}
1830
1811/** 1831/**
1812 * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint 1832 * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint
1813 * @work: RPC transport to connect 1833 * @work: RPC transport to connect
1814 * 1834 *
1815 * Invoked by a work queue tasklet. 1835 * Invoked by a work queue tasklet.
1816 */ 1836 */
1817static void xs_tcp_connect_worker6(struct work_struct *work) 1837static void xs_tcp_connect_worker4(struct work_struct *work)
1818{ 1838{
1819 struct sock_xprt *transport = 1839 struct sock_xprt *transport =
1820 container_of(work, struct sock_xprt, connect_worker.work); 1840 container_of(work, struct sock_xprt, connect_worker.work);
1821 struct rpc_xprt *xprt = &transport->xprt; 1841 struct rpc_xprt *xprt = &transport->xprt;
1822 struct socket *sock = transport->sock;
1823 int err, status = -EIO;
1824 1842
1825 if (xprt->shutdown) 1843 xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock4);
1826 goto out; 1844}
1827
1828 if (!sock) {
1829 clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
1830 /* start from scratch */
1831 if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
1832 dprintk("RPC: can't create TCP transport socket (%d).\n", -err);
1833 goto out;
1834 }
1835 xs_reclassify_socket6(sock);
1836 1845
1837 if (xs_bind6(transport, sock) < 0) { 1846static struct socket *xs_create_tcp_sock6(struct rpc_xprt *xprt,
1838 sock_release(sock); 1847 struct sock_xprt *transport)
1839 goto out; 1848{
1840 } 1849 struct socket *sock;
1841 } else { 1850 int err;
1842 int abort_and_exit;
1843 1851
1844 abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, 1852 /* start from scratch */
1845 &xprt->state); 1853 err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock);
1846 /* "close" the socket, preserving the local port */ 1854 if (err < 0) {
1847 xs_tcp_reuse_connection(xprt, transport); 1855 dprintk("RPC: can't create TCP transport socket (%d).\n",
1856 -err);
1857 goto out_err;
1858 }
1859 xs_reclassify_socket6(sock);
1848 1860
1849 if (abort_and_exit) 1861 if (xs_bind6(transport, sock) < 0) {
1850 goto out_eagain; 1862 sock_release(sock);
1863 goto out_err;
1851 } 1864 }
1865 return sock;
1866out_err:
1867 return ERR_PTR(-EIO);
1868}
1852 1869
1853 dprintk("RPC: worker connecting xprt %p to address: %s\n", 1870/**
1854 xprt, xprt->address_strings[RPC_DISPLAY_ALL]); 1871 * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint
1872 * @work: RPC transport to connect
1873 *
1874 * Invoked by a work queue tasklet.
1875 */
1876static void xs_tcp_connect_worker6(struct work_struct *work)
1877{
1878 struct sock_xprt *transport =
1879 container_of(work, struct sock_xprt, connect_worker.work);
1880 struct rpc_xprt *xprt = &transport->xprt;
1855 1881
1856 status = xs_tcp_finish_connecting(xprt, sock); 1882 xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock6);
1857 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
1858 xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
1859 switch (status) {
1860 case -ECONNREFUSED:
1861 case -ECONNRESET:
1862 case -ENETUNREACH:
1863 /* retry with existing socket, after a delay */
1864 case 0:
1865 case -EINPROGRESS:
1866 case -EALREADY:
1867 xprt_clear_connecting(xprt);
1868 return;
1869 }
1870 /* get rid of existing socket, and retry */
1871 xs_tcp_shutdown(xprt);
1872 printk("%s: connect returned unhandled error %d\n",
1873 __func__, status);
1874out_eagain:
1875 status = -EAGAIN;
1876out:
1877 xprt_clear_connecting(xprt);
1878 xprt_wake_pending_tasks(xprt, status);
1879} 1883}
1880 1884
1881/** 1885/**