From: sashiko-bot@kernel.org
To: "Joshua Hahn" <joshua.hahnjy@gmail.com>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Shakeel Butt" <shakeel.butt@linux.dev>,
"Michal Hocko" <mhocko@kernel.org>,
"Michal Koutný" <mkoutny@suse.com>
Cc: "Roman Gushchin" <roman.gushchin@linux.dev>,
"Muchun Song" <muchun.song@linux.dev>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Kuniyuki Iwashima" <kuniyu@google.com>,
"Harry Yoo" <harry@kernel.org>,
"David Hildenbrand" <david@kernel.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Mike Rapoport" <rppt@kernel.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Maarten Lankhorst" <dev@lankhorst.se>,
"Maxime Ripard" <mripard@kernel.org>,
"Natalie Vock" <nat@pixelcluster.dev>,
"Tejun Heo" <tj@kernel.org>, "Oscar Salvador" <osalvador@suse.de>,
linux-mm@kvack.org, kernel-team@meta.com
Subject: Re: [PATCH v8 7/7] mm/memcontrol: restrict memory stock to leaf cgroups on v2
Date: Thu, 05 Nov 2026 23:31:05 +0000 [thread overview]
Message-ID: <sashiko-outbox-200379@kernel.org> (raw)
In-Reply-To: <20261104233029.3282438-8-joshua.hahnjy@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mm: foreign slot drain on fast path in page_counter_consume_stock()
--
commit 4a3e7ea8b6bee1d8310dd3c42d8ad7c15aae3cf4
Author: Joshua Hahn <joshua.hahnjy@gmail.com>
mm/memcontrol: restrict memory stock to leaf cgroups on v2
This commit disables memory page_counter stock on cgroup v2 non-leaf cgroups
when they gain a child, schedules per-CPU stock drains for online CPUs, and
lazily drains any remaining disabled cached counters during stock consumption.
When a parent cgroup becomes a leaf again on child offlining, its memory stock
is re-enabled.
> diff --git a/mm/page_counter.c b/mm/page_counter.c
> index e1feb2bd1e225..7a3b7cea0ff94 100644
> --- a/mm/page_counter.c
> +++ b/mm/page_counter.c
> @@ -158,6 +158,7 @@ static void page_counter_drain_stock(struct page_counter_stock_pcp *stock,
> * Consume the cached charge if enough nr_pages are present, otherwise return
> * failure. Also return failure for charge requests larger than
> * PAGE_COUNTER_STOCK_BATCH or if the local lock is already taken.
> + * Drain disabled cached counters while looking up the requested counter.
> */
> static bool page_counter_consume_stock(struct page_counter *counter,
> unsigned long nr_pages)
> @@ -176,12 +177,17 @@ static bool page_counter_consume_stock(struct page_counter *counter,
> for (i = 0; i < NR_PAGE_COUNTER_STOCK; i++) {
> struct page_counter *cached = pcp_stock->cached[i];
>
> + /* Drain any stock that is disabled but hasn't drained yet */
> + if (cached && !READ_ONCE(cached->stock)) {
> + page_counter_drain_stock(pcp_stock, i);
> + continue;
> + }
> if (counter != cached)
> continue;
[Severity: High]
Can draining an unrelated disabled slot in page_counter_consume_stock()
acquire spinning locks from an NMI or alloc_pages_nolock() context, and also
add foreign cacheline loads to every fast-path stock hit?
In mm/memcontrol.c:try_charge_memcg(), may_batch is set to false when
!gfpflags_allow_spinning(gfp_mask) so that charges from non-spinning contexts
such as alloc_pages_nolock(__GFP_ACCOUNT, ...) do not evict other stock slots
or take spinning locks:
mm/memcontrol.c:try_charge_memcg() {
bool allow_spinning = gfpflags_allow_spinning(gfp_mask);
/* Charges from reclaim or non-spinning contexts don't batch. */
bool may_batch = allow_spinning && !(current->flags & PF_MEMALLOC);
}
However, mm/page_counter.c:page_counter_try_charge() calls
page_counter_consume_stock() unconditionally before checking may_batch:
mm/page_counter.c:page_counter_try_charge() {
retry:
if (page_counter_consume_stock(counter, nr_pages)) {
if (nr_charged)
*nr_charged = 0;
return true;
}
}
For the counter being charged (counter == cached), the caller holds an active
CSS reference, so css_put(counter->stock_css) when depleting the matching slot
cannot drop the final CSS reference.
For an unrelated counter in pcp_stock->cached[i] (cached != counter) whose
stock was disabled via mem_cgroup_disable_stock(), the charging caller holds
no reference to cached->stock_css. If that cgroup and its child were
subsequently removed while its per-CPU stock slot remained populated (for
example on an isolated CPU where schedule_drain_work() returns false, or
after a racing refill or contended mutex_trylock(&percpu_charge_mutex) in
drain_all_stock()), pcp_stock->cached[i] can hold the final reference to a
dying CSS after css_killed_work_fn() completes.
If an NMI or non-spinning caller on that CPU then runs:
alloc_pages_nolock(__GFP_ACCOUNT, ...)
-> __memcg_kmem_charge_page()
-> obj_cgroup_charge_pages()
-> try_charge_memcg()
-> page_counter_try_charge()
-> page_counter_consume_stock()
-> page_counter_drain_stock()
-> css_put(counter->stock_css)
-> css_release()
-> queue_work(cgroup_release_wq, &css->destroy_work)
wouldn't queue_work() spin on workqueue pool and scheduler locks in a context
where spinning is forbidden?
In addition, the commit message notes that lazy cleanup happens on the next
local stock miss ("The next local stock miss on that CPU scans for any stock
that has been disabled, and will drain its stock"). Because the
!READ_ONCE(cached->stock) check is placed before the counter != cached check
inside page_counter_consume_stock(), every fast-path stock hit at index i will
also dereference cached->stock across foreign struct page_counter cachelines
for slots 0..i and drain any disabled slots before i while holding
stock->lock.
Should the lazy cleanup of disabled slots be moved to
page_counter_refill_stock() (which only runs on a stock miss when may_batch is
true and gfpflags_allow_spinning(gfp_mask) holds), while
page_counter_consume_stock() only checks counter == cached?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261104233029.3282438-1-joshua.hahnjy@gmail.com?part=7
next prev parent reply other threads:[~2026-11-05 23:31 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 23:30 [PATCH v8 0/7] mm/page_counter: move stock from mem_cgroup to page_counter Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 1/7] mm/memcontrol: flatten try_charge_memcg control flow Joshua Hahn
2026-11-05 6:08 ` Balbir Singh
2026-11-04 23:30 ` [PATCH v8 2/7] mm/page_counter: introduce per-CPU stock Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 3/7] mm/page_counter: make page_counter_try_charge() stock-aware Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 4/7] mm/memcontrol: check PF_MEMALLOC after trying the limits Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 5/7] mm/memcontrol: move memory stock to page counters Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 6/7] mm/memcontrol: add stock to the memsw page counter Joshua Hahn
2026-11-04 23:30 ` [PATCH v8 7/7] mm/memcontrol: restrict memory stock to leaf cgroups on v2 Joshua Hahn
2026-11-05 23:31 ` sashiko-bot [this message]
2026-11-05 6:17 ` [PATCH v8 0/7] mm/page_counter: move stock from mem_cgroup to page_counter Balbir Singh
2026-11-05 14:50 ` Joshua Hahn
2026-11-06 10:07 ` Balbir Singh
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=sashiko-outbox-200379@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=dev@lankhorst.se \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=joshua.hahnjy@gmail.com \
--cc=kernel-team@meta.com \
--cc=kuniyu@google.com \
--cc=liam@infradead.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@kernel.org \
--cc=mkoutny@suse.com \
--cc=mripard@kernel.org \
--cc=muchun.song@linux.dev \
--cc=nat@pixelcluster.dev \
--cc=osalvador@suse.de \
--cc=roman.gushchin@linux.dev \
--cc=rppt@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=tj@kernel.org \
--cc=vbabka@kernel.org \
/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