From nobody Sun Feb 8 21:49:10 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (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 676052D8771; Fri, 23 Jan 2026 01:45:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132741; cv=none; b=VCJmXzLnvsRWD2uFUpBIIwexqSTyxkk8YNCJMqIosB/CTH3BZEj4Um2Fn4dt9mI7zlXyrWnObhj8PNOwgGRqTQYjarW8tAt0HFypKpZhrmziENJMT46Qk69N0oshwB0MHdY+7+luOpLLdfy8/bLGC4JqrycAyN+Y3h8rgJ6brmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132741; c=relaxed/simple; bh=/DOP628ou57Yld7gMP4kYmxmunqIn78QOq3XPXhRUAY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NPBlNzVkfvwpGSwkKMlUj2JfG28zAZbyiywRiQxRRNmh+InxihJGNUbCQlslTfxbHQJB9m4ko2zIqIqE8AmXZhKjcd/TXbWARWelLEz9DrNeX7kYNpdsSRSqlyR16cqT3bSxO/YsAfLQLCj/cj2i7BzuYPlA1e5vMPY9oS+MVHw= 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=aViTVgKb; arc=none smtp.client-ip=113.46.200.216 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="aViTVgKb" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=IJqOVDMyH2cU6HZaQ6KGaq7L7r7sGB/NU+oSMo68sYk=; b=aViTVgKbU3p9F6fvfb/DRZ9GIhljQ3rKlHQMPA1II5YccTLm1l79Wl8RBcmkkhYNwMzHKxXz0 9YV1Y0ow6kq2fONT0jz7uycW8blnvYaMxZYGGACdFOLs9cXkvJ3tWcEIwXSiiP4I/798eIXtO+j kCdEQvGGYPkM65v8oi6/oqU= Received: from mail.maildlp.com (unknown [172.19.162.144]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4dy0yJ3SK4z1T4HP; Fri, 23 Jan 2026 09:41:12 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 8077140567; Fri, 23 Jan 2026 09:45:17 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:16 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 01/10] fs: Export alloc_empty_backing_file Date: Fri, 23 Jan 2026 01:31:23 +0000 Message-ID: <20260123013132.662393-2-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" There is no need to open nonexistent real files if backing files couldn't be backed by real files (e.g., EROFS page cache sharing doesn't need typical real files to open again). Therefore, we export the alloc_empty_backing_file() helper, allowing filesystems to dynamically set the backing file without real file open. This is particularly useful for obtaining the correct @path and @inode when calling file_user_path() and file_user_inode(). Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang Acked-by: Amir Goldstein --- fs/file_table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/file_table.c b/fs/file_table.c index cd4a3db4659a..476edfe7d8f5 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -308,6 +308,7 @@ struct file *alloc_empty_backing_file(int flags, const = struct cred *cred) ff->file.f_mode |=3D FMODE_BACKING | FMODE_NOACCOUNT; return &ff->file; } +EXPORT_SYMBOL_GPL(alloc_empty_backing_file); =20 /** * file_init_path - initialize a 'struct file' based on path --=20 2.22.0 From nobody Sun Feb 8 21:49:10 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (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 A7C193559CB; Fri, 23 Jan 2026 01:45:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132733; cv=none; b=bh8htnFRqqZ3GgCjZM2ozou0mvv0vzKzGnEfFlW9ThbwuM83PgNi6PvEyeFWUHvJpq414HYXHcBQNsrbo7fQv3Q7jEK+f3ztlXav6k35pheHnRXfknta0YqIi4Kusx2Fn3Ic08MYvQhs997WTiuYKzctkPozMG/D+IvOXukekNo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132733; c=relaxed/simple; bh=bLPyX55goz9UpKyTSsH/rsQVx9Lcd+68NmlbcIC2gHs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YQndiY39Bu9HRJ/95ykxy9GHsTsqqVC3jMpB7MY/wT5tICT16cJlkkdL5BIB8X+6hjccSm4TmFN0u1EeCdP5RhxjMfRsrERTqcJJCutKFS4tlFTdhPIW0jKiEVLUksmaMp2K+RlxyI1JIzTMplL3umE38bA4GjVOP0e2FKxqBpY= 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=oJbF4d0t; arc=none smtp.client-ip=113.46.200.218 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="oJbF4d0t" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=otZzmT6rxktVNDVECk5mC06H07hAnwXYZ9UJTBeZ2EE=; b=oJbF4d0t5wRl+Q3D2MEG1XxQ46Sws4p95wCVOUDW01xFXaHTtZLIuDaU1CGP+FYnhHWI9gyc+ vl1DpAL3wOTCohN8rpHMh58gcD4/VUG36UAoqVqtLr4Wg1E8jI9n820W4N+o3Weae21OVDrRQCJ RiDve7yi5NEMgQAYQ4IAnOc= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4dy0yd2dPfzpStB; Fri, 23 Jan 2026 09:41:29 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id EBA8C40537; Fri, 23 Jan 2026 09:45:17 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:17 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 02/10] erofs: decouple `struct erofs_anon_fs_type` Date: Fri, 23 Jan 2026 01:31:24 +0000 Message-ID: <20260123013132.662393-3-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" From: Gao Xiang - Move the `struct erofs_anon_fs_type` to super.c and expose it in preparation for the upcoming page cache share feature; - Remove the `.owner` field, as they are all internal mounts and fully managed by EROFS. Retaining `.owner` would unnecessarily increment module reference counts, preventing the EROFS kernel module from being unloaded. Signed-off-by: Gao Xiang --- fs/erofs/fscache.c | 13 ------------- fs/erofs/internal.h | 2 ++ fs/erofs/super.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 7a346e20f7b7..f4937b025038 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..98fe652aea33 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -188,6 +188,8 @@ static inline bool erofs_is_fileio_mode(struct erofs_sb= _info *sbi) return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file; } =20 +extern struct file_system_type erofs_anon_fs_type; + static inline bool erofs_is_fscache_mode(struct super_block *sb) { return IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 937a215f626c..f18f43b78fca 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 @@ -936,6 +937,19 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 +#if defined(CONFIG_EROFS_FS_ONDEMAND) +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 { + .name =3D "pseudo_erofs", + .init_fs_context =3D erofs_anon_init_fs_context, + .kill_sb =3D kill_anon_super, +}; +#endif + static int __init erofs_module_init(void) { int err; --=20 2.22.0 From nobody Sun Feb 8 21:49:10 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 230333016E2; Fri, 23 Jan 2026 01:45:22 +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=1769132737; cv=none; b=qL1ZSTGhdrvyn50jebV2kqimYvSuWL8lfqgpcdcWmp7D8ZDAj8HPvwn8ID6MVPzDauFj23wO+pT8Dcncm3HZ2SJIiItKBzUoL5gl2XLKPu2Jactq29h2+hLvghnMXBSPMjoFnTJO+tjqYNgpgcVO1ZQLtDyM0qXP0iS8YrNELic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132737; c=relaxed/simple; bh=hjtjZM+/G2TpOF1N0I5N/LIijanDvM1LsENzKcdgQcE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JugxK4/MX7JbtaAJuwl0gQ4PSafX4MYSGDTrkN/JuidGdXeAKkaiu+hdvgUeugxNN+epJZso3LAecmjFY9Vx6KtxeBo2giCfK5YyplzuPw8GES1iUj3sEFxEo0KZKjgC/6jwoR7RA4k4AJoe50V2P6k6RFx6xrOeaX5qL19N31w= 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=VpLGGUGK; 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="VpLGGUGK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=R7ApHnfNiBchhGXf8a8E/bOiMkaOH3q7V/YSP7S/uow=; b=VpLGGUGK+sRa0H7ow0v8gH347fWJZpEHkyBZ3bykf3XfoVbM3NPW+A+CBiyS787GwG0uZeAsy ruololEhaWwkPw29RrTxowpDFgVzkkLk4xJ2sTZwI9Q4ua+/fGcOQsKa6W7kUNaxDZdizCESOW3 zJu9mBU9EfwJBzx/UWj/eLE= Received: from mail.maildlp.com (unknown [172.19.162.92]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z62FyzzLlTR; Fri, 23 Jan 2026 09:41:54 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 71CB540565; Fri, 23 Jan 2026 09:45:18 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:17 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 03/10] erofs: support user-defined fingerprint name Date: Fri, 23 Jan 2026 01:31:25 +0000 Message-ID: <20260123013132.662393-4-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) 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 Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/Kconfig | 9 +++++++++ fs/erofs/erofs_fs.h | 5 +++-- fs/erofs/internal.h | 2 ++ fs/erofs/super.c | 9 +++++++++ fs/erofs/xattr.c | 13 +++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index d81f3318417d..b71f2a8074fe 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -194,3 +194,12 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI at higher priority. =20 If unsure, say N. + +config EROFS_FS_PAGE_CACHE_SHARE + bool "EROFS page cache share support (experimental)" + depends on EROFS_FS && EROFS_FS_XATTR && !EROFS_FS_ONDEMAND + help + This enables page cache sharing among inodes with identical + content fingerprints on the same machine. + + If unsure, say N. diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index e24268acdd62..b30a74d307c5 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -17,7 +17,7 @@ #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 #define EROFS_FEATURE_COMPAT_SHARED_EA_IN_METABOX 0x00000008 #define EROFS_FEATURE_COMPAT_PLAIN_XATTR_PFX 0x00000010 - +#define EROFS_FEATURE_COMPAT_ISHARE_XATTRS 0x00000020 =20 /* * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should @@ -83,7 +83,8 @@ struct erofs_super_block { __le32 xattr_prefix_start; /* start of long xattr prefixes */ __le64 packed_nid; /* nid of the special packed inode */ __u8 xattr_filter_reserved; /* reserved for xattr name filter */ - __u8 reserved[3]; + __u8 ishare_xattr_prefix_id; + __u8 reserved[2]; __le32 build_time; /* seconds added to epoch for mkfs time */ __le64 rootnid_8b; /* (48BIT on) nid of root directory */ __le64 reserved2; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 98fe652aea33..ec79e8b44d3b 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -134,6 +134,7 @@ struct erofs_sb_info { u32 xattr_blkaddr; u32 xattr_prefix_start; u8 xattr_prefix_count; + u8 ishare_xattr_prefix_id; struct erofs_xattr_prefix_item *xattr_prefixes; unsigned int xattr_filter_reserved; #endif @@ -238,6 +239,7 @@ 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) EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX) +EROFS_FEATURE_FUNCS(ishare_xattrs, compat, COMPAT_ISHARE_XATTRS) =20 static inline u64 erofs_nid_to_ino64(struct erofs_sb_info *sbi, erofs_nid_= t nid) { diff --git a/fs/erofs/super.c b/fs/erofs/super.c index f18f43b78fca..dca1445f6c92 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -320,6 +320,15 @@ static int erofs_read_superblock(struct super_block *s= b) sbi->xattr_prefix_start =3D le32_to_cpu(dsb->xattr_prefix_start); sbi->xattr_prefix_count =3D dsb->xattr_prefix_count; sbi->xattr_filter_reserved =3D dsb->xattr_filter_reserved; + if (erofs_sb_has_ishare_xattrs(sbi)) { + if (dsb->ishare_xattr_prefix_id >=3D sbi->xattr_prefix_count) { + erofs_err(sb, "invalid ishare xattr prefix id %u", + dsb->ishare_xattr_prefix_id); + ret =3D -EFSCORRUPTED; + goto out; + } + sbi->ishare_xattr_prefix_id =3D dsb->ishare_xattr_prefix_id; + } #endif sbi->islotbits =3D ilog2(sizeof(struct erofs_inode_compact)); if (erofs_sb_has_48bit(sbi) && dsb->rootnid_8b) { diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 396536d9a862..ae61f20cb861 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -519,6 +519,19 @@ int erofs_xattr_prefixes_init(struct super_block *sb) } =20 erofs_put_metabuf(&buf); + if (!ret && erofs_sb_has_ishare_xattrs(sbi)) { + struct erofs_xattr_prefix_item *pf =3D pfs + sbi->ishare_xattr_prefix_id; + struct erofs_xattr_long_prefix *newpfx; + + newpfx =3D krealloc(pf->prefix, + sizeof(*newpfx) + pf->infix_len + 1, GFP_KERNEL); + if (newpfx) { + newpfx->infix[pf->infix_len] =3D '\0'; + pf->prefix =3D newpfx; + } else { + ret =3D -ENOMEM; + } + } sbi->xattr_prefixes =3D pfs; if (ret) erofs_xattr_prefixes_cleanup(sb); --=20 2.22.0 From nobody Sun Feb 8 21:49:10 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 10D163148A1; Fri, 23 Jan 2026 01:45:26 +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=1769132742; cv=none; b=E4Y8axullE+XQ7+eknivPDsCIbMpfI4XJPHnJdOXr+sOXrxAzWgJYx2o06Tw8lynP1cGqZnOw9qW74S0QWOeSFshjh6Lp5osfytyJ/MESMPvWX+pnhJGj5vh+zOqyatAEr6OmxQvZ0upFlltYzRmT8qC4xOsrWyfcSIaI+7uwU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132742; c=relaxed/simple; bh=x6fUikO0R/nUdmFtuYDUi+dRxJEe5v8ULG3T99qF5t8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bT2yOicXY/UZgt7tSCK8UhvonyzlHyrvGpzHbCRoyogZcnp3tlyd699l824y8yTRGmVHWYo83UivbKctzjYeQk268EyO8A4fse4L8P61NhLC3YVg1Go/7IhDdR1UohIJmREH9rGvfwgAVqo6XmcNoqTH1X38Mfwo1Dm+Xc1UZkg= 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=PyrjXgwh; 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="PyrjXgwh" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=X2tclZhWoOBbnPRpt4KYODEDqulzqggXkTbvFvdkSDc=; b=PyrjXgwh3oeFedO0IZtiBPyXTRCGepZB/sHrUDQu8DHUBA6xjpY+IVm3leGntWEF0yQjfuM1C GOAOihZk5rhBq+iw2hEYiXh6p0G/2Az2gHnlqpjZicpx93dMKt+9VH7fQzQh6iFEItYHkqFoA4+ lN2IHN+tl9MPpZRn3IFFDcQ= Received: from mail.maildlp.com (unknown [172.19.162.223]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4dy0yT3s6fz12LD8; Fri, 23 Jan 2026 09:41:21 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id E0DB340569; Fri, 23 Jan 2026 09:45:18 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:18 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 04/10] erofs: add erofs_inode_set_aops helper to set the aops Date: Fri, 23 Jan 2026 01:31:26 +0000 Message-ID: <20260123013132.662393-5-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" Add erofs_inode_set_aops helper to set the inode->i_mapping->a_ops to make it cleaner. Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/inode.c | 24 +----------------------- fs/erofs/internal.h | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index bce98c845a18..202cbbb4eada 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -203,7 +203,6 @@ static int erofs_read_inode(struct inode *inode) =20 static int erofs_fill_inode(struct inode *inode) { - struct erofs_inode *vi =3D EROFS_I(inode); int err; =20 trace_erofs_fill_inode(inode); @@ -235,28 +234,7 @@ static int erofs_fill_inode(struct inode *inode) } =20 mapping_set_large_folios(inode->i_mapping); - if (erofs_inode_is_data_compressed(vi->datalayout)) { -#ifdef CONFIG_EROFS_FS_ZIP - DO_ONCE_LITE_IF(inode->i_blkbits !=3D PAGE_SHIFT, - erofs_info, inode->i_sb, - "EXPERIMENTAL EROFS subpage compressed block support in use. Use at y= our own risk!"); - inode->i_mapping->a_ops =3D &z_erofs_aops; -#else - err =3D -EOPNOTSUPP; -#endif - } else { - inode->i_mapping->a_ops =3D &erofs_aops; -#ifdef CONFIG_EROFS_FS_ONDEMAND - if (erofs_is_fscache_mode(inode->i_sb)) - inode->i_mapping->a_ops =3D &erofs_fscache_access_aops; -#endif -#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE - if (erofs_is_fileio_mode(EROFS_SB(inode->i_sb))) - inode->i_mapping->a_ops =3D &erofs_fileio_aops; -#endif - } - - return err; + return erofs_inode_set_aops(inode, inode, false); } =20 /* diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index ec79e8b44d3b..13b66564057a 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -455,6 +455,32 @@ static inline void *erofs_vm_map_ram(struct page **pag= es, unsigned int count) return NULL; } =20 +static inline int erofs_inode_set_aops(struct inode *inode, + struct inode *realinode, bool no_fscache) +{ + if (erofs_inode_is_data_compressed(EROFS_I(realinode)->datalayout)) { +#ifdef CONFIG_EROFS_FS_ZIP + DO_ONCE_LITE_IF(realinode->i_blkbits !=3D PAGE_SHIFT, + erofs_info, realinode->i_sb, + "EXPERIMENTAL EROFS subpage compressed block support in use. Use at y= our own risk!"); + inode->i_mapping->a_ops =3D &z_erofs_aops; +#else + return -EOPNOTSUPP; +#endif + } else { + inode->i_mapping->a_ops =3D &erofs_aops; +#ifdef CONFIG_EROFS_FS_ONDEMAND + if (!no_fscache && erofs_is_fscache_mode(realinode->i_sb)) + inode->i_mapping->a_ops =3D &erofs_fscache_access_aops; +#endif +#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE + if (erofs_is_fileio_mode(EROFS_SB(realinode->i_sb))) + inode->i_mapping->a_ops =3D &erofs_fileio_aops; +#endif + } + return 0; +} + int erofs_register_sysfs(struct super_block *sb); void erofs_unregister_sysfs(struct super_block *sb); int __init erofs_init_sysfs(void); --=20 2.22.0 From nobody Sun Feb 8 21:49:10 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (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 D62142DA75F; Fri, 23 Jan 2026 01:45:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132736; cv=none; b=mrBEE0JJFI4rjlysZy07VeZEQt/q6AYODdWb7ka+iSBmwzfamEsaGZMUZk5viaA36QBW5bpKRVQprXM7QxUPqQeVqAgumWoVR8CpKp6hJGHw0hhog9j0NUJ5A4q5/PlawT+6L7CM1I8um53p3XU3a9QruV41b9GWkpVp1BvmvLk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132736; c=relaxed/simple; bh=i4IxHS9vd+Y/yVMGn6Su/zXk268XgHWFKwcAj1dzo2s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QwKVHlNElUrv3n7pHIL/jbDSeNamq5brCV+e1QiFRbP6QqtCeBKPY3b4yl70Z65infvNjNNDh+a84tGSynLZh9zmZpynlXeaWwLm2HJi8PvlcZkpnkgIE80rrCi6aOcYP6QGGBwivQGvC2KQeawkbLQZa/772SAdKiMJK24Wtsw= 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=rutdvmdo; arc=none smtp.client-ip=113.46.200.224 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="rutdvmdo" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=MM8TsauSDpoIZ20LujoMlgVoP0k5Dxv+caeL1MPk8ho=; b=rutdvmdomAR7xcskRUZYp3W4+DpdvSHcbEvxC0n6cYxBOvYi8DdsB+Mv6VegqAuIzwUdmlfSH Z5lCKFfzVfvavsiloG3x2Lkhs22Gvq8CZrXXGGdKdR/gGpoE0U2liT37sPH2VopWIzpFle0IpQK rF5JNX/CctceFbwK/e+UpQw= Received: from mail.maildlp.com (unknown [172.19.163.15]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z716Prz1cySK; Fri, 23 Jan 2026 09:41:55 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 6AD1B40565; Fri, 23 Jan 2026 09:45:19 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:18 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 05/10] erofs: using domain_id in the safer way Date: Fri, 23 Jan 2026 01:31:27 +0000 Message-ID: <20260123013132.662393-6-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" Either the existing fscache usecase or the upcoming page cache sharing case, the `domain_id` should be protected as sensitive information, so we use the safer helpers to allocate, free and display domain_id. Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- Documentation/filesystems/erofs.rst | 5 +++-- fs/erofs/fscache.c | 4 ++-- fs/erofs/super.c | 10 ++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystem= s/erofs.rst index 08194f194b94..40dbf3b6a35f 100644 --- a/Documentation/filesystems/erofs.rst +++ b/Documentation/filesystems/erofs.rst @@ -126,8 +126,9 @@ dax=3D{always,never} Use direct access (no page cac= he). See dax A legacy option which is an alias for ``dax=3Dalway= s``. device=3D%s Specify a path to an extra device to be used toge= ther. fsid=3D%s Specify a filesystem image ID for Fscache back-en= d. -domain_id=3D%s Specify a domain ID in fscache mode so that diffe= rent images - with the same blobs under a given domain ID can sha= re storage. +domain_id=3D%s Specify a trusted domain ID for fscache mode so t= hat + different images with the same blobs, identified by= blob IDs, + can share storage within the same trusted domain. fsoffset=3D%llu Specify block-aligned filesystem offset for the p= rimary device. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index f4937b025038..a2cc0f3fa9d0 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -379,7 +379,7 @@ static void erofs_fscache_domain_put(struct erofs_domai= n *domain) } fscache_relinquish_volume(domain->volume, NULL, false); mutex_unlock(&erofs_domain_list_lock); - kfree(domain->domain_id); + kfree_sensitive(domain->domain_id); kfree(domain); return; } @@ -446,7 +446,7 @@ static int erofs_fscache_init_domain(struct super_block= *sb) sbi->domain =3D domain; return 0; out: - kfree(domain->domain_id); + kfree_sensitive(domain->domain_id); kfree(domain); return err; } diff --git a/fs/erofs/super.c b/fs/erofs/super.c index dca1445f6c92..38be26ba04bb 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -525,10 +525,8 @@ static int erofs_fc_parse_param(struct fs_context *fc, return -ENOMEM; break; case Opt_domain_id: - kfree(sbi->domain_id); - sbi->domain_id =3D kstrdup(param->string, GFP_KERNEL); - if (!sbi->domain_id) - return -ENOMEM; + kfree_sensitive(sbi->domain_id); + sbi->domain_id =3D no_free_ptr(param->string); break; #else case Opt_fsid: @@ -624,7 +622,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->fsid) super_set_sysfs_name_generic(sb, "%s,%s", sbi->domain_id, sbi->fsid); else if (sbi->fsid) @@ -852,7 +850,7 @@ static void erofs_sb_free(struct erofs_sb_info *sbi) { erofs_free_dev_context(sbi->devs); kfree(sbi->fsid); - kfree(sbi->domain_id); + kfree_sensitive(sbi->domain_id); if (sbi->dif0.file) fput(sbi->dif0.file); kfree(sbi->volume_name); --=20 2.22.0 From nobody Sun Feb 8 21:49:10 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 25C9E29BDAE; Fri, 23 Jan 2026 01:45:24 +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=1769132765; cv=none; b=XmRzOpseuALMlyPZofYAm8EbliiQ/ZM/IRb/FWNtkd/i7ui4ujsTssSEz+Hgv2iyMQp7a64eODfw2p3dtz8FyPGc9QSfLdd0ECQ31MPs7T0j/oO43D/YdkA6pb3TfOiIdAzU/yFlcWoizwGTFZ09Fbai7qAxhs7IhxPak3bV0IA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132765; c=relaxed/simple; bh=amProFxf4hcdCctbuNsN8PvheDKEN2Yqp+G83sF1sQU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=owv79RWVFZc147eXV+TVuBBpyyPIkpa1RQoVeTCJecmVVC4D8ZnxrZji9KAg3Z0IrokfdVlOQadvP2ILg8Qg9SkvrZaEhtdHqkdlHTVCUbJHG4hjgXequ1RbQE+OVCUGf6hEipR0FZm4JT1zriMmXrCB7vFzaODB1HItu1DjYaM= 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=exmPKAde; 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="exmPKAde" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=UjeT3fm9zONbZtDo72ghMNrf17/7VcqNTDBxWhwyAtI=; b=exmPKAdez97v2M7yCw50H/4IJyl/Mv6pSIhGl+Px0k0xao3AQz9zwgQhAWhxX7J5NMKeXg3ZH 4aCpOEiVWA9OG76y6AxHawn61tfCaXZhpnvC3RA/zz1T3CCFOwiLpqqhRyPGwcppvgpCFh4HSMe vdMhCE0pVCQyA0C8fo5dyQI= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4dy0yR4Tckzcb1l; Fri, 23 Jan 2026 09:41:19 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id D70C24056E; Fri, 23 Jan 2026 09:45:19 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:19 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 06/10] erofs: introduce the page cache share feature Date: Fri, 23 Jan 2026 01:31:28 +0000 Message-ID: <20260123013132.662393-7-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) 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 shared inode and use its page cache as shared. Reads for files with identical content will ultimately be routed to the page cache of the shared inode. In this way, a single page cache satisfies multiple read requests for different files with the same contents. We introduce new mount option `inode_share` to enable the page sharing mode during mounting. This option is used in conjunction with `domain_id` to share the page cache within the same trusted domain. Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- Documentation/filesystems/erofs.rst | 5 + fs/erofs/Makefile | 1 + fs/erofs/internal.h | 31 ++++++ fs/erofs/ishare.c | 167 ++++++++++++++++++++++++++++ fs/erofs/super.c | 62 ++++++++++- fs/erofs/xattr.c | 34 ++++++ fs/erofs/xattr.h | 3 + 7 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 fs/erofs/ishare.c diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystem= s/erofs.rst index 40dbf3b6a35f..bfef8e87f299 100644 --- a/Documentation/filesystems/erofs.rst +++ b/Documentation/filesystems/erofs.rst @@ -129,7 +129,12 @@ fsid=3D%s Specify a filesystem image ID= for Fscache back-end. domain_id=3D%s Specify a trusted domain ID for fscache mode so t= hat different images with the same blobs, identified by= blob IDs, can share storage within the same trusted domain. + Also used for different filesystems with inode page= sharing + enabled to share page cache within the trusted doma= in. fsoffset=3D%llu Specify block-aligned filesystem offset for the p= rimary device. +inode_share Enable inode page sharing for this filesystem. Ino= des with + identical content within the same domain ID can sha= re the + page cache. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 Sysfs Entries diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 549abc424763..a80e1762b607 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_PAGE_CACHE_SHARE) +=3D ishare.o diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 13b66564057a..15945e3308b8 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -179,6 +179,7 @@ struct erofs_sb_info { #define EROFS_MOUNT_DAX_ALWAYS 0x00000040 #define EROFS_MOUNT_DAX_NEVER 0x00000080 #define EROFS_MOUNT_DIRECT_IO 0x00000100 +#define EROFS_MOUNT_INODE_SHARE 0x00000200 =20 #define clear_opt(opt, option) ((opt)->mount_opt &=3D ~EROFS_MOUNT_##optio= n) #define set_opt(opt, option) ((opt)->mount_opt |=3D EROFS_MOUNT_##option) @@ -269,6 +270,11 @@ static inline u64 erofs_nid_to_ino64(struct erofs_sb_i= nfo *sbi, erofs_nid_t nid) /* default readahead size of directories */ #define EROFS_DIR_RA_BYTES 16384 =20 +struct erofs_inode_fingerprint { + u8 *opaque; + int size; +}; + struct erofs_inode { erofs_nid_t nid; =20 @@ -304,6 +310,18 @@ struct erofs_inode { }; #endif /* CONFIG_EROFS_FS_ZIP */ }; +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + struct list_head ishare_list; + union { + /* for each anon shared inode */ + struct { + struct erofs_inode_fingerprint fingerprint; + spinlock_t ishare_lock; + }; + /* for each real inode */ + struct inode *sharedinode; + }; +#endif /* the corresponding vfs inode */ struct inode vfs_inode; }; @@ -410,6 +428,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 @@ -567,6 +586,18 @@ static inline struct bio *erofs_fscache_bio_alloc(stru= ct erofs_map_dev *mdev) { static inline void erofs_fscache_submit_bio(struct bio *bio) {} #endif =20 +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE +int __init erofs_init_ishare(void); +void erofs_exit_ishare(void); +bool erofs_ishare_fill_inode(struct inode *inode); +void erofs_ishare_free_inode(struct inode *inode); +#else +static inline int erofs_init_ishare(void) { return 0; } +static inline void erofs_exit_ishare(void) {} +static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } +static inline void erofs_ishare_free_inode(struct inode *inode) {} +#endif + long erofs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); long erofs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c new file mode 100644 index 000000000000..3d26b2826710 --- /dev/null +++ b/fs/erofs/ishare.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024, Alibaba Cloud + */ +#include +#include +#include "internal.h" +#include "xattr.h" + +#include "../internal.h" + +static struct vfsmount *erofs_ishare_mnt; + +static int erofs_ishare_iget5_eq(struct inode *inode, void *data) +{ + struct erofs_inode_fingerprint *fp1 =3D &EROFS_I(inode)->fingerprint; + struct erofs_inode_fingerprint *fp2 =3D data; + + return fp1->size =3D=3D fp2->size && + !memcmp(fp1->opaque, fp2->opaque, fp2->size); +} + +static int erofs_ishare_iget5_set(struct inode *inode, void *data) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + + vi->fingerprint =3D *(struct erofs_inode_fingerprint *)data; + INIT_LIST_HEAD(&vi->ishare_list); + spin_lock_init(&vi->ishare_lock); + return 0; +} + +bool erofs_ishare_fill_inode(struct inode *inode) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(inode->i_sb); + struct erofs_inode *vi =3D EROFS_I(inode); + struct erofs_inode_fingerprint fp; + struct inode *sharedinode; + unsigned long hash; + + if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id)) + return false; + hash =3D xxh32(fp.opaque, fp.size, 0); + sharedinode =3D iget5_locked(erofs_ishare_mnt->mnt_sb, hash, + erofs_ishare_iget5_eq, erofs_ishare_iget5_set, + &fp); + if (!sharedinode) { + kfree(fp.opaque); + return false; + } + + if (inode_state_read_once(sharedinode) & I_NEW) { + if (erofs_inode_set_aops(sharedinode, inode, true)) { + iget_failed(sharedinode); + kfree(fp.opaque); + return false; + } + sharedinode->i_size =3D vi->vfs_inode.i_size; + unlock_new_inode(sharedinode); + } else { + kfree(fp.opaque); + if (sharedinode->i_size !=3D vi->vfs_inode.i_size) { + _erofs_printk(inode->i_sb, KERN_WARNING + "size(%lld:%lld) not matches for the same fingerprint\n", + vi->vfs_inode.i_size, sharedinode->i_size); + iput(sharedinode); + return false; + } + } + vi->sharedinode =3D sharedinode; + INIT_LIST_HEAD(&vi->ishare_list); + spin_lock(&EROFS_I(sharedinode)->ishare_lock); + list_add(&vi->ishare_list, &EROFS_I(sharedinode)->ishare_list); + spin_unlock(&EROFS_I(sharedinode)->ishare_lock); + return true; +} + +void erofs_ishare_free_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + struct inode *sharedinode =3D vi->sharedinode; + + if (!sharedinode) + return; + spin_lock(&EROFS_I(sharedinode)->ishare_lock); + list_del(&vi->ishare_list); + spin_unlock(&EROFS_I(sharedinode)->ishare_lock); + iput(sharedinode); + vi->sharedinode =3D NULL; +} + +static int erofs_ishare_file_open(struct inode *inode, struct file *file) +{ + struct inode *sharedinode =3D EROFS_I(inode)->sharedinode; + struct file *realfile; + + if (file->f_flags & O_DIRECT) + return -EINVAL; + realfile =3D alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred()); + if (IS_ERR(realfile)) + return PTR_ERR(realfile); + ihold(sharedinode); + realfile->f_op =3D &erofs_file_fops; + realfile->f_inode =3D sharedinode; + realfile->f_mapping =3D sharedinode->i_mapping; + path_get(&file->f_path); + backing_file_set_user_path(realfile, &file->f_path); + + 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; + + iput(realfile->f_inode); + fput(realfile); + file->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 kiocb dedup_iocb; + ssize_t nread; + + if (!iov_iter_count(to)) + return 0; + kiocb_clone(&dedup_iocb, iocb, realfile); + nread =3D filemap_read(&dedup_iocb, to, 0); + iocb->ki_pos =3D dedup_iocb.ki_pos; + return nread; +} + +static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct file *realfile =3D file->private_data; + + 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, +}; + +int __init erofs_init_ishare(void) +{ + erofs_ishare_mnt =3D kern_mount(&erofs_anon_fs_type); + return PTR_ERR_OR_ZERO(erofs_ishare_mnt); +} + +void erofs_exit_ishare(void) +{ + kern_unmount(erofs_ishare_mnt); +} diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 38be26ba04bb..e8f1b1892ecf 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -396,6 +396,7 @@ static void erofs_default_options(struct erofs_sb_info = *sbi) enum { Opt_user_xattr, Opt_acl, Opt_cache_strategy, Opt_dax, Opt_dax_enum, Opt_device, Opt_fsid, Opt_domain_id, Opt_directio, Opt_fsoffset, + Opt_inode_share, }; =20 static const struct constant_table erofs_param_cache_strategy[] =3D { @@ -423,6 +424,7 @@ static const struct fs_parameter_spec erofs_fs_paramete= rs[] =3D { fsparam_string("domain_id", Opt_domain_id), fsparam_flag_no("directio", Opt_directio), fsparam_u64("fsoffset", Opt_fsoffset), + fsparam_flag("inode_share", Opt_inode_share), {} }; =20 @@ -524,6 +526,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_PAGE_CACH= E_SHARE) case Opt_domain_id: kfree_sensitive(sbi->domain_id); sbi->domain_id =3D no_free_ptr(param->string); @@ -547,6 +551,13 @@ static int erofs_fc_parse_param(struct fs_context *fc, case Opt_fsoffset: sbi->dif0.fsoff =3D result.uint_64; break; + case Opt_inode_share: +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + set_opt(&sbi->opt, INODE_SHARE); +#else + errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name); +#endif + break; } return 0; } @@ -645,6 +656,15 @@ static int erofs_fc_fill_super(struct super_block *sb,= struct fs_context *fc) sb->s_maxbytes =3D MAX_LFS_FILESIZE; sb->s_op =3D &erofs_sops; =20 + if (!sbi->domain_id && test_opt(&sbi->opt, INODE_SHARE)) { + errorfc(fc, "domain_id is needed when inode_ishare is on"); + return -EINVAL; + } + if (test_opt(&sbi->opt, DAX_ALWAYS) && test_opt(&sbi->opt, INODE_SHARE)) { + errorfc(fc, "FSDAX is not allowed when inode_ishare is on"); + return -EINVAL; + } + sbi->blkszbits =3D PAGE_SHIFT; if (!sb->s_bdev) { /* @@ -715,6 +735,12 @@ static int erofs_fc_fill_super(struct super_block *sb,= struct fs_context *fc) erofs_info(sb, "unsupported blocksize for DAX"); clear_opt(&sbi->opt, DAX_ALWAYS); } + if (test_opt(&sbi->opt, INODE_SHARE) && !erofs_sb_has_ishare_xattrs(sbi))= { + erofs_info(sb, "on-disk ishare xattrs not found. Turning off inode_share= ."); + clear_opt(&sbi->opt, INODE_SHARE); + } + if (test_opt(&sbi->opt, INODE_SHARE)) + erofs_info(sb, "EXPERIMENTAL EROFS page cache share support in use. Use = at your own risk!"); =20 sb->s_time_gran =3D 1; sb->s_xattr =3D erofs_xattr_handlers; @@ -944,10 +970,32 @@ static struct file_system_type erofs_fs_type =3D { }; MODULE_ALIAS_FS("erofs"); =20 -#if defined(CONFIG_EROFS_FS_ONDEMAND) +#if defined(CONFIG_EROFS_FS_ONDEMAND) || defined(CONFIG_EROFS_FS_PAGE_CACH= E_SHARE) +static void erofs_free_anon_inode(struct inode *inode) +{ + struct erofs_inode *vi =3D EROFS_I(inode); + +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE + kfree(vi->fingerprint.opaque); +#endif + kmem_cache_free(erofs_inode_cachep, vi); +} + +static const struct super_operations erofs_anon_sops =3D { + .alloc_inode =3D erofs_alloc_inode, + .drop_inode =3D inode_just_drop, + .free_inode =3D erofs_free_anon_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) + return -ENOMEM; + ctx->ops =3D &erofs_anon_sops; + return 0; } =20 struct file_system_type erofs_anon_fs_type =3D { @@ -982,6 +1030,10 @@ static int __init erofs_module_init(void) if (err) goto sysfs_err; =20 + err =3D erofs_init_ishare(); + if (err) + goto ishare_err; + err =3D register_filesystem(&erofs_fs_type); if (err) goto fs_err; @@ -989,6 +1041,8 @@ static int __init erofs_module_init(void) return 0; =20 fs_err: + erofs_exit_ishare(); +ishare_err: erofs_exit_sysfs(); sysfs_err: z_erofs_exit_subsystem(); @@ -1006,6 +1060,7 @@ static void __exit erofs_module_exit(void) /* Ensure all RCU free inodes / pclusters are safe to be destroyed. */ rcu_barrier(); =20 + erofs_exit_ishare(); erofs_exit_sysfs(); z_erofs_exit_subsystem(); erofs_exit_shrinker(); @@ -1060,6 +1115,8 @@ static int erofs_show_options(struct seq_file *seq, s= truct dentry *root) #endif if (sbi->dif0.fsoff) seq_printf(seq, ",fsoffset=3D%llu", sbi->dif0.fsoff); + if (test_opt(opt, INODE_SHARE)) + seq_puts(seq, ",inode_share"); return 0; } =20 @@ -1070,6 +1127,7 @@ static void erofs_evict_inode(struct inode *inode) dax_break_layout_final(inode); #endif =20 + erofs_ishare_free_inode(inode); truncate_inode_pages_final(&inode->i_data); clear_inode(inode); } diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index ae61f20cb861..e1709059d3cc 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -577,3 +577,37 @@ struct posix_acl *erofs_get_acl(struct inode *inode, i= nt type, bool rcu) return acl; } #endif + +#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE +int erofs_xattr_fill_inode_fingerprint(struct erofs_inode_fingerprint *fp, + struct inode *inode, const char *domain_id) +{ + struct erofs_sb_info *sbi =3D EROFS_SB(inode->i_sb); + struct erofs_xattr_prefix_item *prefix; + const char *infix; + int valuelen, base_index; + + if (!test_opt(&sbi->opt, INODE_SHARE)) + return -EOPNOTSUPP; + if (!sbi->xattr_prefixes) + return -EINVAL; + prefix =3D sbi->xattr_prefixes + sbi->ishare_xattr_prefix_id; + infix =3D prefix->prefix->infix; + base_index =3D prefix->prefix->base_index; + valuelen =3D erofs_getxattr(inode, base_index, infix, NULL, 0); + if (valuelen <=3D 0 || valuelen > (1 << sbi->blkszbits)) + return -EFSCORRUPTED; + fp->size =3D valuelen + (domain_id ? strlen(domain_id) : 0); + fp->opaque =3D kmalloc(fp->size, GFP_KERNEL); + if (!fp->opaque) + return -ENOMEM; + if (valuelen !=3D erofs_getxattr(inode, base_index, infix, + fp->opaque, valuelen)) { + kfree(fp->opaque); + fp->opaque =3D NULL; + return -EFSCORRUPTED; + } + memcpy(fp->opaque + valuelen, domain_id, fp->size - valuelen); + return 0; +} +#endif diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 6317caa8413e..bf75a580b8f1 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -67,4 +67,7 @@ struct posix_acl *erofs_get_acl(struct inode *inode, int = type, bool rcu); #define erofs_get_acl (NULL) #endif =20 +int erofs_xattr_fill_inode_fingerprint(struct erofs_inode_fingerprint *fp, + struct inode *inode, const char *domain_id); + #endif --=20 2.22.0 From nobody Sun Feb 8 21:49:10 2026 Received: from canpmsgout06.his.huawei.com (canpmsgout06.his.huawei.com [113.46.200.221]) (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 4FA2536CDFB; Fri, 23 Jan 2026 01:45:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.221 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132739; cv=none; b=UwV1havyvekMWRMpLtS8V8dVyBYDC8/eWN1mFHa+cwfrNkHC5XfFHihw3mXz9U7+vafzKm89EV5+ZKBzsVy5FDE71lV48FnCH+zSwQCYxz0l6bBzxX5Md+izpbSYlkf0txPRLKgrD0EpNR9ZJ4AQuWvbJ7x8AtNl8DoVZTtMgPo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132739; c=relaxed/simple; bh=QoXfgAbGNUQiQj1f2aRExtgVmE/mWpc0tyqc/O344lI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jTufgH4S98D/7Pd5zbLhK8RCecj5UHOLsspG5u0sj3JEJSBKukXd/9Qgj8/QNyxxtScqow6h/I0Ba0rcEhqO2O8S2iGLF59xYe3hNLRnJ6APg/2bZoxmFH+TIwv6fhGUSG4g3jE9gwHdtgHxo3aw/LCgXLEf59ApehhSQiHCZtE= 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=ZSFqI/eL; arc=none smtp.client-ip=113.46.200.221 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="ZSFqI/eL" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=j6kl+aNNrzyjMKF8SjtxTwU6f9KRILQcLr8ULQnojpQ=; b=ZSFqI/eL8SkZkha+KVfw4O1daKwpmPXrJHkt4VIZy7RqDziP4M3b26lurC9oWQb4xEkoRMwF7 Rx0GyuiyyZFUPRB8EwtOwz3Gm5FPYcfoydiffhkwDsmDApHzd6lHcG4G3/0z67w0SKB36Z6sAPR KPvfG+EO7YjzG4bNch88GYo= Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout06.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z71kTNzRhV6; Fri, 23 Jan 2026 09:41:55 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 43B4F40363; Fri, 23 Jan 2026 09:45:20 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:19 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 07/10] erofs: pass inode to trace_erofs_read_folio Date: Fri, 23 Jan 2026 01:31:29 +0000 Message-ID: <20260123013132.662393-8-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) Content-Type: text/plain; charset="utf-8" The trace_erofs_read_folio accesses inode information through folio, but this method fails if the real inode is not associated with the folio(such as in the upcoming page cache sharing case). Therefore, we pass the real inode to it so that the inode information can be printed out in that case. Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/data.c | 6 ++---- fs/erofs/fileio.c | 2 +- fs/erofs/zdata.c | 2 +- include/trace/events/erofs.h | 10 +++++----- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 71e23d91123d..ea198defb531 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -385,8 +385,7 @@ static int erofs_read_folio(struct file *file, struct f= olio *folio) }; struct erofs_iomap_iter_ctx iter_ctx =3D {}; =20 - trace_erofs_read_folio(folio, true); - + trace_erofs_read_folio(folio_inode(folio), folio, true); iomap_read_folio(&erofs_iomap_ops, &read_ctx, &iter_ctx); return 0; } @@ -400,8 +399,7 @@ static void erofs_readahead(struct readahead_control *r= ac) struct erofs_iomap_iter_ctx iter_ctx =3D {}; =20 trace_erofs_readahead(rac->mapping->host, readahead_index(rac), - readahead_count(rac), true); - + readahead_count(rac), true); iomap_readahead(&erofs_iomap_ops, &read_ctx, &iter_ctx); } =20 diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c index 932e8b353ba1..d07dc248d264 100644 --- a/fs/erofs/fileio.c +++ b/fs/erofs/fileio.c @@ -161,7 +161,7 @@ static int erofs_fileio_read_folio(struct file *file, s= truct folio *folio) struct erofs_fileio io =3D {}; int err; =20 - trace_erofs_read_folio(folio, true); + trace_erofs_read_folio(folio_inode(folio), folio, true); err =3D erofs_fileio_scan_folio(&io, folio); erofs_fileio_rq_submit(io.rq); return err; diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 3d31f7840ca0..93ab6a481b64 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1887,7 +1887,7 @@ static int z_erofs_read_folio(struct file *file, stru= ct folio *folio) Z_EROFS_DEFINE_FRONTEND(f, inode, folio_pos(folio)); int err; =20 - trace_erofs_read_folio(folio, false); + trace_erofs_read_folio(inode, folio, false); z_erofs_pcluster_readmore(&f, NULL, true); err =3D z_erofs_scan_folio(&f, folio, false); z_erofs_pcluster_readmore(&f, NULL, false); diff --git a/include/trace/events/erofs.h b/include/trace/events/erofs.h index dad7360f42f9..def20d06507b 100644 --- a/include/trace/events/erofs.h +++ b/include/trace/events/erofs.h @@ -82,9 +82,9 @@ TRACE_EVENT(erofs_fill_inode, =20 TRACE_EVENT(erofs_read_folio, =20 - TP_PROTO(struct folio *folio, bool raw), + TP_PROTO(struct inode *inode, struct folio *folio, bool raw), =20 - TP_ARGS(folio, raw), + TP_ARGS(inode, folio, raw), =20 TP_STRUCT__entry( __field(dev_t, dev ) @@ -96,9 +96,9 @@ TRACE_EVENT(erofs_read_folio, ), =20 TP_fast_assign( - __entry->dev =3D folio->mapping->host->i_sb->s_dev; - __entry->nid =3D EROFS_I(folio->mapping->host)->nid; - __entry->dir =3D S_ISDIR(folio->mapping->host->i_mode); + __entry->dev =3D inode->i_sb->s_dev; + __entry->nid =3D EROFS_I(inode)->nid; + __entry->dir =3D S_ISDIR(inode->i_mode); __entry->index =3D folio->index; __entry->uptodate =3D folio_test_uptodate(folio); __entry->raw =3D raw; --=20 2.22.0 From nobody Sun Feb 8 21:49:10 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (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 5E66537F10D; Fri, 23 Jan 2026 01:45:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132745; cv=none; b=GsKbJO0DC3DVkkrHU1Zj6qv9GSezwRFBmdwDw52/vkBKy9Buke9tJOqYFYQBA5za4Z8kcb6BudpDvB3mf+HdjWhyOnXhC2HBrX8TWoirkZTMAUH8lpHZ7n2FcKRmjQ+Jhs8k/mUwixOu7HNvVTu5wOCVyMMJ/1IYJkudDJqmje4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132745; c=relaxed/simple; bh=D2K4yxsmpX4NR5cXmRj6WmfRIaDslgFCnA19dAJylY4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TC50FNkd2+9Q/eY34Wj4uClpiPmBz2mvkFGnnKs1d+wKeLS9C0JTRFjd5VIV4CClqU+gT6VU6sKmZEzpm0ao6uiq1qzcyE9pJ9XTHmP0mIyUaVlIgAcRO4PrJHk8VNtNosSmIWuSVpH/FW5z2vfWotuIIX1UzH9JzZy0tfJcGlg= 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=Wwgruz10; arc=none smtp.client-ip=113.46.200.224 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="Wwgruz10" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=mRrts9Sxp0zunICFM5NmKmdoVUTt7lZH5sI3kZ/zSSA=; b=Wwgruz10bhtBL27DWJJK3XErCeDUbDgl57tH/fEDvpU5LQaB6Ml6LsfY8Sqr/VUYlfMlfY2fe /quDf+CepAJZuoq1kzmHV/14Sv1V2fgoy77ZjAX285SPnWJlsIKw+8VRci696Sf9q/cxBqLKJ5E 43GRbE9o9XzIXyddEvqvEfg= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z83BMVz1cySK; Fri, 23 Jan 2026 09:41:56 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id B584A402AB; Fri, 23 Jan 2026 09:45:20 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:20 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 08/10] erofs: support unencoded inodes for page cache share Date: Fri, 23 Jan 2026 01:31:30 +0000 Message-ID: <20260123013132.662393-9-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) To kwepemr500015.china.huawei.com (7.202.195.162) 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% | +-------------------+------------------+-------------+---------------+ Co-developed-by: Hongzhen Luo Signed-off-by: Hongzhen Luo Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/data.c | 32 +++++++++++++++++++++++--------- fs/erofs/fileio.c | 25 ++++++++++++++++--------- fs/erofs/inode.c | 3 ++- fs/erofs/internal.h | 6 ++++++ fs/erofs/ishare.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index ea198defb531..3a4eb0dececd 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -269,6 +269,7 @@ void erofs_onlinefolio_end(struct folio *folio, int err= , bool dirty) struct erofs_iomap_iter_ctx { struct page *page; void *base; + struct inode *realinode; }; =20 static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, @@ -276,14 +277,15 @@ static int erofs_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length, { struct iomap_iter *iter =3D container_of(iomap, struct iomap_iter, iomap); struct erofs_iomap_iter_ctx *ctx =3D iter->private; - struct super_block *sb =3D inode->i_sb; + struct inode *realinode =3D ctx ? ctx->realinode : inode; + struct super_block *sb =3D realinode->i_sb; struct erofs_map_blocks map; struct erofs_map_dev mdev; int ret; =20 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 @@ -296,7 +298,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, return 0; } =20 - if (!(map.m_flags & EROFS_MAP_META) || !erofs_inode_in_metabox(inode)) { + if (!(map.m_flags & EROFS_MAP_META) || !erofs_inode_in_metabox(realinode)= ) { mdev =3D (struct erofs_map_dev) { .m_deviceid =3D map.m_deviceid, .m_pa =3D map.m_pa, @@ -322,7 +324,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_= t offset, loff_t length, void *ptr; =20 ptr =3D erofs_read_metabuf(&buf, sb, map.m_pa, - erofs_inode_in_metabox(inode)); + erofs_inode_in_metabox(realinode)); if (IS_ERR(ptr)) return PTR_ERR(ptr); iomap->inline_data =3D ptr; @@ -383,10 +385,15 @@ static int erofs_read_folio(struct file *file, struct= folio *folio) .ops =3D &iomap_bio_read_ops, .cur_folio =3D folio, }; - struct erofs_iomap_iter_ctx iter_ctx =3D {}; + bool need_iput; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .realinode =3D erofs_real_inode(folio_inode(folio), &need_iput), + }; =20 - trace_erofs_read_folio(folio_inode(folio), folio, true); + trace_erofs_read_folio(iter_ctx.realinode, folio, true); iomap_read_folio(&erofs_iomap_ops, &read_ctx, &iter_ctx); + if (need_iput) + iput(iter_ctx.realinode); return 0; } =20 @@ -396,11 +403,16 @@ static void erofs_readahead(struct readahead_control = *rac) .ops =3D &iomap_bio_read_ops, .rac =3D rac, }; - struct erofs_iomap_iter_ctx iter_ctx =3D {}; + bool need_iput; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .realinode =3D erofs_real_inode(rac->mapping->host, &need_iput), + }; =20 - trace_erofs_readahead(rac->mapping->host, readahead_index(rac), + trace_erofs_readahead(iter_ctx.realinode, readahead_index(rac), readahead_count(rac), true); iomap_readahead(&erofs_iomap_ops, &read_ctx, &iter_ctx); + if (need_iput) + iput(iter_ctx.realinode); } =20 static sector_t erofs_bmap(struct address_space *mapping, sector_t block) @@ -421,7 +433,9 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb,= struct iov_iter *to) return dax_iomap_rw(iocb, to, &erofs_iomap_ops); #endif if ((iocb->ki_flags & IOCB_DIRECT) && inode->i_sb->s_bdev) { - struct erofs_iomap_iter_ctx iter_ctx =3D {}; + struct erofs_iomap_iter_ctx iter_ctx =3D { + .realinode =3D inode, + }; =20 return iomap_dio_rw(iocb, to, &erofs_iomap_ops, NULL, 0, &iter_ctx, 0); diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c index d07dc248d264..c1d0081609dc 100644 --- a/fs/erofs/fileio.c +++ b/fs/erofs/fileio.c @@ -88,9 +88,9 @@ void erofs_fileio_submit_bio(struct bio *bio) bio)); } =20 -static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *= folio) +static int erofs_fileio_scan_folio(struct erofs_fileio *io, + struct inode *inode, struct folio *folio) { - struct inode *inode =3D folio_inode(folio); struct erofs_map_blocks *map =3D &io->map; unsigned int cur =3D 0, end =3D folio_size(folio), len, attached =3D 0; loff_t pos =3D folio_pos(folio), ofs; @@ -158,31 +158,38 @@ static int erofs_fileio_scan_folio(struct erofs_filei= o *io, struct folio *folio) =20 static int erofs_fileio_read_folio(struct file *file, struct folio *folio) { + bool need_iput; + struct inode *realinode =3D erofs_real_inode(folio_inode(folio), &need_ip= ut); struct erofs_fileio io =3D {}; int err; =20 - trace_erofs_read_folio(folio_inode(folio), folio, true); - err =3D erofs_fileio_scan_folio(&io, folio); + trace_erofs_read_folio(realinode, folio, true); + err =3D erofs_fileio_scan_folio(&io, realinode, folio); erofs_fileio_rq_submit(io.rq); + if (need_iput) + iput(realinode); return err; } =20 static void erofs_fileio_readahead(struct readahead_control *rac) { - struct inode *inode =3D rac->mapping->host; + bool need_iput; + struct inode *realinode =3D erofs_real_inode(rac->mapping->host, &need_ip= ut); struct erofs_fileio io =3D {}; struct folio *folio; int err; =20 - trace_erofs_readahead(inode, readahead_index(rac), + trace_erofs_readahead(realinode, readahead_index(rac), readahead_count(rac), true); while ((folio =3D readahead_folio(rac))) { - err =3D erofs_fileio_scan_folio(&io, folio); + err =3D erofs_fileio_scan_folio(&io, realinode, folio); 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); } erofs_fileio_rq_submit(io.rq); + if (need_iput) + iput(realinode); } =20 const struct address_space_operations erofs_fileio_aops =3D { diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 202cbbb4eada..d33816cff813 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -213,7 +213,8 @@ static int erofs_fill_inode(struct inode *inode) switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op =3D &erofs_generic_iops; - inode->i_fop =3D &erofs_file_fops; + inode->i_fop =3D erofs_ishare_fill_inode(inode) ? + &erofs_ishare_fops : &erofs_file_fops; break; case S_IFDIR: inode->i_op =3D &erofs_dir_iops; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 15945e3308b8..d38e63e361c1 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -591,11 +591,17 @@ int __init erofs_init_ishare(void); void erofs_exit_ishare(void); bool erofs_ishare_fill_inode(struct inode *inode); void erofs_ishare_free_inode(struct inode *inode); +struct inode *erofs_real_inode(struct inode *inode, bool *need_iput); #else static inline int erofs_init_ishare(void) { return 0; } static inline void erofs_exit_ishare(void) {} static inline bool erofs_ishare_fill_inode(struct inode *inode) { return f= alse; } static inline void erofs_ishare_free_inode(struct inode *inode) {} +static inline struct inode *erofs_real_inode(struct inode *inode, bool *ne= ed_iput) +{ + *need_iput =3D false; + return inode; +} #endif =20 long erofs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index 3d26b2826710..ab459fb62473 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -11,6 +11,12 @@ =20 static struct vfsmount *erofs_ishare_mnt; =20 +static inline bool erofs_is_ishare_inode(struct inode *inode) +{ + /* assumed FS_ONDEMAND is excluded with FS_PAGE_CACHE_SHARE feature */ + return inode->i_sb->s_type =3D=3D &erofs_anon_fs_type; +} + static int erofs_ishare_iget5_eq(struct inode *inode, void *data) { struct erofs_inode_fingerprint *fp1 =3D &EROFS_I(inode)->fingerprint; @@ -38,6 +44,8 @@ bool erofs_ishare_fill_inode(struct inode *inode) struct inode *sharedinode; unsigned long hash; =20 + if (erofs_inode_is_data_compressed(vi->datalayout)) + return false; if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id)) return false; hash =3D xxh32(fp.opaque, fp.size, 0); @@ -155,6 +163,32 @@ const struct file_operations erofs_ishare_fops =3D { .splice_read =3D filemap_splice_read, }; =20 +struct inode *erofs_real_inode(struct inode *inode, bool *need_iput) +{ + struct erofs_inode *vi, *vi_share; + struct inode *realinode; + + *need_iput =3D false; + if (!erofs_is_ishare_inode(inode)) + return inode; + + vi_share =3D EROFS_I(inode); + spin_lock(&vi_share->ishare_lock); + /* fetch any one as real inode */ + DBG_BUGON(list_empty(&vi_share->ishare_list)); + list_for_each_entry(vi, &vi_share->ishare_list, ishare_list) { + realinode =3D igrab(&vi->vfs_inode); + if (realinode) { + *need_iput =3D true; + break; + } + } + spin_unlock(&vi_share->ishare_lock); + + DBG_BUGON(!realinode); + return realinode; +} + int __init erofs_init_ishare(void) { erofs_ishare_mnt =3D kern_mount(&erofs_anon_fs_type); --=20 2.22.0 From nobody Sun Feb 8 21:49:10 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 55DBA37F0F0; Fri, 23 Jan 2026 01:45:27 +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=1769132746; cv=none; b=n6SqSmQqeHmbEkdYQ78kODfKJR008rEMFAPfZBWplNpnKn4dgKgwkNyDdPtMtSkQcv7n1sNh9K30r0tr3rJou3SKGmMFcyCuxxqkI57m/1iZz4FYrg0VG5cMmPpTBXMhdHgPprr2cLe9bxns9I+Quu5mmD9kmTAZhWH56wseJzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132746; c=relaxed/simple; bh=q00Zd1QsMQfMJFxzkErcBoqacEhWRBiRzGcZl/vaS0s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oDdEHtkK/P7wpSpNGEcqM70DxB4me8JzNL80F1P7Ova4l/bSaHBvVvrVVukfk07QFtccXFCnHHdPM0gWoCxpLhZeruLFFGzcom+y8pEEQgnw++U8YDoW1xcJpvRJ0gRJ9KmhxrjhdJeHStQX+0ABnpwyrMp2TQTOkaCBIuxIVdM= 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=giAWo/rr; 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="giAWo/rr" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=bHJ8+pUveP5svlVbwXvXskyfrLfruh6IJ5eNHjeX9MY=; b=giAWo/rrr36d61qXZy7nal68rbmHJdEjeYRngYq28DWnXnVKPxdQs4UH90wHaoH2epVSG/3Fo 3cPnC2zjW8mvicpxt81D327RXehW2Y5xtx0GB6U+baNmL27IDjhpW2xm+/WLe00jHXgdWehx7gt G1ataZt/JO5XeBUfr7+xPxM= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z86vSTzLlTR; Fri, 23 Jan 2026 09:41:56 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 1A90A4055B; Fri, 23 Jan 2026 09:45:21 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:20 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 09/10] erofs: support compressed inodes for page cache share Date: Fri, 23 Jan 2026 01:31:31 +0000 Message-ID: <20260123013132.662393-10-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) 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 Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/ishare.c | 2 -- fs/erofs/zdata.c | 38 ++++++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index ab459fb62473..ad53a57dbcbc 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -44,8 +44,6 @@ bool erofs_ishare_fill_inode(struct inode *inode) struct inode *sharedinode; unsigned long hash; =20 - if (erofs_inode_is_data_compressed(vi->datalayout)) - return false; if (erofs_xattr_fill_inode_fingerprint(&fp, inode, sbi->domain_id)) return false; hash =3D xxh32(fp.opaque, fp.size, 0); diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 93ab6a481b64..59ee9a36d9eb 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -493,7 +493,7 @@ enum z_erofs_pclustermode { }; =20 struct z_erofs_frontend { - struct inode *const inode; + struct inode *inode, *sharedinode; struct erofs_map_blocks map; struct z_erofs_bvec_iter biter; =20 @@ -508,8 +508,8 @@ struct z_erofs_frontend { unsigned int icur; }; =20 -#define Z_EROFS_DEFINE_FRONTEND(fe, i, ho) struct z_erofs_frontend fe =3D = { \ - .inode =3D i, .head =3D Z_EROFS_PCLUSTER_TAIL, \ +#define Z_EROFS_DEFINE_FRONTEND(fe, i, si, ho) struct z_erofs_frontend fe = =3D { \ + .inode =3D i, .sharedinode =3D si, .head =3D Z_EROFS_PCLUSTER_TAIL, \ .mode =3D Z_EROFS_PCLUSTER_FOLLOWED, .headoffset =3D ho } =20 static bool z_erofs_should_alloc_cache(struct z_erofs_frontend *fe) @@ -1866,7 +1866,7 @@ static void z_erofs_pcluster_readmore(struct z_erofs_= frontend *f, pgoff_t index =3D cur >> PAGE_SHIFT; struct folio *folio; =20 - folio =3D erofs_grab_folio_nowait(inode->i_mapping, index); + folio =3D erofs_grab_folio_nowait(f->sharedinode->i_mapping, index); if (!IS_ERR_OR_NULL(folio)) { if (folio_test_uptodate(folio)) folio_unlock(folio); @@ -1883,11 +1883,13 @@ 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 *sharedinode =3D folio->mapping->host; + bool need_iput; + struct inode *realinode =3D erofs_real_inode(sharedinode, &need_iput); + Z_EROFS_DEFINE_FRONTEND(f, realinode, sharedinode, folio_pos(folio)); int err; =20 - trace_erofs_read_folio(inode, folio, false); + trace_erofs_read_folio(realinode, folio, false); z_erofs_pcluster_readmore(&f, NULL, true); err =3D z_erofs_scan_folio(&f, folio, false); z_erofs_pcluster_readmore(&f, NULL, false); @@ -1896,23 +1898,28 @@ 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 (need_iput) + iput(realinode); 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 *sharedinode =3D rac->mapping->host; + bool need_iput; + struct inode *realinode =3D erofs_real_inode(sharedinode, &need_iput); + Z_EROFS_DEFINE_FRONTEND(f, realinode, sharedinode, readahead_pos(rac)); unsigned int nrpages =3D readahead_count(rac); struct folio *head =3D NULL, *folio; int err; =20 - trace_erofs_readahead(inode, readahead_index(rac), nrpages, false); + 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; @@ -1926,8 +1933,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); @@ -1935,6 +1942,9 @@ static void z_erofs_readahead(struct readahead_contro= l *rac) (void)z_erofs_runqueue(&f, nrpages); erofs_put_metabuf(&f.map.buf); erofs_release_pages(&f.pagepool); + + if (need_iput) + iput(realinode); } =20 const struct address_space_operations z_erofs_aops =3D { --=20 2.22.0 From nobody Sun Feb 8 21:49:10 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 4FFC6376BC5; Fri, 23 Jan 2026 01:45:29 +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=1769132736; cv=none; b=nciitzSL/zN9Rlak+IgDUaodbEee8QHE09FyMJIuAbAVu1Z5mTnwv30R6sYepxAtiPHR4NL5CgVkQ4e+JFEeLCqloXGFDArlr2HzcuG5oLNzdTP4DJCEUtxhUmIXUnGi82VaKi25G6JEJeveUIBabW4WY1VzA/8UYoImEzsQ+x4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769132736; c=relaxed/simple; bh=anA6yDKzxBNODzduD70HgdLsrJbw6S9AkfSIJUGFzX0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nCj76lmZYbGiikKLgQtPFQ3tWB24TT8NQpSA+MqbVPw93T3n6n/CmyDI4tSEyV/kepxeaKfW8y7G0de8uQHenvOiosOma+wkzEbnSAWvZrDHolCCfoYoitzqSmAeUt4yjTSM72/orF4R1ASOk6gmXvf4dtrg12+Wxf8DCYPSBgg= 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=uTFxrd8I; 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="uTFxrd8I" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=pjdMVj5WK0KjkehQa5OTHZ+MCiwfMCyVPXQRCDg124Y=; b=uTFxrd8IXGqAsUVgSzf8YOFirRCl+3Vri/JQVcixI0RqRwASzkKo/jUAAOd1zf2p8vAHRhNct 7JRO2KnDibrXmcR1YSb58tPaTU2XzWY8irks5vvRwYuE1ugRbA9HdzpSp+Pa/6cphzU/dMAJn2U JzHDdXLMT0jGr7lSzjEguOw= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4dy0z93hBczLlTR; Fri, 23 Jan 2026 09:41:57 +0800 (CST) Received: from kwepemr500015.china.huawei.com (unknown [7.202.195.162]) by mail.maildlp.com (Postfix) with ESMTPS id 9F0384055B; Fri, 23 Jan 2026 09:45:21 +0800 (CST) Received: from huawei.com (10.67.174.162) by kwepemr500015.china.huawei.com (7.202.195.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 23 Jan 2026 09:45:20 +0800 From: Hongbo Li To: , , CC: , , , , , , Subject: [PATCH v18 10/10] erofs: implement .fadvise for page cache share Date: Fri, 23 Jan 2026 01:31:32 +0000 Message-ID: <20260123013132.662393-11-lihongbo22@huawei.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20260123013132.662393-1-lihongbo22@huawei.com> References: <20260123013132.662393-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: kwepems200001.china.huawei.com (7.221.188.67) 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 Signed-off-by: Hongbo Li Reviewed-by: Gao Xiang --- fs/erofs/ishare.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/erofs/ishare.c b/fs/erofs/ishare.c index ad53a57dbcbc..ce980320a8b9 100644 --- a/fs/erofs/ishare.c +++ b/fs/erofs/ishare.c @@ -151,6 +151,12 @@ 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_fadvise(struct file *file, loff_t offset, + loff_t len, int advice) +{ + return vfs_fadvise(file->private_data, offset, len, advice); +} + const struct file_operations erofs_ishare_fops =3D { .open =3D erofs_ishare_file_open, .llseek =3D generic_file_llseek, @@ -159,6 +165,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_fadvise, }; =20 struct inode *erofs_real_inode(struct inode *inode, bool *need_iput) --=20 2.22.0