Re: [PATCH] mm: kmemleak: scan modified objects as soon as they are grayed

From: Catalin Marinas

Date: Mon Oct 19 2026 - 14:05:22 EST


On Fri, Oct 16, 2026 at 09:07:24AM -0700, Breno Leitao wrote:
> diff --git a/mm/kmemleak.c b/mm/kmemleak.c
> index 8fa409a4f9fb26..6e12bcd95312d2 100644
> --- a/mm/kmemleak.c
> +++ b/mm/kmemleak.c
> @@ -1696,8 +1696,10 @@ static void scan_gray_list(void)
> * Conditionally call resched() in an object iteration loop while making sure
> * that the given object won't go away without RCU read lock by performing a
> * get_object() if necessaary.
> + * If @scan_gray is set, also scan the gray list while the RCU lock is dropped.
> */
> -static void kmemleak_cond_resched(struct kmemleak_object *object)
> +static void kmemleak_cond_resched(struct kmemleak_object *object,
> + bool scan_gray)
> {
> if (!get_object(object))
> return; /* Try next object */
> @@ -1709,6 +1711,8 @@ static void kmemleak_cond_resched(struct kmemleak_object *object)
> raw_spin_unlock_irq(&kmemleak_lock);
>
> rcu_read_unlock();
> + if (scan_gray)
> + scan_gray_list();
> cond_resched_tasks_rcu_qs();
> rcu_read_lock();
>
> @@ -1910,7 +1914,7 @@ static int __kmemleak_scan(bool full)
> raw_spin_unlock_irq(&object->lock);
>
> if (need_resched())
> - kmemleak_cond_resched(object);
> + kmemleak_cond_resched(object, false);
> }
> rcu_read_unlock();
>
> @@ -1981,8 +1985,13 @@ static int __kmemleak_scan(bool full)
> */
> rcu_read_lock();
> list_for_each_entry_rcu(object, &object_list, object_list) {
> - if (need_resched())
> - kmemleak_cond_resched(object);
> + /*
> + * Scan newly grayed objects now, not after the walk: one may
> + * hold the only reference to another and be freed by then,
> + * like a maple tree node that keeps being replaced.
> + */
> + if (need_resched() || !list_empty(&gray_list))
> + kmemleak_cond_resched(object, true);

I think that's a good way to reduce the false positives for such maple
tree scenario. Do you have any numbers on how much this extends the scan
time by? If it's too expensive, we could rate-limit it, say every jiffy.

>
> /*
> * This is racy but we can save the overhead of lock/unlock
> @@ -2082,7 +2091,7 @@ static void kmemleak_scan(void)
> bool dedup_print;
>
> if (need_resched())
> - kmemleak_cond_resched(object);
> + kmemleak_cond_resched(object, false);

Nitpick: instead of passing 'false' in a few places, rename
kmemleak_cond_resched() to kmemleak_resched_drain() (well, some better
name) call get kmemleak_cond_resched() to call that with 'false'. We
could also move need_resched() in such function, being a small wrapper
the compiler should inline it.

Either way,

Reviewed-by: Catalin Marinas <catalin.marinas@xxxxxxx>