mm/hugetlb.c | 57 ++++++++++++++++++++++++++++++++++++++++++---- mm/hugetlb_sysfs.c | 10 ++++---- 2 files changed, 57 insertions(+), 10 deletions(-)
From: Longlong Xia <xialonglong@kylinos.cn> This series fixes two problems in the hugetlb demote path. Patch 1 fixes surplus accounting in the source hstate. demote_pool_huge_page() removes every source folio as a persistent folio, but a free folio may instead account for one of the source hstate's surplus pages (for example after a vmemmap restoration failure). Removing such a folio without adjusting surplus_huge_pages makes the persistent count underflow, and later subtracting it from max_huge_pages can underflow that counter as well. Patch 2 fixes an availability overcount in the sysfs demote path. The sysfs trigger checks whether any page is available but then passes the entire request to demote_pool_huge_page(), which can remove free huge pages that back existing reservations. With two free pages and one reservation, a request for two pages removes both and leaves the reservation without a backing page. Both patches carry Fixes tags. 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(-) -- 2.43.0
On Sun, 23 Aug 2026 11:43:05 +0800 Longlong Xia <xialonglong2025@163.com> wrote: > This series fixes two problems in the hugetlb demote path. > > Patch 1 fixes surplus accounting in the source hstate. > demote_pool_huge_page() removes every source folio as a persistent > folio, but a free folio may instead account for one of the source > hstate's surplus pages (for example after a vmemmap restoration > failure). Removing such a folio without adjusting surplus_huge_pages > makes the persistent count underflow, and later subtracting it from > max_huge_pages can underflow that counter as well. > > Patch 2 fixes an availability overcount in the sysfs demote path. The > sysfs trigger checks whether any page is available but then passes the > entire request to demote_pool_huge_page(), which can remove free huge > pages that back existing reservations. With two free pages and one > reservation, a request for two pages removes both and leaves the > reservation without a backing page. Thanks. Have you created and tested reproducers for these? Gemini was trivially able to do this for me. If so, it would be helpful to includes the details in the changelogging.
在 2026/8/29 7:10, Andrew Morton 写道:
> On Sun, 23 Aug 2026 11:43:05 +0800 Longlong Xia<xialonglong2025@163.com> wrote:
>
>> This series fixes two problems in the hugetlb demote path.
>>
>> Patch 1 fixes surplus accounting in the source hstate.
>> demote_pool_huge_page() removes every source folio as a persistent
>> folio, but a free folio may instead account for one of the source
>> hstate's surplus pages (for example after a vmemmap restoration
>> failure). Removing such a folio without adjusting surplus_huge_pages
>> makes the persistent count underflow, and later subtracting it from
>> max_huge_pages can underflow that counter as well.
>>
>> Patch 2 fixes an availability overcount in the sysfs demote path. The
>> sysfs trigger checks whether any page is available but then passes the
>> entire request to demote_pool_huge_page(), which can remove free huge
>> pages that back existing reservations. With two free pages and one
>> reservation, a request for two pages removes both and leaves the
>> reservation without a backing page.
> Thanks. Have you created and tested reproducers for these? Gemini was
> trivially able to do this for me.
>
> If so, it would be helpful to includes the details in the
> changelogging.
Hi Andrew,
Yes, I created and tested reproducers for both bugs.
Patch 1 requires a vmemmap restoration failure, which is difficult to
trigger deterministically. For that test only, I added a one-shot fault
injection that makes the first attempt to restore the vmemmap of an
optimized 1 GiB folio fail with -ENOMEM. The injection does not modify
the demotion or accounting code, and it is one-shot so that the later
restore performed during demotion can succeed.
Patch 2 is reproducible entirely from userspace and requires no kernel
instrumentation.
Patch 1 (surplus accounting):
1. Hack the kernel to force the first 1G vmemmap restore to 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;
}
2. Boot QEMU with:
hugepagesz=1G hugepages=0 hugetlb_cma=1G hugetlb_free_vmemmap=on
3. Enable overcommit:
echo 1 >
/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_overcommit_hugepages
4. Allocate one 1G hugepage:
nr=1 surplus=1 free=0 resv=0
5. Unmap it. Due to the forced restore failure, the folio is left on
the freelist but still accounted as surplus:
nr=1 surplus=1 free=1 resv=0
6. Demote one page:
echo 1 > /sys/kernel/mm/hugepages/hugepages-1048576kB/demote
Before fix:
nr=0 surplus=1 free=0 resv=0
surplus > nr (wrong -- surplus not decremented)
After fix:
nr=0 surplus=0 free=0 resv=0
accounts consistent
Patch 2 (cap demotion):
1. Boot QEMU with:
hugepagesz=1G hugepages=2
nr=2 surplus=0 free=2 resv=0
2. Reserve one 1G page (mmap hugetlbfs, do not touch):
nr=2 surplus=0 free=2 resv=1
3. Request demotion of 2 pages:
echo 2 > /sys/kernel/mm/hugepages/hugepages-1048576kB/demote
Before fix:
nr=0 surplus=0 free=0 resv=1
resv > free (wrong -- reservation has no backing page)
After fix:
nr=1 surplus=0 free=1 resv=1
resv == free (correct -- request capped at available=1)
4. Touch the reserved page and let the process exit:
Before fix:
Bus error (core dumped)
nr=0 surplus=0 free=0 resv=0
After fix:
touch: OK (value=0x00)
nr=1 surplus=0 free=1 resv=0
I'll include these reproducer details in the changelog of the next
version.
Thanks,
Longlong
© 2016 - 2026 Red Hat, Inc.