FAILED: patch "[PATCH] mm/kmemleak: report RCU-tasks quiescent states during the" failed to apply to 7.2-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 7.2-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 <[email protected]>.
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-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x 3541a2b06ecd78ba333188df04368dcf97273d6a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090344-tightly-handiwork-36ab@gregkh' --subject-prefix 'PATCH 7.2.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 <[email protected]>
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_scanand, 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_freeThen 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").
mm/kmemleak.c +7 -7
@@ -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 ;
Sasha Levin
maintainerPATCH 1/3 mm/kmemleak: avoid soft lockup when scanning task stacks
From: Breno Leitao <[email protected]>
[ 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
kthreadPatch 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.
Stable-dep-of: 3541a2b06ecd ("mm/kmemleak: report RCU-tasks quiescent states during the scan")
--- mm/kmemleak.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-)
mm/kmemleak.c +38 -13
@@ -1696,6 +1696,42 @@ 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 ; + +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) { +scan_block (stack, stack +THREAD_SIZE ,NULL ); +put_task_stack (p); + } +put_task_struct (p); + } +cond_resched (); + }while (pid && !scan_should_stop ()); +} +/* * Print one leak inline. The hex dump is gated on OBJECT_ALLOCATED so it * does not touch user memory that was freed concurrently; the rest of the
@@ -1885,19 +1921,8 @@ static void kmemleak_scan(void)/* * 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
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 mm/kmemleak: stop the task stack scan early when interrupted
From: Breno Leitao <[email protected]>
[ Upstream commit eb11f56eeca56069613d00bf623607e305b271d9 ]
scan_block() already checks scan_should_stop() for every pointer and bails out of the current block, but the task stack walk cannot tell and keeps issuing a separate scan_should_stop() between every task.
Return that status from scan_block() and use it as the task stack loop condition, so the walk stops as soon as a scan is interrupted.
Stable-dep-of: 3541a2b06ecd ("mm/kmemleak: report RCU-tasks quiescent states during the scan")
--- mm/kmemleak.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
mm/kmemleak.c +12 -6
@@ -1525,22 +1525,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);
@@ -1550,6 +1553,8 @@ static void scan_block(void *_start, void *_end,pointer_update_refs (scanned, pointer,OBJECT_PERCPU ); }raw_spin_unlock_irqrestore (&kmemleak_lock, flags); + +return stop; }/*
@@ -1705,6 +1710,7 @@ static void kmemleak_scan_task_stacks(void) {struct pid *pid;int nr =1 ; +int stop =0 ; do { struct task_struct *p = NULL;
@@ -1723,13 +1729,13 @@ static void kmemleak_scan_task_stacks(void)void *stack =try_get_task_stack (p);if (stack) { -scan_block (stack, stack +THREAD_SIZE ,NULL ); + stop =scan_block (stack, stack +THREAD_SIZE ,NULL );put_task_stack (p); }put_task_struct (p); }cond_resched (); - }while (pid && !scan_should_stop ()); + }while (pid && !stop); }/*
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 mm/kmemleak: report RCU-tasks quiescent states during the scan
In reply to Sasha LevinFrom: Breno Leitao <[email protected]>
[ 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_scanand, 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_freeThen 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").
--- mm/kmemleak.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
mm/kmemleak.c +7 -7
@@ -1569,7 +1569,7 @@ static void scan_large_block(void *start, void *end) next =min (start +MAX_SCAN_SIZE , end);scan_block (start, next,NULL ); start = next; - cond_resched(); + cond_resched_tasks_rcu_qs(); } }#endif
@@ -1604,7 +1604,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 ;
@@ -1626,7 +1626,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 {
@@ -1654,7 +1654,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 ())
@@ -1689,7 +1689,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);
@@ -1734,7 +1734,7 @@ static void kmemleak_scan_task_stacks(void) }put_task_struct (p); } -cond_resched (); +cond_resched_tasks_rcu_qs (); }while (pid && !stop); }
@@ -1908,7 +1908,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 ;
Signature · 1 line
2.53.0