Commit b70ae915 authored by Trond Myklebust's avatar Trond Myklebust

SUNRPC: Handle connection reset more efficiently.

If the connection reset is due to an active call on our side, then
the state change is sometimes not reported. Catch those instances
using xs_error_report() instead.
Also remove the xs_tcp_shutdown() call in xs_tcp_send_request() as
the change in behaviour makes it redundant.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 9e2b9f37
...@@ -718,7 +718,6 @@ static int xs_tcp_send_request(struct rpc_task *task) ...@@ -718,7 +718,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
dprintk("RPC: sendmsg returned unrecognized error %d\n", dprintk("RPC: sendmsg returned unrecognized error %d\n",
-status); -status);
case -ECONNRESET: case -ECONNRESET:
xs_tcp_shutdown(xprt);
case -ECONNREFUSED: case -ECONNREFUSED:
case -ENOTCONN: case -ENOTCONN:
case -EADDRINUSE: case -EADDRINUSE:
...@@ -774,6 +773,21 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s ...@@ -774,6 +773,21 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
sk->sk_error_report = transport->old_error_report; sk->sk_error_report = transport->old_error_report;
} }
static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
{
smp_mb__before_atomic();
clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
clear_bit(XPRT_CLOSING, &xprt->state);
smp_mb__after_atomic();
}
static void xs_sock_mark_closed(struct rpc_xprt *xprt)
{
xs_sock_reset_connection_flags(xprt);
/* Mark transport as closed and wake up all pending tasks */
xprt_disconnect_done(xprt);
}
/** /**
* xs_error_report - callback to handle TCP socket state errors * xs_error_report - callback to handle TCP socket state errors
* @sk: socket * @sk: socket
...@@ -793,6 +807,9 @@ static void xs_error_report(struct sock *sk) ...@@ -793,6 +807,9 @@ static void xs_error_report(struct sock *sk)
err = -sk->sk_err; err = -sk->sk_err;
if (err == 0) if (err == 0)
goto out; goto out;
/* Is this a reset event? */
if (sk->sk_state == TCP_CLOSE)
xs_sock_mark_closed(xprt);
dprintk("RPC: xs_error_report client %p, error=%d...\n", dprintk("RPC: xs_error_report client %p, error=%d...\n",
xprt, -err); xprt, -err);
trace_rpc_socket_error(xprt, sk->sk_socket, err); trace_rpc_socket_error(xprt, sk->sk_socket, err);
...@@ -801,14 +818,6 @@ static void xs_error_report(struct sock *sk) ...@@ -801,14 +818,6 @@ static void xs_error_report(struct sock *sk)
read_unlock_bh(&sk->sk_callback_lock); read_unlock_bh(&sk->sk_callback_lock);
} }
static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
{
smp_mb__before_atomic();
clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
clear_bit(XPRT_CLOSING, &xprt->state);
smp_mb__after_atomic();
}
static void xs_reset_transport(struct sock_xprt *transport) static void xs_reset_transport(struct sock_xprt *transport)
{ {
struct socket *sock = transport->sock; struct socket *sock = transport->sock;
...@@ -1421,13 +1430,6 @@ static void xs_tcp_data_ready(struct sock *sk) ...@@ -1421,13 +1430,6 @@ static void xs_tcp_data_ready(struct sock *sk)
read_unlock_bh(&sk->sk_callback_lock); read_unlock_bh(&sk->sk_callback_lock);
} }
static void xs_sock_mark_closed(struct rpc_xprt *xprt)
{
xs_sock_reset_connection_flags(xprt);
/* Mark transport as closed and wake up all pending tasks */
xprt_disconnect_done(xprt);
}
/** /**
* xs_tcp_state_change - callback to handle TCP socket state changes * xs_tcp_state_change - callback to handle TCP socket state changes
* @sk: socket whose state has changed * @sk: socket whose state has changed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment