From 06875b3f2182eab24b81083dfde542f778b201cc Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 3 Jan 2025 10:40:11 +0800 Subject: erofs-utils: mkfs: support `-Efragdedupe=inode` 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 Link: https://lore.kernel.org/r/20250103024011.198163-1-hsiangkao@linux.alibaba.com --- include/erofs/config.h | 8 +++++++- lib/compress.c | 9 +++++++-- mkfs/main.c | 13 ++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/erofs/config.h b/include/erofs/config.h index 47e4d00..92c1467 100644 --- a/include/erofs/config.h +++ b/include/erofs/config.h @@ -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; diff --git a/lib/compress.c b/lib/compress.c index 0e8faad..20ab208 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -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); diff --git a/mkfs/main.c b/mkfs/main.c index 3f74fa2..0f6a32b 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -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; } -- cgit 1.2.3-korg