diff options
| author | zhangjian <zhangjian496@huawei.com> | 2025-06-19 09:18:29 +0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-06-27 11:07:40 +0100 |
| commit | 5db2538e8d6f31c604618063c8ade013914a2951 (patch) | |
| tree | 0def5669fdacc6fde66087dacfee604517d87313 /fs | |
| parent | 6e8a0aae9fd498485ccbda0568096ec36e9ab932 (diff) | |
| download | linux-5db2538e8d6f31c604618063c8ade013914a2951.tar.gz linux-5db2538e8d6f31c604618063c8ade013914a2951.tar.bz2 linux-5db2538e8d6f31c604618063c8ade013914a2951.zip | |
smb: client: fix first command failure during re-negotiation
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>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/smb/client/connect.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index f351fb408f5c..6486e514686f 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -4217,6 +4217,7 @@ retry: return 0; } + server->lstrp = jiffies; server->tcpStatus = CifsInNegotiate; spin_unlock(&server->srv_lock); |
