mm/hugetlb.c | 57 ++++++++++++++++++++++++++++++++++++++++++---- mm/hugetlb_sysfs.c | 10 ++++---- 2 files changed, 57 insertions(+), 10 deletions(-)
From: Longlong Xia <xialonglong@kylinos.cn>
This is v2 of the two-patch series fixing surplus accounting and
availability checks in the hugetlb demote path.
Patch 1 fixes source hstate accounting when the free folio selected for
demotion accounts for a surplus page. Patch 2 prevents demotion from
removing free huge pages that back reservations.
Both fixes were tested with x86_64 QEMU guests. The commands below use:
hstate=/sys/kernel/mm/hugepages/hugepages-1048576kB
Patch 1: surplus accounting
A vmemmap restoration failure is difficult to trigger deterministically.
For this test only, add a one-shot fault injection that makes the first
attempt to restore the vmemmap of an optimized 1 GiB folio fail:
/* TEST ONLY: fail the first optimized 1G folio restore. */
static atomic_t fail_next_1g_restore = ATOMIC_INIT(1);
/* In __hugetlb_vmemmap_restore_folio(). */
if (huge_page_size(h) == SZ_1G &&
atomic_cmpxchg(&fail_next_1g_restore, 1, 0) == 1) {
pr_info("TEST ONLY: forcing one 1G vmemmap "
"restore failure\n");
return -ENOMEM;
}
The injection does not modify the demotion or accounting code. It is
one-shot so that the later restore performed during demotion can succeed.
1. Boot QEMU with:
hugepagesz=1G hugepages=0 hugetlb_cma=1G
hugetlb_free_vmemmap=on
2. Enable overcommit:
echo 1 > "$hstate/nr_overcommit_hugepages"
3. Allocate one 1 GiB huge page:
nr=1 surplus=1 free=0 resv=0
4. Unmap it. The forced restoration failure leaves the folio on the
freelist while it is still accounted as surplus:
nr=1 surplus=1 free=1 resv=0
5. Demote one page:
echo 1 > "$hstate/demote"
Before this fix:
nr=0 surplus=1 free=0 resv=0
surplus > nr
After this fix:
nr=0 surplus=0 free=0 resv=0
Patch 2: cap demotion
This reproducer requires no kernel instrumentation.
1. Boot QEMU with:
hugepagesz=1G hugepages=2
nr=2 surplus=0 free=2 resv=0
2. Reserve one 1 GiB huge page with an untouched hugetlbfs mapping:
nr=2 surplus=0 free=2 resv=1
3. Request demotion of two pages:
echo 2 > "$hstate/demote"
Before this fix:
nr=0 surplus=0 free=0 resv=1
resv > free
After this fix:
nr=1 surplus=0 free=1 resv=1
resv == free
4. Touch the reserved page and let the process exit.
Before this fix, the access fails with SIGBUS and leaves:
nr=0 surplus=0 free=0 resv=0
After this fix, the access succeeds and leaves:
nr=1 surplus=0 free=1 resv=0
Changes in v2:
- Add reproducer details and test results suggested by Andrew Morton.
Link: https://lore.kernel.org/all/20260823034307.1072415-1-xialonglong2025@163.com/
Longlong Xia (2):
mm/hugetlb: preserve source surplus accounting during demotion
mm/hugetlb: cap demotion at currently available free pages
mm/hugetlb.c | 57 ++++++++++++++++++++++++++++++++++++++++++----
mm/hugetlb_sysfs.c | 10 ++++----
2 files changed, 57 insertions(+), 10 deletions(-)
base-commit: a4ff2be345d0abc943da8dd8da98151843b750dc
--
2.43.0
On Mon, 31 Aug 2026 21:35:17 +0800 Longlong Xia <xialonglong2025@163.com> wrote: > From: Longlong Xia <xialonglong@kylinos.cn> > > This is v2 of the two-patch series fixing surplus accounting and > availability checks in the hugetlb demote path. > Could we please get some review of these two fixes? Thanks.
On Mon, 31 Aug 2026 21:35:17 +0800 Longlong Xia <xialonglong2025@163.com> wrote: > From: Longlong Xia <xialonglong@kylinos.cn> > > This is v2 of the two-patch series fixing surplus accounting and > availability checks in the hugetlb demote path. > > Patch 1 fixes source hstate accounting when the free folio selected for > demotion accounts for a surplus page. Patch 2 prevents demotion from > removing free huge pages that back reservations. > > Both fixes were tested with x86_64 QEMU guests. The commands below use: > > hstate=/sys/kernel/mm/hugepages/hugepages-1048576kB > > Patch 1: surplus accounting > > A vmemmap restoration failure is difficult to trigger deterministically. > For this test only, add a one-shot fault injection that makes the first > attempt to restore the vmemmap of an optimized 1 GiB folio fail: OK, so hard to hit from userspace but not impossible. > Patch 2: cap demotion > > This reproducer requires no kernel instrumentation. > > ... > > Before this fix, the access fails with SIGBUS and leaves: > > nr=0 surplus=0 free=0 resv=0 > > After this fix, the access succeeds and leaves: > > nr=1 surplus=0 free=1 resv=0 OK, that's bad behavior. I asked my friendly neighborhood LLM and was told : I'd phrase it like this, keeping the stable justification concrete : without overstating the exact failure mode: : : On architectures where gigantic HugeTLB pages cannot be allocated or : freed at runtime, memory hot-remove or hwpoison can attempt to dissolve : a boot-allocated gigantic page. The lower-level removal helpers : silently reject such pages, but dissolve_free_hugetlb_folio() continues : and can free the folio while it is still on the HugeTLB free list. If : vmemmap restoration fails, the rollback can additionally add the : already-listed folio to the free list again. : : This corrupts the HugeTLB free-page state. The corruption can persist : beyond the operation which triggered it and be encountered by a later : HugeTLB allocation, potentially resulting in kernel warnings, crashes : or memory corruption. Avoid the corruption by rejecting gigantic pages : without runtime support before modifying the HugeTLB pool. So, with a statement like that, I'm thinking that we should backport these fixes (or something else that fixes these issues!) Anyway, these are matters for maintainers to consider, please. For now I'll get these patches under test.
© 2016 - 2026 Red Hat, Inc.