* FAILED: patch "[PATCH] mm/kmemleak: report RCU-tasks quiescent states during the" failed to apply to 6.12-stable tree
@ 2026-09-03 10:47 gregkh
2026-09-03 18:32 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-09-03 10:47 UTC (permalink / raw)
To: leitao, akpm, catalin.marinas, paulmck, puranjay, sj, stable; +Cc: stable
The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 3541a2b06ecd78ba333188df04368dcf97273d6a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090345-doorpost-concur-ba65@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 3541a2b06ecd78ba333188df04368dcf97273d6a Mon Sep 17 00:00:00 2001
From: Breno Leitao <leitao@debian.org>
Date: Mon, 20 Jul 2026 06:23:45 -0700
Subject: [PATCH] mm/kmemleak: report RCU-tasks quiescent states during the
scan
kmemleak_scan() can run for ages on large debug kernels. It was
causing some soft-lockups which I got fixed with commit
3175fcfec8b16baeb ("mm/kmemleak: avoid soft lockup when scanning task
stacks") with our beloved cond_resched().
I've got the fix above deployed in the Meta fleet, and now I am seeing:
INFO: rcu_tasks detected stalls on tasks:
task:kmemleak state:R ... nvcsw: 274/274 holdout: 1 idle_cpu: -1/3
scan_block
scan_gray_list
kmemleak_scan
and, worse, blocks the callers waiting on that grace period. Here a BPF
struct_ops map free, which waits via synchronize_rcu_mult(call_rcu,
call_rcu_tasks), is stuck long enough to also trip the hung task check:
INFO: task kworker/...:bpf_map_free_deferred blocked for 122 seconds
__wait_rcu_gp
bpf_struct_ops_map_free
Then I've learned that cond_resched() is not an RCU-tasks quiescent
state, so, we need to use stronger primitives.
Use cond_resched_tasks_rcu_qs() at the scan reschedule points so the scan
reports an RCU-tasks quiescent state as it proceeds.
Inspired by commit b96285e10aad ("tracing: Have osnoise_main() add a
quiescent state for task rcu").
Link: https://lore.kernel.org/20260720-kmemleak_rcu_task-v1-1-5b460ade777d@debian.org
Fixes: c4b28963fd79 ("mm/kmemleak: rely on rcu for task stack scanning")
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Breno Leitao <leitao@debian.org>
Cc: Puranjay Mohan <puranjay@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index e96e9efd19b0..0a6045c857d6 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1571,7 +1571,7 @@ static int scan_large_block(void *start, void *end)
if (scan_block(start, next, NULL))
return 1;
start = next;
- cond_resched();
+ cond_resched_tasks_rcu_qs();
}
return 0;
@@ -1608,7 +1608,7 @@ static void scan_object(struct kmemleak_object *object)
scan_block(start, end, object);
raw_spin_unlock_irqrestore(&object->lock, flags);
- cond_resched();
+ cond_resched_tasks_rcu_qs();
raw_spin_lock_irqsave(&object->lock, flags);
if (!(object->flags & OBJECT_ALLOCATED))
break;
@@ -1630,7 +1630,7 @@ static void scan_object(struct kmemleak_object *object)
break;
raw_spin_unlock_irqrestore(&object->lock, flags);
- cond_resched();
+ cond_resched_tasks_rcu_qs();
raw_spin_lock_irqsave(&object->lock, flags);
} while (object->flags & OBJECT_ALLOCATED);
} else {
@@ -1658,7 +1658,7 @@ static void scan_gray_list(void)
*/
object = list_entry(gray_list.next, typeof(*object), gray_list);
while (&object->gray_list != &gray_list) {
- cond_resched();
+ cond_resched_tasks_rcu_qs();
/* may add new objects to the list */
if (!scan_should_stop())
@@ -1693,7 +1693,7 @@ static void kmemleak_cond_resched(struct kmemleak_object *object)
raw_spin_unlock_irq(&kmemleak_lock);
rcu_read_unlock();
- cond_resched();
+ cond_resched_tasks_rcu_qs();
rcu_read_lock();
raw_spin_lock_irq(&kmemleak_lock);
@@ -1738,7 +1738,7 @@ static void kmemleak_scan_task_stacks(void)
}
put_task_struct(p);
}
- cond_resched();
+ cond_resched_tasks_rcu_qs();
} while (pid && !stop);
}
@@ -1915,7 +1915,7 @@ static void kmemleak_scan(void)
struct page *page = pfn_to_online_page(pfn);
if (!(pfn & 63))
- cond_resched();
+ cond_resched_tasks_rcu_qs();
if (!page)
continue;
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks 2026-09-03 10:47 FAILED: patch "[PATCH] mm/kmemleak: report RCU-tasks quiescent states during the" failed to apply to 6.12-stable tree gregkh @ 2026-09-03 18:32 ` Sasha Levin 2026-09-03 18:32 ` [PATCH 6.12.y 2/2] mm/kmemleak: report RCU-tasks quiescent states during the scan Sasha Levin 2026-09-17 11:22 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Greg KH 0 siblings, 2 replies; 4+ messages in thread From: Sasha Levin @ 2026-09-03 18:32 UTC (permalink / raw) To: stable Cc: Breno Leitao, Catalin Marinas, Davidlohr Bueso, Lance Yang, Oleg Nesterov, Qian Cai, SeongJae Park, Andrew Morton, Sasha Levin From: Breno Leitao <leitao@debian.org> [ Upstream commit 5d10d4e19e6daa487f0cd0ea6cba472325de92f9 ] Patch series "mm/kmemleak: avoid soft lockup when scanning task", v3. kmemleak_scan() scans every task stack under one rcu_read_lock() with no reschedule point, which can trip the soft lockup watchdog on hosts with very many threads. That prints the following message, depending on the workload+host configuration: watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537] scan_block kmemleak_scan kmemleak_scan_thread kthread Patch 1 walks the tasks with find_ge_pid() so the scan reschedules between tasks Patches 2-3 let the scan loops stop early once a scan is interrupted. This patch (of 3): kmemleak_scan() walks every thread and scans its kernel stack under a single rcu_read_lock() with no reschedule point. On a host with very many threads -- amplified by KASAN/lockdep in debug builds -- this loop can hog a CPU long enough to trip the soft lockup watchdog: watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537] scan_block kmemleak_scan kmemleak_scan_thread kthread A cond_resched() cannot be added directly: the loop runs inside an RCU read-side critical section. Walk the tasks one PID at a time with find_ge_pid(), taking the RCU read lock only to look up and pin each task. The stack is then scanned with no lock held, so cond_resched() runs between tasks and the scan stops early on scan_should_stop(). This follows the next_tgid()/task_seq_get_next() iteration pattern and keeps each RCU critical section short. Link: https://lore.kernel.org/20260615-kmemleak-stack-resched-v3-0-acecd7d7fd92@debian.org Link: https://lore.kernel.org/20260615-kmemleak-stack-resched-v3-1-acecd7d7fd92@debian.org Fixes: c4b28963fd79 ("mm/kmemleak: rely on rcu for task stack scanning") Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Reviewed-by: Lance Yang <lance.yang@linux.dev> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Qian Cai <cai@lca.pw> Cc: SeongJae Park <sj@kernel.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Stable-dep-of: 3541a2b06ecd ("mm/kmemleak: report RCU-tasks quiescent states during the scan") Signed-off-by: Sasha Levin <sashal@kernel.org> --- mm/kmemleak.c | 91 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 4092f38d3fc84..0dcdddb3c33d8 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1499,22 +1499,25 @@ static int scan_should_stop(void) /* * Scan a memory block (exclusive range) for valid pointers and add those - * found to the gray list. + * found to the gray list. Return non-zero if the scan was interrupted. */ -static void scan_block(void *_start, void *_end, - struct kmemleak_object *scanned) +static int scan_block(void *_start, void *_end, + struct kmemleak_object *scanned) { unsigned long *ptr; unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER); unsigned long *end = _end - (BYTES_PER_POINTER - 1); unsigned long flags; + int stop = 0; raw_spin_lock_irqsave(&kmemleak_lock, flags); for (ptr = start; ptr < end; ptr++) { unsigned long pointer; - if (scan_should_stop()) + if (scan_should_stop()) { + stop = 1; break; + } kasan_disable_current(); pointer = *(unsigned long *)kasan_reset_tag((void *)ptr); @@ -1524,22 +1527,28 @@ static void scan_block(void *_start, void *_end, pointer_update_refs(scanned, pointer, OBJECT_PERCPU); } raw_spin_unlock_irqrestore(&kmemleak_lock, flags); + + return stop; } /* * Scan a large memory block in MAX_SCAN_SIZE chunks to reduce the latency. + * Return non-zero if the scan was interrupted. */ #ifdef CONFIG_SMP -static void scan_large_block(void *start, void *end) +static int scan_large_block(void *start, void *end) { void *next; while (start < end) { next = min(start + MAX_SCAN_SIZE, end); - scan_block(start, next, NULL); + if (scan_block(start, next, NULL)) + return 1; start = next; cond_resched(); } + + return 0; } #endif @@ -1670,6 +1679,43 @@ static void kmemleak_cond_resched(struct kmemleak_object *object) put_object(object); } +/* + * Scan all task kernel stacks, rescheduling between tasks. Each task is looked + * up and pinned within its own RCU read-side section, so no lock is held across + * the scan and the walk cannot trip the soft lockup watchdog. + */ +static void kmemleak_scan_task_stacks(void) +{ + struct pid *pid; + int nr = 1; + int stop = 0; + + do { + struct task_struct *p = NULL; + + rcu_read_lock(); + pid = find_ge_pid(nr, &init_pid_ns); + if (pid) { + nr = pid_nr(pid) + 1; + p = pid_task(pid, PIDTYPE_PID); + if (p) + get_task_struct(p); + } + rcu_read_unlock(); + + if (p) { + void *stack = try_get_task_stack(p); + + if (stack) { + stop = scan_block(stack, stack + THREAD_SIZE, NULL); + put_task_stack(p); + } + put_task_struct(p); + } + cond_resched(); + } while (pid && !stop); +} + /* * Scan data sections and all the referenced memory blocks allocated via the * kernel's standard allocators. This function must be called with the @@ -1681,6 +1727,7 @@ static void kmemleak_scan(void) struct zone *zone; int __maybe_unused i; int new_leaks = 0; + int stop = 0; jiffies_last_scan = jiffies; @@ -1724,9 +1771,11 @@ static void kmemleak_scan(void) #ifdef CONFIG_SMP /* per-cpu sections scanning */ - for_each_possible_cpu(i) - scan_large_block(__per_cpu_start + per_cpu_offset(i), - __per_cpu_end + per_cpu_offset(i)); + for_each_possible_cpu(i) { + if (scan_large_block(__per_cpu_start + per_cpu_offset(i), + __per_cpu_end + per_cpu_offset(i))) + goto scan_gray; + } #endif /* @@ -1753,32 +1802,28 @@ static void kmemleak_scan(void) /* only scan if page is in use */ if (page_count(page) == 0) continue; - scan_block(page, page + 1, NULL); + stop = scan_block(page, page + 1, NULL); + if (stop) + break; } + if (stop) + break; } put_online_mems(); + if (stop) + goto scan_gray; /* * Scanning the task stacks (may introduce false negatives). */ - if (kmemleak_stack_scan) { - struct task_struct *p, *g; - - rcu_read_lock(); - for_each_process_thread(g, p) { - void *stack = try_get_task_stack(p); - if (stack) { - scan_block(stack, stack + THREAD_SIZE, NULL); - put_task_stack(p); - } - } - rcu_read_unlock(); - } + if (kmemleak_stack_scan) + kmemleak_scan_task_stacks(); /* * Scan the objects already referenced from the sections scanned * above. */ +scan_gray: scan_gray_list(); /* -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.12.y 2/2] mm/kmemleak: report RCU-tasks quiescent states during the scan 2026-09-03 18:32 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Sasha Levin @ 2026-09-03 18:32 ` Sasha Levin 2026-09-17 11:22 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Greg KH 1 sibling, 0 replies; 4+ messages in thread From: Sasha Levin @ 2026-09-03 18:32 UTC (permalink / raw) To: stable Cc: Breno Leitao, Paul E. McKenney, SJ Park, Catalin Marinas, Puranjay Mohan, Andrew Morton, Sasha Levin From: Breno Leitao <leitao@debian.org> [ Upstream commit 3541a2b06ecd78ba333188df04368dcf97273d6a ] kmemleak_scan() can run for ages on large debug kernels. It was causing some soft-lockups which I got fixed with commit 3175fcfec8b16baeb ("mm/kmemleak: avoid soft lockup when scanning task stacks") with our beloved cond_resched(). I've got the fix above deployed in the Meta fleet, and now I am seeing: INFO: rcu_tasks detected stalls on tasks: task:kmemleak state:R ... nvcsw: 274/274 holdout: 1 idle_cpu: -1/3 scan_block scan_gray_list kmemleak_scan and, worse, blocks the callers waiting on that grace period. Here a BPF struct_ops map free, which waits via synchronize_rcu_mult(call_rcu, call_rcu_tasks), is stuck long enough to also trip the hung task check: INFO: task kworker/...:bpf_map_free_deferred blocked for 122 seconds __wait_rcu_gp bpf_struct_ops_map_free Then I've learned that cond_resched() is not an RCU-tasks quiescent state, so, we need to use stronger primitives. Use cond_resched_tasks_rcu_qs() at the scan reschedule points so the scan reports an RCU-tasks quiescent state as it proceeds. Inspired by commit b96285e10aad ("tracing: Have osnoise_main() add a quiescent state for task rcu"). Link: https://lore.kernel.org/20260720-kmemleak_rcu_task-v1-1-5b460ade777d@debian.org Fixes: c4b28963fd79 ("mm/kmemleak: rely on rcu for task stack scanning") Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Paul E. McKenney <paulmck@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Breno Leitao <leitao@debian.org> Cc: Puranjay Mohan <puranjay@kernel.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> --- mm/kmemleak.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 0dcdddb3c33d8..1957bb7c670e7 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1545,7 +1545,7 @@ static int scan_large_block(void *start, void *end) if (scan_block(start, next, NULL)) return 1; start = next; - cond_resched(); + cond_resched_tasks_rcu_qs(); } return 0; @@ -1582,7 +1582,7 @@ static void scan_object(struct kmemleak_object *object) scan_block(start, end, object); raw_spin_unlock_irqrestore(&object->lock, flags); - cond_resched(); + cond_resched_tasks_rcu_qs(); raw_spin_lock_irqsave(&object->lock, flags); if (!(object->flags & OBJECT_ALLOCATED)) break; @@ -1604,7 +1604,7 @@ static void scan_object(struct kmemleak_object *object) break; raw_spin_unlock_irqrestore(&object->lock, flags); - cond_resched(); + cond_resched_tasks_rcu_qs(); raw_spin_lock_irqsave(&object->lock, flags); } while (object->flags & OBJECT_ALLOCATED); } else { @@ -1632,7 +1632,7 @@ static void scan_gray_list(void) */ object = list_entry(gray_list.next, typeof(*object), gray_list); while (&object->gray_list != &gray_list) { - cond_resched(); + cond_resched_tasks_rcu_qs(); /* may add new objects to the list */ if (!scan_should_stop()) @@ -1667,7 +1667,7 @@ static void kmemleak_cond_resched(struct kmemleak_object *object) raw_spin_unlock_irq(&kmemleak_lock); rcu_read_unlock(); - cond_resched(); + cond_resched_tasks_rcu_qs(); rcu_read_lock(); raw_spin_lock_irq(&kmemleak_lock); @@ -1712,7 +1712,7 @@ static void kmemleak_scan_task_stacks(void) } put_task_struct(p); } - cond_resched(); + cond_resched_tasks_rcu_qs(); } while (pid && !stop); } @@ -1791,7 +1791,7 @@ static void kmemleak_scan(void) struct page *page = pfn_to_online_page(pfn); if (!(pfn & 63)) - cond_resched(); + cond_resched_tasks_rcu_qs(); if (!page) continue; -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks 2026-09-03 18:32 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Sasha Levin 2026-09-03 18:32 ` [PATCH 6.12.y 2/2] mm/kmemleak: report RCU-tasks quiescent states during the scan Sasha Levin @ 2026-09-17 11:22 ` Greg KH 1 sibling, 0 replies; 4+ messages in thread From: Greg KH @ 2026-09-17 11:22 UTC (permalink / raw) To: Sasha Levin Cc: stable, Breno Leitao, Catalin Marinas, Davidlohr Bueso, Lance Yang, Oleg Nesterov, Qian Cai, SeongJae Park, Andrew Morton On Thu, Sep 03, 2026 at 02:32:41PM -0400, Sasha Levin wrote: > From: Breno Leitao <leitao@debian.org> > > [ Upstream commit 5d10d4e19e6daa487f0cd0ea6cba472325de92f9 ] > > Patch series "mm/kmemleak: avoid soft lockup when scanning task", v3. > > kmemleak_scan() scans every task stack under one rcu_read_lock() with no > reschedule point, which can trip the soft lockup watchdog on hosts with > very many threads. > > That prints the following message, depending on the workload+host > configuration: > > watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537] > scan_block > kmemleak_scan > kmemleak_scan_thread > kthread > > Patch 1 walks the tasks with find_ge_pid() so the scan reschedules between > tasks > > Patches 2-3 let the scan loops stop early once a scan is interrupted. > > This patch (of 3): > > kmemleak_scan() walks every thread and scans its kernel stack under a > single rcu_read_lock() with no reschedule point. On a host with very many > threads -- amplified by KASAN/lockdep in debug builds -- this loop can hog > a CPU long enough to trip the soft lockup watchdog: > > watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537] > scan_block > kmemleak_scan > kmemleak_scan_thread > kthread > > A cond_resched() cannot be added directly: the loop runs inside an RCU > read-side critical section. > > Walk the tasks one PID at a time with find_ge_pid(), taking the RCU read > lock only to look up and pin each task. The stack is then scanned with no > lock held, so cond_resched() runs between tasks and the scan stops early > on scan_should_stop(). This follows the next_tgid()/task_seq_get_next() > iteration pattern and keeps each RCU critical section short. > > Link: https://lore.kernel.org/20260615-kmemleak-stack-resched-v3-0-acecd7d7fd92@debian.org > Link: https://lore.kernel.org/20260615-kmemleak-stack-resched-v3-1-acecd7d7fd92@debian.org > Fixes: c4b28963fd79 ("mm/kmemleak: rely on rcu for task stack scanning") > Signed-off-by: Breno Leitao <leitao@debian.org> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> > Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> > Reviewed-by: Lance Yang <lance.yang@linux.dev> > Reviewed-by: Oleg Nesterov <oleg@redhat.com> > Cc: Qian Cai <cai@lca.pw> > Cc: SeongJae Park <sj@kernel.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org> > Stable-dep-of: 3541a2b06ecd ("mm/kmemleak: report RCU-tasks quiescent states during the scan") > Signed-off-by: Sasha Levin <sashal@kernel.org> > --- > mm/kmemleak.c | 91 ++++++++++++++++++++++++++++++++++++++------------- > 1 file changed, 68 insertions(+), 23 deletions(-) > > diff --git a/mm/kmemleak.c b/mm/kmemleak.c > index 4092f38d3fc84..0dcdddb3c33d8 100644 > --- a/mm/kmemleak.c > +++ b/mm/kmemleak.c > @@ -1499,22 +1499,25 @@ static int scan_should_stop(void) > > /* > * Scan a memory block (exclusive range) for valid pointers and add those > - * found to the gray list. > + * found to the gray list. Return non-zero if the scan was interrupted. > */ > -static void scan_block(void *_start, void *_end, > - struct kmemleak_object *scanned) > +static int scan_block(void *_start, void *_end, > + struct kmemleak_object *scanned) > { > unsigned long *ptr; > unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER); > unsigned long *end = _end - (BYTES_PER_POINTER - 1); > unsigned long flags; > + int stop = 0; > > raw_spin_lock_irqsave(&kmemleak_lock, flags); > for (ptr = start; ptr < end; ptr++) { > unsigned long pointer; > > - if (scan_should_stop()) > + if (scan_should_stop()) { > + stop = 1; > break; > + } > > kasan_disable_current(); > pointer = *(unsigned long *)kasan_reset_tag((void *)ptr); > @@ -1524,22 +1527,28 @@ static void scan_block(void *_start, void *_end, > pointer_update_refs(scanned, pointer, OBJECT_PERCPU); > } > raw_spin_unlock_irqrestore(&kmemleak_lock, flags); > + > + return stop; > } > > /* > * Scan a large memory block in MAX_SCAN_SIZE chunks to reduce the latency. > + * Return non-zero if the scan was interrupted. > */ > #ifdef CONFIG_SMP > -static void scan_large_block(void *start, void *end) > +static int scan_large_block(void *start, void *end) > { > void *next; > > while (start < end) { > next = min(start + MAX_SCAN_SIZE, end); > - scan_block(start, next, NULL); > + if (scan_block(start, next, NULL)) > + return 1; > start = next; > cond_resched(); > } > + > + return 0; > } > #endif > > @@ -1670,6 +1679,43 @@ static void kmemleak_cond_resched(struct kmemleak_object *object) > put_object(object); > } > > +/* > + * Scan all task kernel stacks, rescheduling between tasks. Each task is looked > + * up and pinned within its own RCU read-side section, so no lock is held across > + * the scan and the walk cannot trip the soft lockup watchdog. > + */ > +static void kmemleak_scan_task_stacks(void) > +{ > + struct pid *pid; > + int nr = 1; > + int stop = 0; > + > + do { > + struct task_struct *p = NULL; > + > + rcu_read_lock(); > + pid = find_ge_pid(nr, &init_pid_ns); > + if (pid) { > + nr = pid_nr(pid) + 1; > + p = pid_task(pid, PIDTYPE_PID); > + if (p) > + get_task_struct(p); > + } > + rcu_read_unlock(); > + > + if (p) { > + void *stack = try_get_task_stack(p); > + > + if (stack) { > + stop = scan_block(stack, stack + THREAD_SIZE, NULL); > + put_task_stack(p); > + } > + put_task_struct(p); > + } > + cond_resched(); > + } while (pid && !stop); > +} > + > /* > * Scan data sections and all the referenced memory blocks allocated via the > * kernel's standard allocators. This function must be called with the > @@ -1681,6 +1727,7 @@ static void kmemleak_scan(void) > struct zone *zone; > int __maybe_unused i; > int new_leaks = 0; > + int stop = 0; > > jiffies_last_scan = jiffies; > > @@ -1724,9 +1771,11 @@ static void kmemleak_scan(void) > > #ifdef CONFIG_SMP > /* per-cpu sections scanning */ > - for_each_possible_cpu(i) > - scan_large_block(__per_cpu_start + per_cpu_offset(i), > - __per_cpu_end + per_cpu_offset(i)); > + for_each_possible_cpu(i) { > + if (scan_large_block(__per_cpu_start + per_cpu_offset(i), > + __per_cpu_end + per_cpu_offset(i))) > + goto scan_gray; > + } > #endif > > /* > @@ -1753,32 +1802,28 @@ static void kmemleak_scan(void) > /* only scan if page is in use */ > if (page_count(page) == 0) > continue; > - scan_block(page, page + 1, NULL); > + stop = scan_block(page, page + 1, NULL); > + if (stop) > + break; > } > + if (stop) > + break; > } > put_online_mems(); > + if (stop) > + goto scan_gray; > > /* > * Scanning the task stacks (may introduce false negatives). > */ > - if (kmemleak_stack_scan) { > - struct task_struct *p, *g; > - > - rcu_read_lock(); > - for_each_process_thread(g, p) { > - void *stack = try_get_task_stack(p); > - if (stack) { > - scan_block(stack, stack + THREAD_SIZE, NULL); > - put_task_stack(p); > - } > - } > - rcu_read_unlock(); > - } > + if (kmemleak_stack_scan) > + kmemleak_scan_task_stacks(); > > /* > * Scan the objects already referenced from the sections scanned > * above. > */ > +scan_gray: > scan_gray_list(); > > /* > -- > 2.53.0 > > Does not apply ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-17 11:25 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-03 10:47 FAILED: patch "[PATCH] mm/kmemleak: report RCU-tasks quiescent states during the" failed to apply to 6.12-stable tree gregkh 2026-09-03 18:32 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Sasha Levin 2026-09-03 18:32 ` [PATCH 6.12.y 2/2] mm/kmemleak: report RCU-tasks quiescent states during the scan Sasha Levin 2026-09-17 11:22 ` [PATCH 6.12.y 1/2] mm/kmemleak: avoid soft lockup when scanning task stacks Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox