From: Shakeel Butt <shakeel.butt@linux.dev>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <muchun.song@linux.dev>,
Qi Zheng <qi.zheng@linux.dev>, Alexandre Ghiti <alex@ghiti.fr>,
Joshua Hahn <joshua.hahnjy@gmail.com>,
Harry Yoo <harry@kernel.org>,
David Laight <david.laight.linux@gmail.com>,
Meta kernel team <kernel-team@meta.com>,
linux-mm@kvack.org, cgroups@vger.kernel.org,
linux-kernel@vger.kernel.org,
kernel test robot <oliver.sang@intel.com>
Subject: [PATCH v3 2/4] memcg: uint16_t for nr_bytes in obj_stock_pcp
Date: Mon, 25 May 2026 20:39:29 -0700 [thread overview]
Message-ID: <20260526033931.1760588-3-shakeel.butt@linux.dev> (raw)
In-Reply-To: <20260526033931.1760588-1-shakeel.butt@linux.dev>
Currently struct obj_stock_pcp stores nr_bytes in an 'unsigned int'
which is 4 bytes on 64-bit machines. Switch the field to uint16_t to
shrink the per-CPU cache.
The kernel supports PAGE_SIZE_4KB, _8KB, _16KB, _32KB, _64KB and
_256KB (see HAVE_PAGE_SIZE_* in arch/Kconfig). After the
PAGE_SIZE-aligned flush in __refill_obj_stock(), the sub-page
remainder fits in uint16_t up through 64KiB pages where PAGE_SIZE - 1
== U16_MAX, but on 256KiB pages PAGE_SIZE - 1 == 0x3FFFF exceeds
U16_MAX. The accumulator also needs to stay within uint16_t between
page-aligned flushes on 64KiB pages where PAGE_SIZE itself is
U16_MAX + 1.
Accumulate the new total in an 'unsigned int' local, then on
PAGE_SHIFT <= 16 flush whenever the accumulator would hit U16_MAX;
together with the existing allow_uncharge flush at PAGE_SIZE this
keeps the uint16_t safe.
On configs with PAGE_SHIFT > 16 (PAGE_SIZE_256KB on hexagon and
powerpc 44x, both 32-bit), uint16_t cannot represent the sub-page
remainder. Define obj_stock_bytes_t as 'unsigned int' on those
archs so nr_bytes can hold the full remainder and the normal
page-boundary flush in __refill_obj_stock() and the page extraction
in drain_obj_stock() both work correctly.
The single-cache-line layout target only applies to PAGE_SHIFT <= 16;
those archs are 32-bit embedded and not the optimization target.
Fixes: 01b9da291c49 ("mm: memcontrol: convert objcg to be per-memcg per-node type")
Tested-by: kernel test robot <oliver.sang@intel.com>
Reviewed-by: Harry Yoo (Oracle) <harry@kernel.org>
Acked-by: Qi Zheng <qi.zheng@linux.dev>
Acked-by: Muchun Song <muchun.song@linux.dev>
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
---
Changes since v2:
- Based on Sashiko's concern regarding archs with 256KiB base pages, added
special handling for such arch and simplify the code overall.
- Updated commit message.
- Have kept the review tags as overall code remains same mostly.
Changes since v1:
- Collected tags
- Rearrange fields of obj_stock_pcp (David Laight)
- Fix comparison operator (Harry)
mm/memcontrol.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 9bee9031171f..8c1b65e6da5d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2020,8 +2020,17 @@ static DEFINE_PER_CPU_ALIGNED(struct memcg_stock_pcp, memcg_stock) = {
struct obj_stock_pcp {
local_trylock_t lock;
- unsigned int nr_bytes;
struct obj_cgroup *cached_objcg;
+#if PAGE_SHIFT > 16
+ /*
+ * On rare archs with 256KiB base page size (hexagon and powerpc 44x)
+ * keep nr_bytes to unsigned int as uint16_t cannot represent the full
+ * sub-page remainder.
+ */
+ unsigned int nr_bytes;
+#else
+ uint16_t nr_bytes;
+#endif
int16_t node_id;
int nr_slab_reclaimable_b;
int nr_slab_unreclaimable_b;
@@ -3334,6 +3343,7 @@ static void __refill_obj_stock(struct obj_cgroup *objcg,
bool allow_uncharge)
{
unsigned int nr_pages = 0;
+ unsigned int stock_nr_bytes;
if (!stock) {
nr_pages = nr_bytes >> PAGE_SHIFT;
@@ -3342,21 +3352,24 @@ static void __refill_obj_stock(struct obj_cgroup *objcg,
goto out;
}
+ stock_nr_bytes = stock->nr_bytes;
if (READ_ONCE(stock->cached_objcg) != objcg) { /* reset if necessary */
drain_obj_stock(stock);
obj_cgroup_get(objcg);
- stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
+ stock_nr_bytes = atomic_read(&objcg->nr_charged_bytes)
? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
WRITE_ONCE(stock->cached_objcg, objcg);
allow_uncharge = true; /* Allow uncharge when objcg changes */
}
- stock->nr_bytes += nr_bytes;
+ stock_nr_bytes += nr_bytes;
- if (allow_uncharge && (stock->nr_bytes > PAGE_SIZE)) {
- nr_pages = stock->nr_bytes >> PAGE_SHIFT;
- stock->nr_bytes &= (PAGE_SIZE - 1);
+ if ((allow_uncharge && (stock_nr_bytes > PAGE_SIZE)) ||
+ stock_nr_bytes > U16_MAX) {
+ nr_pages = stock_nr_bytes >> PAGE_SHIFT;
+ stock_nr_bytes &= (PAGE_SIZE - 1);
}
+ stock->nr_bytes = stock_nr_bytes;
out:
if (nr_pages)
--
2.53.0-Meta
next prev parent reply other threads:[~2026-05-26 3:40 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-26 3:39 [PATCH v3 0/4] memcg: shrink obj_stock_pcp and cache multiple objcgs Shakeel Butt
2026-05-26 3:39 ` [PATCH v3 1/4] memcg: store node_id instead of pglist_data pointer Shakeel Butt
2026-05-26 3:39 ` Shakeel Butt [this message]
2026-05-26 3:39 ` [PATCH v3 3/4] memcg: int16_t for cached slab stats Shakeel Butt
2026-05-26 3:39 ` [PATCH v3 4/4] memcg: multi objcg charge support Shakeel Butt
2026-05-26 5:44 ` Harry Yoo
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=20260526033931.1760588-3-shakeel.butt@linux.dev \
--to=shakeel.butt@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=alex@ghiti.fr \
--cc=cgroups@vger.kernel.org \
--cc=david.laight.linux@gmail.com \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.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=oliver.sang@intel.com \
--cc=qi.zheng@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 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.