erofs-utils: lib: fix `fragmentoff` larger than 4GiB
authorGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 6 Apr 2025 03:48:41 +0000 (11:48 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 6 Apr 2025 04:23:20 +0000 (12:23 +0800)
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@linux.alibaba.com>
Link: https://lore.kernel.org/r/20250406034841.3931822-1-hsiangkao@linux.alibaba.com
include/erofs/fragments.h
lib/compress.c
lib/fragments.c

index ccfdd9bc7594c1add75d5546f79d975a87580ade..a57b63caac8c77ccdbffed61cd10e73afa502d32 100644 (file)
@@ -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);
index 9f71022bcc2e4122111f0347603cf2722c527d33..17425299928c1c83e08b1b287bba13f2efb76d12 100644 (file)
@@ -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);
index 41b9912549c1f65597aee1a3a9b8f6a85a73c0ac..9dfe0e3598751e53b0aa651d06a405c0e80e6671 100644 (file)
@@ -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);