smb: client: negotiate compression algorithms
authorEnzo Matsumiya <ematsumiya@suse.de>
Fri, 23 Feb 2024 14:58:57 +0000 (11:58 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 14:22:49 +0000 (16:22 +0200)
[ Upstream commit 8fe7062b7d11fcd21c4dcb5f530eaa1a099b24e7 ]

Change "compress=" mount option to a boolean flag, that, if set,
will enable negotiating compression algorithms with the server.

Do not de/compress anything for now.

Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/client/cifs_debug.c
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h
fs/smb/client/smb2pdu.c

index aa95fa95ca1124bd9a470fc017a9914e964cff14..c71ae5c043060ebf5dd7f6d9e5f63e6e7bcf7841 100644 (file)
@@ -280,6 +280,24 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
        return 0;
 }
 
+static __always_inline const char *compression_alg_str(__le16 alg)
+{
+       switch (alg) {
+       case SMB3_COMPRESS_NONE:
+               return "NONE";
+       case SMB3_COMPRESS_LZNT1:
+               return "LZNT1";
+       case SMB3_COMPRESS_LZ77:
+               return "LZ77";
+       case SMB3_COMPRESS_LZ77_HUFF:
+               return "LZ77-Huffman";
+       case SMB3_COMPRESS_PATTERN:
+               return "Pattern_V1";
+       default:
+               return "invalid";
+       }
+}
+
 static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 {
        struct mid_q_entry *mid_entry;
@@ -425,12 +443,6 @@ skip_rdma:
                        server->echo_credits,
                        server->oplock_credits,
                        server->dialect);
-               if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
-                       seq_printf(m, " COMPRESS_LZNT1");
-               else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
-                       seq_printf(m, " COMPRESS_LZ77");
-               else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
-                       seq_printf(m, " COMPRESS_LZ77_HUFF");
                if (server->sign)
                        seq_printf(m, " signed");
                if (server->posix_ext_supported)
@@ -462,6 +474,14 @@ skip_rdma:
                                   server->leaf_fullpath);
                }
 
+               seq_puts(m, "\nCompression: ");
+               if (!server->compression.requested)
+                       seq_puts(m, "disabled on mount");
+               else if (server->compression.enabled)
+                       seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg));
+               else
+                       seq_puts(m, "disabled (not supported by this server)");
+
                seq_printf(m, "\n\n\tSessions: ");
                i = 0;
                list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
index 053556ca6f011da513a732cc480ee4d2f6236b98..70a12584375defbfd0beaca903e533c3527109b4 100644 (file)
@@ -772,7 +772,11 @@ struct TCP_Server_Info {
        unsigned int    max_write;
        unsigned int    min_offload;
        unsigned int    retrans;
-       __le16  compress_algorithm;
+       struct {
+               bool requested; /* "compress" mount option set*/
+               bool enabled; /* actually negotiated with server */
+               __le16 alg; /* preferred alg negotiated with server */
+       } compression;
        __u16   signing_algorithm;
        __le16  cipher_type;
         /* save initital negprot hash */
index deba1cfd1180170df974685666a50ee0d5c540a7..5acfd2057ca04d0027a36aca3491224dde9b434e 100644 (file)
@@ -1748,7 +1748,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
        tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
        tcp_ses->reconnect_instance = 1;
        tcp_ses->lstrp = jiffies;
-       tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
+       tcp_ses->compression.requested = ctx->compress;
        spin_lock_init(&tcp_ses->req_lock);
        spin_lock_init(&tcp_ses->srv_lock);
        spin_lock_init(&tcp_ses->mid_lock);
index fbaa901d3493ac1a0e710f4273f0c40a6462383d..3bbac925d0766b8c456d731355e71b1594b94af3 100644 (file)
@@ -978,7 +978,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
 
        switch (opt) {
        case Opt_compress:
-               ctx->compression = UNKNOWN_TYPE;
+               ctx->compress = true;
                cifs_dbg(VFS,
                        "SMB3 compression support is experimental\n");
                break;
index e77ee81846b31d73981fe758f43ee942d00cf065..cf577ec0dd0ac4a8f5a3131e8ed0c3ce9574a4d7 100644 (file)
@@ -277,7 +277,7 @@ struct smb3_fs_context {
        unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
        unsigned int max_channels;
        unsigned int max_cached_dirs;
-       __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
+       bool compress; /* enable SMB2 messages (READ/WRITE) de/compression */
        bool rootfs:1; /* if it's a SMB root file system */
        bool witness:1; /* use witness protocol */
        char *leaf_fullpath;
index 4d805933e14f3eed2d903947d10d333b8365d9e9..86c647a947ccd1065a8edb0712e113351839b96f 100644 (file)
@@ -743,7 +743,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
        pneg_ctxt += sizeof(struct smb2_posix_neg_context);
        neg_context_count++;
 
-       if (server->compress_algorithm) {
+       if (server->compression.requested) {
                build_compression_ctxt((struct smb2_compression_capabilities_context *)
                                pneg_ctxt);
                ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8);
@@ -791,6 +791,9 @@ static void decode_compress_ctx(struct TCP_Server_Info *server,
                         struct smb2_compression_capabilities_context *ctxt)
 {
        unsigned int len = le16_to_cpu(ctxt->DataLength);
+       __le16 alg;
+
+       server->compression.enabled = false;
 
        /*
         * Caller checked that DataLength remains within SMB boundary. We still
@@ -801,15 +804,22 @@ static void decode_compress_ctx(struct TCP_Server_Info *server,
                pr_warn_once("server sent bad compression cntxt\n");
                return;
        }
+
        if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
-               pr_warn_once("Invalid SMB3 compress algorithm count\n");
+               pr_warn_once("invalid SMB3 compress algorithm count\n");
                return;
        }
-       if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
-               pr_warn_once("unknown compression algorithm\n");
+
+       alg = ctxt->CompressionAlgorithms[0];
+
+       /* 'NONE' (0) compressor type is never negotiated */
+       if (alg == 0 || le16_to_cpu(alg) > 3) {
+               pr_warn_once("invalid compression algorithm '%u'\n", alg);
                return;
        }
-       server->compress_algorithm = ctxt->CompressionAlgorithms[0];
+
+       server->compression.alg = alg;
+       server->compression.enabled = true;
 }
 
 static int decode_encrypt_ctx(struct TCP_Server_Info *server,