mm/kmemleak.c | 113 +++++++++++++++++++++- tools/testing/selftests/mm/test_kmemleak_dedup.sh | 86 ++++++++++++++++ 2 files changed, 197 insertions(+), 2 deletions(-)
I am starting to run with kmemleak in verbose enabled in some "probe
points" across the my employers fleet so that suspected leaks land in
dmesg without needing a separate read of /sys/kernel/debug/kmemleak.
The downside is that workloads which leak many objects from a single
allocation site flood the console with byte-for-byte identical
backtraces. Hundreds of duplicates per scan are common, drowning out
distinct leaks and unrelated kernel messages, while adding no signal
beyond the first occurrence.
This series collapses those duplicates inside kmemleak itself. Each
unique stackdepot trace_handle prints once per scan, followed by a
short summary line when more than one object shares it:
kmemleak: unreferenced object 0xff110001083beb00 (size 192):
kmemleak: comm "modprobe", pid 974, jiffies 4294754196
kmemleak: ...
kmemleak: backtrace (crc 6f361828):
kmemleak: __kmalloc_cache_noprof+0x1af/0x650
kmemleak: ...
kmemleak: ... and 71 more object(s) with the same backtrace
The "N new suspected memory leaks" tally and the contents of
/sys/kernel/debug/kmemleak are unchanged - the per-object detail is
still available on demand, only the verbose (dmesg) output is collapsed.
Patch 1 is the kmemleak change.
Patch 2 adds a selftest that loads samples/kmemleak's CONFIG_SAMPLE
kmemleak-test module to generate ten leaks sharing one call site and
checks that the printed count is strictly less than the reported leak
total. Not sure if Patch 2 is useful or not, if not, it is easier to
discard.
Breno Leitao (2):
mm/kmemleak: dedupe verbose scan output by allocation backtrace
selftests/mm: add kmemleak verbose dedup test
mm/kmemleak.c | 102 +++++++++++++++++-
.../selftests/mm/test_kmemleak_dedup.sh | 78 ++++++++++++++
2 files changed, 175 insertions(+), 5 deletions(-)
create mode 100755 tools/testing/selftests/mm/test_kmemleak_dedup.sh
--
2.52.0
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (2):
mm/kmemleak: dedupe verbose scan output by allocation backtrace
selftests/mm: add kmemleak verbose dedup test
mm/kmemleak.c | 113 +++++++++++++++++++++-
tools/testing/selftests/mm/test_kmemleak_dedup.sh | 86 ++++++++++++++++
2 files changed, 197 insertions(+), 2 deletions(-)
---
base-commit: 97e797263a5e963da3d1e66e743fd518567dfe37
change-id: 20260420-kmemleak_dedup-bee54ffa65e7
Best regards,
--
Breno Leitao <leitao@debian.org>
On Tue, 21 Apr 2026 06:45:03 -0700 Breno Leitao <leitao@debian.org> wrote: > I am starting to run with kmemleak in verbose enabled in some "probe > points" across the my employers fleet so that suspected leaks land in > dmesg without needing a separate read of /sys/kernel/debug/kmemleak. > > The downside is that workloads which leak many objects from a single > allocation site flood the console with byte-for-byte identical > backtraces. Hundreds of duplicates per scan are common, drowning out > distinct leaks and unrelated kernel messages, while adding no signal > beyond the first occurrence. > > This series collapses those duplicates inside kmemleak itself. Each > unique stackdepot trace_handle prints once per scan, followed by a > short summary line when more than one object shares it: AI review: https://sashiko.dev/#/patchset/20260421-kmemleak_dedup-v1-0-65e31c6cdf0c@debian.org
Hello Andrew,
On Fri, Apr 24, 2026 at 06:53:25AM -0700, Andrew Morton wrote:
> On Tue, 21 Apr 2026 06:45:03 -0700 Breno Leitao <leitao@debian.org> wrote:
>
> > I am starting to run with kmemleak in verbose enabled in some "probe
> > points" across the my employers fleet so that suspected leaks land in
> > dmesg without needing a separate read of /sys/kernel/debug/kmemleak.
> >
> > The downside is that workloads which leak many objects from a single
> > allocation site flood the console with byte-for-byte identical
> > backtraces. Hundreds of duplicates per scan are common, drowning out
> > distinct leaks and unrelated kernel messages, while adding no signal
> > beyond the first occurrence.
> >
> > This series collapses those duplicates inside kmemleak itself. Each
> > unique stackdepot trace_handle prints once per scan, followed by a
> > short summary line when more than one object shares it:
>
> AI review:
> https://sashiko.dev/#/patchset/20260421-kmemleak_dedup-v1-0-65e31c6cdf0c@debian.org
V2 will have them addressed. Here are some of the answers for the question
raised by Sashiko.
> Can print_unreferenced() access freed memory here and in the fallback
> path above? Since the lock is dropped and reacquired, do we need to
> re-check object->flags & OBJECT_ALLOCATED before printing?
v2 introduces print_leak_locked(), which re-acquires object->lock and gates the
hex dump on OBJECT_ALLOCATED:
static void print_leak_locked(struct kmemleak_object *object, bool hex_dump)
{
raw_spin_lock_irq(&object->lock);
__print_unreferenced(NULL, object,
hex_dump && (object->flags & OBJECT_ALLOCATED));
raw_spin_unlock_irq(&object->lock);
}
hex_dump_object() is the only path that reads object->pointer's user memory;
the rest of the report (backtrace, comm/pid/jiffies, checksum) lives in the
kmemleak_object metadata, which get_object() keeps alive. __delete_object()
clears OBJECT_ALLOCATED under object->lock before the user memory goes away, so
the recheck is sufficient.
> If get_object(object) failed, it means the object's reference count is
> already 0 and it is actively being deleted. Unconditionally locking and
> dumping it there seems like it will read freed memory.
Fixed in v2 by reordering: get_object() is now attempted before xa_store(), and
on failure we simply skip the object — the leak count was already incremented,
and the memory has been freed concurrently so it's no longer a leak.
> What happens to valid memory leaks that failed to record a stack trace (e.g.
> due to memory pressure or context limits)? Will these leaks also be
> permanently ignored in all future scans?
Also fixed in v2. dedup_record() now starts with:
if (!trace_handle) {
print_leak_locked(object, true);
return;
}
so leaks with trace_handle == NULL (early-boot allocations tracked before
kmemleak_init() set up object_cache, or stack_depot_save() failures under
memory pressure) are printed inline through the same locked.
© 2016 - 2026 Red Hat, Inc.