* [PATCH v2 0/2] mm: fix node reclaim swappiness handling @ 2026-07-16 3:17 Ridong 2026-07-16 3:17 ` [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h Ridong 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong 0 siblings, 2 replies; 7+ messages in thread From: Ridong @ 2026-07-16 3:17 UTC (permalink / raw) To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Qi Zheng, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, Ridong From: Ridong <chenridong@xiaomi.com> The per-node proactive reclaim interface (/sys/devices/system/node/nodeX/reclaim) accepts a swappiness parameter, but it is silently ignored when CONFIG_MEMCG is disabled. The root cause is that sc_swappiness() has separate implementations for CONFIG_MEMCG and !CONFIG_MEMCG, and the latter never checks proactive_swappiness. Patch 1 moves mem_cgroup_swappiness() and vm_swappiness out of the public include/linux/swap.h into the mm-private mm/swap.h, and makes the helper handle both CONFIG_MEMCG and !CONFIG_MEMCG in a single inline function. This is a prerequisite for unifying sc_swappiness(). Patch 2 consolidates sc_swappiness() into a single definition that works regardless of CONFIG_MEMCG, fixing the node reclaim swappiness bug. --- v1 -> v2: - Move mem_cgroup_swappiness() and vm_swappiness to mm/swap.h instead of include/linux/memcontrol.h. Suggested by Barry Song. - Correct fix tag for patch 2. v1: https://lore.kernel.org/all/20260711091157.306070-1-ridong.chen@linux.dev/ Ridong Chen (2): memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h mm: vmscan: fix node reclaim ignoring swappiness parameter include/linux/memcontrol.h | 4 ++-- include/linux/swap.h | 19 ------------------- mm/memcontrol.c | 4 ++-- mm/swap.h | 20 ++++++++++++++++++++ mm/vmscan.c | 19 +++++++------------ 5 files changed, 31 insertions(+), 35 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h 2026-07-16 3:17 [PATCH v2 0/2] mm: fix node reclaim swappiness handling Ridong @ 2026-07-16 3:17 ` Ridong 2026-07-16 6:06 ` Tao Cui 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong 1 sibling, 1 reply; 7+ messages in thread From: Ridong @ 2026-07-16 3:17 UTC (permalink / raw) To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Qi Zheng, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, Ridong Chen From: Ridong Chen <chenridong@xiaomi.com> The per-memcg swappiness knob is v1-only; v2 always uses global vm_swappiness and ignores the per-cgroup field. Both mem_cgroup_swappiness() and vm_swappiness are only used within mm/ (memcontrol.c, memcontrol-v1.c, vmscan.c), so move them out of the public include/linux/swap.h into the mm-private mm/swap.h. This keeps unrelated declarations out of include/linux/swap.h. Guard memcg->swappiness with CONFIG_MEMCG_V1 as well, so v2-only kernels drop the unused field. No functional change for v1; v2-only kernels drop the unused field. Signed-off-by: Ridong Chen <chenridong@xiaomi.com> --- include/linux/memcontrol.h | 4 ++-- include/linux/swap.h | 19 ------------------- mm/memcontrol.c | 4 ++-- mm/swap.h | 20 ++++++++++++++++++++ 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 957260677678..e7a794dfb40e 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -239,8 +239,6 @@ struct mem_cgroup { */ bool oom_group; - int swappiness; - /* memory.events and memory.events.local */ struct cgroup_file events_file; struct cgroup_file events_local_file; @@ -318,6 +316,8 @@ struct mem_cgroup { /* List of events which userspace want to receive */ struct list_head event_list; spinlock_t event_list_lock; + + int swappiness; #endif /* CONFIG_MEMCG_V1 */ struct mem_cgroup_per_node *nodeinfo[]; diff --git a/include/linux/swap.h b/include/linux/swap.h index 696ed01709c2..330a420fd6de 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -309,7 +309,6 @@ static inline bool lru_cache_disabled(void) } extern unsigned long shrink_all_memory(unsigned long nr_pages); -extern int vm_swappiness; long remove_mapping(struct address_space *mapping, struct folio *folio); #if defined(CONFIG_SYSFS) && defined(CONFIG_NUMA) @@ -468,25 +467,7 @@ static inline int add_swap_extent(struct swap_info_struct *sis, } #endif /* CONFIG_SWAP */ #ifdef CONFIG_MEMCG -static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) -{ - /* Cgroup2 doesn't have per-cgroup swappiness */ - if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) - return READ_ONCE(vm_swappiness); - - /* root ? */ - if (mem_cgroup_disabled() || mem_cgroup_is_root(memcg)) - return READ_ONCE(vm_swappiness); - - return READ_ONCE(memcg->swappiness); -} - void lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int nid); -#else -static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) -{ - return READ_ONCE(vm_swappiness); -} #endif #if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 22f55aeb94f3..d6ba276740ea 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -63,6 +63,7 @@ #include <linux/sched/isolation.h> #include <linux/kmemleak.h> #include "internal.h" +#include "swap.h" #include "swap_table.h" #include <net/sock.h> #include <net/ip.h> @@ -4174,11 +4175,10 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) #endif page_counter_set_high(&memcg->swap, PAGE_COUNTER_MAX); if (parent) { - WRITE_ONCE(memcg->swappiness, mem_cgroup_swappiness(parent)); - page_counter_init(&memcg->memory, &parent->memory, memcg_on_dfl); page_counter_init(&memcg->swap, &parent->swap, false); #ifdef CONFIG_MEMCG_V1 + WRITE_ONCE(memcg->swappiness, mem_cgroup_swappiness(parent)); memcg->memory.track_failcnt = !memcg_on_dfl; WRITE_ONCE(memcg->oom_kill_disable, READ_ONCE(parent->oom_kill_disable)); page_counter_init(&memcg->kmem, &parent->kmem, false); diff --git a/mm/swap.h b/mm/swap.h index b51ad3071a73..a0e04b97a466 100644 --- a/mm/swap.h +++ b/mm/swap.h @@ -4,6 +4,7 @@ #include <linux/atomic.h> /* for atomic_long_t */ #include <linux/mm.h> /* for PAGE_SHIFT */ +#include <linux/memcontrol.h> /* for mem_cgroup_swappiness() */ struct mempolicy; struct swap_iocb; struct swap_memcg_table; @@ -76,6 +77,25 @@ enum swap_cluster_flags { CLUSTER_FLAG_MAX, }; +extern int vm_swappiness; + +static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) +{ +#ifdef CONFIG_MEMCG_V1 + /* Cgroup2 doesn't have per-cgroup swappiness */ + if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) + return READ_ONCE(vm_swappiness); + + /* root ? */ + if (mem_cgroup_disabled() || mem_cgroup_is_root(memcg)) + return READ_ONCE(vm_swappiness); + + return READ_ONCE(memcg->swappiness); +#else + return READ_ONCE(vm_swappiness); +#endif +} + #ifdef CONFIG_SWAP #include <linux/swapops.h> /* for swp_offset */ #include <linux/blk_types.h> /* for bio_end_io_t */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h 2026-07-16 3:17 ` [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h Ridong @ 2026-07-16 6:06 ` Tao Cui 0 siblings, 0 replies; 7+ messages in thread From: Tao Cui @ 2026-07-16 6:06 UTC (permalink / raw) To: Ridong, Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: cui.tao, Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Qi Zheng, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen Reviewed-by: Song Hu <husong@kylinos.cn> 在 2026/7/16 11:17, Ridong 写道: > From: Ridong Chen <chenridong@xiaomi.com> > > The per-memcg swappiness knob is v1-only; v2 always uses global > vm_swappiness and ignores the per-cgroup field. > > Both mem_cgroup_swappiness() and vm_swappiness are only used within > mm/ (memcontrol.c, memcontrol-v1.c, vmscan.c), so move them out of the > public include/linux/swap.h into the mm-private mm/swap.h. This keeps > unrelated declarations out of include/linux/swap.h. > > Guard memcg->swappiness with CONFIG_MEMCG_V1 as well, so v2-only > kernels drop the unused field. > > No functional change for v1; v2-only kernels drop the unused field. > > Signed-off-by: Ridong Chen <chenridong@xiaomi.com> > --- > include/linux/memcontrol.h | 4 ++-- > include/linux/swap.h | 19 ------------------- > mm/memcontrol.c | 4 ++-- > mm/swap.h | 20 ++++++++++++++++++++ > 4 files changed, 24 insertions(+), 23 deletions(-) > > diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h > index 957260677678..e7a794dfb40e 100644 > --- a/include/linux/memcontrol.h > +++ b/include/linux/memcontrol.h > @@ -239,8 +239,6 @@ struct mem_cgroup { > */ > bool oom_group; > > - int swappiness; > - > /* memory.events and memory.events.local */ > struct cgroup_file events_file; > struct cgroup_file events_local_file; > @@ -318,6 +316,8 @@ struct mem_cgroup { > /* List of events which userspace want to receive */ > struct list_head event_list; > spinlock_t event_list_lock; > + > + int swappiness; > #endif /* CONFIG_MEMCG_V1 */ > > struct mem_cgroup_per_node *nodeinfo[]; > diff --git a/include/linux/swap.h b/include/linux/swap.h > index 696ed01709c2..330a420fd6de 100644 > --- a/include/linux/swap.h > +++ b/include/linux/swap.h > @@ -309,7 +309,6 @@ static inline bool lru_cache_disabled(void) > } > > extern unsigned long shrink_all_memory(unsigned long nr_pages); > -extern int vm_swappiness; > long remove_mapping(struct address_space *mapping, struct folio *folio); > > #if defined(CONFIG_SYSFS) && defined(CONFIG_NUMA) > @@ -468,25 +467,7 @@ static inline int add_swap_extent(struct swap_info_struct *sis, > } > #endif /* CONFIG_SWAP */ > #ifdef CONFIG_MEMCG > -static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) > -{ > - /* Cgroup2 doesn't have per-cgroup swappiness */ > - if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) > - return READ_ONCE(vm_swappiness); > - > - /* root ? */ > - if (mem_cgroup_disabled() || mem_cgroup_is_root(memcg)) > - return READ_ONCE(vm_swappiness); > - > - return READ_ONCE(memcg->swappiness); > -} > - > void lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int nid); > -#else > -static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) > -{ > - return READ_ONCE(vm_swappiness); > -} > #endif > > #if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP) > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index 22f55aeb94f3..d6ba276740ea 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -63,6 +63,7 @@ > #include <linux/sched/isolation.h> > #include <linux/kmemleak.h> > #include "internal.h" > +#include "swap.h" > #include "swap_table.h" > #include <net/sock.h> > #include <net/ip.h> > @@ -4174,11 +4175,10 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) > #endif > page_counter_set_high(&memcg->swap, PAGE_COUNTER_MAX); > if (parent) { > - WRITE_ONCE(memcg->swappiness, mem_cgroup_swappiness(parent)); > - > page_counter_init(&memcg->memory, &parent->memory, memcg_on_dfl); > page_counter_init(&memcg->swap, &parent->swap, false); > #ifdef CONFIG_MEMCG_V1 > + WRITE_ONCE(memcg->swappiness, mem_cgroup_swappiness(parent)); > memcg->memory.track_failcnt = !memcg_on_dfl; > WRITE_ONCE(memcg->oom_kill_disable, READ_ONCE(parent->oom_kill_disable)); > page_counter_init(&memcg->kmem, &parent->kmem, false); > diff --git a/mm/swap.h b/mm/swap.h > index b51ad3071a73..a0e04b97a466 100644 > --- a/mm/swap.h > +++ b/mm/swap.h > @@ -4,6 +4,7 @@ > > #include <linux/atomic.h> /* for atomic_long_t */ > #include <linux/mm.h> /* for PAGE_SHIFT */ > +#include <linux/memcontrol.h> /* for mem_cgroup_swappiness() */ > struct mempolicy; > struct swap_iocb; > struct swap_memcg_table; > @@ -76,6 +77,25 @@ enum swap_cluster_flags { > CLUSTER_FLAG_MAX, > }; > > +extern int vm_swappiness; > + > +static inline int mem_cgroup_swappiness(struct mem_cgroup *memcg) > +{ > +#ifdef CONFIG_MEMCG_V1 > + /* Cgroup2 doesn't have per-cgroup swappiness */ > + if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) > + return READ_ONCE(vm_swappiness); > + > + /* root ? */ > + if (mem_cgroup_disabled() || mem_cgroup_is_root(memcg)) > + return READ_ONCE(vm_swappiness); > + > + return READ_ONCE(memcg->swappiness); > +#else > + return READ_ONCE(vm_swappiness); > +#endif > +} > + > #ifdef CONFIG_SWAP > #include <linux/swapops.h> /* for swp_offset */ > #include <linux/blk_types.h> /* for bio_end_io_t */ ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter 2026-07-16 3:17 [PATCH v2 0/2] mm: fix node reclaim swappiness handling Ridong 2026-07-16 3:17 ` [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h Ridong @ 2026-07-16 3:17 ` Ridong 2026-07-16 3:25 ` Qi Zheng ` (2 more replies) 1 sibling, 3 replies; 7+ messages in thread From: Ridong @ 2026-07-16 3:17 UTC (permalink / raw) To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Qi Zheng, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, Ridong Chen, stable From: Ridong Chen <chenridong@xiaomi.com> sc_swappiness() had two separate definitions depending on CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned vm_swappiness, ignoring the proactive_swappiness value passed through scan_control. This caused the swappiness parameter written to /sys/devices/system/node/nodeX/reclaim to have no effect when CONFIG_MEMCG is disabled. Fix this by consolidating sc_swappiness() into a single definition that checks sc->proactive_swappiness first, then falls back to mem_cgroup_swappiness() which already handles both CONFIG_MEMCG and !CONFIG_MEMCG. Before fix (swappiness=max ignored, mostly file pages reclaimed): # cat /proc/sys/vm/swappiness 60 # cat /proc/vmstat | grep pgsteal pgsteal_kswapd 0 pgsteal_direct 0 pgsteal_khugepaged 0 pgsteal_proactive 1840 pgsteal_anon 25 pgsteal_file 1815 # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim # cat /proc/vmstat | grep pgsteal pgsteal_kswapd 0 pgsteal_direct 0 pgsteal_khugepaged 0 pgsteal_proactive 18013 pgsteal_anon 337 pgsteal_file 17676 After fix (swappiness=max honored, anon pages reclaimed as expected): # cat /proc/vmstat | grep pgsteal pgsteal_kswapd 0 pgsteal_direct 0 pgsteal_khugepaged 0 pgsteal_proactive 0 pgsteal_anon 0 pgsteal_file 0 # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim # cat /proc/vmstat | grep pgsteal pgsteal_kswapd 0 pgsteal_direct 0 pgsteal_khugepaged 0 pgsteal_proactive 16283 pgsteal_anon 16283 pgsteal_file 0 Cc: stable@vger.kernel.org # 6.17+ Fixes: b980077899ea ("mm: introduce per-node proactive reclaim interface") Signed-off-by: Ridong Chen <chenridong@xiaomi.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Barry Song <baohua@kernel.org> --- mm/vmscan.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 986dde8e7429..bd71595c8b2b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -199,6 +199,13 @@ struct scan_control { */ int vm_swappiness = 60; +static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) +{ + if (sc->proactive && sc->proactive_swappiness) + return *sc->proactive_swappiness; + return mem_cgroup_swappiness(memcg); +} + #ifdef CONFIG_MEMCG /* Returns true for reclaim through cgroup limits or cgroup interfaces. */ @@ -239,13 +246,6 @@ static bool writeback_throttling_sane(struct scan_control *sc) #endif return false; } - -static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) -{ - if (sc->proactive && sc->proactive_swappiness) - return *sc->proactive_swappiness; - return mem_cgroup_swappiness(memcg); -} #else static bool cgroup_reclaim(struct scan_control *sc) { @@ -261,11 +261,6 @@ static bool writeback_throttling_sane(struct scan_control *sc) { return true; } - -static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) -{ - return READ_ONCE(vm_swappiness); -} #endif static void set_task_reclaim_state(struct task_struct *task, -- 2.34.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong @ 2026-07-16 3:25 ` Qi Zheng 2026-07-16 3:58 ` Qi Zheng 2026-07-16 6:06 ` Tao Cui 2 siblings, 0 replies; 7+ messages in thread From: Qi Zheng @ 2026-07-16 3:25 UTC (permalink / raw) To: Ridong, Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, stable On 7/16/26 11:17 AM, Ridong wrote: > From: Ridong Chen <chenridong@xiaomi.com> > > sc_swappiness() had two separate definitions depending on > CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned > vm_swappiness, ignoring the proactive_swappiness value passed > through scan_control. This caused the swappiness parameter > written to /sys/devices/system/node/nodeX/reclaim to have no > effect when CONFIG_MEMCG is disabled. > > Fix this by consolidating sc_swappiness() into a single definition > that checks sc->proactive_swappiness first, then falls back to > mem_cgroup_swappiness() which already handles both CONFIG_MEMCG > and !CONFIG_MEMCG. > > Before fix (swappiness=max ignored, mostly file pages reclaimed): > > # cat /proc/sys/vm/swappiness > 60 > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 1840 > pgsteal_anon 25 > pgsteal_file 1815 > # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 18013 > pgsteal_anon 337 > pgsteal_file 17676 > > After fix (swappiness=max honored, anon pages reclaimed as expected): > > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 0 > pgsteal_anon 0 > pgsteal_file 0 > # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 16283 > pgsteal_anon 16283 > pgsteal_file 0 > > Cc: stable@vger.kernel.org # 6.17+ > Fixes: b980077899ea ("mm: introduce per-node proactive reclaim interface") > Signed-off-by: Ridong Chen <chenridong@xiaomi.com> > Acked-by: Johannes Weiner <hannes@cmpxchg.org> > Reviewed-by: Barry Song <baohua@kernel.org> > --- > mm/vmscan.c | 19 +++++++------------ > 1 file changed, 7 insertions(+), 12 deletions(-) Thanks for fixing this! Acked-by: Qi Zheng <qi.zheng@linux.dev> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong 2026-07-16 3:25 ` Qi Zheng @ 2026-07-16 3:58 ` Qi Zheng 2026-07-16 6:06 ` Tao Cui 2 siblings, 0 replies; 7+ messages in thread From: Qi Zheng @ 2026-07-16 3:58 UTC (permalink / raw) To: Ridong, Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, stable Hi Ridong, On 7/16/26 11:17 AM, Ridong wrote: > From: Ridong Chen <chenridong@xiaomi.com> > > sc_swappiness() had two separate definitions depending on > CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned > vm_swappiness, ignoring the proactive_swappiness value passed > through scan_control. This caused the swappiness parameter > written to /sys/devices/system/node/nodeX/reclaim to have no > effect when CONFIG_MEMCG is disabled. > > Fix this by consolidating sc_swappiness() into a single definition > that checks sc->proactive_swappiness first, then falls back to > mem_cgroup_swappiness() which already handles both CONFIG_MEMCG > and !CONFIG_MEMCG. > > Before fix (swappiness=max ignored, mostly file pages reclaimed): > > # cat /proc/sys/vm/swappiness > 60 > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 1840 > pgsteal_anon 25 > pgsteal_file 1815 > # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 18013 > pgsteal_anon 337 > pgsteal_file 17676 > > After fix (swappiness=max honored, anon pages reclaimed as expected): > By the way, in get_scan_count(), it seems we still reclaim file pages without swap space, even if swappiness=max (SWAPPINESS_ANON_ONLY) is set. This behavior appears to contradict the semantics of SWAPPINESS_ANON_ONLY, which probably needs a fix as well. Thanks, Qi ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong 2026-07-16 3:25 ` Qi Zheng 2026-07-16 3:58 ` Qi Zheng @ 2026-07-16 6:06 ` Tao Cui 2 siblings, 0 replies; 7+ messages in thread From: Tao Cui @ 2026-07-16 6:06 UTC (permalink / raw) To: Ridong, Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt, Andrew Morton, Chris Li, Kairui Song Cc: cui.tao, Muchun Song, Kemeng Shi, Nhat Pham, Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Qi Zheng, Lorenzo Stoakes, Axel Rasmussen, Yuanchu Xie, Wei Xu, Davidlohr Bueso, cgroups, linux-mm, linux-kernel, Ridong Chen, stable Hi Ridong, Reproduced the bug and verified the fix in a QEMU x86_64 guest with CONFIG_MEMCG disabled. Global vm.swappiness pinned to 1, then: echo "64M swappiness=<x>" > /sys/devices/system/node/node0/reclaim swappiness= | buggy (anon/file) | patched (anon/file) ----------- | -------------------- | -------------------- max | 0 / 16385 | 16292 / 0 200 | 2 / 16384 | 16837 / 0 1 | 0 / 16386 | 0 / 16467 Unpatched ignores the swappiness arg (always file); patched honors it. Matches the commit message. Tested-by: Song Hu <husong@kylinos.cn> Reviewed-by: Song Hu <husong@kylinos.cn> 在 2026/7/16 11:17, Ridong 写道: > From: Ridong Chen <chenridong@xiaomi.com> > > sc_swappiness() had two separate definitions depending on > CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned > vm_swappiness, ignoring the proactive_swappiness value passed > through scan_control. This caused the swappiness parameter > written to /sys/devices/system/node/nodeX/reclaim to have no > effect when CONFIG_MEMCG is disabled. > > Fix this by consolidating sc_swappiness() into a single definition > that checks sc->proactive_swappiness first, then falls back to > mem_cgroup_swappiness() which already handles both CONFIG_MEMCG > and !CONFIG_MEMCG. > > Before fix (swappiness=max ignored, mostly file pages reclaimed): > > # cat /proc/sys/vm/swappiness > 60 > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 1840 > pgsteal_anon 25 > pgsteal_file 1815 > # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 18013 > pgsteal_anon 337 > pgsteal_file 17676 > > After fix (swappiness=max honored, anon pages reclaimed as expected): > > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 0 > pgsteal_anon 0 > pgsteal_file 0 > # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim > # cat /proc/vmstat | grep pgsteal > pgsteal_kswapd 0 > pgsteal_direct 0 > pgsteal_khugepaged 0 > pgsteal_proactive 16283 > pgsteal_anon 16283 > pgsteal_file 0 > > Cc: stable@vger.kernel.org # 6.17+ > Fixes: b980077899ea ("mm: introduce per-node proactive reclaim interface") > Signed-off-by: Ridong Chen <chenridong@xiaomi.com> > Acked-by: Johannes Weiner <hannes@cmpxchg.org> > Reviewed-by: Barry Song <baohua@kernel.org> > --- > mm/vmscan.c | 19 +++++++------------ > 1 file changed, 7 insertions(+), 12 deletions(-) > > diff --git a/mm/vmscan.c b/mm/vmscan.c > index 986dde8e7429..bd71595c8b2b 100644 > --- a/mm/vmscan.c > +++ b/mm/vmscan.c > @@ -199,6 +199,13 @@ struct scan_control { > */ > int vm_swappiness = 60; > > +static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) > +{ > + if (sc->proactive && sc->proactive_swappiness) > + return *sc->proactive_swappiness; > + return mem_cgroup_swappiness(memcg); > +} > + > #ifdef CONFIG_MEMCG > > /* Returns true for reclaim through cgroup limits or cgroup interfaces. */ > @@ -239,13 +246,6 @@ static bool writeback_throttling_sane(struct scan_control *sc) > #endif > return false; > } > - > -static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) > -{ > - if (sc->proactive && sc->proactive_swappiness) > - return *sc->proactive_swappiness; > - return mem_cgroup_swappiness(memcg); > -} > #else > static bool cgroup_reclaim(struct scan_control *sc) > { > @@ -261,11 +261,6 @@ static bool writeback_throttling_sane(struct scan_control *sc) > { > return true; > } > - > -static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg) > -{ > - return READ_ONCE(vm_swappiness); > -} > #endif > > static void set_task_reclaim_state(struct task_struct *task, ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-07-16 6:07 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-16 3:17 [PATCH v2 0/2] mm: fix node reclaim swappiness handling Ridong 2026-07-16 3:17 ` [PATCH v2 1/2] memcg: move mem_cgroup_swappiness and vm_swappiness to mm/swap.h Ridong 2026-07-16 6:06 ` Tao Cui 2026-07-16 3:17 ` [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter Ridong 2026-07-16 3:25 ` Qi Zheng 2026-07-16 3:58 ` Qi Zheng 2026-07-16 6:06 ` Tao Cui
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox