AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/06/26 20:21 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": [
    "COMPACTION"
  ],
  "FocusSymbols": [
    "__alloc_pages_direct_compact",
    "try_to_compact_pages",
    "compact_zone_order",
    "suitable_migration_source",
    "fast_find_migrateblock"
  ],
  "Reasoning": "The patch modifies memory compaction and allocation logic, specifically how direct compaction and reclaim handle page capture and compaction orders. It promotes the compaction order to `pageblock_order` for certain allocations to prevent fragmentation. This is core memory management logic that is reachable during high-order memory allocations and memory pressure. It is functional and should be fuzzed.",
  "WorthFuzzing": true
}

1/1 2026/06/26 20:21 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 16bbc4e99e1ad6ec710c09981dd0d026d32fba15\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Fri Jun 26 20:21:52 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/include/linux/compaction.h b/include/linux/compaction.h\nindex f29ef0653546ed..66a2f70e9e019d 100644\n--- a/include/linux/compaction.h\n+++ b/include/linux/compaction.h\n@@ -58,6 +58,7 @@ enum compact_result {\n };\n \n struct alloc_context; /* in mm/internal.h */\n+struct capture_control; /* in mm/internal.h */\n \n /*\n  * Number of free order-0 pages that should be available above given watermark\n@@ -92,7 +93,7 @@ extern int fragmentation_index(struct zone *zone, unsigned int order);\n extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,\n \t\tunsigned int order, unsigned int alloc_flags,\n \t\tconst struct alloc_context *ac, enum compact_priority prio,\n-\t\tstruct page **page);\n+\t\tstruct capture_control *capc);\n extern void reset_isolation_suitable(pg_data_t *pgdat);\n extern bool compaction_suitable(struct zone *zone, int order,\n \t\t\t\tunsigned long watermark, int highest_zoneidx);\ndiff --git a/mm/compaction.c b/mm/compaction.c\nindex f08765ade014ce..c2701bf1d04ed7 100644\n--- a/mm/compaction.c\n+++ b/mm/compaction.c\n@@ -1381,12 +1381,33 @@ static bool suitable_migration_source(struct compact_control *cc,\n \tif (pageblock_skip_persistent(page))\n \t\treturn false;\n \n-\tif ((cc-\u003emode != MIGRATE_ASYNC) || !cc-\u003edirect_compaction)\n+\t/*\n+\t * Background compaction produces blocks for the zone at\n+\t * large, with no particular allocation context. Allow all\n+\t * block types, including CMA.\n+\t */\n+\tif (!cc-\u003edirect_compaction)\n \t\treturn true;\n \n \tblock_mt = get_pageblock_migratetype(page);\n \n-\tif (cc-\u003emigratetype == MIGRATE_MOVABLE)\n+\t/*\n+\t * CMA pages can only be taken by ALLOC_CMA requests. For anybody\n+\t * else, vacating a CMA block consumes free pages the caller\n+\t * could have used, and produces free pages it cannot.\n+\t */\n+\tif (is_migrate_cma(block_mt) \u0026\u0026 !(cc-\u003ealloc_flags \u0026 ALLOC_CMA))\n+\t\treturn false;\n+\n+\tif (cc-\u003emode != MIGRATE_ASYNC)\n+\t\treturn true;\n+\n+\t/*\n+\t * Prevent small unmovable/reclaimable requests from polluting\n+\t * movable blocks through fallbacks. Whole-block production is\n+\t * exempt as the allocator claims and converts these.\n+\t */\n+\tif (cc-\u003emigratetype == MIGRATE_MOVABLE || cc-\u003eorder \u003e= pageblock_order)\n \t\treturn is_migrate_movable(block_mt);\n \telse\n \t\treturn block_mt == cc-\u003emigratetype;\n@@ -1974,12 +1995,12 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)\n \t\treturn pfn;\n \n \t/*\n-\t * Only allow kcompactd and direct requests for movable pages to\n-\t * quickly clear out a MOVABLE pageblock for allocation. This\n-\t * reduces the risk that a large movable pageblock is freed for\n-\t * an unmovable/reclaimable small allocation.\n+\t * Prevent small unmovable/reclaimable requests from polluting\n+\t * movable blocks through fallbacks. Whole-block production is\n+\t * exempt as the allocator claims and converts these.\n \t */\n-\tif (cc-\u003edirect_compaction \u0026\u0026 cc-\u003emigratetype != MIGRATE_MOVABLE)\n+\tif (cc-\u003edirect_compaction \u0026\u0026 cc-\u003emigratetype != MIGRATE_MOVABLE \u0026\u0026\n+\t    cc-\u003eorder \u003c pageblock_order)\n \t\treturn pfn;\n \n \t/*\n@@ -2770,7 +2791,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc)\n static enum compact_result compact_zone_order(struct zone *zone, int order,\n \t\tgfp_t gfp_mask, enum compact_priority prio,\n \t\tunsigned int alloc_flags, int highest_zoneidx,\n-\t\tstruct page **capture)\n+\t\tstruct capture_control *capc)\n {\n \tenum compact_result ret;\n \tstruct compact_control cc = {\n@@ -2787,35 +2808,22 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,\n \t\t.ignore_skip_hint = (prio == MIN_COMPACT_PRIORITY),\n \t\t.ignore_block_suitable = (prio == MIN_COMPACT_PRIORITY)\n \t};\n-\tstruct capture_control capc = {\n-\t\t.cc = \u0026cc,\n-\t\t.page = NULL,\n-\t};\n \n-\t/*\n-\t * Make sure the structs are really initialized before we expose the\n-\t * capture control, in case we are interrupted and the interrupt handler\n-\t * frees a page.\n-\t */\n+\t/* See the comment in __alloc_pages_direct_compact() */\n \tbarrier();\n-\tWRITE_ONCE(current-\u003ecapture_control, \u0026capc);\n+\tWRITE_ONCE(capc-\u003ecc, \u0026cc);\n \n-\tret = compact_zone(\u0026cc, \u0026capc);\n+\tret = compact_zone(\u0026cc, capc);\n+\n+\tWRITE_ONCE(capc-\u003ecc, NULL);\n \n-\t/*\n-\t * Make sure we hide capture control first before we read the captured\n-\t * page pointer, otherwise an interrupt could free and capture a page\n-\t * and we would leak it.\n-\t */\n-\tWRITE_ONCE(current-\u003ecapture_control, NULL);\n-\t*capture = READ_ONCE(capc.page);\n \t/*\n \t * Technically, it is also possible that compaction is skipped but\n \t * the page is still captured out of luck(IRQ came and freed the page).\n \t * Returning COMPACT_SUCCESS in such cases helps in properly accounting\n \t * the COMPACT[STALL|FAIL] when compaction is skipped.\n \t */\n-\tif (*capture)\n+\tif (capc-\u003epage)\n \t\tret = COMPACT_SUCCESS;\n \n \treturn ret;\n@@ -2828,13 +2836,13 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,\n  * @alloc_flags: The allocation flags of the current allocation\n  * @ac: The context of current allocation\n  * @prio: Determines how hard direct compaction should try to succeed\n- * @capture: Pointer to free page created by compaction will be stored here\n+ * @capc: The context for capturing pages during freeing\n  *\n  * This is the main entry point for direct page compaction.\n  */\n enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,\n \t\tunsigned int alloc_flags, const struct alloc_context *ac,\n-\t\tenum compact_priority prio, struct page **capture)\n+\t\tenum compact_priority prio, struct capture_control *capc)\n {\n \tstruct zoneref *z;\n \tstruct zone *zone;\n@@ -2862,7 +2870,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,\n \t\t}\n \n \t\tstatus = compact_zone_order(zone, order, gfp_mask, prio,\n-\t\t\t\talloc_flags, ac-\u003ehighest_zoneidx, capture);\n+\t\t\t\talloc_flags, ac-\u003ehighest_zoneidx, capc);\n \t\trc = max(status, rc);\n \n \t\t/* The allocation should succeed, stop compacting */\ndiff --git a/mm/internal.h b/mm/internal.h\nindex 181e79f1d6a207..1f636cfc859a1a 100644\n--- a/mm/internal.h\n+++ b/mm/internal.h\n@@ -1060,6 +1060,13 @@ struct compact_control {\n  */\n struct capture_control {\n \tstruct compact_control *cc;\n+\t/*\n+\t * Allocation request order. May differ from the compaction\n+\t * order: defrag_mode promotes sub-block allocations to\n+\t * pageblock-order compaction; capture still matches at the\n+\t * original allocation order so prep_new_page() is consistent.\n+\t */\n+\tint order;\n \tstruct page *page;\n };\n \ndiff --git a/mm/page_alloc.c b/mm/page_alloc.c\nindex ee902a468c2f5b..575a99a4c72384 100644\n--- a/mm/page_alloc.c\n+++ b/mm/page_alloc.c\n@@ -718,7 +718,7 @@ static inline struct capture_control *task_capc(struct zone *zone)\n {\n \tstruct capture_control *capc = current-\u003ecapture_control;\n \n-\treturn unlikely(capc) \u0026\u0026\n+\treturn unlikely(capc \u0026\u0026 capc-\u003ecc) \u0026\u0026\n \t\t!(current-\u003eflags \u0026 PF_KTHREAD) \u0026\u0026\n \t\t!capc-\u003epage \u0026\u0026\n \t\tcapc-\u003ecc-\u003ezone == zone ? capc : NULL;\n@@ -728,7 +728,7 @@ static inline bool\n compaction_capture(struct capture_control *capc, struct page *page,\n \t\t   int order, int migratetype)\n {\n-\tif (!capc || order != capc-\u003ecc-\u003eorder)\n+\tif (!capc || order != capc-\u003eorder)\n \t\treturn false;\n \n \t/* Do not accidentally pollute CMA or isolated regions*/\n@@ -748,7 +748,7 @@ compaction_capture(struct capture_control *capc, struct page *page,\n \t\treturn false;\n \n \tif (migratetype != capc-\u003ecc-\u003emigratetype)\n-\t\ttrace_mm_page_alloc_extfrag(page, capc-\u003ecc-\u003eorder, order,\n+\t\ttrace_mm_page_alloc_extfrag(page, capc-\u003eorder, order,\n \t\t\t\t\t    capc-\u003ecc-\u003emigratetype, migratetype);\n \n \tcapc-\u003epage = page;\n@@ -4146,21 +4146,59 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\n \tstruct page *page = NULL;\n \tunsigned long pflags;\n \tunsigned int noreclaim_flag;\n+\tstruct capture_control capc = {\n+\t\t.order = order,\n+\t\t.page = NULL,\n+\t};\n+\tint compact_order = order;\n \n-\tif (!order)\n+\t/*\n+\t * If fallbacks are not permitted (defrag_mode), we either\n+\t * need to reclaim space in a block of matching type, or clear\n+\t * out an entire block to allow __rmqueue_claim() to convert.\n+\t *\n+\t * Reclaim by itself is primarily freeing space in movable\n+\t * blocks, since that's where the LRU pages live. So this\n+\t * works for movable requests, but not for others.\n+\t *\n+\t * For those, promote the order to help make blocks, instead\n+\t * of spinning in reclaim alone unproductively.\n+\t */\n+\tif ((alloc_flags \u0026 ALLOC_NOFRAGMENT) \u0026\u0026 ac-\u003emigratetype != MIGRATE_MOVABLE)\n+\t\tcompact_order = max(order, pageblock_order);\n+\n+\tif (!compact_order)\n \t\treturn NULL;\n \n+\t/*\n+\t * Make sure the structs are really initialized before we expose the\n+\t * capture control, in case we are interrupted and the interrupt handler\n+\t * frees a page.\n+\t */\n+\tbarrier();\n+\tWRITE_ONCE(current-\u003ecapture_control, \u0026capc);\n+\n \tpsi_memstall_enter(\u0026pflags);\n \tdelayacct_compact_start();\n+\tfs_reclaim_acquire(gfp_mask);\n \tnoreclaim_flag = memalloc_noreclaim_save();\n \n-\t*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,\n-\t\t\t\t\t\t\t\tprio, \u0026page);\n+\t*compact_result = try_to_compact_pages(gfp_mask, compact_order,\n+\t\t\t\t\t       alloc_flags, ac, prio, \u0026capc);\n \n \tmemalloc_noreclaim_restore(noreclaim_flag);\n+\tfs_reclaim_release(gfp_mask);\n \tpsi_memstall_leave(\u0026pflags);\n \tdelayacct_compact_end();\n \n+\t/*\n+\t * Make sure we hide capture control first before we read the captured\n+\t * page pointer, otherwise an interrupt could free and capture a page\n+\t * and we would leak it.\n+\t */\n+\tWRITE_ONCE(current-\u003ecapture_control, NULL);\n+\tpage = READ_ONCE(capc.page);\n+\n \tif (*compact_result == COMPACT_SKIPPED ||\n \t    *compact_result == COMPACT_DEFERRED)\n \t\treturn NULL;\n@@ -4182,7 +4220,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\n \t\tstruct zone *zone = page_zone(page);\n \n \t\tzone-\u003ecompact_blockskip_flush = false;\n-\t\tcompaction_defer_reset(zone, order, true);\n+\t\tcompaction_defer_reset(zone, compact_order, true);\n \t\tcount_vm_event(COMPACTSUCCESS);\n \t\treturn page;\n \t}\n@@ -4422,9 +4460,14 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,\n \tstruct page *page = NULL;\n \tunsigned long pflags;\n \tbool drained = false;\n+\tint reclaim_order = order;\n+\n+\t/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */\n+\tif ((alloc_flags \u0026 ALLOC_NOFRAGMENT) \u0026\u0026 ac-\u003emigratetype != MIGRATE_MOVABLE)\n+\t\treclaim_order = max(order, pageblock_order);\n \n \tpsi_memstall_enter(\u0026pflags);\n-\t*did_some_progress = __perform_reclaim(gfp_mask, order, ac);\n+\t*did_some_progress = __perform_reclaim(gfp_mask, reclaim_order, ac);\n \tif (unlikely(!(*did_some_progress)))\n \t\tgoto out;\n \n"
}

2/1 2026/06/26 20:21 agent patch-evaluator
1m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "COMPACTION"
  ],
  "FocusSymbols": [
    "__alloc_pages_direct_compact",
    "try_to_compact_pages",
    "compact_zone_order",
    "suitable_migration_source",
    "fast_find_migrateblock"
  ],
  "Reasoning": "The patch modifies memory compaction and allocation logic, specifically how direct compaction and reclaim handle page capture and compaction orders. It promotes the compaction order to `pageblock_order` for certain allocations to prevent fragmentation. This is core memory management logic that is reachable during high-order memory allocations and memory pressure. It is functional and should be fuzzed.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 16bbc4e99e1ad6ec710c09981dd0d026d32fba15
Author: syz-cluster <triage@syzkaller.com>
Date:   Fri Jun 26 20:21:52 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index f29ef0653546ed..66a2f70e9e019d 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -58,6 +58,7 @@ enum compact_result {
 };
 
 struct alloc_context; /* in mm/internal.h */
+struct capture_control; /* in mm/internal.h */
 
 /*
  * Number of free order-0 pages that should be available above given watermark
@@ -92,7 +93,7 @@ extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
 		unsigned int order, unsigned int alloc_flags,
 		const struct alloc_context *ac, enum compact_priority prio,
-		struct page **page);
+		struct capture_control *capc);
 extern void reset_isolation_suitable(pg_data_t *pgdat);
 extern bool compaction_suitable(struct zone *zone, int order,
 				unsigned long watermark, int highest_zoneidx);
diff --git a/mm/compaction.c b/mm/compaction.c
index f08765ade014ce..c2701bf1d04ed7 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1381,12 +1381,33 @@ static bool suitable_migration_source(struct compact_control *cc,
 	if (pageblock_skip_persistent(page))
 		return false;
 
-	if ((cc->mode != MIGRATE_ASYNC) || !cc->direct_compaction)
+	/*
+	 * Background compaction produces blocks for the zone at
+	 * large, with no particular allocation context. Allow all
+	 * block types, including CMA.
+	 */
+	if (!cc->direct_compaction)
 		return true;
 
 	block_mt = get_pageblock_migratetype(page);
 
-	if (cc->migratetype == MIGRATE_MOVABLE)
+	/*
+	 * CMA pages can only be taken by ALLOC_CMA requests. For anybody
+	 * else, vacating a CMA block consumes free pages the caller
+	 * could have used, and produces free pages it cannot.
+	 */
+	if (is_migrate_cma(block_mt) && !(cc->alloc_flags & ALLOC_CMA))
+		return false;
+
+	if (cc->mode != MIGRATE_ASYNC)
+		return true;
+
+	/*
+	 * Prevent small unmovable/reclaimable requests from polluting
+	 * movable blocks through fallbacks. Whole-block production is
+	 * exempt as the allocator claims and converts these.
+	 */
+	if (cc->migratetype == MIGRATE_MOVABLE || cc->order >= pageblock_order)
 		return is_migrate_movable(block_mt);
 	else
 		return block_mt == cc->migratetype;
@@ -1974,12 +1995,12 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)
 		return pfn;
 
 	/*
-	 * Only allow kcompactd and direct requests for movable pages to
-	 * quickly clear out a MOVABLE pageblock for allocation. This
-	 * reduces the risk that a large movable pageblock is freed for
-	 * an unmovable/reclaimable small allocation.
+	 * Prevent small unmovable/reclaimable requests from polluting
+	 * movable blocks through fallbacks. Whole-block production is
+	 * exempt as the allocator claims and converts these.
 	 */
-	if (cc->direct_compaction && cc->migratetype != MIGRATE_MOVABLE)
+	if (cc->direct_compaction && cc->migratetype != MIGRATE_MOVABLE &&
+	    cc->order < pageblock_order)
 		return pfn;
 
 	/*
@@ -2770,7 +2791,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc)
 static enum compact_result compact_zone_order(struct zone *zone, int order,
 		gfp_t gfp_mask, enum compact_priority prio,
 		unsigned int alloc_flags, int highest_zoneidx,
-		struct page **capture)
+		struct capture_control *capc)
 {
 	enum compact_result ret;
 	struct compact_control cc = {
@@ -2787,35 +2808,22 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
 		.ignore_skip_hint = (prio == MIN_COMPACT_PRIORITY),
 		.ignore_block_suitable = (prio == MIN_COMPACT_PRIORITY)
 	};
-	struct capture_control capc = {
-		.cc = &cc,
-		.page = NULL,
-	};
 
-	/*
-	 * Make sure the structs are really initialized before we expose the
-	 * capture control, in case we are interrupted and the interrupt handler
-	 * frees a page.
-	 */
+	/* See the comment in __alloc_pages_direct_compact() */
 	barrier();
-	WRITE_ONCE(current->capture_control, &capc);
+	WRITE_ONCE(capc->cc, &cc);
 
