From: Gao Xiang <xiang@kernel.org>
To: linux-erofs@lists.ozlabs.org
Cc: Jonathan Calmels <jcalmels@nvidia.com>, Gao Xiang <xiang@kernel.org>
Subject: [RFC PATCH v2 2/2] erofs-utils: mkfs: support rebuild mode for compressed inodes
Date: Fri, 11 Sep 2026 20:21:10 +0800 [thread overview]
Message-ID: <20260911122110.189175-1-xiang@kernel.org> (raw)
In-Reply-To: <20260911120914.185958-2-xiang@kernel.org>
Add support for generating a meta-only multidev manifest image with
an overlayfs-like merged tree from multiple compressed EROFS images:
$ mkfs.erofs -zlz4 -Enoinline_data layerA.erofs layerA/
$ mkfs.erofs -zlz4 -Enoinline_data layerB.erofs layerB/
$ mkfs.erofs -zlz4 fsmeta.erofs layerA.erofs layerB.erofs
# mount -t erofs \
-odevice=layerA.erofs,device=layerB.erofs
fsmeta.erofs mnt/
Note that `-Efragments` is not yet supported: it needs further
userspace development.
Cc: Jonathan Calmels <jcalmels@nvidia.com>
Signed-off-by: Gao Xiang <xiang@kernel.org>
---
lib/compress.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/rebuild.c | 22 ++++++++++-
2 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/lib/compress.c b/lib/compress.c
index 3e8f9b6..fb0f92e 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -2435,3 +2435,103 @@ int z_erofs_compress_exit(struct erofs_sb_info *sbi)
free(sbi->zmgr);
return 0;
}
+
+int z_erofs_rebuild_load_metadata(struct erofs_sb_info *dst_sbi,
+ struct erofs_inode *inode)
+{
+ struct erofs_sb_info *sbi = inode->sbi;
+ struct erofs_map_blocks map = {
+ .buf = __EROFS_BUF_INITIALIZER,
+ .m_la = 0,
+ };
+ struct z_erofs_extent_item *ei, *n;
+ erofs_off_t pend = EROFS_NULL_ADDR;
+ bool consecutive = true;
+ LIST_HEAD(extents);
+ int err, device_id;
+
+ while (map.m_la < inode->i_size) {
+ struct erofs_map_dev mdev;
+ bool raw;
+
+ err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_FIEMAP);
+ if (err)
+ goto err_out;
+
+ mdev = (struct erofs_map_dev) {
+ .m_deviceid = map.m_deviceid,
+ .m_pa = map.m_pa,
+ };
+ err = erofs_map_dev(sbi, &mdev);
+ if (err)
+ goto err_out;
+
+ raw = (map.m_algorithmformat >= Z_EROFS_COMPRESSION_MAX);
+
+ ei = malloc(sizeof(*ei));
+ if (!ei) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ init_list_head(&ei->list);
+ ei->e = (struct z_erofs_inmem_extent) {
+ .length = map.m_llen,
+ .plen = map.m_plen,
+ .pstart = mdev.m_pa,
+ .device_id = inode->dev, /* FIXME! */
+ .partial = map.m_flags & EROFS_MAP_PARTIAL_REF,
+ .raw = raw,
+ .inlined = map.m_flags & EROFS_MAP_META,
+ };
+ if (!raw) {
+ ei->e.algofmt = map.m_algorithmformat;
+ if (!(dst_sbi->available_compr_algs & (1 << ei->e.algofmt))) {
+ err = -EOPNOTSUPP;
+ goto err_free_ei;
+ }
+ }
+
+ if (map.m_flags & __EROFS_MAP_FRAGMENT) {
+ err = -EOPNOTSUPP;
+ goto err_free_ei;
+// inode->fragment_size = map.m_llen;
+// DBG_BUGON(inode->fragmentoff != map.m_pa);
+ } else if (map.m_flags & EROFS_MAP_META) {
+ DBG_BUGON(inode->idata_size != map.m_plen);
+ inode->idata = malloc(inode->idata_size);
+ if (!inode->idata) {
+ err = -ENOMEM;
+ goto err_free_ei;
+ }
+ err = erofs_dev_read(sbi, 0, inode->idata, mdev.m_pa,
+ inode->idata_size);
+ if (err)
+ goto err_free_ei;
+ DBG_BUGON(map.m_la + map.m_llen != inode->i_size);
+ } else {
+ if (pend != EROFS_NULL_ADDR && (pend != ei->e.pstart ||
+ device_id != ei->e.device_id))
+ consecutive = false;
+ pend = ei->e.pstart + ei->e.plen;
+ device_id = ei->e.device_id;
+ }
+ list_add_tail(&ei->list, &extents);
+ map.m_la += map.m_llen;
+ }
+
+ inode->z_lclusterbits = sbi->blkszbits;
+ err = z_erofs_prepare_layout(inode, &extents, consecutive, false);
+ if (err)
+ goto err_out;
+ return 0;
+
+err_free_ei:
+ free(ei);
+err_out:
+ list_for_each_entry_safe(ei, n, &extents, list) {
+ list_del(&ei->list);
+ free(ei);
+ }
+ return err;
+}
diff --git a/lib/rebuild.c b/lib/rebuild.c
index 38ced3c..b431bd4 100644
--- a/lib/rebuild.c
+++ b/lib/rebuild.c
@@ -152,7 +152,7 @@ struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
return d;
}
-static int erofs_rebuild_write_blob_index(struct erofs_sb_info *dst_sb,
+static int erofs_rebuild_load_chunk_index(struct erofs_sb_info *dst_sb,
struct erofs_inode *inode)
{
int ret;
@@ -222,6 +222,17 @@ err:
return ret;
}
+static int erofs_rebuild_write_blob_index(struct erofs_sb_info *dst_sb,
+ struct erofs_inode *inode)
+{
+ int z_erofs_rebuild_load_metadata(struct erofs_sb_info *dst_sb,
+ struct erofs_inode *inode);
+
+ if (is_inode_layout_compression(inode))
+ return z_erofs_rebuild_load_metadata(dst_sb, inode);
+ return erofs_rebuild_load_chunk_index(dst_sb, inode);
+}
+
static int erofs_rebuild_write_full_data(struct erofs_inode *inode)
{
struct erofs_sb_info *src_sbi = inode->sbi;
@@ -514,6 +525,15 @@ int erofs_rebuild_load_tree(struct erofs_inode *root, struct erofs_sb_info *sbi,
return ret;
}
+ if (erofs_sb_has_dedupe(sbi))
+ erofs_sb_set_dedupe(root->sbi);
+ if (erofs_sb_has_big_pcluster(sbi) &&
+ !erofs_sb_has_big_pcluster(root->sbi)) {
+ erofs_err("failed to load tree from image %d with big pclusters",
+ sbi->dev);
+ return -EOPNOTSUPP;
+ }
+
inode.nid = sbi->root_nid;
inode.sbi = sbi;
ret = erofs_read_inode_from_disk(&inode);
--
2.47.3
prev parent reply other threads:[~2026-09-11 12:22 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 12:09 [RFC PATCH 1/2] erofs-utils: record algorithm id in in-memory compression extents Gao Xiang
2026-09-11 12:09 ` [RFC PATCH 2/2] erofs-utils: mkfs: support rebuild mode for compressed inodes Gao Xiang
2026-09-11 12:21 ` Gao Xiang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260911122110.189175-1-xiang@kernel.org \
--to=xiang@kernel.org \
--cc=jcalmels@nvidia.com \
--cc=linux-erofs@lists.ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.