diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-08 18:35:25 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-08 21:47:28 -0500 |
commit | 6cc7e908362a9dfec3c821f77ec98b6758592060 (patch) | |
tree | 305503853cae950c4f96e18f11efc2688d38512c /net/sunrpc | |
parent | 76698b2358de466d23f44eaa1b0c9ebe8206099a (diff) |
SUNRPC: Ensure xs_reset_transport() resets the close connection flags
Otherwise, we may end up looping.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtsock.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ea1882f97912..0fa7ed93dc20 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -803,10 +803,21 @@ static void xs_error_report(struct sock *sk) | |||
803 | read_unlock_bh(&sk->sk_callback_lock); | 803 | read_unlock_bh(&sk->sk_callback_lock); |
804 | } | 804 | } |
805 | 805 | ||
806 | static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) | ||
807 | { | ||
808 | smp_mb__before_atomic(); | ||
809 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
810 | clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
811 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
812 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
813 | smp_mb__after_atomic(); | ||
814 | } | ||
815 | |||
806 | static void xs_reset_transport(struct sock_xprt *transport) | 816 | static void xs_reset_transport(struct sock_xprt *transport) |
807 | { | 817 | { |
808 | struct socket *sock = transport->sock; | 818 | struct socket *sock = transport->sock; |
809 | struct sock *sk = transport->inet; | 819 | struct sock *sk = transport->inet; |
820 | struct rpc_xprt *xprt = &transport->xprt; | ||
810 | 821 | ||
811 | if (sk == NULL) | 822 | if (sk == NULL) |
812 | return; | 823 | return; |
@@ -819,8 +830,9 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
819 | 830 | ||
820 | xs_restore_old_callbacks(transport, sk); | 831 | xs_restore_old_callbacks(transport, sk); |
821 | write_unlock_bh(&sk->sk_callback_lock); | 832 | write_unlock_bh(&sk->sk_callback_lock); |
833 | xs_sock_reset_connection_flags(xprt); | ||
822 | 834 | ||
823 | trace_rpc_socket_close(&transport->xprt, sock); | 835 | trace_rpc_socket_close(xprt, sock); |
824 | sock_release(sock); | 836 | sock_release(sock); |
825 | } | 837 | } |
826 | 838 | ||
@@ -845,11 +857,6 @@ static void xs_close(struct rpc_xprt *xprt) | |||
845 | xs_reset_transport(transport); | 857 | xs_reset_transport(transport); |
846 | xprt->reestablish_timeout = 0; | 858 | xprt->reestablish_timeout = 0; |
847 | 859 | ||
848 | smp_mb__before_atomic(); | ||
849 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
850 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
851 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
852 | smp_mb__after_atomic(); | ||
853 | xprt_disconnect_done(xprt); | 860 | xprt_disconnect_done(xprt); |
854 | } | 861 | } |
855 | 862 | ||
@@ -1455,16 +1462,6 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) | |||
1455 | xprt_clear_connecting(xprt); | 1462 | xprt_clear_connecting(xprt); |
1456 | } | 1463 | } |
1457 | 1464 | ||
1458 | static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) | ||
1459 | { | ||
1460 | smp_mb__before_atomic(); | ||
1461 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
1462 | clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
1463 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
1464 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
1465 | smp_mb__after_atomic(); | ||
1466 | } | ||
1467 | |||
1468 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | 1465 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) |
1469 | { | 1466 | { |
1470 | xs_sock_reset_connection_flags(xprt); | 1467 | xs_sock_reset_connection_flags(xprt); |