-	ret = compact_zone(&cc, &capc);
+	ret = compact_zone(&cc, capc);
+
+	WRITE_ONCE(capc->cc, NULL);
 
-	/*
-	 * Make sure we hide capture control first before we read the captured
-	 * page pointer, otherwise an interrupt could free and capture a page
-	 * and we would leak it.
-	 */
-	WRITE_ONCE(current->capture_control, NULL);
-	*capture = READ_ONCE(capc.page);
 	/*
 	 * Technically, it is also possible that compaction is skipped but
 	 * the page is still captured out of luck(IRQ came and freed the page).
 	 * Returning COMPACT_SUCCESS in such cases helps in properly accounting
 	 * the COMPACT[STALL|FAIL] when compaction is skipped.
 	 */
-	if (*capture)
+	if (capc->page)
 		ret = COMPACT_SUCCESS;
 
 	return ret;
@@ -2828,13 +2836,13 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
  * @alloc_flags: The allocation flags of the current allocation
  * @ac: The context of current allocation
  * @prio: Determines how hard direct compaction should try to succeed
- * @capture: Pointer to free page created by compaction will be stored here
+ * @capc: The context for capturing pages during freeing
  *
  * This is the main entry point for direct page compaction.
  */
 enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
 		unsigned int alloc_flags, const struct alloc_context *ac,
-		enum compact_priority prio, struct page **capture)
+		enum compact_priority prio, struct capture_control *capc)
 {
 	struct zoneref *z;
 	struct zone *zone;
@@ -2862,7 +2870,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
 		}
 
 		status = compact_zone_order(zone, order, gfp_mask, prio,
-				alloc_flags, ac->highest_zoneidx, capture);
+				alloc_flags, ac->highest_zoneidx, capc);
 		rc = max(status, rc);
 
 		/* The allocation should succeed, stop compacting */
