public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH 0/2] fix kmem over-charging for embedded obj_exts array
@ 2026-03-10 11:38 ranxiaokai627
  2026-03-10 11:38 ` [PATCH 1/2] mm/slab: move obj_exts_in_slab() definition to slab.h ranxiaokai627
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: ranxiaokai627 @ 2026-03-10 11:38 UTC (permalink / raw)
  To: hannes, mhocko, roman.gushchin, shakeel.butt, muchun.song, akpm,
	vbabka, harry.yoo, hao.li, cl, rientjes
  Cc: cgroups, linux-mm, linux-kernel, ran.xiaokai, ranxiaokai627

From: Ran Xiaokai <ran.xiaokai@zte.com.cn>

Since commit a77d6d338685 ("mm/slab: place slabobj_ext metadata
in unused space within s->size"), the struct slabobj_ext array can
use slab leftover space or be embedded into the slub object to save
memory. In these cases, no extra kmalloc space is allocated for the
obj_exts array.

However, obj_full_size() always returns extra sizeof(struct obj_cgroup *)
bytes for every object, which leads to over-charging for slabs with
embedded obj_exts.

This series optimizes obj_full_size() to check whether obj_exts uses
slab leftover space or is embedded in the object. If so, only the object
size is charged. Otherwise, the extra obj_cgroup pointer space is also
charged.

Patch1 moves obj_exts_in_slab() definition to slab.h so it can be
       called from memcontrol.c.
Patch2 updates obj_full_size() to avoid over-charging.

Ran Xiaokai (2):
  mm/slab: move obj_exts_in_slab() definition to slab.h
  memcg: fix kmem over-charging for embedded obj_exts array

 mm/memcontrol.c | 19 ++++++++++++++-----
 mm/slab.h       | 19 +++++++++++++++++++
 mm/slub.c       | 19 -------------------
 3 files changed, 33 insertions(+), 24 deletions(-)

-- 
2.25.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] mm/slab: move obj_exts_in_slab() definition to slab.h
  2026-03-10 11:38 [PATCH 0/2] fix kmem over-charging for embedded obj_exts array ranxiaokai627
@ 2026-03-10 11:38 ` ranxiaokai627
  2026-03-10 11:38 ` [PATCH 2/2] memcg: fix kmem over-charging for embedded obj_exts array ranxiaokai627
  2026-03-11  2:13 ` [PATCH 0/2] " Harry Yoo
  2 siblings, 0 replies; 6+ messages in thread
From: ranxiaokai627 @ 2026-03-10 11:38 UTC (permalink / raw)
  To: hannes, mhocko, roman.gushchin, shakeel.butt, muchun.song, akpm,
	vbabka, harry.yoo, hao.li, cl, rientjes
  Cc: cgroups, linux-mm, linux-kernel, ran.xiaokai, ranxiaokai627

From: Ran Xiaokai <ran.xiaokai@zte.com.cn>

Move the definition of obj_exts_in_slab() to slab.h. This is in
preparation for the next patch, which needs to access this helper
from memcontrol.c.

No functional change intended.

Signed-off-by: Ran Xiaokai <ran.xiaokai@zte.com.cn>
---
 mm/slab.h | 19 +++++++++++++++++++
 mm/slub.c | 19 -------------------
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/mm/slab.h b/mm/slab.h
index 77242024e7d5..8354d5669ee7 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -597,6 +597,21 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab,
 	return kasan_reset_tag(obj_ext);
 }
 
+static inline bool obj_exts_in_slab(struct kmem_cache *s, struct slab *slab)
+{
+	unsigned long obj_exts;
+	unsigned long start;
+	unsigned long end;
+
+	obj_exts = slab_obj_exts(slab);
+	if (!obj_exts)
+		return false;
+
+	start = (unsigned long)slab_address(slab);
+	end = start + slab_size(slab);
+	return (obj_exts >= start) && (obj_exts < end);
+}
+
 int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
                         gfp_t gfp, bool new_slab);
 
@@ -617,6 +632,10 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab,
 static inline void slab_set_stride(struct slab *slab, unsigned int stride) { }
 static inline unsigned int slab_get_stride(struct slab *slab) { return 0; }
 
+static inline bool obj_exts_in_slab(struct kmem_cache *s, struct slab *slab)
+{
+	return false;
+}
 
 #endif /* CONFIG_SLAB_OBJ_EXT */
 
diff --git a/mm/slub.c b/mm/slub.c
index 1871c5ef354a..845a67736688 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -808,20 +808,6 @@ static inline bool obj_exts_fit_within_slab_leftover(struct kmem_cache *s,
 	return objext_offset + objext_size <= slab_size(slab);
 }
 
-static inline bool obj_exts_in_slab(struct kmem_cache *s, struct slab *slab)
-{
-	unsigned long obj_exts;
-	unsigned long start;
-	unsigned long end;
-
-	obj_exts = slab_obj_exts(slab);
-	if (!obj_exts)
-		return false;
-
-	start = (unsigned long)slab_address(slab);
-	end = start + slab_size(slab);
-	return (obj_exts >= start) && (obj_exts < end);
-}
 #else
 static inline bool need_slab_obj_exts(struct kmem_cache *s)
 {
@@ -845,11 +831,6 @@ static inline bool obj_exts_fit_within_slab_leftover(struct kmem_cache *s,
 	return false;
 }
 
-static inline bool obj_exts_in_slab(struct kmem_cache *s, struct slab *slab)
-{
-	return false;
-}
-
 #endif
 
 #if defined(CONFIG_SLAB_OBJ_EXT) && defined(CONFIG_64BIT)
-- 
2.25.1




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] memcg: fix kmem over-charging for embedded obj_exts array
  2026-03-10 11:38 [PATCH 0/2] fix kmem over-charging for embedded obj_exts array ranxiaokai627
  2026-03-10 11:38 ` [PATCH 1/2] mm/slab: move obj_exts_in_slab() definition to slab.h ranxiaokai627
@ 2026-03-10 11:38 ` ranxiaokai627
  2026-03-11  2:13 ` [PATCH 0/2] " Harry Yoo
  2 siblings, 0 replies; 6+ messages in thread
From: ranxiaokai627 @ 2026-03-10 11:38 UTC (permalink / raw)
  To: hannes, mhocko, roman.gushchin, shakeel.butt, muchun.song, akpm,
	vbabka, harry.yoo, hao.li, cl, rientjes
  Cc: cgroups, linux-mm, linux-kernel, ran.xiaokai, ranxiaokai627,
	stable

From: Ran Xiaokai <ran.xiaokai@zte.com.cn>

Since commit a77d6d338685 ("mm/slab: place slabobj_ext metadata
in unused space within s->size"), the struct slabobj_ext array
can use slab leftover space or be embedded into the slub object
to save memory by calling alloc_slab_obj_exts_early(). In these
cases, no extra kmalloc space is allocated to store the obj_exts array.

Optimize obj_full_size() behavior to avoid over-charging kmem
for objects whose obj_exts use slab leftover space or are embedded
in the object.

Fixes: a77d6d338685 ("mm/slab: place slabobj_ext metadata in unused space within s->size")
Cc: stable@vger.kernel.org
Signed-off-by: Ran Xiaokai <ran.xiaokai@zte.com.cn>
---
 mm/memcontrol.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 87614cfc4a3e..d6289a5cd6f3 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3199,11 +3199,20 @@ void obj_cgroup_uncharge(struct obj_cgroup *objcg, size_t size)
 	refill_obj_stock(objcg, size, true, 0, NULL, 0);
 }
 
-static inline size_t obj_full_size(struct kmem_cache *s)
+static inline size_t obj_full_size(struct kmem_cache *s, struct slab *slab)
 {
+	if (obj_exts_in_slab(s, slab)) {
+		/*
+		 * If obj_exts array uses slab leftover space or is embedded
+		 * in object, no extra space is allocated, just charge the
+		 * object size.
+		 */
+		return s->size;
+	}
+
 	/*
-	 * For each accounted object there is an extra space which is used
-	 * to store obj_cgroup membership. Charge it too.
+	 * For caches whose obj_exts array is allocated separately
+	 * outside of slab, also charge the objcg pointer.
 	 */
 	return s->size + sizeof(struct obj_cgroup *);
 }
@@ -3270,7 +3279,7 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
 		 * TODO: we could batch this until slab_pgdat(slab) changes
 		 * between iterations, with a more complicated undo
 		 */
-		if (obj_cgroup_charge_account(objcg, flags, obj_full_size(s),
+		if (obj_cgroup_charge_account(objcg, flags, obj_full_size(s, slab),
 					slab_pgdat(slab), cache_vmstat_idx(s)))
 			return false;
 
@@ -3289,7 +3298,7 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
 void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
 			    void **p, int objects, unsigned long obj_exts)
 {
-	size_t obj_size = obj_full_size(s);
+	size_t obj_size = obj_full_size(s, slab);
 
 	for (int i = 0; i < objects; i++) {
 		struct obj_cgroup *objcg;
-- 
2.25.1




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] fix kmem over-charging for embedded obj_exts array
  2026-03-10 11:38 [PATCH 0/2] fix kmem over-charging for embedded obj_exts array ranxiaokai627
  2026-03-10 11:38 ` [PATCH 1/2] mm/slab: move obj_exts_in_slab() definition to slab.h ranxiaokai627
  2026-03-10 11:38 ` [PATCH 2/2] memcg: fix kmem over-charging for embedded obj_exts array ranxiaokai627
@ 2026-03-11  2:13 ` Harry Yoo
  2026-03-11  3:06   ` Hao Li
  2 siblings, 1 reply; 6+ messages in thread
From: Harry Yoo @ 2026-03-11  2:13 UTC (permalink / raw)
  To: ranxiaokai627
  Cc: hannes, mhocko, roman.gushchin, shakeel.butt, muchun.song, akpm,
	vbabka, hao.li, cl, rientjes, cgroups, linux-mm, linux-kernel,
	ran.xiaokai

On Tue, Mar 10, 2026 at 11:38:02AM +0000, ranxiaokai627@163.com wrote:
> From: Ran Xiaokai <ran.xiaokai@zte.com.cn>
> 
> Since commit a77d6d338685 ("mm/slab: place slabobj_ext metadata
> in unused space within s->size"), the struct slabobj_ext array can
> use slab leftover space or be embedded into the slub object to save
> memory. In these cases, no extra kmalloc space is allocated for the
> obj_exts array.
> 
> However, obj_full_size() always returns extra sizeof(struct obj_cgroup *)
> bytes for every object, which leads to over-charging for slabs with
> embedded obj_exts.
> 
> This series optimizes obj_full_size() to check whether obj_exts uses
> slab leftover space or is embedded in the object. If so, only the object
> size is charged. Otherwise, the extra obj_cgroup pointer space is also
> charged.

Hi Ran,

At first look, I'm not sure if it's a good idea - although it's
allocated from wasted space, it's still memory that's needed to
charge objects.

But for "embedded into the slub object" case, yeah,
the metadata is charged twice, as it's already included in s->size.

Not having much expertise on memcg myself,
let's see what memcg folks say :)

> Patch1 moves obj_exts_in_slab() definition to slab.h so it can be
>        called from memcontrol.c.
> Patch2 updates obj_full_size() to avoid over-charging.
> 
> Ran Xiaokai (2):
>   mm/slab: move obj_exts_in_slab() definition to slab.h
>   memcg: fix kmem over-charging for embedded obj_exts array
> 
>  mm/memcontrol.c | 19 ++++++++++++++-----
>  mm/slab.h       | 19 +++++++++++++++++++
>  mm/slub.c       | 19 -------------------
>  3 files changed, 33 insertions(+), 24 deletions(-)
> 
> -- 
> 2.25.1
> 
> 
> 

-- 
Cheers,
Harry / Hyeonggon


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] fix kmem over-charging for embedded obj_exts array
  2026-03-11  2:13 ` [PATCH 0/2] " Harry Yoo
