Re: [PATCH v2] mm/vmscan: clear hopeless kswapd when global direct reclaim makes progress
From: Altan Hacigumus
Date: Tue Jul 14 2026 - 22:30:53 EST
On Mon, Jul 13, 2026 at 4:20 AM Johannes Weiner <hannes@xxxxxxxxxxx> wrote:
>
> On Fri, Jul 10, 2026 at 09:39:46PM -0700, Altan Hacigumus wrote:
> > Direct reclaim clears the hopeless kswapd state only once the node
> > becomes balanced - added by commit dc9fe9b7056a ("mm/vmscan: mitigate
> > spurious kswapd_failures reset from direct reclaim") so that cgroup
> > memory.high reclaim cannot repeatedly revive a kswapd that is unable to
> > balance the node. Before it, any reclaim progress revived kswapd.
> >
> > However, this restriction also prevents global direct reclaim from
> > reviving kswapd. Under sustained memory pressure, global direct reclaim
> > may continue making progress without the node ever reaching the high
> > watermark, leaving reclaim to allocating tasks.
> >
> > The effect is visible on systems where a database workload mlocks most
> > of memory and the remainder is under continuous pressure: allocations
> > stall long enough that ordinary tasks (e.g. ssh) become slow or
> > unresponsive, while kswapd sits idle.
> >
> > Unlike memcg reclaim, global direct reclaim follows the same node-wide
> > reclaim path as kswapd. Clear the hopeless state when global direct
> > reclaim makes progress, while continuing to require a balanced node for
> > memcg reclaim. kswapd_try_clear_hopeless() becomes static since struct
> > scan_control is private to vmscan.c.
> >
> > On a workload with most memory mlocked and the remainder under sustained
> > churn, with swap enabled, comparing the same 60s window:
> > base patched
> > allocstall (all zones) 413441 6532
> > pgsteal_direct 15889552 255619
> > pgsteal_kswapd 0 26079382
> > PSI memory full avg60 13.10% 9.37%
> >
> > Direct reclaim was already reclaiming many pages in the baseline;
> > this change lets kswapd resume doing that work asynchronously.
>
> But does kswapd actually stop?
>
> I don't see how you avoid re-introducing the issue described in
> dc9fe9b7056a. Direct reclaim picking up a few pages is no guarantee
> that kswapd is able to restore the watermarks and stop running.
>
> The distinction between global reclaim and memcg reclaim seems
> handwavy to me. Either can free a couple of pages on the node. Who is
> doing it has little bearing on the question whether kswapd can balance
> the node and go to sleep?
kswapd still stops for the same reason as before. Its own reclaim
progress never clears the hopeless state; only pgdat_balanced() does.
If it stops making progress, it reaches MAX_RECLAIM_RETRIES and parks
again. This change only allows successful global direct reclaim to
revive it. Whether a revived kswapd can rebalance the node is not
guaranteed - nor required: under sustained pressure the change is about
who performs the reclaim, kswapd asynchronously instead of every
allocating task synchronously.
The distinction is mechanical rather than "handwavy"; global direct
reclaim follows the same reclaim path with the same protection rules as
kswapd, whereas memcg reclaim does not: reclaim targeting a cgroup
ignores that cgroup's own memory.min/memory.low protection (see
mem_cgroup_unprotected()), so it can succeed where kswapd cannot. Thats
why the patch gates the reset on pgdat_balanced() for memcg reclaim, but
not for global direct reclaim.