diff --git a/mm/internal.h b/mm/internal.h
index 181e79f1d6a207..1f636cfc859a1a 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1060,6 +1060,13 @@ struct compact_control {
  */
 struct capture_control {
 	struct compact_control *cc;
+	/*
+	 * Allocation request order. May differ from the compaction
+	 * order: defrag_mode promotes sub-block allocations to
+	 * pageblock-order compaction; capture still matches at the
+	 * original allocation order so prep_new_page() is consistent.
+	 */
+	int order;
 	struct page *page;
 };
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ee902a468c2f5b..575a99a4c72384 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -718,7 +718,7 @@ static inline struct capture_control *task_capc(struct zone *zone)
 {
 	struct capture_control *capc = current->capture_control;
 
-	return unlikely(capc) &&
+	return unlikely(capc && capc->cc) &&
 		!(current->flags & PF_KTHREAD) &&
 		!capc->page &&
 		capc->cc->zone == zone ? capc : NULL;
@@ -728,7 +728,7 @@ static inline bool
 compaction_capture(struct capture_control *capc, struct page *page,
 		   int order, int migratetype)
 {
-	if (!capc || order != capc->cc->order)
+	if (!capc || order != capc->order)
 		return false;
 
 	/* Do not accidentally pollute CMA or isolated regions*/
@@ -748,7 +748,7 @@ compaction_capture(struct capture_control *capc, struct page *page,
 		return false;
 
 	if (migratetype != capc->cc->migratetype)
-		trace_mm_page_alloc_extfrag(page, capc->cc->order, order,
+		trace_mm_page_alloc_extfrag(page, capc->order, order,
 					    capc->cc->migratetype, migratetype);
 
 	capc->page = page;
@@ -4146,21 +4146,59 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
 	struct page *page = NULL;
 	unsigned long pflags;
 	unsigned int noreclaim_flag;
+	struct capture_control capc = {
+		.order = order,
+		.page = NULL,
+	};
+	int compact_order = order;
 
-	if (!order)
+	/*
+	 * If fallbacks are not permitted (defrag_mode), we either
+	 * need to reclaim space in a block of matching type, or clear
+	 * out an entire block to allow __rmqueue_claim() to convert.
+	 *
+	 * Reclaim by itself is primarily freeing space in movable
+	 * blocks, since that's where the LRU pages live. So this
+	 * works for movable requests, but not for others.
+	 *
+	 * For those, promote the order to help make blocks, instead
+	 * of spinning in reclaim alone unproductively.
+	 */
+	if ((alloc_flags & ALLOC_NOFRAGMENT) && ac->migratetype != MIGRATE_MOVABLE)
+		compact_order = max(order, pageblock_order);
+
+	if (!compact_order)
 		return NULL;
 
+	/*
+	 * Make sure the structs are really initialized before we expose the
+	 * capture control, in case we are interrupted and the interrupt handler
+	 * frees a page.
+	 */
+	barrier();
+	WRITE_ONCE(current->capture_control, &capc);
+
 	psi_memstall_enter(&pflags);
 	delayacct_compact_start();
+	fs_reclaim_acquire(gfp_mask);
 	noreclaim_flag = memalloc_noreclaim_save();
 
-	*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
-								prio, &page);
+	*compact_result = try_to_compact_pages(gfp_mask, compact_order,
+					       alloc_flags, ac, prio, &capc);
 
 	memalloc_noreclaim_restore(noreclaim_flag);
+	fs_reclaim_release(gfp_mask);
 	psi_memstall_leave(&pflags);
 	delayacct_compact_end();
 
+	/*
+	 * Make sure we hide capture control first before we read the captured
+	 * page pointer, otherwise an interrupt could free and capture a page
+	 * and we would leak it.
+	 */
+	WRITE_ONCE(current->capture_control, NULL);
+	page = READ_ONCE(capc.page);
+
 	if (*compact_result == COMPACT_SKIPPED ||
 	    *compact_result == COMPACT_DEFERRED)
 		return NULL;
@@ -4182,7 +4220,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
 		struct zone *zone = page_zone(page);
 
 		zone->compact_blockskip_flush = false;
-		compaction_defer_reset(zone, order, true);
+		compaction_defer_reset(zone, compact_order, true);
 		count_vm_event(COMPACTSUCCESS);
 		return page;
 	}
@@ -4422,9 +4460,14 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
 	struct page *page = NULL;
 	unsigned long pflags;
 	bool drained = false;
+	int reclaim_order = order;
+
+	/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */
+	if ((alloc_flags & ALLOC_NOFRAGMENT) && ac->migratetype != MIGRATE_MOVABLE)
+		reclaim_order = max(order, pageblock_order);
 
 	psi_memstall_enter(&pflags);
-	*did_some_progress = __perform_reclaim(gfp_mask, order, ac);
+	*did_some_progress = __perform_reclaim(gfp_mask, reclaim_order, ac);
 	if (unlikely(!(*did_some_progress)))
 		goto out;
 

3/2 2026/06/26 20:21 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 5314
							output: 21
							thoughts: 364
						

Thoughts:
**Analyzing the Memory Compaction Patch**

Okay, so I've got this patch here that’s tinkering with memory compaction and allocation, specifically with how we handle compaction orders and page capture in `try_to_compact_pages` and `__alloc_pages_direct_compact`. It seems like the core logic is being tweaked. This is definitely worth a closer look, given that this touches upon `pageblock_order` when `ALLOC_NOFRAGMENT` is set and the migration type isn’t `MIGRATE_MOVABLE`. The patch also seems to be affecting `suitable_migration_source` and `fast_find_migrateblock`, which are crucial within the compaction framework.

Given that this is core memory management code, it's definitely high-value for fuzzing. We need to identify the key functions to focus our efforts.

Based on the code changes, it looks like we're zeroing in on: `suitable_migration_source`, `fast_find_migrateblock`, `compact_zone_order`, `try_to_compact_pages`, `compaction_capture`, `__alloc_pages_direct_compact`, and `__alloc_pages_direct_reclaim`.

`__alloc_pages_direct_compact` and `__alloc_pages_direct_reclaim` are part of the page allocator slow path, as expected. `try_to_compact_pages` is the direct compaction entry point, which makes it a critical area. `compact_zone_order` is a static function, and so are `suitable_migration_source` and `fast_find_migrateblock`.

I should check if there are any specific kernel configurations relevant to compaction, like `CONFIG_COMPACTION`. Let's grep for that and also for `try_to_compact_pages` to get a broader view of how these changes are tied into the rest of the system. This will give me a better understanding of how the code might behave in different scenarios.



4/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "try_to_compact_pages"
}

Results:
{
  "Output": "include/linux/compaction.h=11=enum compact_priority {\n--\ninclude/linux/compaction.h-20-\ninclude/linux/compaction.h:21:/* Return values for compact_zone() and try_to_compact_pages() */\ninclude/linux/compaction.h-22-/* When adding new states, please adjust include/trace/events/compaction.h */\n--\ninclude/linux/compaction.h=92=extern int fragmentation_index(struct zone *zone, unsigned int order);\ninclude/linux/compaction.h:93:extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,\ninclude/linux/compaction.h-94-\t\tunsigned int order, unsigned int alloc_flags,\n--\ninclude/trace/events/compaction.h=131=TRACE_EVENT(mm_compaction_end,\n--\ninclude/trace/events/compaction.h-164-\ninclude/trace/events/compaction.h:165:TRACE_EVENT(mm_compaction_try_to_compact_pages,\ninclude/trace/events/compaction.h-166-\n--\nmm/compaction.c=2791=static enum compact_result compact_zone_order(struct zone *zone, int order,\n--\nmm/compaction.c-2832-/**\nmm/compaction.c:2833: * try_to_compact_pages - Direct compact to satisfy a high-order allocation\nmm/compaction.c-2834- * @gfp_mask: The GFP mask of the current allocation\n--\nmm/compaction.c-2842- */\nmm/compaction.c:2843:enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,\nmm/compaction.c-2844-\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n--\nmm/compaction.c-2853-\nmm/compaction.c:2854:\ttrace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio);\nmm/compaction.c-2855-\n--\nmm/page_alloc.c=4142=__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4185-\nmm/page_alloc.c:4186:\t*compact_result = try_to_compact_pages(gfp_mask, compact_order,\nmm/page_alloc.c-4187-\t\t\t\t\t       alloc_flags, ac, prio, \u0026capc);\n--\nmm/vmscan.c=5998=static bool in_reclaim_compaction(struct scan_control *sc)\n--\nmm/vmscan.c-6011- * true if more pages should be reclaimed such that when the page allocator\nmm/vmscan.c:6012: * calls try_to_compact_pages() that it will have enough free pages to succeed.\nmm/vmscan.c-6013- * It will give up earlier than that if there is difficulty reclaiming pages.\n"
}

5/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 6910
							output: 26
							thoughts: 37
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Analyzing Compaction and Allocation Code Dependencies**

Alright, I need to understand the interaction between compaction and allocation. Based on the file paths, I'm diving into `mm/compaction.c` and `mm/page_alloc.c`. My immediate thought is, before I get too deep into the weeds, I should quickly verify if compaction is conditionally compiled. I'll need to confirm if `CONFIG_COMPACTION` is enabled or required to understand the code path properly, particularly how it affects the memory management scheme. I'll search for the preprocessor directives related to that config option to get a handle on the build configuration. That will provide crucial context before going any further with the analysis of those files.



6/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "CONFIG_COMPACTION",
  "PathPrefix": "mm/"
}

Results:
{
  "Output": "mm/compaction.c-28-\nmm/compaction.c:29:#ifdef CONFIG_COMPACTION\nmm/compaction.c-30-/*\n--\nmm/compaction.c=59=static inline bool is_via_compact_memory(int order) { return false; }\n--\nmm/compaction.c-61-\nmm/compaction.c:62:#if defined CONFIG_COMPACTION || defined CONFIG_CMA\nmm/compaction.c-63-\n--\nmm/compaction.c=91=static unsigned long release_free_list(struct list_head *freepages)\n--\nmm/compaction.c-115-\nmm/compaction.c:116:#ifdef CONFIG_COMPACTION\nmm/compaction.c-117-\n--\nmm/compaction.c=490=static bool test_and_set_skip(struct compact_control *cc, struct page *page)\n--\nmm/compaction.c-493-}\nmm/compaction.c:494:#endif /* CONFIG_COMPACTION */\nmm/compaction.c-495-\n--\nmm/compaction.c=1337=isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,\n--\nmm/compaction.c-1372-\nmm/compaction.c:1373:#endif /* CONFIG_COMPACTION || CONFIG_CMA */\nmm/compaction.c:1374:#ifdef CONFIG_COMPACTION\nmm/compaction.c-1375-\n--\nmm/compaction.c=3361=subsys_initcall(kcompactd_init)\nmm/compaction.c-3362-\nmm/compaction.c:3363:#endif /* CONFIG_COMPACTION */\n--\nmm/internal.h=999=static inline void sparse_init_subsection_map(unsigned long pfn,\n--\nmm/internal.h-1004-\nmm/internal.h:1005:#if defined CONFIG_COMPACTION || defined CONFIG_CMA\nmm/internal.h-1006-\n--\nmm/internal.h=1081=void init_cma_reserved_pageblock(struct page *page);\nmm/internal.h-1082-\nmm/internal.h:1083:#endif /* CONFIG_COMPACTION || CONFIG_CMA */\nmm/internal.h-1084-\n--\nmm/mm_init.c=1333=static void __init calculate_node_totalpages(struct pglist_data *pgdat,\n--\nmm/mm_init.c-1375-\nmm/mm_init.c:1376:#ifdef CONFIG_COMPACTION\nmm/mm_init.c-1377-static void pgdat_init_kcompactd(struct pglist_data *pgdat)\n--\nmm/oom_kill.c=456=static void dump_header(struct oom_control *oc)\n--\nmm/oom_kill.c-460-\t\t\tcurrent-\u003esignal-\u003eoom_score_adj);\nmm/oom_kill.c:461:\tif (!IS_ENABLED(CONFIG_COMPACTION) \u0026\u0026 oc-\u003eorder)\nmm/oom_kill.c-462-\t\tpr_warn(\"COMPACTION is disabled!!!\\n\");\n--\nmm/page_alloc.c=710=static inline void set_buddy_order(struct page *page, unsigned int order)\n--\nmm/page_alloc.c-715-\nmm/page_alloc.c:716:#ifdef CONFIG_COMPACTION\nmm/page_alloc.c-717-static inline struct capture_control *task_capc(struct zone *zone)\n--\nmm/page_alloc.c=765=compaction_capture(struct capture_control *capc, struct page *page,\n--\nmm/page_alloc.c-769-}\nmm/page_alloc.c:770:#endif /* CONFIG_COMPACTION */\nmm/page_alloc.c-771-\n--\nmm/page_alloc.c=4047=__alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4138-\nmm/page_alloc.c:4139:#ifdef CONFIG_COMPACTION\nmm/page_alloc.c-4140-/* Try memory compaction for high-order allocations before reclaim */\n--\nmm/page_alloc.c=4317=should_compact_retry(gfp_t gfp_mask, struct alloc_context *ac, int order,\n--\nmm/page_alloc.c-4342-}\nmm/page_alloc.c:4343:#endif /* CONFIG_COMPACTION */\nmm/page_alloc.c-4344-\n--\nmm/vmscan.c=6331=static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)\n--\nmm/vmscan.c-6371-\t\t\t */\nmm/vmscan.c:6372:\t\t\tif (IS_ENABLED(CONFIG_COMPACTION) \u0026\u0026\nmm/vmscan.c-6373-\t\t\t    sc-\u003eorder \u003e PAGE_ALLOC_COSTLY_ORDER \u0026\u0026\n--\nmm/vmstat.c=1042=void memmap_pages_add(long delta)\n--\nmm/vmstat.c-1046-\nmm/vmstat.c:1047:#ifdef CONFIG_COMPACTION\nmm/vmstat.c-1048-\n--\nmm/vmstat.c=1187=const char * const vmstat_text[] = {\n--\nmm/vmstat.c-1370-#endif\nmm/vmstat.c:1371:#ifdef CONFIG_COMPACTION\nmm/vmstat.c-1372-\t[I(COMPACTMIGRATE_SCANNED)]\t\t= \"compact_migrate_scanned\",\n--\nmm/vmstat.c-1496-\nmm/vmstat.c:1497:#if (defined(CONFIG_DEBUG_FS) \u0026\u0026 defined(CONFIG_COMPACTION)) || \\\nmm/vmstat.c-1498-     defined(CONFIG_PROC_FS)\n--\nmm/vmstat.c=2268=void __init init_mm_internals(void)\n--\nmm/vmstat.c-2301-\nmm/vmstat.c:2302:#if defined(CONFIG_DEBUG_FS) \u0026\u0026 defined(CONFIG_COMPACTION)\nmm/vmstat.c-2303-\n--\nmm/zsmalloc.c=199=struct zs_pool {\n--\nmm/zsmalloc.c-213-#endif\nmm/zsmalloc.c:214:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-215-\tstruct work_struct free_work;\n--\nmm/zsmalloc.c=360=static bool ZsHugePage(struct zspage *zspage)\n--\nmm/zsmalloc.c-364-\nmm/zsmalloc.c:365:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-366-static void kick_deferred_free(struct zs_pool *pool);\n--\nmm/zsmalloc.c=931=static struct zspage *alloc_zspage(struct zs_pool *pool,\n--\nmm/zsmalloc.c-941-\nmm/zsmalloc.c:942:\tif (!IS_ENABLED(CONFIG_COMPACTION))\nmm/zsmalloc.c-943-\t\tgfp \u0026= ~__GFP_MOVABLE;\n--\nmm/zsmalloc.c=1594=static int putback_zspage(struct size_class *class, struct zspage *zspage)\n--\nmm/zsmalloc.c-1603-\nmm/zsmalloc.c:1604:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-1605-/*\n--\nmm/zsmalloc.c=1609=static void lock_zspage(struct zspage *zspage)\n--\nmm/zsmalloc.c-1645-}\nmm/zsmalloc.c:1646:#endif /* CONFIG_COMPACTION */\nmm/zsmalloc.c-1647-\nmm/zsmalloc.c:1648:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-1649-\n--\nmm/zsmalloc.c=2237=static int __init zs_init(void)\n--\nmm/zsmalloc.c-2244-\nmm/zsmalloc.c:2245:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-2246-\trc = set_movable_ops(\u0026zsmalloc_mops, PGTY_zsmalloc);\n--\nmm/zsmalloc.c=2256=static void __exit zs_exit(void)\nmm/zsmalloc.c-2257-{\nmm/zsmalloc.c:2258:#ifdef CONFIG_COMPACTION\nmm/zsmalloc.c-2259-\tset_movable_ops(NULL, PGTY_zsmalloc);\n"
}

7/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 9426
							output: 36
							thoughts: 203
						

Thoughts:
**Analyzing the Kernel's Memory Compaction Implementation**

Okay, so the primary configuration option driving this seems to be `CONFIG_COMPACTION`. I need to understand how these changes impact the system. It looks like `__alloc_pages_direct_compact` is conditionally compiled based on `CONFIG_COMPACTION`, which is a key piece of information. I should look for any other related configuration options, just in case.

Alright, let's break down the code modifications. The patch targets `mm/compaction.c` and `mm/page_alloc.c`, so those are the areas of interest. In `mm/compaction.c`, I see functions like `suitable_migration_source`, `fast_find_migrateblock`, `compact_zone_order`, and `try_to_compact_pages`. That's the expected core compaction logic.

Now, in `mm/page_alloc.c`, I'm seeing `compaction_capture`, `__alloc_pages_direct_compact`, and `__alloc_pages_direct_reclaim`. Hmm, wait a second... `__alloc_pages_direct_reclaim` isn't guarded by an `#ifdef CONFIG_COMPACTION` preprocessor directive, which is interesting. I'll need to check the code around line 4460 in `mm/page_alloc.c` to understand the exact context there. This implies that even without active compaction, some direct reclaim functionality might still be interacting with the related code.



8/2 2026/06/26 20:22 tool read-file
0m Args:
{
  "File": "mm/page_alloc.c",
  "FirstLine": 4450,
  "LineCount": 50
}

Results:
{
  "Contents": "4450:\t\n4451:\t\treturn progress;\n4452:\t}\n4453:\t\n4454:\t/* The really slow allocator path where we enter direct reclaim */\n4455:\tstatic inline struct page *\n4456:\t__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,\n4457:\t\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n4458:\t\t\tunsigned long *did_some_progress)\n4459:\t{\n4460:\t\tstruct page *page = NULL;\n4461:\t\tunsigned long pflags;\n4462:\t\tbool drained = false;\n4463:\t\tint reclaim_order = order;\n4464:\t\n4465:\t\t/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */\n4466:\t\tif ((alloc_flags \u0026 ALLOC_NOFRAGMENT) \u0026\u0026 ac-\u003emigratetype != MIGRATE_MOVABLE)\n4467:\t\t\treclaim_order = max(order, pageblock_order);\n4468:\t\n4469:\t\tpsi_memstall_enter(\u0026pflags);\n4470:\t\t*did_some_progress = __perform_reclaim(gfp_mask, reclaim_order, ac);\n4471:\t\tif (unlikely(!(*did_some_progress)))\n4472:\t\t\tgoto out;\n4473:\t\n4474:\tretry:\n4475:\t\tpage = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);\n4476:\t\n4477:\t\t/*\n4478:\t\t * If an allocation failed after direct reclaim, it could be because\n4479:\t\t * pages are pinned on the per-cpu lists or in high alloc reserves.\n4480:\t\t * Shrink them and try again\n4481:\t\t */\n4482:\t\tif (!page \u0026\u0026 !drained) {\n4483:\t\t\tunreserve_highatomic_pageblock(ac, false);\n4484:\t\t\tdrain_all_pages(NULL);\n4485:\t\t\tdrained = true;\n4486:\t\t\tgoto retry;\n4487:\t\t}\n4488:\tout:\n4489:\t\tpsi_memstall_leave(\u0026pflags);\n4490:\t\n4491:\t\treturn page;\n4492:\t}\n4493:\t\n4494:\tstatic void wake_all_kswapds(unsigned int order, gfp_t gfp_mask,\n4495:\t\t\t\t     const struct alloc_context *ac)\n4496:\t{\n4497:\t\tstruct zoneref *z;\n4498:\t\tstruct zone *zone;\n4499:\t\tpg_data_t *last_pgdat = NULL;\n"
}

9/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10720
							output: 36
							thoughts: 59
						

Thoughts:
Here's my take on the thought process:

**Diving into the Memory Allocation Code**

Alright, so `__alloc_pages_direct_reclaim` is definitely in the build, no conditional compilation there. That's good to know. Now, `__alloc_pages_direct_compact`... ah, that's tucked behind a `#ifdef CONFIG_COMPACTION`. Makes sense. So, its presence in the kernel image depends on that configuration option being enabled. Time to dig in a bit further. Let me jump over to `mm/page_alloc.c` and take a look around line 4146. That's a reasonable place to start, given the function names. Hopefully, I can see how these two functions are called and how they interact. Let's see what we find there.



10/2 2026/06/26 20:22 tool read-file
0m Args:
{
  "File": "mm/page_alloc.c",
  "FirstLine": 4130,
  "LineCount": 50
}

Results:
{
  "Contents": "4130:\t\treturn page;\n4131:\t}\n4132:\t\n4133:\t/*\n4134:\t * Maximum number of compaction retries with a progress before OOM\n4135:\t * killer is consider as the only way to move forward.\n4136:\t */\n4137:\t#define MAX_COMPACT_RETRIES 16\n4138:\t\n4139:\t#ifdef CONFIG_COMPACTION\n4140:\t/* Try memory compaction for high-order allocations before reclaim */\n4141:\tstatic struct page *\n4142:\t__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\n4143:\t\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n4144:\t\t\tenum compact_priority prio, enum compact_result *compact_result)\n4145:\t{\n4146:\t\tstruct page *page = NULL;\n4147:\t\tunsigned long pflags;\n4148:\t\tunsigned int noreclaim_flag;\n4149:\t\tstruct capture_control capc = {\n4150:\t\t\t.order = order,\n4151:\t\t\t.page = NULL,\n4152:\t\t};\n4153:\t\tint compact_order = order;\n4154:\t\n4155:\t\t/*\n4156:\t\t * If fallbacks are not permitted (defrag_mode), we either\n4157:\t\t * need to reclaim space in a block of matching type, or clear\n4158:\t\t * out an entire block to allow __rmqueue_claim() to convert.\n4159:\t\t *\n4160:\t\t * Reclaim by itself is primarily freeing space in movable\n4161:\t\t * blocks, since that's where the LRU pages live. So this\n4162:\t\t * works for movable requests, but not for others.\n4163:\t\t *\n4164:\t\t * For those, promote the order to help make blocks, instead\n4165:\t\t * of spinning in reclaim alone unproductively.\n4166:\t\t */\n4167:\t\tif ((alloc_flags \u0026 ALLOC_NOFRAGMENT) \u0026\u0026 ac-\u003emigratetype != MIGRATE_MOVABLE)\n4168:\t\t\tcompact_order = max(order, pageblock_order);\n4169:\t\n4170:\t\tif (!compact_order)\n4171:\t\t\treturn NULL;\n4172:\t\n4173:\t\t/*\n4174:\t\t * Make sure the structs are really initialized before we expose the\n4175:\t\t * capture control, in case we are interrupted and the interrupt handler\n4176:\t\t * frees a page.\n4177:\t\t */\n4178:\t\tbarrier();\n4179:\t\tWRITE_ONCE(current-\u003ecapture_control, \u0026capc);\n"
}

11/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11721
							output: 35
							thoughts: 44
						

Thoughts:
**Compaction Configuration Review**

Okay, so most of these changes I'm looking at hinge on `CONFIG_COMPACTION`. That's pretty standard, but I need to make sure I haven't missed anything crucial. Let's not assume anything. I need to get into a methodical approach for this.

I'm thinking, are there any *other* config options I need to double-check related to these compaction modifications? Let's take a look at `suitable_migration_source` within `mm/compaction.c`. That function will give me a good, low-level insight into the compaction behavior. Time to delve into the code and rule out any dependencies or edge cases.



12/2 2026/06/26 20:22 tool read-file
0m Args:
{
  "File": "mm/compaction.c",
  "FirstLine": 1370,
  "LineCount": 50
}

Results:
{
  "Contents": "1370:\t\treturn ret;\n1371:\t}\n1372:\t\n1373:\t#endif /* CONFIG_COMPACTION || CONFIG_CMA */\n1374:\t#ifdef CONFIG_COMPACTION\n1375:\t\n1376:\tstatic bool suitable_migration_source(struct compact_control *cc,\n1377:\t\t\t\t\t\t\t\tstruct page *page)\n1378:\t{\n1379:\t\tint block_mt;\n1380:\t\n1381:\t\tif (pageblock_skip_persistent(page))\n1382:\t\t\treturn false;\n1383:\t\n1384:\t\t/*\n1385:\t\t * Background compaction produces blocks for the zone at\n1386:\t\t * large, with no particular allocation context. Allow all\n1387:\t\t * block types, including CMA.\n1388:\t\t */\n1389:\t\tif (!cc-\u003edirect_compaction)\n1390:\t\t\treturn true;\n1391:\t\n1392:\t\tblock_mt = get_pageblock_migratetype(page);\n1393:\t\n1394:\t\t/*\n1395:\t\t * CMA pages can only be taken by ALLOC_CMA requests. For anybody\n1396:\t\t * else, vacating a CMA block consumes free pages the caller\n1397:\t\t * could have used, and produces free pages it cannot.\n1398:\t\t */\n1399:\t\tif (is_migrate_cma(block_mt) \u0026\u0026 !(cc-\u003ealloc_flags \u0026 ALLOC_CMA))\n1400:\t\t\treturn false;\n1401:\t\n1402:\t\tif (cc-\u003emode != MIGRATE_ASYNC)\n1403:\t\t\treturn true;\n1404:\t\n1405:\t\t/*\n1406:\t\t * Prevent small unmovable/reclaimable requests from polluting\n1407:\t\t * movable blocks through fallbacks. Whole-block production is\n1408:\t\t * exempt as the allocator claims and converts these.\n1409:\t\t */\n1410:\t\tif (cc-\u003emigratetype == MIGRATE_MOVABLE || cc-\u003eorder \u003e= pageblock_order)\n1411:\t\t\treturn is_migrate_movable(block_mt);\n1412:\t\telse\n1413:\t\t\treturn block_mt == cc-\u003emigratetype;\n1414:\t}\n1415:\t\n1416:\t/* Returns true if the page is within a block suitable for migration to */\n1417:\tstatic bool suitable_migration_target(struct compact_control *cc,\n1418:\t\t\t\t\t\t\t\tstruct page *page)\n1419:\t{\n"
}

13/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12639
							output: 20
							thoughts: 62
						

Thoughts:
Okay, here's my interpretation of these changes, phrased as a personal thought process:

**Diving into the Migration Source Logic**

Alright, so I'm looking at these changes in `suitable_migration_source` and it's clear the focus is around how we're handling CMA (Contiguous Memory Allocator) memory for migration. Specifically, it seems like we're relying on the functions `is_migrate_cma(block_mt)` and the macro `ALLOC_CMA`. My initial question is, do these changes imply a *requirement* for `CONFIG_CMA` to be enabled? It seems likely, given the direct use of these CMA-related constructs. I need to trace this back.

Ah, `is_migrate_cma` is defined in `include/linux/mmzone.h`, which is the correct place for memory zone information and definitions. That's good, it's where I'd expect it to be. This suggests the logic is checking if the current memory block (`block_mt`) is allocated from a CMA zone. I need to see how the interactions with `ALLOC_CMA` affect the overall migration path.



14/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "is_migrate_cma"
}

