From nobody Sun Feb 8 09:10:57 2026 Received: from out199-2.us.a.mail.aliyun.com (out199-2.us.a.mail.aliyun.com [47.90.199.2]) (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 8408A1E3DF7 for ; Sat, 1 Mar 2025 14:50:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.199.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840629; cv=none; b=Djsfjzu0TG9i4g8z1Jpg+amUhYQVEKgvhLGvbkGZHjaxHfXKVw06LzRa3qMFZnQ7WIGzA43L4U/SN8G7KSOAf4r7bZ5CuVVAQV/p9adNoYkL/TRiwf9OjDvD29leDiOVZc9BF1Irw+fazH+znTYMouaY4BikP4DIEIrUF0yFICw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840629; c=relaxed/simple; bh=0RM1j+DywwWJ8i4SROytSoMfisLkjp04QQv7+pnWFiY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IDI6u+HmMnkz9hPuGASTVbc5TBlYy3uSNm9XkJz5wUeIpGV1Jk0YapT2WboRzop+0UO3mVlpSNuVkd/PVFg9ADI0ScrSR7ZK2VgDCHHFxSH96DzgDs7K/5ZHyKaPyrSwLaHA5UdZ1r8Yc8W7L2T24W39ii9hiY3usWROM+GO/i0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=xT9hvynK; arc=none smtp.client-ip=47.90.199.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="xT9hvynK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840614; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=F1wkNOLPVE+3E35nVrJ+MFirrarMWBSrgK7jQArB6mY=; b=xT9hvynKLSIsKcoOYrulVRINGDu9/ZImQWvPdXynbcE+v8FIueAkRgD/q938RVQChgiwDP0LuSaNZIAtqlgBOC+Qnk3/C48qNkC2uLBgOs/5RcuL4ISeVB1JDIRNB9XEtl855ef+THfgH2QtYozslDj+U1gSmG24o+0AyK5q1vw= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSfpXs_1740840613 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:13 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 1/7] erofs: move `struct erofs_anon_fs_type` to super.c Date: Sat, 1 Mar 2025 22:49:38 +0800 Message-ID: <20250301145002.2420830-2-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 Reviewed-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 ce3d8737df85..ae7bd9ebff38 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 686d835eb533..47004eb89838 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -379,6 +379,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 827b62665649..eb052a770088 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 @@ -850,6 +851,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.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out30-110.freemail.mail.aliyun.com (out30-110.freemail.mail.aliyun.com [115.124.30.110]) (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 027A43597B for ; Sat, 1 Mar 2025 14:55:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.110 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840947; cv=none; b=rc71tPVGcnvh3qDcCGHJOEnbWE+GfOaYFrt53d4Iv0YvU2X8UKsK35VNYm2SZ/FSDMT2S9C0ZeLeDz3GOitOpu/elxd+kgN1DJF2AE+yXEb1ndwxaAnnEJzCdXNbE80mxW05qAGahREknFCnHhxkmRGpEZxE4ZWh7xNgm8n2BX4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840947; c=relaxed/simple; bh=sTzSp/8qfcEqBSVHmyuGqrapK+jTuhfWi4FyeGdXC+k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Uyu30NMexNa87zHFFRhGL7nLa6PnypIh/7eKB/LKNJcvozQCExO+Ihrterl3Q2RbQDW/vKN1YP/MxlTSoOVrPH0bR5eMpfjIgrJBCDIuetqF3eo8rGKIdINV+XlR/k7666XnrttIACtW+wyIzqDf77sh34U+iAbg06cYRLioT1k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=jRHd29SD; arc=none smtp.client-ip=115.124.30.110 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="jRHd29SD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840934; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=wO9fUs9nTc63v3PD92iK3A86VObYSvLUKYRWlwxrLN8=; b=jRHd29SDNM9xwm3nc0b4mVcc8ijSpSOXUUFTk48qw609RocqX/+ju1T3qVimqqdiGcsLa2rBcAUx9BdKTviijklIp4QkOplHS3eXknGxspAUowm1GQ+/prvYRNcAsCK0wFJMtmHXo9yyTRarGCKkGgd3Ixaha8F1PhQ+mdn03Kw= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSfpY4_1740840614 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:14 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 2/7] erofs: support user-defined fingerprint name Date: Sat, 1 Mar 2025 22:49:39 +0800 Message-ID: <20250301145002.2420830-3-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 --- fs/erofs/Kconfig | 10 +++++++++ fs/erofs/erofs_fs.h | 9 ++++++--- fs/erofs/internal.h | 6 ++++++ fs/erofs/super.c | 4 ++++ fs/erofs/xattr.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/xattr.h | 6 ++++++ 6 files changed, 81 insertions(+), 3 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 6ea60661fa55..d2416d35035a 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -178,3 +178,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. diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 199395ed1c1f..261bd9bd47c4 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -30,6 +30,7 @@ #define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020 #define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020 #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 +#define EROFS_FEATURE_INCOMPAT_ISHARE_KEY 0x00000080 #define EROFS_ALL_FEATURE_INCOMPAT \ (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \ EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ @@ -40,7 +41,8 @@ EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \ EROFS_FEATURE_INCOMPAT_FRAGMENTS | \ EROFS_FEATURE_INCOMPAT_DEDUPE | \ - EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES) + EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES | \ + EROFS_FEATURE_INCOMPAT_ISHARE_KEY) =20 #define EROFS_SB_EXTSLOT_SIZE 16 =20 @@ -84,8 +86,9 @@ 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 reserved2[23]; -}; + __le32 ishare_key_start; /* start of ishare key */ + __u8 reserved2[19]; +} __packed; =20 /* * EROFS inode datalayout (i_format in on-disk inode): diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 47004eb89838..21bf9b694048 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -166,6 +166,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) @@ -233,6 +238,7 @@ EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZT= AILPACKING) EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS) EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE) EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES) +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) =20 diff --git a/fs/erofs/super.c b/fs/erofs/super.c index eb052a770088..6af02cc8b8c6 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -313,6 +313,8 @@ static int erofs_read_superblock(struct super_block *sb) sbi->packed_nid =3D le64_to_cpu(dsb->packed_nid); sbi->inos =3D le64_to_cpu(dsb->inos); =20 + sbi->ishare_key_start =3D le32_to_cpu(dsb->ishare_key_start); + sbi->build_time =3D le64_to_cpu(dsb->build_time); sbi->build_time_nsec =3D le32_to_cpu(dsb->build_time_nsec); =20 @@ -676,6 +678,8 @@ 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 7940241d9355..30a64ac3239a 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -549,3 +549,52 @@ 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; + ptr =3D erofs_read_metadata(sb, &buf, &pos, &len); + + if (IS_ERR(ptr)) { + erofs_put_metabuf(&buf); + return; + } + + for (i =3D 0; ARRAY_SIZE(erofs_xattr_handlers); i++) { + handler =3D erofs_xattr_handlers[i]; + if (!handler) + break; + if (!memcmp(handler->prefix, ptr, strlen(handler->prefix))) + break; + } + + if (!handler) + return; + + len -=3D strlen(handler->prefix); + key =3D kzalloc(len + 1, GFP_KERNEL); + if (!key) { + erofs_put_metabuf(&buf); + return; + } + + memcpy(key, ptr + strlen(handler->prefix), len); + sbi->ishare_key =3D key; + sbi->ishare_key_idx =3D handler->flags; + erofs_put_metabuf(&buf); +} +#endif diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index b246cd0e135e..24a243165417 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -70,4 +70,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.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out30-130.freemail.mail.aliyun.com (out30-130.freemail.mail.aliyun.com [115.124.30.130]) (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 22ED61E2307 for ; Sat, 1 Mar 2025 14:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840626; cv=none; b=RGNYSaej/dJvZmEtV1gHslYcS62yLBTiX0YIaOEqSjnR5lDtlmzfR/gSIiBCCYyti3+9iC1jTVxcqZyPiqXuntPkOejGr174nFmF57i+pUcDnyRrKO+v+zlyI5SAQZDkmUyaGOYnSWHb6qdyP0gK/ynoGv1XPi9eFI4IQ1qTAyo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840626; c=relaxed/simple; bh=tr7tF7qVsTRf8JeqGnQQFgvhRP/lf2ZGRgv+8ERwR9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b9xKfbNKtw1zhIilNwFua9o15epNr1YgZcQtogj02S5wwWdwyA4gkKE4gpxP6Px1WA2fFichmHQ2+6BfBSXratgqQlNXU+HECDfBuwBpR33HJMf+/+raNioLmRvmfiqGKWecq8p1vLttSZqX6YIgDjuJc6ZLsX2pyLSEwka6u1Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=L8iVrfac; arc=none smtp.client-ip=115.124.30.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="L8iVrfac" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840615; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=6USqGVcPTi586mkMaCckvU+yah8nBs9aiwe4n8Cy5OI=; b=L8iVrfac2JLdV8zk6cYlUXhwgxFiusr8wmaD5Ox+nLc0CFJ2R0HHcYffnHZjg3iXwaknQqSij5nFOXzrr7yFIZ6lTO07OdqalFGyJPClit7cOKmRkgsGhyVNYAqfEyxtd+D94RmdgPeSSAiW+vPKZfpSC161uVEFXqaXtC3KbVA= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSgWQj_1740840614 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:15 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 3/7] erofs: support domain-specific page cache share Date: Sat, 1 Mar 2025 22:49:40 +0800 Message-ID: <20250301145002.2420830-4-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 --- fs/erofs/super.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 6af02cc8b8c6..ceab0c29b061 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -489,6 +489,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); @@ -558,16 +560,16 @@ 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) super_set_sysfs_name_generic(sb, "%s", sbi->fsid); - else if (erofs_is_fileio_mode(sbi)) + else if (!sb->s_bdi || !sb->s_bdi->dev) + super_set_sysfs_name_id(sb); + else super_set_sysfs_name_generic(sb, "%s", bdi_dev_name(sb->s_bdi)); - else - super_set_sysfs_name_id(sb); } =20 static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *= fc) @@ -965,6 +967,8 @@ static int erofs_show_options(struct seq_file *seq, str= uct 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.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out30-111.freemail.mail.aliyun.com (out30-111.freemail.mail.aliyun.com [115.124.30.111]) (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 21D311DF986 for ; Sat, 1 Mar 2025 14:50:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.111 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840622; cv=none; b=TW3eK0sWY58ZEBFqUJQqkLvi1pHUFOUjYmJ3OYUinGV/fLQKv9IOu2NhzbvWxGqb6/ciW0MbfdoqRsRXO3lt5kVWgAKIIKgwcIDG7Mj/G0Cq1v8YIUeZKZEXWvnExlkx0OHJVNZxuwKSyiGSCepryRIPziihm7m0h+5tJoaPn/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840622; c=relaxed/simple; bh=GcT1npEXFlfJFpwqhqX2uE09mrFjzTY8f9+Xl4xRbkQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fwtL0tCd16/WWF3IT9zuSeJIBOidvqAGuYyDa1gAlPdZmnjUkIsw/OELBxBoACfdGF4Oe1u/4vu6qflDWchnPM6eDHg9niTkaEHyTSGQa5cMeCztcY16s3kIxNVwAfLmOAJG9ri9DA7pbZQbXngSx8K2mvgvJ+ORNPaiUJu6l1Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=fl4G5tdu; arc=none smtp.client-ip=115.124.30.111 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="fl4G5tdu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840616; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=wz9frzctN1J75p3iB2EhAvBmgsu+2wgIZcjjMDkmW/o=; b=fl4G5tduyYpplGZuyDIpuq0CEuzBMg1get/fGRjDFXQzOgboeTgKdw7AWVZuDXcRGtoAfLMzDMRlVPwQa4hwEFQBuddMeJ94TgP9EapOsnO9RTMuUpH9CJIwN77hw3QoMJCPrDQSRXg0UATVtbz9L95F6NDwHCD7HmJswNpzw0E= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSgWR0_1740840615 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:15 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 4/7] erofs: introduce the page cache share feature Date: Sat, 1 Mar 2025 22:49:41 +0800 Message-ID: <20250301145002.2420830-5-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 --- fs/erofs/Makefile | 1 + fs/erofs/internal.h | 17 ++++ fs/erofs/ishare.c | 238 ++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/ishare.h | 28 ++++++ fs/erofs/super.c | 28 +++++- 5 files changed, 311 insertions(+), 1 deletion(-) 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 4331d53c7109..2eb35bec8472 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -9,3 +9,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) +=3D decompressor_defl= ate.o erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) +=3D decompressor_zstd.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 diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 21bf9b694048..49613b257a6a 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -286,6 +286,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; }; @@ -382,6 +398,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..77786ec6834e --- /dev/null +++ b/fs/erofs/ishare.c @@ -0,0 +1,238 @@ +// 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; + + kfree(sbi->ishare_key); + + 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); +} + +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 *realinode, + struct file *realfile) +{ + struct file *file; + struct inode *inode; + + inode =3D EROFS_I(realinode)->ishare; + if (!inode) + return -EINVAL; + + file =3D alloc_file_pseudo(inode, erofs_ishare_mnt, "erofs_ishare_file", + O_RDONLY, &erofs_file_fops); + if (IS_ERR(file)) + return PTR_ERR(file); + + file_ra_state_init(&file->f_ra, realfile->f_mapping); + file->private_data =3D EROFS_I(realinode); + ihold(inode); + + realfile->private_data =3D file; + return 0; +} + +static int erofs_ishare_file_release(struct inode *inode, struct file *fil= e) +{ + if (!file->private_data) + return -EINVAL; + + fput((struct file *)file->private_data); + file->private_data =3D NULL; + return 0; +} + +static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb, + struct iov_iter *to) +{ + struct file *backing_file =3D iocb->ki_filp->private_data; + struct inode *inode =3D file_inode(iocb->ki_filp); + struct kiocb dedup_iocb; + ssize_t nread; + + 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)) + backing_file =3D iocb->ki_filp; + + kiocb_clone(&dedup_iocb, iocb, backing_file); + 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 *backing_file =3D file->private_data; + + if (!backing_file) + return -EINVAL; + + vma_set_file(vma, backing_file); + vma->vm_ops =3D &generic_file_vm_ops; + return 0; +} + +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 ceab0c29b061..98d8b58afe5e 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 @@ -857,9 +858,34 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 +#ifdef CONFIG_EROFS_FS_INODE_SHARE +static void erofs_free_dedup_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + kfree(vi->fingerprint); + kmem_cache_free(erofs_inode_cachep, vi); +}; +#else +#define erofs_free_dedup_inode NULL +#endif + +static const struct super_operations erofs_anon_sops =3D { + .statfs =3D simple_statfs, + .alloc_inode =3D erofs_alloc_inode, + .free_inode =3D erofs_free_dedup_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 { --=20 2.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out199-8.us.a.mail.aliyun.com (out199-8.us.a.mail.aliyun.com [47.90.199.8]) (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 8A6991E32D6 for ; Sat, 1 Mar 2025 14:50:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.199.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840639; cv=none; b=cKo9Voy3gFv3Tk2XDszLk65ysHGzI3WyEY9PaELUxNWIGksHlQbWNkeJdk18H/FOHGSiNJ8b4AM83pGb2QElAPu9oGijMg/xHfLLGvdgXQJY4ShSIuWx8bZM8KlcIa98A+LkBXKl42cgEcuu2mYEDMLuz/RlDLgpGk4zAEX601c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840639; c=relaxed/simple; bh=mxK1VEV63yXM+eWQmAv2I10cdt50ddHpXlE4bxsOE9Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PchEWyrBh/yCKSdl8s1Ny2Rvw/JNFDTXc5RWO5vvoICDRuHmBM2RwrBsXb0tWMLiVV3eBUidE5d3Wmo4cjsaJC0cjDlZR/CSKwgfMm1/KebOaaZ+OR9OwjuTD5AhL9hShlv45Kxgwyge8uLYWE6nKlTNkSKHffNr6JsUuo8E1Ac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=dBwZWNLz; arc=none smtp.client-ip=47.90.199.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="dBwZWNLz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840617; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=cEQ88iz4dOmNw4DeKVvc23lhQVA1B+Iv1dIwRL42kpM=; b=dBwZWNLzFjxOzux7d7yHh23P6buBwCeQ0bQXIqoLxFBIY3QMpq70dv0kfC4raPoI/LkwM6yhNzad+hYT2aJqEdGNNjFTrx6dDxzDbySOuCzZUU1iYtb0OOen1jyzs+Uh/BmHLdW25q0mvqkSJ3N1zmn6dxg3WRV9lcz30jBj7NM= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSgWRM_1740840616 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:16 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 5/7] erofs: support unencoded inodes for page cache share Date: Sat, 1 Mar 2025 22:49:42 +0800 Message-ID: <20250301145002.2420830-6-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 --- fs/erofs/data.c | 82 ++++++++++++++++++++++++++++++++++++++++---- fs/erofs/inode.c | 5 +++ fs/erofs/internal.h | 4 +++ fs/erofs/ishare.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/ishare.h | 27 +++++++++++++++ fs/erofs/super.c | 11 ++++++ 6 files changed, 205 insertions(+), 7 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 0cd6b5c4df98..b7d7e67832eb 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 @@ -267,18 +268,44 @@ void erofs_onlinefolio_end(struct folio *folio, int e= rr) folio_end_read(folio, !(v & 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; =20 - ret =3D erofs_map_blocks(inode, &map); + ret =3D erofs_map_blocks(realinode, &map); if (ret < 0) return ret; =20 @@ -297,7 +324,11 @@ static int erofs_iomap_begin(struct inode *inode, loff= _t offset, loff_t length, iomap->bdev =3D mdev.m_bdev; iomap->length =3D map.m_llen; iomap->flags =3D 0; - iomap->private =3D NULL; + + if (is_ishare) + erofs_iomap->base =3D NULL; + else + iomap->private =3D NULL; =20 if (!(map.m_flags & EROFS_MAP_MAPPED)) { iomap->type =3D IOMAP_HOLE; @@ -316,7 +347,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; iomap->addr =3D mdev.m_pa; @@ -329,7 +363,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 { @@ -342,6 +386,13 @@ 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 @@ -370,12 +421,29 @@ int erofs_fiemap(struct inode *inode, struct fiemap_e= xtent_info *fieinfo, */ static int erofs_read_folio(struct file *file, struct folio *folio) { - return iomap_read_folio(folio, &erofs_iomap_ops); + 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); + + return ret; } =20 static void erofs_readahead(struct readahead_control *rac) { - return iomap_readahead(rac, &erofs_iomap_ops); + 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); } =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 d4b89407822a..77893761d773 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 =20 static int erofs_fill_symlink(struct inode *inode, void *kaddr, @@ -216,6 +217,10 @@ static int erofs_fill_inode(struct inode *inode) inode->i_fop =3D &generic_ro_fops; else 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 49613b257a6a..d736e4b57701 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -294,11 +294,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 77786ec6834e..e68bb1a6cf4b 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); @@ -236,3 +239,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_real, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi_real =3D rdctx->file->private_data; + vi_dedup =3D EROFS_I(file_inode(rdctx->file)); + + spin_lock(&vi_dedup->lock); + if (!list_empty(&vi_real->processing_link)) { + atomic_inc(&vi_real->processing_count); + } else { + list_add(&vi_real->processing_link, + &vi_dedup->processing_head); + atomic_set(&vi_real->processing_count, 1); + } + spin_unlock(&vi_dedup->lock); +} + +void erofs_read_end(struct erofs_read_ctx *rdctx) +{ + struct erofs_inode *vi_real, *vi_dedup; + + if (!rdctx->file || !erofs_is_ishare_inode(rdctx->inode)) + return; + + vi_real =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_real->processing_count)) + list_del_init(&vi_real->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_real, *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_real, &vi_dedup->processing_head, + processing_link) { + realinode =3D igrab(&vi_real->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_real, &vi_dedup->backing_head, backing_link) { + realinode =3D igrab(&vi_real->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..a0ff9403511b 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,20 @@ 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 +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; +} + +/* 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 +42,14 @@ 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 bool erofs_is_ishare_inode(struct inode *inode) { return fal= se; } + +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 98d8b58afe5e..64ef5c78fedd 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -82,6 +82,7 @@ static void erofs_free_inode(struct inode *inode) { struct erofs_inode *vi =3D EROFS_I(inode); =20 + erofs_ishare_free_inode(inode); if (inode->i_op =3D=3D &erofs_fast_symlink_iops) kfree(inode->i_link); kfree(vi->xattr_shared_xattrs); @@ -688,6 +689,12 @@ static int erofs_fc_fill_super(struct super_block *sb,= struct fs_context *fc) if (err) return err; =20 + if (sbi->ishare_key) { + err =3D erofs_ishare_init(sb); + if (err) + return err; + } + erofs_info(sb, "mounted with root inode @ nid %llu.", sbi->root_nid); return 0; } @@ -823,6 +830,10 @@ static void erofs_kill_sb(struct super_block *sb) kill_anon_super(sb); else kill_block_super(sb); + + if (sbi->ishare_key) + erofs_ishare_exit(sb); + fs_put_dax(sbi->dif0.dax_dev, NULL); erofs_fscache_unregister_fs(sb); erofs_sb_free(sbi); --=20 2.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out30-131.freemail.mail.aliyun.com (out30-131.freemail.mail.aliyun.com [115.124.30.131]) (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 1BD5B1E3769 for ; Sat, 1 Mar 2025 14:50:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840628; cv=none; b=S1QGCDoLVprwECdLiZI7svjhysu7nvjssR8ZiOwT7HTm05c5xU5EaH+Yw81kQ0l935Qs91rKpUOQKj0QvEB07kFc0FvSp5KGw+crW685Mm/4l3b6RGvWCN7M/be1Pf8oeVkfZzqXBHUC+/ucm3GnIEeDTxGTy+NbKTtA58aP3JY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840628; c=relaxed/simple; bh=TXe/AJi4P0405t0Nn8ub1Nz6aLbMsSePOpe5bgKwALs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F4hsZxitiPyIuJbawB8XeGFpSXle/Du4K6Ku62J455XdQs6O358sMkHY5vE+b2QSY+eUw/IQQnTDHup3Yfyf6FGdDn8vQvz/fOqdsv96oJj8d87Mc37vs1wLG64DCg+h4LZwie4Sm81dm/EvVhcWdMsQLEQuel9doZgoOxrPBKg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=B5F3CPmV; arc=none smtp.client-ip=115.124.30.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="B5F3CPmV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840618; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=LsN4AVILIAF5l64ooZXWfDVtzbln1b/ogW51HXy4MRg=; b=B5F3CPmVrptC4nafYB2La266UwPWmytf4kxNsaAjWBilVE27yjdkNVnfio9nxU+FzaP8WO+ibfoCofF3eNaLecfhN1Sei7ysc74u1rbmQLtxn9Tj4I4Y/A/GZ3OSmRlqC4P3leG5cLJPdHKHugbp4AB41YoXKmsKmH7QsCuvKj8= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSfpYr_1740840617 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:17 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 6/7] erofs: support compressed inodes for page cache share Date: Sat, 1 Mar 2025 22:49:43 +0800 Message-ID: <20250301145002.2420830-7-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" This patch adds page cache sharing functionality for compressed inodes. Signed-off-by: Hongzhen Luo --- fs/erofs/zdata.c | 57 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index aff09f94afb2..b6383cb26acb 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 @@ -474,7 +475,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 @@ -1835,11 +1836,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; z_erofs_pcluster_readmore(&f, NULL, true); err =3D z_erofs_scan_folio(&f, folio, false); z_erofs_pcluster_readmore(&f, NULL, false); @@ -1848,25 +1862,43 @@ 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)); struct folio *head =3D NULL, *folio; unsigned int nrpages =3D readahead_count(rac); + struct erofs_read_ctx rdctx =3D { + .file =3D rac->file, + .inode =3D inode, + }; int err; =20 + erofs_read_begin(&rdctx); + + if (erofs_is_ishare_inode(inode)) + realinode =3D erofs_ishare_iget(inode); + else + realinode =3D inode; + + f.inode =3D realinode; z_erofs_pcluster_readmore(&f, rac, true); nrpages =3D readahead_count(rac); - trace_erofs_readpages(inode, readahead_index(rac), nrpages, false); + trace_erofs_readpages(realinode, readahead_index(rac), nrpages, false); while ((folio =3D readahead_folio(rac))) { folio->private =3D head; head =3D folio; @@ -1879,8 +1911,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); @@ -1888,6 +1920,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.43.5 From nobody Sun Feb 8 09:10:57 2026 Received: from out30-100.freemail.mail.aliyun.com (out30-100.freemail.mail.aliyun.com [115.124.30.100]) (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 3896C1E47A9 for ; Sat, 1 Mar 2025 14:50:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.100 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840630; cv=none; b=RKLRh2afgpRw1m4atXZQfbp/VogrxSkyeCh/RO5ap3e9mWms5A9UTHaTO6/Vde7R9yLSI+yDeQvcRgfX06w/nPjsJZG/szgKO2ZkuAcsUqftXQffxuF0hqzXUwK6Fd6jNZmn8v5GWT7N5mGuBMjtUhEkqr6K0iZf6Fzkr645OqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740840630; c=relaxed/simple; bh=SjANaxWCmJNj7oi93bssrFLPFZbesMUZ2Sr1VspqT/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u4KkgjrwggwV5kT40sJgCwFz3XhgH1JHW0BVAnIoWRtIHZORs/17Kk0sbtc2jy4LDhJ/91kYJJ3wNUA8KWDDcGJXfco4UXo9hdjfMMSXirhMGr8XnmcF3Ukj82ia4wAUwVsfBnPaAnE5naZMjDcsgqRvy2SvShQlD+6S+2OHjEo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=vP3RPgHM; arc=none smtp.client-ip=115.124.30.100 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="vP3RPgHM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1740840618; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=BOTXNFCiusEeI6Bv6xOR/ZPHNnysL9qJrOFxRXLReDE=; b=vP3RPgHMSzIAPHz8aTu6ZjY4xUOztAbZMm80vDbi1CkVUidoqg9QC/s1ISypt+VU7ysizTTesi3TmMc/+pF68NoyAtu931nagBseUxS4yLk5D/PW+/oBa+pSr8i2GMf/0xz481pR+RosnNEr47DOZOHNNcj7HuqT9IaUQeuclz4= Received: from localhost(mailfrom:hongzhen@linux.alibaba.com fp:SMTPD_---0WQSjMs._1740840617 cluster:ay36) by smtp.aliyun-inc.com; Sat, 01 Mar 2025 22:50:18 +0800 From: Hongzhen Luo To: linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, Hongzhen Luo Subject: [RFC PATCH v6 7/7] erofs: implement .fadvise for page cache share Date: Sat, 1 Mar 2025 22:49:44 +0800 Message-ID: <20250301145002.2420830-8-hongzhen@linux.alibaba.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250301145002.2420830-1-hongzhen@linux.alibaba.com> References: <20250301145002.2420830-1-hongzhen@linux.alibaba.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 Content-Type: text/plain; charset="utf-8" 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 --- fs/erofs/ishare.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index e68bb1a6cf4b..a7c2be5d6f25 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -230,6 +230,14 @@ static int erofs_ishare_mmap(struct file *file, struct= vm_area_struct *vma) return 0; } =20 +static int erofs_ishare_fadvice(struct file *realfile, loff_t offset, loff= _t len, + int advice) +{ + struct file *file =3D realfile->private_data; + + return vfs_fadvise(file, offset, len, advice); +} + const struct file_operations erofs_ishare_fops =3D { .open =3D erofs_ishare_file_open, .llseek =3D generic_file_llseek, @@ -238,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.43.5