lkml.org 
[lkml]   [2018]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 7/8] lib/lzo: separate lzo-rle from lzo
    Date
    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/20181127161913.23863-8-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: Stephen Rothwell <sfr@canb.auug.org.au>
    Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
    ---
    Documentation/lzo.txt | 12 ++-
    crypto/Makefile | 2 +-
    crypto/lzo-rle.c | 175 +++++++++++++++++++++++++++++++++++++
    crypto/tcrypt.c | 4 +-
    drivers/block/zram/zcomp.c | 1 +
    include/linux/lzo.h | 4 +
    lib/lzo/lzo1x_compress.c | 42 +++++++--
    lib/lzo/lzodefs.h | 3 +-
    8 files changed, 226 insertions(+), 17 deletions(-)
    create mode 100644 crypto/lzo-rle.c

    diff --git a/Documentation/lzo.txt b/Documentation/lzo.txt
    index 306c60344ca7..f79934225d8d 100644
    --- a/Documentation/lzo.txt
    +++ b/Documentation/lzo.txt
    @@ -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.

    diff --git a/crypto/Makefile b/crypto/Makefile
    index 5e789dc2d4fd..23491b70e601 100644
    --- a/crypto/Makefile
    +++ b/crypto/Makefile
    @@ -127,7 +127,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
    diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c
    new file mode 100644
    index 000000000000..ea9c75b1db49
    --- /dev/null
    +++ b/crypto/lzo-rle.c
    @@ -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");
    diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
    index 0590a9204562..c1c56c9771cf 100644
    --- a/crypto/tcrypt.c
    +++ b/crypto/tcrypt.c
    @@ -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
    };

    diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
    index 4ed0a78fdc09..4d9a38890965 100644
    --- a/drivers/block/zram/zcomp.c
    +++ b/drivers/block/zram/zcomp.c
    @@ -20,6 +20,7 @@

    static const char * const backends[] = {
    "lzo",
    + "lzo-rle",
    #if IS_ENABLED(CONFIG_CRYPTO_LZ4)
    "lz4",
    #endif
    diff --git a/include/linux/lzo.h b/include/linux/lzo.h
    index 547a86c71e1b..e95c7d1092b2 100644
    --- a/include/linux/lzo.h
    +++ b/include/linux/lzo.h
    @@ -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);
    diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
    index 03834b99a5a1..c4384ea14a50 100644
    --- a/lib/lzo/lzo1x_compress.c
    +++ b/lib/lzo/lzo1x_compress.c
    @@ -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 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
    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)
    @@ -282,30 +283,36 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
    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;
    @@ -348,7 +355,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");
    diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
    index 682359058b3c..c0657441a35d 100644
    --- a/lib/lzo/lzodefs.h
    +++ b/lib/lzo/lzodefs.h
    @@ -52,7 +52,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
    --
    2.17.1
    \
     
     \ /
      Last update: 2018-11-30 15:27    [W:6.582 / U:0.724 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site