[RFC PATCH 37/40] mm: page_alloc: move spb_get_category and spb_tainted_reserve to mmzone.h

From: Rik van Riel

Date: Wed May 20 2026 - 11:15:47 EST


Pure move with no semantic change. Both helpers will be needed in
mm/compaction.c by upcoming SPB-skip predicates; keep a single source
of truth for them in <linux/mmzone.h> alongside pfn_to_superpageblock().

Signed-off-by: Rik van Riel <riel@xxxxxxxxxxx>
Assisted-by: Claude:claude-opus-4.7 syzkaller
---
include/linux/mmzone.h | 30 ++++++++++++++++++++++++++++++
mm/page_alloc.c | 27 +++++----------------------
2 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index c9c248d5b14e..d51dbca59656 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1296,6 +1296,36 @@ static inline struct superpageblock *pfn_to_superpageblock(struct zone *zone,
return &zone->superpageblocks[idx];
}

+/**
+ * spb_get_category - Determine if a superpageblock is clean or tainted
+ * @sb: superpageblock to classify
+ *
+ * A superpageblock is clean if it contains only free and movable pageblocks.
+ * Any unmovable, reclaimable, or reserved pageblocks make it tainted.
+ */
+static inline enum sb_category spb_get_category(struct superpageblock *sb)
+{
+ if (sb->nr_unmovable || sb->nr_reclaimable || sb->nr_reserved)
+ return SB_TAINTED;
+ return SB_CLEAN;
+}
+
+/*
+ * Minimum free-pageblock reserve a tainted SPB tries to maintain so the
+ * allocator can satisfy non-movable allocations without tainting fresh
+ * clean SPBs. Used by spb_tainted_reserve() as a floor for the per-SPB
+ * reserve; the page allocator and compaction both consult
+ * spb_tainted_reserve() to decide when a tainted SPB has so few free
+ * pageblocks left that movable allocations should look elsewhere.
+ * Scale with SPB size: reserve ~3% of pageblocks (minimum 4).
+ */
+#define SPB_TAINTED_RESERVE_MIN 4
+
+static inline u16 spb_tainted_reserve(const struct superpageblock *sb)
+{
+ return max_t(u16, SPB_TAINTED_RESERVE_MIN, sb->total_pageblocks / 32);
+}
+
enum pgdat_flags {
PGDAT_WRITEBACK, /* reclaim scanning has recently found
* many pages under writeback
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4e45fac14622..62edbdf0c3f3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -673,22 +673,8 @@ void superpageblock_set_has_movable(struct zone *zone, struct page *page)
}
#endif /* CONFIG_COMPACTION */

-/**
- * spb_get_category - Determine if a superpageblock is clean or tainted
- * @sb: superpageblock to classify
- *
- * A superpageblock is clean if it contains only free and movable pageblocks.
- * Any unmovable, reclaimable, or reserved pageblocks make it tainted.
- * Reserved pageblocks (memory holes) taint the superpageblock because it
- * can never be used for 1GB hugepages, making it a better home for
- * unmovable/reclaimable allocations.
- */
-static inline enum sb_category spb_get_category(struct superpageblock *sb)
-{
- if (sb->nr_unmovable || sb->nr_reclaimable || sb->nr_reserved)
- return SB_TAINTED;
- return SB_CLEAN;
-}
+/* spb_get_category() lives in <linux/mmzone.h> for shared use with
+ * mm/compaction.c. */

/**
* sb_get_fullness - Determine the fullness bucket for a superpageblock
@@ -2700,13 +2686,10 @@ static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags
*
* Scale with SPB size: reserve ~3% of pageblocks (minimum 4).
* For a 512-pageblock SPB this gives 16 reserved pageblocks.
+ *
+ * SPB_TAINTED_RESERVE_MIN and spb_tainted_reserve() live in
+ * <linux/mmzone.h> for shared use with mm/compaction.c.
*/
-#define SPB_TAINTED_RESERVE_MIN 4
-
-static inline u16 spb_tainted_reserve(const struct superpageblock *sb)
-{
- return max_t(u16, SPB_TAINTED_RESERVE_MIN, sb->total_pageblocks / 32);
-}

/*
* spb_tainted_can_serve_smaller - could a smaller-order @migratetype alloc
--
2.54.0