From 155cf09222aaa60aa133b33e95af1f2233939d76 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:47 +0800 Subject: [PATCH 01/15] sched: introduce for_each_process_rculock and for_each_thread_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Gregory Price (Meta) Reviewed-by: Oleg Nesterov Reviewed-by: Lorenzo Stoakes (ARM) --- include/linux/sched/signal.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 584ae88b435e..ea23c7e9db33 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -2,6 +2,7 @@ #ifndef _LINUX_SCHED_SIGNAL_H #define _LINUX_SCHED_SIGNAL_H +#include #include #include #include @@ -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 0b5699fba86115a47dffafff60715e49f5b93cc4 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:48 +0800 Subject: [PATCH 02/15] mm/oom_kill: convert process/thread iterators to for_each_*_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Gregory Price (Meta) Reviewed-by: Lorenzo Stoakes (ARM) --- mm/oom_kill.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 5f372f6e26fa..ef2e1c423c1d 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -94,8 +94,7 @@ static bool oom_cpuset_eligible(struct task_struct *start, bool ret = false; const nodemask_t *mask = oc->nodemask; - rcu_read_lock(); - for_each_thread(start, tsk) { + for_each_thread_rculock(start, tsk) { if (mask) { /* * If this is a mempolicy constrained oom, tsk's @@ -114,7 +113,6 @@ static bool oom_cpuset_eligible(struct task_struct *start, if (ret) break; } - rcu_read_unlock(); return ret; } @@ -368,11 +366,9 @@ static void select_bad_process(struct oom_control *oc) else { struct task_struct *p; - rcu_read_lock(); - for_each_process(p) + for_each_process_rculock(p) if (oom_evaluate_task(p, oc)) break; - rcu_read_unlock(); } } @@ -430,14 +426,12 @@ static void dump_tasks(struct oom_control *oc) struct task_struct *p; int i = 0; - rcu_read_lock(); - for_each_process(p) { + for_each_process_rculock(p) { /* Avoid potential softlockup warning */ if ((++i & 1023) == 0) touch_softlockup_watchdog(); dump_task(p, oc); } - rcu_read_unlock(); } } @@ -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)) @@ -904,7 +897,6 @@ static bool task_will_free_mem(struct task_struct *task) if (!ret) break; } - rcu_read_unlock(); return ret; } @@ -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)) @@ -982,7 +973,6 @@ static void __oom_kill_process(struct task_struct *victim, const char *message) continue; do_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_TGID); } - rcu_read_unlock(); if (can_oom_reap) queue_oom_reaper(victim); From 18ceb04e7a772fd9a1400638eec5bc1a7744c2a1 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:49 +0800 Subject: [PATCH 03/15] mm/ksm: convert process iterator to for_each_process_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Acked-by: David Hildenbrand (Arm) Reviewed-by: Gregory Price (Meta) Reviewed-by: Lorenzo Stoakes (ARM) --- mm/ksm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/ksm.c b/mm/ksm.c index 49d48d1e0998..69d30e80a090 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -3280,8 +3280,7 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page, struct anon_vma *av = rmap_item->anon_vma; anon_vma_lock_read(av); - rcu_read_lock(); - for_each_process(tsk) { + for_each_process_rculock(tsk) { struct anon_vma_chain *vmac; const unsigned long addr = rmap_item->address & PAGE_MASK; const unsigned long index = rmap_item->linear_page_index; @@ -3298,7 +3297,6 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page, } } } - rcu_read_unlock(); anon_vma_unlock_read(av); } } From 1ee4940bcf4e7938582ff4348e69c959c3565a18 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:50 +0800 Subject: [PATCH 04/15] mm/memory-failure: convert process iterator to for_each_process_rculock 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 Acked-by: Michal Hocko Acked-by: Miaohe Lin Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: SJ Park Reviewed-by: Gregory Price (Meta) --- mm/memory-failure.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index a8b03e2920ba..7d93deb1f7b3 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -555,8 +555,7 @@ static void collect_procs_anon(const struct folio *folio, return; pgoff = page_pgoff(folio, page); - rcu_read_lock(); - for_each_process(tsk) { + for_each_process_rculock(tsk) { struct vm_area_struct *vma; struct anon_vma_chain *vmac; struct task_struct *t = task_early_kill(tsk, force_early); @@ -572,7 +571,6 @@ static void collect_procs_anon(const struct folio *folio, add_to_kill_anon_file(t, page, vma, to_kill, addr); } } - rcu_read_unlock(); anon_vma_unlock_read(av); } @@ -589,9 +587,8 @@ static void collect_procs_file(const struct folio *folio, pgoff_t pgoff; i_mmap_lock_read(mapping); - rcu_read_lock(); pgoff = page_pgoff(folio, page); - for_each_process(tsk) { + for_each_process_rculock(tsk) { struct task_struct *t = task_early_kill(tsk, force_early); unsigned long addr; @@ -611,7 +608,6 @@ static void collect_procs_file(const struct folio *folio, add_to_kill_anon_file(t, page, vma, to_kill, addr); } } - rcu_read_unlock(); i_mmap_unlock_read(mapping); } @@ -635,8 +631,7 @@ static void collect_procs_fsdax(const struct page *page, struct task_struct *tsk; i_mmap_lock_read(mapping); - rcu_read_lock(); - for_each_process(tsk) { + for_each_process_rculock(tsk) { struct task_struct *t = tsk; /* @@ -653,7 +648,6 @@ static void collect_procs_fsdax(const struct page *page, add_to_kill_fsdax(t, page, vma, to_kill, pgoff); } } - rcu_read_unlock(); i_mmap_unlock_read(mapping); } #endif /* CONFIG_FS_DAX */ @@ -2288,8 +2282,7 @@ static void collect_procs_pfn(struct pfn_address_space *pfn_space, struct address_space *mapping = pfn_space->mapping; i_mmap_lock_read(mapping); - rcu_read_lock(); - for_each_process(tsk) { + for_each_process_rculock(tsk) { struct task_struct *t = tsk; t = task_early_kill(tsk, true); @@ -2303,7 +2296,6 @@ static void collect_procs_pfn(struct pfn_address_space *pfn_space, add_to_kill_pgoff(t, vma, to_kill, pgoff); } } - rcu_read_unlock(); i_mmap_unlock_read(mapping); } From 3e3087cb8d98435f8a2d70406309bed34ea4995e Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:51 +0800 Subject: [PATCH 05/15] cpu/hotplug: convert process iterator to for_each_process_rculock Replace the manual rcu_read_lock()/rcu_read_unlock() pair combined with for_each_process() loop in kernel/cpu.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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/cpu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index b3c8553d7bd6..00638d2abc0f 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1254,8 +1254,7 @@ void clear_tasks_mm_cpumask(int cpu) * full-fledged tasklist_lock. */ WARN_ON(cpu_online(cpu)); - rcu_read_lock(); - for_each_process(p) { + for_each_process_rculock(p) { struct task_struct *t; /* @@ -1268,7 +1267,6 @@ void clear_tasks_mm_cpumask(int cpu) arch_clear_mm_cpumask_cpu(cpu, t->mm); task_unlock(t); } - rcu_read_unlock(); } /* Take this CPU down. */ From 37e43eedd1a68aa60127ec5d6e3b78ab3436650e Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:52 +0800 Subject: [PATCH 06/15] freezer: convert thread iterator to for_each_thread_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/freezer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/freezer.c b/kernel/freezer.c index a76bf957fb32..7a870f71dcf6 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c @@ -217,11 +217,9 @@ void thaw_process(struct task_struct *p) { struct task_struct *t; - rcu_read_lock(); - for_each_thread(p, t) { + for_each_thread_rculock(p, t) { __thaw_task(t); } - rcu_read_unlock(); } /** From 0019ea430ee8b68349e22627771fc331665b3e4e Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:53 +0800 Subject: [PATCH 07/15] hung_task: convert process/thread iterators to for_each_*_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/hung_task.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/kernel/hung_task.c b/kernel/hung_task.c index 6fcc94ce4ca9..73a5ad3be9a8 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c @@ -315,13 +315,12 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) return; this_round_count = 0; - rcu_read_lock(); - for_each_process_thread(g, t) { + for_each_process_thread_rculock(g, t) { if (!max_count--) - goto unlock; + goto out; if (time_after(jiffies, last_break + HUNG_TASK_LOCK_BREAK)) { if (!rcu_lock_break(g, t)) - goto unlock; + goto out; last_break = jiffies; } @@ -337,9 +336,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) hung_task_info(t, timeout, this_round_count); } } - unlock: - rcu_read_unlock(); - +out: if (!this_round_count) return; From b98b02b88a607d536a65adac6d93b0991d05327c Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:54 +0800 Subject: [PATCH 08/15] locking/lockdep: convert process/thread iterators to for_each_*_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/locking/lockdep.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index c56a7f91d72e..ea218dc75ad5 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -6834,15 +6834,13 @@ void debug_show_all_locks(void) } pr_warn("\nShowing all locks held in the system:\n"); - rcu_read_lock(); - for_each_process_thread(g, p) { + for_each_process_thread_rculock(g, p) { if (!p->lockdep_depth) continue; lockdep_print_held_locks(p); touch_nmi_watchdog(); touch_all_softlockup_watchdogs(); } - rcu_read_unlock(); pr_warn("\n"); pr_warn("=============================================\n\n"); From 150747d304d063e5169e7cf6eea53c0e429c1e94 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:55 +0800 Subject: [PATCH 09/15] rcu: convert process/thread iterator to for_each_process_thread_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/rcu/update.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index b62735a67884..bac6366da41e 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -547,15 +547,13 @@ void synchronize_rcu_trivial_preempt(void) struct task_struct *t; smp_mb(); // Order prior accesses before grace-period start. - rcu_read_lock(); // Protect task list. - for_each_process_thread(g, t) { + for_each_process_thread_rculock(g, t) { if (t == current) continue; // Don't deadlock on ourselves! // Order later rcu_read_lock() on other tasks after QS. while (smp_load_acquire(&t->rcu_trivial_preempt_nesting)) continue; } - rcu_read_unlock(); } EXPORT_SYMBOL_GPL(synchronize_rcu_trivial_preempt); #endif // #if IS_ENABLED(CONFIG_TRIVIAL_PREEMPT_RCU) From 515bd548fdc22183764587a3dcd6441f74fd0fd7 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:56 +0800 Subject: [PATCH 10/15] sched: convert process/thread iterators to for_each_*_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov --- kernel/sched/core.c | 3 +-- kernel/sched/debug.c | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f78275192036..7f9dbd4c7d62 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2015,8 +2015,7 @@ static void uclamp_sync_util_min_rt_default(void) smp_mb__after_spinlock(); read_unlock(&tasklist_lock); - guard(rcu)(); - for_each_process_thread(g, p) + for_each_process_thread_rculock(g, p) uclamp_update_util_min_rt_default(p); } diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 72236db67983..cdae165b98f7 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -1029,14 +1029,12 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu) #endif "\n"); - rcu_read_lock(); - for_each_process_thread(g, p) { + for_each_process_thread_rculock(g, p) { if (task_cpu(p) != rq_cpu) continue; print_task(m, rq, p); } - rcu_read_unlock(); } void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) From 253ca48cae4969269d475bbb3dd9735d8f570e09 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:57 +0800 Subject: [PATCH 11/15] tracing/fgraph: convert process/thread iterator to for_each_process_thread_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov Acked-by: Steven Rostedt --- kernel/trace/fgraph.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c index 40d373d65f9b..f797ce119223 100644 --- a/kernel/trace/fgraph.c +++ b/kernel/trace/fgraph.c @@ -1057,11 +1057,10 @@ static int alloc_retstack_tasklist(unsigned long **ret_stack_list) } } - rcu_read_lock(); - for_each_process_thread(g, t) { + for_each_process_thread_rculock(g, t) { if (start == end) { ret = -EAGAIN; - goto unlock; + goto free; } if (t->ret_stack == NULL) { @@ -1074,9 +1073,6 @@ static int alloc_retstack_tasklist(unsigned long **ret_stack_list) t->ret_stack = ret_stack_list[start++]; } } - -unlock: - rcu_read_unlock(); free: for (i = start; i < end; i++) kmem_cache_free(fgraph_stack_cachep, ret_stack_list[i]); From 945933905f8825f9f303f73017f5e6ab4387573f Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:58 +0800 Subject: [PATCH 12/15] unwind: convert process/thread iterator to for_each_process_thread_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Oleg Nesterov Acked-by: Steven Rostedt --- kernel/unwind/deferred.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c index 5bea47314254..ecfe1336095e 100644 --- a/kernel/unwind/deferred.c +++ b/kernel/unwind/deferred.c @@ -319,9 +319,8 @@ void unwind_deferred_cancel(struct unwind_work *work) synchronize_srcu(&unwind_srcu); - guard(rcu)(); /* Clear this bit from all threads */ - for_each_process_thread(g, t) { + for_each_process_thread_rculock(g, t) { atomic_long_andnot(BIT(bit), &t->unwind_info.unwind_mask); if (t->unwind_info.cache) From e2dba746dc268f92d71a05e7febbb139a5d06299 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:20:59 +0800 Subject: [PATCH 13/15] fs: convert process/thread iterators to for_each_*_rculock 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 Acked-by: Michal Hocko Reviewed-by: SJ Park Reviewed-by: Gregory Price (Meta) Reviewed-by: Lorenzo Stoakes (ARM) --- fs/proc/base.c | 4 +--- fs/resctrl/rdtgroup.c | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 6a39de424f62..3de4f4557e4c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1160,8 +1160,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) if (mm) { struct task_struct *p; - rcu_read_lock(); - for_each_process(p) { + for_each_process_rculock(p) { if (same_thread_group(task, p)) continue; @@ -1177,7 +1176,6 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) } task_unlock(p); } - rcu_read_unlock(); mmdrop(mm); } err_unlock: diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 5dcbb0a964e8..b14df8b23f1a 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -709,14 +709,12 @@ int rdtgroup_tasks_assigned(struct rdtgroup *r) lockdep_assert_held(&rdtgroup_mutex); - rcu_read_lock(); - for_each_process_thread(p, t) { + for_each_process_thread_rculock(p, t) { if (is_closid_match(t, r) || is_rmid_match(t, r)) { ret = 1; break; } } - rcu_read_unlock(); return ret; } @@ -826,15 +824,13 @@ static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s) struct task_struct *p, *t; pid_t pid; - rcu_read_lock(); - for_each_process_thread(p, t) { + for_each_process_thread_rculock(p, t) { if (is_closid_match(t, r) || is_rmid_match(t, r)) { pid = task_pid_vnr(t); if (pid) seq_printf(s, "%d\n", pid); } } - rcu_read_unlock(); } static int rdtgroup_tasks_show(struct kernfs_open_file *of, From 5b2cc48829913cf140d75f31a7a14aa908967cca Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:33:10 +0800 Subject: [PATCH 14/15] lib: convert process iterator to for_each_process_rculock 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 Acked-by: Michal Hocko Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Gregory Price (Meta) Reviewed-by: SJ Park --- lib/is_single_threaded.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c index 8c98b20bfc41..4e7fe85454ab 100644 --- a/lib/is_single_threaded.c +++ b/lib/is_single_threaded.c @@ -26,8 +26,7 @@ bool current_is_single_threaded(void) return true; ret = false; - rcu_read_lock(); - for_each_process(p) { + for_each_process_rculock(p) { if (unlikely(p->flags & PF_KTHREAD)) continue; if (unlikely(p == task->group_leader)) @@ -48,7 +47,5 @@ bool current_is_single_threaded(void) } ret = true; found: - rcu_read_unlock(); - return ret; } From bd66c25299a970d536950aef59b5ace5a291b172 Mon Sep 17 00:00:00 2001 From: Ye Liu Date: Mon, 21 Sep 2026 17:33:33 +0800 Subject: [PATCH 15/15] security/landlock: convert thread iterator to for_each_thread_rculock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Justin Suess Reviewed-by: Günther Noack Reviewed-by: Gregory Price (Meta) Reviewed-by: SJ Park Reviewed-by: Lorenzo Stoakes (ARM) --- security/landlock/tsync.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/security/landlock/tsync.c b/security/landlock/tsync.c index cfa73a2a67ca..ec1fab0beac9 100644 --- a/security/landlock/tsync.c +++ b/security/landlock/tsync.c @@ -351,9 +351,7 @@ static size_t count_additional_threads(const struct tsync_works *works) caller = current; - guard(rcu)(); - - for_each_thread(caller, thread) { + for_each_thread_rculock(caller, thread) { /* Skip current, since it is initiating the sync. */ if (thread == caller) continue; @@ -392,9 +390,7 @@ static bool schedule_task_work(struct tsync_works *works, caller = current; - guard(rcu)(); - - for_each_thread(caller, thread) { + for_each_thread_rculock(caller, thread) { /* Skip current, since it is initiating the sync. */ if (thread == caller) continue;