@ 2026-03-11  3:06   ` Hao Li
  2026-03-11  7:38     ` vbabka
  0 siblings, 1 reply; 6+ messages in thread
From: Hao Li @ 2026-03-11  3:06 UTC (permalink / raw)
  To: Harry Yoo
  Cc: ranxiaokai627, hannes, mhocko, roman.gushchin, shakeel.butt,
	muchun.song, akpm, vbabka, cl, rientjes, cgroups, linux-mm,
	linux-kernel, ran.xiaokai

On Wed, Mar 11, 2026 at 11:13:18AM +0900, Harry Yoo wrote:
> On Tue, Mar 10, 2026 at 11:38:02AM +0000, ranxiaokai627@163.com wrote:
> > From: Ran Xiaokai <ran.xiaokai@zte.com.cn>
> > 
> > Since commit a77d6d338685 ("mm/slab: place slabobj_ext metadata
> > in unused space within s->size"), the struct slabobj_ext array can
> > use slab leftover space or be embedded into the slub object to save
> > memory. In these cases, no extra kmalloc space is allocated for the
> > obj_exts array.
> > 
> > However, obj_full_size() always returns extra sizeof(struct obj_cgroup *)
> > bytes for every object, which leads to over-charging for slabs with
> > embedded obj_exts.
> > 
> > This series optimizes obj_full_size() to check whether obj_exts uses
> > slab leftover space or is embedded in the object. If so, only the object
> > size is charged. Otherwise, the extra obj_cgroup pointer space is also
> > charged.
> 
> Hi Ran,
> 
> At first look, I'm not sure if it's a good idea - although it's
> allocated from wasted space, it's still memory that's needed to
> charge objects.

Yes, I've been thinking about this as well.

For slabobj_ext that lives at the end of the whole slab, it seems reasonable to
charge it to the cgroup.

> 
> But for "embedded into the slub object" case, yeah,
> the metadata is charged twice, as it's already included in s->size.

While reading patch 2, I was also thinking about whether it would make sense to
call obj_exts_in_slab() on every object allocation and free for this case...

I wonder if we could use objext_flags to carry a bit of information about where
slabobj_ext is located.

-- 
Thanks,
Hao


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] fix kmem over-charging for embedded obj_exts array
  2026-03-11  3:06   ` Hao Li
@ 2026-03-11  7:38     ` vbabka
  0 siblings, 0 replies; 6+ messages in thread
