Re: [RFC PATCH 1/3] alloc_tag: skip percpu counter allocation when profiling is disabled
Suren Baghdasaryan <[email protected]>
| Newsgroups | org.kernel.vger.linux-modules,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <CAJuCfpHAzhCC1Sx3uJr7kbhBzc7RFqwLhMyjo04hqZz=HBJH8Q@mail.gmail.com> |
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 >