summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorHarry Yoo <harry.yoo@oracle.com>2026-01-13 15:18:41 +0900
committerVlastimil Babka <vbabka@suse.cz>2026-02-04 10:05:35 +0100
commit7a8e71bc619d34c7607adef0e368d10421b7d4f6 (patch)
treecd8a066f1ebd537609f228706f1b27af6ea9ce9f /mm
parent52f1ca8a459a73cf423a0b71b59f0b950e522cab (diff)
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>
Diffstat (limited to 'mm')
-rw-r--r--mm/slab.h37
-rw-r--r--mm/slub.c2
2 files changed, 35 insertions, 4 deletions
diff --git a/mm/slab.h b/mm/slab.h
index 4935602b3fce..be0e62c98da0 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -55,6 +55,14 @@ struct freelist_counters {
* that the slab was corrupted
*/
unsigned frozen:1;
+#ifdef CONFIG_64BIT
+ /*
+ * Some optimizations use free bits in 'counters' field
+ * to save memory. In case ->stride field is not available,
+ * such optimizations are disabled.
+ */
+ unsigned short stride;
+#endif
};
};
};
@@ -529,6 +537,26 @@ static inline unsigned long slab_obj_exts(struct slab *slab)
return obj_exts & ~OBJEXTS_FLAGS_MASK;
}
+#ifdef CONFIG_64BIT
+static inline void slab_set_stride(struct slab *slab, unsigned short stride)
+{
+ slab->stride = stride;
+}
+static inline unsigned short slab_get_stride(struct slab *slab)
+{
+ return slab->stride;
+}
+#else
+static inline void slab_set_stride(struct slab *slab, unsigned short stride)
+{
+ VM_WARN_ON_ONCE(stride != sizeof(struct slabobj_ext));
+}
+static inline unsigned short slab_get_stride(struct slab *slab)
+{
+ return sizeof(struct slabobj_ext);
+}
+#endif
+
/*
* slab_obj_ext - get the pointer to the slab object extension metadata
* associated with an object in a slab.
@@ -542,12 +570,9 @@ 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(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,
@@ -567,6 +592,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 09af619c2c69..020a2c4afb45 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2206,6 +2206,8 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
retry:
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