[PATCH 1/2] erofs-utils: fix reproducible builds for multi-threaded libdeflate
Gao Xiang
hsiangkao at linux.alibaba.com
Fri Jul 12 19:38:07 AEST 2024
`last_uncompressed_size` should be reset on the basis of segments.
Fixes: 830b27bc2334 ("erofs-utils: mkfs: introduce inner-file multi-threaded compression")
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/compress.c | 2 +-
lib/compressor.c | 6 +++++
lib/compressor.h | 2 ++
lib/compressor_libdeflate.c | 46 +++++++++++++++++++++++++++----------
4 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/lib/compress.c b/lib/compress.c
index b473587..b61907a 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -1245,7 +1245,7 @@ void z_erofs_mt_workfn(struct erofs_work *work, void *tlsp)
sctx->queue = tls->queue;
sctx->destbuf = tls->destbuf;
sctx->chandle = &tls->ccfg[cwork->alg_id].handle;
-
+ erofs_compressor_reset(sctx->chandle);
sctx->membuf = malloc(round_up(sctx->remaining, erofs_blksiz(sbi)));
if (!sctx->membuf) {
ret = -ENOMEM;
diff --git a/lib/compressor.c b/lib/compressor.c
index 24c99ac..41f49ff 100644
--- a/lib/compressor.c
+++ b/lib/compressor.c
@@ -155,3 +155,9 @@ int erofs_compressor_exit(struct erofs_compress *c)
return c->alg->c->exit(c);
return 0;
}
+
+void erofs_compressor_reset(struct erofs_compress *c)
+{
+ if (c->alg && c->alg->c->reset)
+ c->alg->c->reset(c);
+}
diff --git a/lib/compressor.h b/lib/compressor.h
index 59d525d..8d322d5 100644
--- a/lib/compressor.h
+++ b/lib/compressor.h
@@ -19,6 +19,7 @@ struct erofs_compressor {
int (*init)(struct erofs_compress *c);
int (*exit)(struct erofs_compress *c);
+ void (*reset)(struct erofs_compress *c);
int (*setlevel)(struct erofs_compress *c, int compression_level);
int (*setdictsize)(struct erofs_compress *c, u32 dict_size);
@@ -63,5 +64,6 @@ int erofs_compress_destsize(const struct erofs_compress *c,
int erofs_compressor_init(struct erofs_sb_info *sbi, struct erofs_compress *c,
char *alg_name, int compression_level, u32 dict_size);
int erofs_compressor_exit(struct erofs_compress *c);
+void erofs_compressor_reset(struct erofs_compress *c);
#endif
diff --git a/lib/compressor_libdeflate.c b/lib/compressor_libdeflate.c
index 14cbce4..32e8ff9 100644
--- a/lib/compressor_libdeflate.c
+++ b/lib/compressor_libdeflate.c
@@ -3,22 +3,28 @@
#include "erofs/print.h"
#include "erofs/config.h"
#include <libdeflate.h>
+#include <stdlib.h>
#include "compressor.h"
#include "erofs/atomic.h"
+struct erofs_libdeflate_context {
+ struct libdeflate_compressor *strm;
+ size_t last_uncompressed_size;
+};
+
static int libdeflate_compress_destsize(const struct erofs_compress *c,
const void *src, unsigned int *srcsize,
void *dst, unsigned int dstsize)
{
- static size_t last_uncompressed_size = 0;
+ struct erofs_libdeflate_context *ctx = c->private_data;
size_t l = 0; /* largest input that fits so far */
size_t l_csize = 0;
size_t r = *srcsize + 1; /* smallest input that doesn't fit so far */
size_t m;
u8 tmpbuf[dstsize + 9];
- if (last_uncompressed_size)
- m = last_uncompressed_size * 15 / 16;
+ if (ctx->last_uncompressed_size)
+ m = ctx->last_uncompressed_size * 15 / 16;
else
m = dstsize * 4;
for (;;) {
@@ -27,7 +33,7 @@ static int libdeflate_compress_destsize(const struct erofs_compress *c,
m = max(m, l + 1);
m = min(m, r - 1);
- csize = libdeflate_deflate_compress(c->private_data, src, m,
+ csize = libdeflate_deflate_compress(ctx->strm, src, m,
tmpbuf, dstsize + 9);
/*printf("Tried %zu => %zu\n", m, csize);*/
if (csize > 0 && csize <= dstsize) {
@@ -68,33 +74,48 @@ static int libdeflate_compress_destsize(const struct erofs_compress *c,
/*printf("Choosing %zu => %zu\n", l, l_csize);*/
*srcsize = l;
- last_uncompressed_size = l;
+ ctx->last_uncompressed_size = l;
return l_csize;
}
static int compressor_libdeflate_exit(struct erofs_compress *c)
{
- if (!c->private_data)
- return -EINVAL;
+ struct erofs_libdeflate_context *ctx = c->private_data;
- libdeflate_free_compressor(c->private_data);
+ if (!ctx)
+ return -EINVAL;
+ libdeflate_free_compressor(ctx->strm);
+ free(ctx);
return 0;
}
static int compressor_libdeflate_init(struct erofs_compress *c)
{
static erofs_atomic_bool_t __warnonce;
+ struct erofs_libdeflate_context *ctx;
- libdeflate_free_compressor(c->private_data);
- c->private_data = libdeflate_alloc_compressor(c->compression_level);
- if (!c->private_data)
+ DBG_BUGON(c->private_data);
+ ctx = calloc(1, sizeof(struct erofs_libdeflate_context));
+ if (!ctx)
return -ENOMEM;
-
+ ctx->strm = libdeflate_alloc_compressor(c->compression_level);
+ if (!ctx->strm) {
+ free(ctx);
+ return -ENOMEM;
+ }
+ c->private_data = ctx;
if (!erofs_atomic_test_and_set(&__warnonce))
erofs_warn("EXPERIMENTAL libdeflate compressor in use. Use at your own risk!");
return 0;
}
+static void compressor_libdeflate_reset(struct erofs_compress *c)
+{
+ struct erofs_libdeflate_context *ctx = c->private_data;
+
+ ctx->last_uncompressed_size = 0;
+}
+
static int erofs_compressor_libdeflate_setlevel(struct erofs_compress *c,
int compression_level)
{
@@ -114,6 +135,7 @@ const struct erofs_compressor erofs_compressor_libdeflate = {
.best_level = 12,
.init = compressor_libdeflate_init,
.exit = compressor_libdeflate_exit,
+ .reset = compressor_libdeflate_reset,
.setlevel = erofs_compressor_libdeflate_setlevel,
.compress_destsize = libdeflate_compress_destsize,
};
--
2.43.5
More information about the Linux-erofs
mailing list