From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Matthew Wilcox <willy@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>, Jan Kara <jack@suse.cz>,
Hugh Dickins <hughd@google.com>,
Christian Brauner <brauner@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Harry Yoo <harry@kernel.org>
Cc: "Kiryl Shutsemau (Meta)" <kas@kernel.org>,
Miklos Szeredi <miklos@szeredi.hu>,
Miaohe Lin <linmiaohe@huawei.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Oscar Salvador <osalvador@suse.de>,
"Liam R. Howlett" <liam@infradead.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>,
Brendan Jackman <brendan.jackman@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Nico Pache <nico.pache@linux.dev>,
Ryan Roberts <ryan.roberts@arm.com>, Dev Jain <dev.jain@arm.com>,
Barry Song <baohua@kernel.org>, Lance Yang <lance.yang@linux.dev>,
Usama Arif <usama.arif@linux.dev>,
Kairui Song <kasong@tencent.com>, Qi Zheng <qi.zheng@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Axel Rasmussen <axelrasmussen@google.com>,
Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
Baoquan He <baoquan.he@linux.dev>,
"Paul E. McKenney" <paulmck@kernel.org>,
Pedro Falcato <pfalcato@suse.de>,
Luis Chamberlain <mcgrof@kernel.org>,
Ilya Gladyshev <ilya.gladyshev@linux.dev>,
Jaegeuk Kim <jaegeuk@kernel.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org, fuse-devel@lists.linux.dev,
kernel-team@meta.com
Subject: [RFC PATCH v2 18/18] mm/filemap: add a debugfs switch for lockless page cache reads
Date: Wed, 4 Nov 2026 13:01:14 +0000 [thread overview]
Message-ID: <20261104130118.2507513-19-kas@kernel.org> (raw)
In-Reply-To: <20261104130118.2507513-1-kas@kernel.org>
Reading hot folios without a reference defers the free of their memory
by an RCU grace period. A workload that loses on that trade, or a bug
in the lockless read, has no way to turn it off: CONFIG_PAGE_RCU_FREE is
on in every 64-bit kernel.
Add lockless_page_cache_read to debugfs. Writing 0 stops filemap_read()
and shmem_file_read_iter() from setting PG_rcu_free and from copying
without a reference. A static key keeps the test off the read path.
debugfs, not a sysctl: the switch is not ABI and can go once the reads
have proven themselves.
Folios that have the flag keep it, and their free stays deferred: a read
that tested the key before the switch may still be copying from them.
Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
---
mm/Kconfig | 3 +++
mm/filemap.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/mm/Kconfig b/mm/Kconfig
index 6e5341b0bf64..768873ebc71c 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -733,6 +733,9 @@ config PAGE_RCU_FREE
32-bit. Not on PREEMPT_RT, where expedited grace periods are
normal ones, so freeing the waiting pages on demand would stall.
+ Writing 0 to lockless_page_cache_read in debugfs turns these
+ reads off.
+
config PHYS_ADDR_T_64BIT
def_bool 64BIT
diff --git a/mm/filemap.c b/mm/filemap.c
index e148490db4da..eff29d501f58 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -48,6 +48,7 @@
#include <linux/rcupdate_wait.h>
#include <linux/sched/mm.h>
#include <linux/sysctl.h>
+#include <linux/debugfs.h>
#include <linux/pgalloc.h>
#include <asm/tlbflush.h>
@@ -2759,6 +2760,50 @@ static inline bool pos_same_folio(loff_t pos1, loff_t pos2, struct folio *folio)
return (pos1 >> shift == pos2 >> shift);
}
+#ifdef CONFIG_PAGE_RCU_FREE
+/* Writing 0 to lockless_page_cache_read in debugfs turns the reads off */
+static DEFINE_STATIC_KEY_TRUE(lockless_read_key);
+
+static bool lockless_read_enabled(void)
+{
+ return static_branch_likely(&lockless_read_key);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int lockless_read_get(void *data, u64 *val)
+{
+ *val = static_key_enabled(&lockless_read_key);
+ return 0;
+}
+
+static int lockless_read_set(void *data, u64 val)
+{
+ if (val > 1)
+ return -EINVAL;
+ if (val)
+ static_branch_enable(&lockless_read_key);
+ else
+ static_branch_disable(&lockless_read_key);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(lockless_read_fops, lockless_read_get,
+ lockless_read_set, "%llu\n");
+
+static int __init lockless_read_debugfs_init(void)
+{
+ debugfs_create_file_unsafe("lockless_page_cache_read", 0644, NULL, NULL,
+ &lockless_read_fops);
+ return 0;
+}
+late_initcall(lockless_read_debugfs_init);
+#endif
+#else
+static bool lockless_read_enabled(void)
+{
+ return false;
+}
+#endif
+
/*
* Reads keep coming back to @folio: free it only after an RCU grace period
* from now on. Not if its next read needs a reference anyway. Not if it
@@ -2769,7 +2814,7 @@ static void filemap_mark_hot(struct folio *folio)
{
struct address_space *mapping;
- if (!IS_ENABLED(CONFIG_PAGE_RCU_FREE))
+ if (!lockless_read_enabled())
return;
if (folio_test_rcu_free(folio) || !folio_test_uptodate(folio) ||
folio_test_dropbehind(folio) || folio_test_unevictable(folio))
@@ -3028,8 +3073,8 @@ size_t filemap_read_rcu(struct kiocb *iocb, struct iov_iter *iter,
pgoff_t last_index = (last_pos - 1) >> PAGE_SHIFT;
size_t copied = 0;
- /* Not on an inode that never had a folio flagged */
- if (!IS_ENABLED(CONFIG_PAGE_RCU_FREE) ||
+ /* Not when switched off, or on an inode that never had a folio flagged */
+ if (!lockless_read_enabled() ||
!mapping_rcu_read(iocb->ki_filp->f_mapping))
return 0;
--
2.54.0
prev parent reply other threads:[~2026-11-04 13:03 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 13:00 [RFC PATCH v2 00/18] mm: read the page cache without folio references Kiryl Shutsemau (Meta)
2026-11-04 13:00 ` [RFC PATCH v2 01/18] mm: free PG_rcu_free folios only after an RCU grace period Kiryl Shutsemau (Meta)
2026-11-05 20:37 ` David Hildenbrand (Arm)
2026-11-04 13:00 ` [RFC PATCH v2 02/18] splice: don't steal page cache folios Kiryl Shutsemau (Meta)
2026-11-04 16:05 ` David Hildenbrand (Arm)
2026-11-05 14:55 ` Kiryl Shutsemau
2026-11-04 13:00 ` [RFC PATCH v2 03/18] fuse: don't move a folio with PG_rcu_free into a fuse file Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 04/18] mm: count the pages waiting for a grace period Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 05/18] mm: expedite the grace period when a CPU has many deferred frees Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 06/18] mm: free the pages waiting for a grace period before OOM Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` [RFC PATCH v2 07/18] mm: free the pages waiting for a grace period before isolation fails Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` [RFC PATCH v2 08/18] mm/compaction: free the migrated folios that wait for a grace period Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` [RFC PATCH v2 09/18] mm/memory-failure: handle folios with PG_rcu_free Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` [RFC PATCH v2 10/18] mm: have folio_mark_accessed() return whether the folio is hot Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 11/18] mm/filemap: mark a folio accessed in one place in filemap_read() Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 12/18] mm/filemap: set PG_rcu_free on the folios that reads keep coming back to Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 13/18] mm/filemap: read from the page cache without folio references Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 14/18] mm/filemap: read large folios " Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` [RFC PATCH v2 15/18] mm/filemap: don't store f_ra.prev_pos for FMODE_RANDOM files Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 16/18] mm/shmem: count accesses to a folio the way filemap_read() does Kiryl Shutsemau (Meta)
2026-11-04 13:01 ` [RFC PATCH v2 17/18] mm/shmem: read without folio references Kiryl Shutsemau (Meta)
2026-11-05 13:03 ` sashiko-bot
2026-11-04 13:01 ` Kiryl Shutsemau (Meta) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261104130118.2507513-19-kas@kernel.org \
--to=kas@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=brauner@kernel.org \
--cc=brendan.jackman@linux.dev \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=fuse-devel@lists.linux.dev \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=hughd@google.com \
--cc=ilya.gladyshev@linux.dev \
--cc=jack@suse.cz \
--cc=jaegeuk@kernel.org \
--cc=kasong@tencent.com \
--cc=kernel-team@meta.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linmiaohe@huawei.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mcgrof@kernel.org \
--cc=mhocko@suse.com \
--cc=miklos@szeredi.hu \
--cc=nao.horiguchi@gmail.com \
--cc=nico.pache@linux.dev \
--cc=osalvador@suse.de \
--cc=paulmck@kernel.org \
--cc=pfalcato@suse.de \
--cc=qi.zheng@linux.dev \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=torvalds@linux-foundation.org \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--cc=viro@zeniv.linux.org.uk \
--cc=weixugc@google.com \
--cc=willy@infradead.org \
--cc=yuanchu@google.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.