From nobody Sun Feb 8 13:17:03 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0BF6715E97 for ; Fri, 14 Nov 2025 09:40:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763113240; cv=none; b=medWzI58gYe1C7m9X1cnR69k8IpFHtIStUjzu9HPFb+DtNs9DtaLR3SoI6ev9hhO1kijjJ+U6alwd1Q7FTgsMvROvozLD38MOGHt/90Soxqh20x/N84BOWO+0lG5XdSDV/F0wALvlUQylRr2/uS4Dnjug3txcoghQAfEFh7gPXE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763113240; c=relaxed/simple; bh=dkyHFTlz/Xge1ww08M54kuwaefRsC3Z1rNoDjY7sxRc=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=tzwK5CgypRvGMSde7r92tovgJ5gyF0A5lvcetbnWuINe2EPgoTrSDmhJY/MuxdaaiwANtK8myIzXcC3DoWdceZJiRlgYxEOlsi/wst5IL3qHFGA/qbOBbyGEiXEByI8x8ARvtKqJywJRyv1VZ0+MA/XVlIsM0I28IPoksAGlsyE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=fjx2YYET; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="fjx2YYET" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=nGgWr0kipJ5E0wWdigyiC5O5Pq+qTGGfj2uTaWcc3xM=; b=fjx2YYETns/TidnEM0QoG5X+VPwAiY8wMgMAOFbl5H3BqM3M/XHxE9oe8+MLfa27Cc1mCC7Tl 3YhsPu+gHUbPTBjPyDW1ISa3Y0XhQjebJKmheqUcGhRs7arYOFB79zF42hq7dZ77/jwesqGgypv 3L7Y0SIQScv9HdNVVcSWPOs= Received: from mail.maildlp.com (unknown [172.19.88.105]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4d7Bst30XTz12LFQ; Fri, 14 Nov 2025 17:38:58 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id C63B1140136; Fri, 14 Nov 2025 17:40:28 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 14 Nov 2025 17:40:28 +0800 From: Hongbo Li To: , CC: , , Subject: [PATCH] erofs-utils: introduce --ishare_key option for local dir to support shared page cache Date: Fri, 14 Nov 2025 09:28:45 +0000 Message-ID: <20251114092845.207368-1-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" For uncoming page cache sharing feature, we provide the --ishare_key option to calculate the sha256 on content for localdir. The usage is like: mkfs.erofs --ishare_key=3Dtrusted.erofs.fingerprint foo.img foo/ Signed-off-by: Hongbo Li --- include/erofs/config.h | 1 + include/erofs/internal.h | 3 +++ include/erofs/xattr.h | 3 ++- include/erofs_fs.h | 6 ++++-- lib/inode.c | 7 +++++++ lib/super.c | 2 ++ lib/xattr.c | 35 +++++++++++++++++++++++++++++++++-- mkfs/main.c | 26 +++++++++++++++++++++----- 8 files changed, 73 insertions(+), 10 deletions(-) diff --git a/include/erofs/config.h b/include/erofs/config.h index 525a8cd..dd4fa73 100644 --- a/include/erofs/config.h +++ b/include/erofs/config.h @@ -61,6 +61,7 @@ struct erofs_configure { u64 c_unix_timestamp; const char *mount_point; u32 c_root_xattr_isize; + const char *ishare_key; #ifdef EROFS_MT_ENABLED u64 c_mkfs_segment_size; u32 c_mt_workers; diff --git a/include/erofs/internal.h b/include/erofs/internal.h index 62594b8..482bee2 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -132,6 +132,8 @@ struct erofs_sb_info { u8 xattr_prefix_count; struct erofs_xattr_prefix_item *xattr_prefixes; =20 + u8 ishare_key_start; + struct erofs_vfile bdev; int devblksz; u64 devsz; @@ -186,6 +188,7 @@ EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE) EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES) EROFS_FEATURE_FUNCS(48bit, incompat, INCOMPAT_48BIT) EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX) +EROFS_FEATURE_FUNCS(ishare_key, incompat, INCOMPAT_ISHARE_KEY) EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX) diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h index ef80123..c1a4205 100644 --- a/include/erofs/xattr.h +++ b/include/erofs/xattr.h @@ -46,6 +46,7 @@ static inline unsigned int xattrblock_offset(struct erofs= _inode *vi, struct erofs_importer; =20 int erofs_xattr_init(struct erofs_sb_info *sbi); +int erofs_hook_ishare_xattrs(struct erofs_inode *inode, const char *ishare= _key); int erofs_scan_file_xattrs(struct erofs_inode *inode); int erofs_prepare_xattr_ibody(struct erofs_inode *inode, bool noroom); char *erofs_export_xattr_ibody(struct erofs_inode *inode); @@ -56,7 +57,7 @@ void erofs_xattr_cleanup_name_prefixes(void); int erofs_xattr_flush_name_prefixes(struct erofs_importer *im, bool plain); int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi); =20 -int erofs_setxattr(struct erofs_inode *inode, char *key, +int erofs_setxattr(struct erofs_inode *inode, const char *key, const void *value, size_t size); int erofs_set_opaque_xattr(struct erofs_inode *inode); void erofs_clear_opaque_xattr(struct erofs_inode *inode); diff --git a/include/erofs_fs.h b/include/erofs_fs.h index 887f37f..1869844 100644 --- a/include/erofs_fs.h +++ b/include/erofs_fs.h @@ -34,8 +34,9 @@ #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 #define EROFS_FEATURE_INCOMPAT_48BIT 0x00000080 #define EROFS_FEATURE_INCOMPAT_METABOX 0x00000100 +#define EROFS_FEATURE_INCOMPAT_ISHARE_KEY 0x00000200 #define EROFS_ALL_FEATURE_INCOMPAT \ - ((EROFS_FEATURE_INCOMPAT_METABOX << 1) - 1) + ((EROFS_FEATURE_INCOMPAT_ISHARE_KEY << 1) - 1) =20 #define EROFS_SB_EXTSLOT_SIZE 16 =20 @@ -82,7 +83,8 @@ struct erofs_super_block { __le32 xattr_prefix_start; /* start of long xattr prefixes */ __le64 packed_nid; /* nid of the special packed inode */ __u8 xattr_filter_reserved; /* reserved for xattr name filter */ - __u8 reserved[3]; + __u8 ishare_key_start; /* start of ishare key */ + __u8 reserved[2]; __le32 build_time; /* seconds added to epoch for mkfs time */ __le64 rootnid_8b; /* (48BIT on) nid of root directory */ __le64 reserved2; diff --git a/lib/inode.c b/lib/inode.c index d993c8f..92ecce7 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -1899,6 +1899,13 @@ static int erofs_mkfs_handle_inode(struct erofs_impo= rter *im, return ret; } =20 + if (!rebuild && cfg.ishare_key && + S_ISREG(inode->i_mode) && inode->i_size) { + ret =3D erofs_hook_ishare_xattrs(inode, cfg.ishare_key); + if (ret < 0) + return ret; + } + if (!rebuild && !params->no_xattrs) { ret =3D erofs_scan_file_xattrs(inode); if (ret < 0) diff --git a/lib/super.c b/lib/super.c index d626c7c..f9ce1b7 100644 --- a/lib/super.c +++ b/lib/super.c @@ -137,6 +137,7 @@ int erofs_read_superblock(struct erofs_sb_info *sbi) sbi->inos =3D le64_to_cpu(dsb->inos); sbi->checksum =3D le32_to_cpu(dsb->checksum); =20 + sbi->ishare_key_start =3D dsb->ishare_key_start; sbi->epoch =3D (s64)le64_to_cpu(dsb->epoch); sbi->fixed_nsec =3D le32_to_cpu(dsb->fixed_nsec); sbi->build_time =3D le32_to_cpu(dsb->build_time); @@ -196,6 +197,7 @@ int erofs_writesb(struct erofs_sb_info *sbi) .xattr_blkaddr =3D cpu_to_le32(sbi->xattr_blkaddr), .xattr_prefix_count =3D sbi->xattr_prefix_count, .xattr_prefix_start =3D cpu_to_le32(sbi->xattr_prefix_start), + .ishare_key_start =3D sbi->ishare_key_start, .feature_incompat =3D cpu_to_le32(sbi->feature_incompat), .feature_compat =3D cpu_to_le32(sbi->feature_compat & ~EROFS_FEATURE_COMPAT_SB_CHKSUM), diff --git a/lib/xattr.c b/lib/xattr.c index 8f0332b..1548f8e 100644 --- a/lib/xattr.c +++ b/lib/xattr.c @@ -21,6 +21,7 @@ #include "liberofs_metabox.h" #include "liberofs_xxhash.h" #include "liberofs_private.h" +#include "sha256.h" =20 #ifndef XATTR_SYSTEM_PREFIX #define XATTR_SYSTEM_PREFIX "system." @@ -475,7 +476,7 @@ err: return ret; } =20 -int erofs_setxattr(struct erofs_inode *inode, char *key, +int erofs_setxattr(struct erofs_inode *inode, const char *key, const void *value, size_t size) { struct erofs_sb_info *sbi =3D inode->sbi; @@ -573,6 +574,36 @@ static int erofs_droid_xattr_set_caps(struct erofs_ino= de *inode) } #endif =20 +int erofs_hook_ishare_xattrs(struct erofs_inode *inode, const char *ishare= _key) +{ + erofs_off_t isize =3D inode->i_size; + void *buffer; + u8 sha256[32]; + int ret, fd; + + buffer =3D malloc(isize); + if (!buffer) + return -ENOMEM; + + fd =3D open(inode->i_srcpath, O_RDONLY | O_BINARY); + if (fd < 0) { + ret =3D -errno; + goto free_err; + } + ret =3D erofs_io_pread(&(struct erofs_vfile){ .fd =3D fd }, buffer, isize= , 0); + if (ret !=3D isize) { + ret =3D -errno; + goto close_err; + } + erofs_sha256(buffer, isize, sha256); + ret =3D erofs_setxattr(inode, ishare_key, sha256, 32); +close_err: + close(fd); +free_err: + free(buffer); + return ret; +} + int erofs_scan_file_xattrs(struct erofs_inode *inode) { int ret; @@ -1653,7 +1684,7 @@ int erofs_xattr_insert_name_prefix(const char *prefix) ea_prefix_count++; init_list_head(&tnode->list); list_add_tail(&tnode->list, &ea_name_prefixes); - return 0; + return tnode->index; } =20 void erofs_xattr_cleanup_name_prefixes(void) diff --git a/mkfs/main.c b/mkfs/main.c index 76bf843..66507c3 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -102,6 +102,7 @@ static struct option long_options[] =3D { #endif {"zD", optional_argument, NULL, 536}, {"ZI", optional_argument, NULL, 537}, + {"ishare_key", required_argument, NULL, 538}, {0, 0, 0, 0}, }; =20 @@ -1261,7 +1262,7 @@ static int mkfs_parse_options_cfg(struct erofs_import= er_params *params, case 19: errno =3D 0; opt =3D erofs_xattr_insert_name_prefix(optarg); - if (opt) { + if (opt < 0) { erofs_err("failed to parse xattr name prefix: %s", erofs_strerror(opt)); return opt; @@ -1421,6 +1422,18 @@ static int mkfs_parse_options_cfg(struct erofs_impor= ter_params *params, else mkfscfg.inode_metazone =3D false; break; + case 538: + opt =3D erofs_xattr_insert_name_prefix(optarg); + if (opt < 0) { + erofs_err("failed to parse xattr name prefix: %s", + erofs_strerror(opt)); + return opt; + } + cfg.ishare_key =3D optarg; + g_sbi.ishare_key_start =3D opt; + cfg.c_extra_ea_name_prefixes =3D true; + erofs_sb_set_ishare_key(&g_sbi); + break; case 'V': version(); exit(0); @@ -1875,10 +1888,6 @@ int main(int argc, char **argv) goto exit; } =20 - if (cfg.c_extra_ea_name_prefixes) - erofs_xattr_flush_name_prefixes(&importer, - mkfs_plain_xattr_pfx); - root =3D erofs_new_inode(&g_sbi); if (IS_ERR(root)) { err =3D PTR_ERR(root); @@ -1965,6 +1974,13 @@ int main(int argc, char **argv) goto exit; } =20 + if (cfg.c_extra_ea_name_prefixes) { + err =3D erofs_xattr_flush_name_prefixes(&importer, + mkfs_plain_xattr_pfx); + if (err) + goto exit; + } + err =3D erofs_importer_flush_all(&importer); if (err) goto exit; --=20 2.22.0