mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
mm/slab: stop allocating objcg pointers when unnecessary
Start using the slab_needs_objcg() helper to calculate slabobj_ext size. Caches that we know to never need objcg pointers (currently KMALLOC_NORMAL caches) will thus stop wasting memory on them when memory allocation profiling is enabled. For things to work properly, we need to also add slab_needs_objcg() checks to mem_cgroup_from_obj_slab() and memcg_slab_free_hook(), because when obj_exts array exists for a slab only due to mem_alloc profiling, we would otherwise attempt to access a non-existing objcg pointer in that slab. In slab_obj_ext_[set_]objcg() add debug warnings if called on a slab where slab_needs_objcg() is false. Reviewed-by: Hao Li <hao.li@linux.dev> Link: https://patch.msgid.link/20260727-b4-objext_split-v3-12-c29ef0f1f257@kernel.org Reviewed-by: Harry Yoo <harry@kernel.org> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
This commit is contained in:
parent
7def2e8549
commit
d4404b0f5b
|
|
@ -2871,6 +2871,9 @@ struct mem_cgroup *mem_cgroup_from_obj_slab(struct slab *slab, void *p)
|
|||
if (!obj_exts)
|
||||
return NULL;
|
||||
|
||||
if (!slab_needs_objcg(slab))
|
||||
return NULL;
|
||||
|
||||
get_slab_obj_exts(obj_exts);
|
||||
obj_ext = slab_obj_ext(slab->slab_cache, slab, obj_exts, p);
|
||||
objcg = slab_obj_ext_objcg(slab, obj_ext);
|
||||
|
|
|
|||
18
mm/slab.h
18
mm/slab.h
|
|
@ -615,7 +615,7 @@ static inline size_t cache_obj_ext_size(struct kmem_cache *s)
|
|||
{
|
||||
size_t sz = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MEMCG))
|
||||
if (cache_needs_objcg(s))
|
||||
sz += 1;
|
||||
|
||||
if (slab_obj_ext_has_codetag())
|
||||
|
|
@ -626,7 +626,15 @@ static inline size_t cache_obj_ext_size(struct kmem_cache *s)
|
|||
|
||||
static inline size_t slab_obj_ext_size(struct slab *slab)
|
||||
{
|
||||
return cache_obj_ext_size(slab->slab_cache);
|
||||
size_t sz = 0;
|
||||
|
||||
if (slab_needs_objcg(slab))
|
||||
sz += 1;
|
||||
|
||||
if (slab_obj_ext_has_codetag())
|
||||
sz += 1;
|
||||
|
||||
return sizeof(struct slabobj_ext) * sz;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SLAB_OBJ_EXT
|
||||
|
|
@ -738,6 +746,8 @@ slab_obj_ext(struct kmem_cache *s, struct slab *slab, unsigned long obj_exts,
|
|||
static inline struct obj_cgroup *
|
||||
slab_obj_ext_objcg(struct slab *slab, struct slabobj_ext *obj_ext)
|
||||
{
|
||||
VM_WARN_ON_ONCE(!slab_needs_objcg(slab));
|
||||
|
||||
/* if objcg exists, it comes first, so we don't need to do anything */
|
||||
return obj_ext->_objcg;
|
||||
}
|
||||
|
|
@ -746,6 +756,8 @@ static inline void
|
|||
slab_obj_ext_set_objcg(struct slab *slab, struct slabobj_ext *obj_ext,
|
||||
struct obj_cgroup *objcg)
|
||||
{
|
||||
VM_WARN_ON_ONCE(!slab_needs_objcg(slab));
|
||||
|
||||
/* if objcg exists, it comes first, so we don't need to do anything */
|
||||
obj_ext->_objcg = objcg;
|
||||
}
|
||||
|
|
@ -757,7 +769,7 @@ slab_obj_ext_codetag_ref(struct slab *slab, struct slabobj_ext *obj_ext)
|
|||
{
|
||||
VM_WARN_ON_ONCE(!slab_obj_ext_has_codetag());
|
||||
|
||||
if (IS_ENABLED(CONFIG_MEMCG))
|
||||
if (slab_needs_objcg(slab))
|
||||
obj_ext += 1;
|
||||
|
||||
return &obj_ext->_ctref;
|
||||
|
|
|
|||
|
|
@ -2513,6 +2513,9 @@ void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab, void **p,
|
|||
if (likely(!obj_exts))
|
||||
return;
|
||||
|
||||
if (!slab_needs_objcg(slab))
|
||||
return;
|
||||
|
||||
get_slab_obj_exts(obj_exts);
|
||||
__memcg_slab_free_hook(s, slab, p, objects, obj_exts);
|
||||
put_slab_obj_exts(obj_exts);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user