Hi Suren
On 2026/8/15 14:15, Suren Baghdasaryan wrote: > 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. Agree, will do in the next version. > >> --- >> 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 >>

