]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.4
authorSasha Levin <sashal@kernel.org>
Fri, 15 May 2020 16:27:06 +0000 (12:27 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 15 May 2020 16:27:06 +0000 (12:27 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.4/cifs-check-for-timeout-on-negotiate-stage.patch [new file with mode: 0644]
queue-4.4/cifs-fix-a-race-condition-with-cifs_echo_request.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/cifs-check-for-timeout-on-negotiate-stage.patch b/queue-4.4/cifs-check-for-timeout-on-negotiate-stage.patch
new file mode 100644 (file)
index 0000000..4ffae40
--- /dev/null
@@ -0,0 +1,124 @@
+From 57aa47dce67bc9657b9c6f069110336e5baad01e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2017 12:44:39 +0200
+Subject: cifs: Check for timeout on Negotiate stage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Samuel Cabrero <scabrero@suse.de>
+
+[ Upstream commit 76e752701a8af4404bbd9c45723f7cbd6e4a251e ]
+
+Some servers seem to accept connections while booting but never send
+the SMBNegotiate response neither close the connection, causing all
+processes accessing the share hang on uninterruptible sleep state.
+
+This happens when the cifs_demultiplex_thread detects the server is
+unresponsive so releases the socket and start trying to reconnect.
+At some point, the faulty server will accept the socket and the TCP
+status will be set to NeedNegotiate. The first issued command accessing
+the share will start the negotiation (pid 5828 below), but the response
+will never arrive so other commands will be blocked waiting on the mutex
+(pid 55352).
+
+This patch checks for unresponsive servers also on the negotiate stage
+releasing the socket and reconnecting if the response is not received
+and checking again the tcp state when the mutex is acquired.
+
+PID: 55352  TASK: ffff880fd6cc02c0  CPU: 0   COMMAND: "ls"
+ #0 [ffff880fd9add9f0] schedule at ffffffff81467eb9
+ #1 [ffff880fd9addb38] __mutex_lock_slowpath at ffffffff81468fe0
+ #2 [ffff880fd9addba8] mutex_lock at ffffffff81468b1a
+ #3 [ffff880fd9addbc0] cifs_reconnect_tcon at ffffffffa042f905 [cifs]
+ #4 [ffff880fd9addc60] smb_init at ffffffffa042faeb [cifs]
+ #5 [ffff880fd9addca0] CIFSSMBQPathInfo at ffffffffa04360b5 [cifs]
+ ....
+
+Which is waiting a mutex owned by:
+
+PID: 5828   TASK: ffff880fcc55e400  CPU: 0   COMMAND: "xxxx"
+ #0 [ffff880fbfdc19b8] schedule at ffffffff81467eb9
+ #1 [ffff880fbfdc1b00] wait_for_response at ffffffffa044f96d [cifs]
+ #2 [ffff880fbfdc1b60] SendReceive at ffffffffa04505ce [cifs]
+ #3 [ffff880fbfdc1bb0] CIFSSMBNegotiate at ffffffffa0438d79 [cifs]
+ #4 [ffff880fbfdc1c50] cifs_negotiate_protocol at ffffffffa043b383 [cifs]
+ #5 [ffff880fbfdc1c80] cifs_reconnect_tcon at ffffffffa042f911 [cifs]
+ #6 [ffff880fbfdc1d20] smb_init at ffffffffa042faeb [cifs]
+ #7 [ffff880fbfdc1d60] CIFSSMBQFSInfo at ffffffffa0434eb0 [cifs]
+ ....
+
+Signed-off-by: Samuel Cabrero <scabrero@suse.de>
+Reviewed-by: AurĂ©lien Aptel <aaptel@suse.de>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/cifssmb.c | 12 ++++++++++++
+ fs/cifs/connect.c |  3 ++-
+ fs/cifs/smb2pdu.c | 12 ++++++++++++
+ 3 files changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+index b9b8f19dce0e1..fa07f7cb85a51 100644
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -184,6 +184,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
+        * reconnect the same SMB session
+        */
+       mutex_lock(&ses->session_mutex);
++
++      /*
++       * Recheck after acquire mutex. If another thread is negotiating
++       * and the server never sends an answer the socket will be closed
++       * and tcpStatus set to reconnect.
++       */
++      if (server->tcpStatus == CifsNeedReconnect) {
++              rc = -EHOSTDOWN;
++              mutex_unlock(&ses->session_mutex);
++              goto out;
++      }
++
+       rc = cifs_negotiate_protocol(0, ses);
+       if (rc == 0 && ses->need_reconnect)
+               rc = cifs_setup_session(0, ses, nls_codepage);
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index c9793ce0d3368..7022750cae2fd 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -558,7 +558,8 @@ server_unresponsive(struct TCP_Server_Info *server)
+        * 65s kernel_recvmsg times out, and we see that we haven't gotten
+        *     a response in >60s.
+        */
+-      if (server->tcpStatus == CifsGood &&
++      if ((server->tcpStatus == CifsGood ||
++          server->tcpStatus == CifsNeedNegotiate) &&
+           time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
+               cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
+                        server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
+diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index d4472a4947581..4ffd5e177288e 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -249,6 +249,18 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
+        * the same SMB session
+        */
+       mutex_lock(&tcon->ses->session_mutex);
++
++      /*
++       * Recheck after acquire mutex. If another thread is negotiating
++       * and the server never sends an answer the socket will be closed
++       * and tcpStatus set to reconnect.
++       */
++      if (server->tcpStatus == CifsNeedReconnect) {
++              rc = -EHOSTDOWN;
++              mutex_unlock(&tcon->ses->session_mutex);
++              goto out;
++      }
++
+       rc = cifs_negotiate_protocol(0, tcon->ses);
+       if (!rc && tcon->ses->need_reconnect) {
+               rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+-- 
+2.20.1
+
diff --git a/queue-4.4/cifs-fix-a-race-condition-with-cifs_echo_request.patch b/queue-4.4/cifs-fix-a-race-condition-with-cifs_echo_request.patch
new file mode 100644 (file)
index 0000000..0b96a65
--- /dev/null
@@ -0,0 +1,65 @@
+From 1ad27ac06c8caf0acccccf25d12b6f3e9bbad601 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jul 2019 06:52:46 +1000
+Subject: cifs: Fix a race condition with cifs_echo_request
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+[ Upstream commit f2caf901c1b7ce65f9e6aef4217e3241039db768 ]
+
+There is a race condition with how we send (or supress and don't send)
+smb echos that will cause the client to incorrectly think the
+server is unresponsive and thus needs to be reconnected.
+
+Summary of the race condition:
+ 1) Daisy chaining scheduling creates a gap.
+ 2) If traffic comes unfortunate shortly after
+    the last echo, the planned echo is suppressed.
+ 3) Due to the gap, the next echo transmission is delayed
+    until after the timeout, which is set hard to twice
+    the echo interval.
+
+This is fixed by changing the timeouts from 2 to three times the echo interval.
+
+Detailed description of the bug: https://lutz.donnerhacke.de/eng/Blog/Groundhog-Day-with-SMB-remount
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/connect.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 7022750cae2fd..21ddfd77966eb 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -548,10 +548,10 @@ static bool
+ server_unresponsive(struct TCP_Server_Info *server)
+ {
+       /*
+-       * We need to wait 2 echo intervals to make sure we handle such
++       * We need to wait 3 echo intervals to make sure we handle such
+        * situations right:
+        * 1s  client sends a normal SMB request
+-       * 2s  client gets a response
++       * 3s  client gets a response
+        * 30s echo workqueue job pops, and decides we got a response recently
+        *     and don't need to send another
+        * ...
+@@ -560,9 +560,9 @@ server_unresponsive(struct TCP_Server_Info *server)
+        */
+       if ((server->tcpStatus == CifsGood ||
+           server->tcpStatus == CifsNeedNegotiate) &&
+-          time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
++          time_after(jiffies, server->lstrp + 3 * SMB_ECHO_INTERVAL)) {
+               cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
+-                       server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
++                       server->hostname, (3 * SMB_ECHO_INTERVAL) / HZ);
+               cifs_reconnect(server);
+               wake_up(&server->response_q);
+               return true;
+-- 
+2.20.1
+
index c0f037a4310681fab2f455ea0875aa842baa0fa9..811d666f50dadd6eea72c94ad3e9e715dfb96030 100644 (file)
@@ -38,3 +38,5 @@ net-moxa-fix-a-potential-double-free_irq.patch
 drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch
 scsi-sg-add-sg_remove_request-in-sg_write.patch
 spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch
+cifs-check-for-timeout-on-negotiate-stage.patch
+cifs-fix-a-race-condition-with-cifs_echo_request.patch