diff options
Diffstat (limited to 'fs/smb/client/compress/lz77.c')
| -rw-r--r-- | fs/smb/client/compress/lz77.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/smb/client/compress/lz77.c b/fs/smb/client/compress/lz77.c index 80c57175769d..1d0cb4a22f5f 100644 --- a/fs/smb/client/compress/lz77.c +++ b/fs/smb/client/compress/lz77.c @@ -131,6 +131,26 @@ static __always_inline void *lz77_write_match(void *dst, void **nib, u32 dist, u return dst + 4; } +/* + * Compute compressed (dst) buffer length based on uncompressed (src) length. + * + * Accounts for metadata and overprovision for the worst case scenario. + * + * Metadata is a 4-byte flag. + * A flag is written: + * - on dst begin (pos 0) + * - when flag count is 32 (1 literal or 1 match increments counter) + * - on end-of-stream (end of dst) + * + * Worst case scenario is an all-literal compression, this means: + * metadata_bytes = 4 + ((@slen / 32) * 4) + 4, or reduced (@slen >> 3) + 8 + * -> @slen + metadata_bytes + */ +u32 lz77_calc_dlen(u32 slen) +{ + return slen + (slen >> 3) + 8; +} + noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen) { const void *srcp, *end; @@ -150,7 +170,12 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen) if (!htable) return -ENOMEM; - /* Main loop. */ + /* + * Main loop. + * + * Assuming @dlen was computed with lz77_calc_dlen(), we can run without bound checking + * @dst. + */ do { u32 dist, len = 0; const void *wnd; @@ -182,15 +207,6 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen) continue; } - /* - * Bail out if @dstp reached >= 7/8 of @slen -- already compressed badly, not worth - * going further. - */ - if (unlikely(dstp - dst >= slen - (slen >> 3))) { - *dlen = slen; - goto out; - } - dstp = lz77_write_match(dstp, &nib, dist, len); srcp += len; @@ -227,7 +243,6 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen) lz77_write32(flag_pos, flag); *dlen = dstp - dst; -out: kvfree(htable); if (*dlen < slen) |
