Re: [RFC PATCH 2/5] mm/page_alloc: count a merged buddy's pages under the merged type
From: Dev Jain
Date: Wed Oct 14 2026 - 10:23:43 EST
On 07/10/26 7:42 am, Rik van Riel wrote:
> __free_one_page() merges a freed page with a free buddy of another
> mergeable type at pageblock order and above, and retypes the buddy to
> match. The buddy's pages stay counted under the old type: nothing moves
> them to the merged type in the free counts.
>
> That is unobservable today. NR_FREE_PAGES does not separate types, so the
> missing move nets to zero there. Any future per-type free count would
> undercount on a merge from the other side, and allocating the merged
> run later could wrap it.
>
> Move the buddy's pages to the merged type in the count too.
>
> Assisted-by: LLM
> Signed-off-by: Rik van Riel <riel@xxxxxxxxxxx>
> ---
> mm/page_alloc.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 4658af97be010..ae38e25971559 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -993,6 +993,11 @@ static inline void __free_one_page(struct page *page,
> account_freepages(zone, 1 << order, migratetype);
> } else {
> __del_page_from_free_list(buddy, zone, order, buddy_mt);
> + /* The buddy's free pages join the merged block's type. */
> + if (unlikely(buddy_mt != migratetype)) {
> + account_freepages(zone, -(1 << order), buddy_mt);
> + account_freepages(zone, 1 << order, migratetype);
> + }
> }
>
MAX_PAGE_ORDER > pageblock_order confuses things so much : (
Sashiko raises something:
https://sashiko.dev/#/patchset/20261007021250.1665929-1-riel%40surriel.com
Although feels like it is exaggerating.
My concern is for systems with a high diff between MAX_PAGE_ORDER and
pageblock_order. So on arm64 systems with 64K pagesize but pageblock
size as 2M (and PMD size 512M), the pageblock order is 5. We use this
configuration to reliably get TLB optimization from contpte size mappings.
Will we then repeatedly overflow the pcpu counter into the zone counter,
regressing stuff?
Perhaps I am overthinking. Your approach is clean, but perhaps we could
also do:
void account_freepages_move(zone, order, buddy_mt, mt)
/* PCP-types do not have per-migratetype free counts. */
if (likely (buddy_mt < MIGRATE_PCPTYPES && mt < MIGRATE_PCPTYPES))
return;
account_freepages(zone, -(1 << order), buddy_mt);
account_freepages(zone, 1 << order, migratetype);
> if (unlikely(buddy_mt != migratetype)) {