On 9/11/23 21:41, Johannes Weiner wrote: > When a block is partially outside the zone of the cursor page, the > function cuts the range to the pivot page instead of the zone > start. This can leave large parts of the block behind, which > encourages incompatible page mixing down the line (ask for one type, > get another), and thus long-term fragmentation. > > This triggers reliably on the first block in the DMA zone, whose > start_pfn is 1. The block is stolen, but everything before the pivot > page (which was often hundreds of pages) is left on the old list. > > Signed-off-by: Johannes Weiner <hannes@xxxxxxxxxxx> Reviewed-by: Vlastimil Babka <vbabka@xxxxxxx> Note below: > --- > mm/page_alloc.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index f6f658c3d394..5bbe5f3be5ad 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1652,7 +1652,7 @@ int move_freepages_block(struct zone *zone, struct page *page, > > /* Do not cross zone boundaries */ > if (!zone_spans_pfn(zone, start_pfn)) > - start_pfn = pfn; > + start_pfn = zone->zone_start_pfn; > if (!zone_spans_pfn(zone, end_pfn)) > return 0; Culdn't we also adjust end_pfn to zone_end_pfn() so we don't just ignore the last half-pageblock for no good reason? (or am I missing any?) Also would stop treating end_pfn as inclusive here and in move_freepages(), it's rather uncommon. >