[PATCH] erofs-utils: lib: fix `fragmentoff` larger than 4GiB

Gao Xiang hsiangkao at linux.alibaba.com
Sun Apr 6 13:48:41 AEST 2025


The `EROFS_INODE_COMPRESSED_FULL` datalayout should be used forcibly.

Fixes: cf04b8b78f09 ("erofs-utils: mkfs: implement extent-based deduplication")
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 include/erofs/fragments.h |  1 -
 lib/compress.c            | 13 +++++++++++--
 lib/fragments.c           | 25 ++++++-------------------
 3 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/include/erofs/fragments.h b/include/erofs/fragments.h
index ccfdd9b..a57b63c 100644
--- a/include/erofs/fragments.h
+++ b/include/erofs/fragments.h
@@ -17,7 +17,6 @@ extern const char *erofs_frags_packedname;
 
 int z_erofs_fragments_dedupe(struct erofs_inode *inode, int fd, u32 *tofcrc);
 
-void z_erofs_fragments_commit(struct erofs_inode *inode);
 int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc);
 int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
 			   unsigned int len, u32 tofcrc);
diff --git a/lib/compress.c b/lib/compress.c
index 9f71022..1742529 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -1004,7 +1004,13 @@ static void *z_erofs_write_indexes(struct z_erofs_compress_ictx *ctx)
 	struct z_erofs_extent_item *ei, *n;
 	void *metabuf;
 
-	if (!cfg.c_legacy_compress && !ctx->dedupe &&
+	/*
+	 * If the packed inode is larger than 4GiB, the full fragmentoff
+	 * will be recorded by switching to the noncompact layout anyway.
+	 */
+	if (inode->fragment_size && inode->fragmentoff >> 32) {
+		inode->datalayout = EROFS_INODE_COMPRESSED_FULL;
+	} else if (!cfg.c_legacy_compress && !ctx->dedupe &&
 	    inode->z_logical_clusterbits <= 14) {
 		if (inode->z_logical_clusterbits <= 12)
 			inode->z_advise |= Z_EROFS_ADVISE_COMPACTED_2B;
@@ -1165,7 +1171,10 @@ int erofs_commit_compressed_file(struct z_erofs_compress_ictx *ictx,
 	u8 *compressmeta;
 	int ret;
 
-	z_erofs_fragments_commit(inode);
+	if (inode->fragment_size) {
+		inode->z_advise |= Z_EROFS_ADVISE_FRAGMENT_PCLUSTER;
+		erofs_sb_set_fragments(inode->sbi);
+	}
 
 	/* fall back to no compression mode */
 	DBG_BUGON(pstart < (!!inode->idata_size) << bbits);
diff --git a/lib/fragments.c b/lib/fragments.c
index 41b9912..9dfe0e3 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -179,21 +179,6 @@ static int z_erofs_fragments_dedupe_insert(struct list_head *hash, void *data,
 	return 0;
 }
 
-void z_erofs_fragments_commit(struct erofs_inode *inode)
-{
-	if (!inode->fragment_size)
-		return;
-	/*
-	 * If the packed inode is larger than 4GiB, the full fragmentoff
-	 * will be recorded by switching to the noncompact layout anyway.
-	 */
-	if (inode->fragmentoff >> 32)
-		inode->datalayout = EROFS_INODE_COMPRESSED_FULL;
-
-	inode->z_advise |= Z_EROFS_ADVISE_FRAGMENT_PCLUSTER;
-	erofs_sb_set_fragments(inode->sbi);
-}
-
 int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc)
 {
 	struct erofs_packed_inode *epi = inode->sbi->packedinode;
@@ -250,8 +235,9 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc)
 		}
 	}
 
-	erofs_dbg("Recording %llu fragment data at %llu",
-		  inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL);
+	erofs_dbg("Recording %llu fragment data at %llu of %s",
+		  inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL,
+		  inode->i_srcpath);
 
 	if (memblock)
 		rc = z_erofs_fragments_dedupe_insert(
@@ -289,8 +275,9 @@ int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
 		return -EIO;
 	}
 
-	erofs_dbg("Recording %llu fragment data at %llu",
-		  inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL);
+	erofs_dbg("Recording %llu fragment data at %llu of %s",
+		  inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL,
+		  inode->i_srcpath);
 
 	ret = z_erofs_fragments_dedupe_insert(&epi->hash[FRAGMENT_HASH(tofcrc)],
 					      data, len, inode->fragmentoff);
-- 
2.43.5



More information about the Linux-erofs mailing list