From: sashiko-bot@kernel.org
To: "Mark Bundschuh" <mkbund@amazon.com>
Cc: linux-mm@kvack.org, david@kernel.org, yangge <yangge1116@126.com>,
"Baolin Wang" <baolin.wang@linux.alibaba.com>,
"Barry Song" <21cnbao@gmail.com>,
"David Hildenbrand" <david@redhat.com>,
"SeongJae Park" <sj@kernel.org>,
"Andrew Morton" <akpm@linux-foundation.org>
Subject: Re: [PATCH 5.15] mm: replace free hugepage folios after migration
Date: Fri, 06 Nov 2026 07:03:53 +0000 [thread overview]
Message-ID: <sashiko-outbox-200952@kernel.org> (raw)
In-Reply-To: <20261105070206.3094675-1-mkbund@amazon.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] mm/hugetlb: isolated free pages in free_huge_pages break
reservations and offline
- [Medium] mm: missing free hugepage replacement after migration in
alloc_contig_range()
--
commit c4fd411e1512176c3c86e8729268c9e64aee0792
Author: yangge <yangge1116@126.com>
mm: replace free hugepage folios after migration
This backport takes the dequeue_huge_page_node_exact() hunk from upstream
commit 04f13d241b8b146b23038bffd907cb8278391d07 so that free hugetlb pages
in MIGRATE_ISOLATE pageblocks are skipped when allocating from the hugetlb
pool.
Link: https://lkml.kernel.org/r/1734503588-16254-1-git-send-email-yangge1116@126.com
Link: https://lkml.kernel.org/r/1736582300-11364-1-git-send-email-yangge1116@126.com
[Severity: Medium]
In mm/hugetlb.c, dequeue_huge_page_node_exact() is updated to skip pages
where is_migrate_isolate_page(page) is true, while the commit subject and
changelog state that replace_free_hugepage_folios() is introduced and
invoked after migrating in-use hugetlb pages so cma_alloc() and
test_pages_isolated() succeed.
In 5.15, hugetlb pages are allocated with GFP_HIGHUSER_MOVABLE via
htlb_alloc_mask() and can reside in MIGRATE_CMA and MIGRATE_MOVABLE
pageblocks. During cma_alloc() -> alloc_contig_range() ->
__alloc_contig_migrate_range() in mm/page_alloc.c,
isolate_or_dissolve_huge_page() in mm/hugetlb.c dissolves free hugepages in
the target range via alloc_and_dissolve_huge_page(), but for in-use
hugepages (page_count(head) > 0) it isolates them onto cc->migratepages via
isolate_hugetlb() and advances cc->migrate_pfn past them.
When migrate_pages() migrates those in-use hugepages via
alloc_migration_target() -> alloc_huge_page_nodemask(), if unreserved free
hugepages exist in the pool (h->free_huge_pages - h->resv_huge_pages > 0),
dequeue_huge_page_nodemask() returns a free pool hugepage without
HPageTemporary set. Because HPageTemporary(newpage) is false,
move_hugetlb_state() does not set HPageTemporary on the old source page, so
free_huge_page() enqueues the old page back onto h->hugepage_freelists[nid]
inside the MIGRATE_ISOLATE range instead of returning it to the buddy
allocator.
Because this backport omits the post-migration replacement step after
__alloc_contig_migrate_range() (even though alloc_and_dissolve_huge_page()
already exists in mm/hugetlb.c), won't migrating in-use persistent hugetlb
pages still leave the freed source hugepages on h->hugepage_freelists
inside [start, end) and cause test_pages_isolated() in alloc_contig_range()
to fail with -EBUSY? Also, should the commit subject and message be updated
if only the dequeue_huge_page_node_exact() change is intended?
[Severity: High]
In mm/hugetlb.c, dequeue_huge_page_node_exact() skips pages where
is_migrate_isolate_page(page) is true, but those isolated pages remain on
h->hugepage_freelists[nid] and remain counted in h->free_huge_pages. Can
this cause both memory offlining (offline_pages()) and reserved hugetlb
page faults (alloc_huge_page()) to fail when free hugepages sit in a
MIGRATE_ISOLATE range?
Consider a memory block [start_pfn, end_pfn) being offlined via
offline_pages() that contains two in-use hugepages H0 and H1 (or one free
hugepage H0 and one in-use hugepage H1), while outside the block there is
one unreserved free hugepage F0 and one reserved free hugepage F1 backing
an existing reservation (h->free_huge_pages == 2, h->resv_huge_pages == 1):
1. offline_pages() calls start_isolate_page_range(), marking
[start_pfn, end_pfn) as MIGRATE_ISOLATE, and then calls
do_migrate_range().
2. Migrating H0 dequeues F0. When H0 is released via
putback_active_hugepage() -> free_huge_page() -> enqueue_huge_page(), H0
is placed onto h->hugepage_freelists[nid] inside the MIGRATE_ISOLATE
range and increments h->free_huge_pages back to 2.
3. When migrating H1, alloc_huge_page_nodemask() in mm/hugetlb.c checks:
if (h->free_huge_pages - h->resv_huge_pages > 0)
Because the isolated page H0 is still counted in h->free_huge_pages,
2 - 1 > 0 succeeds even though the only non-isolated free page (F1) is
needed to back h->resv_huge_pages.
4. dequeue_huge_page_node_exact() skips H0 because
is_migrate_isolate_page(H0) is true and dequeues the reserved page F1
for H1. H1 is then freed onto h->hugepage_freelists[nid] inside the
MIGRATE_ISOLATE range, leaving both free hugepages (H0 and H1) inside
the MIGRATE_ISOLATE range while h->resv_huge_pages == 1.
5. In offline_pages(), dissolve_free_huge_pages(start_pfn, end_pfn)
dissolves H0 (reducing h->free_huge_pages to 1) and then calls
dissolve_free_huge_page() on H1, which hits:
if (h->free_huge_pages - h->resv_huge_pages == 0)
goto out;
and fails with -EBUSY, aborting offline_pages().
In addition, gather_surplus_pages() in mm/hugetlb.c computes:
needed = (h->resv_huge_pages + delta) - h->free_huge_pages;
if (needed <= 0) {
h->resv_huge_pages += delta;
return 0;
}
which counts MIGRATE_ISOLATE free pages in h->free_huge_pages as usable to
satisfy reservations. Whenever the free pages backing h->resv_huge_pages
are in MIGRATE_ISOLATE pageblocks (either from migration swapping F1 with
H1 above, or from gather_surplus_pages()), a page fault on a VMA with a
valid reservation calls alloc_huge_page() -> dequeue_huge_page_vma(), which
skips the isolated pages in dequeue_huge_page_node_exact() and returns
NULL.
alloc_huge_page() then falls back to alloc_buddy_huge_page_with_mpol() ->
alloc_surplus_huge_page(), which fails when h->surplus_huge_pages >=
h->nr_overcommit_huge_pages (0 by default) or hstate_is_gigantic(h),
returning ERR_PTR(-ENOSPC) and delivering SIGBUS to a process faulting on a
reserved mapping.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105070206.3094675-1-mkbund@amazon.com?part=1
next prev parent reply other threads:[~2026-11-06 7:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 7:02 [PATCH 5.15] mm: replace free hugepage folios after migration Mark Bundschuh
2026-11-06 7:03 ` sashiko-bot [this message]
2026-11-06 7:46 ` David Hildenbrand (Arm)
2026-11-06 22:04 ` [PATCH v2 5.15 0/2] " Mark Bundschuh
2026-11-06 22:04 ` [PATCH v2 5.15 1/2] " Mark Bundschuh
2026-11-07 22:05 ` sashiko-bot
2026-11-06 22:04 ` [PATCH v2 5.15 2/2] mm/hugetlb: fix kernel NULL pointer dereference when replacing free hugetlb folios Mark Bundschuh
2026-11-07 22:05 ` sashiko-bot
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=sashiko-outbox-200952@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=21cnbao@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=david@kernel.org \
--cc=david@redhat.com \
--cc=linux-mm@kvack.org \
--cc=mkbund@amazon.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sj@kernel.org \
--cc=yangge1116@126.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.