erofs-utils: mkfs: support `-Efragdedupe=inode`
authorGao Xiang <hsiangkao@linux.alibaba.com>
Fri, 3 Jan 2025 02:40:11 +0000 (10:40 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Fri, 3 Jan 2025 14:06:04 +0000 (22:06 +0800)
If the entire inode can be deduplicated against an existing fragment,
simply reuse it.

Multi-threading can still be applied for `-Efragdedupe=inode` with
the current codebase:

Fedora Linux 39 (Workstation Edition) LiveCD results:
 -zlzma,level=6,dictsize=131072 -C65536 -Eall-fragments

   `-E^fragdedupe`         2,003,587,072 bytes (1911 MiB)
   `-Efragdedupe=inode`    1,970,577,408 bytes (1880 MiB)

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20250103024011.198163-1-hsiangkao@linux.alibaba.com
include/erofs/config.h
lib/compress.c
mkfs/main.c

index 47e4d0005ed55296c3e83e57017ab715d6dc76c3..92c1467f96a507ff36d8e14b1ff622363518ea77 100644 (file)
@@ -33,6 +33,12 @@ enum {
        TIMESTAMP_CLAMPING,
 };
 
+enum {
+       FRAGDEDUPE_FULL,
+       FRAGDEDUPE_INODE,
+       FRAGDEDUPE_OFF,
+};
+
 #define EROFS_MAX_COMPR_CFGS           64
 
 struct erofs_compr_opts {
@@ -53,7 +59,7 @@ struct erofs_configure {
        bool c_fragments;
        bool c_all_fragments;
        bool c_dedupe;
-       bool c_nofragdedupe;
+       char c_fragdedupe;
        bool c_ignore_mtime;
        bool c_showprogress;
        bool c_extra_ea_name_prefixes;
index 0e8faada85a57f84f3ff4b18681b774ab9073259..20ab20847ca0b869881798a819f718f28ff3d63a 100644 (file)
@@ -1527,12 +1527,17 @@ void *erofs_begin_compressed_file(struct erofs_inode *inode, int fd, u64 fpos)
         * parts into the packed inode.
         */
        if (cfg.c_fragments && !erofs_is_packed_inode(inode) &&
-           !cfg.c_nofragdedupe) {
+           cfg.c_fragdedupe != FRAGDEDUPE_OFF) {
                ret = z_erofs_fragments_dedupe(inode, fd, &ictx->tof_chksum);
                if (ret < 0)
                        goto err_free_ictx;
-       }
 
+               if (cfg.c_fragdedupe == FRAGDEDUPE_INODE &&
+                   inode->fragment_size < inode->i_size) {
+                       erofs_dbg("Discard the sub-inode tail fragment @ nid %llu", inode->nid);
+                       inode->fragment_size = 0;
+               }
+       }
        ictx->inode = inode;
        ictx->fpos = fpos;
        init_list_head(&ictx->extents);
index 3f74fa2fc272febacefa9e116a0f576e25813859..0f6a32bc07ddc7aff6d8b65d51086e5908da7ddd 100644 (file)
@@ -306,9 +306,16 @@ static int erofs_mkfs_feat_set_dedupe(bool en, const char *val,
 static int erofs_mkfs_feat_set_fragdedupe(bool en, const char *val,
                                          unsigned int vallen)
 {
-       if (vallen)
-               return -EINVAL;
-       cfg.c_nofragdedupe = !en;
+       if (!en) {
+               if (vallen)
+                       return -EINVAL;
+               cfg.c_fragdedupe = FRAGDEDUPE_OFF;
+       } else if (vallen == sizeof("inode") - 1 &&
+                  !memcmp(val, "inode", vallen)) {
+               cfg.c_fragdedupe = FRAGDEDUPE_INODE;
+       } else {
+               cfg.c_fragdedupe = FRAGDEDUPE_FULL;
+       }
        return 0;
 }