[PATCH v2 0/2] mm/hugetlb: fix surplus accounting and availability checks during demotion
From: Longlong Xia
Date: Mon Aug 31 2026 - 10:31:27 EST
From: Longlong Xia <xialonglong@xxxxxxxxxx>
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@xxxxxxx/
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