From: Gao Xiang <hsiang...@aol.com> This patch adds LZMA compression algorithms to erofs-utils compression framework by using upstream liblzma.
Cc: Lasse Collin <lasse.col...@tukaani.org> Signed-off-by: Gao Xiang <hsiang...@aol.com> --- include/erofs_fs.h | 3 +- lib/Makefile.am | 1 + lib/compress.c | 5 ++- lib/compressor.c | 1 + lib/compressor.h | 1 + lib/compressor_liblzma.c | 93 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 lib/compressor_liblzma.c diff --git a/include/erofs_fs.h b/include/erofs_fs.h index a69f179a51a5..24772043cb8b 100644 --- a/include/erofs_fs.h +++ b/include/erofs_fs.h @@ -193,7 +193,8 @@ static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) /* available compression algorithm types (for h_algorithmtype) */ enum { - Z_EROFS_COMPRESSION_LZ4 = 0, + Z_EROFS_COMPRESSION_LZ4 = 0, + Z_EROFS_COMPRESSION_LZMA = 1, Z_EROFS_COMPRESSION_MAX }; diff --git a/lib/Makefile.am b/lib/Makefile.am index e048a16d73f2..e9b3255a2653 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,3 +14,4 @@ endif endif liberofs_la_CFLAGS += -I/tmp/xz-test/include +liberofs_la_SOURCES += compressor_liblzma.c diff --git a/lib/compress.c b/lib/compress.c index 2e8deaf81907..d77998fb6857 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -493,6 +493,8 @@ static int erofs_get_compress_algorithm_id(const char *name) { if (!strcmp(name, "lz4") || !strcmp(name, "lz4hc")) return Z_EROFS_COMPRESSION_LZ4; + if (!strcmp(name, "lzma")) + return Z_EROFS_COMPRESSION_LZMA; return -ENOTSUP; } @@ -511,7 +513,8 @@ int z_erofs_compress_init(void) * clear LZ4_0PADDING feature for old kernel compatibility. */ if (!cfg.c_compr_alg_master || - strncmp(cfg.c_compr_alg_master, "lz4", 3)) + (strncmp(cfg.c_compr_alg_master, "lz4", 3) && + strcmp(cfg.c_compr_alg_master, "lzma"))) erofs_sb_clear_lz4_0padding(); if (!cfg.c_compr_alg_master) diff --git a/lib/compressor.c b/lib/compressor.c index e28aa8f934c0..cc39fc7a685a 100644 --- a/lib/compressor.c +++ b/lib/compressor.c @@ -19,6 +19,7 @@ static struct erofs_compressor *compressors[] = { #endif &erofs_compressor_lz4, #endif + &erofs_compressor_lzma, }; int erofs_compress_destsize(struct erofs_compress *c, diff --git a/lib/compressor.h b/lib/compressor.h index 8c4e72cfa8b9..e783ca1de509 100644 --- a/lib/compressor.h +++ b/lib/compressor.h @@ -45,6 +45,7 @@ struct erofs_compress { /* list of compression algorithms */ extern struct erofs_compressor erofs_compressor_lz4; extern struct erofs_compressor erofs_compressor_lz4hc; +extern struct erofs_compressor erofs_compressor_lzma; int erofs_compress_destsize(struct erofs_compress *c, void *src, unsigned int *srcsize, diff --git a/lib/compressor_liblzma.c b/lib/compressor_liblzma.c new file mode 100644 index 000000000000..af135c2cd32b --- /dev/null +++ b/lib/compressor_liblzma.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * erofs-utils/lib/compressor_liblzma.c + * + * Copyright (C) 2018-2019 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang <gaoxian...@huawei.com> + */ +#include <stdlib.h> +#include <lzma.h> +#include "erofs/internal.h" +#include "compressor.h" + +struct erofs_liblzma_context { + lzma_options_lzma opt; + lzma_stream strm; +}; + +static int erofs_liblzma_compress_destsize(struct erofs_compress *c, + void *src, unsigned int *srcsize, + void *dst, unsigned int dstsize) +{ + struct erofs_liblzma_context *ctx = c->private_data; + lzma_stream *strm = &ctx->strm; + + lzma_ret ret = lzma_erofs_encoder(strm, &ctx->opt); + if (ret != LZMA_OK) + return -EFAULT; + + strm->next_in = src; + strm->avail_in = *srcsize; + strm->next_out = dst; + strm->avail_out = dstsize; + + ret = lzma_code(strm, LZMA_FINISH); + if (ret != LZMA_STREAM_END) + return -EBADMSG; + + *srcsize = strm->total_in; + return strm->total_out; +} + +static int erofs_compressor_liblzma_exit(struct erofs_compress *c) +{ + struct erofs_liblzma_context *ctx = c->private_data; + + if (!ctx) + return -EINVAL; + + lzma_end(&ctx->strm); + free(ctx); + return 0; +} + +static int erofs_compressor_liblzma_setlevel(struct erofs_compress *c, + int compression_level) +{ + struct erofs_liblzma_context *ctx = c->private_data; + + if (compression_level < 0) + compression_level = LZMA_PRESET_DEFAULT; + + if (lzma_lzma_preset(&ctx->opt, compression_level)) + return -EINVAL; + + ctx->opt.dict_size = 64U << 10; + c->compression_level = compression_level; + return 0; +} + +static int erofs_compressor_liblzma_init(struct erofs_compress *c) +{ + struct erofs_liblzma_context *ctx; + + c->alg = &erofs_compressor_lzma; + ctx = malloc(sizeof(*ctx)); + if (!ctx) + return -ENOMEM; + ctx->strm = (lzma_stream)LZMA_STREAM_INIT; + c->private_data = ctx; + return 0; +} + +struct erofs_compressor erofs_compressor_lzma = { + .name = "lzma", + .default_level = LZMA_PRESET_DEFAULT, + .best_level = LZMA_PRESET_EXTREME, + .init = erofs_compressor_liblzma_init, + .exit = erofs_compressor_liblzma_exit, + .setlevel = erofs_compressor_liblzma_setlevel, + .compress_destsize = erofs_liblzma_compress_destsize, +}; + -- 2.24.0