diff options
| author | Jinmeng Zhou <jinmengzhou22@gmail.com> | 2026-09-07 21:20:55 +0800 |
|---|---|---|
| committer | Andrew Morton <akpm@linux-foundation.org> | 2026-09-13 21:32:31 -0700 |
| commit | 23becfb18688d1b22854a88764270750cc61c17f (patch) | |
| tree | 8e06e8be5636a176ca03440608ec207dc0e46abd /mm | |
| parent | 6f72dd6c0bb19722f39cceb1bcc81971e0421230 (diff) | |
| download | linux-next-23becfb18688d1b22854a88764270750cc61c17f.tar.gz linux-next-23becfb18688d1b22854a88764270750cc61c17f.zip | |
mm/hugetlb: fix subpool minimum reservation rollback
When a reservation request is partially covered by a subpool minimum and
the remaining global reservation fails, the error path first calls
hugepage_subpool_put_pages() for the subpool-backed portion. It removes
the failed global portion from used_hpages only afterwards.
hugepage_subpool_put_pages() uses used_hpages to decide whether rsv_hpages
should be restored. Since used_hpages still includes the global portion,
it can remain at or above min_hpages and prevent that restoration. It
then reports the subpool reservation as releasable, causing
hugetlb_acct_memory() to incorrectly decrement h->resv_huge_pages.
This was reproduced with four 2 MB huge pages and a hugetlbfs mount with
size=10M,min_size=8M. After a successful three-page reservation, a
two-page reservation which needed one subpool page and one global page
failed with -ENOMEM. HugePages_Rsvd incorrectly dropped from four to
three even though the subpool minimum was still four pages.
Roll back the failed global portion from used_hpages first, so that
hugepage_subpool_put_pages() evaluates the minimum reservation against the
current usage and returns the correct global adjustment.
Link: https://lore.kernel.org/20260907132055.26696-1-zhoujinmeng@bytedance.com
Fixes: a833a693a490 ("mm: hugetlb: fix incorrect fallback for subpool")
Signed-off-by: Jinmeng Zhou <zhoujinmeng@bytedance.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Ma Wupeng <mawupeng1@huawei.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: <stable@vger.kernel.org>
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/hugetlb.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a78a9fa26958..290150eb12a6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -6862,15 +6862,6 @@ long hugetlb_reserve_pages(struct inode *inode, out_put_pages: spool_resv = chg - gbl_reserve; - if (spool_resv) { - /* put sub pool's reservation back, chg - gbl_reserve */ - gbl_resv = hugepage_subpool_put_pages(spool, spool_resv); - /* - * subpool's reserved pages can not be put back due to race, - * return to hstate. - */ - hugetlb_acct_memory(h, -gbl_resv); - } /* Restore used_hpages for pages that failed global reservation */ if (gbl_reserve && spool) { unsigned long flags; @@ -6880,6 +6871,15 @@ out_put_pages: spool->used_hpages -= gbl_reserve; unlock_or_release_subpool(spool, flags); } + if (spool_resv) { + /* put sub pool's reservation back, chg - gbl_reserve */ + gbl_resv = hugepage_subpool_put_pages(spool, spool_resv); + /* + * subpool's reserved pages can not be put back due to race, + * return to hstate. + */ + hugetlb_acct_memory(h, -gbl_resv); + } out_uncharge_cgroup: hugetlb_cgroup_uncharge_cgroup_rsvd(hstate_index(h), chg * pages_per_huge_page(h), h_cg); |
