Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Mark Bundschuh" <mkbund@amazon.com>
Cc: sashal@kernel.org, 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 v2 6.6 1/2] mm: replace free hugepage folios after migration
Date: Sat, 07 Nov 2026 22:08:45 +0000	[thread overview]
Message-ID: <sashiko-outbox-203356@kernel.org> (raw)
In-Reply-To: <20261106220812.2874571-2-mkbund@amazon.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] mm: hugetlb: skipping isolated folios in dequeue breaks resv
  accounting
- [Medium] mm: hugetlb: pfn step in replace_free_hugepage_folios()
  over-allocates
- [Medium] mm: hugetlb: missing free_hpage_work flush after hugetlb
  migration
--

commit 001656b3d65502344f54f0dc762e32f45c183341
Author: yangge <yangge1116@126.com>

mm: replace free hugepage folios after migration

This commit skips isolated free hugetlb folios during pool dequeuing and
adds replace_free_hugepage_folios() to replace and dissolve free hugetlb
folios in the target range after migration in alloc_contig_range().

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

> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 8bfaaa84bb3f7..2ef28c49b9d0f 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c

[ ... ]

> @@ -1344,6 +1345,9 @@ static struct folio *dequeue_hugetlb_folio_node_exact(struct hstate *h,
>  		if (folio_test_hwpoison(folio))
>  			continue;
>  
> +		if (is_migrate_isolate_page(&folio->page))
> +			continue;
> +
>  		list_move(&folio->lru, &h->hugepage_activelist);
>  		folio_ref_unfreeze(folio, 1);
>  		folio_clear_hugetlb_freed(folio);

[Severity: High]
Does skipping isolated folios in dequeue_hugetlb_folio_node_exact() while
still counting them in h->free_huge_pages break hugetlb reservation
accounting?

available_huge_pages(h) computes h->free_huge_pages - h->resv_huge_pages,
so a free folio in a MIGRATE_ISOLATE pageblock still appears as an
available unreserved page even though it cannot be dequeued.  When
alloc_hugetlb_folio_nodemask() or an unreserved fault sees
available_huge_pages(h) > 0, dequeue_hugetlb_folio_node_exact() skips the
isolated folio and consumes a non-isolated free folio that was backing
h->resv_huge_pages instead of allocating a temporary migration folio via
alloc_migrate_hugetlb_folio().

Once the reserved free folios have been replaced by isolated free folios:

1. A page fault on a VMA with a valid reservation sees
   dequeue_hugetlb_folio_vma() return NULL and falls back to
   alloc_buddy_hugetlb_folio_with_mpol(), which fails with -ENOSPC (and
   delivers SIGBUS) whenever surplus overcommit is disabled
   (nr_overcommit_huge_pages == 0 by default, or gigantic pages).

2. In offline_pages(), dissolve_free_huge_pages() dissolves the unreserved
   folio (dropping available_huge_pages(h) to 0 and shrinking
   h->max_huge_pages) and then fails with -EBUSY on the remaining isolated
   free folios because !available_huge_pages(h).

Also, is_migrate_isolate_page(&folio->page) only checks the head pageblock
and misses isolated tail pageblocks when huge_page_order(h) >
pageblock_order.

> @@ -3048,6 +3052,44 @@ int isolate_or_dissolve_huge_page(struct page *page, struct list_head *list)
>  	return ret;
>  }
>  
> +/*
> + *  replace_free_hugepage_folios - Replace free hugepage folios in a given pfn
> + *  range with new folios.
> + *  @start_pfn: start pfn of the given pfn range
> + *  @end_pfn: end pfn of the given pfn range
> + *  Returns 0 on success, otherwise negated error.
> + */
> +int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn)
> +{
> +	struct hstate *h;
> +	struct folio *folio;
> +	int ret = 0;
> +
> +	LIST_HEAD(isolate_list);
> +
> +	while (start_pfn < end_pfn) {
> +		folio = pfn_folio(start_pfn);
> +		if (folio_test_hugetlb(folio)) {
> +			h = folio_hstate(folio);
> +		} else {
> +			start_pfn++;
> +			continue;
> +		}
> +
> +		if (!folio_ref_count(folio)) {
> +			ret = alloc_and_dissolve_hugetlb_folio(h, folio,
> +							       &isolate_list);

[Severity: Medium]
When HugeTLB vmemmap optimization (HVO) is active, can
replace_free_hugepage_folios() miss temporary or surplus folios that were
just freed by __alloc_contig_migrate_range()?

Because dequeue_hugetlb_folio_node_exact() now skips isolated free folios,
hugetlb migrations in the range fall back to alloc_migrate_hugetlb_folio(),
which sets HPG_temporary.  When migration finishes, free_huge_folio() frees
the old folio via update_and_free_hugetlb_folio(h, folio, true); for an HVO
folio, this keeps a reference count of 1 and queues the folio onto
hpage_freelist for free_hpage_work to restore vmemmap asynchronously.

Without flushing free_hpage_work (for example via
wait_for_freed_hugetlb_folios() or flush_free_hpage_work(h)) before
scanning the range, folio_ref_count(folio) is still 1 here and
test_pages_isolated() subsequently fails with -EBUSY because the folio has
not yet been returned to the buddy allocator.

> +			if (ret)
> +				break;
> +
> +			putback_movable_pages(&isolate_list);
> +		}
> +		start_pfn++;
> +	}

[Severity: Medium]
Can advancing start_pfn by 1 cause replace_free_hugepage_folios() to call
alloc_and_dissolve_hugetlb_folio() on every tail page of the same hugepage
if it was not dissolved?

In alloc_and_dissolve_hugetlb_folio(), __update_and_free_hugetlb_folio()
can fail to restore vmemmap under memory pressure and put old_folio back on
the hugetlb freelist as a surplus page with refcount 0 while still
returning 0:

mm/hugetlb.c:__update_and_free_hugetlb_folio() {
    ...
	if (hugetlb_vmemmap_restore(h, &folio->page)) {
		spin_lock_irq(&hugetlb_lock);
		add_hugetlb_folio(h, folio, true);
		spin_unlock_irq(&hugetlb_lock);
		return;
	}
    ...
}

Because old_folio remains a free hugetlb folio and start_pfn only increments
by 1, the loop hits the same folio on each of its remaining tail PFNs,
allocating a new replacement hugepage and incrementing h->nr_huge_pages and
h->surplus_huge_pages on every tail PFN (up to 511 extra hugepages for a
2MB folio).  The same repeated scan happens if
alloc_and_dissolve_hugetlb_folio() isolates a concurrently referenced folio
into isolate_list and putback_movable_pages(&isolate_list) immediately
releases it.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106220812.2874571-1-mkbund@amazon.com?part=1


  reply	other threads:[~2026-11-07 22:08 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05  7:04 [PATCH 6.6] mm: replace free hugepage folios after migration Mark Bundschuh
2026-11-06  7:04 ` sashiko-bot
2026-11-06 22:08 ` [PATCH v2 6.6 0/2] " Mark Bundschuh
2026-11-06 22:08   ` [PATCH v2 6.6 1/2] " Mark Bundschuh
2026-11-07 22:08     ` sashiko-bot [this message]
2026-11-06 22:08   ` [PATCH v2 6.6 2/2] mm/hugetlb: fix kernel NULL pointer dereference when replacing free hugetlb folios Mark Bundschuh

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-203356@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=sashal@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox