mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Muchun Song <muchun.song@linux.dev>
To: Kaitao Cheng <kaitao.cheng@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>,
	David Hildenbrand <david@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Mike Rapoport <rppt@kernel.org>,
	Johannes Weiner <hannes@cmpxchg.org>,
	Michal Hocko <mhocko@kernel.org>,
	Roman Gushchin <roman.gushchin@linux.dev>,
	Shakeel Butt <shakeel.butt@linux.dev>,
	Mani Tofigh <mt4022@columbia.edu>, Zi Yan <ziy@nvidia.com>,
	Mike Kravetz <mike.kravetz@oracle.com>,
	Baolin Wang <baolin.wang@linux.alibaba.com>,
	Miaohe Lin <linmiaohe@huawei.com>,
	Naoya Horiguchi <nao.horiguchi@gmail.com>,
	Frank van der Linden <fvdl@google.com>,
	Chris Down <chris@chrisdown.name>,
	Joshua Hahn <joshua.hahnjy@gmail.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	cgroups@vger.kernel.org, Kaitao Cheng <chengkaitao@kylinos.cn>
Subject: Re: [PATCH v2 3/3] mm/hugetlb: Fix NR_HUGETLB accounting for surplus folios
Date: Mon, 2 Nov 2026 11:23:12 +0800	[thread overview]
Message-ID: <320A5EDF-0511-4069-A276-599852CCD6F2@linux.dev> (raw)
In-Reply-To: <20261102024910.31486-4-kaitao.cheng@linux.dev>



> On Nov 2, 2026, at 10:49, Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
> 
> From: Kaitao Cheng <chengkaitao@kylinos.cn>
> 
> NR_HUGETLB is incremented in the allocation entry points, but decremented
> unconditionally in free_huge_folio(). Surplus folios allocated while
> gathering reservations can be freed without passing through those entry
> points, leaving an unmatched decrement in the per-node counter.
> 
> This happens when reservation gathering fails or allocates more folios
> than needed, or when the overcommit recheck rejects a newly allocated
> surplus folio. These paths cause nr_hugetlb in /proc/vmstat to underreport
> usage.
> 
> Move node accounting to the underlying folio state transitions. Increment
> NR_HUGETLB when dequeuing a free folio or allocating a fresh surplus or
> migration folio, and decrement it when returning the folio to the pool or
> removing it from active use. Balance the temporary increment when surplus
> folios gathered for reservations are added to the free pool.
> 
> Separate memcg statistics from node accounting, updating them after a
> successful charge and before uncharging. This keeps node accounting
> balanced independently of whether the folio is charged to a memcg.
> 
> Fixes: 05d4532b60e3 ("memcg/hugetlb: add hugeTLB counters to memcg")
> Closes: https://sashiko.dev/#/bug/linux-860a3b8f-0b07-4cd5-a122-aa2288463bee
> Suggested-by: Muchun Song <muchun.song@linux.dev>
> Suggested-by: Oscar Salvador <osalvador@suse.de>
> Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
> ---
> mm/hugetlb.c    | 42 +++++++++++++++++++++++++++---------------
> mm/memcontrol.c |  6 +-----
> 2 files changed, 28 insertions(+), 20 deletions(-)

I want to keep it simple for a backport fix, so your last version is good
to me, and this one should be a cleanup based on the top of that.

Thanks.

