diff options
author | Andy Chittenden <andyc.bluearc@gmail.com> | 2010-08-10 10:19:53 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-08-10 10:19:53 -0400 |
commit | 669502ff31d7dba1849aec7ee2450a3c61f57d39 (patch) | |
tree | a56e4958f71efcc5e9f844255e3d437e00306a06 /net | |
parent | f6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff) |
SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494)
When reusing a TCP connection, ensure that it's aborted if a previous
shutdown attempt has been made on that connection so that the RPC over
TCP recovery mechanism succeeds.
Signed-off-by: Andy Chittenden <andyc.bluearc@gmail.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtsock.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7ca65c7005ea..66d136984d57 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1305,10 +1305,11 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1305 | if (!(xprt = xprt_from_sock(sk))) | 1305 | if (!(xprt = xprt_from_sock(sk))) |
1306 | goto out; | 1306 | goto out; |
1307 | dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); | 1307 | dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); |
1308 | dprintk("RPC: state %x conn %d dead %d zapped %d\n", | 1308 | dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n", |
1309 | sk->sk_state, xprt_connected(xprt), | 1309 | sk->sk_state, xprt_connected(xprt), |
1310 | sock_flag(sk, SOCK_DEAD), | 1310 | sock_flag(sk, SOCK_DEAD), |
1311 | sock_flag(sk, SOCK_ZAPPED)); | 1311 | sock_flag(sk, SOCK_ZAPPED), |
1312 | sk->sk_shutdown); | ||
1312 | 1313 | ||
1313 | switch (sk->sk_state) { | 1314 | switch (sk->sk_state) { |
1314 | case TCP_ESTABLISHED: | 1315 | case TCP_ESTABLISHED: |
@@ -1779,10 +1780,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra | |||
1779 | { | 1780 | { |
1780 | unsigned int state = transport->inet->sk_state; | 1781 | unsigned int state = transport->inet->sk_state; |
1781 | 1782 | ||
1782 | if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) | 1783 | if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) { |
1783 | return; | 1784 | /* we don't need to abort the connection if the socket |
1784 | if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) | 1785 | * hasn't undergone a shutdown |
1785 | return; | 1786 | */ |
1787 | if (transport->inet->sk_shutdown == 0) | ||
1788 | return; | ||
1789 | dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n", | ||
1790 | __func__, transport->inet->sk_shutdown); | ||
1791 | } | ||
1792 | if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) { | ||
1793 | /* we don't need to abort the connection if the socket | ||
1794 | * hasn't undergone a shutdown | ||
1795 | */ | ||
1796 | if (transport->inet->sk_shutdown == 0) | ||
1797 | return; | ||
1798 | dprintk("RPC: %s: ESTABLISHED/SYN_SENT " | ||
1799 | "sk_shutdown set to %d\n", | ||
1800 | __func__, transport->inet->sk_shutdown); | ||
1801 | } | ||
1786 | xs_abort_connection(xprt, transport); | 1802 | xs_abort_connection(xprt, transport); |
1787 | } | 1803 | } |
1788 | 1804 | ||