From: Andrew Morton <akpm@linux-foundation.org>
To: Bo Zhang <zhangbo0325@gmail.com>
Cc: hannes@cmpxchg.org, baohua@kernel.org, kasong@tencent.com,
qi.zheng@linux.dev, shakeel.butt@linux.dev, david@kernel.org,
mhocko@kernel.org, ljs@kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, Bo Zhang <zhangbo56@xiaomi.com>
Subject: Re: [PATCH v2] mm: vmscan: avoid anon scanning for GFP_NOIO with low swapcache
Date: Sat, 5 Sep 2026 19:46:02 -0700 [thread overview]
Message-ID: <20260905194602.b88f549b9462033e40336db6@linux-foundation.org> (raw)
In-Reply-To: <20260906011820.382381-1-zhangbo56@xiaomi.com>
On Sun, 6 Sep 2026 09:18:20 +0800 Bo Zhang <zhangbo0325@gmail.com> wrote:
> We have observed some cases where memory is allocated with GFP_NOIO, so
> we cannot reclaim any anon folios unless they are in swapcache. We can
> end up spending more than 150 ms looping in `shrink_folio_list()` scanning
> non-swapcache folios without reclaiming a single folio. This is pure
> overhead.
>
> This is particularly true on systems using zRAM, where swapcache is
> relatively rare. So let's check whether anon reclaim is allowed by
> GFP_IO and whether there is enough swapcache to make it worthwhile. If
> the swapcache is extremely low, we're essentially searching for a
> needle in a haystack, so let's avoid scanning anon in the first place.
>
> On Android this is triggered by dm-verity hash-block reads through
> dm-bufio, which use GFP_NOIO:
>
> verity_verify_io -> verity_hash_for_block -> verity_verify_level
> -> dm_bufio_read_with_ioprio -> new_read -> __bufio_new
> -> alloc_buffer
> gfp: GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN
>
> Such a reclaimer can land on a memcg with a large, unswapped anon LRU and
> a tiny file LRU (e.g. inactive_anon ~335 MB vs inactive_file ~4 MB, with
> negligible swapcache). shrink_lruvec() then keeps feeding that huge anon
> list into shrink_folio_list() - ~2400 shrink_folio_list() calls, ~93,000
> anon folios scanned - where every folio is kept because it needs IO. The
> 150+ ms above is one such single shrink_lruvec() pass (not accumulated
> across a reclaim cycle), and it reclaims nothing; the actual progress
> comes entirely from the file side.
>
> Aging anon alongside file does have some value for a later __GFP_IO
> reclaimer, so it is not strictly pure overhead. But that aging is only
> deferred, not lost: kswapd and other __GFP_IO reclaimers still walk and
> age anon. Spending ~168 ms aging memory that this context cannot reclaim
> is not a worthwhile trade-off in a latency-sensitive path.
Thanks. That sounds like something we want to fix.
> To stay conservative, this only skips anon when the swapcache is really
> tiny - below 1/64 of the anon LRU - i.e. when essentially no anon on the
> list can be reclaimed without IO. Whenever there is a meaningful amount of
> swapcached anon, the normal path is used and anon is scanned and aged as
> before.
Argh. The thing about magic numbers is that they're always suboptimal
for everyone. But I understand that a full-on dynamic tuning setup is
a big project and hopefully not worthwhile. And yet another /proc knob
would require quite some justification.
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -362,6 +362,23 @@ static bool can_demote(int nid, struct scan_control *sc,
> return !nodes_empty(allowed_mask);
> }
>
> +static inline bool reclaimable_anon_is_low(struct mem_cgroup *memcg,
> + int nid, struct scan_control *sc)
> +{
> + struct lruvec *lruvec;
> + unsigned long anon_pages, swapcache;
> +
> + if (!sc || (sc->gfp_mask & __GFP_IO))
> + return false;
> +
> + lruvec = mem_cgroup_lruvec(memcg, NODE_DATA(nid));
> + anon_pages = lruvec_page_state(lruvec, NR_INACTIVE_ANON) +
> + lruvec_page_state(lruvec, NR_ACTIVE_ANON);
> + swapcache = lruvec_page_state(lruvec, NR_SWAPCACHE);
> +
> + return swapcache < (anon_pages >> 6);
> +}
I think this function deserves a comment. One which explains why isn't
doing what it does rather than what it does. That comment would
highlight the heuristic and explain the thinking behind it.
Also, AI review asks "does reclaimable_anon_is_low() incorrectly use
root memcg statistics instead of node-wide statistics during global
memory reclaim?".
https://sashiko.dev/#/patchset/20260906011820.382381-1-zhangbo56@xiaomi.com
next prev parent reply other threads:[~2026-09-06 2:46 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 4:01 [RFC PATCH] mm: vmscan: avoid anon scanning for GFP_NOIO with low swapcache Bo Zhang
2026-09-03 10:35 ` Barry Song
2026-09-03 12:49 ` Bo Zhang
2026-09-03 13:03 ` Johannes Weiner
2026-09-04 2:07 ` Bo Zhang
2026-09-04 16:38 ` Johannes Weiner
2026-09-06 1:18 ` [PATCH v2] " Bo Zhang
2026-09-06 2:46 ` Andrew Morton [this message]
2026-09-06 3:56 ` Bo Zhang
2026-09-06 4:53 ` Barry Song
2026-09-06 5:04 ` Bo Zhang
2026-09-06 5:49 ` Kairui Song
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=20260905194602.b88f549b9462033e40336db6@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--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=zhangbo0325@gmail.com \
--cc=zhangbo56@xiaomi.com \
/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