aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-11-05 15:44:12 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-30 02:05:26 -0500
commite06799f958bf7f9f8fae15f0c6f519953fb0257c (patch)
treeb1dd5c6bee1d7fa3ecd45f85b20b001c4af2dcdd /net/sunrpc/xprtsock.c
parentef80367071dce7d2533e79ae8f3c84ec42708dc8 (diff)
SUNRPC: Use shutdown() instead of close() when disconnecting a TCP socket
By using shutdown() rather than close() we allow the RPC client to wait for the TCP close handshake to complete before we start trying to reconnect using the same port. We use shutdown(SHUT_WR) only instead of shutting down both directions, however we wait until the server has closed the connection on its side. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-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};