diff options
| author | Longlong Xia <xialonglong@kylinos.cn> | 2026-08-14 16:30:27 +0800 |
|---|---|---|
| committer | Andrew Morton <akpm@linux-foundation.org> | 2026-09-01 20:26:21 -0700 |
| commit | 267bede12d3b108ca29997ce280e927a570ec97f (patch) | |
| tree | b5111ca29ae43aa280d3e9157fdac2b4a684a9fc | |
| parent | dc41e961a269f2ca4196e669d6d8e05480899cd4 (diff) | |
mm/hugetlb: keep max_huge_pages when dissolving surplus folios
dissolve_free_hugetlb_folio() can remove a free folio as surplus when its
node has surplus pages. In that case remove_hugetlb_folio() decrements
both nr_huge_pages and surplus_huge_pages, leaving the persistent pool
size unchanged.
Updating max_huge_pages as if a persistent folio had been removed can
therefore corrupt the persistent pool target and underflow it when
max_huge_pages is zero. Keep max_huge_pages unchanged for surplus folios,
including the vmemmap restoration rollback path.
Link: https://lore.kernel.org/20260814083027.1419487-1-xialonglong2025@163.com
Fixes: cb402bbdabca ("mm/hugetlb: fix surplus pages in dissolve_free_huge_page()")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Longlong Xia <xialonglong@kylinos.cn>
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Cc: David Hildenbrand <david@kernel.org>
Cc: Jinjiang Tu <tujinjiang@huawei.com>
Cc: Longlong Xia <xialonglong@kylinos.cn>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
| -rw-r--r-- | mm/hugetlb.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 785772845795..885017e26fd4 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1992,7 +1992,8 @@ retry: if (h->surplus_huge_pages_node[folio_nid(folio)]) adjust_surplus = true; remove_hugetlb_folio(h, folio, adjust_surplus); - h->max_huge_pages--; + if (!adjust_surplus) + h->max_huge_pages--; spin_unlock_irq(&hugetlb_lock); /* @@ -2012,7 +2013,8 @@ retry: if (rc) { spin_lock_irq(&hugetlb_lock); add_hugetlb_folio(h, folio, adjust_surplus); - h->max_huge_pages++; + if (!adjust_surplus) + h->max_huge_pages++; goto out; } } else { |
