On Thu, Aug 13, 2026 at 2:34 AM Hao Ge <[email protected]> wrote:
>
> After shutdown_mem_profiling() clears mem_profiling_support,
> needs_section_mem() returns false, so later modules have their codetag
> section placed as regular data and never enter the alloc_tag maple tree.
> codetag_load_module() still called load_module(), which allocated a percpu
> counter for every tag; release_module_tags() could not find these modules
> on unload, so the counters leaked.
>
> Return CODETAG_MODULE_EXCLUDED from load_module() when profiling is off:
> codetag_module_init() drops the module's cmod and no counters are
> allocated. codetag_unload_module() now always calls free_section_mem(),
> since an excluded module may still hold a reserved section.
>
> Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
> Signed-off-by: Hao Ge <[email protected]>

Thanks for the fix. I think it could be done simpler, see below.

> ---
>  include/linux/codetag.h | 4 ++++
>  lib/codetag.c           | 8 +++++---
>  mm/alloc_tag.c          | 8 ++++++--
>  3 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/codetag.h b/include/linux/codetag.h
> index a25a085c2df1..88081c618673 100644
> --- a/include/linux/codetag.h
> +++ b/include/linux/codetag.h
> @@ -52,6 +52,10 @@ struct codetag_type_desc {
>  #endif
>  };
>
> +/* module_load() return values */
> +#define CODETAG_MODULE_LOAD    0       /* module loads with its tags */
> +#define CODETAG_MODULE_EXCLUDED        1       /* module loads without its 
> tags */

I see no reason for adding these special values. You could simply
return -ENOTSUP when profiling is disabled.

> +
>  struct codetag_iterator {
>         struct codetag_type *cttype;
>         struct codetag_module *cmod;
> diff --git a/lib/codetag.c b/lib/codetag.c
> index a9cda4c962a3..8506ecab9ea7 100644
> --- a/lib/codetag.c
> +++ b/lib/codetag.c
> @@ -238,9 +238,10 @@ static int codetag_module_init(struct codetag_type 
> *cttype, struct module *mod)
>         }
>         up_write(&cttype->mod_lock);
>
> -       if (err < 0) {
> +       if (err) {
> +               /* Error or excluded: cmod is dropped, free it. */

IIUC here you want to call kfree() if profiling got disabled. If you
return -ENOTSUP instead of CODETAG_MODULE_EXCLUDED then this condition
does not need to change.

>                 kfree(cmod);
> -               return err;
> +               return err < 0 ? err : 0;

Here you can do:
                    if (err && err != -ENOTSUP)
                            return err;
                   return 0;

>         }
>
>         return 0;
> @@ -388,7 +389,8 @@ void codetag_unload_module(struct module *mod)
>                         ++cttype->content_id;
>                 }
>                 up_write(&cttype->mod_lock);
> -               if (found && cttype->desc.free_section_mem)
> +               /* an excluded module may still hold section memory */
> +               if (cttype->desc.free_section_mem)
>                         cttype->desc.free_section_mem(mod, true);
>         }
>         mutex_unlock(&codetag_lock);
> diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c
> index 0a7b657fe2de..461fa87fbb0b 100644
> --- a/mm/alloc_tag.c
> +++ b/mm/alloc_tag.c
> @@ -977,9 +977,13 @@ static int load_module(struct module *mod, struct 
> codetag *start, struct codetag
>         struct alloc_tag *stop_tag;
>         struct alloc_tag *tag;
>
> +       /* Profiling disabled: load the module but exclude its tags. */
> +       if (!mem_profiling_support)
> +               return CODETAG_MODULE_EXCLUDED;

Return -ENOTSUP here.



> +
>         /* percpu counters for core allocations are already statically 
> allocated */
>         if (!mod)
> -               return 0;
> +               return CODETAG_MODULE_LOAD;
>
>         start_tag = ct_to_alloc_tag(start);
>         stop_tag = ct_to_alloc_tag(stop);
> @@ -1002,7 +1006,7 @@ static int load_module(struct module *mod, struct 
> codetag *start, struct codetag
>                  */
>                 kmemleak_ignore_percpu(tag->counters);
>         }
> -       return 0;
> +       return CODETAG_MODULE_LOAD;
>  }
>
>  static void replace_module(struct module *mod, struct module *new_mod)
> --
> 2.25.1
>

Reply via email to