Skip to content

Commit 7a8e71b

Browse files
hygonitehcaster
authored andcommitted
mm/slab: use stride to access slabobj_ext
Use a configurable stride value when accessing slab object extension metadata instead of assuming a fixed sizeof(struct slabobj_ext). Store stride value in free bits of slab->counters field. This allows for flexibility in cases where the extension is embedded within slab objects. Since these free bits exist only on 64-bit, any future optimizations that need to change stride value cannot be enabled on 32-bit architectures. Suggested-by: Vlastimil Babka <vbabka@suse.cz> Reviewed-by: Suren Baghdasaryan <surenb@google.com> Signed-off-by: Harry Yoo <harry.yoo@oracle.com> Link: https://patch.msgid.link/20260113061845.159790-6-harry.yoo@oracle.com Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent 52f1ca8 commit 7a8e71b

2 files changed

Lines changed: 35 additions & 4 deletions

File tree

mm/slab.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ struct freelist_counters {
5555
* that the slab was corrupted
5656
*/
5757
unsigned frozen:1;
58+
#ifdef CONFIG_64BIT
59+
/*
60+
* Some optimizations use free bits in 'counters' field
61+
* to save memory. In case ->stride field is not available,
62+
* such optimizations are disabled.
63+
*/
64+
unsigned short stride;
65+
#endif
5866
};
5967
};
6068
};
@@ -529,6 +537,26 @@ static inline unsigned long slab_obj_exts(struct slab *slab)
529537
return obj_exts & ~OBJEXTS_FLAGS_MASK;
530538
}
531539

540+
#ifdef CONFIG_64BIT
541+
static inline void slab_set_stride(struct slab *slab, unsigned short stride)
542+
{
543+
slab->stride = stride;
544+
}
545+
static inline unsigned short slab_get_stride(struct slab *slab)
546+
{
547+
return slab->stride;
548+
}
549+
#else
550+
static inline void slab_set_stride(struct slab *slab, unsigned short stride)
551+
{
552+
VM_WARN_ON_ONCE(stride != sizeof(struct slabobj_ext));
553+
}
554+
static inline unsigned short slab_get_stride(struct slab *slab)
555+
{
556+
return sizeof(struct slabobj_ext);
557+
}
558+
#endif
559+
532560
/*
533561
* slab_obj_ext - get the pointer to the slab object extension metadata
534562
* associated with an object in a slab.
@@ -542,12 +570,9 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab,
542570
unsigned long obj_exts,
543571
unsigned int index)
544572
{
545-
struct slabobj_ext *obj_ext;
546-
547573
VM_WARN_ON_ONCE(obj_exts != slab_obj_exts(slab));
548574

549-
obj_ext = (struct slabobj_ext *)obj_exts;
550-
return &obj_ext[index];
575+
return (struct slabobj_ext *)(obj_exts + slab_get_stride(slab) * index);
551576
}
552577

553578
int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
@@ -567,6 +592,10 @@ static inline struct slabobj_ext *slab_obj_ext(struct slab *slab,
567592
return NULL;
568593
}
569594

595+
static inline void slab_set_stride(struct slab *slab, unsigned int stride) { }
596+
static inline unsigned int slab_get_stride(struct slab *slab) { return 0; }
597+
598+
570599
#endif /* CONFIG_SLAB_OBJ_EXT */
571600

572601
static inline enum node_stat_item cache_vmstat_idx(struct kmem_cache *s)

mm/slub.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,8 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
22062206
retry:
22072207
old_exts = READ_ONCE(slab->obj_exts);
22082208
handle_failed_objexts_alloc(old_exts, vec, objects);
2209+
slab_set_stride(slab, sizeof(struct slabobj_ext));
2210+
22092211
if (new_slab) {
22102212
/*
22112213
* If the slab is brand new and nobody can yet access its

0 commit comments

Comments
 (0)