diff options
-rw-r--r-- | net/sunrpc/xprtsock.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 25aae8c526e4..a4c06900f398 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -614,6 +614,22 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
614 | return status; | 614 | return status; |
615 | } | 615 | } |
616 | 616 | ||
617 | /** | ||
618 | * xs_tcp_shutdown - gracefully shut down a TCP socket | ||
619 | * @xprt: transport | ||
620 | * | ||
621 | * Initiates a graceful shutdown of the TCP socket by calling the | ||
622 | * equivalent of shutdown(SHUT_WR); | ||
623 | */ | ||
624 | static void xs_tcp_shutdown(struct rpc_xprt *xprt) | ||
625 | { | ||
626 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
627 | struct socket *sock = transport->sock; | ||
628 | |||
629 | if (sock != NULL) | ||
630 | kernel_sock_shutdown(sock, SHUT_WR); | ||
631 | } | ||
632 | |||
617 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | 633 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) |
618 | { | 634 | { |
619 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | 635 | u32 reclen = buf->len - sizeof(rpc_fraghdr); |
@@ -691,7 +707,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
691 | default: | 707 | default: |
692 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | 708 | dprintk("RPC: sendmsg returned unrecognized error %d\n", |
693 | -status); | 709 | -status); |
694 | xprt_disconnect(xprt); | 710 | xs_tcp_shutdown(xprt); |
695 | break; | 711 | break; |
696 | } | 712 | } |
697 | 713 | ||
@@ -1637,8 +1653,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work) | |||
1637 | break; | 1653 | break; |
1638 | default: | 1654 | default: |
1639 | /* get rid of existing socket, and retry */ | 1655 | /* get rid of existing socket, and retry */ |
1640 | xs_close(xprt); | 1656 | xs_tcp_shutdown(xprt); |
1641 | break; | ||
1642 | } | 1657 | } |
1643 | } | 1658 | } |
1644 | out: | 1659 | out: |
@@ -1697,8 +1712,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work) | |||
1697 | break; | 1712 | break; |
1698 | default: | 1713 | default: |
1699 | /* get rid of existing socket, and retry */ | 1714 | /* get rid of existing socket, and retry */ |
1700 | xs_close(xprt); | 1715 | xs_tcp_shutdown(xprt); |
1701 | break; | ||
1702 | } | 1716 | } |
1703 | } | 1717 | } |
1704 | out: | 1718 | out: |
@@ -1745,6 +1759,19 @@ static void xs_connect(struct rpc_task *task) | |||
1745 | } | 1759 | } |
1746 | } | 1760 | } |
1747 | 1761 | ||
1762 | static void xs_tcp_connect(struct rpc_task *task) | ||
1763 | { | ||
1764 | struct rpc_xprt *xprt = task->tk_xprt; | ||
1765 | |||
1766 | /* Initiate graceful shutdown of the socket if not already done */ | ||
1767 | if (test_bit(XPRT_CONNECTED, &xprt->state)) | ||
1768 | xs_tcp_shutdown(xprt); | ||
1769 | /* Exit if we need to wait for socket shutdown to complete */ | ||
1770 | if (test_bit(XPRT_CLOSING, &xprt->state)) | ||
1771 | return; | ||
1772 | xs_connect(task); | ||
1773 | } | ||
1774 | |||
1748 | /** | 1775 | /** |
1749 | * xs_udp_print_stats - display UDP socket-specifc stats | 1776 | * xs_udp_print_stats - display UDP socket-specifc stats |
1750 | * @xprt: rpc_xprt struct containing statistics | 1777 | * @xprt: rpc_xprt struct containing statistics |
@@ -1815,12 +1842,12 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1815 | .release_xprt = xs_tcp_release_xprt, | 1842 | .release_xprt = xs_tcp_release_xprt, |
1816 | .rpcbind = rpcb_getport_async, | 1843 | .rpcbind = rpcb_getport_async, |
1817 | .set_port = xs_set_port, | 1844 | .set_port = xs_set_port, |
1818 | .connect = xs_connect, | 1845 | .connect = xs_tcp_connect, |
1819 | .buf_alloc = rpc_malloc, | 1846 | .buf_alloc = rpc_malloc, |
1820 | .buf_free = rpc_free, | 1847 | .buf_free = rpc_free, |
1821 | .send_request = xs_tcp_send_request, | 1848 | .send_request = xs_tcp_send_request, |
1822 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | 1849 | .set_retrans_timeout = xprt_set_retrans_timeout_def, |
1823 | .close = xs_close, | 1850 | .close = xs_tcp_shutdown, |
1824 | .destroy = xs_destroy, | 1851 | .destroy = xs_destroy, |
1825 | .print_stats = xs_tcp_print_stats, | 1852 | .print_stats = xs_tcp_print_stats, |
1826 | }; | 1853 | }; |