[RFC PATCH v2 1/4] mm: compaction: parameterize fragmentation score by order

From: Bo Zhang

Date: Wed Sep 30 2026 - 20:14:50 EST


The proactive compaction fragmentation score functions are hardwired to
COMPACTION_HPAGE_ORDER (typically order-9 for 2MB THP). To later allow
proactive compaction to target other orders (e.g. smaller mTHP orders),
generalize these helpers to take an explicit order argument:

- fragmentation_score_zone(zone, order)
- fragmentation_score_zone_weighted(zone, order)
- fragmentation_score_node(pgdat, order)

All callers pass COMPACTION_HPAGE_ORDER, so this patch is a pure
refactor with no functional change.

Signed-off-by: Bo Zhang <zhangbo56@xxxxxxxxxx>
---
mm/compaction.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index 4994e200bbec..ecd3e6cf54fc 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -2208,16 +2208,16 @@ static bool kswapd_is_running(pg_data_t *pgdat)

/*
* A zone's fragmentation score is the external fragmentation wrt to the
- * COMPACTION_HPAGE_ORDER. It returns a value in the range [0, 100].
+ * given order. It returns a value in the range [0, 100].
*/
-static unsigned int fragmentation_score_zone(struct zone *zone)
+static unsigned int fragmentation_score_zone(struct zone *zone, unsigned int order)
{
- return extfrag_for_order(zone, COMPACTION_HPAGE_ORDER);
+ return extfrag_for_order(zone, order);
}

/*
* A weighted zone's fragmentation score is the external fragmentation
- * wrt to the COMPACTION_HPAGE_ORDER scaled by the zone's size. It
+ * wrt to the given order scaled by the zone's size. It
* returns a value in the range [0, 100].
*
* The scaling factor ensures that proactive compaction focuses on larger
@@ -2225,11 +2225,11 @@ static unsigned int fragmentation_score_zone(struct zone *zone)
* ZONE_DMA32. For smaller zones, the score value remains close to zero,
* and thus never exceeds the high threshold for proactive compaction.
*/
-static unsigned int fragmentation_score_zone_weighted(struct zone *zone)
+static unsigned int fragmentation_score_zone_weighted(struct zone *zone, unsigned int order)
{
unsigned long score;

- score = zone->present_pages * fragmentation_score_zone(zone);
+ score = zone->present_pages * fragmentation_score_zone(zone, order);
return div64_ul(score, zone->zone_pgdat->node_present_pages + 1);
}

@@ -2240,7 +2240,7 @@ static unsigned int fragmentation_score_zone_weighted(struct zone *zone)
* the node's score falls below the low threshold, or one of the back-off
* conditions is met.
*/
-static unsigned int fragmentation_score_node(pg_data_t *pgdat)
+static unsigned int fragmentation_score_node(pg_data_t *pgdat, unsigned int order)
{
unsigned int score = 0;
int zoneid;
@@ -2251,7 +2251,7 @@ static unsigned int fragmentation_score_node(pg_data_t *pgdat)
zone = &pgdat->node_zones[zoneid];
if (!populated_zone(zone))
continue;
- score += fragmentation_score_zone_weighted(zone);
+ score += fragmentation_score_zone_weighted(zone, order);
}

return score;
@@ -2269,12 +2269,13 @@ static unsigned int fragmentation_score_wmark(bool low)
static bool should_proactive_compact_node(pg_data_t *pgdat)
{
int wmark_high;
+ unsigned int order = COMPACTION_HPAGE_ORDER;

if (!sysctl_compaction_proactiveness || kswapd_is_running(pgdat))
return false;

wmark_high = fragmentation_score_wmark(false);
- return fragmentation_score_node(pgdat) > wmark_high;
+ return fragmentation_score_node(pgdat, order) > wmark_high;
}

static enum compact_result __compact_finished(struct compact_control *cc)
@@ -2305,13 +2306,14 @@ static enum compact_result __compact_finished(struct compact_control *cc)

if (cc->proactive_compaction) {
int score, wmark_low;
+ unsigned int order = COMPACTION_HPAGE_ORDER;
pg_data_t *pgdat;

pgdat = cc->zone->zone_pgdat;
if (kswapd_is_running(pgdat))
return COMPACT_PARTIAL_SKIPPED;

- score = fragmentation_score_zone(cc->zone);
+ score = fragmentation_score_zone(cc->zone, order);
wmark_low = fragmentation_score_wmark(true);

if (score > wmark_low)
@@ -3237,10 +3239,11 @@ static int kcompactd(void *p)
timeout = default_timeout;
if (should_proactive_compact_node(pgdat)) {
unsigned int prev_score, score;
+ unsigned int order = COMPACTION_HPAGE_ORDER;

- prev_score = fragmentation_score_node(pgdat);
+ prev_score = fragmentation_score_node(pgdat, order);
compact_node(pgdat, true);
- score = fragmentation_score_node(pgdat);
+ score = fragmentation_score_node(pgdat, order);
/*
* Defer proactive compaction if the fragmentation
* score did not go down i.e. no progress made.
--
2.34.1