Re: [PATCH RFC 11/12] mm/slab: add slab_needs_objcg() helper
From: Suren Baghdasaryan
Date: Thu Jul 16 2026 - 00:39:20 EST
On Wed, Jul 15, 2026 at 3:11 AM Vlastimil Babka (SUSE)
<vbabka@xxxxxxxxxx> wrote:
>
> Slabs of some caches never need the objcg part of struct slabobj_ext.
> Introduce a helper to query this for a slab.
>
> Currently only is_kmalloc_normal() caches are considered as not needing
> objcg's. We could also consider all kmem caches without SLAB_ACCOUNT,
> however some might be used with and without __GFP_ACCOUNT concurrently
> and we currently don't restrict that. This can be improved later.
>
> To make the evaluation of slab_needs_objcg() faster in the allocation
> and free fast paths, add a obj_exts_needs_objcg flag into slab itself.
> This optimization is only available on 64bit architectures where free
> bits are available for the flag.
>
> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@xxxxxxxxxx>
Reviewed-by: Suren Baghdasaryan <surenb@xxxxxxxxxx>
> ---
> mm/kfence/core.c | 3 +++
> mm/slab.h | 31 +++++++++++++++++++++++++++++--
> mm/slub.c | 4 ++++
> 3 files changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/mm/kfence/core.c b/mm/kfence/core.c
> index 717e8baf7e5d..afeaf80484ad 100644
> --- a/mm/kfence/core.c
> +++ b/mm/kfence/core.c
> @@ -640,6 +640,9 @@ static unsigned long kfence_init_pool(void)
> struct slab *slab = page_slab(page);
> slab->obj_exts = (unsigned long)&kfence_metadata_init[i / 2 - 1].obj_exts |
> MEMCG_DATA_OBJEXTS;
> +#ifdef CONFIG_64BIT
> + slab->obj_exts_needs_objcg = 1;
> +#endif
> #endif
> }
>
> diff --git a/mm/slab.h b/mm/slab.h
> index a50347c9dbe3..948d075cdbef 100644
> --- a/mm/slab.h
> +++ b/mm/slab.h
> @@ -81,10 +81,11 @@ struct freelist_counters {
> #ifdef CONFIG_64BIT
> /*
> * Some optimizations use free bits in 'counters' field
> - * to save memory. If these free bits are not available,
> - * such optimizations are disabled.
> + * to save memory or CPU. If these free bits are not
> + * available, such optimizations are disabled.
> */
> unsigned obj_exts_in_object:1;
> + unsigned obj_exts_needs_objcg:1;
> #endif
> };
> };
> @@ -580,6 +581,32 @@ static inline bool slab_obj_ext_has_codetag(void)
> }
> #endif
>
> +#ifdef CONFIG_MEMCG
> +static inline bool cache_needs_objcg(struct kmem_cache *cache)
> +{
> + return !is_kmalloc_normal(cache);
> +}
> +
> +static inline bool slab_needs_objcg(struct slab *slab)
> +{
> +#ifdef CONFIG_64BIT
> + return slab->obj_exts_needs_objcg;
> +#else
> + return cache_needs_objcg(slab->slab_cache);
> +#endif
> +}
> +#else
> +static inline bool cache_needs_objcg(struct kmem_cache *cache)
> +{
> + return false;
> +}
> +
> +static inline bool slab_needs_objcg(struct slab *slab)
> +{
> + return false;
> +}
> +#endif
> +
> static inline size_t static_obj_ext_size(void)
> {
> size_t sz = 0;
> diff --git a/mm/slub.c b/mm/slub.c
> index 4200e7105b30..771d73abacb6 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -3426,6 +3426,10 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags,
>
> slab->objects = oo_objects(oo);
>
> +#ifdef CONFIG_64BIT
> + if (cache_needs_objcg(s))
> + slab->obj_exts_needs_objcg = 1;
> +#endif
> slab->slab_cache = s;
>
> kasan_poison_slab(slab);
>
> --
> 2.55.0
>