Re: [PATCH -v4 4/4] mm/mglru: fix anon-only reclaim evicting file pages when swappiness=max
From: Kairui Song
Date: Fri Jul 24 2026 - 03:23:56 EST
On Fri, Jul 24, 2026 at 11:36 AM Ridong <ridong.chen@xxxxxxxxx> wrote:
>
> From: Ridong Chen <chenridong@xxxxxxxxxx>
>
> The previous patch fixed this issue for the traditional LRU. The same
> problem exists in MGLRU [1]: when swappiness=max (SWAPPINESS_ANON_ONLY)
> is set, reclaim is expected to evict anonymous pages exclusively, but
> file pages can still be reclaimed when anonymous pages cannot be
> reclaimed (e.g. no swap and no demotion target).
>
> Fix it the same way as the traditional LRU: keep returning
> SWAPPINESS_ANON_ONLY in get_swappiness(), and return 0 from
> get_nr_to_scan() when SWAPPINESS_ANON_ONLY is set but anon pages cannot
> be reclaimed. Since get_nr_to_scan() decides how much MGLRU scans,
> returning 0 skips the scan entirely and avoids the useless scan work
> when there is nothing eligible to reclaim.
>
> The test result:
> Before fix:
>
> # cat /sys/kernel/mm/lru_gen/enabled
> 0x0007
> # cat memory.stat
> anon 204800
> file 67108864
> ...
> pgsteal_proactive 0
> pgscan_proactive 0
>
> # echo "64M swappiness=max" > memory.reclaim
> # cat memory.stat
> anon 208896
> file 0
> ...
> pgsteal_proactive 16384
> pgscan_proactive 16384
>
> After fix:
>
> # cat memory.stat
> anon 188416
> file 67215360
> kernel 1970176
> ...
> pgsteal_proactive 0
> pgscan_proactive 0
>
> # echo "64M swappiness=max" > memory.reclaim
> -bash: echo: write error: Resource temporarily unavailable
> # cat memory.stat
> anon 204800
> file 67215360
> ...
> pgsteal_proactive 0
> pgscan_proactive 0
>
> [1] https://sashiko.dev/#/patchset/20260717113300.214717-1-ridong.chen@xxxxxxxxx
>
> Fixes: 68a1436bde00 ("mm: add swappiness=max arg to memory.reclaim for only anon reclaim")
> Signed-off-by: Ridong Chen <chenridong@xxxxxxxxxx>
> ---
> mm/vmscan.c | 20 +++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 859655fcf60d..254827544461 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -2708,6 +2708,10 @@ static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc)
> {
> struct mem_cgroup *memcg = lruvec_memcg(lruvec);
> struct pglist_data *pgdat = lruvec_pgdat(lruvec);
> + int swappiness = sc_swappiness(sc, memcg);
> +
> + if (swappiness == SWAPPINESS_ANON_ONLY)
> + return swappiness;
>
> if (!sc->may_swap)
> return 0;
> @@ -2716,7 +2720,7 @@ static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc)
> mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH)
> return 0;
>
> - return sc_swappiness(sc, memcg);
> + return swappiness;
> }
>
> static int get_nr_gens(struct lruvec *lruvec, int type)
> @@ -4921,6 +4925,20 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc,
> struct mem_cgroup *memcg, int swappiness)
> {
> unsigned long nr_to_scan, evictable;
> + struct pglist_data *pgdat = lruvec_pgdat(lruvec);
> +
> + /*
> + * Proactive reclaim initiated by userspace for anonymous memory only.
> + * SWAPPINESS_ANON_ONLY is set only on the proactive reclaim path, so
> + * warn if it shows up elsewhere. When anon cannot be reclaimed (e.g.
> + * no swap), return 0 to skip the scan entirely, avoiding useless scan
> + * work when there is nothing eligible to reclaim.
> + */
> + if (swappiness == SWAPPINESS_ANON_ONLY) {
> + WARN_ON_ONCE(!sc->proactive);
> + if (!can_reclaim_anon_pages(memcg, pgdat->node_id, sc))
> + return 0;
> + }
>
> evictable = lruvec_evictable_size(lruvec, swappiness);
>
> --
> 2.34.1
Looks good to me, thanks!
Reviewed-by: Kairui Song <kasong@xxxxxxxxxxx>