From: Joshua Hahn <joshua.hahnjy@gmail.com>
To: "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>,
cgroups@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, kernel-team@meta.com
Subject: [PATCH v8 0/7] mm/page_counter: move stock from mem_cgroup to page_counter
Date: Wed, 4 Nov 2026 15:30:21 -0800 [thread overview]
Message-ID: <20261104233029.3282438-1-joshua.hahnjy@gmail.com> (raw)
v7 --> v8
=========
- Rebase onto mm-new as of 11/03/2026. This picks up two memcg series
that required some rework:
- Kuniyuki Iwashima's memcg stock cleanups were worked into the
series, so the changes now live in page_counter code instead.
- Shakeel Butt's memory.high rework. Commit 4/7 folds in his
PF_MEMALLOC change into the page_counter checks. This change was
suggested by Shakeel.
- Commit 7/7 is new. It brings back an optimization from an earlier
version of the series to let stock charge only accumulate on leaf
cgroups.
- To accommodate this change, sprinkle in READ_ONCE() for
counter->stock reads since the pointer can change at runtime now.
- Cover letter rework as suggested by Michal Hocko.
INTRODUCTION
============
Memcg keeps a per-CPU stock of precharged pages so that small and
frequent allocations do not walk the page_counter hierarchy every time.
Today, the stock implementation lives in memcontrol code, even though
the operation it caches is a page_counter charge. This makes it
difficult to add new page_counters to a memcg and preserve the fast path
behavior.
This series moves the stock into the page_counter layer.
page_counter_try_charge() consumes the stock, charges a batch to the
hierarchy on a miss, and refills the stock with the surplus. Memcg no
longer manages the stock in try_charge_memcg.
So the stock keeps the existing layout, which is still a per-CPU bank
of 7 slots, each holding a count of precharged pages that it hands out.
It maintains exclusion using local locks on each CPU, and for remote
drains we schedule on the memcg workqueue.
This change gives us the following benefits:
- Separate charge caching (page_counter) from charge policy (memcg).
- Makes it simple to keep stock out of interior cgroups on cgroup v2.
- Prepares for future work for stock improvement, which can now be
isolated from memcg changes.
With this change, make sure to preserve:
- All locking behavior is unchanged from before.
- Non-leaf cgroups do not hold stock. Specifically, their stock is
drained when they become a parent, and remaining stock (isolated CPUs,
concurrent refills, etc.) gets drained lazily on future stock misses.
- Exact charging for non-spinning callers.
- Stocks only exist for the memory and memsw page_counters as before.
Other page_counters (swap, v1 kmem, v1 tcpmem, hugetlb_cgroup, dmem)
don't stock as before.
EFFECT ON CGROUP V2 USERS
=========================
Currently when a cgroup becomes a parent, it doesn't drain the stock.
Rather, it just prevents new charges from accumulating by nature of
parent cgroups not having processes. Here, we can do a little better.
When a cgroup becomes a parent, schedule drains right away, in addition
to making sure parents don't accumulate new charges.
Everything else is preserved. We preserve all draining, refilling,
and (un)charging behavior, including the uncharge path's refills
and direct uncharges.
EFFECT ON CGROUP V1 USERS
=========================
The memory and memsw counters now have separate stocks, which can hit,
evict, and drain independently. Their raw values can therefore drift
apart by the stocked amounts, even though every charge is applied to
both.
To preserve the user-visible property that
memory.usage_in_bytes <= memory.memsw.usage_in_bytes, the memory
value reports the smaller of the two values. Both raw values are already
upper bounds on real usage, so this stays within the fuzz that
usage_in_bytes always had (and this is also already documented, see
section 5.5 usage_in_bytes in Documentation/admin-guide/cgroup-v1/
memory.rst).
TESTING
=======
This series should not have big changes to performance, so I ran some
benchmarks to verify that. I did testing on a 16-CPU, 32G machine VM.
I ran repeated anonymous memory faults and MADV_DONTNEED to measure the
CPU time spent per page. So + number is worse. I ran each experiment
5 times, with 4 workers.
+-----------+-----------+--------------+-------+
| | base (ns) | patched (ns) | delta |
+-----------+-----------+--------------+-------+
| cgroup v1 | 890.6 | 901.8 | +1.2% |
| cgroup v2 | 893.5 | 902.2 | +1.0% |
+-----------+-----------+--------------+-------+
Based on mm-new as of 11/03/26:
74d73ffcffe03 "riscv: mm: fix concurrency in mark_new_valid_map()"
Joshua Hahn (7):
mm/memcontrol: flatten try_charge_memcg control flow
mm/page_counter: introduce per-CPU stock
mm/page_counter: make page_counter_try_charge() stock-aware
mm/memcontrol: check PF_MEMALLOC after trying the limits
mm/memcontrol: move memory stock to page counters
mm/memcontrol: add stock to the memsw page counter
mm/memcontrol: restrict memory stock to leaf cgroups on v2
include/linux/page_counter.h | 35 ++-
kernel/cgroup/dmem.c | 2 +-
mm/hugetlb_cgroup.c | 2 +-
mm/memcontrol-v1.c | 17 +-
mm/memcontrol.c | 430 +++++++++++++----------------------
mm/page_counter.c | 233 ++++++++++++++++++-
6 files changed, 430 insertions(+), 289 deletions(-)
--
2.53.0-Meta
next reply other threads:[~2026-11-04 23:30 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 23:30 Joshua Hahn [this message]
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 6:17 ` [PATCH v8 0/7] mm/page_counter: move stock from mem_cgroup to page_counter 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=20261104233029.3282438-1-joshua.hahnjy@gmail.com \
--to=joshua.hahnjy@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cgroups@vger.kernel.org \
--cc=david@kernel.org \
--cc=dev@lankhorst.se \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=kernel-team@meta.com \
--cc=kuniyu@google.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.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=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
all inboxes | Powered by JetHome®