| From 78e4ee0eb3280bbd319b86c41ad90e0d63ec3aa6 Mon Sep 17 00:00:00 2001 |
| From: Andy Chittenden <andyc.bluearc@gmail.com> |
| Date: Tue, 10 Aug 2010 10:19:53 -0400 |
| Subject: [PATCH] SUNRPC: fix NFS client over TCP hangs due to packet loss |
| (Bug 16494) |
| |
| commit 669502ff31d7dba1849aec7ee2450a3c61f57d39 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c |
| index b613cb7..9bfb685 100644 |
| --- a/net/sunrpc/xprtsock.c |
| +++ b/net/sunrpc/xprtsock.c |
| @@ -1324,10 +1324,11 @@ static void xs_tcp_state_change(struct sock *sk) |
| if (!(xprt = xprt_from_sock(sk))) |
| goto out; |
| dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); |
| - dprintk("RPC: state %x conn %d dead %d zapped %d\n", |
| + dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n", |
| sk->sk_state, xprt_connected(xprt), |
| sock_flag(sk, SOCK_DEAD), |
| - sock_flag(sk, SOCK_ZAPPED)); |
| + sock_flag(sk, SOCK_ZAPPED), |
| + sk->sk_shutdown); |
| |
| switch (sk->sk_state) { |
| case TCP_ESTABLISHED: |
| @@ -1798,10 +1799,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra |
| { |
| unsigned int state = transport->inet->sk_state; |
| |
| - if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) |
| - return; |
| - if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) |
| - return; |
| + if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) { |
| + /* we don't need to abort the connection if the socket |
| + * hasn't undergone a shutdown |
| + */ |
| + if (transport->inet->sk_shutdown == 0) |
| + return; |
| + dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n", |
| + __func__, transport->inet->sk_shutdown); |
| + } |
| + if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) { |
| + /* we don't need to abort the connection if the socket |
| + * hasn't undergone a shutdown |
| + */ |
| + if (transport->inet->sk_shutdown == 0) |
| + return; |
| + dprintk("RPC: %s: ESTABLISHED/SYN_SENT " |
| + "sk_shutdown set to %d\n", |
| + __func__, transport->inet->sk_shutdown); |
| + } |
| xs_abort_connection(xprt, transport); |
| } |
| |
| -- |
| 1.7.7 |
| |