> 
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 931ca3a30773..d1d7e14858d3 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1288,6 +1288,8 @@ static struct folio *dequeue_hugetlb_folio_node_exact(struct hstate *h,
> 		folio_clear_hugetlb_freed(folio);
> 		h->free_huge_pages--;
> 		h->free_huge_pages_node[nid]--;
> +		mod_node_page_state(folio_pgdat(folio), NR_HUGETLB,
> +				    pages_per_huge_page(h));
> 		return folio;
> 	}
> 
> @@ -1416,6 +1418,9 @@ void remove_hugetlb_folio(struct hstate *h, struct folio *folio,
> 		folio_clear_hugetlb_freed(folio);
> 		h->free_huge_pages--;
> 		h->free_huge_pages_node[nid]--;
> +	} else {
> +		mod_node_page_state(folio_pgdat(folio), NR_HUGETLB,
> +				    -(long)pages_per_huge_page(h));
> 	}
> 	if (adjust_surplus) {
> 		h->surplus_huge_pages--;
> @@ -1693,6 +1698,17 @@ struct hstate *size_to_hstate(unsigned long size)
> 	return NULL;
> }
> 
> +static void mod_hugetlb_memcg_state(struct folio *folio, int nr_pages)
> +{
> +	struct mem_cgroup *memcg;
> +
> +	guard(rcu)();
> +	memcg = folio_memcg(folio);
> +	if (memcg)
> +		mod_memcg_lruvec_state(mem_cgroup_lruvec(memcg, folio_pgdat(folio)),
> +				       NR_HUGETLB, nr_pages);
> +}
> +
> void free_huge_folio(struct folio *folio)
> {
> 	/*
> @@ -1740,7 +1756,7 @@ void free_huge_folio(struct folio *folio)
> 				     pages_per_huge_page(h), folio);
> 	hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h),
> 					  pages_per_huge_page(h), folio);
> -	lruvec_stat_mod_folio(folio, NR_HUGETLB, -pages_per_huge_page(h));
> +	mod_hugetlb_memcg_state(folio, -pages_per_huge_page(h));
> 	mem_cgroup_uncharge(folio);
> 	if (restore_reserve)
> 		h->resv_huge_pages++;
> @@ -1756,6 +1772,8 @@ void free_huge_folio(struct folio *folio)
> 		spin_unlock_irqrestore(&hugetlb_lock, flags);
> 		update_and_free_hugetlb_folio(h, folio, true);
> 	} else {
> +		mod_node_page_state(folio_pgdat(folio), NR_HUGETLB,
> +				    -(long)pages_per_huge_page(h));
> 		arch_clear_hugetlb_flags(folio);
> 		enqueue_hugetlb_folio(h, folio);
> 		spin_unlock_irqrestore(&hugetlb_lock, flags);
> @@ -2123,6 +2141,9 @@ static struct folio *alloc_surplus_hugetlb_folio(struct hstate *h,
> 	 */
> 	account_new_hugetlb_folio(h, folio);
> 
> +	/* The overcommit recheck below can free this folio. */
> +	mod_node_page_state(folio_pgdat(folio), NR_HUGETLB, pages_per_huge_page(h));
> +
> 	/*
> 	 * We could have raced with the pool size change.
> 	 * Double check that and simply deallocate the new page
> @@ -2160,6 +2181,7 @@ static struct folio *alloc_migrate_hugetlb_folio(struct hstate *h, gfp_t gfp_mas
> 
> 	spin_lock_irq(&hugetlb_lock);
> 	account_new_hugetlb_folio(h, folio);
> +	mod_node_page_state(folio_pgdat(folio), NR_HUGETLB, pages_per_huge_page(h));
> 	spin_unlock_irq(&hugetlb_lock);
> 
> 	/* fresh huge pages are frozen */
> @@ -2218,10 +2240,6 @@ struct folio *alloc_hugetlb_folio_reserve(struct hstate *h, int preferred_nid,
> 
> 	spin_unlock_irq(&hugetlb_lock);
> 
> -	if (folio)
> -		lruvec_stat_mod_folio(folio, NR_HUGETLB,
> -				      folio_nr_pages(folio));
> -
> 	return folio;
> }
> 
> @@ -2249,9 +2267,6 @@ struct folio *alloc_hugetlb_folio_nodemask(struct hstate *h, int preferred_nid,
> 						    nmask);
> 	}
> 
> -	if (folio)
> -		lruvec_stat_mod_folio(folio, NR_HUGETLB, folio_nr_pages(folio));
> -
> 	return folio;
> }
> 
> @@ -2369,6 +2384,8 @@ static int gather_surplus_pages(struct hstate *h, long delta)
> 		if ((--needed) < 0)
> 			break;
> 		/* Add the page to the hugetlb allocator */
> +		mod_node_page_state(folio_pgdat(folio), NR_HUGETLB,
> +				    -(long)pages_per_huge_page(h));
> 		enqueue_hugetlb_folio(h, folio);
> 	}
> free:
> @@ -2944,13 +2961,6 @@ struct folio *hugetlb_alloc_folio(struct hstate *h,
> 
> 	ret = mem_cgroup_charge_hugetlb(folio, mm,
> 					gfp | __GFP_RETRY_MAYFAIL);
> -	/*
> -	 * Unconditionally increment NR_HUGETLB here because if
> -	 * mem_cgroup_charge_hugetlb failed, freeing the page will
> -	 * decrement NR_HUGETLB.
> -	 */
> -	lruvec_stat_mod_folio(folio, NR_HUGETLB, nr_pages);
> -
> 	if (ret == -ENOMEM) {
> 		folio_put(folio);
> 		/*
> @@ -2965,6 +2975,8 @@ struct folio *hugetlb_alloc_folio(struct hstate *h,
> 		return ERR_PTR(-ENOSPC);
> 	}
> 
> +	mod_hugetlb_memcg_state(folio, nr_pages);
> +
> 	return folio;
> 
>  err_uncharge_hugetlb_cgroup:
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 84f4a8fd4d16..3bfe4b108170 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -5417,11 +5417,7 @@ int mem_cgroup_charge_hugetlb(struct folio *folio, struct mm_struct *mm,
> 	struct mem_cgroup *memcg = get_mem_cgroup_from_mm(mm);
> 	int ret = 0;
> 
> -	/*
> -	 * Even memcg does not account for hugetlb, we still want to update
> -	 * system-level stats via lruvec_stat_mod_folio. Return 0, and skip
> -	 * charging the memcg.
> -	 */
> +	/* Skip charging unless hugetlb accounting is enabled for cgroup v2. */
> 	if (mem_cgroup_disabled() || !memcg_accounts_hugetlb() ||
> 		!memcg || !cgroup_subsys_on_dfl(memory_cgrp_subsys))
> 		goto out;
> -- 
> 2.54.0 (Apple Git-157)
> 


      reply	other threads:[~2026-11-02  3:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02  2:49 [PATCH v2 0/3] mm/hugetlb: Fix CMA parsing, flags and usage accounting Kaitao Cheng
2026-11-02  2:49 ` [PATCH v2 1/3] mm/hugetlb_cma: fix incorrect hugetlb_cma_size assignment on malformed input Kaitao Cheng
2026-11-02  2:49 ` [PATCH v2 2/3] mm/hugetlb: Preserve persistent flags when returning folios to the pool Kaitao Cheng
2026-11-02  3:10   ` Muchun Song
2026-11-02  4:03   ` Zi Yan
2026-11-02  8:07   ` Qi Zheng
2026-11-02  2:49 ` [PATCH v2 3/3] mm/hugetlb: Fix NR_HUGETLB accounting for surplus folios Kaitao Cheng
2026-11-02  3:23   ` Muchun Song [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=320A5EDF-0511-4069-A276-599852CCD6F2@linux.dev \
    --to=muchun.song@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=cgroups@vger.kernel.org \
    --cc=chengkaitao@kylinos.cn \
    --cc=chris@chrisdown.name \
    --cc=david@kernel.org \
    --cc=fvdl@google.com \
    --cc=hannes@cmpxchg.org \
    --cc=joshua.hahnjy@gmail.com \
    --cc=kaitao.cheng@linux.dev \
    --cc=linmiaohe@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@kernel.org \
    --cc=mike.kravetz@oracle.com \
    --cc=mt4022@columbia.edu \
    --cc=nao.horiguchi@gmail.com \
    --cc=osalvador@suse.de \
    --cc=roman.gushchin@linux.dev \
    --cc=rppt@kernel.org \
    --cc=shakeel.butt@linux.dev \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®