From: Ye Liu <liuye@kylinos.cn>
Introduce for_each_process_rculock(), for_each_thread_rculock() and
for_each_process_thread_rculock() macros that combine the existing
iteration macros with scoped_guard(rcu), so that the RCU read lock
is automatically acquired before iteration and released when the
loop exits — including via break, goto, or return.
The rest of the series converts manual rcu_read_lock()/
rcu_read_unlock() and guard(rcu)() pairs across mm/, kernel/, fs/,
lib/ and security/ to use the new macros.
Suggested by Michal Hocko for the oom_kill path [2].
Signed-off-by: Ye Liu <liuye@kylinos.cn>
---
Changes since v2 [3]:
- Split the kernel/ patch into per-subsystem patches, as the
combined patch could not be applied (Peter Zijlstra, Steven
Rostedt).
- Move changelog below the --- separator so it is excluded from
the commit message (Lorenzo Stoakes).
- Indent loop body in macro definitions to show scoped_guard
scope (Lorenzo Stoakes).
Changes since v1 [1]:
- Rename macros from *_rcu to *_rculock, as suggested by Steven
Rostedt and acked by Thomas Gleixner, to avoid confusion with
existing *_rcu() list iterators that expect the caller to hold
the RCU read lock.
- Improve the comment on for_each_process_thread_rculock() to
document that 'break' only exits the inner loop and 'goto' is
needed to exit both loops (Thomas Gleixner).
- Rename the stale 'unlock:' label to 'out:' in hung_task.c, as
noted by Günther Noack.
- Clarify in patch 4 that page_pgoff() is safe outside the RCU
read-side critical section (SJ Park).
- CC all relevant maintainers on every patch (Lorenzo Stoakes).
- Drop the mm: prefix from patch 1, as the macros are in
From: Ye Liu <liuye@kylinos.cn>
Introduce for_each_process_rculock(), for_each_thread_rculock() and
for_each_process_thread_rculock() macros that acquire the RCU read
lock before the iteration starts and release it when the loop is left,
so that the RCU read-side critical section is scoped to the loop body
instead of an externally managed rcu_read_lock()/rcu_read_unlock()
pair.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Changes in v3:
- Indent loop body to show scoped_guard scope (Lorenzo Stoakes)
Changes in v2:
- Rename macros from *_rcu to *_rculock (Steven Rostedt, Thomas Gleixner)
- Improve comment on for_each_process_thread_rculock() double loop
- Change prefix from mm: to sched: (Michal Hocko)
include/linux/sched/signal.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
@@ -663,6 +664,31 @@ extern bool current_is_single_threaded(void); #define for_each_process_thread(p, t) \ for_each_process(p) for_each_thread(p, t)+/*+ * Variants of for_each_process(), for_each_thread() and+ * for_each_process_thread() that automatically acquire and release the+ * RCU read lock via scoped_guard(rcu). The lock is held for the+ * duration of the loop and released on exit, including via break,+ * goto, or return.+ */+#define for_each_process_rculock(p) \+ scoped_guard(rcu) \+ for (p = &init_task ; (p = next_task(p)) != &init_task ; )++#define for_each_thread_rculock(p, t) \+ scoped_guard(rcu) \+ __for_each_thread((p)->signal, t)++/*+ * Double loop: 'break' only exits the inner for_each_thread() loop.+ * Use 'goto' to exit both loops; the RCU read lock is released+ * automatically when the scoped_guard scope is left.+ */+#define for_each_process_thread_rculock(p, t) \+ scoped_guard(rcu) \+ for_each_process(p) \+ for_each_thread(p, t)+ typedef int (*proc_visitor)(struct task_struct *p, void *data); void walk_process_tree(struct task_struct *top, proc_visitor, void *);
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pairs wrapping
for_each_process()/for_each_thread() loops with for_each_process_rculock()
and for_each_thread_rculock(), which scope the RCU read lock to the
loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Changes in v2:
- Rename *_rcu to *_rculock
mm/oom_kill.c | 20 +++++---------------
1 file changed, 5 insertions(+), 15 deletions(-)
@@ -894,8 +888,7 @@ static bool task_will_free_mem(struct task_struct *task) * are dying as well to make sure that a) nobody pins its mm and * b) the task is also reapable by the oom reaper. */- rcu_read_lock();- for_each_process(p) {+ for_each_process_rculock(p) { if (!process_shares_mm(p, mm)) continue; if (same_thread_group(task, p))
@@ -960,8 +952,7 @@ static void __oom_kill_process(struct task_struct *victim, const char *message) * That thread will now get access to memory reserves since it has a * pending fatal signal. */- rcu_read_lock();- for_each_process(p) {+ for_each_process_rculock(p) { if (!process_shares_mm(p, mm)) continue; if (same_thread_group(p, victim))
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process() loop in mm/ksm.c with for_each_process_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Changes in v2:
- Rename *_rcu to *_rculock
mm/ksm.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pairs combined
with for_each_process() loop in mm/memory-failure.c with
for_each_process_rculock(), which scopes the RCU read lock to the
loop body via scoped_guard(rcu).
In collect_procs_file(), the page_pgoff() call now falls outside the
RCU read-side critical section. This is safe because page_pgoff()
only reads folio->index and does not traverse any RCU-protected
structures.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
---
Changes in v2:
- Rename *_rcu to *_rculock
- Clarify page_pgoff() safety outside RCU lock (SJ Park)
mm/memory-failure.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_thread() loop in kernel/cpu.c with for_each_thread_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/cpu.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_thread() loop in kernel/freezer.c with
for_each_thread_rculock(), which scopes the RCU read lock to the
loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/freezer.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process_thread() loop in kernel/hung_task.c with
for_each_process_thread_rculock(), which scopes the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
- Rename stale 'unlock:' label to 'out:' in hung_task.c (Günther Noack)
kernel/hung_task.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process_thread() loop in kernel/locking/lockdep.c with
for_each_process_thread_rculock(), which scopes the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/locking/lockdep.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process_thread() loop in kernel/rcu/update.c with
for_each_process_thread_rculock(), which scopes the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/rcu/update.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() and guard(rcu)
pairs combined with for_each_process_thread() loops in kernel/sched/
with for_each_process_thread_rculock(), which scopes the RCU read
lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/sched/core.c | 3 +--
kernel/sched/debug.c | 4 +---
2 files changed, 2 insertions(+), 5 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process_thread() loop in kernel/trace/fgraph.c with
for_each_process_thread_rculock(), which scopes the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/trace/fgraph.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace guard(rcu)() combined with for_each_process_thread() loop in
kernel/unwind/deferred.c with for_each_process_thread_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
---
Changes in v3:
- Split from kernel/ patch in v2 (Peter Zijlstra, Steven Rostedt)
Changes in v2:
- Rename *_rcu to *_rculock
kernel/unwind/deferred.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pairs combined
with for_each_process() and for_each_process_thread() loops in fs/
with the for_each_*_rculock() macros, which scope the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Changes in v2:
- Rename *_rcu to *_rculock
fs/proc/base.c | 4 +---
fs/resctrl/rdtgroup.c | 8 ++------
2 files changed, 3 insertions(+), 9 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process() loop in lib/ with for_each_process_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: SJ Park <sj@kernel.org>
---
Changes in v2:
- Rename *_rcu to *_rculock
lib/is_single_threaded.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
From: Ye Liu <liuye@kylinos.cn>
Replace guard(rcu)() + for_each_thread() with for_each_thread_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Reviewed-by: Justin Suess <redacted>
Reviewed-by: Günther Noack <redacted>
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Changes in v2:
- Rename *_rcu to *_rculock
security/landlock/tsync.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
From: Steven Rostedt <rostedt@goodmis.org> Date: 2026-09-11 12:57:04
On Fri, 11 Sep 2026 15:57:57 +0800
Ye Liu [off-list ref] wrote:
From: Ye Liu <liuye@kylinos.cn>
Replace guard(rcu)() combined with for_each_process_thread() loop in
kernel/unwind/deferred.c with for_each_process_thread_rculock(),
which scopes the RCU read lock to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
-- Steve
From: Steven Rostedt <rostedt@goodmis.org> Date: 2026-09-11 12:58:31
On Fri, 11 Sep 2026 15:57:56 +0800
Ye Liu [off-list ref] wrote:
From: Ye Liu <liuye@kylinos.cn>
Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined
with for_each_process_thread() loop in kernel/trace/fgraph.c with
for_each_process_thread_rculock(), which scopes the RCU read lock
to the loop body via scoped_guard(rcu).
No functional change.
Signed-off-by: Ye Liu <liuye@kylinos.cn>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
-- Steve