On Fri, Apr 24, 2026 at 02:26:53AM -0700, Breno Leitao wrote:
> diff --git a/mm/kmemleak.c b/mm/kmemleak.c
> index 2eff0d6b622b6..d521cc71ec1ee 100644
> --- a/mm/kmemleak.c
> +++ b/mm/kmemleak.c
> @@ -92,6 +92,7 @@
>  #include <linux/nodemask.h>
>  #include <linux/mm.h>
>  #include <linux/workqueue.h>
> +#include <linux/xarray.h>
>  #include <linux/crc32.h>
>  
>  #include <asm/sections.h>
> @@ -153,6 +154,8 @@ struct kmemleak_object {
>       /* checksum for detecting modified objects */
>       u32 checksum;
>       depot_stack_handle_t trace_handle;
> +     /* per-scan dedup count, valid only while in scan-local dedup xarray */
> +     unsigned int dup_count;

I would add this around the pid_t pid member since both are 32-bit,
better struct compaction. Here we'll get 32-bit padding.

>       /* memory ranges to be scanned inside an object (empty for all) */
>       struct hlist_head area_list;
>       unsigned long jiffies;          /* creation timestamp */
> @@ -360,8 +363,9 @@ static const char *__object_type_str(struct 
> kmemleak_object *object)
>   * Printing of the unreferenced objects information to the seq file. The
>   * print_unreferenced function must be called with the object->lock held.
>   */
> -static void print_unreferenced(struct seq_file *seq,
> -                            struct kmemleak_object *object)
> +static void __print_unreferenced(struct seq_file *seq,
> +                              struct kmemleak_object *object,
> +                              bool no_hex_dump)
>  {
>       int i;
>       unsigned long *entries;
> @@ -373,7 +377,8 @@ static void print_unreferenced(struct seq_file *seq,
>                          object->pointer, object->size);
>       warn_or_seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
>                          object->comm, object->pid, object->jiffies);
> -     hex_dump_object(seq, object);
> +     if (!no_hex_dump)
> +             hex_dump_object(seq, object);

Nit: just use "hex_dump" and avoid double negation.

>       warn_or_seq_printf(seq, "  backtrace (crc %x):\n", object->checksum);
>  
>       for (i = 0; i < nr_entries; i++) {
> @@ -382,6 +387,12 @@ static void print_unreferenced(struct seq_file *seq,
>       }
>  }
>  
> +static void print_unreferenced(struct seq_file *seq,
> +                            struct kmemleak_object *object)
> +{
> +     __print_unreferenced(seq, object, false);
> +}
> +
>  /*
>   * Print the kmemleak_object information. This function is used mainly for
>   * debugging special cases when kmemleak operations. It must be called with
> @@ -1684,6 +1695,103 @@ static void kmemleak_cond_resched(struct 
> kmemleak_object *object)
>       put_object(object);
>  }
>  
> +/*
> + * Print one leak inline, re-checking OBJECT_ALLOCATED under the lock so
> + * the hex dump does not touch user memory that was freed concurrently.
> + * Used by the dedup_record() fallback paths where we cannot dedup and defer
> + * printing through the xarray.
> + */
> +static void print_leak_locked(struct kmemleak_object *object, bool 
> no_hex_dump)
> +{
> +     raw_spin_lock_irq(&object->lock);
> +     if (object->flags & OBJECT_ALLOCATED)
> +             __print_unreferenced(NULL, object, no_hex_dump);
> +     raw_spin_unlock_irq(&object->lock);

I don't think OBJECT_ALLOCATED should prevent the printing here. If it's
called from dedup_flush() and the first object that kept accumulating
the dup_count is freed, you'd not print anything. I would only use
OBJECT_ALLOCATED to decide whether to do the hex dump if requested.

-- 
Catalin

Reply via email to