SUNRPC: Handle connection reset more efficiently.
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 9 Feb 2015 14:41:32 +0000 (09:41 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 9 Feb 2015 16:27:42 +0000 (11:27 -0500)
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: Trond Myklebust <trond.myklebust@primarydata.com>
net/sunrpc/xprtsock.c

index c72b13e2bdf52f2ab81069a7ff2e4161e84e8a3e..540d542d85e5596d180a488d490528152b4a82b6 100644 (file)
@@ -718,7 +718,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
        case -ECONNRESET:
-               xs_tcp_shutdown(xprt);
        case -ECONNREFUSED:
        case -ENOTCONN:
        case -EADDRINUSE:
@@ -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;
 }
 
+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
  * @sk: socket
@@ -793,6 +807,9 @@ static void xs_error_report(struct sock *sk)
        err = -sk->sk_err;
        if (err == 0)
                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",
                        xprt, -err);
        trace_rpc_socket_error(xprt, sk->sk_socket, err);
@@ -801,14 +818,6 @@ static void xs_error_report(struct sock *sk)
        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)
 {
        struct socket *sock = transport->sock;
@@ -1421,13 +1430,6 @@ out:
        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
  * @sk: socket whose state has changed