Results:
{
  "Output": "include/linux/mmzone.h=147=extern const char * const migratetype_names[MIGRATE_TYPES];\n--\ninclude/linux/mmzone.h-149-#ifdef CONFIG_CMA\ninclude/linux/mmzone.h:150:#  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)\ninclude/linux/mmzone.h:151:#  define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)\ninclude/linux/mmzone.h-152-/*\n--\ninclude/linux/mmzone.h-155- */\ninclude/linux/mmzone.h:156:#  define is_migrate_cma_folio(folio, pfn) \\\ninclude/linux/mmzone.h-157-\t(get_pfnblock_migratetype(\u0026folio-\u003epage, pfn) == MIGRATE_CMA)\ninclude/linux/mmzone.h-158-#else\ninclude/linux/mmzone.h:159:#  define is_migrate_cma(migratetype) false\ninclude/linux/mmzone.h:160:#  define is_migrate_cma_page(_page) false\ninclude/linux/mmzone.h:161:#  define is_migrate_cma_folio(folio, pfn) false\ninclude/linux/mmzone.h-162-#endif\n--\ninclude/linux/mmzone.h=164=static inline bool is_migrate_movable(int mt)\ninclude/linux/mmzone.h-165-{\ninclude/linux/mmzone.h:166:\treturn is_migrate_cma(mt) || mt == MIGRATE_MOVABLE;\ninclude/linux/mmzone.h-167-}\n--\nmm/compaction.c=1376=static bool suitable_migration_source(struct compact_control *cc,\n--\nmm/compaction.c-1398-\t */\nmm/compaction.c:1399:\tif (is_migrate_cma(block_mt) \u0026\u0026 !(cc-\u003ealloc_flags \u0026 ALLOC_CMA))\nmm/compaction.c-1400-\t\treturn false;\n--\nmm/debug.c=70=static void __dump_folio(const struct folio *folio, const struct page *page,\n--\nmm/debug.c-115-\tpr_warn(\"%sflags: %pGp%s\\n\", type, \u0026folio-\u003eflags,\nmm/debug.c:116:\t\tis_migrate_cma_folio(folio, pfn) ? \" CMA\" : \"\");\nmm/debug.c-117-\tif (page_has_type(\u0026folio-\u003epage))\n--\nmm/page_alloc.c=728=compaction_capture(struct capture_control *capc, struct page *page,\n--\nmm/page_alloc.c-734-\t/* Do not accidentally pollute CMA or isolated regions*/\nmm/page_alloc.c:735:\tif (is_migrate_cma(migratetype) ||\nmm/page_alloc.c-736-\t    is_migrate_isolate(migratetype))\n--\nmm/page_alloc.c=772=static inline void account_freepages(struct zone *zone, int nr_pages,\n--\nmm/page_alloc.c-781-\nmm/page_alloc.c:782:\tif (is_migrate_cma(migratetype))\nmm/page_alloc.c-783-\t\t__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, nr_pages);\n--\nmm/page_isolation.c=134=static struct page *has_unmovable_pages(unsigned long start_pfn, unsigned long end_pfn,\n--\nmm/page_isolation.c-142-\nmm/page_isolation.c:143:\tif (is_migrate_cma_page(page)) {\nmm/page_isolation.c-144-\t\t/*\n--\nmm/page_owner.c=425=void pagetypeinfo_showmixedcount_print(struct seq_file *m,\n--\nmm/page_owner.c-485-\t\t\tif (pageblock_mt != page_mt) {\nmm/page_owner.c:486:\t\t\t\tif (is_migrate_cma(pageblock_mt))\nmm/page_owner.c-487-\t\t\t\t\tcount[MIGRATE_MOVABLE]++;\n"
}

