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