[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