diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-22 17:14:36 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-24 10:46:15 -0400 |
commit | f878b657ce8e7d3673afe48110ec208a29e38c4a (patch) | |
tree | ce2f01c75268473a8d4e8879f5f55b73a16caa7d /net | |
parent | 4bc1e68ed6a8b59be8a79eb719be515a55c7bc68 (diff) |
SUNRPC: Get rid of the xs_error_report socket callback
Chris Perl reports that we're seeing races between the wakeup call in
xs_error_report and the connect attempts. Basically, Chris has shown
that in certain circumstances, the call to xs_error_report causes the
rpc_task that is responsible for reconnecting to wake up early, thus
triggering a disconnect and retry.
Since the sk->sk_error_report() calls in the socket layer are always
followed by a tcp_done() in the cases where we care about waking up
the rpc_tasks, just let the state_change callbacks take responsibility
for those wake ups.
Reported-by: Chris Perl <chris.perl@gmail.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@vger.kernel.org
Tested-by: Chris Perl <chris.perl@gmail.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtsock.c | 25 |
1 files changed, 0 insertions, 25 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 1f105c2d2e15..75853cabf4c9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -254,7 +254,6 @@ struct sock_xprt { | |||
254 | void (*old_data_ready)(struct sock *, int); | 254 | void (*old_data_ready)(struct sock *, int); |
255 | void (*old_state_change)(struct sock *); | 255 | void (*old_state_change)(struct sock *); |
256 | void (*old_write_space)(struct sock *); | 256 | void (*old_write_space)(struct sock *); |
257 | void (*old_error_report)(struct sock *); | ||
258 | }; | 257 | }; |
259 | 258 | ||
260 | /* | 259 | /* |
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | |||
781 | transport->old_data_ready = sk->sk_data_ready; | 780 | transport->old_data_ready = sk->sk_data_ready; |
782 | transport->old_state_change = sk->sk_state_change; | 781 | transport->old_state_change = sk->sk_state_change; |
783 | transport->old_write_space = sk->sk_write_space; | 782 | transport->old_write_space = sk->sk_write_space; |
784 | transport->old_error_report = sk->sk_error_report; | ||
785 | } | 783 | } |
786 | 784 | ||
787 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | 785 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) |
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s | |||
789 | sk->sk_data_ready = transport->old_data_ready; | 787 | sk->sk_data_ready = transport->old_data_ready; |
790 | sk->sk_state_change = transport->old_state_change; | 788 | sk->sk_state_change = transport->old_state_change; |
791 | sk->sk_write_space = transport->old_write_space; | 789 | sk->sk_write_space = transport->old_write_space; |
792 | sk->sk_error_report = transport->old_error_report; | ||
793 | } | 790 | } |
794 | 791 | ||
795 | static void xs_reset_transport(struct sock_xprt *transport) | 792 | static void xs_reset_transport(struct sock_xprt *transport) |
@@ -1546,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1546 | read_unlock_bh(&sk->sk_callback_lock); | 1543 | read_unlock_bh(&sk->sk_callback_lock); |
1547 | } | 1544 | } |
1548 | 1545 | ||
1549 | /** | ||
1550 | * xs_error_report - callback mainly for catching socket errors | ||
1551 | * @sk: socket | ||
1552 | */ | ||
1553 | static void xs_error_report(struct sock *sk) | ||
1554 | { | ||
1555 | struct rpc_xprt *xprt; | ||
1556 | |||
1557 | read_lock_bh(&sk->sk_callback_lock); | ||
1558 | if (!(xprt = xprt_from_sock(sk))) | ||
1559 | goto out; | ||
1560 | dprintk("RPC: %s client %p...\n" | ||
1561 | "RPC: error %d\n", | ||
1562 | __func__, xprt, sk->sk_err); | ||
1563 | xprt_wake_pending_tasks(xprt, -EAGAIN); | ||
1564 | out: | ||
1565 | read_unlock_bh(&sk->sk_callback_lock); | ||
1566 | } | ||
1567 | |||
1568 | static void xs_write_space(struct sock *sk) | 1546 | static void xs_write_space(struct sock *sk) |
1569 | { | 1547 | { |
1570 | struct socket *sock; | 1548 | struct socket *sock; |
@@ -1864,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, | |||
1864 | sk->sk_user_data = xprt; | 1842 | sk->sk_user_data = xprt; |
1865 | sk->sk_data_ready = xs_local_data_ready; | 1843 | sk->sk_data_ready = xs_local_data_ready; |
1866 | sk->sk_write_space = xs_udp_write_space; | 1844 | sk->sk_write_space = xs_udp_write_space; |
1867 | sk->sk_error_report = xs_error_report; | ||
1868 | sk->sk_allocation = GFP_ATOMIC; | 1845 | sk->sk_allocation = GFP_ATOMIC; |
1869 | 1846 | ||
1870 | xprt_clear_connected(xprt); | 1847 | xprt_clear_connected(xprt); |
@@ -1989,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1989 | sk->sk_user_data = xprt; | 1966 | sk->sk_user_data = xprt; |
1990 | sk->sk_data_ready = xs_udp_data_ready; | 1967 | sk->sk_data_ready = xs_udp_data_ready; |
1991 | sk->sk_write_space = xs_udp_write_space; | 1968 | sk->sk_write_space = xs_udp_write_space; |
1992 | sk->sk_error_report = xs_error_report; | ||
1993 | sk->sk_no_check = UDP_CSUM_NORCV; | 1969 | sk->sk_no_check = UDP_CSUM_NORCV; |
1994 | sk->sk_allocation = GFP_ATOMIC; | 1970 | sk->sk_allocation = GFP_ATOMIC; |
1995 | 1971 | ||
@@ -2102,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2102 | sk->sk_data_ready = xs_tcp_data_ready; | 2078 | sk->sk_data_ready = xs_tcp_data_ready; |
2103 | sk->sk_state_change = xs_tcp_state_change; | 2079 | sk->sk_state_change = xs_tcp_state_change; |
2104 | sk->sk_write_space = xs_tcp_write_space; | 2080 | sk->sk_write_space = xs_tcp_write_space; |
2105 | sk->sk_error_report = xs_error_report; | ||
2106 | sk->sk_allocation = GFP_ATOMIC; | 2081 | sk->sk_allocation = GFP_ATOMIC; |
2107 | 2082 | ||
2108 | /* socket options */ | 2083 | /* socket options */ |