15/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14098
							output: 33
							thoughts: 693
						

Thoughts:
**Analyzing the Memory Compaction Logic**

Okay, so I'm diving into this code related to memory compaction. It seems the main focus of this particular set of changes revolves around optimizing how the system handles memory fragmentation, primarily when dealing with allocations that require contiguous physical memory. The `is_migrate_cma` flag is tied to `CONFIG_CMA`, which suggests there's some interaction with Contiguous Memory Allocation, but that's not the central piece, at least not initially. The crucial aspect appears to be `CONFIG_COMPACTION`.

Specifically, I'm keying in on `suitable_migration_source` because it has the interesting conditional logic regarding CMA pages. It states that CMA pages can only be allocated if `ALLOC_CMA` is set. This affects the migration process, but more broadly, the core change is within `__alloc_pages_direct_compact`. Looking at the code for that function, it looks like it promotes the compaction order when `ALLOC_NOFRAGMENT` is set and the migration type isn't movable. This seems to be where the real change lies: boosting the order of the compaction to more aggressively create larger contiguous blocks.

I need to nail down exactly where to focus. Let's make sure I'm zeroing in on the right functions: `__alloc_pages_direct_compact`, `__alloc_pages_direct_reclaim`, `try_to_compact_pages`, `compact_zone_order`, `suitable_migration_source`, `fast_find_migrateblock`, and `compaction_capture`.

