[PATCH 0/2] mm: kmemleak: batch the struct page scan

From: Breno Leitao

Date: Mon Sep 21 2026 - 08:33:09 EST


kmemleak walks the struct page array as a scan root and hands it to
scan_block() one page at a time.

scan_block() takes kmemleak_lock with interrupts disabled for the
duration of the call, so the scanner acquires the lock once per online
PFN in order to look at a single 64-byte struct page.

Batching adjacent pages up to that size keeps exactly the same pages
under the same maximum lock hold time, with MAX_SCAN_SIZE / pagesize
fewer acquisitions.

Patch 1 lifts the loop out of __kmemleak_scan() into scan_zone_pages()
with no functional change. Patch 2 does the batching, which is then
contained in that one function.

This improves the performance due to less atomic operations, which is
not a big deal on a regular machine, but, given kmemleak usually comes
with extra debug options, such as PROVE_LOCKING, DEBUG_SPINLOCK, etc.

For instance, measuring Meta's "debug kernel flavor" on an arm64 hosts,
this improve the scan time by 20%.

It is safe to get more work into scan_block(), given it has the
protections, added by commit eb11f56eeca560 ("mm/kmemleak: stop the task
stack scan early when interrupted")

MAX_SCAN_SIZE is also not a new maximum for a single scan_block() call.
kmemleak_scan_task_stacks() already hands it a whole task stack in one
go. On arm64 and x86_64 THREAD_SIZE is never below 16 KiB, four times
MAX_SCAN_SIZE, and it is 64 KiB on arm64 with 64K pages.

Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>
---
Breno Leitao (2):
mm: kmemleak: move the struct page scan into a helper
mm: kmemleak: scan the struct page array in MAX_SCAN_SIZE batches

mm/kmemleak.c | 70 +++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 47 insertions(+), 23 deletions(-)
---
base-commit: 3f2425f5b5bbbdd991ca9cdfd5502e68d8895998
change-id: 20260918-b4-kmemleak-page-scan-c7ac6b088c4f

Best regards,
--
Breno Leitao <leitao@xxxxxxxxxx>