aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2018-12-17 13:34:59 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-12-18 11:03:57 -0500
commit0445f92c5d537c173a54446b80d2052145de5148 (patch)
tree23b94aa7599440d464970fe1cd85689446b84580 /net/sunrpc/xprtsock.c
parent7566ec393f4161572ba6f11ad5171fd5d59b0fbd (diff)
SUNRPC: Fix disconnection races
When the socket is closed, we need to call xprt_disconnect_done() in order to clean up the XPRT_WRITE_SPACE flag, and wake up the sleeping tasks. However, we also want to ensure that we don't wake them up before the socket is closed, since that would cause thundering herd issues with everyone piling up to retransmit before the TCP shutdown dance has completed. Only the task that holds XPRT_LOCKED needs to wake up early in order to allow the close to complete. Reported-by: Dave Wysochanski <dwysocha@redhat.com> Reported-by: Scott Mayhew <smayhew@redhat.com> Cc: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Tested-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 8a5e823e0b33..4c471b4235ba 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1217,6 +1217,8 @@ static void xs_reset_transport(struct sock_xprt *transport)
1217 1217
1218 trace_rpc_socket_close(xprt, sock); 1218 trace_rpc_socket_close(xprt, sock);
1219 sock_release(sock); 1219 sock_release(sock);
1220
1221 xprt_disconnect_done(xprt);
1220} 1222}
1221 1223
1222/** 1224/**
@@ -1237,8 +1239,6 @@ static void xs_close(struct rpc_xprt *xprt)
1237 1239
1238 xs_reset_transport(transport); 1240 xs_reset_transport(transport);
1239 xprt->reestablish_timeout = 0; 1241 xprt->reestablish_timeout = 0;
1240
1241 xprt_disconnect_done(xprt);
1242} 1242}
1243 1243
1244static void xs_inject_disconnect(struct rpc_xprt *xprt) 1244static void xs_inject_disconnect(struct rpc_xprt *xprt)
@@ -1489,8 +1489,6 @@ static void xs_tcp_state_change(struct sock *sk)
1489 &transport->sock_state)) 1489 &transport->sock_state))
1490 xprt_clear_connecting(xprt); 1490 xprt_clear_connecting(xprt);
1491 clear_bit(XPRT_CLOSING, &xprt->state); 1491 clear_bit(XPRT_CLOSING, &xprt->state);
1492 if (sk->sk_err)
1493 xprt_wake_pending_tasks(xprt, -sk->sk_err);
1494 /* Trigger the socket release */ 1492 /* Trigger the socket release */
1495 xs_tcp_force_close(xprt); 1493 xs_tcp_force_close(xprt);
1496 } 1494 }