xref: /linux/fs/smb/common/compress/lz77.h (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2024-2026, SUSE LLC
4  *
5  * Authors: Enzo Matsumiya <ematsumiya@suse.de>
6  *
7  * Implementation of the LZ77 "plain" compression algorithm, as per MS-XCA spec.
8  */
9 #ifndef _SMB_COMPRESS_LZ77_H
10 #define _SMB_COMPRESS_LZ77_H
11 
12 #include <linux/kernel.h>
13 
14 /**
15  * smb_lz77_compressed_alloc_size() - Compute compressed buffer size.
16  * @size:	uncompressed (src) size
17  *
18  * Compute allocation size for the compressed buffer based on uncompressed size.
19  * Accounts for metadata and overprovision for the worst case scenario.
20  *
21  * LZ77 metadata is a 4-byte flag that is written:
22  * - on dst begin (pos 0)
23  * - every 32 literals or matches
24  * - on end-of-stream (possibly, if last write was another flag)
25  *
26  * Worst case scenario is an all-literal compression, which means:
27  * metadata bytes = 4 + ((@size / 32) * 4) + 4, or, simplified, (@size >> 3) + 8
28  *
29  * The worst case scenario rarely happens, but such overprovisioning also
30  * allows smb_lz77_compress() main loop to run without ever bound checking dst,
31  * which is a huge perf improvement, while also being safe when compression goes
32  * bad.
33  *
34  * Return: required (*) allocation size for compressed buffer.
35  *
36  * (*) checked once in the beginning of smb_lz77_compress()
37  */
38 static __always_inline u32 smb_lz77_compressed_alloc_size(const u32 size)
39 {
40 	return size + (size >> 3) + 8;
41 }
42 
43 int smb_lz77_compress(const void *src, const u32 slen, void *dst, u32 *dlen);
44 int smb_lz77_decompress(const void *src, const u32 slen, void *dst,
45 			const u32 dlen);
46 #endif /* _SMB_COMPRESS_LZ77_H */
47