Re: [PATCH v3 21/26] mm/page_alloc: implement FREETYPE_UNMAPPED allocations
From: Yosry Ahmed
Date: Mon Aug 17 2026 - 20:49:43 EST
On Sat, Aug 15, 2026 at 03:43:18PM +0100, Brendan Jackman wrote:
> On Wed Aug 12, 2026 at 10:26 PM BST, Yosry Ahmed wrote:
> > [..]
> >> static __always_inline
> >> struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone,
> >> unsigned int order, unsigned int alloc_flags,
> >> @@ -3433,13 +3580,15 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone,
> >> */
> >> if (!page && (alloc_flags & (ALLOC_OOM|ALLOC_HARDER)))
> >> page = __rmqueue_smallest(zone, order, ft_high);
> >> -
> >> - if (!page) {
> >> - spin_unlock_irqrestore(&zone->lock, flags);
> >> - return NULL;
> >> - }
> >> }
> >> spin_unlock_irqrestore(&zone->lock, flags);
> >> +
> >> + /* Try changing direct map, now we've released the zone lock */
> >> + if (!page)
> >> + page = __rmqueue_direct_map(zone, order, alloc_flags, freetype);
> >
> > Is it intentional that this is called outside __rmqueue() and doesn't
> > cover pcplists refills through rmqueue_bulk()?
> >
> > IIUC, we will never change a pageblock to unmapped to refill the
> > pcplists, so the unmapped pcplists can get filled in two ways:
> > (a) When unmapped pages are freed.
> > (b) When a pageblock is converted here (in rmqueue_buddy()), if the
> > allocation only consumes part of it, the new allocation might move
> > the rest into the pcplist through rmqueue_bulk().
> >
> > Does this mean that unmapped pcplists are less effective in serving
> > allocations? There is a tradeoff here because converting a pageblock to
> > unmapped is expensive, so maybe this is the right choice to make, I am
> > just wondering if this was intentional and/or if we tried it a different
> > way.
>
> Yeah I think this is all aligned with how I envisaged this working. I
> have been assuming that changing pageblocks only happens:
>
> 1. When botting / changing between different kinds of workload.
>
> 2. When the system is quite distressed by memory pressure.
>
> I think in both cases, proactively flipping a block just to refill
> pcplists is unhelpful?
I guess it depends on what context we refill in the pcplists in. If we
are already holding the zone lock it might be worth a refill to avoid
holding it again to do it later? I am not sure. We can probably punt on
this until we have numbers.
>
> > Actuall, THPs are not covered by scenario (b) above if the pageblock
> > size is the same as THP size, as the converted THPs are always consumed
> > by the allocation, so the THP pcplist will only be filled when THPs are
> > freed.
> >
> > I wonder if this would cause a problem for THP-heavy workloads (e.g.
> > guest_memfd using THP, or any THP usage with ASI).
>
> And again it doesn't feel right to proactively flip a block just to
> create a pcplist. The cost of a pcplist miss is basically a bit of
> cacheline contention while the cost of flipping a block is pretty high,
> it seems well worth risking the former to avoid the latter.
Zone lock contention can be a big problem. But yeah we probably
shouldn't make a decision without some numbers.
>
> > The other thing (that I probably mentioned elsewhere) is that kcompactd
> > does not produce unmapped pageblocks, so it seems like THP allocations
> > will mostly hit this code path and convert a pageblock to unmapped.
>
> Yeah, I think making kcompactd produce unmapped blocks is a nice
> standalone optimisation series and it can probably wait until someone
> has a workload they can share the performance improvements from.
Yup.
>
> > Actually, if we do bulk conversion to unmapped (e.g. in kcompactd) we
> > could batch the TLB shootdowns as well, but that should probably be done
> > separately.
>
> Oh, that's a good point though, coz that would also interact nicely with
> pcplists. In theory we could allocate several contiguous pageblocks,
> flip them with a single amortised flush, and then use that to refill
> pcplists. But yeah this still feels like far future optimisations if and
> when we actually knew it helped.
Agreed.