When two buddy pages merge in __free_one_page(), preserve PG_zeroed on the merged page only if both buddies have the flag set. Otherwise clear it. Without this, a zeroed page (freed via free_frozen_pages_zeroed from balloon deflate) could merge with a non-zero buddy. The merged page would inherit PG_zeroed, and a later __GFP_ZERO allocation would skip zeroing stale data in the non-zero half. The page reporting path is not affected: it sets PG_zeroed during allocation (page_del_and_expand), not on free list pages. Signed-off-by: Michael S. Tsirkin Assisted-by: Claude:claude-opus-4-6 Assisted-by: cursor-agent:GPT-5.4-xhigh --- mm/page_alloc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9311374bbd2d..122b49a6d435 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -991,6 +991,8 @@ static inline void __free_one_page(struct page *page, unsigned long buddy_pfn = 0; unsigned long combined_pfn; struct page *buddy; + bool buddy_zeroed; + bool page_zeroed; bool to_tail; VM_BUG_ON(!zone_is_initialized(zone)); @@ -1029,6 +1031,8 @@ static inline void __free_one_page(struct page *page, goto done_merging; } + buddy_zeroed = PageZeroed(buddy); + /* * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page, * merge with it and move up one order. @@ -1047,10 +1051,17 @@ static inline void __free_one_page(struct page *page, change_pageblock_range(buddy, order, migratetype); } + page_zeroed = PageZeroed(page); + __ClearPageZeroed(page); + __ClearPageZeroed(buddy); + combined_pfn = buddy_pfn & pfn; page = page + (combined_pfn - pfn); pfn = combined_pfn; order++; + + if (page_zeroed && buddy_zeroed) + __SetPageZeroed(page); } done_merging: -- MST