[PATCH v2 03/14] smb: client: compress: disable compression on reconnects
Enzo Matsumiya <[email protected]> Mon, 20 Jul 2026 16:49:14 -0300
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
Windows Server resets the connection if it gets a compressed request that it couldn't decompress. Some encoded payloads might decode differently on the server, or vice-versa, due to different implementation details (not really a bug), or an actual bug on either implementation. To prevent an infinite retry on such failed sends, simply disable compression for that server when a reconnect is about to happen. Other: - add disable_compression() helper (cifsglob.h) Signed-off-by: Enzo Matsumiya <[email protected]> --- fs/smb/client/cifsglob.h | 20 ++++++++++++++++++++ fs/smb/client/connect.c | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 99f9e6dca62b..5a397499dcb0 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -835,6 +835,26 @@ struct TCP_Server_Info { char dns_dom[CIFS_MAX_DOMAINNAME_LEN + 1]; }; +static __always_inline void disable_compression(struct TCP_Server_Info *server) +{ + /* + * should_compress() checks the primary server compression state, so disable it only + * on primary server. + */ + if (SERVER_IS_CHAN(server)) + server = server->primary_server; + + if (server->compression.enabled) { + pr_warn("%s: disabling compression (failsafe)\n", server->hostname); + + /* + * We must keep ->requested as true, in case new channels are added, so server + * capabilities are kept in sync (even though no further compression will be done). + */ + server->compression.enabled = false; + } +} + static inline bool is_smb1(const struct TCP_Server_Info *server) { return server->vals->protocol_id == SMB10_PROT_ID; diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 85aec302c89e..6a4afefe337d 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -401,6 +401,17 @@ static int __cifs_reconnect(struct TCP_Server_Info *server, try_to_freeze(); cifs_server_lock(server); + /* + * Servers might disconnect us when they can't decompress a compressed request we + * sent. + * When this happens, as a failsafe measure, disable compression entirely to avoid + * an endless retry. + * + * TODO: implement a more flexible alternative, e.g. identify and retry sending + * the failed request uncompressed, without having to disable compression entirely. + */ + disable_compression(server); + if (!cifs_swn_set_server_dstaddr(server) && !SERVER_IS_CHAN(server)) { /* resolve the hostname again to make sure that IP address is up-to-date */ -- 2.54.0