[PATCH] erofs-utils: disallow new algorithms on incremental builds
Gao Xiang
xiang at kernel.org
Tue Aug 6 10:08:59 AEST 2024
From: Gao Xiang <hsiangkao at linux.alibaba.com>
On-disk compression configurations are not rewritten on incremental
builds, therefore there is no way to add new algorithms in this mode.
Clean builds should be used instead.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
dump/main.c | 2 +-
include/erofs/internal.h | 12 +++++++++---
lib/compress.c | 33 ++++++++++++++++++++++++++-------
lib/compressor_lz4.c | 3 ++-
lib/compressor_lz4hc.c | 3 ++-
lib/decompress.c | 34 +++++++++++++++++++++++++++++-----
lib/super.c | 2 +-
7 files changed, 70 insertions(+), 19 deletions(-)
diff --git a/dump/main.c b/dump/main.c
index 06ca4d3..372162e 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -651,7 +651,7 @@ static void erofsdump_show_superblock(void)
g_sbi.available_compr_algs);
} else {
fprintf(stdout, "Filesystem lz4_max_distance: %u\n",
- g_sbi.lz4_max_distance | 0U);
+ g_sbi.lz4.max_distance | 0U);
}
fprintf(stdout, "Filesystem sb_size: %u\n",
g_sbi.sb_size | 0U);
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 708e51e..2edc1b4 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -66,6 +66,13 @@ struct erofs_device_info {
u32 mapped_blkaddr;
};
+/* all filesystem-wide lz4 configurations */
+struct erofs_sb_lz4_info {
+ u16 max_distance;
+ /* maximum possible blocks for pclusters in the filesystem */
+ u16 max_pclusterblks;
+};
+
struct erofs_xattr_prefix_item {
struct erofs_xattr_long_prefix *prefix;
u8 infix_len;
@@ -75,6 +82,7 @@ struct erofs_xattr_prefix_item {
struct erofs_mkfs_dfops;
struct erofs_sb_info {
+ struct erofs_sb_lz4_info lz4;
struct erofs_device_info *devs;
char *devname;
@@ -102,10 +110,8 @@ struct erofs_sb_info {
u8 uuid[16];
char volume_name[16];
- u16 available_compr_algs;
- u16 lz4_max_distance;
-
u32 checksum;
+ u16 available_compr_algs;
u16 extra_devices;
union {
u16 devt_slotoff; /* used for mkfs */
diff --git a/lib/compress.c b/lib/compress.c
index 794f714..cea96f4 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -1591,7 +1591,7 @@ static int z_erofs_build_compr_cfgs(struct erofs_sb_info *sbi,
.size = cpu_to_le16(sizeof(struct z_erofs_lz4_cfgs)),
.lz4 = {
.max_distance =
- cpu_to_le16(sbi->lz4_max_distance),
+ cpu_to_le16(sbi->lz4.max_distance),
.max_pclusterblks =
cfg.c_mkfs_pclustersize_max >> sbi->blkszbits,
}
@@ -1686,6 +1686,7 @@ int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *s
{
int i, ret, id;
u32 max_dict_size[Z_EROFS_COMPRESSION_MAX] = {};
+ u32 available_compr_algs = 0;
for (i = 0; cfg.c_compr_opts[i].alg; ++i) {
struct erofs_compress *c = &erofs_ccfg[i].handle;
@@ -1699,7 +1700,7 @@ int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *s
id = z_erofs_get_compress_algorithm_id(c);
erofs_ccfg[i].algorithmtype = id;
erofs_ccfg[i].enable = true;
- sbi->available_compr_algs |= 1 << erofs_ccfg[i].algorithmtype;
+ available_compr_algs |= 1 << erofs_ccfg[i].algorithmtype;
if (erofs_ccfg[i].algorithmtype != Z_EROFS_COMPRESSION_LZ4)
erofs_sb_set_compr_cfgs(sbi);
if (c->dict_size > max_dict_size[id])
@@ -1710,14 +1711,32 @@ int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *s
* if primary algorithm is empty (e.g. compression off),
* clear 0PADDING feature for old kernel compatibility.
*/
- if (!cfg.c_compr_opts[0].alg ||
- (cfg.c_legacy_compress &&
- !strncmp(cfg.c_compr_opts[0].alg, "lz4", 3)))
+ if (!available_compr_algs ||
+ (cfg.c_legacy_compress && available_compr_algs == 1))
erofs_sb_clear_lz4_0padding(sbi);
- if (!cfg.c_compr_opts[0].alg)
+ if (!available_compr_algs)
return 0;
+ if (!sb_bh) {
+ u32 dalg = available_compr_algs & (~sbi->available_compr_algs);
+
+ if (dalg) {
+ erofs_err("unavailable algorithms 0x%x on incremental builds",
+ dalg);
+ return -EOPNOTSUPP;
+ }
+ if (available_compr_algs & (1 << Z_EROFS_COMPRESSION_LZ4) &&
+ sbi->lz4.max_pclusterblks << sbi->blkszbits <
+ cfg.c_mkfs_pclustersize_max) {
+ erofs_err("pclustersize %u is too large on incremental builds",
+ cfg.c_mkfs_pclustersize_max);
+ return -EOPNOTSUPP;
+ }
+ } else {
+ sbi->available_compr_algs = available_compr_algs;
+ }
+
/*
* if big pcluster is enabled, an extra CBLKCNT lcluster index needs
* to be loaded in order to get those compressed block counts.
@@ -1736,7 +1755,7 @@ int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *s
return -EINVAL;
}
- if (erofs_sb_has_compr_cfgs(sbi)) {
+ if (sb_bh && erofs_sb_has_compr_cfgs(sbi)) {
ret = z_erofs_build_compr_cfgs(sbi, sb_bh, max_dict_size);
if (ret)
return ret;
diff --git a/lib/compressor_lz4.c b/lib/compressor_lz4.c
index 5ecfd3e..f3d88b0 100644
--- a/lib/compressor_lz4.c
+++ b/lib/compressor_lz4.c
@@ -32,7 +32,8 @@ static int compressor_lz4_exit(struct erofs_compress *c)
static int compressor_lz4_init(struct erofs_compress *c)
{
- c->sbi->lz4_max_distance = LZ4_DISTANCE_MAX;
+ c->sbi->lz4.max_distance = max_t(u16, c->sbi->lz4.max_distance,
+ LZ4_DISTANCE_MAX);
return 0;
}
diff --git a/lib/compressor_lz4hc.c b/lib/compressor_lz4hc.c
index f354b84..1e1ccc7 100644
--- a/lib/compressor_lz4hc.c
+++ b/lib/compressor_lz4hc.c
@@ -43,7 +43,8 @@ static int compressor_lz4hc_init(struct erofs_compress *c)
if (!c->private_data)
return -ENOMEM;
- c->sbi->lz4_max_distance = LZ4_DISTANCE_MAX;
+ c->sbi->lz4.max_distance = max_t(u16, c->sbi->lz4.max_distance,
+ LZ4_DISTANCE_MAX);
return 0;
}
diff --git a/lib/decompress.c b/lib/decompress.c
index 1e22f9f..1b44a18 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -545,6 +545,30 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq)
return -EOPNOTSUPP;
}
+static int z_erofs_load_lz4_config(struct erofs_sb_info *sbi,
+ struct erofs_super_block *dsb, void *data, int size)
+{
+ struct z_erofs_lz4_cfgs *lz4 = data;
+ u16 distance;
+
+ if (lz4) {
+ if (size < sizeof(struct z_erofs_lz4_cfgs)) {
+ erofs_err("invalid lz4 cfgs, size=%u", size);
+ return -EINVAL;
+ }
+ distance = le16_to_cpu(lz4->max_distance);
+
+ sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks);
+ if (!sbi->lz4.max_pclusterblks)
+ sbi->lz4.max_pclusterblks = 1; /* reserved case */
+ } else {
+ distance = le16_to_cpu(dsb->u1.lz4_max_distance);
+ sbi->lz4.max_pclusterblks = 1;
+ }
+ sbi->lz4.max_distance = distance;
+ return 0;
+}
+
int z_erofs_parse_cfgs(struct erofs_sb_info *sbi, struct erofs_super_block *dsb)
{
unsigned int algs, alg;
@@ -553,8 +577,7 @@ int z_erofs_parse_cfgs(struct erofs_sb_info *sbi, struct erofs_super_block *dsb)
if (!erofs_sb_has_compr_cfgs(sbi)) {
sbi->available_compr_algs = 1 << Z_EROFS_COMPRESSION_LZ4;
- sbi->lz4_max_distance = le16_to_cpu(dsb->u1.lz4_max_distance);
- return 0;
+ return z_erofs_load_lz4_config(sbi, dsb, NULL, 0);
}
sbi->available_compr_algs = le16_to_cpu(dsb->u1.available_compr_algs);
@@ -578,10 +601,11 @@ int z_erofs_parse_cfgs(struct erofs_sb_info *sbi, struct erofs_super_block *dsb)
break;
}
- if (alg == Z_EROFS_COMPRESSION_DEFLATE)
+ ret = 0;
+ if (alg == Z_EROFS_COMPRESSION_LZ4)
+ ret = z_erofs_load_lz4_config(sbi, dsb, data, size);
+ else if (alg == Z_EROFS_COMPRESSION_DEFLATE)
ret = z_erofs_load_deflate_config(sbi, dsb, data, size);
- else
- ret = 0;
free(data);
if (ret)
break;
diff --git a/lib/super.c b/lib/super.c
index 45233c4..32e10cd 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -188,7 +188,7 @@ int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh,
if (erofs_sb_has_compr_cfgs(sbi))
sb.u1.available_compr_algs = cpu_to_le16(sbi->available_compr_algs);
else
- sb.u1.lz4_max_distance = cpu_to_le16(sbi->lz4_max_distance);
+ sb.u1.lz4_max_distance = cpu_to_le16(sbi->lz4.max_distance);
buf = calloc(sb_blksize, 1);
if (!buf) {
--
2.30.2
More information about the Linux-erofs
mailing list