From nobody Mon Feb 9 01:31:15 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (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 94F7D25A659 for ; Tue, 21 Oct 2025 10:59:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044379; cv=none; b=V3kq2ThJjRPDm0npX4vH9l0TpxR+TcHr/6cJLMkr/TdPe6m1btOEbqR/osSGnF9mXFj2OnwSpSQdxrlb2seHPnw/Wv2jNEAJKbnKZIT89q+7SnAP5j2x1gB9K3cWgn50Ayo10dcNC7ubdxAdeJe1xoC8plHjrUZVtV4no4PKG6Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044379; c=relaxed/simple; bh=hxYo7Q6qOMeggBzfEhc8RHPansfQK2QUiJ09j6RQiIM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=k7kugSCgF4gkPQD0/QFMFfnujQcFhJ4dld+MJsun/NPvv4Z9VthwPsi/kUAUABGYUjjQ79c+HB4GF97Bvt4BqQWNWjiDksBsgcEKtXbx+YmXStPpYqfhi8HnpjhueS+wfR1huGvzEnhCsegU56+YmZfSgjhXrJso0kJGTomWfZ0= 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=47ADE1VB; arc=none smtp.client-ip=113.46.200.219 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="47ADE1VB" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=ck6npKF+h2adwSuQA2R5HJLsYhHiaeynnKxMeeII07Y=; b=47ADE1VBKayVDXlfGWjppD5Q3HsUlPmyl2823Ec93LKTFo+BZ4ayGE/cSJOLkotjTQQVYv5Mm 3G8CxfzCOaXzx8kTnwLFOSgtNsTefOeldOf1AVtinYJGWpvne3rM8/8/s/0zoSqnCoanN0HWkQt 6kMae5IM70a9CMJGRNW5XXM= Received: from mail.maildlp.com (unknown [172.19.163.252]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4crTnS6kg7z1prQN; Tue, 21 Oct 2025 18:59:08 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 5038C180B6B; Tue, 21 Oct 2025 18:59:33 +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; Tue, 21 Oct 2025 18:59:32 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 1/7] erofs: move `struct erofs_anon_fs_type` to super.c Date: Tue, 21 Oct 2025 10:48:09 +0000 Message-ID: <20251021104815.70662-2-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Move the `struct erofs_anon_fs_type` to the super.c and expose it in preparation for the upcoming page cache share feature. Signed-off-by: Hongzhen Luo [hongbo: forward port] Signed-off-by: Hongbo Li --- fs/erofs/fscache.c | 13 ------------- fs/erofs/internal.h | 2 ++ fs/erofs/super.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 362acf828279..2d1683479fc0 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -3,7 +3,6 @@ * Copyright (C) 2022, Alibaba Cloud * Copyright (C) 2022, Bytedance Inc. All rights reserved. */ -#include #include #include "internal.h" =20 @@ -13,18 +12,6 @@ static LIST_HEAD(erofs_domain_list); static LIST_HEAD(erofs_domain_cookies_list); static struct vfsmount *erofs_pseudo_mnt; =20 -static int erofs_anon_init_fs_context(struct fs_context *fc) -{ - return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; -} - -static struct file_system_type erofs_anon_fs_type =3D { - .owner =3D THIS_MODULE, - .name =3D "pseudo_erofs", - .init_fs_context =3D erofs_anon_init_fs_context, - .kill_sb =3D kill_anon_super, -}; - struct erofs_fscache_io { struct netfs_cache_resources cres; struct iov_iter iter; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index f7f622836198..eac067446140 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -409,6 +409,8 @@ extern const struct file_operations erofs_dir_fops; =20 extern const struct iomap_ops z_erofs_iomap_report_ops; =20 +extern struct file_system_type erofs_anon_fs_type; + /* flags for erofs_fscache_register_cookie() */ #define EROFS_REG_COOKIE_SHARE 0x0001 #define EROFS_REG_COOKIE_NEED_NOEXIST 0x0002 diff --git a/fs/erofs/super.c b/fs/erofs/super.c index f3f8d8c066e4..f9d8f978bf81 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "xattr.h" =20 #define CREATE_TRACE_POINTS @@ -920,6 +921,18 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 +static int erofs_anon_init_fs_context(struct fs_context *fc) +{ + return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; +} + +struct file_system_type erofs_anon_fs_type =3D { + .owner =3D THIS_MODULE, + .name =3D "pseudo_erofs", + .init_fs_context =3D erofs_anon_init_fs_context, + .kill_sb =3D kill_anon_super, +}; + static int __init erofs_module_init(void) { int err; --=20 2.22.0 From nobody Mon Feb 9 01:31:15 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 A63BE32D425 for ; Tue, 21 Oct 2025 10:59:41 +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=1761044384; cv=none; b=TMPGhO2njoGc7IIHy0LIbIaWUzCWYIEaHK2cqJi7efyjY86rIuEx5D3p9uy9YRTCyxvJnmxs7zF9cKKu2yaNbgvMeg1gbgblQUxX2YyZxVdH5W6Yw6RzlSS3dcwi1b0qWP5+i54Tz8d2izGrigIU6/PxqL7vKzkNe9DQTmCFgz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044384; c=relaxed/simple; bh=6ltMIJOMRUnLqgkD+4BfTH80suRtsHd4Crs9+gCuy8g=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=f7qbrPbJs8wTBWKsdL9zJoyZ0t6X8Km8Vp+WgNeM6R6AD6vmfCdP8p+AOWLgYJe96vCvzlIXBqodsLlT4wZqy9bAfqS0Y7UqlbGM2Q+Mdt9sxzPAy9VdG7YPdgDz4VbBZcLND01SHGhmF4K4QfQADD7Eh0glDwgsQf9NmNa+JPI= 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=c3RAl8th; 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="c3RAl8th" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=p0DA4pa48eyEbYiRWGDSuEKqCbnb228fv9F0XYlpl/o=; b=c3RAl8th+kW+FpwaciR5if0MoXyaCirYght7JKovA7Tel97DCAC/JPwtzajnvz8jLza93+C2w Z9IvQV++/TaxRv6obU7r5TNVONNy78bN3lBaVdgIceMnWMHRNMPm5JQFDrU4MTi6p+lHp63Lu6k lItn9MUpfLaOD987I1W3QsQ= Received: from mail.maildlp.com (unknown [172.19.88.105]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4crTn76SR9z12LDD; Tue, 21 Oct 2025 18:58:51 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 9AD0B140155; Tue, 21 Oct 2025 18:59:33 +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; Tue, 21 Oct 2025 18:59:33 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 2/7] erofs: support user-defined fingerprint name Date: Tue, 21 Oct 2025 10:48:10 +0000 Message-ID: <20251021104815.70662-3-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo When creating the EROFS image, users can specify the fingerprint name. This is to prepare for the upcoming inode page cache share. Signed-off-by: Hongzhen Luo [hongbo: forward port, minor fixes and cleanup] Signed-off-by: Hongbo Li --- fs/erofs/Kconfig | 10 ++++++++++ fs/erofs/erofs_fs.h | 6 ++++-- fs/erofs/internal.h | 6 ++++++ fs/erofs/super.c | 3 ++- fs/erofs/xattr.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/xattr.h | 6 ++++++ 6 files changed, 75 insertions(+), 3 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index d81f3318417d..ef30cb452244 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -194,3 +194,13 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI at higher priority. =20 If unsure, say N. + +config EROFS_FS_INODE_SHARE + bool "EROFS inode page cache share support" + depends on EROFS_FS && EROFS_FS_XATTR + default n + help + This permits EROFS to share page cache for files with same + fingerprints. + + If unsure, say N. \ No newline at end of file diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 3d5738f80072..f6ea8c35db45 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -35,8 +35,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 @@ -86,7 +87,8 @@ struct erofs_super_block { __u8 reserved[3]; __le32 build_time; /* seconds added to epoch for mkfs time */ __le64 rootnid_8b; /* (48BIT on) nid of root directory */ - __le64 reserved2; + __le32 ishare_key_start; /* start of ishare key */ + __le32 reserved2; __le64 metabox_nid; /* (METABOX on) nid of the metabox inode */ __le64 reserved3; /* [align to extslot 1] */ }; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index eac067446140..245b9e3897bc 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -167,6 +167,11 @@ struct erofs_sb_info { struct erofs_domain *domain; char *fsid; char *domain_id; + + /* inode page cache share support */ + u32 ishare_key_start; + int ishare_key_idx; + char *ishare_key; }; =20 #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -232,6 +237,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(shared_ea_in_metabox, compat, COMPAT_SHARED_EA_IN_META= BOX) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index f9d8f978bf81..283449024996 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -339,7 +339,7 @@ static int erofs_read_superblock(struct super_block *sb) return -EFSCORRUPTED; /* self-loop detection */ } sbi->inos =3D le64_to_cpu(dsb->inos); - + sbi->ishare_key_start =3D le32_to_cpu(dsb->ishare_key_start); sbi->epoch =3D (s64)le64_to_cpu(dsb->epoch); sbi->fixed_nsec =3D le32_to_cpu(dsb->fixed_nsec); super_set_uuid(sb, (void *)dsb->uuid, sizeof(dsb->uuid)); @@ -738,6 +738,7 @@ static int erofs_fc_fill_super(struct super_block *sb, = struct fs_context *fc) if (err) return err; =20 + erofs_xattr_set_ishare_key(sb); erofs_set_sysfs_name(sb); err =3D erofs_register_sysfs(sb); if (err) diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 396536d9a862..6610c007ee4c 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -564,3 +564,50 @@ struct posix_acl *erofs_get_acl(struct inode *inode, i= nt type, bool rcu) return acl; } #endif + +#ifdef CONFIG_EROFS_FS_INODE_SHARE +void erofs_xattr_set_ishare_key(struct super_block *sb) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; + struct xattr_handler const *handler; + erofs_off_t pos; + char *key; + int len, i; + void *ptr; + + if (!erofs_sb_has_fragments(sbi) || !erofs_sb_has_ishare_key(sbi) || + !sbi->packed_inode) + return; + + buf.mapping =3D sbi->packed_inode->i_mapping; + pos =3D sbi->ishare_key_start << 2; + (void)erofs_init_metabuf(&buf, sb, false); + ptr =3D erofs_read_metadata(sb, &buf, &pos, &len); + + if (IS_ERR(ptr)) + goto out; + + for (i =3D 0; ARRAY_SIZE(erofs_xattr_handlers) - 1; i++) { + handler =3D erofs_xattr_handlers[i]; + if (!handler) + break; + if (!memcmp(handler->prefix, ptr, strlen(handler->prefix))) + break; + } + + if (!handler) + goto out; + + len -=3D strlen(handler->prefix); + key =3D kzalloc(len + 1, GFP_KERNEL); + if (!key) + goto out; + + memcpy(key, ptr + strlen(handler->prefix), len); + sbi->ishare_key =3D key; + sbi->ishare_key_idx =3D handler->flags; +out: + erofs_put_metabuf(&buf); +} +#endif diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 6317caa8413e..99c4674cfd51 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -67,4 +67,10 @@ struct posix_acl *erofs_get_acl(struct inode *inode, int= type, bool rcu); #define erofs_get_acl (NULL) #endif =20 +#ifdef CONFIG_EROFS_FS_INODE_SHARE +void erofs_xattr_set_ishare_key(struct super_block *sb); +#else +static inline void erofs_xattr_set_ishare_key(struct super_block *sb) {} +#endif + #endif --=20 2.22.0 From nobody Mon Feb 9 01:31:15 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 A644032D426 for ; Tue, 21 Oct 2025 10:59:41 +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=1761044383; cv=none; b=ffafh6CKKQ5IXc6Mbr3g7gHwPs66fQB5izu09yXh+PRSNlMFqtJ5K6DxlksukOX7K9qnSDRMyvBdIIFpPIbQed9gpZAb68MycPdZXb50QO9g8XA5u+KKgoGvZPvqnhYYJe/bjEusHnHYwTzOnSngzAY3Sak9hO8QJJWTxD19prA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044383; c=relaxed/simple; bh=QXtAtWPpAQQCg/4es6RksdN5P67u6Ia1as9Sf1erACU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qL2G+bWARu04VmG3OnvEv68EgTy5mbbCzX6OhFCXHrB2sA3BT+R2uBajnkBOXLAabDqfxytVS1KpkP/KESXH9azSTa8X69I889OzwU5HONaVyIxFqGOwuLvV/mPONxkTZBeYpy+X/G8Ct4bbQ3TRLzXP+wfizFJoaPcfKg+ilJ8= 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=uRfDiAd4; 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="uRfDiAd4" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=krQn0u8nFubnBr1gbykuo1KbTyd2uBSqO/9+KeEmkgM=; b=uRfDiAd4kQoGQf21Iyo4WnxrpzV7P9onlEb8FsKEDUZJfzSNb9vCTzMSDLaAf7td3pPENNnzJ QKJETRrg//pyl4QIC3Y3I139WiLOkxHNLQ8mfh5pDkOqxlBmTVpRa8NKryQIIaAC024Jx8QlgDg J39t3i4wet2ePTBOMBVhTTE= Received: from mail.maildlp.com (unknown [172.19.163.174]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4crTn81rtgz12LDD; Tue, 21 Oct 2025 18:58:52 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id EDD23140156; Tue, 21 Oct 2025 18:59:33 +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; Tue, 21 Oct 2025 18:59:33 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 3/7] erofs: support domain-specific page cache share Date: Tue, 21 Oct 2025 10:48:11 +0000 Message-ID: <20251021104815.70662-4-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Only files in the same domain will share the page cache. Also modify the sysfs related content in preparation for the upcoming page cache share feature. Signed-off-by: Hongzhen Luo [hongbo: forward port, minor fixes] Signed-off-by: Hongbo Li --- fs/erofs/super.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 283449024996..93cc24542405 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -515,6 +515,8 @@ static int erofs_fc_parse_param(struct fs_context *fc, if (!sbi->fsid) return -ENOMEM; break; +#endif +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) case Opt_domain_id: kfree(sbi->domain_id); sbi->domain_id =3D kstrdup(param->string, GFP_KERNEL); @@ -615,7 +617,7 @@ static void erofs_set_sysfs_name(struct super_block *sb) { struct erofs_sb_info *sbi =3D EROFS_SB(sb); =20 - if (sbi->domain_id) + if (sbi->domain_id && !sbi->ishare_key) super_set_sysfs_name_generic(sb, "%s,%s", sbi->domain_id, sbi->fsid); else if (sbi->fsid) @@ -1032,6 +1034,8 @@ static int erofs_show_options(struct seq_file *seq, s= truct dentry *root) #ifdef CONFIG_EROFS_FS_ONDEMAND if (sbi->fsid) seq_printf(seq, ",fsid=3D%s", sbi->fsid); +#endif +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_INODE_SHA= RE) if (sbi->domain_id) seq_printf(seq, ",domain_id=3D%s", sbi->domain_id); #endif --=20 2.22.0 From nobody Mon Feb 9 01:31:15 2026 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (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 3FAB02F2603 for ; Tue, 21 Oct 2025 11:17:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761045482; cv=none; b=o8Be2sC/H0iuodfNPjixRepnfn8QqNTGabocbIgSIt8EzMLCe9Kn3kTmWoVv3pI6LH2x84RiSppMjjI5JbAB/LT31e/sANq+9uBEG/p+LPaOPCUiXPjseEEg4cICQo0tzWlLkafjtYHmQorWLi4HJZa21ZreBt+cAZpNfg+fmkU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761045482; c=relaxed/simple; bh=ZYvoAl0sRHnijm6GN2cHxE8OKKohFQQy3T+gkIOGs6U=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FXo3nVl184VRhSQhaQL8v0NJ4QXaZUahycJTd4vzqVPoVdgsdItZeO+3vEJzCxzBLqvFEK9EteHpn3Dt/T53mjTyfrurA3koOpk6IaQkgtz8hRuXAL/XSHxSIXMj7lwMhZzTqoORwwV56tnwsLJz8mDXk7Xp3wIU9C8dJWRHGIY= 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=Q7u3xP+e; arc=none smtp.client-ip=45.249.212.188 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="Q7u3xP+e" Received: from canpmsgout07.his.huawei.com (unknown [172.19.92.160]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4crThg0pdZzTh5t for ; Tue, 21 Oct 2025 18:54:59 +0800 (CST) dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=BFZfK/0YEQSEtzV8IiT0VSkhYfjw4vZsWKJaCKfBT2g=; b=Q7u3xP+ePgjovL7GhSaB+3IoAuz0C5D15GorwS1Yy3Ehlgm7qMmyeK1hp9fb+W5ka2igmPaYk Yu961IQe1GNU8GjXkxnGuBfdbr3zyJdvBqutkXVe30Y4rdWssRtJx4VEYrHzoF6RoUAiyfvtWeL fxTxrXn63TG0Q0Htnc3cvBI= Received: from mail.maildlp.com (unknown [172.19.163.17]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4crTnV2bcdzLlVc; Tue, 21 Oct 2025 18:59:10 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 5C0F51A0188; Tue, 21 Oct 2025 18:59:34 +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; Tue, 21 Oct 2025 18:59:33 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 4/7] erofs: introduce the page cache share feature Date: Tue, 21 Oct 2025 10:48:12 +0000 Message-ID: <20251021104815.70662-5-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo Currently, reading files with different paths (or names) but the same content will consume multiple copies of the page cache, even if the content of these page caches is the same. For example, reading identical files (e.g., *.so files) from two different minor versions of container images will cost multiple copies of the same page cache, since different containers have different mount points. Therefore, sharing the page cache for files with the same content can save memory. This introduces the page cache share feature in erofs. It allocate a deduplicated inode and use its page cache as shared. Reads for files with identical content will ultimately be routed to the page cache of the deduplicated inode. In this way, a single page cache satisfies multiple read requests for different files with the same contents. Signed-off-by: Hongzhen Luo [hongbo: forward port, minor fixes and cleanup] Signed-off-by: Hongbo Li --- fs/erofs/Makefile | 1 + fs/erofs/internal.h | 25 +++++ fs/erofs/ishare.c | 236 ++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/ishare.h | 28 ++++++ fs/erofs/super.c | 30 +++++- fs/erofs/xattr.c | 14 +-- 6 files changed, 326 insertions(+), 8 deletions(-) create mode 100644 fs/erofs/ishare.c create mode 100644 fs/erofs/ishare.h diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 549abc424763..102a23bf5dec 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -10,3 +10,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) +=3D decompressor_zstd.o erofs-$(CONFIG_EROFS_FS_ZIP_ACCEL) +=3D decompressor_crypto.o erofs-$(CONFIG_EROFS_FS_BACKED_BY_FILE) +=3D fileio.o erofs-$(CONFIG_EROFS_FS_ONDEMAND) +=3D fscache.o +erofs-$(CONFIG_EROFS_FS_INODE_SHARE) +=3D ishare.o \ No newline at end of file diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 245b9e3897bc..158bda6ba784 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -199,6 +199,14 @@ static inline bool erofs_is_fscache_mode(struct super_= block *sb) !erofs_is_fileio_mode(EROFS_SB(sb)) && !sb->s_bdev; } =20 +extern struct file_system_type erofs_anon_fs_type; + +static inline bool erofs_is_ishare_inode(struct inode *inode) +{ + return !erofs_is_fscache_mode(inode->i_sb) && + inode->i_sb->s_type =3D=3D &erofs_anon_fs_type; +} + enum { EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_READAHEAD, @@ -306,6 +314,22 @@ struct erofs_inode { }; #endif /* CONFIG_EROFS_FS_ZIP */ }; +#ifdef CONFIG_EROFS_FS_INODE_SHARE + union { + /* internal dedup inode */ + struct { + char *fingerprint; + spinlock_t lock; + /* all backing inodes */ + struct list_head backing_head; + }; + + struct { + struct inode *ishare; + struct list_head backing_link; + }; + }; +#endif /* the corresponding vfs inode */ struct inode vfs_inode; }; @@ -412,6 +436,7 @@ extern const struct inode_operations erofs_dir_iops; =20 extern const struct file_operations erofs_file_fops; extern const struct file_operations erofs_dir_fops; +extern const struct file_operations erofs_ishare_fops; =20 extern const struct iomap_ops z_erofs_iomap_report_ops; =20 diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c new file mode 100644 index 000000000000..910b732bf8e7 --- /dev/null +++ b/fs/erofs/ishare.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#include +#include +#include +#include +#include +#include "ishare.h" +#include "internal.h" +#include "xattr.h" + +static DEFINE_MUTEX(erofs_ishare_lock); +static struct vfsmount *erofs_ishare_mnt; +static refcount_t erofs_ishare_supers; + +int erofs_ishare_init(struct super_block *sb) +{ + struct vfsmount *mnt =3D NULL; + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + + if (!sbi->ishare_key) + return 0; + + mutex_lock(&erofs_ishare_lock); + if (erofs_ishare_mnt) { + refcount_inc(&erofs_ishare_supers); + } else { + mnt =3D kern_mount(&erofs_anon_fs_type); + if (!IS_ERR(mnt)) { + erofs_ishare_mnt =3D mnt; + refcount_set(&erofs_ishare_supers, 1); + } + } + mutex_unlock(&erofs_ishare_lock); + return IS_ERR(mnt) ? PTR_ERR(mnt) : 0; +} + +void erofs_ishare_exit(struct super_block *sb) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(sb); + struct vfsmount *tmp; + + if (!sbi->ishare_key || !erofs_ishare_mnt) + return; + + mutex_lock(&erofs_ishare_lock); + if (refcount_dec_and_test(&erofs_ishare_supers)) { + tmp =3D erofs_ishare_mnt; + erofs_ishare_mnt =3D NULL; + mutex_unlock(&erofs_ishare_lock); + kern_unmount(tmp); + mutex_lock(&erofs_ishare_lock); + } + mutex_unlock(&erofs_ishare_lock); + kfree(sbi->ishare_key); + sbi->ishare_key =3D NULL; +} + +static int erofs_ishare_iget5_eq(struct inode *inode, void *data) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + return vi->fingerprint && memcmp(vi->fingerprint, data, + sizeof(size_t) + *(size_t *)data) =3D=3D 0; +} + +static int erofs_ishare_iget5_set(struct inode *inode, void *data) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + vi->fingerprint =3D data; + INIT_LIST_HEAD(&vi->backing_head); + spin_lock_init(&vi->lock); + return 0; +} + +bool erofs_ishare_fill_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct erofs_sb_info *sbi =3D EROFS_SB(inode->i_sb); + struct inode *idedup; + /* + * fingerprint layout: + * fingerprint length + fingerprint content (xattr_value + domain_id) + */ + char *ishare_key =3D sbi->ishare_key, *fingerprint; + ssize_t ishare_vlen; + unsigned long hash; + int key_idx; + + if (!sbi->domain_id || !ishare_key) + return false; + + key_idx =3D sbi->ishare_key_idx; + ishare_vlen =3D erofs_getxattr(inode, key_idx, ishare_key, NULL, 0); + if (ishare_vlen <=3D 0 || ishare_vlen > (1 << sbi->blkszbits)) + return false; + + fingerprint =3D kmalloc(sizeof(ssize_t) + ishare_vlen + + strlen(sbi->domain_id), GFP_KERNEL); + if (!fingerprint) + return false; + + *(ssize_t *)fingerprint =3D ishare_vlen + strlen(sbi->domain_id); + if (ishare_vlen !=3D erofs_getxattr(inode, key_idx, ishare_key, + fingerprint + sizeof(ssize_t), + ishare_vlen)) { + kfree(fingerprint); + return false; + } + + memcpy(fingerprint + sizeof(ssize_t) + ishare_vlen, + sbi->domain_id, strlen(sbi->domain_id)); + hash =3D xxh32(fingerprint + sizeof(ssize_t), + ishare_vlen + strlen(sbi->domain_id), hash); + idedup =3D iget5_locked(erofs_ishare_mnt->mnt_sb, hash, + erofs_ishare_iget5_eq, erofs_ishare_iget5_set, + fingerprint); + if (!idedup) { + kfree(fingerprint); + return false; + } + + INIT_LIST_HEAD(&vi->backing_link); + vi->ishare =3D idedup; + spin_lock(&EROFS_I(idedup)->lock); + list_add(&vi->backing_link, &EROFS_I(idedup)->backing_head); + spin_unlock(&EROFS_I(idedup)->lock); + + if (!(idedup->i_state & I_NEW)) { + kfree(fingerprint); + return true; + } + + if (erofs_inode_is_data_compressed(vi->datalayout)) + idedup->i_mapping->a_ops =3D &z_erofs_aops; + else + idedup->i_mapping->a_ops =3D &erofs_aops; + idedup->i_mode =3D vi->vfs_inode.i_mode; + i_size_write(idedup, vi->vfs_inode.i_size); + unlock_new_inode(idedup); + return true; +} + +void erofs_ishare_free_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct inode *idedup =3D vi->ishare; + + if (!idedup) + return; + + spin_lock(&EROFS_I(idedup)->lock); + list_del(&vi->backing_link); + spin_unlock(&EROFS_I(idedup)->lock); + iput(idedup); + vi->ishare =3D NULL; +} + +static int erofs_ishare_file_open(struct inode *inode, struct file *file) +{ + struct file *realfile; + struct inode *dedup; + + dedup =3D EROFS_I(inode)->ishare; + if (!dedup) + return -EINVAL; + + realfile =3D alloc_file_pseudo(dedup, erofs_ishare_mnt, "erofs_ishare_fil= e", + O_RDONLY, &erofs_file_fops); + if (IS_ERR(realfile)) + return PTR_ERR(realfile); + + file_ra_state_init(&realfile->f_ra, file->f_mapping); + realfile->private_data =3D EROFS_I(inode); + file->private_data =3D realfile; + return 0; +} + +static int erofs_ishare_file_release(struct inode *inode, struct file *fil= e) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + fput(realfile); + realfile->private_data =3D NULL; + return 0; +} + +static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb, + struct iov_iter *to) +{ + struct file *realfile =3D iocb->ki_filp->private_data; + struct inode *inode =3D file_inode(iocb->ki_filp); + struct kiocb dedup_iocb; + ssize_t nread; + + if (!realfile) + return -EINVAL; + if (!iov_iter_count(to)) + return 0; + + /* fallback to the original file in DAX or DIRECT mode */ + if (IS_DAX(inode) || (iocb->ki_flags & IOCB_DIRECT)) + realfile =3D iocb->ki_filp; + + kiocb_clone(&dedup_iocb, iocb, realfile); + nread =3D filemap_read(&dedup_iocb, to, 0); + iocb->ki_pos =3D dedup_iocb.ki_pos; + touch_atime(&iocb->ki_filp->f_path); + return nread; +} + +static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + + vma_set_file(vma, realfile); + return generic_file_readonly_mmap(file, vma); +} + +const struct file_operations erofs_ishare_fops =3D { + .open =3D erofs_ishare_file_open, + .llseek =3D generic_file_llseek, + .read_iter =3D erofs_ishare_file_read_iter, + .mmap =3D erofs_ishare_mmap, + .release =3D erofs_ishare_file_release, + .get_unmapped_area =3D thp_get_unmapped_area, + .splice_read =3D filemap_splice_read, +}; diff --git a/fs/erofs/ishare.h b/fs/erofs/ishare.h new file mode 100644 index 000000000000..54f2251c8179 --- /dev/null +++ b/fs/erofs/ishare.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#ifndef __EROFS_ISHARE_H +#define __EROFS_ISHARE_H + +#include +#include +#include "internal.h" + +#ifdef CONFIG_EROFS_FS_INODE_SHARE + +int erofs_ishare_init(struct super_block *sb); +void erofs_ishare_exit(struct super_block *sb); +bool erofs_ishare_fill_inode(struct inode *inode); +void erofs_ishare_free_inode(struct inode *inode); + +#else + +static inline int erofs_ishare_init(struct super_block *sb) { return 0; } +static inline void erofs_ishare_exit(struct super_block *sb) {} +static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } +static inline void erofs_ishare_free_inode(struct inode *inode) {} + +#endif // CONFIG_EROFS_FS_INODE_SHARE + +#endif diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 93cc24542405..f067633c0072 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -13,6 +13,7 @@ #include #include #include "xattr.h" +#include "ishare.h" =20 #define CREATE_TRACE_POINTS #include @@ -77,10 +78,25 @@ static struct inode *erofs_alloc_inode(struct super_blo= ck *sb) return &vi->vfs_inode; } =20 +#ifdef CONFIG_EROFS_FS_INODE_SHARE +static void erofs_free_dedup_inode(struct erofs_inode *vi) +{ + kfree(vi->fingerprint); + kmem_cache_free(erofs_inode_cachep, vi); +}; +#else +static void erofs_free_dedup_inode(struct erofs_inode *vi) +{} +#endif + static void erofs_free_inode(struct inode *inode) { struct erofs_inode *vi =3D EROFS_I(inode); =20 + if (erofs_is_ishare_inode(inode)) { + erofs_free_dedup_inode(vi); + return; + } if (inode->i_op =3D=3D &erofs_fast_symlink_iops) kfree(inode->i_link); kfree(vi->xattr_shared_xattrs); @@ -924,9 +940,21 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 +static const struct super_operations erofs_anon_sops =3D { + .statfs =3D simple_statfs, + .alloc_inode =3D erofs_alloc_inode, + .free_inode =3D erofs_free_inode, +}; + static int erofs_anon_init_fs_context(struct fs_context *fc) { - return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM; + struct pseudo_fs_context *ctx; + + ctx =3D init_pseudo(fc, EROFS_SUPER_MAGIC); + if (ctx) + ctx->ops =3D &erofs_anon_sops; + + return ctx ? 0 : -ENOMEM; } =20 struct file_system_type erofs_anon_fs_type =3D { diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 6610c007ee4c..4b39db939135 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -571,6 +571,7 @@ void erofs_xattr_set_ishare_key(struct super_block *sb) struct erofs_sb_info *sbi =3D EROFS_SB(sb); struct erofs_buf buf =3D __EROFS_BUF_INITIALIZER; struct xattr_handler const *handler; + bool found =3D false; erofs_off_t pos; char *key; int len, i; @@ -582,28 +583,27 @@ void erofs_xattr_set_ishare_key(struct super_block *s= b) =20 buf.mapping =3D sbi->packed_inode->i_mapping; pos =3D sbi->ishare_key_start << 2; - (void)erofs_init_metabuf(&buf, sb, false); ptr =3D erofs_read_metadata(sb, &buf, &pos, &len); =20 if (IS_ERR(ptr)) goto out; =20 - for (i =3D 0; ARRAY_SIZE(erofs_xattr_handlers) - 1; i++) { + for (i =3D 0; ARRAY_SIZE(erofs_xattr_handlers); i++) { handler =3D erofs_xattr_handlers[i]; if (!handler) + continue; + if (!memcmp(handler->prefix, ptr, strlen(handler->prefix))) { + found =3D true; break; - if (!memcmp(handler->prefix, ptr, strlen(handler->prefix))) - break; + } } =20 - if (!handler) + if (!found) goto out; - len -=3D strlen(handler->prefix); key =3D kzalloc(len + 1, GFP_KERNEL); if (!key) goto out; - memcpy(key, ptr + strlen(handler->prefix), len); sbi->ishare_key =3D key; sbi->ishare_key_idx =3D handler->flags; --=20 2.22.0 From nobody Mon Feb 9 01:31:15 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (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 0822D32E12E for ; Tue, 21 Oct 2025 10:59:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044386; cv=none; b=RDx2cu1/fy3fT+3iidl0leH21259rITSHsW3NJiC2+qbHBXm5kZOB9XHOYlnBmy0EZfj5V0JZIgm1L36j1om0wPnjm9UMNkd25bORSoh4oL5Uuu8uThd+mAdE3ubENlUiEQzMKVnbfULqE2+S6VCQg1kVGig/OLSPBtGAn64rmU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044386; c=relaxed/simple; bh=JhNd83WD2w/WLEeLAvyx8sCelylgN07rekchxNwHQBY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Z7eemQ/HQXSWuUfAqq65klqwjuSs+lJPA3XFQttbkiRX2viF8x7fFI+9kbHBB9TX6tPpv08f/zPAyVJp2XZ8Vrct1A22bDOkcu51EkRGM/hu629Vn+H1cboraYHlqsH6V0INNoOCYB+8lILhSj4hLQyV/uGv7+TsvUTsFPIf4cQ= 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=1dRJFm92; arc=none smtp.client-ip=113.46.200.226 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="1dRJFm92" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=LY07TegupRGvSH/9+tapmPTo/3N1TCD/ljyoNiLW+uE=; b=1dRJFm92O/Ob7s4AZR8cRATGWCbuqsGQ5t0VTKsGnL8F6JKz80VYYpQExCGGoORilrLZCwWpS fvQET1psEIgqMO0tKVnui7dMEHL7YjMpyKaA6CGcfn8w3HYmf+ij1rJtgbosF/3wTJnwdobe46L xjUdRqksDRBtpL4AWl2PEPc= Received: from mail.maildlp.com (unknown [172.19.88.163]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4crTnV6LdmzKm5G; Tue, 21 Oct 2025 18:59:10 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id BA3A018001B; Tue, 21 Oct 2025 18:59:34 +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; Tue, 21 Oct 2025 18:59:34 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 5/7] erofs: support unencoded inodes for page cache share Date: Tue, 21 Oct 2025 10:48:13 +0000 Message-ID: <20251021104815.70662-6-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo This patch adds inode page cache sharing functionality for unencoded files. I conducted experiments in the container environment. Below is the memory usage for reading all files in two different minor versions of container images: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 241 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 163 | 33% | +-------------------+------------------+-------------+---------------+ | | No | 872 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 630 | 28% | +-------------------+------------------+-------------+---------------+ | | No | 2771 | - | | tensorflow +------------------+-------------+---------------+ | 2.11.0 & 2.11.1 | Yes | 2340 | 16% | +-------------------+------------------+-------------+---------------+ | | No | 926 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 735 | 21% | +-------------------+------------------+-------------+---------------+ | | No | 390 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 219 | 44% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 924 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 474 | 49% | +-------------------+------------------+-------------+---------------+ Additionally, the table below shows the runtime memory usage of the container: +-------------------+------------------+-------------+---------------+ | Image | Page Cache Share | Memory (MB) | Memory | | | | | Reduction (%) | +-------------------+------------------+-------------+---------------+ | | No | 35 | - | | redis +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 28 | 20% | +-------------------+------------------+-------------+---------------+ | | No | 149 | - | | postgres +------------------+-------------+---------------+ | 16.1 & 16.2 | Yes | 95 | 37% | +-------------------+------------------+-------------+---------------+ | | No | 1028 | - | | tensorflow +------------------+-------------+---------------+ | 2.11.0 & 2.11.1 | Yes | 930 | 10% | +-------------------+------------------+-------------+---------------+ | | No | 155 | - | | mysql +------------------+-------------+---------------+ | 8.0.11 & 8.0.12 | Yes | 132 | 15% | +-------------------+------------------+-------------+---------------+ | | No | 25 | - | | nginx +------------------+-------------+---------------+ | 7.2.4 & 7.2.5 | Yes | 20 | 20% | +-------------------+------------------+-------------+---------------+ | tomcat | No | 186 | - | | 10.1.25 & 10.1.26 +------------------+-------------+---------------+ | | Yes | 98 | 48% | +-------------------+------------------+-------------+---------------+ Signed-off-by: Hongzhen Luo [hongbo: forward port, minor fixes and cleanup] Signed-off-by: Hongbo Li --- fs/erofs/data.c | 81 ++++++++++++++++++++++++++++++++++++++----- fs/erofs/inode.c | 5 +++ fs/erofs/internal.h | 4 +++ fs/erofs/ishare.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/ishare.h | 18 ++++++++++ fs/erofs/super.c | 7 ++++ 6 files changed, 190 insertions(+), 8 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 8ca29962a3dd..438d43c959aa 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -5,6 +5,7 @@ * Copyright (C) 2021, Alibaba Cloud */ #include "internal.h" +#include "ishare.h" #include #include =20 @@ -266,25 +267,55 @@ void erofs_onlinefolio_end(struct folio *folio, int e= rr, bool dirty) folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO))); } =20 +struct erofs_iomap { + void *base; + struct inode *realinode; +}; + static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, unsigned int flags, struct iomap *iomap, struct iomap *srcmap) { int ret; - struct super_block *sb =3D inode->i_sb; + struct super_block *sb; struct erofs_map_blocks map; struct erofs_map_dev mdev; + struct inode *realinode =3D inode; + struct erofs_iomap *erofs_iomap; + bool is_ishare =3D erofs_is_ishare_inode(inode); + + if (is_ishare) { + if (!iomap->private) { + erofs_iomap =3D kzalloc(sizeof(*erofs_iomap), + GFP_KERNEL); + if (!erofs_iomap) + return -ENOMEM; + erofs_iomap->realinode =3D erofs_ishare_iget(inode); + if (!erofs_iomap->realinode) { + kfree(erofs_iomap); + return -EINVAL; + } + iomap->private =3D erofs_iomap; + } + erofs_iomap =3D iomap->private; + realinode =3D erofs_iomap->realinode; + } =20 + sb =3D realinode->i_sb; map.m_la =3D offset; map.m_llen =3D length; - ret =3D erofs_map_blocks(inode, &map); + ret =3D erofs_map_blocks(realinode, &map); if (ret < 0) return ret; =20 iomap->offset =3D map.m_la; iomap->length =3D map.m_llen; iomap->flags =3D 0; - iomap->private =3D NULL; iomap->addr =3D IOMAP_NULL_ADDR; + + if (is_ishare) + erofs_iomap->base =3D NULL; + else + iomap->private =3D NULL; if (!(map.m_flags & EROFS_MAP_MAPPED)) { iomap->type =3D IOMAP_HOLE; return 0; @@ -318,7 +349,10 @@ static int erofs_iomap_begin(struct inode *inode, loff= _t offset, loff_t length, if (IS_ERR(ptr)) return PTR_ERR(ptr); iomap->inline_data =3D ptr; - iomap->private =3D buf.base; + if (is_ishare) + erofs_iomap->base =3D buf.base; + else + iomap->private =3D buf.base; } else { iomap->type =3D IOMAP_MAPPED; } @@ -328,7 +362,17 @@ static int erofs_iomap_begin(struct inode *inode, loff= _t offset, loff_t length, static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length, ssize_t written, unsigned int flags, struct iomap *iomap) { - void *ptr =3D iomap->private; + struct erofs_iomap *erofs_iomap; + bool is_ishare; + void *ptr; + + is_ishare =3D erofs_is_ishare_inode(inode); + if (is_ishare) { + erofs_iomap =3D iomap->private; + ptr =3D erofs_iomap->base; + } else { + ptr =3D iomap->private; + } =20 if (ptr) { struct erofs_buf buf =3D { @@ -341,6 +385,12 @@ static int erofs_iomap_end(struct inode *inode, loff_t= pos, loff_t length, } else { DBG_BUGON(iomap->type =3D=3D IOMAP_INLINE); } + + if (is_ishare) { + erofs_ishare_iput(erofs_iomap->realinode); + kfree(erofs_iomap); + iomap->private =3D NULL; + } return written; } =20 @@ -369,17 +419,32 @@ int erofs_fiemap(struct inode *inode, struct fiemap_e= xtent_info *fieinfo, */ static int erofs_read_folio(struct file *file, struct folio *folio) { + struct erofs_read_ctx rdctx =3D { + .file =3D file, + .inode =3D folio_inode(folio), + }; + int ret; + + erofs_read_begin(&rdctx); + ret =3D iomap_read_folio(folio, &erofs_iomap_ops); + erofs_read_end(&rdctx); trace_erofs_read_folio(folio, true); =20 - return iomap_read_folio(folio, &erofs_iomap_ops); + return ret; } =20 static void erofs_readahead(struct readahead_control *rac) { + struct erofs_read_ctx rdctx =3D { + .file =3D rac->file, + .inode =3D rac->mapping->host, + }; + + erofs_read_begin(&rdctx); + iomap_readahead(rac, &erofs_iomap_ops); + erofs_read_end(&rdctx); trace_erofs_readahead(rac->mapping->host, readahead_index(rac), readahead_count(rac), true); - - return iomap_readahead(rac, &erofs_iomap_ops); } =20 static sector_t erofs_bmap(struct address_space *mapping, sector_t block) diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index cb780c095d28..fe45e6c18f8e 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -5,6 +5,7 @@ * Copyright (C) 2021, Alibaba Cloud */ #include "xattr.h" +#include "ishare.h" #include #include =20 @@ -215,6 +216,10 @@ static int erofs_fill_inode(struct inode *inode) case S_IFREG: inode->i_op =3D &erofs_generic_iops; inode->i_fop =3D &erofs_file_fops; +#ifdef CONFIG_EROFS_FS_INODE_SHARE + if (erofs_ishare_fill_inode(inode)) + inode->i_fop =3D &erofs_ishare_fops; +#endif break; case S_IFDIR: inode->i_op =3D &erofs_dir_iops; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 158bda6ba784..9ce6e5753978 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -322,11 +322,15 @@ struct erofs_inode { spinlock_t lock; /* all backing inodes */ struct list_head backing_head; + /* processing list */ + struct list_head processing_head; }; =20 struct { struct inode *ishare; struct list_head backing_link; + struct list_head processing_link; + atomic_t processing_count; }; }; #endif diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index 910b732bf8e7..73432b13bf75 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -72,6 +72,7 @@ static int erofs_ishare_iget5_set(struct inode *inode, vo= id *data) =20 vi->fingerprint =3D data; INIT_LIST_HEAD(&vi->backing_head); + INIT_LIST_HEAD(&vi->processing_head); spin_lock_init(&vi->lock); return 0; } @@ -124,7 +125,9 @@ bool erofs_ishare_fill_inode(struct inode *inode) } =20 INIT_LIST_HEAD(&vi->backing_link); + INIT_LIST_HEAD(&vi->processing_link); vi->ishare =3D idedup; + spin_lock(&EROFS_I(idedup)->lock); list_add(&vi->backing_link, &EROFS_I(idedup)->backing_head); spin_unlock(&EROFS_I(idedup)->lock); @@ -234,3 +237,83 @@ const struct file_operations erofs_ishare_fops =3D { .get_unmapped_area =3D thp_get_unmapped_area, .splice_read =3D filemap_splice_read, }; + +void erofs_read_begin(struct erofs_read_ctx *rdctx) +{ + struct erofs_inode *vi, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi =3D rdctx->file->private_data; + vi_dedup =3D EROFS_I(file_inode(rdctx->file)); + + spin_lock(&vi_dedup->lock); + if (!list_empty(&vi->processing_link)) { + atomic_inc(&vi->processing_count); + } else { + list_add(&vi->processing_link, + &vi_dedup->processing_head); + atomic_set(&vi->processing_count, 1); + } + spin_unlock(&vi_dedup->lock); +} + +void erofs_read_end(struct erofs_read_ctx *rdctx) +{ + struct erofs_inode *vi, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi =3D rdctx->file->private_data; + vi_dedup =3D EROFS_I(file_inode(rdctx->file)); + + spin_lock(&vi_dedup->lock); + if (atomic_dec_and_test(&vi->processing_count)) + list_del_init(&vi->processing_link); + spin_unlock(&vi_dedup->lock); +} + +/* + * erofs_ishare_iget - find the backing inode. + */ +struct inode *erofs_ishare_iget(struct inode *inode) +{ + struct erofs_inode *vi, *vi_dedup; + struct inode *realinode; + + if (!erofs_is_ishare_inode(inode)) + return igrab(inode); + + vi_dedup =3D EROFS_I(inode); + spin_lock(&vi_dedup->lock); + /* try processing inodes first */ + if (!list_empty(&vi_dedup->processing_head)) { + list_for_each_entry(vi, &vi_dedup->processing_head, + processing_link) { + realinode =3D igrab(&vi->vfs_inode); + if (realinode) { + spin_unlock(&vi_dedup->lock); + return realinode; + } + } + } + + /* fall back to all backing inodes */ + DBG_BUGON(list_empty(&vi_dedup->backing_head)); + list_for_each_entry(vi, &vi_dedup->backing_head, backing_link) { + realinode =3D igrab(&vi->vfs_inode); + if (realinode) + break; + } + spin_unlock(&vi_dedup->lock); + + DBG_BUGON(!realinode); + return realinode; +} + +void erofs_ishare_iput(struct inode *realinode) +{ + iput(realinode); +} diff --git a/fs/erofs/ishare.h b/fs/erofs/ishare.h index 54f2251c8179..b85fa240507b 100644 --- a/fs/erofs/ishare.h +++ b/fs/erofs/ishare.h @@ -9,6 +9,11 @@ #include #include "internal.h" =20 +struct erofs_read_ctx { + struct file *file; /* may be NULL */ + struct inode *inode; +}; + #ifdef CONFIG_EROFS_FS_INODE_SHARE =20 int erofs_ishare_init(struct super_block *sb); @@ -16,6 +21,13 @@ void erofs_ishare_exit(struct super_block *sb); bool erofs_ishare_fill_inode(struct inode *inode); void erofs_ishare_free_inode(struct inode *inode); =20 +/* read/readahead */ +void erofs_read_begin(struct erofs_read_ctx *rdctx); +void erofs_read_end(struct erofs_read_ctx *rdctx); + +struct inode *erofs_ishare_iget(struct inode *inode); +void erofs_ishare_iput(struct inode *realinode); + #else =20 static inline int erofs_ishare_init(struct super_block *sb) { return 0; } @@ -23,6 +35,12 @@ static inline void erofs_ishare_exit(struct super_block = *sb) {} static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } static inline void erofs_ishare_free_inode(struct inode *inode) {} =20 +static inline void erofs_read_begin(struct erofs_read_ctx *rdctx) {} +static inline void erofs_read_end(struct erofs_read_ctx *rdctx) {} + +static inline struct inode *erofs_ishare_iget(struct inode *inode) { retur= n inode; } +static inline void erofs_ishare_iput(struct inode *realinode) {} + #endif // CONFIG_EROFS_FS_INODE_SHARE =20 #endif diff --git a/fs/erofs/super.c b/fs/erofs/super.c index f067633c0072..cba3da383558 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -97,6 +97,7 @@ static void erofs_free_inode(struct inode *inode) erofs_free_dedup_inode(vi); return; } + erofs_ishare_free_inode(inode); if (inode->i_op =3D=3D &erofs_fast_symlink_iops) kfree(inode->i_link); kfree(vi->xattr_shared_xattrs); @@ -762,6 +763,10 @@ static int erofs_fc_fill_super(struct super_block *sb,= struct fs_context *fc) if (err) return err; =20 + err =3D erofs_ishare_init(sb); + if (err) + return err; + sbi->dir_ra_bytes =3D EROFS_DIR_RA_BYTES; erofs_info(sb, "mounted with root inode @ nid %llu.", sbi->root_nid); return 0; @@ -911,6 +916,7 @@ static void erofs_kill_sb(struct super_block *sb) kill_anon_super(sb); else kill_block_super(sb); + erofs_drop_internal_inodes(sbi); fs_put_dax(sbi->dif0.dax_dev, NULL); erofs_fscache_unregister_fs(sb); @@ -922,6 +928,7 @@ static void erofs_put_super(struct super_block *sb) { struct erofs_sb_info *const sbi =3D EROFS_SB(sb); =20 + erofs_ishare_exit(sb); erofs_unregister_sysfs(sb); erofs_shrinker_unregister(sb); erofs_xattr_prefixes_cleanup(sb); --=20 2.22.0 From nobody Mon Feb 9 01:31:15 2026 Received: from canpmsgout02.his.huawei.com (canpmsgout02.his.huawei.com [113.46.200.217]) (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 EA5D32EDD75 for ; Tue, 21 Oct 2025 10:59:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.217 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044379; cv=none; b=j8hdhAFx5pZBwxQ0zOvqsbuZOO5tl234R2TXhnB5qRk29nr8MWtqnTgEPEoPF1kgobqSVjO+cNxYlhBY5Us3yU5jDsTTxqZ6CzsVQbDZvSB0xFNUQm3el48HzKas6c6fHuQcBXU2lz5zKw/yj6O/8ola4vvsgKrZFugjdJpYL9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044379; c=relaxed/simple; bh=xXFZfZ4nNiHBb/W39Fr5wgWasrpseyiO8U4O8631IYQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KDYWyuBKgmpMEWAit5pbDfFMak+osG+aRe6+eqRgbCjSDrqsi+a8dgZwqzKqqQT1BVSMp7hrx1szD5pPxtgaYjdpsqPBDTqHiVmDjvptDLyERDiAiWN0rt9KETROLsCgDHTXB79gO5+GB0hr/rjk7Qxgx56tUlC2H4NYY81oSBY= 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=BArDbB0+; arc=none smtp.client-ip=113.46.200.217 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="BArDbB0+" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=R4gUs6vcWZbCSV9LDMDP4DWnJrknFMDZIKHxe0URueo=; b=BArDbB0+hRPRn0B6O7TN88wkUMspQEkzSzPdTl4i7nSpGbgtuMx4OVRI99e3WAafOdehNWKwr sno+fDYuQ+28C0inJTMPgQmZiL0sBUSQ8WwiXl/2gqvjhkfP8LGIKgp2RHPToloytwverYLkiuY jXZ9by+DPiu+i86jKnuSHbo= Received: from mail.maildlp.com (unknown [172.19.88.194]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4crTmd4r3Czcb1P; Tue, 21 Oct 2025 18:58:25 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 147DC140123; Tue, 21 Oct 2025 18:59:35 +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; Tue, 21 Oct 2025 18:59:34 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 6/7] erofs: support compressed inodes for page cache share Date: Tue, 21 Oct 2025 10:48:14 +0000 Message-ID: <20251021104815.70662-7-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo This patch adds page cache sharing functionality for compressed inodes. Signed-off-by: Hongzhen Luo [hongbo: forward port] Signed-off-by: Hongbo Li --- fs/erofs/zdata.c | 56 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index bc80cfe482f7..e76421de86cb 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -5,6 +5,7 @@ * Copyright (C) 2022 Alibaba Cloud */ #include "compress.h" +#include "ishare.h" #include #include #include @@ -493,7 +494,7 @@ enum z_erofs_pclustermode { }; =20 struct z_erofs_frontend { - struct inode *const inode; + struct inode *inode; struct erofs_map_blocks map; struct z_erofs_bvec_iter biter; =20 @@ -1870,10 +1871,24 @@ static void z_erofs_pcluster_readmore(struct z_erof= s_frontend *f, =20 static int z_erofs_read_folio(struct file *file, struct folio *folio) { - struct inode *const inode =3D folio->mapping->host; - Z_EROFS_DEFINE_FRONTEND(f, inode, folio_pos(folio)); + struct inode *const inode =3D folio->mapping->host, *realinode; + Z_EROFS_DEFINE_FRONTEND(f, NULL, folio_pos(folio)); + struct erofs_read_ctx rdctx =3D { + .file =3D file, + .inode =3D inode, + }; int err; =20 + trace_erofs_read_folio(folio, false); + + erofs_read_begin(&rdctx); + + if (erofs_is_ishare_inode(inode)) + realinode =3D erofs_ishare_iget(inode); + else + realinode =3D inode; + + f.inode =3D realinode; trace_erofs_read_folio(folio, false); z_erofs_pcluster_readmore(&f, NULL, true); err =3D z_erofs_scan_folio(&f, folio, false); @@ -1883,23 +1898,39 @@ static int z_erofs_read_folio(struct file *file, st= ruct folio *folio) /* if some pclusters are ready, need submit them anyway */ err =3D z_erofs_runqueue(&f, 0) ?: err; if (err && err !=3D -EINTR) - erofs_err(inode->i_sb, "read error %d @ %lu of nid %llu", - err, folio->index, EROFS_I(inode)->nid); + erofs_err(realinode->i_sb, "read error %d @ %lu of nid %llu", + err, folio->index, EROFS_I(realinode)->nid); =20 erofs_put_metabuf(&f.map.buf); erofs_release_pages(&f.pagepool); + + if (erofs_is_ishare_inode(inode)) + erofs_ishare_iput(realinode); + + erofs_read_end(&rdctx); return err; } =20 static void z_erofs_readahead(struct readahead_control *rac) { - struct inode *const inode =3D rac->mapping->host; - Z_EROFS_DEFINE_FRONTEND(f, inode, readahead_pos(rac)); + struct inode *const inode =3D rac->mapping->host, *realinode; + Z_EROFS_DEFINE_FRONTEND(f, NULL, readahead_pos(rac)); unsigned int nrpages =3D readahead_count(rac); struct folio *head =3D NULL, *folio; + struct erofs_read_ctx rdctx =3D { + .file =3D rac->file, + .inode =3D inode, + }; int err; =20 - trace_erofs_readahead(inode, readahead_index(rac), nrpages, false); + erofs_read_begin(&rdctx); + if (erofs_is_ishare_inode(inode)) + realinode =3D erofs_ishare_iget(inode); + else + realinode =3D inode; + + f.inode =3D realinode; + trace_erofs_readahead(realinode, readahead_index(rac), nrpages, false); z_erofs_pcluster_readmore(&f, rac, true); while ((folio =3D readahead_folio(rac))) { folio->private =3D head; @@ -1913,8 +1944,8 @@ static void z_erofs_readahead(struct readahead_contro= l *rac) =20 err =3D z_erofs_scan_folio(&f, folio, true); if (err && err !=3D -EINTR) - erofs_err(inode->i_sb, "readahead error at folio %lu @ nid %llu", - folio->index, EROFS_I(inode)->nid); + erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu", + folio->index, EROFS_I(realinode)->nid); } z_erofs_pcluster_readmore(&f, rac, false); z_erofs_pcluster_end(&f); @@ -1922,6 +1953,11 @@ static void z_erofs_readahead(struct readahead_contr= ol *rac) (void)z_erofs_runqueue(&f, nrpages); erofs_put_metabuf(&f.map.buf); erofs_release_pages(&f.pagepool); + + if (erofs_is_ishare_inode(inode)) + erofs_ishare_iput(realinode); + + erofs_read_end(&rdctx); } =20 const struct address_space_operations z_erofs_aops =3D { --=20 2.22.0 From nobody Mon Feb 9 01:31:15 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (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 BBA9C32D44F for ; Tue, 21 Oct 2025 10:59:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044384; cv=none; b=XJPM0692vTPZ6p8ZmOQqMOSp+ytZD65R9FpdlX/GXgTr3JVBuhzrSY43onaVH1EzvBFK3zKelItGC+ViZO0BJQZKpKhrXw64YbhHO6sI42YbLEXubhGSGGcFwRxA2PReA7hpUzAe2/a0oeoENFYKdoJDm5MbKKZ5UjarHFJI3Pc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761044384; c=relaxed/simple; bh=m7lKZNF6v1JOQns6TrfDyOTVCleCZ4N0YNF027wTilo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PQ1gMxdAxl9pbx7DcE4p+k4tfJP2z3rKsKLKp2UbE67rKx3PklsEwYTfyPHo3oEJLNfWelLnJRvHjXzdYDGeECH2VTIW57IQGe2wJRiCFOK+ijEFzt34WvKBA4zmD/0DcqEQgC0Nk++xOSe+AwcuvqRR7fcFSDlUQpI6S5xUCnQ= 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=OL51/MT6; arc=none smtp.client-ip=113.46.200.222 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="OL51/MT6" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=7tLzL1Hn+o30kT4oezlP37EIN8PptJGJl2YdtDGMiFg=; b=OL51/MT6lH4JzPxeE4Ja31IrCJ1JqVY7JIg139eAaBwpCxvYSSs5h1rpm/ITf+iojHnGCp4eB rPFLyv/Y6nbRPZUQ6Qqd78D5H8hV+J3b4DYlmlr7Ss1xFjDSAdzsuL+B5mCkUXBcpXW/2j/xtWr FoGSwycp4DtguNH2SPFgiVs= Received: from mail.maildlp.com (unknown [172.19.162.112]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4crTnW36VmzLlVc; Tue, 21 Oct 2025 18:59:11 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 6DDE0140155; Tue, 21 Oct 2025 18:59:35 +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; Tue, 21 Oct 2025 18:59:34 +0800 From: Hongbo Li To: , , , CC: , , Subject: [PATCH RFC v7 7/7] erofs: implement .fadvise for page cache share Date: Tue, 21 Oct 2025 10:48:15 +0000 Message-ID: <20251021104815.70662-8-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20251021104815.70662-1-lihongbo22@huawei.com> References: <20251021104815.70662-1-lihongbo22@huawei.com> 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: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Hongzhen Luo This patch implements the .fadvise interface for page cache share. Similar to overlayfs, it drops those clean, unused pages through vfs_fadvise(). Signed-off-by: Hongzhen Luo [hongbo: forward port, minor cleanup] Signed-off-by: Hongbo Li --- fs/erofs/ishare.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index 73432b13bf75..b067f0e02d6c 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -228,6 +228,16 @@ static int erofs_ishare_mmap(struct file *file, struct= vm_area_struct *vma) return generic_file_readonly_mmap(file, vma); } =20 +static int erofs_ishare_fadvice(struct file *file, loff_t offset, + loff_t len, int advice) +{ + struct file *realfile =3D file->private_data; + + if (!realfile) + return -EINVAL; + return vfs_fadvise(realfile, offset, len, advice); +} + const struct file_operations erofs_ishare_fops =3D { .open =3D erofs_ishare_file_open, .llseek =3D generic_file_llseek, @@ -236,6 +246,7 @@ const struct file_operations erofs_ishare_fops =3D { .release =3D erofs_ishare_file_release, .get_unmapped_area =3D thp_get_unmapped_area, .splice_read =3D filemap_splice_read, + .fadvise =3D erofs_ishare_fadvice, }; =20 void erofs_read_begin(struct erofs_read_ctx *rdctx) --=20 2.22.0