After a quick mental review, `__alloc_pages_direct_compact` and `__alloc_pages_direct_reclaim` are part of the page allocator's slow path, so they're important. `try_to_compact_pages` seems to be a good entry point to the compaction logic. The others are static or static inline, meaning they may be more contained.

Wait a second. It looks like `__alloc_pages_direct_compact` is static. This means it is only accessible from within `mm/page_alloc.c`. This could be a problem in terms of debugging and tracing because I can't directly target it. `try_to_compact_pages` on the other hand, is exported. Okay, let's head over to `mm/compaction.c` to understand `try_to_compact_pages` more.



16/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "try_to_compact_pages",
  "PathPrefix": "mm/compaction.c"
}

Results:
{
  "Output": "mm/compaction.c=2791=static enum compact_result compact_zone_order(struct zone *zone, int order,\n--\nmm/compaction.c-2832-/**\nmm/compaction.c:2833: * try_to_compact_pages - Direct compact to satisfy a high-order allocation\nmm/compaction.c-2834- * @gfp_mask: The GFP mask of the current allocation\n--\nmm/compaction.c-2842- */\nmm/compaction.c:2843:enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,\nmm/compaction.c-2844-\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n--\nmm/compaction.c-2853-\nmm/compaction.c:2854:\ttrace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio);\nmm/compaction.c-2855-\n"
}

17/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15608
							output: 36
							thoughts: 195
						

Thoughts:
**Analyzing Syzkaller's Potential for Targeting Memory Compaction Functions**

Okay, so I'm looking at these memory compaction functions and how they relate to fuzzing with Syzkaller. It looks like `try_to_compact_pages` is *not* a static function, while `compact_zone_order`, `suitable_migration_source`, `fast_find_migrateblock`, `__alloc_pages_direct_compact`, and `__alloc_pages_direct_reclaim` *are* static. The question that immediately comes to mind, as an expert in this area, is whether Syzkaller can effectively target these static functions.

Syzkaller, in general, works by fuzzing syscalls, so the scope is the entire kernel. The key here is the `FocusSymbols` list; it guides the fuzzer to prioritize inputs that hit specific functions. That seems like a good approach. The good news is that Syzkaller uses instruction addresses for coverage, so as long as the static functions aren't completely inlined, we should be able to map them and use them.

Now, a crucial detail to verify. I'm pretty sure `__alloc_pages_direct_compact` is *not* inlined. However, I need to double-check on `__alloc_pages_direct_reclaim`. It's flagged as `static inline` in the patch. I need to be sure; let's check the source for confirmation. This will make or break the effectiveness of the targeted fuzzing campaign.



18/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "__alloc_pages_direct_reclaim",
  "PathPrefix": "mm/page_alloc.c"
}

Results:
{
  "Output": "mm/page_alloc.c=4455=static inline struct page *\nmm/page_alloc.c:4456:__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,\nmm/page_alloc.c-4457-\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n--\nmm/page_alloc.c=4768=__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4918-\tif (!compact_first) {\nmm/page_alloc.c:4919:\t\tpage = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags,\nmm/page_alloc.c-4920-\t\t\t\t\t\t\tac, \u0026did_some_progress);\n"
}

19/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16384
							output: 35
							thoughts: 59
						

Thoughts:
Here's my understanding of the situation, given my expertise:

**Examining Memory Allocation Internals**

Okay, so I'm looking at these low-level memory allocation functions. `__alloc_pages_direct_reclaim` is declared as `static inline`. This is significant because it strongly suggests that the compiler will likely try to *inline* this function directly into the `__alloc_pages_slowpath` function. That means the code from `__alloc_pages_direct_reclaim` will be merged directly into `__alloc_pages_slowpath` to potentially increase performance by eliminating a function call overhead. It is a common compiler optimization technique used to reduce overhead.

Now, `compaction_capture` is also `static inline`. This suggests the same inlining behavior as before. This is another area to watch out for optimizations, as the `static inline` declaration is a clue to its intended usage.

Finally, `__alloc_pages_direct_compact` is declared as `static`.  This is important. A `static` function has internal linkage only and is not visible outside the current compilation unit. It won't be inlined and is only used within the source file it's defined in. This probably means it performs a specific compaction routine within this specific allocation path, and there's no need for it to be accessible elsewhere in the kernel. This also lets the compiler perform more aggressive optimizations.



20/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "__alloc_pages_direct_compact",
  "PathPrefix": "mm/page_alloc.c"
}

Results:
{
  "Output": "mm/page_alloc.c=4141=static struct page *\nmm/page_alloc.c:4142:__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\nmm/page_alloc.c-4143-\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n--\nmm/page_alloc.c=4307=static inline struct page *\nmm/page_alloc.c:4308:__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,\nmm/page_alloc.c-4309-\t\tunsigned int alloc_flags, const struct alloc_context *ac,\n--\nmm/page_alloc.c=4456=__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4464-\nmm/page_alloc.c:4465:\t/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */\nmm/page_alloc.c-4466-\tif ((alloc_flags \u0026 ALLOC_NOFRAGMENT) \u0026\u0026 ac-\u003emigratetype != MIGRATE_MOVABLE)\n--\nmm/page_alloc.c=4768=__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4925-\t/* Try direct compaction and then allocating */\nmm/page_alloc.c:4926:\tpage = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,\nmm/page_alloc.c-4927-\t\t\t\t\tcompact_priority, \u0026compact_result);\n"
}

21/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17210
							output: 32
							thoughts: 87
						

Thoughts:
Okay, let's break this down.

**My Analysis of the Direct Compaction Process**

Right, so `__alloc_pages_direct_compact` is declared `static`, which immediately narrows the scope of where I need to focus my attention. It means I need to ignore its direct calls outside of the file it's defined in. This suggests a localized optimization or a helper function that’s not intended to be exposed widely. Thus, the relevant calls to focus on are the functions it calls.

Therefore, the key functions to investigate further are: `__alloc_pages_direct_compact`, naturally, then `try_to_compact_pages`, which seems to be the logical entry point for the compaction attempt, followed by the zone-level compaction logic in `compact_zone_order`. I also want to dive into the source/destination page selection, and in particular to understand how the system determines a `suitable_migration_source` and finally I need to know the fast path for allocation that involves `fast_find_migrateblock`.

I think `fast_find_migrateblock` is the one to inspect first. I'll start with this one.



22/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "fast_find_migrateblock",
  "PathPrefix": "mm/compaction.c"
}

Results:
{
  "Output": "mm/compaction.c=1944=reinit_migrate_pfn(struct compact_control *cc)\n--\nmm/compaction.c-1959- */\nmm/compaction.c:1960:static unsigned long fast_find_migrateblock(struct compact_control *cc)\nmm/compaction.c-1961-{\n--\nmm/compaction.c=2082=static isolate_migrate_t isolate_migratepages(struct compact_control *cc)\n--\nmm/compaction.c-2097-\t */\nmm/compaction.c:2098:\tlow_pfn = fast_find_migrateblock(cc);\nmm/compaction.c-2099-\tblock_start_pfn = pageblock_start_pfn(low_pfn);\n--\nmm/compaction.c-2103-\t/*\nmm/compaction.c:2104:\t * fast_find_migrateblock() has already ensured the pageblock is not\nmm/compaction.c-2105-\t * set with a skipped flag, so to avoid the isolation_suitable check\n--\nmm/compaction.c=2553=compact_zone(struct compact_control *cc, struct capture_control *capc)\n--\nmm/compaction.c-2709-\t\t\t * within the pageblock_order-aligned block and\nmm/compaction.c:2710:\t\t\t * fast_find_migrateblock may be used then scan the\nmm/compaction.c-2711-\t\t\t * remainder of the pageblock. This will mark the\n--\nmm/compaction.c-2714-\t\t\t * for the request but avoid loops due to\nmm/compaction.c:2715:\t\t\t * fast_find_migrateblock revisiting blocks that were\nmm/compaction.c-2716-\t\t\t * recently partially scanned.\n"
}

