Use a configurable stride value when accessing slab object extension metadata instead of assuming a fixed sizeof(struct slabobj_ext). Store stride value in the lower 16 bits of struct slab.__page_type. This allows for flexibility in cases where the extension is embedded within slab objects. Suggested-by: Vlastimil Babka Signed-off-by: Harry Yoo --- mm/slab.h | 18 ++++++++++++++---- mm/slub.c | 2 ++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mm/slab.h b/mm/slab.h index 4eb63360fdb5..3bded6bd0152 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -540,6 +540,15 @@ static inline unsigned long slab_obj_exts(struct slab *slab) return obj_exts & ~OBJEXTS_FLAGS_MASK; } +static inline void slab_set_stride(struct slab *slab, unsigned int stride) +{ + slab->__page_type |= stride; +} +static inline unsigned int slab_get_stride(struct slab *slab) +{ + return slab->__page_type & USHRT_MAX; +} + /* * slab_obj_ext - get the pointer to the slab object extension metadata * associated with an object in a slab. @@ -553,13 +562,10 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab, unsigned long obj_exts, unsigned int index) { - struct slabobj_ext *obj_ext; - VM_WARN_ON_ONCE(!slab_obj_exts(slab)); VM_WARN_ON_ONCE(obj_exts != slab_obj_exts(slab)); - obj_ext = (struct slabobj_ext *)obj_exts; - return &obj_ext[index]; + return (struct slabobj_ext *)(obj_exts + slab_get_stride(slab) * index); } int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, @@ -578,6 +584,10 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab, return NULL; } +static inline void slab_set_stride(struct slab *slab, unsigned int stride) { } +static inline unsigned int slab_get_stride(struct slab *slab) { return 0; } + + #endif /* CONFIG_SLAB_OBJ_EXT */ static inline enum node_stat_item cache_vmstat_idx(struct kmem_cache *s) diff --git a/mm/slub.c b/mm/slub.c index 33e2692ca618..b80bf3a24ab9 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2107,6 +2107,8 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, #endif old_exts = READ_ONCE(slab->obj_exts); handle_failed_objexts_alloc(old_exts, vec, objects); + slab_set_stride(slab, sizeof(struct slabobj_ext)); + if (new_slab) { /* * If the slab is brand new and nobody can yet access its -- 2.43.0