diff options
Diffstat (limited to 'queue-6.15/smb-client-fix-first-command-failure-during-re-negotiation.patch')
-rw-r--r-- | queue-6.15/smb-client-fix-first-command-failure-during-re-negotiation.patch | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/queue-6.15/smb-client-fix-first-command-failure-during-re-negotiation.patch b/queue-6.15/smb-client-fix-first-command-failure-during-re-negotiation.patch new file mode 100644 index 0000000000..57a609185c --- /dev/null +++ b/queue-6.15/smb-client-fix-first-command-failure-during-re-negotiation.patch @@ -0,0 +1,71 @@ +From 34331d7beed7576acfc98e991c39738b96162499 Mon Sep 17 00:00:00 2001 +From: zhangjian <zhangjian496@huawei.com> +Date: Thu, 19 Jun 2025 09:18:29 +0800 +Subject: smb: client: fix first command failure during re-negotiation + +From: zhangjian <zhangjian496@huawei.com> + +commit 34331d7beed7576acfc98e991c39738b96162499 upstream. + +after fabc4ed200f9, server_unresponsive add a condition to check whether client +need to reconnect depending on server->lstrp. When client failed to reconnect +for some time and abort connection, server->lstrp is updated for the last time. +In the following scene, server->lstrp is too old. This cause next command +failure in re-negotiation rather than waiting for re-negotiation done. + +1. mount -t cifs -o username=Everyone,echo_internal=10 //$server_ip/export /mnt +2. ssh $server_ip "echo b > /proc/sysrq-trigger &" +3. ls /mnt +4. sleep 21s +5. ssh $server_ip "service firewalld stop" +6. ls # return EHOSTDOWN + +If the interval between 5 and 6 is too small, 6 may trigger sending negotiation +request. Before backgrounding cifsd thread try to receive negotiation response +from server in cifs_readv_from_socket, server_unresponsive may trigger +cifs_reconnect which cause 6 to be failed: + +ls thread +---------------- + smb2_negotiate + server->tcpStatus = CifsInNegotiate + compound_send_recv + wait_for_compound_request + +cifsd thread +---------------- + cifs_readv_from_socket + server_unresponsive + server->tcpStatus == CifsInNegotiate && jiffies > server->lstrp + 20s + cifs_reconnect + cifs_abort_connection: mid_state = MID_RETRY_NEEDED + +ls thread +---------------- + cifs_sync_mid_result return EAGAIN + smb2_negotiate return EHOSTDOWN + +Though server->lstrp means last server response time, it is updated in +cifs_abort_connection and cifs_get_tcp_session. We can also update server->lstrp +before switching into CifsInNegotiate state to avoid failure in 6. + +Fixes: 7ccc1465465d ("smb: client: fix hang in wait_for_response() for negproto") +Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> +Acked-by: Meetakshi Setiya <msetiya@microsoft.com> +Signed-off-by: zhangjian <zhangjian496@huawei.com> +Signed-off-by: Steve French <stfrench@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + fs/smb/client/connect.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -4193,6 +4193,7 @@ retry: + return 0; + } + ++ server->lstrp = jiffies; + server->tcpStatus = CifsInNegotiate; + spin_unlock(&server->srv_lock); + |