Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Hui Zhu" <hui.zhu@linux.dev>
To: Andrew Morton <akpm@linux-foundation.org>,
	Kairui Song <kasong@tencent.com>, Qi Zheng <qi.zheng@linux.dev>,
	Shakeel Butt <shakeel.butt@linux.dev>,
	Barry Song <baohua@kernel.org>,
	Axel Rasmussen <axelrasmussen@google.com>,
	Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
	Johannes Weiner <hannes@cmpxchg.org>,
	David Hildenbrand <david@kernel.org>,
	Michal Hocko <mhocko@kernel.org>,
	Lorenzo Stoakes <ljs@kernel.org>,
	Baolin Wang <baolin.wang@linux.alibaba.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org
Cc: Hui Zhu <zhuhui@kylinos.cn>
Subject: [PATCH mm-unstable v4 0/2] mm/vmscan: fix NR_ISOLATED accounting and throttling for MGLRU
Date: Thu, 20 Aug 2026 10:48:13 +0800	[thread overview]
Message-ID: <cover.1787193916.git.zhuhui@kylinos.cn> (raw)

From: Hui Zhu <zhuhui@kylinos.cn>

The legacy reclaim path updates the NR_ISOLATED_ANON/FILE node
counters around isolation and throttles direct reclaimers via
too_many_isolated() when isolated folios pile up.  The MGLRU eviction
path does neither: evict_folios() isolates folios without touching
the counters and never consults too_many_isolated().

Patch 1 updates NR_ISOLATED_ANON/FILE around isolation in
evict_folios(), reusing the existing nr_isolated.  Without this the
counters stay at zero while MGLRU reclaim is active, so compaction's
too_many_isolated() cannot see the pages MGLRU has isolated.

Patch 2 adds throttle_evictable_types() and calls it from
evict_folios(), before the lruvec lock is taken since throttling
sleeps, leaving the legacy path untouched.  The MGLRU check differs
from the legacy per-list one in shrink_inactive_list() because
isolate_folios() picks the type to scan from the refault feedback
and may fall back to the other one: it computes the set of evictable
types that are not over-isolated and only sleeps when all of them
are, waiting once for concurrent reclaimers exactly like the legacy
path.  The mask of the remaining types is passed to isolate_folios(),
which restricts both its initial choice and its fallback to it, so
isolation never lands on an over-isolated type and a type that is
merely over-isolated never blocks the reclaim of the other one.
This way the MGLRU eviction path backs off when isolated folios pile
up instead of thrashing the shrinking LRU lists - the scenario the
too_many_isolated() check exists for.  A dying task fakes reclaim
progress exactly like the legacy path so it exits reclaim quickly.

Testing
=======

Test on 8G RAM qemu.
The reproducer confines stress-ng workers in a 192M memcg and swaps
through dm-delay (300ms write latency) so pageout is slow and isolated
folios pile up; the workload is intentionally extreme.  nr_isolated_*
is sampled every 50ms against the per-type too_many_isolated
threshold (inactive/8), and throttle events are counted via the
mm_vmscan_throttled tracepoint.
The test scripts and test log are in [1].

Test 1, reclaim throttling, parallel direct reclaim in the memcg:

                             before        after
throttle events (ISOLATED)        0            0
  - from kswapd                   0            0
nr_isolated_anon peak             0         3166
nr_isolated_file peak             0          174
  - samples above the
    too_many_isolated threshold  0/1088     89/1077
pgscan_direct            1540044096    858332151
pswpout                   6299497       725819

Without the series MGLRU reclaim spins on the shrinking LRU lists
while nr_isolated_* stays at 0 and nothing is throttled:
pgscan_direct runs to 1.5 billion and 6.3M pages are pushed through
the 300ms swap device, i.e. the memcg anon is recycled over and
over.  With the series the counters are updated and the
too_many_isolated threshold is crossed (89 of 1077 samples).  Only
anon is over-isolated in this workload, so the throttle never has
to sleep: it stops reclaimers from isolating more anon and has them
fall back to file instead (nr_isolated_file peaks at 174 instead of
0), and anon isolation stays around the threshold (peak 3166).
Scanning drops by ~45% and the swap-out storm by ~9x: the reclaimers
stop hammering the shrinking anon LRU while the slow swap device is
still writing out the previous batches.  kswapd stays exempt.

Test 2, counters visible to compaction, same pressure plus
compact_memory in parallel:

                             before        after
nr_isolated peak                456         2232

The "before" 456 is compaction's own transient isolation; reclaim's
isolation is invisible.  With patch 1 it becomes visible to
compaction's too_many_isolated().  (Compaction's own throttling
threshold, (inactive + active) / 16, is about 25k pages on this box
and needs more pile-up than the box can generate; test 1 shows the
same too_many_isolated() check firing on the reclaim side.)

[1] https://gist.github.com/teawater/d3968aac92eb6bd1378beb54a82933f4

Changelog:
v4:
According to the commens of Baolin and Barry, rework patch 2:
drop the throttle_is_throttled() helper extracted
from shrink_inactive_list() and leave the legacy path untouched.
The new MGLRU-only throttle_evictable_types() only sleeps when all
evictable types are over-isolated - v3 throttled as soon as any of
them was, which unnecessarily blocked the reclaim of the other type
and passes the mask of the remaining types to isolate_folios(),
which restricts both its initial choice and its fallback, so that
isolation never lands on a throttled type.  The v3 gate did not
constrain the type actually isolated, so the fallback could still
pick the over-isolated one.
Re-run the tests and update the test log.
v3:
According to the commens of Baolin, remove the redundant nr_isolated
check before restoring the NR_ISOLATED_* counters in evict_folios().
rename the extracted helper to throttle_is_throttled() to avoid
confusion with the existing wake_throttle_isolated() naming space.
Use for_each_evictable_type() in the MGLRU throttle to check each
evictable type's isolation instead of only the type returned by
get_type_to_scan(), since isolate_folios() may fall back to the
other type.
Re-run the tests and update the test log.
v2:
According to the commens of Kairun, Rebased on mm-unstable.
Split into two patches; patch 2 is new and adds the
too_many_isolated() throttling to the MGLRU eviction path, which v1
did not cover.
Add test infomations.

Hui Zhu (2):
  mm/vmscan: fix missing NR_ISOLATED counter update in MGLRU reclaim
    path
  mm/vmscan: apply too_many_isolated() throttling to MGLRU eviction

 mm/vmscan.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 5 deletions(-)

-- 
2.53.0



             reply	other threads:[~2026-08-20  2:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20  2:48 Hui Zhu [this message]
2026-08-20  2:48 ` [PATCH mm-unstable v4 1/2] mm/vmscan: fix missing NR_ISOLATED counter update in MGLRU reclaim path Hui Zhu
2026-08-20  2:48 ` [PATCH mm-unstable v4 2/2] mm/vmscan: apply too_many_isolated() throttling to MGLRU eviction Hui Zhu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1787193916.git.zhuhui@kylinos.cn \
    --to=hui.zhu@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@kernel.org \
    --cc=qi.zheng@linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=weixugc@google.com \
    --cc=yuanchu@google.com \
    --cc=zhuhui@kylinos.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox