Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/lzo: separate lzo-rle from lzo

To prevent any issues with persistent data, separate lzo-rle from lzo so
that it is treated as a separate algorithm, and lzo is still available.

Link: http://lkml.kernel.org/r/20190205155944.16007-3-dave.rodgman@arm.com
Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Markus F.X.J. Oberhumer <markus@oberhumer.com>
Cc: Matt Sealey <matt.sealey@arm.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nitin Gupta <nitingupta910@gmail.com>
Cc: Richard Purdie <rpurdie@openedhand.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: Sonny Rao <sonnyrao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dave Rodgman and committed by
Linus Torvalds
45ec975e 5ee4014a

+226 -17
+8 -4
Documentation/lzo.txt
··· 88 88 common case for zram. This modifies the bitstream in a backwards compatible way 89 89 (v1 can correctly decompress v0 compressed data, but v0 cannot read v1 data). 90 90 91 + For maximum compatibility, both versions are available under different names 92 + (lzo and lzo-rle). Differences in the encoding are noted in this document with 93 + e.g.: version 1 only. 94 + 91 95 Byte sequences 92 96 ============== 93 97 ··· 103 99 invalid at this place. 104 100 105 101 17 : bitstream version. If the first byte is 17, the next byte 106 - gives the bitstream version. If the first byte is not 17, 107 - the bitstream version is 0. 102 + gives the bitstream version (version 1 only). If the first byte 103 + is not 17, the bitstream version is 0. 108 104 109 105 18..21 : copy 0..3 literals 110 106 state = (byte - 17) = 0..3 [ copy <state> literals ] ··· 158 154 state = S (copy S literals after this block) 159 155 End of stream is reached if distance == 16384 160 156 161 - In version 1, this instruction is also used to encode a run of zeros if 162 - distance = 0xbfff, i.e. H = 1 and the D bits are all 1. 157 + In version 1 only, this instruction is also used to encode a run of 158 + zeros if distance = 0xbfff, i.e. H = 1 and the D bits are all 1. 163 159 In this case, it is followed by a fourth byte, X. 164 160 run length = ((X << 3) | (0 0 0 0 0 L L L)) + 4. 165 161
+1 -1
crypto/Makefile
··· 128 128 obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o 129 129 obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o 130 130 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o 131 - obj-$(CONFIG_CRYPTO_LZO) += lzo.o 131 + obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o 132 132 obj-$(CONFIG_CRYPTO_LZ4) += lz4.o 133 133 obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o 134 134 obj-$(CONFIG_CRYPTO_842) += 842.o
+175
crypto/lzo-rle.c
··· 1 + /* 2 + * Cryptographic API. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 51 15 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 + * 17 + */ 18 + 19 + #include <linux/init.h> 20 + #include <linux/module.h> 21 + #include <linux/crypto.h> 22 + #include <linux/vmalloc.h> 23 + #include <linux/mm.h> 24 + #include <linux/lzo.h> 25 + #include <crypto/internal/scompress.h> 26 + 27 + struct lzorle_ctx { 28 + void *lzorle_comp_mem; 29 + }; 30 + 31 + static void *lzorle_alloc_ctx(struct crypto_scomp *tfm) 32 + { 33 + void *ctx; 34 + 35 + ctx = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); 36 + if (!ctx) 37 + return ERR_PTR(-ENOMEM); 38 + 39 + return ctx; 40 + } 41 + 42 + static int lzorle_init(struct crypto_tfm *tfm) 43 + { 44 + struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm); 45 + 46 + ctx->lzorle_comp_mem = lzorle_alloc_ctx(NULL); 47 + if (IS_ERR(ctx->lzorle_comp_mem)) 48 + return -ENOMEM; 49 + 50 + return 0; 51 + } 52 + 53 + static void lzorle_free_ctx(struct crypto_scomp *tfm, void *ctx) 54 + { 55 + kvfree(ctx); 56 + } 57 + 58 + static void lzorle_exit(struct crypto_tfm *tfm) 59 + { 60 + struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm); 61 + 62 + lzorle_free_ctx(NULL, ctx->lzorle_comp_mem); 63 + } 64 + 65 + static int __lzorle_compress(const u8 *src, unsigned int slen, 66 + u8 *dst, unsigned int *dlen, void *ctx) 67 + { 68 + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ 69 + int err; 70 + 71 + err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx); 72 + 73 + if (err != LZO_E_OK) 74 + return -EINVAL; 75 + 76 + *dlen = tmp_len; 77 + return 0; 78 + } 79 + 80 + static int lzorle_compress(struct crypto_tfm *tfm, const u8 *src, 81 + unsigned int slen, u8 *dst, unsigned int *dlen) 82 + { 83 + struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm); 84 + 85 + return __lzorle_compress(src, slen, dst, dlen, ctx->lzorle_comp_mem); 86 + } 87 + 88 + static int lzorle_scompress(struct crypto_scomp *tfm, const u8 *src, 89 + unsigned int slen, u8 *dst, unsigned int *dlen, 90 + void *ctx) 91 + { 92 + return __lzorle_compress(src, slen, dst, dlen, ctx); 93 + } 94 + 95 + static int __lzorle_decompress(const u8 *src, unsigned int slen, 96 + u8 *dst, unsigned int *dlen) 97 + { 98 + int err; 99 + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ 100 + 101 + err = lzo1x_decompress_safe(src, slen, dst, &tmp_len); 102 + 103 + if (err != LZO_E_OK) 104 + return -EINVAL; 105 + 106 + *dlen = tmp_len; 107 + return 0; 108 + } 109 + 110 + static int lzorle_decompress(struct crypto_tfm *tfm, const u8 *src, 111 + unsigned int slen, u8 *dst, unsigned int *dlen) 112 + { 113 + return __lzorle_decompress(src, slen, dst, dlen); 114 + } 115 + 116 + static int lzorle_sdecompress(struct crypto_scomp *tfm, const u8 *src, 117 + unsigned int slen, u8 *dst, unsigned int *dlen, 118 + void *ctx) 119 + { 120 + return __lzorle_decompress(src, slen, dst, dlen); 121 + } 122 + 123 + static struct crypto_alg alg = { 124 + .cra_name = "lzo-rle", 125 + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 126 + .cra_ctxsize = sizeof(struct lzorle_ctx), 127 + .cra_module = THIS_MODULE, 128 + .cra_init = lzorle_init, 129 + .cra_exit = lzorle_exit, 130 + .cra_u = { .compress = { 131 + .coa_compress = lzorle_compress, 132 + .coa_decompress = lzorle_decompress } } 133 + }; 134 + 135 + static struct scomp_alg scomp = { 136 + .alloc_ctx = lzorle_alloc_ctx, 137 + .free_ctx = lzorle_free_ctx, 138 + .compress = lzorle_scompress, 139 + .decompress = lzorle_sdecompress, 140 + .base = { 141 + .cra_name = "lzo-rle", 142 + .cra_driver_name = "lzo-rle-scomp", 143 + .cra_module = THIS_MODULE, 144 + } 145 + }; 146 + 147 + static int __init lzorle_mod_init(void) 148 + { 149 + int ret; 150 + 151 + ret = crypto_register_alg(&alg); 152 + if (ret) 153 + return ret; 154 + 155 + ret = crypto_register_scomp(&scomp); 156 + if (ret) { 157 + crypto_unregister_alg(&alg); 158 + return ret; 159 + } 160 + 161 + return ret; 162 + } 163 + 164 + static void __exit lzorle_mod_fini(void) 165 + { 166 + crypto_unregister_alg(&alg); 167 + crypto_unregister_scomp(&scomp); 168 + } 169 + 170 + module_init(lzorle_mod_init); 171 + module_exit(lzorle_mod_fini); 172 + 173 + MODULE_LICENSE("GPL"); 174 + MODULE_DESCRIPTION("LZO-RLE Compression Algorithm"); 175 + MODULE_ALIAS_CRYPTO("lzo-rle");
+2 -2
crypto/tcrypt.c
··· 76 76 "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", 77 77 "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", 78 78 "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", 79 - "lzo", "cts", "sha3-224", "sha3-256", "sha3-384", "sha3-512", 80 - "streebog256", "streebog512", 79 + "lzo", "lzo-rle", "cts", "sha3-224", "sha3-256", "sha3-384", 80 + "sha3-512", "streebog256", "streebog512", 81 81 NULL 82 82 }; 83 83
+1
drivers/block/zram/zcomp.c
··· 20 20 21 21 static const char * const backends[] = { 22 22 "lzo", 23 + "lzo-rle", 23 24 #if IS_ENABLED(CONFIG_CRYPTO_LZ4) 24 25 "lz4", 25 26 #endif
+4
include/linux/lzo.h
··· 24 24 int lzo1x_1_compress(const unsigned char *src, size_t src_len, 25 25 unsigned char *dst, size_t *dst_len, void *wrkmem); 26 26 27 + /* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */ 28 + int lzorle1x_1_compress(const unsigned char *src, size_t src_len, 29 + unsigned char *dst, size_t *dst_len, void *wrkmem); 30 + 27 31 /* safe decompression with overrun testing */ 28 32 int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, 29 33 unsigned char *dst, size_t *dst_len);
+33 -9
lib/lzo/lzo1x_compress.c
··· 20 20 static noinline size_t 21 21 lzo1x_1_do_compress(const unsigned char *in, size_t in_len, 22 22 unsigned char *out, size_t *out_len, 23 - size_t ti, void *wrkmem, signed char *state_offset) 23 + size_t ti, void *wrkmem, signed char *state_offset, 24 + const unsigned char bitstream_version) 24 25 { 25 26 const unsigned char *ip; 26 27 unsigned char *op; ··· 47 46 break; 48 47 dv = get_unaligned_le32(ip); 49 48 50 - if (dv == 0) { 49 + if (dv == 0 && bitstream_version) { 51 50 const unsigned char *ir = ip + 4; 52 51 const unsigned char *limit = ip_end 53 52 < (ip + MAX_ZERO_RUN_LENGTH + 1) ··· 285 284 return in_end - (ii - ti); 286 285 } 287 286 288 - int lzo1x_1_compress(const unsigned char *in, size_t in_len, 287 + int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, 289 288 unsigned char *out, size_t *out_len, 290 - void *wrkmem) 289 + void *wrkmem, const unsigned char bitstream_version) 291 290 { 292 291 const unsigned char *ip = in; 293 292 unsigned char *op = out; 294 293 size_t l = in_len; 295 294 size_t t = 0; 296 295 signed char state_offset = -2; 296 + unsigned int m4_max_offset; 297 297 298 298 // LZO v0 will never write 17 as first byte, 299 299 // so this is used to version the bitstream 300 - *op++ = 17; 301 - *op++ = LZO_VERSION; 300 + if (bitstream_version > 0) { 301 + *op++ = 17; 302 + *op++ = bitstream_version; 303 + m4_max_offset = M4_MAX_OFFSET_V1; 304 + } else { 305 + m4_max_offset = M4_MAX_OFFSET_V0; 306 + } 302 307 303 308 while (l > 20) { 304 - size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1); 309 + size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1); 305 310 uintptr_t ll_end = (uintptr_t) ip + ll; 306 311 if ((ll_end + ((t + ll) >> 5)) <= ll_end) 307 312 break; 308 313 BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS); 309 314 memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t)); 310 - t = lzo1x_1_do_compress(ip, ll, op, out_len, 311 - t, wrkmem, &state_offset); 315 + t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem, 316 + &state_offset, bitstream_version); 312 317 ip += ll; 313 318 op += *out_len; 314 319 l -= ll; ··· 358 351 *out_len = op - out; 359 352 return LZO_E_OK; 360 353 } 354 + 355 + int lzo1x_1_compress(const unsigned char *in, size_t in_len, 356 + unsigned char *out, size_t *out_len, 357 + void *wrkmem) 358 + { 359 + return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0); 360 + } 361 + 362 + int lzorle1x_1_compress(const unsigned char *in, size_t in_len, 363 + unsigned char *out, size_t *out_len, 364 + void *wrkmem) 365 + { 366 + return lzogeneric1x_1_compress(in, in_len, out, out_len, 367 + wrkmem, LZO_VERSION); 368 + } 369 + 361 370 EXPORT_SYMBOL_GPL(lzo1x_1_compress); 371 + EXPORT_SYMBOL_GPL(lzorle1x_1_compress); 362 372 363 373 MODULE_LICENSE("GPL"); 364 374 MODULE_DESCRIPTION("LZO1X-1 Compressor");
+2 -1
lib/lzo/lzodefs.h
··· 44 44 #define M1_MAX_OFFSET 0x0400 45 45 #define M2_MAX_OFFSET 0x0800 46 46 #define M3_MAX_OFFSET 0x4000 47 - #define M4_MAX_OFFSET 0xbffe 47 + #define M4_MAX_OFFSET_V0 0xbfff 48 + #define M4_MAX_OFFSET_V1 0xbffe 48 49 49 50 #define M1_MIN_LEN 2 50 51 #define M1_MAX_LEN 2