[RFC PATCH 39/40] mm: compaction: respect tainted SPB reserve in destination selection

From: Rik van Riel

Date: Wed May 20 2026 - 11:20:40 EST


Tainted SPBs reserve headroom (per
spb_tainted_reserve()) so the allocator can satisfy non-movable
allocations without tainting fresh clean SPBs. Compaction's free-page
scanner can erode that reserve by picking destination pages from
tainted-SPB free lists -- exactly the headroom we need for unmovable
demand.

Refuse tainted-SPB pageblocks as compaction destinations once nr_free
is at or below spb_tainted_reserve(sb). Clean SPBs (no reserve) stay
fully eligible. This naturally biases compaction toward producing
free pageblocks inside clean SPBs, where they're useful for hugepage
allocation.

Combined with the source-side skip and the kcompactd wake fix, this
is sufficient for kcompactd to handle clean-SPB consolidation alone.

Signed-off-by: Rik van Riel <riel@xxxxxxxxxxx>
Assisted-by: Claude:claude-opus-4.7 syzkaller
---
mm/compaction.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/mm/compaction.c b/mm/compaction.c
index f9de52875c88..3d1015dffa82 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1503,6 +1503,21 @@ static bool suitable_migration_target(struct compact_control *cc,
if (cc->ignore_block_suitable)
return true;

+ /*
+ * Tainted superpageblocks reserve some headroom for non-movable
+ * allocations. Don't spill compaction migration into that reserve --
+ * doing so erodes the headroom the allocator was holding to avoid
+ * tainting fresh clean SPBs. Clean SPBs (no reserve) stay eligible.
+ */
+ if (cc->zone->nr_superpageblocks) {
+ struct superpageblock *sb =
+ pfn_to_superpageblock(cc->zone, page_to_pfn(page));
+
+ if (sb && spb_get_category(sb) == SB_TAINTED &&
+ sb->nr_free <= spb_tainted_reserve(sb))
+ return false;
+ }
+
/* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
if (is_migrate_movable(get_pageblock_migratetype(page)))
return true;
--
2.54.0