From: Shakeel Butt <shakeel.butt@linux.dev>
To: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <muchun.song@linux.dev>,
Andrew Morton <akpm@linux-foundation.org>,
cgroups@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, kernel-team@meta.com
Subject: Re: [PATCH] mm/memcontrol: publish null pointer before dropping css reference
Date: Tue, 20 Oct 2026 14:21:22 -0700 [thread overview]
Message-ID: <atfMngq7nyZpt4u-@linux.dev> (raw)
In-Reply-To: <20261020193531.181318-1-joshua.hahnjy@gmail.com>
On Tue, Oct 20, 2026 at 12:35:31PM -0700, Joshua Hahn wrote:
> On Tue, 20 Oct 2026 12:03:38 -0700 Joshua Hahn <joshua.hahnjy@gmail.com> wrote:
>
[...]
> >
> > So for drain_local_memcg_stock I agree, since FLUSHING_CACHED_CHARGE
> > is set, so you can't have it concurrent with drain_all_stock since it
> > will skip that stock. But refill_stock also calls drain_stock when
> > it evicts the slot but the flag isn't set, so is_memcg_drain_needed
> > can read it at the same time.
> >
> > What do you think I should do? I think reordering makes the intent more
> > obvious and maybe it's just me but I did find it a bit misleading at
> > first that we were dropping the reference and then publishing.
>
> Oh and just for clarification, my page_counter_stock series actually
> gets rid of this codepath and switches the order when moving it anyways.
Yes but this patch has fixes and might get backported, so we need to be use it
is fixing an issue which is real.
Let's try to reason how the race can happen between is_memcg_drain_needed and
drain_stock:
CPU 1 CPU 2
drain_stock
WRITE_ONCE(stock->nr_pages[i], 0); is_memcg_drain_needed
css_put(&old->css);
/* assume full grace period */
rcu_read_lock()
memcg = READ_ONCE(stock->cached[i]);
if(READ_ONCE(stock->nr_pages[i])
mem_cgroup_is_descendant(memcg);
WRITE_ONCE(stock->cached[i], NULL);
Do you think there is possible race condition in above? I couldn't see.
However I ran this through AI and it has convinced me that on PREEMPT_RT, this
is indeed racy access.
AI reasoning:
-------------
How it breaks on PREEMPT_RT
On RT, local_trylock() takes a per-CPU spinlock_t (an rtmutex). That is
rcu_read_lock() plus migrate_disable(), but the task can still be preempted
inside it.
1. CPU A, refill_stock(X): there is no free slot, so it calls drain_stock(i) on
old. It sets nr_pages[i] = 0, then css_put(old) drops the last reference and
queues the release work on CPU A.
2. The refill task is preempted (by a tick or a threaded IRQ) before it clears
cached[i]. CPU A's kworker runs css_release_work_fn(), which calls call_rcu(),
and grace period G starts. G will wait for the refill task, because that task is
inside an RCU reader.
3. CPU B, drain_all_stock() → is_memcg_drain_needed(): B has already passed a
quiescent state for G. It enters rcu_read_lock() and loads cached[i] == old. G
does not wait for this reader, because it started after G did.
4. B is preempted right after that load (RT readers can be preempted).
5. A resumes. It clears cached[i], puts X in slot i with a non-zero nr_pages[i],
and unlocks. G ends, and old is freed.
6. B resumes. It reads X's non-zero count and calls
mem_cgroup_is_descendant(old, root). That reads old->css.cgroup from freed
memory.
next prev parent reply other threads:[~2026-10-20 21:21 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 16:56 [PATCH] mm/memcontrol: publish null pointer before dropping css reference Joshua Hahn
2026-10-20 18:13 ` Shakeel Butt
2026-10-20 19:03 ` Joshua Hahn
2026-10-20 19:35 ` Joshua Hahn
2026-10-20 21:21 ` Shakeel Butt [this message]
2026-10-20 22:03 ` Joshua Hahn
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=atfMngq7nyZpt4u-@linux.dev \
--to=shakeel.butt@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=cgroups@vger.kernel.org \
--cc=hannes@cmpxchg.org \
--cc=joshua.hahnjy@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@kernel.org \
--cc=muchun.song@linux.dev \
--cc=roman.gushchin@linux.dev \
/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