Commit d14bbfff authored by Steve French's avatar Steve French
Browse files

smb3: mark compression as CONFIG_EXPERIMENTAL and fix missing compression operation



Move SMB3.1.1 compression code into experimental config option,
and fix the compress mount option. Implement unchained LZ77
"plain" compression algorithm as per MS-XCA specification
section "2.3 Plain LZ77 Compression Algorithm Details".

Signed-off-by: default avatarEnzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 6795dab4
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -204,4 +204,18 @@ config CIFS_ROOT

	  Most people say N here.

config CIFS_COMPRESSION
	bool "SMB message compression (Experimental)"
	depends on CIFS
	default n
	help
	  Enables over-the-wire message compression for SMB 3.1.1
	  mounts when negotiated with the server.

	  Only write requests with data size >= PAGE_SIZE will be
	  compressed to avoid wasting resources.

	  Say Y here if you want SMB traffic to be compressed.
	  If unsure, say N.

endif
+2 −0
Original line number Diff line number Diff line
@@ -33,3 +33,5 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o

cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o

cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o
+6 −1
Original line number Diff line number Diff line
@@ -349,6 +349,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
	seq_printf(m, ",ACL");
#ifdef CONFIG_CIFS_SWN_UPCALL
	seq_puts(m, ",WITNESS");
#endif
#ifdef CONFIG_CIFS_COMPRESSION
	seq_puts(m, ",COMPRESSION");
#endif
	seq_putc(m, '\n');
	seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
@@ -475,7 +478,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
		}

		seq_puts(m, "\nCompression: ");
		if (!server->compression.requested)
		if (!IS_ENABLED(CONFIG_CIFS_COMPRESSION))
			seq_puts(m, "no built-in support");
		else 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));
+2 −1
Original line number Diff line number Diff line
@@ -555,7 +555,7 @@ struct smb_version_operations {
	bool (*dir_needs_close)(struct cifsFileInfo *);
	long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
			  loff_t);
	/* init transform request - used for encryption for now */
	/* init transform (compress/encrypt) request */
	int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst,
				 struct smb_rqst *, struct smb_rqst *);
	int (*is_transform_hdr)(void *buf);
@@ -1876,6 +1876,7 @@ static inline bool is_replayable_error(int error)
#define   CIFS_HAS_CREDITS        0x0400 /* already has credits */
#define   CIFS_TRANSFORM_REQ      0x0800 /* transform request before sending */
#define   CIFS_NO_SRV_RSP         0x1000 /* there is no server response */
#define   CIFS_COMPRESS_REQ       0x4000 /* compress request before sending */

/* Security Flags: indicate type of session setup needed */
#define   CIFSSEC_MAY_SIGN	0x00001
+50 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2024, SUSE LLC
 *
 * Authors: Enzo Matsumiya <ematsumiya@suse.de>
 *
 * This file implements I/O compression support for SMB2 messages (SMB 3.1.1 only).
 * See compress/ for implementation details of each algorithm.
 *
 * References:
 * MS-SMB2 "3.1.4.4 Compressing the Message"
 * MS-SMB2 "3.1.5.3 Decompressing the Chained Message"
 * MS-XCA - for details of the supported algorithms
 */
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/uio.h>

#include "cifsglob.h"
#include "../common/smb2pdu.h"
#include "cifsproto.h"
#include "smb2proto.h"

#include "compress/lz77.h"
#include "compress.h"

int smb_compress(void *buf, const void *data, size_t *len)
{
	struct smb2_compression_hdr *hdr;
	size_t buf_len, data_len;
	int ret;

	buf_len = sizeof(struct smb2_write_req);
	data_len = *len;
	*len = 0;

	hdr = buf;
	hdr->ProtocolId = SMB2_COMPRESSION_TRANSFORM_ID;
	hdr->OriginalCompressedSegmentSize = cpu_to_le32(data_len);
	hdr->Offset = cpu_to_le32(buf_len);
	hdr->Flags = SMB2_COMPRESSION_FLAG_NONE;
	hdr->CompressionAlgorithm = SMB3_COMPRESS_LZ77;

	/* XXX: add other algs here as they're implemented */
	ret = lz77_compress(data, data_len, buf + SMB_COMPRESS_HDR_LEN + buf_len, &data_len);
	if (!ret)
		*len = SMB_COMPRESS_HDR_LEN + buf_len + data_len;

	return ret;
}
Loading