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