From: Wei Yang Date: Thu, 2 Oct 2025 03:31:39 +0000 (+0000) Subject: mm/compaction: check the range to pageblock_pfn_to_page() is within the zone first X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=72f51f4c55e69953853887ddf4d710320b3db2f5;p=users%2Fjedix%2Flinux-maple.git mm/compaction: check the range to pageblock_pfn_to_page() is within the zone first While reviewing isolate_migratepages_range(), I noticed a discrepancy: the page range passed to pageblock_pfn_to_page() is different from the range passed to isolate_migratepages_block(). This difference creates a potential issue: pageblock_pfn_to_page() might incorrectly confirm that the range is entirely within the same zone, but isolate_migratepages_block() could then proceed to isolate pages that span two different zones. This is unexpected behavior. Further investigation revealed that pageblock_pfn_to_page() contains an optimization for zones marked as contiguous. This optimization is buggy, as it causes the function to assume a range is within the same zone even if the PFNs actually cross a zone boundary. To resolve these issues, two patches are introduced: Patch 1: Check the range belongs to the zone first. Patch 2: Pass the correct range to pageblock_pfn_to_page() to ensure consistency between the check and the isolation steps. This patch (of 2): The function pageblock_pfn_to_page() was introduced by commit 7d49d8868336 ("mm, compaction: reduce zone checking frequency in the migration scanner"). At that time, it had no requirement that start_pfn and end_pfn had to be contained within the zone boundary; the only requirement was that they were in the same pageblock. Therefore, pageblock_pfn_to_page() would be called with a PFN (Page Frame Number) that wasn't checked against the zone boundary. However, after commit 7cf91a98e607 ("mm/compaction: speed up pageblock_pfn_to_page() when zone is contiguous"), pageblock_pfn_to_page() may incorrectly assume a range is valid and belongs to a contiguous zone, even if the range is outside that zone's actual boundaries. For instance, in fast_isolate_freepages(), min_pfn is assigned using pageblock_start_pfn() and passed to pageblock_pfn_to_page() without checking it against zone_start_pfn. Similarly, end_pfn is often not checked against zone_end_pfn(). To make this function robust, the range must be checked to ensure it is within the zone boundary first. Link: https://lkml.kernel.org/r/20251002033140.24462-1-richard.weiyang@gmail.com Link: https://lkml.kernel.org/r/20251002033140.24462-2-richard.weiyang@gmail.com Fixes: 7cf91a98e607 ("mm/compaction: speed up pageblock_pfn_to_page() when zone is contiguous") Signed-off-by: Wei Yang Cc: Vlastimil Babka Cc: Joonsoo Kim Cc: Brendan Jackman Cc: David Hildenbrand Cc: Johannes Weiner Cc: Liam Howlett Cc: Lorenzo Stoakes Cc: Michal Hocko Cc: Mike Rapoport Cc: Suren Baghdasaryan Cc: Zi Yan Signed-off-by: Andrew Morton --- diff --git a/mm/internal.h b/mm/internal.h index ca7bb5e56dff..a2555be247e5 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -724,6 +724,9 @@ extern struct page *__pageblock_pfn_to_page(unsigned long start_pfn, static inline struct page *pageblock_pfn_to_page(unsigned long start_pfn, unsigned long end_pfn, struct zone *zone) { + if (start_pfn < zone->zone_start_pfn || end_pfn > zone_end_pfn(zone)) + return NULL; + if (zone->contiguous) return pfn_to_page(start_pfn);