infra: add zlib compression

This commit is contained in:
Thomas Schoebel-Theuer 2020-03-29 18:17:48 +02:00
parent 6e55a6da95
commit bcf006ab21
5 changed files with 111 additions and 1 deletions

View File

@ -11,6 +11,8 @@ config MARS
select LZO_DECOMPRESS
select LZ4_COMPRESS
select LZ4_DECOMPRESS
select ZLIB_INFLATE
select ZLIB_DEFLATE
select CRYPTO_MD5
select CRYPTO_CRC32
select CRYPTO_CRC32C

View File

@ -248,4 +248,9 @@ extern int _compat_unlink(
#endif
#endif
#if defined(CONFIG_ZLIB_INFLATE) && defined(CONFIG_ZLIB_DEFLATE)
#include <linux/zlib.h>
#define HAS_ZLIB
#endif
#endif /* _MARS_COMPAT */

View File

@ -181,6 +181,7 @@ enum _MREF_FLAGS {
_MREF_CHKSUM_LAST,
_MREF_COMPRESS_LZO = 24,
_MREF_COMPRESS_LZ4,
_MREF_COMPRESS_ZLIB,
_MREF_COMPRESS_LAST,
};
@ -199,6 +200,7 @@ enum _MREF_FLAGS {
#define MREF_CHKSUM_LAST (1UL << _MREF_CHKSUM_LAST)
#define MREF_COMPRESS_LZO (1UL << _MREF_COMPRESS_LZO)
#define MREF_COMPRESS_LZ4 (1UL << _MREF_COMPRESS_LZ4)
#define MREF_COMPRESS_ZLIB (1UL << _MREF_COMPRESS_ZLIB)
#define MREF_CHKSUM_ANY (MREF_CHKSUM_MD5_OLD | \
MREF_CHKSUM_MD5 | \
MREF_CHKSUM_CRC32C | \
@ -206,7 +208,8 @@ enum _MREF_FLAGS {
MREF_CHKSUM_SHA1 | \
MREF_CHKSUM_LAST)
#define MREF_COMPRESS_ANY (MREF_COMPRESS_LZO | \
MREF_COMPRESS_LZ4)
MREF_COMPRESS_LZ4 | \
MREF_COMPRESS_ZLIB)
#define MREF_OBJECT(OBJTYPE) \
CALLBACK_OBJECT(OBJTYPE); \
@ -549,6 +552,8 @@ extern int compress_overhead;
extern __u32 available_compression_mask;
extern __u32 usable_compression_mask;
extern int mars_zlib_compression_level;
extern int mars_compress(void *src_data,
int src_len,
void *dst_data,

View File

@ -644,6 +644,9 @@ __u32 available_compression_mask =
#endif
#ifdef HAS_LZ4
MREF_COMPRESS_LZ4 |
#endif
#ifdef HAS_ZLIB
MREF_COMPRESS_ZLIB |
#endif
0;
@ -651,6 +654,8 @@ __u32 usable_compression_mask = 0;
__u32 used_compression = 0;
int mars_zlib_compression_level = 3;
int mars_compress(void *src_data,
int src_len,
void *dst_data,
@ -759,6 +764,55 @@ int mars_compress(void *src_data,
/* do not try other compression methods */
goto done;
}
#endif
#ifdef HAS_ZLIB
if (check_flags & MREF_COMPRESS_ZLIB) {
size_t zlib_deflate_wrk_size = zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL);
struct z_stream_s stream = {
.workspace = brick_mem_alloc(zlib_deflate_wrk_size),
};
int status;
if (!dst_data) {
tmp_buf = brick_mem_alloc(src_len);
} else if (dst_len < src_len) {
MARS_ERR("ZLIB compression buffer too small: %d < %d\n",
dst_len, src_len);
return 0;
}
status = zlib_deflateInit(&stream, mars_zlib_compression_level);
if (unlikely(status != Z_OK)) {
MARS_ERR("cannot init zlib compression stream\n");
goto zlib_err;
}
stream.next_in = src_data;
stream.avail_in = src_len;
stream.next_out = tmp_buf;
stream.avail_out = src_len;
status = zlib_deflate(&stream, Z_FINISH);
if (status != Z_STREAM_END)
goto zlib_err;
status = zlib_deflateEnd(&stream);
if (status == Z_OK && stream.total_out < src_len) {
used_compression = MREF_COMPRESS_ZLIB;
*result_flags |= MREF_COMPRESS_ZLIB;
res = stream.total_out;
/*
* TODO: avoid memcpy() by swizzling the src_data pointer
*/
if (!dst_data)
memcpy(src_data, tmp_buf, stream.total_out);
}
zlib_err:
brick_mem_free(stream.workspace);
/* do not try other compression methods */
goto done;
}
#endif
used_compression = 0;
@ -821,6 +875,46 @@ void *mars_decompress(void *src_data,
goto err;
}
#endif
#ifdef HAS_ZLIB
if (check_flags & MREF_COMPRESS_ZLIB) {
size_t zlib_inflate_wrk_size = zlib_inflate_workspacesize();
struct z_stream_s stream = {
.workspace = brick_mem_alloc(zlib_inflate_wrk_size),
};
int status;
status = zlib_inflateInit(&stream);
if (unlikely(status != Z_OK)) {
MARS_ERR("cannot init zlib decompression stream\n");
goto zlib_err;
}
stream.next_in = src_data;
stream.avail_in = src_len;
stream.next_out = res_buf;
stream.avail_out = dst_len;
status = zlib_inflate(&stream, Z_FINISH);
if (unlikely(status != Z_STREAM_END)) {
MARS_ERR("bad ZLIB decompression %d (requested %d)\n",
src_len, dst_len);
goto zlib_err;
}
status = zlib_inflateEnd(&stream);
if (likely(status == Z_OK)) {
brick_mem_free(stream.workspace);
goto done;
}
MARS_ERR("unfinished ZLIB decompression %d (requested %d)\n",
src_len, dst_len);
zlib_err:
brick_mem_free(stream.workspace);
goto err;
}
#endif
MARS_ERR("decompression not compiled into kernel module\n");
@ -908,6 +1002,9 @@ int init_mars_compress(void)
#endif
#ifdef HAS_LZ4
benchmark_compress("lz4", MREF_COMPRESS_LZ4);
#endif
#ifdef HAS_ZLIB
benchmark_compress("zlib", MREF_COMPRESS_ZLIB);
#endif
(void)benchmark_compress;
#endif

View File

@ -344,6 +344,7 @@ struct ctl_table mars_table[] = {
INT_ENTRY("logger_completion_semantics", trans_logger_completion_semantics, 0600),
INT_ENTRY("logger_do_crc", trans_logger_do_crc, 0600),
INT_ENTRY("logger_allow_compress", trans_logger_allow_compress, 0600),
INT_ENTRY("zlib_compress_level", mars_zlib_compression_level, 0600),
INT_ENTRY("syslog_min_class", brick_say_syslog_min, 0600),
INT_ENTRY("syslog_max_class", brick_say_syslog_max, 0600),
INT_ENTRY("syslog_flood_class", brick_say_syslog_flood_class, 0600),