[PATCH 1/2] erofs-utils: lib: migrate `c_compr_opts`

Gao Xiang hsiangkao at linux.alibaba.com
Tue Feb 17 01:39:17 AEDT 2026


It's also used to prepare for extra compression option support.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 include/erofs/config.h   |   7 ---
 include/erofs/importer.h |   1 +
 include/erofs/internal.h |   6 ++
 lib/compress.c           |  53 +++++++++--------
 lib/compress_hints.c     |   2 +-
 lib/compressor.c         |  29 ++++------
 lib/compressor.h         |   2 +-
 lib/config.c             |   4 --
 lib/inode.c              |   4 +-
 lib/remotes/s3.c         |   2 +-
 lib/tar.c                |   2 +-
 mkfs/main.c              | 120 +++++++++++++++++++--------------------
 12 files changed, 113 insertions(+), 119 deletions(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 2a84fb515868..3758cc7c198e 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -29,12 +29,6 @@ enum {
 
 #define EROFS_MAX_COMPR_CFGS		64
 
-struct erofs_compr_opts {
-	char *alg;
-	int level;
-	u32 dict_size;
-};
-
 struct erofs_configure {
 	const char *c_version;
 	int c_dbg_lvl;
@@ -54,7 +48,6 @@ struct erofs_configure {
 	char *c_src_path;
 	char *c_blobdev_path;
 	char *c_compress_hints_file;
-	struct erofs_compr_opts c_compr_opts[EROFS_MAX_COMPR_CFGS];
 	char c_force_chunkformat;
 	u8 c_mkfs_metabox_algid;
 	u32 c_max_decompressed_extent_bytes;
diff --git a/include/erofs/importer.h b/include/erofs/importer.h
index adeea7230447..a7a540d4d182 100644
--- a/include/erofs/importer.h
+++ b/include/erofs/importer.h
@@ -30,6 +30,7 @@ enum {
 };
 
 struct erofs_importer_params {
+	struct z_erofs_paramset *z_paramsets;
 	char *source;
 	u32 mt_async_queue_limit;
 	u32 fixed_uid;
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 3f1e4ffa2b52..3ccae0c7ac86 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -434,6 +434,12 @@ struct erofs_map_dev {
 	unsigned int m_deviceid;
 };
 
+struct z_erofs_paramset {
+	char *alg;
+	int clevel;
+	u32 dict_size;
+};
+
 int liberofs_global_init(void);
 void liberofs_global_exit(void);
 
diff --git a/lib/compress.c b/lib/compress.c
index 222e380cdcd7..1c4aa115641d 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -100,11 +100,7 @@ struct erofs_compress_work {
 	struct z_erofs_compress_sctx ctx;
 	pthread_cond_t cond;
 	struct erofs_compress_work *next;
-
-	unsigned int alg_id;
-	char *alg_name;
-	unsigned int comp_level;
-	unsigned int dict_size;
+	struct z_erofs_paramset *zset;
 
 	int errcode;
 };
@@ -126,7 +122,8 @@ struct z_erofs_compress_fslot {
 /* compressing configuration specified by users */
 struct erofs_compress_cfg {
 	struct erofs_compress handle;
-	unsigned int algorithmtype;
+	struct z_erofs_paramset zset;
+	int algorithmtype;
 	bool enable;
 };
 
@@ -1479,19 +1476,22 @@ void z_erofs_mt_workfn(struct erofs_work *work, void *tlsp)
 	struct z_erofs_compress_ictx *ictx = sctx->ictx;
 	struct erofs_inode *inode = ictx->inode;
 	struct erofs_sb_info *sbi = inode->sbi;
-	struct erofs_compress_cfg *lc = &tls->ccfg[cwork->alg_id];
+	int zsetno = container_of(cwork->zset, struct erofs_compress_cfg, zset)
+			- sbi->zmgr->ccfg;
+	struct erofs_compress_cfg *lc = &tls->ccfg[zsetno];
 	int ret;
 
 	if (__erofs_unlikely(!lc->enable)) {
 		unsigned int pclustersize_max =
 			ictx->im->params->pclusterblks_max << sbi->blkszbits;
 
-		ret = erofs_compressor_init(sbi, &lc->handle,
-					    cwork->alg_name, cwork->comp_level,
-					    cwork->dict_size, pclustersize_max);
+		lc->zset = *cwork->zset;
+		ret = erofs_compressor_init(sbi, &lc->handle, &lc->zset,
+					    pclustersize_max);
 		if (ret)
 			goto out;
-		lc->algorithmtype = cwork->alg_id;
+		lc->algorithmtype =
+			z_erofs_get_compress_algorithm_id(&lc->handle);
 		lc->enable = true;
 	}
 
@@ -1499,7 +1499,7 @@ void z_erofs_mt_workfn(struct erofs_work *work, void *tlsp)
 	DBG_BUGON(sctx->pclustersize > Z_EROFS_PCLUSTER_MAX_SIZE);
 	sctx->queue = tls->queue;
 	sctx->destbuf = tls->destbuf;
-	sctx->chandle = &tls->ccfg[cwork->alg_id].handle;
+	sctx->chandle = &lc->handle;
 	erofs_compressor_reset(sctx->chandle);
 	sctx->membuf = malloc(round_up(sctx->remaining, erofs_blksiz(sbi)));
 	if (!sctx->membuf) {
@@ -1639,10 +1639,7 @@ int z_erofs_mt_compress(struct z_erofs_compress_ictx *ictx)
 		};
 		init_list_head(&cur->ctx.extents);
 
-		cur->alg_id = ccfg->handle.alg->id;
-		cur->alg_name = ccfg->handle.alg->name;
-		cur->comp_level = ccfg->handle.compression_level;
-		cur->dict_size = ccfg->handle.dict_size;
+		cur->zset = &ccfg->zset;
 		cur->errcode = 1;	/* mark as "in progress" */
 
 		if (i >= nsegs - 1) {
@@ -2154,13 +2151,20 @@ int z_erofs_compress_init(struct erofs_importer *im)
 		newzmgr = true;
 	}
 
-	for (i = 0; cfg.c_compr_opts[i].alg; ++i) {
+	for (i = 0; params->z_paramsets[i].alg; ++i) {
 		struct erofs_compress_cfg *ccfg = &sbi->zmgr->ccfg[i];
 		struct erofs_compress *c = &ccfg->handle;
+		const struct z_erofs_paramset *zset = &params->z_paramsets[i];
+
+		if (ccfg->enable)
+			return -EINVAL;
 
-		ret = erofs_compressor_init(sbi, c, cfg.c_compr_opts[i].alg,
-					    cfg.c_compr_opts[i].level,
-					    cfg.c_compr_opts[i].dict_size,
+		ccfg->zset = *zset;
+		ccfg->zset.alg = strdup(zset->alg);
+		if (!ccfg->zset.alg)
+			return -ENOMEM;
+
+		ret = erofs_compressor_init(sbi, c, &ccfg->zset,
 					    pclustersize_max);
 		if (ret)
 			return ret;
@@ -2168,8 +2172,8 @@ int z_erofs_compress_init(struct erofs_importer *im)
 		id = z_erofs_get_compress_algorithm_id(c);
 		ccfg->algorithmtype = id;
 		ccfg->enable = true;
-		available_compr_algs |= 1 << ccfg->algorithmtype;
-		if (ccfg->algorithmtype != Z_EROFS_COMPRESSION_LZ4)
+		available_compr_algs |= 1 << id;
+		if (id != Z_EROFS_COMPRESSION_LZ4)
 			erofs_sb_set_compr_cfgs(sbi);
 		if (c->dict_size > max_dict_size[id])
 			max_dict_size[id] = c->dict_size;
@@ -2253,10 +2257,13 @@ int z_erofs_compress_exit(struct erofs_sb_info *sbi)
 	if (!sbi->zmgr)
 		return 0;
 
-	for (i = 0; cfg.c_compr_opts[i].alg; ++i) {
+	for (i = 0; i < ARRAY_SIZE(sbi->zmgr->ccfg); ++i) {
+		if (!sbi->zmgr->ccfg[i].enable)
+			continue;
 		ret = erofs_compressor_exit(&sbi->zmgr->ccfg[i].handle);
 		if (ret)
 			return ret;
+		free(sbi->zmgr->ccfg[i].zset.alg);
 	}
 	free(sbi->zmgr);
 	return 0;
diff --git a/lib/compress_hints.c b/lib/compress_hints.c
index 15f3e54c2ce4..322ec97f474a 100644
--- a/lib/compress_hints.c
+++ b/lib/compress_hints.c
@@ -129,7 +129,7 @@ int erofs_load_compress_hints(struct erofs_importer *im,
 		} else {
 			ccfg = atoi(alg);
 			if (ccfg >= EROFS_MAX_COMPR_CFGS ||
-			    !cfg.c_compr_opts[ccfg].alg) {
+			    !params->z_paramsets[ccfg].alg) {
 				erofs_err("invalid compressing configuration \"%s\" at line %u",
 					  alg, line);
 				ret = -EINVAL;
diff --git a/lib/compressor.c b/lib/compressor.c
index efcead1b1f29..79d80372968e 100644
--- a/lib/compressor.c
+++ b/lib/compressor.c
@@ -97,8 +97,8 @@ int erofs_compress(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, u32 pclustersize_max)
+			  const struct z_erofs_paramset *zset,
+			  u32 pclustersize_max)
 {
 	int ret, i;
 
@@ -109,43 +109,38 @@ int erofs_compressor_init(struct erofs_sb_info *sbi, struct erofs_compress *c,
 	c->compression_level = -1;
 	c->dict_size = 0;
 
-	if (!alg_name) {
-		c->alg = NULL;
-		return 0;
-	}
-
 	ret = -EINVAL;
 	for (i = 0; i < ARRAY_SIZE(erofs_algs); ++i) {
-		if (alg_name && strcmp(alg_name, erofs_algs[i].name))
+		if (strcmp(zset->alg, erofs_algs[i].name))
 			continue;
 
 		if (!erofs_algs[i].c)
 			continue;
 
 		if (erofs_algs[i].c->setlevel) {
-			ret = erofs_algs[i].c->setlevel(c, compression_level);
+			ret = erofs_algs[i].c->setlevel(c, zset->clevel);
 			if (ret) {
 				erofs_err("failed to set compression level %d for %s",
-					  compression_level, alg_name);
+					  zset->clevel, zset->alg);
 				return ret;
 			}
-		} else if (compression_level >= 0) {
+		} else if (zset->clevel >= 0) {
 			erofs_err("compression level %d is not supported for %s",
-				  compression_level, alg_name);
+				  zset->clevel, zset->alg);
 			return -EINVAL;
 		}
 
 		if (erofs_algs[i].c->setdictsize) {
-			ret = erofs_algs[i].c->setdictsize(c, dict_size,
+			ret = erofs_algs[i].c->setdictsize(c, zset->dict_size,
 							   pclustersize_max);
 			if (ret) {
 				erofs_err("failed to set dict size %u for %s",
-					  dict_size, alg_name);
+					  zset->dict_size, zset->alg);
 				return ret;
 			}
-		} else if (dict_size) {
+		} else if (zset->dict_size) {
 			erofs_err("dict size is not supported for %s",
-				  alg_name);
+				  zset->alg);
 			return -EINVAL;
 		}
 
@@ -158,7 +153,7 @@ int erofs_compressor_init(struct erofs_sb_info *sbi, struct erofs_compress *c,
 			return 0;
 		}
 	}
-	erofs_err("Cannot find a valid compressor %s", alg_name);
+	erofs_err("Cannot find a valid compressor %s", zset->alg);
 	return ret;
 }
 
diff --git a/lib/compressor.h b/lib/compressor.h
index c008206a489d..c679466759d3 100644
--- a/lib/compressor.h
+++ b/lib/compressor.h
@@ -69,7 +69,7 @@ int erofs_compress(const struct erofs_compress *c,
 		   void *dst, unsigned int dstcapacity);
 
 int erofs_compressor_init(struct erofs_sb_info *sbi, struct erofs_compress *c,
-			  char *alg_name, int compression_level, u32 dict_size,
+			  const struct z_erofs_paramset *zset,
 			  u32 pclustersize_max);
 int erofs_compressor_exit(struct erofs_compress *c);
 void erofs_compressor_reset(struct erofs_compress *c);
diff --git a/lib/config.c b/lib/config.c
index 5eb0ddeaa851..3398ded56ac1 100644
--- a/lib/config.c
+++ b/lib/config.c
@@ -46,8 +46,6 @@ void erofs_show_config(void)
 
 void erofs_exit_configure(void)
 {
-	int i;
-
 #ifdef HAVE_LIBSELINUX
 	if (cfg.sehnd)
 		selabel_close(cfg.sehnd);
@@ -56,8 +54,6 @@ void erofs_exit_configure(void)
 		free(cfg.c_img_path);
 	if (cfg.c_src_path)
 		free(cfg.c_src_path);
-	for (i = 0; i < EROFS_MAX_COMPR_CFGS && cfg.c_compr_opts[i].alg; i++)
-		free(cfg.c_compr_opts[i].alg);
 }
 
 struct erofs_configure *erofs_get_configure()
diff --git a/lib/inode.c b/lib/inode.c
index 79e5d3bae573..4a214f91cbb2 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -2023,7 +2023,7 @@ static int erofs_mkfs_begin_nondirectory(const struct erofs_mkfs_btctx *btctx,
 				return ret;
 		}
 
-		if (cfg.c_compr_opts[0].alg &&
+		if (inode->sbi->available_compr_algs &&
 		    erofs_file_is_compressible(im, inode)) {
 			ctx.ictx = erofs_prepare_compressed_file(im, inode);
 			if (IS_ERR(ctx.ictx))
@@ -2352,7 +2352,7 @@ struct erofs_inode *erofs_mkfs_build_special_from_fd(struct erofs_importer *im,
 		return ERR_PTR(ret);
 	}
 
-	if (cfg.c_compr_opts[0].alg &&
+	if (sbi->available_compr_algs &&
 	    erofs_file_is_compressible(im, inode)) {
 		ictx = erofs_prepare_compressed_file(im, inode);
 		if (IS_ERR(ictx))
diff --git a/lib/remotes/s3.c b/lib/remotes/s3.c
index 73db4b786c41..5e4e9d39ab24 100644
--- a/lib/remotes/s3.c
+++ b/lib/remotes/s3.c
@@ -1028,7 +1028,7 @@ static int s3erofs_remote_getobject(struct erofs_importer *im,
 		return -EIO;
 
 	resp.pos = 0;
-	if (!cfg.c_compr_opts[0].alg && im->params->no_datainline) {
+	if (!sbi->available_compr_algs && im->params->no_datainline) {
 		inode->datalayout = EROFS_INODE_FLAT_PLAIN;
 		inode->idata_size = 0;
 		ret = erofs_allocate_inode_bh_data(inode,
diff --git a/lib/tar.c b/lib/tar.c
index 1f3092566bd9..178f843c905c 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -1105,7 +1105,7 @@ new_inode:
 								 inode->i_size))
 					ret = -EIO;
 			} else if (tar->try_no_reorder &&
-				   !cfg.c_compr_opts[0].alg &&
+				   !sbi->available_compr_algs &&
 				   params->no_datainline) {
 				ret = tarerofs_write_uncompressed_file(inode, tar);
 			} else {
diff --git a/mkfs/main.c b/mkfs/main.c
index a948b2e1febd..326c332d37af 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -273,10 +273,12 @@ static void version(void)
 }
 
 static struct erofsmkfs_cfg {
+	struct z_erofs_paramset zcfgs[EROFS_MAX_COMPR_CFGS + 1];
 	/* < 0, xattr disabled and >= INT_MAX, always use inline xattrs */
 	long inlinexattr_tolerance;
 	bool inode_metazone;
 	u64 unix_timestamp;
+	unsigned int total_zcfgs;
 } mkfscfg = {
 	.inlinexattr_tolerance = 2,
 	.unix_timestamp = -1,
@@ -314,7 +316,7 @@ static enum {
 	EROFS_MKFS_SOURCE_REBUILD,
 } source_mode;
 
-static unsigned int rebuild_src_count, total_ccfgs;
+static unsigned int rebuild_src_count;
 static LIST_HEAD(rebuild_src_list);
 static u8 fixeduuid[16];
 static bool valid_fixeduuid;
@@ -837,66 +839,66 @@ static int mkfs_parse_oci_options(struct ocierofs_config *oci_cfg, char *options
 }
 #endif
 
-static int mkfs_parse_one_compress_alg(char *alg,
-				       struct erofs_compr_opts *copts)
+struct z_erofs_paramset erofs_mkfs_zparams[EROFS_MAX_COMPR_CFGS + 1];
+unsigned int erofs_mkfs_total_ccfgs;
+
+static int mkfs_parse_one_compress_alg(char *alg)
 {
+	struct z_erofs_paramset *zset = mkfscfg.zcfgs + mkfscfg.total_zcfgs;
 	char *p, *q, *opt, *endptr;
 
-	copts->level = -1;
-	copts->dict_size = 0;
+	if (zset >= erofs_mkfs_zparams + ARRAY_SIZE(erofs_mkfs_zparams)) {
+		erofs_err("too many algorithm types");
+		return -EINVAL;
+	}
+	zset->clevel = -1;
+	zset->dict_size = 0;
 
 	p = strchr(alg, ',');
-	if (p) {
-		copts->alg = strndup(alg, p - alg);
-
-		/* support old '-zlzma,9' form */
-		if (isdigit(*(p + 1))) {
-			copts->level = strtol(p + 1, &endptr, 10);
-			if (*endptr && *endptr != ',') {
-				erofs_err("invalid compression level %s",
-					  p + 1);
-				return -EINVAL;
-			}
-			return 0;
-		}
+	if (!p) {
+		zset->alg = alg;
 	} else {
-		copts->alg = strdup(alg);
-		return 0;
-	}
-
-	opt = p + 1;
-	while (opt) {
-		q = strchr(opt, ',');
-		if (q)
-			*q = '\0';
-
-		if ((p = strstr(opt, "level="))) {
-			p += strlen("level=");
-			copts->level = strtol(p, &endptr, 10);
-			if ((endptr == p) || (*endptr && *endptr != ',')) {
+		*p++ = '\0';
+		zset->alg = alg;
+		if (isdigit(*p)) {	/* support old '-zlzma,9' form */
+			zset->clevel = strtol(p, &endptr, 10);
+			if (*endptr && *endptr != ',') {
 				erofs_err("invalid compression level %s", p);
 				return -EINVAL;
 			}
-		} else if ((p = strstr(opt, "dictsize="))) {
-			p += strlen("dictsize=");
-			copts->dict_size = strtoul(p, &endptr, 10);
-			if (*endptr == 'k' || *endptr == 'K')
-				copts->dict_size <<= 10;
-			else if (*endptr == 'm' || *endptr == 'M')
-				copts->dict_size <<= 20;
-			else if ((endptr == p) || (*endptr && *endptr != ',')) {
-				erofs_err("invalid compression dictsize %s", p);
-				return -EINVAL;
-			}
 		} else {
-			erofs_err("invalid compression option %s", opt);
-			return -EINVAL;
+			for (opt = p; opt;) {
+				q = strchr(opt, ',');
+				if (q)
+					*q = '\0';
+
+				if ((p = strstr(opt, "level="))) {
+					p += strlen("level=");
+					zset->clevel = strtol(p, &endptr, 10);
+					if ((endptr == p) || (*endptr && *endptr != ',')) {
+						erofs_err("invalid compression level %s", p);
+						return -EINVAL;
+					}
+				} else if ((p = strstr(opt, "dictsize="))) {
+					p += strlen("dictsize=");
+					zset->dict_size = strtoul(p, &endptr, 10);
+					if (*endptr == 'k' || *endptr == 'K')
+						zset->dict_size <<= 10;
+					else if (*endptr == 'm' || *endptr == 'M')
+						zset->dict_size <<= 20;
+					else if ((endptr == p) || (*endptr && *endptr != ',')) {
+						erofs_err("invalid compression dictsize %s", p);
+						return -EINVAL;
+					}
+				} else {
+					erofs_err("invalid compression option %s", opt);
+					return -EINVAL;
+				}
+				opt = q ? q + 1 : NULL;
+			}
 		}
-
-		opt = q ? q + 1 : NULL;
 	}
-
-	return 0;
+	return mkfscfg.total_zcfgs++;
 }
 
 static int mkfs_parse_compress_algs(char *algs)
@@ -905,15 +907,9 @@ static int mkfs_parse_compress_algs(char *algs)
 	int ret;
 
 	for (s = strtok(algs, ":"); s; s = strtok(NULL, ":")) {
-		if (total_ccfgs >= EROFS_MAX_COMPR_CFGS - 1) {
-			erofs_err("too many algorithm types");
-			return -EINVAL;
-		}
-
-		ret = mkfs_parse_one_compress_alg(s, &cfg.c_compr_opts[total_ccfgs]);
-		if (ret)
+		ret = mkfs_parse_one_compress_alg(s);
+		if (ret < 0)
 			return ret;
-		++total_ccfgs;
 	}
 	return 0;
 }
@@ -1210,11 +1206,10 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params,
 				metabox_algorithmid =
 					strtoul(algid + 1, &endptr, 0);
 				if (*endptr != '\0') {
-					err = mkfs_parse_one_compress_alg(algid + 1,
-							&cfg.c_compr_opts[total_ccfgs]);
-					if (err)
+					err = mkfs_parse_one_compress_alg(algid + 1);
+					if (err < 0)
 						return err;
-					metabox_algorithmid = total_ccfgs++;
+					metabox_algorithmid = err;
 				}
 			}
 			pclustersize_metabox = atoi(optarg);
@@ -1856,6 +1851,7 @@ int main(int argc, char **argv)
 
 	if (mkfscfg.inlinexattr_tolerance < 0)
 		importer_params.no_xattrs = true;
+	importer_params.z_paramsets = mkfscfg.zcfgs;
 	importer_params.source = cfg.c_src_path;
 	importer_params.no_datainline = mkfs_no_datainline;
 	importer_params.dot_omitted = mkfs_dot_omitted;
@@ -1864,7 +1860,7 @@ int main(int argc, char **argv)
 		goto exit;
 
 	if (importer_params.dedupe == EROFS_DEDUPE_FORCE_ON) {
-		if (!cfg.c_compr_opts[0].alg) {
+		if (!g_sbi.available_compr_algs) {
 			erofs_err("Compression is not enabled.  Turn on chunk-based data deduplication instead.");
 			cfg.c_chunkbits = g_sbi.blkszbits;
 		} else {
-- 
2.43.5



More information about the Linux-erofs mailing list