[PATCH 4/6] mm: page_alloc: fix move_freepages_block() range error

From: Johannes Weiner
Date: Mon Sep 11 2023 - 17:37:09 EST


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>
---
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;

--
2.42.0