23/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18043
							output: 32
							thoughts: 125
						

Thoughts:
**Analyzing Memory Compaction Symbol Usage**

Okay, so I'm digging into how memory compaction works, and the first thing I'm noting is that `fast_find_migrateblock` *is* indeed a static function. That helps. Given that, my working hypothesis for the key symbols used in the focus of the process should be:

*   `__alloc_pages_direct_compact`
*   `try_to_compact_pages`
*   `compact_zone_order`
*   `suitable_migration_source`
*   `fast_find_migrateblock`

But wait, I need to be careful here. Looking again, `__alloc_pages_direct_reclaim` is defined as `static inline`. Right, so it won't be a unique symbol in the final compiled code. Hmm, that changes things. However, `__perform_reclaim` *might* still be. I need to verify that. Let me quickly double-check the definition and usage of `__perform_reclaim` to be certain.



24/2 2026/06/26 20:22 tool grepper
0m Args:
{
  "Expression": "__perform_reclaim",
  "PathPrefix": "mm/page_alloc.c"
}

Results:
{
  "Output": "mm/page_alloc.c=4429=static unsigned long\nmm/page_alloc.c:4430:__perform_reclaim(gfp_t gfp_mask, unsigned int order,\nmm/page_alloc.c-4431-\t\t\t\t\tconst struct alloc_context *ac)\n--\nmm/page_alloc.c=4456=__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,\n--\nmm/page_alloc.c-4469-\tpsi_memstall_enter(\u0026pflags);\nmm/page_alloc.c:4470:\t*did_some_progress = __perform_reclaim(gfp_mask, reclaim_order, ac);\nmm/page_alloc.c-4471-\tif (unlikely(!(*did_some_progress)))\n"
}

25/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18643
							output: 33
							thoughts: 558
						

Thoughts:
**My Analysis of the Memory Compaction Patch**

Okay, so this patch is interesting. While `__perform_reclaim` itself isn't directly touched, the important change seems to be in `__alloc_pages_direct_reclaim`, which, due to being inlined, actually means the modification is happening within `__alloc_pages_slowpath`. I could try fuzzing that function since it contains the logic for memory allocation failures and it's affected, but that's a *very* hot path. Focusing on the compaction functions seems more targeted and potentially more fruitful.

The first thing I needed to confirm was the configuration requirements. It looks like `CONFIG_COMPACTION` is the only one. It's usually enabled, but it's always good to be explicit.

Let's break down the logic. The core of the patch revolves around modifications to how direct compaction and reclaim handle page capture and compaction orders, specifically promoting the compaction order to `pageblock_order`. This aims to reduce fragmentation during higher-order allocations and under memory pressure. That makes sense, this is right in the heart of the memory management logic.

Double-checking for any other relevant configurations, it looks like `ALLOC_NOFRAGMENT` is a flag, `MIGRATE_MOVABLE` is a migratetype, and `pageblock_order` is a macro/variable. And `try_to_compact_pages` is the main entry point to it all.

Given this is generic MM code, there aren't any architecture-specific configuration considerations. Therefore, `EnableConfigs` should indeed be `["COMPACTION"]`.

Now, for `FocusSymbols`, I've identified several key functions:

*   `__alloc_pages_direct_compact` - Since this function has "direct" in its name, it sounds good to start with.
*   `try_to_compact_pages` - This seems to be the main entry point.
*   `compact_zone_order` - Likely involved in determining the compaction order.
*   `suitable_migration_source` - Part of the page migration process.
*   `fast_find_migrateblock` - Potentially related to finding blocks for migration.

I need to confirm if these functions are inline. I've now verified that `__alloc_pages_direct_compact` (struct page\*), `compact_zone_order` (enum), `suitable_migration_source` (bool), and `fast_find_migrateblock` (unsigned long) are all static and not marked as inline, which is good for targeted fuzzing.

One final check, is `try_to_compact_pages` exported? I should verify that.



26/2 2026/06/26 20:22 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "EXPORT_SYMBOL.*try_to_compact_pages",
  "PathPrefix": "mm/"
}

Results:
{
  "error": "no matches"
}

27/2 2026/06/26 20:22 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19822
							output: 31
							thoughts: 75
						

Thoughts:
Okay, here's my understanding, playing the role of an expert:

**Analyzing the `compaction` Function in the Kernel Memory Management Code**

Alright, so the `compaction` function is in `mm/compaction.c`, but it's *not* exported as a module function. Fine, no big deal, it's global (but non-static), which is totally acceptable for how syzkaller operates. It's not a problem.

Now, I need to look at `compaction_capture`. It looks like it's a `static inline` function. The key here is the `inline`. So, my immediate thought is: this thing's been *inlined* wherever it's used. This means I need to trace the calling context by checking where it is called!



28/2 2026/06/26 20:23 tool grepper
0m Args:
{
  "Expression": "compaction_capture",
  "PathPrefix": "mm/page_alloc.c"
}

Results:
{
  "Output": "mm/page_alloc.c=727=static inline bool\nmm/page_alloc.c:728:compaction_capture(struct capture_control *capc, struct page *page,\nmm/page_alloc.c-729-\t\t   int order, int migratetype)\n--\nmm/page_alloc.c=764=static inline bool\nmm/page_alloc.c:765:compaction_capture(struct capture_control *capc, struct page *page,\nmm/page_alloc.c-766-\t\t   int order, int migratetype)\n--\nmm/page_alloc.c=936=static inline void __free_one_page(struct page *page,\n--\nmm/page_alloc.c-958-\nmm/page_alloc.c:959:\t\tif (compaction_capture(capc, page, order, migratetype)) {\nmm/page_alloc.c-960-\t\t\taccount_freepages(zone, -(1 \u003c\u003c order), migratetype);\n"
}

29/2 2026/06/26 20:23 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20363
							output: 150
							thoughts: 443
						

Thoughts:
**My Analysis of the Memory Compaction Patch**

Okay, so I've been digging into this patch. The key thing I'm seeing is that it's all about memory compaction and allocation, and how they interact. Specifically, it's making some changes to direct compaction and reclaim, focusing on how they handle page capture and compaction orders. The goal seems to be to improve memory management by promoting the compaction order to `pageblock_order` under certain allocation scenarios to reduce fragmentation.

The important thing is that `__free_one_page` is being called, which is a hot path, and we don't want to include this in `FocusSymbols`.

So, the critical functions to focus on are:

*   `__alloc_pages_direct_compact`
*   `try_to_compact_pages`
*   `compact_zone_order`
*   `suitable_migration_source`
*   `fast_find_migrateblock`

I went back and checked if any other functions were modified. I found `task_capc` but since that's inline it's not a major concern.

Thinking it through, the patch is touching core memory management – direct compaction, reclaim, allocation – and that's exactly the kind of thing we want to fuzz. The scenarios it targets are those that involve higher-order memory allocations and memory pressure. It seems functional and definitely worthy of fuzzing.

The relevant config is `COMPACTION`, and there's an optional dependence on `CONFIG_CMA` within `suitable_migration_source`, but `COMPACTION` is the primary one, so that's what I'll list.

I think I've got a solid grasp on this now. I'll move on to `set-results`.



30/2 2026/06/26 20:23 tool set-results
0m Args:
{
  "EnableConfigs": [
    "COMPACTION"
  ],
  "FocusSymbols": [
    "__alloc_pages_direct_compact",
    "try_to_compact_pages",
    "compact_zone_order",
    "suitable_migration_source",
    "fast_find_migrateblock"
  ],
  "Reasoning": "The patch modifies memory compaction and allocation logic, specifically how direct compaction and reclaim handle page capture and compaction orders. It promotes the compaction order to `pageblock_order` for certain allocations to prevent fragmentation. This is core memory management logic that is reachable during high-order memory allocations and memory pressure. It is functional and should be fuzzed.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "COMPACTION"
  ],
  "FocusSymbols": [
    "__alloc_pages_direct_compact",
    "try_to_compact_pages",
    "compact_zone_order",
    "suitable_migration_source",
    "fast_find_migrateblock"
  ],
  "Reasoning": "The patch modifies memory compaction and allocation logic, specifically how direct compaction and reclaim handle page capture and compaction orders. It promotes the compaction order to `pageblock_order` for certain allocations to prevent fragmentation. This is core memory management logic that is reachable during high-order memory allocations and memory pressure. It is functional and should be fuzzed.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)