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

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: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Paulo Alcantara 2024-08-31 21:40:28 -03:00 committed by Steve French
parent 431c1646e1
commit 7ccc146546

View File

@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
static bool static bool
server_unresponsive(struct TCP_Server_Info *server) 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 * We need to wait 3 echo intervals to make sure we handle such
* situations right: * 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 * 65s kernel_recvmsg times out, and we see that we haven't gotten
* a response in >60s. * a response in >60s.
*/ */
spin_lock(&server->srv_lock);
if ((server->tcpStatus == CifsGood || if ((server->tcpStatus == CifsGood ||
server->tcpStatus == CifsNeedNegotiate) && server->tcpStatus == CifsNeedNegotiate) &&
(!server->ops->can_echo || server->ops->can_echo(server)) && (!server->ops->can_echo || server->ops->can_echo(server)) &&