aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/xprtsock.c41
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 */
624static 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
617static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) 633static 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 }
1644out: 1659out:
@@ -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 }
1704out: 1718out:
@@ -1745,6 +1759,19 @@ static void xs_connect(struct rpc_task *task)
1745 } 1759 }
1746} 1760}
1747 1761
1762static 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};