[PATCH RFC 7/9] lib/lz4: switch the decompressor to the vendored sources
flat view
COOLING7d
From: Michal Wilczynski <m.wilczynski@samsung.com>
Date: 2026-09-25 11:35:06
Also in:
linux-block, linux-crypto, linux-f2fs-devel, linux-mips, linux-s390, lkml, llvm
Subsystem:
block layer, library code, the rest, zram compressed ram block device drvier · Maintainers:
Jens Axboe, Andrew Morton, Linus Torvalds, Minchan Kim, Sergey Senozhatsky
Replace the forked decompressor with thin entry points over the vendored
lz4.c. The API is already signature-compatible, so every export is a
plain forwarder. lz4defs.h has no users left and goes.
lib/decompress_unlz4.c still includes this file for the pre-boot
decompressor; the exports stay behind #ifndef STATIC.
That include is why LZ4_streamDecode_t is incomplete: under PREBOOT the
translation unit has both <linux/lz4.h> and upstream's lz4.h, so both
must name the same type. Both repeat upstream's forward declaration,
and the file builds without guards.
LZ4_streamDecode_t is the last of the three, so LZ4_STREAMDECODESIZE and
LZ4_STREAMDECODESIZE_U64 go and LZ4_MEM_DECOMPRESS takes over, 32 bytes.
LZ4_COMPRESSBOUND is likewise defined by both headers; guard it.
LZ4_compressBound() cannot be guarded, so drop the inline wrapper:
lib/decompress_unlz4.c was its only caller and uses the macro now.
This picks up upstream's decoder fixes since v1.8.3 and retires six
local patches:
commit 8cb5d7482810 ("lib/lz4: make arrays static const, reduces object code size")
commit b1a3e75e466d ("lz4: fix kernel decompression speed")
commit 89b158635ad7 ("lib/lz4: explicitly support in-place decompression")
commit 7fde9d6e839d ("lz4_decompress: declare LZ4_decompress_safe_withPrefix64k static")
commit eafc0a02391b ("lz4: fix LZ4_decompress_safe_partial read out of bound")
commit 2d8867f3e083 ("lib: make LZ4_decompress_safe_forceExtDict() static")
The decompression speed fix has an upstream equivalent, carried since
v1.9.3 as upstream commit fe2a1b3707d5
("Call LZ4_memcpy() instead of memcpy()").
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/block/zram/backend_lz4.c | 2 +-
drivers/block/zram/backend_lz4hc.c | 2 +-
include/linux/lz4.h | 51 +--
lib/decompress_unlz4.c | 4 +-
lib/lz4/lz4_decompress.c | 718 +++----------------------------------
lib/lz4/lz4defs.h | 247 -------------
6 files changed, 74 insertions(+), 950 deletions(-)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 50265e3ce256490994cb6dae32a45da376e408e0..b9b8a5f678c155442fa3fd2c1984e45182e6fc38 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c@@ -84,7 +84,7 @@ static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx) if (!zctx->mem) goto error; } else { - zctx->dstrm = kzalloc_obj(*zctx->dstrm); + zctx->dstrm = kzalloc(LZ4_MEM_DECOMPRESS, GFP_KERNEL); if (!zctx->dstrm) goto error;
diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index 894695753d99bf2fec7e191c4ec2fff489b5bddd..7fabd0e6d66095d411007bec5eaa8e5f553b626d 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c@@ -65,7 +65,7 @@ static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx) if (!zctx->mem) goto error; } else { - zctx->dstrm = kzalloc_obj(*zctx->dstrm); + zctx->dstrm = kzalloc(LZ4_MEM_DECOMPRESS, GFP_KERNEL); if (!zctx->dstrm) goto error;
diff --git a/include/linux/lz4.h b/include/linux/lz4.h
index 0e617c096653ba122f466b019c68a30661e04989..22adf26904754b3a274274d6b77955eb119e463f 100644
--- a/include/linux/lz4.h
+++ b/include/linux/lz4.h@@ -48,10 +48,16 @@ * CONSTANTS **************************************************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ + +/* lib/decompress_unlz4.c sees this header and, under PREBOOT, upstream's + * lz4.h too; both define this identically. + */ +#ifndef LZ4_COMPRESSBOUND #define LZ4_COMPRESSBOUND(isize) (\ (unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE \ ? 0 \ : (isize) + ((isize)/255) + 16) +#endif #define LZ4_ACCELERATION_DEFAULT 1
@@ -66,12 +72,8 @@ #define LZ4HC_CLAMP_CLEVEL 10 /*-************************************************************************ - * STREAMING CONSTANTS AND STRUCTURES + * STREAMING STRUCTURES **************************************************************************/ -#define LZ4_STREAMDECODESIZE_U64 4 -#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * \ - sizeof(unsigned long long)) - /* * LZ4_stream_t - an LZ4 stream. Incomplete: lib/lz4 owns the layout. * Allocate LZ4_MEM_COMPRESS bytes and cast, do not sizeof().
@@ -85,21 +87,11 @@ typedef union LZ4_stream_u LZ4_stream_t; typedef union LZ4_streamHC_u LZ4_streamHC_t; /* - * LZ4_streamDecode_t - information structure to track an - * LZ4 stream during decompression. - * - * init this structure using LZ4_setStreamDecode (or memset()) before first use + * LZ4_streamDecode_t - an LZ4 stream during decompression. Incomplete: + * lib/lz4 owns the layout. Allocate LZ4_MEM_DECOMPRESS bytes and cast, do + * not sizeof(). Init with LZ4_setStreamDecode() (or zero it) before use. */ -typedef struct { - const uint8_t *externalDict; - size_t extDictSize; - const uint8_t *prefixEnd; - size_t prefixSize; -} LZ4_streamDecode_t_internal; -typedef union { - unsigned long long table[LZ4_STREAMDECODESIZE_U64]; - LZ4_streamDecode_t_internal internal_donotuse; -} LZ4_streamDecode_t; +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /*-************************************************************************ * SIZE OF STATE
@@ -111,23 +103,12 @@ typedef union { */ #define LZ4_MEM_COMPRESS 16416 #define LZ4HC_MEM_COMPRESS 262200 +#define LZ4_MEM_DECOMPRESS 32 /*-************************************************************************ * Compression Functions **************************************************************************/ -/** - * LZ4_compressBound() - Max. output size in worst case szenarios - * @isize: Size of the input data - * - * Return: Max. size LZ4 may output in a "worst case" szenario - * (data not compressible) - */ -static inline int LZ4_compressBound(size_t isize) -{ - return LZ4_COMPRESSBOUND(isize); -} - /** * LZ4_compress_default() - Compress data from source to dest * @source: source address of the original data
@@ -141,7 +122,7 @@ static inline int LZ4_compressBound(size_t isize) * Compresses 'sourceSize' bytes from buffer 'source' * into already allocated 'dest' buffer of size 'maxOutputSize'. * Compression is guaranteed to succeed if - * 'maxOutputSize' >= LZ4_compressBound(inputSize). + * 'maxOutputSize' >= LZ4_COMPRESSBOUND(inputSize). * It also runs faster, so it's a recommended setting. * If the function cannot compress 'source' into a more limited 'dest' budget, * compression stops *immediately*, and the function result is zero.
@@ -295,7 +276,7 @@ int LZ4_decompress_safe_partial(const char *source, char *dest, * * Compress data from 'src' into 'dst', using the more powerful * but slower "HC" algorithm. Compression is guaranteed to succeed if - * `dstCapacity >= LZ4_compressBound(srcSize) + * `dstCapacity >= LZ4_COMPRESSBOUND(srcSize) * * Return : the number of bytes written into 'dst' or 0 if compression fails. */
@@ -359,7 +340,7 @@ int LZ4_loadDictHC(LZ4_streamHC_t *streamHCPtr, const char *dictionary, * (including initial dictionary when present) must remain accessible * and unmodified during compression. * 'dst' buffer should be sized to handle worst case scenarios, using - * LZ4_compressBound(), to ensure operation success. + * LZ4_COMPRESSBOUND(), to ensure operation success. * If, for any reason, previous data blocks can't be preserved unmodified * in memory during next compression block, * you must save it to a safer memory space, using LZ4_saveDictHC().
@@ -455,7 +436,7 @@ int LZ4_saveDict(LZ4_stream_t *streamPtr, char *safeBuffer, int dictSize); * as dictionary to improve compression ratio. * Important : Previous data blocks are assumed to still * be present and unmodified ! - * If maxDstSize >= LZ4_compressBound(srcSize), + * If maxDstSize >= LZ4_COMPRESSBOUND(srcSize), * compression is guaranteed to succeed, and runs faster. * * Return: Number of bytes written into buffer 'dst' or 0 if compression fails
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c
index c0dbb3cea915eb91d8f4ac26c38c4785bbf19770..48ac767dbf68d69082dd00fa4970aaf50aa1db5c 100644
--- a/lib/decompress_unlz4.c
+++ b/lib/decompress_unlz4.c@@ -69,7 +69,7 @@ STATIC inline int INIT unlz4(u8 *input, long in_len, error("NULL input pointer and missing fill function"); goto exit_1; } else { - inp = large_malloc(LZ4_compressBound(uncomp_chunksize)); + inp = large_malloc(LZ4_COMPRESSBOUND(uncomp_chunksize)); if (!inp) { error("Could not allocate input buffer"); goto exit_1;
@@ -140,7 +140,7 @@ STATIC inline int INIT unlz4(u8 *input, long in_len, inp += 4; size -= 4; } else { - if (chunksize > LZ4_compressBound(uncomp_chunksize)) { + if (chunksize > LZ4_COMPRESSBOUND(uncomp_chunksize)) { error("chunk length is longer than allocated"); goto exit_2; }
diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
index 3a2cd9acada4a09ef70a344090d48167c46088a1..68c8a87476df58fff48b1ffbeee8f2d3bbf743df 100644
--- a/lib/lz4/lz4_decompress.c
+++ b/lib/lz4/lz4_decompress.c@@ -1,707 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause /* - * LZ4 - Fast LZ compression algorithm * Copyright (C) 2011 - 2016, Yann Collet. - * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php) - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * You can contact the author at : - * - LZ4 homepage : http://www.lz4.org - * - LZ4 source repository : https://github.com/lz4/lz4 + * Copyright (C) 2016, Sven Schmidt <4sschmid@informatik.uni-hamburg.de> + * Copyright (c) 2026 Samsung Electronics Co., Ltd. + * Author: Michal Wilczynski <m.wilczynski@samsung.com> * - * Changed for kernel usage by: - * Sven Schmidt <4sschmid@informatik.uni-hamburg.de> + * LZ4 decompressor -- kernel entry points + * + * The decompressor is upstream's, in the verbatim lz4.c included below. The + * API is signature-compatible, so every export is a plain forwarder. This + * file is also included by lib/decompress_unlz4.c for the pre-boot + * decompressor, which defines STATIC. */ -/*-************************************ - * Dependencies - **************************************/ -#include "lz4defs.h" -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/unaligned.h> +#include "lz4_deps.h" +#include "upstream/lz4.c" -/*-***************************** - * Decompression functions - *******************************/ +/* Upstream's short names for these clash with <linux/minmax.h>. */ +#undef MIN +#undef MAX +#undef KB +#undef MB +#undef GB -#define DEBUGLOG(l, ...) {} /* disabled */ +#include "lz4_kernel_api.h" -#ifndef assert -#define assert(condition) ((void)0) +#ifndef STATIC +#include <linux/export.h> +#include <linux/module.h> #endif -/* - * LZ4_decompress_generic() : - * This generic decompression function covers all use cases. - * It shall be instantiated several times, using different sets of directives. - * Note that it is important for performance that this function really get inlined, - * in order to remove useless branches during compilation optimization. - */ -static FORCE_INLINE int LZ4_decompress_generic( - const char * const src, - char * const dst, - int srcSize, - /* - * If endOnInput == endOnInputSize, - * this value is `dstCapacity` - */ - int outputSize, - /* endOnOutputSize, endOnInputSize */ - endCondition_directive endOnInput, - /* full, partial */ - earlyEnd_directive partialDecoding, - /* noDict, withPrefix64k, usingExtDict */ - dict_directive dict, - /* always <= dst, == dst when no prefix */ - const BYTE * const lowPrefix, - /* only if dict == usingExtDict */ - const BYTE * const dictStart, - /* note : = 0 if noDict */ - const size_t dictSize - ) -{ - const BYTE *ip = (const BYTE *) src; - const BYTE * const iend = ip + srcSize; - - BYTE *op = (BYTE *) dst; - BYTE * const oend = op + outputSize; - BYTE *cpy; - - const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize; - static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4}; - static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3}; - - const int safeDecode = (endOnInput == endOnInputSize); - const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB))); - - /* Set up the "end" pointers for the shortcut. */ - const BYTE *const shortiend = iend - - (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/; - const BYTE *const shortoend = oend - - (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/; - - DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__, - srcSize, outputSize); - - /* Special cases */ - assert(lowPrefix <= op); - assert(src != NULL); - - /* Empty output buffer */ - if ((endOnInput) && (unlikely(outputSize == 0))) - return ((srcSize == 1) && (*ip == 0)) ? 0 : -1; - - if ((!endOnInput) && (unlikely(outputSize == 0))) - return (*ip == 0 ? 1 : -1); - - if ((endOnInput) && unlikely(srcSize == 0)) - return -1; - - /* Main Loop : decode sequences */ - while (1) { - size_t length; - const BYTE *match; - size_t offset; - - /* get literal length */ - unsigned int const token = *ip++; - length = token>>ML_BITS; - - /* ip < iend before the increment */ - assert(!endOnInput || ip <= iend); - - /* - * A two-stage shortcut for the most common case: - * 1) If the literal length is 0..14, and there is enough - * space, enter the shortcut and copy 16 bytes on behalf - * of the literals (in the fast mode, only 8 bytes can be - * safely copied this way). - * 2) Further if the match length is 4..18, copy 18 bytes - * in a similar manner; but we ensure that there's enough - * space in the output for those 18 bytes earlier, upon - * entering the shortcut (in other words, there is a - * combined check for both stages). - * - * The & in the likely() below is intentionally not && so that - * some compilers can produce better parallelized runtime code - */ - if ((endOnInput ? length != RUN_MASK : length <= 8) - /* - * strictly "less than" on input, to re-enter - * the loop with at least one byte - */ - && likely((endOnInput ? ip < shortiend : 1) & - (op <= shortoend))) { - /* Copy the literals */ - LZ4_memcpy(op, ip, endOnInput ? 16 : 8); - op += length; ip += length; - - /* - * The second stage: - * prepare for match copying, decode full info. - * If it doesn't work out, the info won't be wasted. - */ - length = token & ML_MASK; /* match length */ - offset = LZ4_readLE16(ip); - ip += 2; - match = op - offset; - assert(match <= op); /* check overflow */ - - /* Do not deal with overlapping matches. */ - if ((length != ML_MASK) && - (offset >= 8) && - (dict == withPrefix64k || match >= lowPrefix)) { - /* Copy the match. */ - LZ4_memcpy(op + 0, match + 0, 8); - LZ4_memcpy(op + 8, match + 8, 8); - LZ4_memcpy(op + 16, match + 16, 2); - op += length + MINMATCH; - /* Both stages worked, load the next token. */ - continue; - } - - /* - * The second stage didn't work out, but the info - * is ready. Propel it right to the point of match - * copying. - */ - goto _copy_match; - } - - /* decode literal length */ - if (length == RUN_MASK) { - unsigned int s; - - if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) { - /* overflow detection */ - goto _output_error; - } - do { - s = *ip++; - length += s; - } while (likely(endOnInput - ? ip < iend - RUN_MASK - : 1) & (s == 255)); - - if ((safeDecode) - && unlikely((uptrval)(op) + - length < (uptrval)(op))) { - /* overflow detection */ - goto _output_error; - } - if ((safeDecode) - && unlikely((uptrval)(ip) + - length < (uptrval)(ip))) { - /* overflow detection */ - goto _output_error; - } - } - - /* copy literals */ - cpy = op + length; - LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); - - if (((endOnInput) && ((cpy > oend - MFLIMIT) - || (ip + length > iend - (2 + 1 + LASTLITERALS)))) - || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) { - if (partialDecoding) { - if (cpy > oend) { - /* - * Partial decoding : - * stop in the middle of literal segment - */ - cpy = oend; - length = oend - op; - } - if ((endOnInput) - && (ip + length > iend)) { - /* - * Error : - * read attempt beyond - * end of input buffer - */ - goto _output_error; - } - } else { - if ((!endOnInput) - && (cpy != oend)) { - /* - * Error : - * block decoding must - * stop exactly there - */ - goto _output_error; - } - if ((endOnInput) - && ((ip + length != iend) - || (cpy > oend))) { - /* - * Error : - * input must be consumed - */ - goto _output_error; - } - } - - /* - * supports overlapping memory regions; only matters - * for in-place decompression scenarios - */ - LZ4_memmove(op, ip, length); - ip += length; - op += length; - - /* Necessarily EOF when !partialDecoding. - * When partialDecoding, it is EOF if we've either - * filled the output buffer or - * can't proceed with reading an offset for following match. - */ - if (!partialDecoding || (cpy == oend) || (ip >= (iend - 2))) - break; - } else { - /* may overwrite up to WILDCOPYLENGTH beyond cpy */ - LZ4_wildCopy(op, ip, cpy); - ip += length; - op = cpy; - } - - /* get offset */ - offset = LZ4_readLE16(ip); - ip += 2; - match = op - offset; - - /* get matchlength */ - length = token & ML_MASK; - -_copy_match: - if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { - /* Error : offset outside buffers */ - goto _output_error; - } - - /* costs ~1%; silence an msan warning when offset == 0 */ - /* - * note : when partialDecoding, there is no guarantee that - * at least 4 bytes remain available in output buffer - */ - if (!partialDecoding) { - assert(oend > op); - assert(oend - op >= 4); - - LZ4_write32(op, (U32)offset); - } - - if (length == ML_MASK) { - unsigned int s; - - do { - s = *ip++; - - if ((endOnInput) && (ip > iend - LASTLITERALS)) - goto _output_error; - - length += s; - } while (s == 255); - - if ((safeDecode) - && unlikely( - (uptrval)(op) + length < (uptrval)op)) { - /* overflow detection */ - goto _output_error; - } - } - - length += MINMATCH; - - /* match starting within external dictionary */ - if ((dict == usingExtDict) && (match < lowPrefix)) { - if (unlikely(op + length > oend - LASTLITERALS)) { - /* doesn't respect parsing restriction */ - if (!partialDecoding) - goto _output_error; - length = min(length, (size_t)(oend - op)); - } - - if (length <= (size_t)(lowPrefix - match)) { - /* - * match fits entirely within external - * dictionary : just copy - */ - memmove(op, dictEnd - (lowPrefix - match), - length); - op += length; - } else { - /* - * match stretches into both external - * dictionary and current block - */ - size_t const copySize = (size_t)(lowPrefix - match); - size_t const restSize = length - copySize; +static_assert(sizeof(LZ4_streamDecode_t) == LZ4_STREAMDECODE_MINSIZE); +static_assert(LZ4_STREAMDECODE_MINSIZE == 32); /* LZ4_MEM_DECOMPRESS */ - LZ4_memcpy(op, dictEnd - copySize, copySize); - op += copySize; - if (restSize > (size_t)(op - lowPrefix)) { - /* overlap copy */ - BYTE * const endOfMatch = op + restSize; - const BYTE *copyFrom = lowPrefix; - - while (op < endOfMatch) - *op++ = *copyFrom++; - } else { - LZ4_memcpy(op, lowPrefix, restSize); - op += restSize; - } - } - continue; - } - - /* copy match within block */ - cpy = op + length; - - /* - * partialDecoding : - * may not respect endBlock parsing restrictions - */ - assert(op <= oend); - if (partialDecoding && - (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { - size_t const mlen = min(length, (size_t)(oend - op)); - const BYTE * const matchEnd = match + mlen; - BYTE * const copyEnd = op + mlen; - - if (matchEnd > op) { - /* overlap copy */ - while (op < copyEnd) - *op++ = *match++; - } else { - LZ4_memcpy(op, match, mlen); - } - op = copyEnd; - if (op == oend) - break; - continue; - } - - if (unlikely(offset < 8)) { - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += inc32table[offset]; - LZ4_memcpy(op + 4, match, 4); - match -= dec64table[offset]; - } else { - LZ4_copy8(op, match); - match += 8; - } - - op += 8; - - if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { - BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1); - - if (cpy > oend - LASTLITERALS) { - /* - * Error : last LASTLITERALS bytes - * must be literals (uncompressed) - */ - goto _output_error; - } - - if (op < oCopyLimit) { - LZ4_wildCopy(op, match, oCopyLimit); - match += oCopyLimit - op; - op = oCopyLimit; - } - while (op < cpy) - *op++ = *match++; - } else { - LZ4_copy8(op, match); - if (length > 16) - LZ4_wildCopy(op + 8, match + 8, cpy); - } - op = cpy; /* wildcopy correction */ - } - - /* end of decoding */ - if (endOnInput) { - /* Nb of output bytes decoded */ - return (int) (((char *)op) - dst); - } else { - /* Nb of input bytes read */ - return (int) (((const char *)ip) - src); - } - - /* Overflow error detected */ -_output_error: - return (int) (-(((const char *)ip) - src)) - 1; -} - -int LZ4_decompress_safe(const char *source, char *dest, - int compressedSize, int maxDecompressedSize) +int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, + int maxDecompressedSize) { - return LZ4_decompress_generic(source, dest, - compressedSize, maxDecompressedSize, - endOnInputSize, decode_full_block, - noDict, (BYTE *)dest, NULL, 0); + return __lz4_decompress_safe(source, dest, compressedSize, + maxDecompressedSize); } -int LZ4_decompress_safe_partial(const char *src, char *dst, - int compressedSize, int targetOutputSize, int dstCapacity) +int LZ4_decompress_safe_partial(const char *source, char *dest, + int compressedSize, int targetOutputSize, + int maxDecompressedSize) { - dstCapacity = min(targetOutputSize, dstCapacity); - return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, - endOnInputSize, partial_decode, - noDict, (BYTE *)dst, NULL, 0); + return __lz4_decompress_safe_partial(source, dest, compressedSize, + targetOutputSize, + maxDecompressedSize); } int LZ4_decompress_fast(const char *source, char *dest, int originalSize) { - return LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, decode_full_block, - withPrefix64k, - (BYTE *)dest - 64 * KB, NULL, 0); -} - -/* ===== Instantiate a few more decoding cases, used more than once. ===== */ - -static int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest, - int compressedSize, int maxOutputSize) -{ - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, - withPrefix64k, - (BYTE *)dest - 64 * KB, NULL, 0); + return __lz4_decompress_fast(source, dest, originalSize); } -static int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest, - int compressedSize, - int maxOutputSize, - size_t prefixSize) -{ - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, - noDict, - (BYTE *)dest - prefixSize, NULL, 0); -} - -static int LZ4_decompress_safe_forceExtDict(const char *source, char *dest, - int compressedSize, int maxOutputSize, - const void *dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, - usingExtDict, (BYTE *)dest, - (const BYTE *)dictStart, dictSize); -} - -static int LZ4_decompress_fast_extDict(const char *source, char *dest, - int originalSize, - const void *dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, - 0, originalSize, - endOnOutputSize, decode_full_block, - usingExtDict, (BYTE *)dest, - (const BYTE *)dictStart, dictSize); -} - -/* - * The "double dictionary" mode, for use with e.g. ring buffers: the first part - * of the dictionary is passed as prefix, and the second via dictStart + dictSize. - * These routines are used only once, in LZ4_decompress_*_continue(). - */ -static FORCE_INLINE -int LZ4_decompress_safe_doubleDict(const char *source, char *dest, - int compressedSize, int maxOutputSize, - size_t prefixSize, - const void *dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, - usingExtDict, (BYTE *)dest - prefixSize, - (const BYTE *)dictStart, dictSize); -} - -static FORCE_INLINE -int LZ4_decompress_fast_doubleDict(const char *source, char *dest, - int originalSize, size_t prefixSize, - const void *dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, - 0, originalSize, - endOnOutputSize, decode_full_block, - usingExtDict, (BYTE *)dest - prefixSize, - (const BYTE *)dictStart, dictSize); -} - -/* ===== streaming decompression functions ===== */ - int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, - const char *dictionary, int dictSize) + const char *dictionary, int dictSize) { - LZ4_streamDecode_t_internal *lz4sd = - &LZ4_streamDecode->internal_donotuse; - - lz4sd->prefixSize = (size_t) dictSize; - lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize; - lz4sd->externalDict = NULL; - lz4sd->extDictSize = 0; - return 1; + return __lz4_setStreamDecode(LZ4_streamDecode, dictionary, dictSize); } -/* - * *_continue() : - * These decoding functions allow decompression of multiple blocks - * in "streaming" mode. - * Previously decoded blocks must still be available at the memory - * position where they were decoded. - * If it's not possible, save the relevant part of - * decoded data into a safe buffer, - * and indicate where it stands using LZ4_setStreamDecode() - */ int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, - const char *source, char *dest, int compressedSize, int maxOutputSize) + const char *source, char *dest, + int compressedSize, int maxDecompressedSize) { - LZ4_streamDecode_t_internal *lz4sd = - &LZ4_streamDecode->internal_donotuse; - int result; - - if (lz4sd->prefixSize == 0) { - /* The first call, no dictionary yet. */ - assert(lz4sd->extDictSize == 0); - result = LZ4_decompress_safe(source, dest, - compressedSize, maxOutputSize); - if (result <= 0) - return result; - lz4sd->prefixSize = result; - lz4sd->prefixEnd = (BYTE *)dest + result; - } else if (lz4sd->prefixEnd == (BYTE *)dest) { - /* They're rolling the current segment. */ - if (lz4sd->prefixSize >= 64 * KB - 1) - result = LZ4_decompress_safe_withPrefix64k(source, dest, - compressedSize, maxOutputSize); - else if (lz4sd->extDictSize == 0) - result = LZ4_decompress_safe_withSmallPrefix(source, - dest, compressedSize, maxOutputSize, - lz4sd->prefixSize); - else - result = LZ4_decompress_safe_doubleDict(source, dest, - compressedSize, maxOutputSize, - lz4sd->prefixSize, - lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) - return result; - lz4sd->prefixSize += result; - lz4sd->prefixEnd += result; - } else { - /* - * The buffer wraps around, or they're - * switching to another buffer. - */ - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_safe_forceExtDict(source, dest, - compressedSize, maxOutputSize, - lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) - return result; - lz4sd->prefixSize = result; - lz4sd->prefixEnd = (BYTE *)dest + result; - } - - return result; + return __lz4_decompress_safe_continue(LZ4_streamDecode, source, dest, + compressedSize, + maxDecompressedSize); } int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, - const char *source, char *dest, int originalSize) + const char *source, char *dest, + int originalSize) { - LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse; - int result; - - if (lz4sd->prefixSize == 0) { - assert(lz4sd->extDictSize == 0); - result = LZ4_decompress_fast(source, dest, originalSize); - if (result <= 0) - return result; - lz4sd->prefixSize = originalSize; - lz4sd->prefixEnd = (BYTE *)dest + originalSize; - } else if (lz4sd->prefixEnd == (BYTE *)dest) { - if (lz4sd->prefixSize >= 64 * KB - 1 || - lz4sd->extDictSize == 0) - result = LZ4_decompress_fast(source, dest, - originalSize); - else - result = LZ4_decompress_fast_doubleDict(source, dest, - originalSize, lz4sd->prefixSize, - lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) - return result; - lz4sd->prefixSize += originalSize; - lz4sd->prefixEnd += originalSize; - } else { - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_fast_extDict(source, dest, - originalSize, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) - return result; - lz4sd->prefixSize = originalSize; - lz4sd->prefixEnd = (BYTE *)dest + originalSize; - } - return result; + return __lz4_decompress_fast_continue(LZ4_streamDecode, source, dest, + originalSize); } int LZ4_decompress_safe_usingDict(const char *source, char *dest, - int compressedSize, int maxOutputSize, + int compressedSize, int maxDecompressedSize, const char *dictStart, int dictSize) { - if (dictSize == 0) - return LZ4_decompress_safe(source, dest, - compressedSize, maxOutputSize); - if (dictStart+dictSize == dest) { - if (dictSize >= 64 * KB - 1) - return LZ4_decompress_safe_withPrefix64k(source, dest, - compressedSize, maxOutputSize); - return LZ4_decompress_safe_withSmallPrefix(source, dest, - compressedSize, maxOutputSize, dictSize); - } - return LZ4_decompress_safe_forceExtDict(source, dest, - compressedSize, maxOutputSize, dictStart, dictSize); + return __lz4_decompress_safe_usingDict(source, dest, compressedSize, + maxDecompressedSize, dictStart, + dictSize); } int LZ4_decompress_fast_usingDict(const char *source, char *dest, - int originalSize, - const char *dictStart, int dictSize) + int originalSize, const char *dictStart, + int dictSize) { - if (dictSize == 0 || dictStart + dictSize == dest) - return LZ4_decompress_fast(source, dest, originalSize); - - return LZ4_decompress_fast_extDict(source, dest, originalSize, - dictStart, dictSize); + return __lz4_decompress_fast_usingDict(source, dest, originalSize, + dictStart, dictSize); } #ifndef STATIC
diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h
deleted file mode 100644
index 17277ec16919f3a554afc7d91ad515c493d745ca..0000000000000000000000000000000000000000
--- a/lib/lz4/lz4defs.h
+++ /dev/null@@ -1,247 +0,0 @@ -#ifndef __LZ4DEFS_H__ -#define __LZ4DEFS_H__ - -/* - * lz4defs.h -- common and architecture specific defines for the kernel usage - - * LZ4 - Fast LZ compression algorithm - * Copyright (C) 2011-2016, Yann Collet. - * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * You can contact the author at : - * - LZ4 homepage : http://www.lz4.org - * - LZ4 source repository : https://github.com/lz4/lz4 - * - * Changed for kernel usage by: - * Sven Schmidt <4sschmid@informatik.uni-hamburg.de> - */ - -#include <linux/unaligned.h> - -#include <linux/bitops.h> -#include <linux/string.h> /* memset, memcpy */ -#include <linux/lz4.h> - -#define FORCE_INLINE __always_inline - -/*-************************************ - * Basic Types - **************************************/ -#include <linux/types.h> - -typedef uint8_t BYTE; -typedef uint16_t U16; -typedef uint32_t U32; -typedef int32_t S32; -typedef uint64_t U64; -typedef uintptr_t uptrval; - -/*-************************************ - * Architecture specifics - **************************************/ -#if defined(CONFIG_64BIT) -#define LZ4_ARCH64 1 -#else -#define LZ4_ARCH64 0 -#endif - -#if defined(__LITTLE_ENDIAN) -#define LZ4_LITTLE_ENDIAN 1 -#else -#define LZ4_LITTLE_ENDIAN 0 -#endif - -/*-************************************ - * Constants - **************************************/ -#define MINMATCH 4 - -#define WILDCOPYLENGTH 8 -#define LASTLITERALS 5 -#define MFLIMIT (WILDCOPYLENGTH + MINMATCH) -/* - * ensure it's possible to write 2 x wildcopyLength - * without overflowing output buffer - */ -#define MATCH_SAFEGUARD_DISTANCE ((2 * WILDCOPYLENGTH) - MINMATCH) - -/* Increase this value ==> compression run slower on incompressible data */ -#define LZ4_SKIPTRIGGER 6 - -#define HASH_UNIT sizeof(size_t) - -#define KB (1 << 10) -#define MB (1 << 20) -#define GB (1U << 30) - -#define MAX_DISTANCE LZ4_DISTANCE_MAX -#define STEPSIZE sizeof(size_t) - -#define ML_BITS 4 -#define ML_MASK ((1U << ML_BITS) - 1) -#define RUN_BITS (8 - ML_BITS) -#define RUN_MASK ((1U << RUN_BITS) - 1) - -/*-************************************ - * Reading and writing into memory - **************************************/ -static FORCE_INLINE U16 LZ4_read16(const void *ptr) -{ - return get_unaligned((const U16 *)ptr); -} - -static FORCE_INLINE U32 LZ4_read32(const void *ptr) -{ - return get_unaligned((const U32 *)ptr); -} - -static FORCE_INLINE size_t LZ4_read_ARCH(const void *ptr) -{ - return get_unaligned((const size_t *)ptr); -} - -static FORCE_INLINE void LZ4_write16(void *memPtr, U16 value) -{ - put_unaligned(value, (U16 *)memPtr); -} - -static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value) -{ - put_unaligned(value, (U32 *)memPtr); -} - -static FORCE_INLINE U16 LZ4_readLE16(const void *memPtr) -{ - return get_unaligned_le16(memPtr); -} - -static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value) -{ - return put_unaligned_le16(value, memPtr); -} - -/* - * LZ4 relies on memcpy with a constant size being inlined. In freestanding - * environments, the compiler can't assume the implementation of memcpy() is - * standard compliant, so apply its specialized memcpy() inlining logic. When - * possible, use __builtin_memcpy() to tell the compiler to analyze memcpy() - * as-if it were standard compliant, so it can inline it in freestanding - * environments. This is needed when decompressing the Linux Kernel, for example. - */ -#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) -#define LZ4_memmove(dst, src, size) __builtin_memmove(dst, src, size) - -static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) -{ -#if LZ4_ARCH64 - U64 a = get_unaligned((const U64 *)src); - - put_unaligned(a, (U64 *)dst); -#else - U32 a = get_unaligned((const U32 *)src); - U32 b = get_unaligned((const U32 *)src + 1); - - put_unaligned(a, (U32 *)dst); - put_unaligned(b, (U32 *)dst + 1); -#endif -} - -/* - * customized variant of memcpy, - * which can overwrite up to 7 bytes beyond dstEnd - */ -static FORCE_INLINE void LZ4_wildCopy(void *dstPtr, - const void *srcPtr, void *dstEnd) -{ - BYTE *d = (BYTE *)dstPtr; - const BYTE *s = (const BYTE *)srcPtr; - BYTE *const e = (BYTE *)dstEnd; - - do { - LZ4_copy8(d, s); - d += 8; - s += 8; - } while (d < e); -} - -static FORCE_INLINE unsigned int LZ4_NbCommonBytes(register size_t val) -{ -#if LZ4_LITTLE_ENDIAN - return __ffs(val) >> 3; -#else - return (BITS_PER_LONG - 1 - __fls(val)) >> 3; -#endif -} - -static FORCE_INLINE unsigned int LZ4_count( - const BYTE *pIn, - const BYTE *pMatch, - const BYTE *pInLimit) -{ - const BYTE *const pStart = pIn; - - while (likely(pIn < pInLimit - (STEPSIZE - 1))) { - size_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); - - if (!diff) { - pIn += STEPSIZE; - pMatch += STEPSIZE; - continue; - } - - pIn += LZ4_NbCommonBytes(diff); - - return (unsigned int)(pIn - pStart); - } - -#if LZ4_ARCH64 - if ((pIn < (pInLimit - 3)) - && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { - pIn += 4; - pMatch += 4; - } -#endif - - if ((pIn < (pInLimit - 1)) - && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { - pIn += 2; - pMatch += 2; - } - - if ((pIn < pInLimit) && (*pMatch == *pIn)) - pIn++; - - return (unsigned int)(pIn - pStart); -} - -typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive; -typedef enum { byPtr, byU32, byU16 } tableType_t; - -typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; -typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; - -typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; -typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; - -#define LZ4_STATIC_ASSERT(c) BUILD_BUG_ON(!(c)) - -#endif
--
2.34.1