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: 14+ 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-05 21:21 ` kernel test robot
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
2026-09-06 1:40 ` [RFC PATCH] " kernel test robot
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.