forked from Minki/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>
This commit is contained in:
parent
5ee4014af9
commit
45ec975efb
@ -88,6 +88,10 @@ length encoding. This improves speed for data with many zeros, which is a
|
||||
common case for zram. This modifies the bitstream in a backwards compatible way
|
||||
(v1 can correctly decompress v0 compressed data, but v0 cannot read v1 data).
|
||||
|
||||
For maximum compatibility, both versions are available under different names
|
||||
(lzo and lzo-rle). Differences in the encoding are noted in this document with
|
||||
e.g.: version 1 only.
|
||||
|
||||
Byte sequences
|
||||
==============
|
||||
|
||||
@ -99,8 +103,8 @@ Byte sequences
|
||||
invalid at this place.
|
||||
|
||||
17 : bitstream version. If the first byte is 17, the next byte
|
||||
gives the bitstream version. If the first byte is not 17,
|
||||
the bitstream version is 0.
|
||||
gives the bitstream version (version 1 only). If the first byte
|
||||
is not 17, the bitstream version is 0.
|
||||
|
||||
18..21 : copy 0..3 literals
|
||||
state = (byte - 17) = 0..3 [ copy <state> literals ]
|
||||
@ -154,8 +158,8 @@ Byte sequences
|
||||
state = S (copy S literals after this block)
|
||||
End of stream is reached if distance == 16384
|
||||
|
||||
In version 1, this instruction is also used to encode a run of zeros if
|
||||
distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
|
||||
In version 1 only, this instruction is also used to encode a run of
|
||||
zeros if distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
|
||||
In this case, it is followed by a fourth byte, X.
|
||||
run length = ((X << 3) | (0 0 0 0 0 L L L)) + 4.
|
||||
|
||||
|
@ -128,7 +128,7 @@ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
|
||||
obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o
|
||||
obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
|
||||
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
|
||||
obj-$(CONFIG_CRYPTO_LZO) += lzo.o
|
||||
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
|
||||
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
|
||||
obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
|
||||
obj-$(CONFIG_CRYPTO_842) += 842.o
|
||||
|
175
crypto/lzo-rle.c
Normal file
175
crypto/lzo-rle.c
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/lzo.h>
|
||||
#include <crypto/internal/scompress.h>
|
||||
|
||||
struct lzorle_ctx {
|
||||
void *lzorle_comp_mem;
|
||||
};
|
||||
|
||||
static void *lzorle_alloc_ctx(struct crypto_scomp *tfm)
|
||||
{
|
||||
void *ctx;
|
||||
|
||||
ctx = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static int lzorle_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
ctx->lzorle_comp_mem = lzorle_alloc_ctx(NULL);
|
||||
if (IS_ERR(ctx->lzorle_comp_mem))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lzorle_free_ctx(struct crypto_scomp *tfm, void *ctx)
|
||||
{
|
||||
kvfree(ctx);
|
||||
}
|
||||
|
||||
static void lzorle_exit(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
lzorle_free_ctx(NULL, ctx->lzorle_comp_mem);
|
||||
}
|
||||
|
||||
static int __lzorle_compress(const u8 *src, unsigned int slen,
|
||||
u8 *dst, unsigned int *dlen, void *ctx)
|
||||
{
|
||||
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
|
||||
int err;
|
||||
|
||||
err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx);
|
||||
|
||||
if (err != LZO_E_OK)
|
||||
return -EINVAL;
|
||||
|
||||
*dlen = tmp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lzorle_compress(struct crypto_tfm *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen)
|
||||
{
|
||||
struct lzorle_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
return __lzorle_compress(src, slen, dst, dlen, ctx->lzorle_comp_mem);
|
||||
}
|
||||
|
||||
static int lzorle_scompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen,
|
||||
void *ctx)
|
||||
{
|
||||
return __lzorle_compress(src, slen, dst, dlen, ctx);
|
||||
}
|
||||
|
||||
static int __lzorle_decompress(const u8 *src, unsigned int slen,
|
||||
u8 *dst, unsigned int *dlen)
|
||||
{
|
||||
int err;
|
||||
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
|
||||
|
||||
err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
|
||||
|
||||
if (err != LZO_E_OK)
|
||||
return -EINVAL;
|
||||
|
||||
*dlen = tmp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lzorle_decompress(struct crypto_tfm *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen)
|
||||
{
|
||||
return __lzorle_decompress(src, slen, dst, dlen);
|
||||
}
|
||||
|
||||
static int lzorle_sdecompress(struct crypto_scomp *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen,
|
||||
void *ctx)
|
||||
{
|
||||
return __lzorle_decompress(src, slen, dst, dlen);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "lzo-rle",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct lzorle_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_init = lzorle_init,
|
||||
.cra_exit = lzorle_exit,
|
||||
.cra_u = { .compress = {
|
||||
.coa_compress = lzorle_compress,
|
||||
.coa_decompress = lzorle_decompress } }
|
||||
};
|
||||
|
||||
static struct scomp_alg scomp = {
|
||||
.alloc_ctx = lzorle_alloc_ctx,
|
||||
.free_ctx = lzorle_free_ctx,
|
||||
.compress = lzorle_scompress,
|
||||
.decompress = lzorle_sdecompress,
|
||||
.base = {
|
||||
.cra_name = "lzo-rle",
|
||||
.cra_driver_name = "lzo-rle-scomp",
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init lzorle_mod_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = crypto_register_alg(&alg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = crypto_register_scomp(&scomp);
|
||||
if (ret) {
|
||||
crypto_unregister_alg(&alg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit lzorle_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
crypto_unregister_scomp(&scomp);
|
||||
}
|
||||
|
||||
module_init(lzorle_mod_init);
|
||||
module_exit(lzorle_mod_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("LZO-RLE Compression Algorithm");
|
||||
MODULE_ALIAS_CRYPTO("lzo-rle");
|
@ -76,8 +76,8 @@ static char *check[] = {
|
||||
"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
|
||||
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
|
||||
"camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
|
||||
"lzo", "cts", "sha3-224", "sha3-256", "sha3-384", "sha3-512",
|
||||
"streebog256", "streebog512",
|
||||
"lzo", "lzo-rle", "cts", "sha3-224", "sha3-256", "sha3-384",
|
||||
"sha3-512", "streebog256", "streebog512",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
static const char * const backends[] = {
|
||||
"lzo",
|
||||
"lzo-rle",
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
|
||||
"lz4",
|
||||
#endif
|
||||
|
@ -24,6 +24,10 @@
|
||||
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst, size_t *dst_len, void *wrkmem);
|
||||
|
||||
/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
|
||||
int lzorle1x_1_compress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst, size_t *dst_len, void *wrkmem);
|
||||
|
||||
/* safe decompression with overrun testing */
|
||||
int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst, size_t *dst_len);
|
||||
|
@ -20,7 +20,8 @@
|
||||
static noinline size_t
|
||||
lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
size_t ti, void *wrkmem, signed char *state_offset)
|
||||
size_t ti, void *wrkmem, signed char *state_offset,
|
||||
const unsigned char bitstream_version)
|
||||
{
|
||||
const unsigned char *ip;
|
||||
unsigned char *op;
|
||||
@ -46,7 +47,7 @@ next:
|
||||
break;
|
||||
dv = get_unaligned_le32(ip);
|
||||
|
||||
if (dv == 0) {
|
||||
if (dv == 0 && bitstream_version) {
|
||||
const unsigned char *ir = ip + 4;
|
||||
const unsigned char *limit = ip_end
|
||||
< (ip + MAX_ZERO_RUN_LENGTH + 1)
|
||||
@ -284,30 +285,36 @@ finished_writing_instruction:
|
||||
return in_end - (ii - ti);
|
||||
}
|
||||
|
||||
int lzo1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
void *wrkmem)
|
||||
void *wrkmem, const unsigned char bitstream_version)
|
||||
{
|
||||
const unsigned char *ip = in;
|
||||
unsigned char *op = out;
|
||||
size_t l = in_len;
|
||||
size_t t = 0;
|
||||
signed char state_offset = -2;
|
||||
unsigned int m4_max_offset;
|
||||
|
||||
// LZO v0 will never write 17 as first byte,
|
||||
// so this is used to version the bitstream
|
||||
*op++ = 17;
|
||||
*op++ = LZO_VERSION;
|
||||
if (bitstream_version > 0) {
|
||||
*op++ = 17;
|
||||
*op++ = bitstream_version;
|
||||
m4_max_offset = M4_MAX_OFFSET_V1;
|
||||
} else {
|
||||
m4_max_offset = M4_MAX_OFFSET_V0;
|
||||
}
|
||||
|
||||
while (l > 20) {
|
||||
size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
|
||||
size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
|
||||
uintptr_t ll_end = (uintptr_t) ip + ll;
|
||||
if ((ll_end + ((t + ll) >> 5)) <= ll_end)
|
||||
break;
|
||||
BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
|
||||
memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
|
||||
t = lzo1x_1_do_compress(ip, ll, op, out_len,
|
||||
t, wrkmem, &state_offset);
|
||||
t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem,
|
||||
&state_offset, bitstream_version);
|
||||
ip += ll;
|
||||
op += *out_len;
|
||||
l -= ll;
|
||||
@ -351,7 +358,24 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
*out_len = op - out;
|
||||
return LZO_E_OK;
|
||||
}
|
||||
|
||||
int lzo1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
void *wrkmem)
|
||||
{
|
||||
return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0);
|
||||
}
|
||||
|
||||
int lzorle1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
void *wrkmem)
|
||||
{
|
||||
return lzogeneric1x_1_compress(in, in_len, out, out_len,
|
||||
wrkmem, LZO_VERSION);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(lzo1x_1_compress);
|
||||
EXPORT_SYMBOL_GPL(lzorle1x_1_compress);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("LZO1X-1 Compressor");
|
||||
|
@ -44,7 +44,8 @@
|
||||
#define M1_MAX_OFFSET 0x0400
|
||||
#define M2_MAX_OFFSET 0x0800
|
||||
#define M3_MAX_OFFSET 0x4000
|
||||
#define M4_MAX_OFFSET 0xbffe
|
||||
#define M4_MAX_OFFSET_V0 0xbfff
|
||||
#define M4_MAX_OFFSET_V1 0xbffe
|
||||
|
||||
#define M1_MIN_LEN 2
|
||||
#define M1_MAX_LEN 2
|
||||
|
Loading…
Reference in New Issue
Block a user