[PATCH v5 22/28] mm: page_alloc: propagate PG_zeroed in split_large_buddy

From: Michael S. Tsirkin

Date: Thu May 07 2026 - 18:31:18 EST


When a large zeroed page is freed with order > pageblock_order,
split_large_buddy splits it into pageblock-sized pieces. Propagate
PG_zeroed from the head page to each sub-block head so the zeroed
hint is not lost.

The propagation reads PageZeroed from the head page (set by
__free_pages_ok before calling free_one_page) rather than from
FPI_ZEROED, to avoid incorrectly marking deferred pages that
share the same code path but may not be zeroed.

For order-0 frees this is a single-iteration no-op (the head
already has the flag). For higher-order frees it ensures all
sub-block heads inherit the zeroed hint.

Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
Assisted-by: Claude:claude-opus-4-6
---
mm/page_alloc.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5c6ab949855a..954d86655f77 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1554,6 +1554,7 @@ static void split_large_buddy(struct zone *zone, struct page *page,
unsigned long pfn, int order, fpi_t fpi)
{
unsigned long end = pfn + (1 << order);
+ bool zeroed = PageZeroed(page);

VM_WARN_ON_ONCE(!IS_ALIGNED(pfn, 1 << order));
/* Caller removed page from freelist, buddy info cleared! */
@@ -1565,6 +1566,8 @@ static void split_large_buddy(struct zone *zone, struct page *page,
do {
int mt = get_pfnblock_migratetype(page, pfn);

+ if (zeroed)
+ __SetPageZeroed(page);
__free_one_page(page, pfn, zone, order, mt, fpi);
pfn += 1 << order;
if (pfn == end)
@@ -1624,8 +1627,11 @@ static void __free_pages_ok(struct page *page, unsigned int order,
unsigned long pfn = page_to_pfn(page);
struct zone *zone = page_zone(page);

- if (__free_pages_prepare(page, order, fpi_flags))
+ if (__free_pages_prepare(page, order, fpi_flags)) {
+ if (fpi_flags & FPI_ZEROED)
+ __SetPageZeroed(page);
free_one_page(zone, page, pfn, order, fpi_flags);
+ }
}

void __meminit __free_pages_core(struct page *page, unsigned int order,
--
MST