Re: [PATCH v5 1/2] alloc_tag: move release_module_tags() above reserve_module_tags()
From: Suren Baghdasaryan
Date: Fri Aug 14 2026 - 23:41:04 EST
On Tue, Aug 11, 2026 at 10:41 PM Hao Ge <hao.ge@xxxxxxxxx> wrote:
>
> release_module_tags() is a cleanup helper. reserve_module_tags() can
> also fail after storing the reservation in the maple tree, in which
> case it should call release_module_tags() to undo it. Move the helper
> above reserve_module_tags() so no forward declaration is needed.
>
> No functional change.
>
> Fixes: 4835f747d3ed ("alloc_tag: support for page allocation tag compression")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Hao Ge <hao.ge@xxxxxxxxx>
Acked-by: Suren Baghdasaryan <surenb@xxxxxxxxxx>
> ---
> mm/alloc_tag.c | 92 +++++++++++++++++++++++++-------------------------
> 1 file changed, 46 insertions(+), 46 deletions(-)
>
> diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c
> index 52aece27b00e..af44f90379f2 100644
> --- a/mm/alloc_tag.c
> +++ b/mm/alloc_tag.c
> @@ -835,6 +835,52 @@ static int vm_module_tags_populate(void)
> return 0;
> }
>
> +static void release_module_tags(struct module *mod, bool used)
> +{
> + MA_STATE(mas, &mod_area_mt, module_tags.size, module_tags.size);
> + struct alloc_tag *start_tag;
> + struct alloc_tag *end_tag;
> + struct module *val;
> +
> + mas_lock(&mas);
> + mas_for_each_rev(&mas, val, 0)
> + if (val == mod)
> + break;
> +
> + if (!val) /* module not found */
> + goto out;
> +
> + if (!used)
> + goto release_area;
> +
> + start_tag = (struct alloc_tag *)(module_tags.start_addr + mas.index);
> + end_tag = (struct alloc_tag *)(module_tags.start_addr + mas.last);
> + if (!clean_unused_counters(start_tag, end_tag)) {
> + struct alloc_tag *tag;
> +
> + for (tag = start_tag; tag <= end_tag; tag++) {
> + struct alloc_tag_counters counter;
> +
> + if (!tag->counters)
> + continue;
> +
> + counter = alloc_tag_read(tag);
> + pr_info("%s:%u module %s func:%s has %llu allocated at module unload\n",
> + tag->ct.filename, tag->ct.lineno, tag->ct.modname,
> + tag->ct.function, counter.bytes);
> + }
> + } else {
> + used = false;
> + }
> +release_area:
> + mas_store(&mas, used ? &unloaded_mod : NULL);
> + val = mas_prev_range(&mas, 0);
> + if (val == &prepend_mod)
> + mas_store(&mas, NULL);
> +out:
> + mas_unlock(&mas);
> +}
> +
> static void *reserve_module_tags(struct module *mod, unsigned long size,
> unsigned int prepend, unsigned long align)
> {
> @@ -922,52 +968,6 @@ static void *reserve_module_tags(struct module *mod, unsigned long size,
> return (struct alloc_tag *)(module_tags.start_addr + offset);
> }
>
> -static void release_module_tags(struct module *mod, bool used)
> -{
> - MA_STATE(mas, &mod_area_mt, module_tags.size, module_tags.size);
> - struct alloc_tag *start_tag;
> - struct alloc_tag *end_tag;
> - struct module *val;
> -
> - mas_lock(&mas);
> - mas_for_each_rev(&mas, val, 0)
> - if (val == mod)
> - break;
> -
> - if (!val) /* module not found */
> - goto out;
> -
> - if (!used)
> - goto release_area;
> -
> - start_tag = (struct alloc_tag *)(module_tags.start_addr + mas.index);
> - end_tag = (struct alloc_tag *)(module_tags.start_addr + mas.last);
> - if (!clean_unused_counters(start_tag, end_tag)) {
> - struct alloc_tag *tag;
> -
> - for (tag = start_tag; tag <= end_tag; tag++) {
> - struct alloc_tag_counters counter;
> -
> - if (!tag->counters)
> - continue;
> -
> - counter = alloc_tag_read(tag);
> - pr_info("%s:%u module %s func:%s has %llu allocated at module unload\n",
> - tag->ct.filename, tag->ct.lineno, tag->ct.modname,
> - tag->ct.function, counter.bytes);
> - }
> - } else {
> - used = false;
> - }
> -release_area:
> - mas_store(&mas, used ? &unloaded_mod : NULL);
> - val = mas_prev_range(&mas, 0);
> - if (val == &prepend_mod)
> - mas_store(&mas, NULL);
> -out:
> - mas_unlock(&mas);
> -}
> -
> static int load_module(struct module *mod, struct codetag *start, struct codetag *stop)
> {
> /* Allocate module alloc_tag percpu counters */
> --
> 2.25.1
>