Re: [PATCH v2 2/2] mm: vmscan: fix node reclaim ignoring swappiness parameter

From: Tao Cui

Date: Thu Jul 16 2026 - 02:06:52 EST


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@xxxxxxxxxx>
Reviewed-by: Song Hu <husong@xxxxxxxxxx>

在 2026/7/16 11:17, Ridong 写道:
> From: Ridong Chen <chenridong@xxxxxxxxxx>
>
> 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@xxxxxxxxxxxxxxx # 6.17+
> Fixes: b980077899ea ("mm: introduce per-node proactive reclaim interface")
> Signed-off-by: Ridong Chen <chenridong@xxxxxxxxxx>
> Acked-by: Johannes Weiner <hannes@xxxxxxxxxxx>
> Reviewed-by: Barry Song <baohua@xxxxxxxxxx>
> ---
> 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,