SUNRPC: Fix congestion window race with disconnect
authorChuck Lever <chuck.lever@oracle.com>
Fri, 13 Sep 2019 20:01:07 +0000 (16:01 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 20 Sep 2019 19:15:24 +0000 (15:15 -0400)
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>
net/sunrpc/xprt.c

index 02d5b21..83ec4ed 100644 (file)
@@ -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);
 }