From: vbabka @ 2026-03-11  7:38 UTC (permalink / raw)
  To: Hao Li, Harry Yoo
  Cc: ranxiaokai627, hannes, mhocko, roman.gushchin, shakeel.butt,
	muchun.song, akpm, cl, rientjes, cgroups, linux-mm, linux-kernel,
	ran.xiaokai

On 3/11/26 04:06, Hao Li wrote:
> On Wed, Mar 11, 2026 at 11:13:18AM +0900, Harry Yoo wrote:
>> On Tue, Mar 10, 2026 at 11:38:02AM +0000, ranxiaokai627@163.com wrote:
>> > From: Ran Xiaokai <ran.xiaokai@zte.com.cn>
>> > 
>> > Since commit a77d6d338685 ("mm/slab: place slabobj_ext metadata
>> > in unused space within s->size"), the struct slabobj_ext array can
>> > use slab leftover space or be embedded into the slub object to save
>> > memory. In these cases, no extra kmalloc space is allocated for the
>> > obj_exts array.
>> > 
>> > However, obj_full_size() always returns extra sizeof(struct obj_cgroup *)
>> > bytes for every object, which leads to over-charging for slabs with
>> > embedded obj_exts.
>> > 
>> > This series optimizes obj_full_size() to check whether obj_exts uses
>> > slab leftover space or is embedded in the object. If so, only the object
>> > size is charged. Otherwise, the extra obj_cgroup pointer space is also
>> > charged.
>> 
>> Hi Ran,
>> 
>> At first look, I'm not sure if it's a good idea - although it's
>> allocated from wasted space, it's still memory that's needed to
>> charge objects.
> 
> Yes, I've been thinking about this as well.
> 
> For slabobj_ext that lives at the end of the whole slab, it seems reasonable to
> charge it to the cgroup.
> 
>> 
>> But for "embedded into the slub object" case, yeah,
>> the metadata is charged twice, as it's already included in s->size.
> 
> While reading patch 2, I was also thinking about whether it would make sense to
> call obj_exts_in_slab() on every object allocation and free for this case...
> 
> I wonder if we could use objext_flags to carry a bit of information about where
> slabobj_ext is located.

Uh maybe let's not complicate it and just drop obj_full_size() altogether
and just charge s->size? Just accept that allocating slab objects has some
overhead, we're not accounting all of it fully anyway. It shouldn't cause a
big difference in practice.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-03-11  7:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 11:38 [PATCH 0/2] fix kmem over-charging for embedded obj_exts array ranxiaokai627
2026-03-10 11:38 ` [PATCH 1/2] mm/slab: move obj_exts_in_slab() definition to slab.h ranxiaokai627
2026-03-10 11:38 ` [PATCH 2/2] memcg: fix kmem over-charging for embedded obj_exts array ranxiaokai627
2026-03-11  2:13 ` [PATCH 0/2] " Harry Yoo
2026-03-11  3:06   ` Hao Li
2026-03-11  7:38     ` vbabka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox