All of 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 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.