diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2019-09-13 16:01:07 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-09-20 15:15:24 -0400 |
commit | 8593e010786181df887b001824ff8f3e52e2098f (patch) | |
tree | c54e3b4ea70d7ab295622d70673d3b9862409a99 /net/sunrpc/xprt.c | |
parent | 9ba828861c56a21d211d5d10f5643774b1ea330d (diff) | |
download | linux-stable-8593e010786181df887b001824ff8f3e52e2098f.tar.gz linux-stable-8593e010786181df887b001824ff8f3e52e2098f.tar.bz2 linux-stable-8593e010786181df887b001824ff8f3e52e2098f.zip |
SUNRPC: Fix congestion window race with disconnect
If the congestion window closes just as the transport disconnects,
a reconnect is never driven because:
1. The XPRT_CONG_WAIT flag prevents tasks from taking the write lock
2. There's no wake-up of the first task on the xprt->sending queue
To address this, clear the congestion wait flag as part of
completing a disconnect.
Fixes: 75891f502f5f ("SUNRPC: Support for congestion control ... ")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 02d5b2125c07..83ec4edd2f91 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -456,6 +456,12 @@ void xprt_release_rqst_cong(struct rpc_task *task) } EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); +static void xprt_clear_congestion_window_wait_locked(struct rpc_xprt *xprt) +{ + if (test_and_clear_bit(XPRT_CWND_WAIT, &xprt->state)) + __xprt_lock_write_next_cong(xprt); +} + /* * Clear the congestion window wait flag and wake up the next * entry on xprt->sending @@ -671,6 +677,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt) spin_lock(&xprt->transport_lock); xprt_clear_connected(xprt); xprt_clear_write_space_locked(xprt); + xprt_clear_congestion_window_wait_locked(xprt); xprt_wake_pending_tasks(xprt, -ENOTCONN); spin_unlock(&xprt->transport_lock); } |