[PATCH RFC 2/3] mm: new migrate_mode flag for async using non-temporal stores
From: Yiannis Nikolakopoulos <hidden>
Date: 2026-05-26 11:37:44
Also in:
linux-mm, linux-nfs, lkml
Subsystem:
filesystems (vfs and infrastructure), memory management, memory management - memory policy and migration, memory management - page allocator, nfs, sunrpc, and lockd clients, the rest, tracing · Maintainers:
Alexander Viro, Christian Brauner, Andrew Morton, David Hildenbrand, Vlastimil Babka, Trond Myklebust, Anna Schumaker, Linus Torvalds, Steven Rostedt, Masami Hiramatsu
From: Alirad Malek <redacted> In preparation for the following patch, add a new migrate_mode which is still async but will use non-temporal stores. Add a helper function that checks for both async modes and replace all plain checks of MIGRATE_ASYNC. Signed-off-by: Alirad Malek <redacted> Co-developed-by: Yiannis Nikolakopoulos <redacted> Signed-off-by: Yiannis Nikolakopoulos <redacted> --- fs/nfs/write.c | 2 +- include/linux/migrate_mode.h | 9 +++++++++ include/trace/events/migrate.h | 1 + mm/compaction.c | 18 +++++++++--------- mm/migrate.c | 12 ++++++------ 5 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 1ed4b3590b1a..beae4441e080 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c@@ -2119,7 +2119,7 @@ int nfs_migrate_folio(struct address_space *mapping, struct folio *dst, } if (folio_test_private_2(src)) { /* [DEPRECATED] */ - if (mode == MIGRATE_ASYNC) + if (migrate_mode_is_async(mode)) return -EBUSY; folio_wait_private_2(src); }
diff --git a/include/linux/migrate_mode.h b/include/linux/migrate_mode.h
index 265c4328b36a..f7186e705b48 100644
--- a/include/linux/migrate_mode.h
+++ b/include/linux/migrate_mode.h@@ -3,6 +3,8 @@ #define MIGRATE_MODE_H_INCLUDED /* * MIGRATE_ASYNC means never block + * MIGRATE_ASYNC_NON_TEMPORAL_STORES means never block and use non-temporal + * stores if supported by the architecture * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking * on most operations but not ->writepage as the potential stall time * is too significant
@@ -10,10 +12,17 @@ */ enum migrate_mode { MIGRATE_ASYNC, + MIGRATE_ASYNC_NON_TEMPORAL_STORES, MIGRATE_SYNC_LIGHT, MIGRATE_SYNC, }; +static inline bool migrate_mode_is_async(enum migrate_mode mode) +{ + return mode == MIGRATE_ASYNC || + mode == MIGRATE_ASYNC_NON_TEMPORAL_STORES; +} + enum migrate_reason { MR_COMPACTION, MR_MEMORY_FAILURE,
diff --git a/include/trace/events/migrate.h b/include/trace/events/migrate.h
index cd01dd7b3640..e493207a3f46 100644
--- a/include/trace/events/migrate.h
+++ b/include/trace/events/migrate.h@@ -9,6 +9,7 @@ #define MIGRATE_MODE \ EM( MIGRATE_ASYNC, "MIGRATE_ASYNC") \ + EM(MIGRATE_ASYNC_NON_TEMPORAL_STORES, "MIGRATE_ASYNC_NON_TEMPORAL_STORES") \ EM( MIGRATE_SYNC_LIGHT, "MIGRATE_SYNC_LIGHT") \ EMe(MIGRATE_SYNC, "MIGRATE_SYNC")
diff --git a/mm/compaction.c b/mm/compaction.c
index 1e8f8eca318c..cd26781b7376 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c@@ -444,7 +444,7 @@ static void update_cached_migrate(struct compact_control *cc, unsigned long pfn) /* Update where async and sync compaction should restart */ if (pfn > zone->compact_cached_migrate_pfn[0]) zone->compact_cached_migrate_pfn[0] = pfn; - if (cc->mode != MIGRATE_ASYNC && + if (!migrate_mode_is_async(cc->mode) && pfn > zone->compact_cached_migrate_pfn[1]) zone->compact_cached_migrate_pfn[1] = pfn; }
@@ -507,7 +507,7 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags, __acquires(lock) { /* Track if the lock is contended in async mode */ - if (cc->mode == MIGRATE_ASYNC && !cc->contended) { + if (migrate_mode_is_async(cc->mode) && !cc->contended) { if (spin_trylock_irqsave(lock, *flags)) return true;
@@ -864,7 +864,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, return -EAGAIN; /* async migration should just abort */ - if (cc->mode == MIGRATE_ASYNC) + if (migrate_mode_is_async(cc->mode)) return -EAGAIN; reclaim_throttle(pgdat, VMSCAN_THROTTLE_ISOLATED);
@@ -875,7 +875,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, cond_resched(); - if (cc->direct_compaction && (cc->mode == MIGRATE_ASYNC)) { + if (cc->direct_compaction && migrate_mode_is_async(cc->mode)) { skip_on_failure = true; next_skip_pfn = block_end_pfn(low_pfn, cc->order); }
@@ -1364,7 +1364,7 @@ static bool suitable_migration_source(struct compact_control *cc, if (pageblock_skip_persistent(page)) return false; - if ((cc->mode != MIGRATE_ASYNC) || !cc->direct_compaction) + if (!migrate_mode_is_async(cc->mode) || !cc->direct_compaction) return true; block_mt = get_pageblock_migratetype(page);
@@ -1465,7 +1465,7 @@ fast_isolate_around(struct compact_control *cc, unsigned long pfn) return; /* Minimise scanning during async compaction */ - if (cc->direct_compaction && cc->mode == MIGRATE_ASYNC) + if (cc->direct_compaction && migrate_mode_is_async(cc->mode)) return; /* Pageblock boundaries */
@@ -1705,7 +1705,7 @@ static void isolate_freepages(struct compact_control *cc) block_end_pfn = min(block_start_pfn + pageblock_nr_pages, zone_end_pfn(zone)); low_pfn = pageblock_end_pfn(cc->migrate_pfn); - stride = cc->mode == MIGRATE_ASYNC ? COMPACT_CLUSTER_MAX : 1; + stride = migrate_mode_is_async(cc->mode) ? COMPACT_CLUSTER_MAX : 1; /* * Isolate free pages until enough are available to migrate the
@@ -2514,7 +2514,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc) unsigned long start_pfn = cc->zone->zone_start_pfn; unsigned long end_pfn = zone_end_pfn(cc->zone); unsigned long last_migrated_pfn; - const bool sync = cc->mode != MIGRATE_ASYNC; + const bool sync = !migrate_mode_is_async(cc->mode); bool update_cached; unsigned int nr_succeeded = 0, nr_migratepages; int order;
@@ -2537,7 +2537,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc) ret = compaction_suit_allocation_order(cc->zone, cc->order, cc->highest_zoneidx, cc->alloc_flags, - cc->mode == MIGRATE_ASYNC, + migrate_mode_is_async(cc->mode), !cc->direct_compaction); if (ret != COMPACT_CONTINUE) return ret;
diff --git a/mm/migrate.c b/mm/migrate.c
index 2c3d489ecf51..ff6cf50e7b0b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c@@ -907,7 +907,7 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head, do { if (!trylock_buffer(bh)) { - if (mode == MIGRATE_ASYNC) + if (migrate_mode_is_async(mode)) goto unlock; if (mode == MIGRATE_SYNC_LIGHT && !buffer_uptodate(bh)) goto unlock;
@@ -1220,7 +1220,7 @@ static int migrate_folio_unmap(new_folio_t get_new_folio, dst->private = NULL; if (!folio_trylock(src)) { - if (mode == MIGRATE_ASYNC) + if (migrate_mode_is_async(mode)) goto out; /*
@@ -1325,7 +1325,7 @@ static int migrate_folio_unmap(new_folio_t get_new_folio, /* Establish migration ptes */ VM_BUG_ON_FOLIO(folio_test_anon(src) && !folio_test_ksm(src) && !anon_vma, src); - try_to_migrate(src, mode == MIGRATE_ASYNC ? TTU_BATCH_FLUSH : 0); + try_to_migrate(src, migrate_mode_is_async(mode) ? TTU_BATCH_FLUSH : 0); old_page_state |= PAGE_WAS_MAPPED; }
@@ -1565,7 +1565,7 @@ static inline int try_split_folio(struct folio *folio, struct list_head *split_f { int rc; - if (mode == MIGRATE_ASYNC) { + if (migrate_mode_is_async(mode)) { if (!folio_trylock(folio)) return -EAGAIN; } else {
@@ -1799,7 +1799,7 @@ static int migrate_pages_batch(struct list_head *from, LIST_HEAD(dst_folios); bool nosplit = (reason == MR_NUMA_MISPLACED); - VM_WARN_ON_ONCE(mode != MIGRATE_ASYNC && + VM_WARN_ON_ONCE(!migrate_mode_is_async(mode) && !list_empty(from) && !list_is_singular(from)); for (pass = 0; pass < nr_pass && retry; pass++) {
@@ -2107,7 +2107,7 @@ int migrate_pages(struct list_head *from, new_folio_t get_new_folio, list_cut_before(&folios, from, &folio2->lru); else list_splice_init(from, &folios); - if (mode == MIGRATE_ASYNC) + if (migrate_mode_is_async(mode)) rc = migrate_pages_batch(&folios, get_new_folio, put_new_folio, private, mode, reason, &ret_folios, &split_folios, &stats,
--
2.43.0