Commit e224b75a authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Wen Zhiwei
Browse files

smb: client: fix hang in wait_for_response() for negproto

stable inclusion
from stable-v6.6.53
commit fabc4ed200f9b1ad17009c49e820dd7c2f732d0c
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ0GM

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fabc4ed200f9b1ad17009c49e820dd7c2f732d0c



--------------------------------

[ Upstream commit 7ccc1465465d78e6411b7bd730d06e7435802b5c ]

Call cifs_reconnect() to wake up processes waiting on negotiate
protocol to handle the case where server abruptly shut down and had no
chance to properly close the socket.

Simple reproducer:

  ssh 192.168.2.100 pkill -STOP smbd
  mount.cifs //192.168.2.100/test /mnt -o ... [never returns]

Cc: Rickard Andersson <rickaran@axis.com>
Signed-off-by: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 46908e04
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
	/*
	 * If we're in the process of mounting a share or reconnecting a session
	 * and the server abruptly shut down (e.g. socket wasn't closed, packet
	 * had been ACK'ed but no SMB response), don't wait longer than 20s to
	 * negotiate protocol.
	 */
	spin_lock(&server->srv_lock);
	if (server->tcpStatus == CifsInNegotiate &&
	    time_after(jiffies, server->lstrp + 20 * HZ)) {
		spin_unlock(&server->srv_lock);
		cifs_reconnect(server, false);
		return true;
	}
	/*
	 * We need to wait 3 echo intervals to make sure we handle such
	 * situations right:
@@ -667,7 +680,6 @@ server_unresponsive(struct TCP_Server_Info *server)
	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
	 *     a response in >60s.
	 */
	spin_lock(&server->srv_lock);
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
	    (!server->ops->can_echo || server->ops->can_echo(server)) &&