* [RFC PATCH 1/3] mm/compaction: skip isolate mlocked folios when compact_unevictable_allowed=0
2026-06-04 2:38 [RFC PATCH 0/3] mm/compaction: honour compact_unevictable_allowed in mlock race and alloc_contig path Wandun Chen
@ 2026-06-04 2:38 ` Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 2/3] mm/compaction: add per-folio isolation tracepoint Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 3/3] mm/compaction: respect compact_unevictable_allowed in alloc_contig path Wandun Chen
2 siblings, 0 replies; 4+ messages in thread
From: Wandun Chen @ 2026-06-04 2:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-trace-kernel, linux-rt-devel
Cc: akpm, vbabka, surenb, mhocko, jackmanb, hannes, ziy, rostedt,
mhiramat, mathieu.desnoyers, david, ljs, liam, rppt, bigeasy,
clrkwllms, Alexander.Krabler
From: Wandun Chen <chenwandun@lixiang.com>
compact_unevictable_allowed is default 0 under PREEMPT_RT,
isolate_migratepages_block() skips folios with PG_unevictable set.
However, mlock_folio() sets PG_mlocked immediately but defers
PG_unevictable to mlock_folio_batch(), result in a folio with
PG_mlocked=1 but PG_unevictable=0. Compaction will isolate such a
folio.
Fix by checking folio_test_mlocked() together with the existing
folio_test_unevictable() check.
A similar issue has been reported by Alexander Krabler on a 6.12-rt
aarch64 system. Vlastimil suggested to check the mlocked flag [1].
Reported-by: Alexander Krabler <Alexander.Krabler@kuka.com>
Closes: https://lore.kernel.org/all/DU0PR01MB10385345F7153F334100981888259A@DU0PR01MB10385.eurprd01.prod.exchangelabs.com/
Suggested-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Wandun Chen <chenwandun@lixiang.com>
Link: https://lore.kernel.org/all/33275585-f2db-4779-89f0-3ae24b455a67@suse.cz/ [1]
---
mm/compaction.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index b776f35ad020..7e07b792bcb5 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1116,7 +1116,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
is_unevictable = folio_test_unevictable(folio);
/* Compaction might skip unevictable pages but CMA takes them */
- if (!(mode & ISOLATE_UNEVICTABLE) && is_unevictable)
+ if (!(mode & ISOLATE_UNEVICTABLE) &&
+ (is_unevictable || folio_test_mlocked(folio)))
goto isolate_fail_put;
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH 2/3] mm/compaction: add per-folio isolation tracepoint
2026-06-04 2:38 [RFC PATCH 0/3] mm/compaction: honour compact_unevictable_allowed in mlock race and alloc_contig path Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 1/3] mm/compaction: skip isolate mlocked folios when compact_unevictable_allowed=0 Wandun Chen
@ 2026-06-04 2:38 ` Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 3/3] mm/compaction: respect compact_unevictable_allowed in alloc_contig path Wandun Chen
2 siblings, 0 replies; 4+ messages in thread
From: Wandun Chen @ 2026-06-04 2:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-trace-kernel, linux-rt-devel
Cc: akpm, vbabka, surenb, mhocko, jackmanb, hannes, ziy, rostedt,
mhiramat, mathieu.desnoyers, david, ljs, liam, rppt, bigeasy,
clrkwllms, Alexander.Krabler
From: Wandun Chen <chenwandun@lixiang.com>
Add a tracepoint that fires once per folio successfully isolated by
isolate_migratepages_block(), recording the pfn, isolation mode and
the folio flags. Knowing these makes it easier to debug unexpected
isolation, such as mlocked or unevictable folios showing up on
PREEMPT_RT kernels [1].
Inspired-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Wandun Chen <chenwandun@lixiang.com>
Link: https://lore.kernel.org/all/20250820142919.HTybedrl@linutronix.de/ [1]
---
include/trace/events/compaction.h | 26 ++++++++++++++++++++++++++
mm/compaction.c | 2 ++
2 files changed, 28 insertions(+)
diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
index d05759d18538..8b8b3ec0f324 100644
--- a/include/trace/events/compaction.h
+++ b/include/trace/events/compaction.h
@@ -76,6 +76,32 @@ DEFINE_EVENT(mm_compaction_isolate_template, mm_compaction_fast_isolate_freepage
);
#ifdef CONFIG_COMPACTION
+TRACE_EVENT(mm_compaction_isolate_folio,
+
+ TP_PROTO(unsigned long pfn,
+ isolate_mode_t mode,
+ unsigned long flags),
+
+ TP_ARGS(pfn, mode, flags),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, pfn)
+ __field(isolate_mode_t, mode)
+ __field(unsigned long, flags)
+ ),
+
+ TP_fast_assign(
+ __entry->pfn = pfn;
+ __entry->mode = mode;
+ __entry->flags = flags;
+ ),
+
+ TP_printk("pfn=0x%lx mode=0x%x flags=%s",
+ __entry->pfn,
+ __entry->mode,
+ show_page_flags(__entry->flags & PAGEFLAGS_MASK))
+);
+
TRACE_EVENT(mm_compaction_migratepages,
TP_PROTO(unsigned int nr_migratepages,
diff --git a/mm/compaction.c b/mm/compaction.c
index 7e07b792bcb5..007d5e00a8ae 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1223,6 +1223,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
isolate_success:
list_add(&folio->lru, &cc->migratepages);
isolate_success_no_list:
+ trace_mm_compaction_isolate_folio(folio_pfn(folio), mode,
+ folio->flags.f);
cc->nr_migratepages += folio_nr_pages(folio);
nr_isolated += folio_nr_pages(folio);
nr_scanned += folio_nr_pages(folio) - 1;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [RFC PATCH 3/3] mm/compaction: respect compact_unevictable_allowed in alloc_contig path
2026-06-04 2:38 [RFC PATCH 0/3] mm/compaction: honour compact_unevictable_allowed in mlock race and alloc_contig path Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 1/3] mm/compaction: skip isolate mlocked folios when compact_unevictable_allowed=0 Wandun Chen
2026-06-04 2:38 ` [RFC PATCH 2/3] mm/compaction: add per-folio isolation tracepoint Wandun Chen
@ 2026-06-04 2:38 ` Wandun Chen
2 siblings, 0 replies; 4+ messages in thread
From: Wandun Chen @ 2026-06-04 2:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-trace-kernel, linux-rt-devel
Cc: akpm, vbabka, surenb, mhocko, jackmanb, hannes, ziy, rostedt,
mhiramat, mathieu.desnoyers, david, ljs, liam, rppt, bigeasy,
clrkwllms, Alexander.Krabler
From: Wandun Chen <chenwandun@lixiang.com>
vm.compact_unevictable_allowed=0 is used to prevent compacting
unevictable pages. However, isolate_migratepages_range() passes
ISOLATE_UNEVICTABLE regardless of this sysctl, so the setting
has no effect in the alloc_contig path.
Fix it by:
- Keep ISOLATE_UNEVICTABLE for CMA allocation, discussed in [1].
- Honour sysctl_compact_unevictable_allowed for non-CMA allocation.
Suggested-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Wandun Chen <chenwandun@lixiang.com>
Link: https://lore.kernel.org/all/25ba0d77-eb61-4efc-b2fc-73878cbd85c1@suse.cz/ [1]
---
include/linux/compaction.h | 6 ++++++
mm/compaction.c | 9 +++++++--
mm/internal.h | 1 +
mm/page_alloc.c | 2 ++
4 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index f29ef0653546..04e60f65b976 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -106,6 +106,7 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
extern void __meminit kcompactd_run(int nid);
extern void __meminit kcompactd_stop(int nid);
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx);
+extern bool compaction_allow_unevictable(void);
#else
static inline void reset_isolation_suitable(pg_data_t *pgdat)
@@ -131,6 +132,11 @@ static inline void wakeup_kcompactd(pg_data_t *pgdat,
{
}
+static inline bool compaction_allow_unevictable(void)
+{
+ return true;
+}
+
#endif /* CONFIG_COMPACTION */
struct node;
diff --git a/mm/compaction.c b/mm/compaction.c
index 007d5e00a8ae..a10acb273454 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1341,6 +1341,7 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
unsigned long end_pfn)
{
unsigned long pfn, block_start_pfn, block_end_pfn;
+ isolate_mode_t mode = cc->allow_unevictable ? ISOLATE_UNEVICTABLE : 0;
int ret = 0;
/* Scan block by block. First and last block may be incomplete */
@@ -1360,8 +1361,7 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
block_end_pfn, cc->zone))
continue;
- ret = isolate_migratepages_block(cc, pfn, block_end_pfn,
- ISOLATE_UNEVICTABLE);
+ ret = isolate_migratepages_block(cc, pfn, block_end_pfn, mode);
if (ret)
break;
@@ -1902,6 +1902,11 @@ typedef enum {
* compactable pages.
*/
static int sysctl_compact_unevictable_allowed __read_mostly = CONFIG_COMPACT_UNEVICTABLE_DEFAULT;
+
+bool compaction_allow_unevictable(void)
+{
+ return sysctl_compact_unevictable_allowed;
+}
/*
* Tunable for proactive compaction. It determines how
* aggressively the kernel should compact memory in the
diff --git a/mm/internal.h b/mm/internal.h
index 181e79f1d6a2..163f9d6b37f3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1052,6 +1052,7 @@ struct compact_control {
* ensure forward progress.
*/
bool alloc_contig; /* alloc_contig_range allocation */
+ bool allow_unevictable; /* Allow isolation of unevictable folios */
};
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 81a9d4d1e6c0..1cf9d4a3b14c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7118,6 +7118,8 @@ int alloc_contig_frozen_range_noprof(unsigned long start, unsigned long end,
.ignore_skip_hint = true,
.no_set_skip_hint = true,
.alloc_contig = true,
+ .allow_unevictable = !!(alloc_flags & ACR_FLAGS_CMA) ||
+ compaction_allow_unevictable(),
};
INIT_LIST_HEAD(&cc.migratepages);
enum pb_isolate_mode mode = (alloc_flags & ACR_FLAGS_CMA) ?
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread