From e51b25d77e23fdcc4de50d4dbc77c4d67491b66f Mon Sep 17 00:00:00 2001 From: Kyungsik Lee Date: Mon, 8 Jul 2013 16:01:45 -0700 Subject: [PATCH] decompressor: add LZ4 decompressor module Add support for LZ4 decompression in the Linux Kernel. LZ4 Decompression APIs for kernel are based on LZ4 implementation by Yann Collet. Benchmark Results(PATCH v3) Compiler: Linaro ARM gcc 4.6.2 1. ARMv7, 1.5GHz based board Kernel: linux 3.4 Uncompressed Kernel Size: 14MB Compressed Size Decompression Speed LZO 6.7MB 20.1MB/s, 25.2MB/s(UA) LZ4 7.3MB 29.1MB/s, 45.6MB/s(UA) 2. ARMv7, 1.7GHz based board Kernel: linux 3.7 Uncompressed Kernel Size: 14MB Compressed Size Decompression Speed LZO 6.0MB 34.1MB/s, 52.2MB/s(UA) LZ4 6.5MB 86.7MB/s - UA: Unaligned memory Access support - Latest patch set for LZO applied This patch set is for adding support for LZ4-compressed Kernel. LZ4 is a very fast lossless compression algorithm and it also features an extremely fast decoder [1]. But we have five of decompressors already and one question which does arise, however, is that of where do we stop adding new ones? This issue had been discussed and came to the conclusion [2]. Russell King said that we should have: - one decompressor which is the fastest - one decompressor for the highest compression ratio - one popular decompressor (eg conventional gzip) If we have a replacement one for one of these, then it should do exactly that: replace it. The benchmark shows that an 8% increase in image size vs a 66% increase in decompression speed compared to LZO(which has been known as the fastest decompressor in the Kernel). Therefore the "fast but may not be small" compression title has clearly been taken by LZ4 [3]. [1] http://code.google.com/p/lz4/ [2] http://thread.gmane.org/gmane.linux.kbuild.devel/9157 [3] http://thread.gmane.org/gmane.linux.kbuild.devel/9347 LZ4 homepage: http://fastcompression.blogspot.com/p/lz4.html LZ4 source repository: http://code.google.com/p/lz4/ Change-Id: Ib7d1226ac0facea4c66f3ff50661242294ba6746 Signed-off-by: Kyungsik Lee Signed-off-by: Yann Collet Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Russell King Cc: Borislav Petkov Cc: Florian Fainelli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/lz4.h | 16 +++++++++++++++ lib/lz4/lz4_decompress.c | 42 ++++++++++++++++++++++++++++++++++++++++ lib/lz4/lz4defs.h | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/include/linux/lz4.h b/include/linux/lz4.h index 438943de93b5..a7dadb3007b3 100644 --- a/include/linux/lz4.h +++ b/include/linux/lz4.h @@ -9,8 +9,11 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +<<<<<<< HEAD #define LZ4_MEM_COMPRESS (4096 * sizeof(unsigned char *)) #define LZ4HC_MEM_COMPRESS (65538 * sizeof(unsigned char *)) +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module /* * lz4_compressbound() @@ -23,6 +26,7 @@ static inline size_t lz4_compressbound(size_t isize) } /* +<<<<<<< HEAD * lz4_compress() * src : source address of the original data * src_len : size of the original data @@ -40,6 +44,8 @@ int lz4_compress(const unsigned char *src, size_t src_len, unsigned char *dst, size_t *dst_len, void *wrkmem); /* +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module * lz4_decompress() * src : source address of the compressed data * src_len : is the input size, whcih is returned after decompress done @@ -50,8 +56,13 @@ int lz4_compress(const unsigned char *src, size_t src_len, * note : Destination buffer must be already allocated. * slightly faster than lz4_decompress_unknownoutputsize() */ +<<<<<<< HEAD int lz4_decompress(const unsigned char *src, size_t *src_len, unsigned char *dest, size_t actual_dest_len); +======= +int lz4_decompress(const char *src, size_t *src_len, char *dest, + size_t actual_dest_len); +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module /* * lz4_decompress_unknownoutputsize() @@ -65,6 +76,11 @@ int lz4_decompress(const unsigned char *src, size_t *src_len, * Error if return (< 0) * note : Destination buffer must be already allocated. */ +<<<<<<< HEAD int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, unsigned char *dest, size_t *dest_len); +======= +int lz4_decompress_unknownoutputsize(const char *src, size_t src_len, + char *dest, size_t *dest_len); +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #endif diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c index 7a85967060a5..e22b4e7ce064 100644 --- a/lib/lz4/lz4_decompress.c +++ b/lib/lz4/lz4_decompress.c @@ -1,7 +1,11 @@ /* * LZ4 Decompressor for Linux kernel * +<<<<<<< HEAD * Copyright (C) 2013, LG Electronics, Kyungsik Lee +======= + * Copyright (C) 2013 LG Electronics Co., Ltd. (http://www.lge.com/) +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module * * Based on LZ4 implementation by Yann Collet. * @@ -72,8 +76,11 @@ static int lz4_uncompress(const char *source, char *dest, int osize) len = *ip++; for (; len == 255; length += 255) len = *ip++; +<<<<<<< HEAD if (unlikely(length > (size_t)(length + len))) goto _output_error; +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module length += len; } @@ -108,8 +115,11 @@ static int lz4_uncompress(const char *source, char *dest, int osize) if (length == ML_MASK) { for (; *ip == 255; length += 255) ip++; +<<<<<<< HEAD if (unlikely(length > (size_t)(length + *ip))) goto _output_error; +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module length += *ip++; } @@ -159,7 +169,11 @@ static int lz4_uncompress(const char *source, char *dest, int osize) /* write overflow error detected */ _output_error: +<<<<<<< HEAD return -1; +======= + return (int) (-(((char *)ip) - source)); +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module } static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, @@ -192,8 +206,11 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, int s = 255; while ((ip < iend) && (s == 255)) { s = *ip++; +<<<<<<< HEAD if (unlikely(length > (size_t)(length + s))) goto _output_error; +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module length += s; } } @@ -234,8 +251,11 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, if (length == ML_MASK) { while (ip < iend) { int s = *ip++; +<<<<<<< HEAD if (unlikely(length > (size_t)(length + s))) goto _output_error; +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module length += s; if (s == 255) continue; @@ -288,11 +308,19 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, /* write overflow error detected */ _output_error: +<<<<<<< HEAD return -1; } int lz4_decompress(const unsigned char *src, size_t *src_len, unsigned char *dest, size_t actual_dest_len) +======= + return (int) (-(((char *) ip) - source)); +} + +int lz4_decompress(const char *src, size_t *src_len, char *dest, + size_t actual_dest_len) +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module { int ret = -1; int input_len = 0; @@ -307,11 +335,19 @@ int lz4_decompress(const unsigned char *src, size_t *src_len, return ret; } #ifndef STATIC +<<<<<<< HEAD EXPORT_SYMBOL(lz4_decompress); #endif int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, unsigned char *dest, size_t *dest_len) +======= +EXPORT_SYMBOL_GPL(lz4_decompress); +#endif + +int lz4_decompress_unknownoutputsize(const char *src, size_t src_len, + char *dest, size_t *dest_len) +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module { int ret = -1; int out_len = 0; @@ -327,8 +363,14 @@ int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, return ret; } #ifndef STATIC +<<<<<<< HEAD EXPORT_SYMBOL(lz4_decompress_unknownoutputsize); MODULE_LICENSE("Dual BSD/GPL"); +======= +EXPORT_SYMBOL_GPL(lz4_decompress_unknownoutputsize); + +MODULE_LICENSE("GPL"); +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module MODULE_DESCRIPTION("LZ4 Decompressor"); #endif diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index 697e08287e43..cdf40442c8d2 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -11,7 +11,12 @@ /* * Detects 64 bits mode */ +<<<<<<< HEAD #if defined(CONFIG_64BIT) +======= +#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \ + || defined(__ppc64__) || defined(__LP64__)) +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #define LZ4_ARCH64 1 #else #define LZ4_ARCH64 0 @@ -20,6 +25,7 @@ /* * Architecture-specific macros */ +<<<<<<< HEAD #define ARM_EFFICIENT_UNALIGNED_ACCESS #define BYTE u8 typedef struct _U16_S { u16 v; } U16_S; @@ -28,11 +34,21 @@ typedef struct _U64_S { u64 v; } U64_S; #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) #define A16(x) (((U16_S *)(x))->v) +======= +#define BYTE u8 +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \ + || defined(CONFIG_ARM) && __LINUX_ARM_ARCH__ >= 6 \ + && defined(ARM_EFFICIENT_UNALIGNED_ACCESS) +typedef struct _U32_S { u32 v; } U32_S; +typedef struct _U64_S { u64 v; } U64_S; + +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #define A32(x) (((U32_S *)(x))->v) #define A64(x) (((U64_S *)(x))->v) #define PUT4(s, d) (A32(d) = A32(s)) #define PUT8(s, d) (A64(d) = A64(s)) +<<<<<<< HEAD #define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ (d = s - A16(p)) @@ -48,10 +64,15 @@ typedef struct _U64_S { u64 v; } U64_S; #define A32(x) get_unaligned((u32 *)&(((U16_S *)(x))->v)) #define A16(x) get_unaligned((u16 *)&(((U16_S *)(x))->v)) +======= +#else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ + +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #define PUT4(s, d) \ put_unaligned(get_unaligned((const u32 *) s), (u32 *) d) #define PUT8(s, d) \ put_unaligned(get_unaligned((const u64 *) s), (u64 *) d) +<<<<<<< HEAD #define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ (d = s - get_unaligned_le16(p)) @@ -61,6 +82,8 @@ typedef struct _U64_S { u64 v; } U64_S; put_unaligned_le16(v, (u16 *)(p)); \ p += 2; \ } while (0) +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #endif #define COPYLENGTH 8 @@ -68,6 +91,7 @@ typedef struct _U64_S { u64 v; } U64_S; #define ML_MASK ((1U << ML_BITS) - 1) #define RUN_BITS (8 - ML_BITS) #define RUN_MASK ((1U << RUN_BITS) - 1) +<<<<<<< HEAD #define MEMORY_USAGE 14 #define MINMATCH 4 #define SKIPSTRENGTH 6 @@ -91,6 +115,8 @@ typedef struct _U64_S { u64 v; } U64_S; ((MINMATCH * 8) - HASHLOG64K)) #define HASH_VALUE(p) (((A32(p)) * 2654435761U) >> \ ((MINMATCH * 8) - HASH_LOG)) +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #if LZ4_ARCH64/* 64-bit */ #define STEPSIZE 8 @@ -110,6 +136,7 @@ typedef struct _U64_S { u64 v; } U64_S; LZ4_WILDCOPY(s, d, e); \ } \ } while (0) +<<<<<<< HEAD #define HTYPE u32 #ifdef __BIG_ENDIAN @@ -117,6 +144,8 @@ typedef struct _U64_S { u64 v; } U64_S; #else #define LZ4_NBCOMMONBYTES(val) (__builtin_ctzll(val) >> 3) #endif +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #else /* 32-bit */ #define STEPSIZE 4 @@ -135,6 +164,7 @@ typedef struct _U64_S { u64 v; } U64_S; } while (0) #define LZ4_SECURECOPY LZ4_WILDCOPY +<<<<<<< HEAD #define HTYPE const u8* #ifdef __BIG_ENDIAN @@ -144,11 +174,18 @@ typedef struct _U64_S { u64 v; } U64_S; #endif #endif +======= +#endif + +#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ + (d = s - get_unaligned_le16(p)) +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module #define LZ4_WILDCOPY(s, d, e) \ do { \ LZ4_COPYPACKET(s, d); \ } while (d < e) +<<<<<<< HEAD #define LZ4_BLINDCOPY(s, d, l) \ do { \ @@ -156,3 +193,5 @@ typedef struct _U64_S { u64 v; } U64_S; LZ4_WILDCOPY(s, d, e); \ d = e; \ } while (0) +======= +>>>>>>> e34e7be... decompressor: add LZ4 decompressor module