From: Johannes Weiner <hannes@cmpxchg.org>
To: Bo Zhang <zhangbo0325@gmail.com>
Cc: akpm@linux-foundation.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, zhangbo56@xiaomi.com
Subject: Re: [RFC PATCH] mm: vmscan: avoid anon scanning for GFP_NOIO with low swapcache
Date: Fri, 4 Sep 2026 12:38:54 -0400 [thread overview]
Message-ID: <20260904163854.GE6641@cmpxchg.org> (raw)
In-Reply-To: <20260904020756.4163139-1-zhangbo56@xiaomi.com>
On Fri, Sep 04, 2026 at 10:07:56AM +0800, Bo Zhang wrote:
> On Thu, Sep 03, 2026 at 09:03:04AM -0400, Johannes Weiner wrote:
> > On Thu, Sep 03, 2026 at 12:01:31PM +0800, Bo Zhang 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.
> >
> > Not entirely. There is some value in aging anon alongside file, so
> > that the next __GFP_IO reclaimer doesn't look at a stale list.
>
> You're right, "pure overhead" was too strong - aging anon does have
> value for a later __GFP_IO reclaimer, and I don't intend to skip it in
> general. Let me describe the case in full, because the reclaim cycle
> itself already provides that aging on a later pass, which is what makes
> me think the trade-off here leans the other way.
>
> > Can you describe a bit more about what you observed? What workload is
> > running, maybe you have a stack trace of which NOIO requests are
> > routinely getting stuck in reclaim?
>
> The workload is app launching on Android. The NOIO allocations come from
> dm-verity hash-block reads via dm-bufio, which legitimately use GFP_NOIO
> because they run underneath the IO path:
>
> worker_thread
> process_scheduled_works
> verity_work
> verity_verify_io
> verity_hash_for_block
> verity_verify_level
> dm_bufio_read_with_ioprio
> new_read
> __bufio_new
> alloc_buffer
> gfp_mask: GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN
>
> So the NOIO use itself is correct; the problem is on the reclaim side.
Ack.
> Here is the full picture of one such direct reclaim. It runs two rounds
> of do_try_to_free_pages(); the target is 32 folios.
>
> Round 1 - partial (shared) memcg walk, 169.20 ms, 0 folios reclaimed
> --------------------------------------------------------------------
> prio 12->1 (~1.3 ms):
> cache_trim_mode is on, so get_scan_count() picks SCAN_FILE. Only the
> file side is scanned. Because this is a shared/partial walk, each
> priority only visits a handful of memcgs before the iterator is
> handed off, so very few memcgs are looked at on the way down:
> 428 file folios scanned, 0 reclaimed.
>
> prio 0 (~167.9 ms):
> priority hits 0 without meeting the target, so get_scan_count()
> forces SCAN_EQUAL. The walk lands on a single memcg with a large,
> unswapped anon LRU and a tiny file LRU:
>
> inactive_anon ~335 MB, inactive_file ~4 MB (~84:1)
> memcg swap usage ~3.6 MB, so swapcache is negligible
>
> shrink_lruvec() now keeps feeding that huge anon list into
> shrink_folio_list() - ~2400 shrink_folio_list() calls, ~93,000 anon
> folios scanned - and every folio hits the !__GFP_IO keep_locked path
> (not in swapcache, needs a swap slot). This single shrink_lruvec()
> pass alone is ~168 ms with 0 folios reclaimed.
Ack. Thanks for the rich explanation, this is illuminating.
Agree with your fix. This GFP_NOIO just has to get through the day,
and aging 90% of memory it cannot reclaim is an unreasonable side
quest. Leave it to kswapd and the other reclaimers.
next prev parent reply other threads:[~2026-09-04 16:39 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 [this message]
2026-09-06 1:18 ` [PATCH v2] " Bo Zhang
2026-09-06 2:46 ` Andrew Morton
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=20260904163854.GE6641@cmpxchg.org \
--to=hannes@cmpxchg.org \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=david@kernel.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