[PATCH v2 09/14] smb: common: compress: allow smb_lz77_compress() to overcompress

Enzo Matsumiya <[email protected]> Mon, 20 Jul 2026 16:49:20 -0300
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
Change smb_lz77_compress() to return 0 on successful compression,
leaving it up to callers to decide if @dlen >= @slen is an error
(currently returns -EMSGSIZE on such cases).

This allows better compression in certain cases where Pattern_V1 got a
good compression already, but LZ77 chunk was overcompressed (which
usually yields good compressed data as a whole)

Other changes:
- adjust client and server callers to correctly interpret the
  new return value

Signed-off-by: Enzo Matsumiya <[email protected]>
---
 fs/smb/client/compress.c      | 4 ++--
 fs/smb/common/compress/lz77.c | 7 ++-----
 fs/smb/server/compress.c      | 5 ++---
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c
index 37e92e2bc816..363ad58ad798 100644
--- a/fs/smb/client/compress.c
+++ b/fs/smb/client/compress.c
@@ -406,7 +406,7 @@ int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_s
 
 	ret = smb_compression_compress(SMB3_COMPRESS_LZ77, chained, use_pattern,
 				       src, slen, dst, &dlen);
-	if (!ret) {
+	if (!ret && dlen < slen) {
 		struct smb2_compression_hdr *hdrp = dst, hdr = {};
 		struct smb_rqst comp_rq = { .rq_nvec = 3, };
 		struct kvec iov[3];
@@ -453,7 +453,7 @@ int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_s
 		comp_rq.rq_iov = iov;
 
 		ret = send_fn(server, 1, &comp_rq);
-	} else if (ret == -EMSGSIZE || dlen >= slen) {
+	} else if (!ret) {
 		ret = send_fn(server, 1, rq);
 	}
 err_free:
diff --git a/fs/smb/common/compress/lz77.c b/fs/smb/common/compress/lz77.c
index e32e2f3040d8..f88f49e01629 100644
--- a/fs/smb/common/compress/lz77.c
+++ b/fs/smb/common/compress/lz77.c
@@ -248,19 +248,16 @@ noinline int smb_lz77_compress(const void *src, const u32 slen, void *dst, u32 *
 	} while (srcp < end);
 out:
 	dstp = lz77_encode_literals(anchor, end, dstp, &flag, &flag_count, &flag_pos);
-
 	flag_count = LZ77_FLAG_MAX - flag_count;
 	flag <<= flag_count;
 	flag |= (1UL << flag_count) - 1;
 	mem_write32(flag_pos, flag);
 
+	/* Compression is successful from our POV -- let caller decide if @dlen suits them. */
 	*dlen = dstp - dst;
 	kvfree(htable);
 
-	if (*dlen < slen)
-		return 0;
-
-	return -EMSGSIZE;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(smb_lz77_compress);
 
diff --git a/fs/smb/server/compress.c b/fs/smb/server/compress.c
index 999b7b11de85..59e78c3b042c 100644
--- a/fs/smb/server/compress.c
+++ b/fs/smb/server/compress.c
@@ -151,10 +151,9 @@ int ksmbd_compress_response(struct ksmbd_work *work)
 				      src, src_len,
 				      out + sizeof(__be32),
 				      &dst_len);
-	if (rc == -EMSGSIZE || dst_len >= src_len) {
-		rc = 0;
+	/* if dst_len >= src_len, rc is 0 */
+	if (rc || dst_len >= src_len)
 		goto out;
-	}
 
 	*(__be32 *)out = cpu_to_be32(dst_len);
 
-- 
2.54.0