Commit 3ffbc1d6 authored by NeilBrown's avatar NeilBrown Committed by Anna Schumaker

net/sunrpc/xprt_sock: fix regression in connection error reporting.

Commit 3d476263 ("tcp: remove poll() flakes when receiving
RST") in v4.12 changed the order in which ->sk_state_change()
and ->sk_error_report() are called when a socket is shut
down - sk_state_change() is now called first.

This causes xs_tcp_state_change() -> xs_sock_mark_closed() ->
xprt_disconnect_done() to wake all pending tasked with -EAGAIN.
When the ->sk_error_report() callback arrives, it is too late to
pass the error on, and it is lost.

As easy way to demonstrate the problem caused is to try to start
rpc.nfsd while rcpbind isn't running.
nfsd will attempt a tcp connection to rpcbind.  A ECONNREFUSED
error is returned, but sunrpc code loses the error and keeps
retrying.  If it saw the ECONNREFUSED, it would abort.

To fix this, handle the sk->sk_err in the TCP_CLOSE branch of
xs_tcp_state_change().

Fixes: 3d476263 ("tcp: remove poll() flakes when receiving RST")
Cc: stable@vger.kernel.org (v4.12)
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent ecc7b435
...@@ -1624,6 +1624,8 @@ static void xs_tcp_state_change(struct sock *sk) ...@@ -1624,6 +1624,8 @@ static void xs_tcp_state_change(struct sock *sk)
if (test_and_clear_bit(XPRT_SOCK_CONNECTING, if (test_and_clear_bit(XPRT_SOCK_CONNECTING,
&transport->sock_state)) &transport->sock_state))
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
if (sk->sk_err)
xprt_wake_pending_tasks(xprt, -sk->sk_err);
xs_sock_mark_closed(xprt); xs_sock_mark_closed(xprt);
} }
out: out:
......
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