* [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter
@ 2026-09-23 15:45 Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling Vlastimil Babka (SUSE)
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
CONFIG_SLUB_TINY was introduced to help tiny systems migrate away from
the SLOB implementation so it could be removed. Its main purpose has
been to disable all forms of percpu object caching (cpu slabs back then,
now sheaves), and being a compile-time config option, some extra minor
saving were achieved by code elimination or more agressive merging of
caches with reclaimable and non-reclaimable objects (keeping those
separate helps reduce high-order page fragmentation but not memory
footprint.
However being a config option brings issues such as incompatibility with
other options that has caused troubles in the past and Linus argued for
removing it [1]. Moreover, there is a use case for having full-blown
scalable implementation enabled and being able to disable it with a
boot-time rather than compile-time decision. That ise base is the kdump
kernel which shares the same vmlinux but wants to minimize the memory
overhead (which has to be pre-reserved from the production kernel) and
does not mind reduced scalability.
Thus this series reworks the CONFIG_SLUB_TINY to be controlled by a
variable set by a boot-time parameter. The config option itself is
deprecated and only sets the default value of the variable, and all its
interactions with other config options are removed.
The conversion builds mainly on the fact that most SLUB_TINY specific
paths to avoiding percpu object caching are shared with slab_debug
handling, except doing any actual debugging checks.
Thus introduce slab_debug=N (for No-op) option to allow using the
slab_debug checks directly, and extract the underlying static key
handling from CONFIG_SLUB_DEBUG only scope. The decision to create
separate kmalloc-rcl caches is also made to be boot-time.
The parts of CONFIG_SLUB_TINY that can't be transformed to a boot-time
decision are related to dead code elimination and fast path inlining,
merging of non-kmalloc reclaimable and unreclaimable caches, and
ignoring SLAB_NO_MERGE for performance purposes (currently used in
networking). Those lost memory saving should be all relatively minor
compared to the savings from avoiding percpu caching.
To sum up, after this series:
- CONFIG_SLUB_TINY is a deprecated option that has no interaction with
other options and only controls the default behavior.
- New slab_tiny boot parameter controls the functionality (and can
override CONFIG_SLUB_TINY in both directions).
- slab_debug=N can effectively achieve most of slab_tiny and on a
per-cache basic
- the implementation is simpler with many ifdefs removed
[1] https://lore.kernel.org/all/CAHk-=wh-k04MsoEC0SGKff2Snm6bBF_e+0pHOKwaWv4umZ_SnQ@mail.gmail.com/
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
Vlastimil Babka (SUSE) (8):
mm, slab: refactor slab_min/max_order handling
mm, slab: introduce slab_debug=N
mm, slab: rework KMALLOC_RECLAIM handling of SLUB_TINY
mm, slab: make SLUB_TINY handling dynamic for sizing decisions
mm, slab: convert CONFIG_SLUB_TINY checks to kmem_cache_debug()
mm, slab: remove remaining compile-time checks for CONFIG_SLUB_TINY
mm, slab: add slab_tiny boot param
mm, slab: deprecate CONFIG_SLUB_TINY and reduce its Kconfig effects
Documentation/admin-guide/kernel-parameters.txt | 4 +
Documentation/admin-guide/mm/slab.rst | 18 ++-
include/linux/slab.h | 17 +--
lib/Kconfig.kasan | 2 +-
mm/Kconfig | 16 ++-
mm/Kconfig.debug | 2 +-
mm/slab.h | 32 +++--
mm/slab_common.c | 12 +-
mm/slub.c | 149 +++++++++++-------------
9 files changed, 120 insertions(+), 132 deletions(-)
---
base-commit: b4218126d498275444f315b0ed4cef6add6beabc
change-id: 20260911-slub_tiny_rework-8f2634dd17a7
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 2/8] mm, slab: introduce slab_debug=N Vlastimil Babka (SUSE)
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
Setting slab_min_order and slab_max_order as boot-time parameters
currently has several not so great aspects:
- slab_min_order is not checked against MAX_PAGE_ORDER
- slab_min_order can raise slab_max_order
- processing requires custom callbacks, their execution order
depends on the order of boot time parameters specified
- upcoming SLUB_TINY changes would be more complicated
Instead of custom callbacks, introduce __initdata variables that hold
the boot-time parameter values (if given). All inputs are then evaluated
deterministically in kmem_cache_init(). slab_min_order is always capped
at slab_max_order and cannot raise it.
debug_guardpage_minorder() still overrides any given boot time params,
but it could be changed if there's a use case.
While at it, rename the slub_min/max_order variables and
slub_min_objects to have a "slab_" prefix instead, as their values
determine the sizing of slabs, and the "slub_" prefix already became
deprecated also for the boot-time parameters.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
mm/slub.c | 84 ++++++++++++++++++++++++---------------------------------------
1 file changed, 32 insertions(+), 52 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 96dca4846b4e..a107a111c75e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -7598,10 +7598,17 @@ EXPORT_SYMBOL(kmem_cache_alloc_bulk_noprof);
* and increases the number of allocations possible without having to
* take the list_lock.
*/
-static unsigned int slub_min_order;
-static unsigned int slub_max_order =
+static unsigned int slab_min_order;
+static unsigned int slab_max_order =
IS_ENABLED(CONFIG_SLUB_TINY) ? 1 : PAGE_ALLOC_COSTLY_ORDER;
-static unsigned int slub_min_objects;
+static unsigned int slab_min_objects;
+
+/*
+ * Store values set by boot-time parameters, to be evaluated in
+ * kmem_cache_init(). UINT_MAX means they were not set, as 0 is a valid value.
+ */
+static unsigned int slab_min_order_param __initdata = UINT_MAX;
+static unsigned int slab_max_order_param __initdata = UINT_MAX;
/*
* Calculate the order of allocation given an slab object size.
@@ -7655,7 +7662,7 @@ static inline int calculate_order(unsigned int size)
unsigned int max_objects;
unsigned int min_order;
- min_objects = slub_min_objects;
+ min_objects = slab_min_objects;
if (!min_objects) {
/*
* Some architectures will only update present cpus when
@@ -7672,10 +7679,10 @@ static inline int calculate_order(unsigned int size)
min_objects = 4 * (fls(nr_cpus) + 1);
}
/* min_objects can't be 0 because get_order(0) is undefined */
- max_objects = max(order_objects(slub_max_order, size), 1U);
+ max_objects = max(order_objects(slab_max_order, size), 1U);
min_objects = min(min_objects, max_objects);
- min_order = max_t(unsigned int, slub_min_order,
+ min_order = max_t(unsigned int, slab_min_order,
get_order(min_objects * size));
if (order_objects(min_order, size) > MAX_OBJS_PER_PAGE)
return get_order(size * MAX_OBJS_PER_PAGE) - 1;
@@ -7696,9 +7703,9 @@ static inline int calculate_order(unsigned int size)
* long as at least single object fits within slab_max_order.
*/
for (unsigned int fraction = 16; fraction > 1; fraction /= 2) {
- order = calc_slab_order(size, min_order, slub_max_order,
+ order = calc_slab_order(size, min_order, slab_max_order,
fraction);
- if (order <= slub_max_order)
+ if (order <= slab_max_order)
return order;
}
@@ -8268,50 +8275,14 @@ void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab)
* Kmalloc subsystem
*******************************************************************/
-static int __init setup_slub_min_order(const char *str, const struct kernel_param *kp)
-{
- int ret;
-
- ret = kstrtouint(str, 0, &slub_min_order);
- if (ret)
- return ret;
+core_param(slab_min_order, slab_min_order_param, uint, 0);
+core_param(slub_min_order, slab_min_order_param, uint, 0);
- if (slub_min_order > slub_max_order)
- slub_max_order = slub_min_order;
+core_param(slab_max_order, slab_max_order_param, uint, 0);
+core_param(slub_max_order, slab_max_order_param, uint, 0);
- return 0;
-}
-
-static const struct kernel_param_ops param_ops_slab_min_order __initconst = {
- .set = setup_slub_min_order,
-};
-__core_param_cb(slab_min_order, ¶m_ops_slab_min_order, &slub_min_order, 0);
-__core_param_cb(slub_min_order, ¶m_ops_slab_min_order, &slub_min_order, 0);
-
-static int __init setup_slub_max_order(const char *str, const struct kernel_param *kp)
-{
- int ret;
-
- ret = kstrtouint(str, 0, &slub_max_order);
- if (ret)
- return ret;
-
- slub_max_order = min_t(unsigned int, slub_max_order, MAX_PAGE_ORDER);
-
- if (slub_min_order > slub_max_order)
- slub_min_order = slub_max_order;
-
- return 0;
-}
-
-static const struct kernel_param_ops param_ops_slab_max_order __initconst = {
- .set = setup_slub_max_order,
-};
-__core_param_cb(slab_max_order, ¶m_ops_slab_max_order, &slub_max_order, 0);
-__core_param_cb(slub_max_order, ¶m_ops_slab_max_order, &slub_max_order, 0);
-
-core_param(slab_min_objects, slub_min_objects, uint, 0);
-core_param(slub_min_objects, slub_min_objects, uint, 0);
+core_param(slab_min_objects, slab_min_objects, uint, 0);
+core_param(slub_min_objects, slab_min_objects, uint, 0);
#ifdef CONFIG_NUMA
static int __init setup_slab_strict_numa(const char *str, const struct kernel_param *kp)
@@ -8684,8 +8655,17 @@ void __init kmem_cache_init(void)
slab_obj_ext_has_codetag_init();
+ if (slab_max_order_param <= MAX_PAGE_ORDER)
+ slab_max_order = slab_max_order_param;
+
+ if (slab_min_order_param <= MAX_PAGE_ORDER)
+ slab_min_order = slab_min_order_param;
+
if (debug_guardpage_minorder())
- slub_max_order = 0;
+ slab_max_order = 0;
+
+ if (slab_min_order > slab_max_order)
+ slab_min_order = slab_max_order;
/* Inform pointer hashing choice about slub debugging state. */
hash_pointers_finalize(__slub_debug_enabled());
@@ -8736,7 +8716,7 @@ void __init kmem_cache_init(void)
pr_info("SLUB: HWalign=%d, Order=%u-%u, MinObjects=%u, CPUs=%u, Nodes=%u\n",
cache_line_size(),
- slub_min_order, slub_max_order, slub_min_objects,
+ slab_min_order, slab_max_order, slab_min_objects,
nr_cpu_ids, nr_node_ids);
}
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 2/8] mm, slab: introduce slab_debug=N
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 3/8] mm, slab: rework KMALLOC_RECLAIM handling of SLUB_TINY Vlastimil Babka (SUSE)
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
Enabling slab_debug has the side-effect of disabling all percpu caching
of objects (now via sheaves), which can be sometimes useful for saving
memory for e.g. kdump kernels. To make this possible without the
overhead (CPU or memory) of actual debugging options such as poisoning,
introduce a No-op debug option that only forces the debugging slow paths
and zero sheaf capacity.
This will also allow reimplementing CONFIG_SLUB_TINY as a boot-time
option.
While documenting the new N option, remove obsolete SLAB references from
the F option description.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
Documentation/admin-guide/mm/slab.rst | 13 +++++++++++--
include/linux/slab.h | 5 ++++-
mm/slab.h | 2 +-
mm/slub.c | 3 +++
4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/Documentation/admin-guide/mm/slab.rst b/Documentation/admin-guide/mm/slab.rst
index 14429ab90611..0beeae71d472 100644
--- a/Documentation/admin-guide/mm/slab.rst
+++ b/Documentation/admin-guide/mm/slab.rst
@@ -45,12 +45,12 @@ of the first "select slabs" blocks that matches the slab's name are applied.
Possible debug options are::
- F Sanity checks on (enables SLAB_DEBUG_CONSISTENCY_CHECKS
- Sorry SLAB legacy issues)
+ F Sanity (slab consistency) checks on alloc and free
Z Red zoning
P Poisoning (object and padding)
U User tracking (free and alloc)
T Trace (please only use on single slabs)
+ N No-op (force debugging slowpaths without any checks)
A Enable failslab filter mark for the cache
O Switch debugging off for caches that would have
caused higher minimum slab orders
@@ -85,6 +85,15 @@ in low memory situations or if there's high fragmentation of memory. To
slab_debug=O
+The No-op option can be useful to minimize slab memory overhead by forcing slab
+debugging slowpaths, which disables percpu object caching. This reduces SMP
+scalability significantly, but does not impose the extra cpu or memory overhead
+of debugging options that actually perform checks. This can be useful for e.g.
+kdump kernels where scalability is not a concern, but memory has to be
+pre-reserved from the production kernel. So for a kdump kernel you can use::
+
+ slab_debug=N
+
You can apply different options to different list of slab names, using blocks
of options. This will enable red zoning for dentry and user tracking for
kmalloc. All other slabs will not get any debugging enabled::
diff --git a/include/linux/slab.h b/include/linux/slab.h
index cda126def67a..ed949e8522be 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -35,6 +35,7 @@ enum _slab_flag_bits {
_SLAB_PANIC,
_SLAB_TYPESAFE_BY_RCU,
_SLAB_TRACE,
+ _SLAB_DEBUG_NOOP,
#ifdef CONFIG_DEBUG_OBJECTS
_SLAB_DEBUG_OBJECTS,
#endif
@@ -166,8 +167,10 @@ enum _slab_flag_bits {
* Note that SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU.
*/
#define SLAB_TYPESAFE_BY_RCU __SLAB_FLAG_BIT(_SLAB_TYPESAFE_BY_RCU)
-/* Trace allocations and frees */
+/* DEBUG: Trace allocations and frees */
#define SLAB_TRACE __SLAB_FLAG_BIT(_SLAB_TRACE)
+/* DEBUG: Force the debug slowpaths without actually doing anything */
+#define SLAB_DEBUG_NOOP __SLAB_FLAG_BIT(_SLAB_DEBUG_NOOP)
/* Flag to prevent checks on free */
#ifdef CONFIG_DEBUG_OBJECTS
diff --git a/mm/slab.h b/mm/slab.h
index 8fd6835e4235..77fcbf99b7b4 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -490,7 +490,7 @@ void flush_rcu_sheaves_on_cache(struct kmem_cache *s);
SLAB_NO_USER_FLAGS | SLAB_KMALLOC | SLAB_NO_MERGE)
#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
- SLAB_TRACE | SLAB_CONSISTENCY_CHECKS)
+ SLAB_TRACE | SLAB_DEBUG_NOOP | SLAB_CONSISTENCY_CHECKS)
#define SLAB_FLAGS_PERMITTED (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS)
diff --git a/mm/slub.c b/mm/slub.c
index a107a111c75e..bc593f0078c0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1897,6 +1897,9 @@ parse_slub_debug_flags(const char *str, slab_flags_t *flags, const char **slabs,
case 't':
*flags |= SLAB_TRACE;
break;
+ case 'n':
+ *flags |= SLAB_DEBUG_NOOP;
+ break;
case 'a':
*flags |= SLAB_FAILSLAB;
break;
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 3/8] mm, slab: rework KMALLOC_RECLAIM handling of SLUB_TINY
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 2/8] mm, slab: introduce slab_debug=N Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 4/8] mm, slab: make SLUB_TINY handling dynamic for sizing decisions Vlastimil Babka (SUSE)
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
One (relatively minor) aspect of CONFIG_SLUB_TINY is the assumption that
letting reclaimable and non-reclaimable caches merge will save more
memory, which is more important on small systems than the page allocator
level fragmentation (where distinguishing reclaimable slabs should
help).
For now that has been achieved by #ifdefs that result in making the
SLAB_RECLAIM_ACCOUNT no-op and aliasing KMALLOC_RECLAIM to
KMALLOC_NORMAL on the enum values level.
With the goal of converting CONFIG_SLUB_TINY to a boot-time decision,
rework this so that SLAB_RECLAIM_ACCOUNT and KMALLOC_RECLAIM are
distinctly defined always. Now, creation of kmalloc-rcl caches is
avoided by assigning a pointer to the normal kmalloc cache on the
kmalloc_caches array level.
To prepare disconnecting of this boot-time decision (and the evaluation
of the need for kmalloc_no_objext) from CONFIG_SLUB_TINY, introduce a
slub_tiny_enabled variable that's initialized to the CONFIG_SLUB_TINY
state.
There is one minor functional change for CONFIG_SLUB_TINY: with
SLAB_RECLAIM_ACCOUNT not being 0 anymore, caches with and without the
flag will stop being mergeable. If that turns out to have a noticeable
impact on memory footprint, we can adjust the merging decisions to
ignore SLAB_RECLAIM_ACCOUNT when slub_tiny_enabled is true.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
include/linux/slab.h | 10 ----------
mm/slab.h | 5 +++--
mm/slab_common.c | 12 ++++++------
mm/slub.c | 2 ++
4 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index ed949e8522be..930dd64b9ad6 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -55,9 +55,7 @@ enum _slab_flag_bits {
#ifdef CONFIG_KFENCE
_SLAB_SKIP_KFENCE,
#endif
-#ifndef CONFIG_SLUB_TINY
_SLAB_RECLAIM_ACCOUNT,
-#endif
_SLAB_OBJECT_POISON,
_SLAB_CMPXCHG_DOUBLE,
#ifdef CONFIG_SLAB_OBJ_EXT
@@ -241,11 +239,7 @@ enum _slab_flag_bits {
* pages are allocated with __GFP_RECLAIMABLE, which affects grouping pages by
* mobility, and are accounted in SReclaimable counter in /proc/meminfo
*/
-#ifndef CONFIG_SLUB_TINY
#define SLAB_RECLAIM_ACCOUNT __SLAB_FLAG_BIT(_SLAB_RECLAIM_ACCOUNT)
-#else
-#define SLAB_RECLAIM_ACCOUNT __SLAB_FLAG_UNUSED
-#endif
#define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */
/* Slab caches without obj_exts array */
@@ -724,11 +718,7 @@ enum kmalloc_cache_type {
#endif
KMALLOC_PARTITION_START = KMALLOC_NORMAL,
KMALLOC_PARTITION_END = KMALLOC_PARTITION_START + KMALLOC_PARTITION_CACHES_NR,
-#ifdef CONFIG_SLUB_TINY
- KMALLOC_RECLAIM = KMALLOC_NORMAL,
-#else
KMALLOC_RECLAIM,
-#endif
#ifdef CONFIG_ZONE_DMA
KMALLOC_DMA,
#endif
diff --git a/mm/slab.h b/mm/slab.h
index 77fcbf99b7b4..00d49ac0d93f 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -410,6 +410,8 @@ extern const struct kmalloc_info_struct {
unsigned int size;
} kmalloc_info[];
+extern bool slab_tiny_enabled;
+
/* Kmalloc array related functions */
void setup_kmalloc_cache_index_table(void);
void create_kmalloc_caches(void);
@@ -590,8 +592,7 @@ static inline bool need_kmalloc_no_objext(void)
if (!mem_alloc_profiling_permanently_disabled())
return true;
- if (!mem_cgroup_kmem_disabled() &&
- (KMALLOC_NORMAL == KMALLOC_RECLAIM))
+ if (!mem_cgroup_kmem_disabled() && slab_tiny_enabled)
return true;
return false;
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 28bf035a58f3..38de7d50bfa7 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -826,11 +826,7 @@ EXPORT_SYMBOL(kmalloc_size_roundup);
#define KMALLOC_CGROUP_NAME(sz)
#endif
-#ifndef CONFIG_SLUB_TINY
#define KMALLOC_RCL_NAME(sz) .name[KMALLOC_RECLAIM] = "kmalloc-rcl-" #sz,
-#else
-#define KMALLOC_RCL_NAME(sz)
-#endif
#ifdef CONFIG_KMALLOC_PARTITION_CACHES
#define __KMALLOC_PARTITION_CONCAT(a, b) a ## b
@@ -967,7 +963,11 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type)
unsigned int aligned_size = kmalloc_info[idx].size;
int aligned_idx = idx;
- if ((KMALLOC_RECLAIM != KMALLOC_NORMAL) && (type == KMALLOC_RECLAIM)) {
+ if (type == KMALLOC_RECLAIM) {
+ if (slab_tiny_enabled) {
+ kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL][idx];
+ return;
+ }
flags |= SLAB_RECLAIM_ACCOUNT;
} else if (IS_ENABLED(CONFIG_MEMCG) && (type == KMALLOC_CGROUP)) {
if (mem_cgroup_kmem_disabled()) {
@@ -1000,7 +1000,7 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type)
* KMALLOC_NO_OBJ_EXT cache.
*/
if (!mem_cgroup_kmem_disabled()) {
- if (type == KMALLOC_NORMAL && KMALLOC_RECLAIM != KMALLOC_NORMAL)
+ if (type == KMALLOC_NORMAL && !slab_tiny_enabled)
flags |= SLAB_NO_MERGE;
else if (!(flags & SLAB_NO_OBJ_EXT))
flags |= SLAB_MAY_ACCOUNT;
diff --git a/mm/slub.c b/mm/slub.c
index bc593f0078c0..2a7b3b3b91b5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -219,6 +219,8 @@ DEFINE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT,
slab_obj_ext_has_codetag_key);
#endif
+bool slab_tiny_enabled __read_mostly = IS_ENABLED(CONFIG_SLUB_TINY);
+
/* Structure holding extra parameters for slab allocations */
struct slab_alloc_context {
unsigned long caller_addr;
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 4/8] mm, slab: make SLUB_TINY handling dynamic for sizing decisions
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
` (2 preceding siblings ...)
2026-09-23 15:45 ` [PATCH RFC 3/8] mm, slab: rework KMALLOC_RECLAIM handling of SLUB_TINY Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 5/8] mm, slab: convert CONFIG_SLUB_TINY checks to kmem_cache_debug() Vlastimil Babka (SUSE)
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
Enabling CONFIG_SLUB_TINY results in the caches' min partial slabs
threshold to be zero, thus every slab where all objects become free is
freed immediately. It also sets the default slab_max_order to 1, with
the goal of reducing the potential of internal slab fragmentation.
Rework both of these decisions to be based on the newly introduced
slab_tiny_enabled flag instead of #ifdefs. It's still possible to
override the reduced slab_max_order with the boot parameter, as before.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
mm/slub.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 2a7b3b3b91b5..2c8477033700 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -272,7 +272,6 @@ void *fixup_red_left(struct kmem_cache *s, void *p)
/* Enable to log cmpxchg failures */
#undef SLUB_DEBUG_CMPXCHG
-#ifndef CONFIG_SLUB_TINY
/*
* Minimum number of partial slabs. These will be left on the partial
* lists even if they are empty. kmem_cache_shrink may reclaim them.
@@ -285,10 +284,6 @@ void *fixup_red_left(struct kmem_cache *s, void *p)
* sort the partial list by the number of objects in use.
*/
#define MAX_PARTIAL 10
-#else
-#define MIN_PARTIAL 0
-#define MAX_PARTIAL 0
-#endif
#define DEBUG_DEFAULT_FLAGS (SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE | \
SLAB_POISON | SLAB_STORE_USER)
@@ -7604,8 +7599,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_bulk_noprof);
* take the list_lock.
*/
static unsigned int slab_min_order;
-static unsigned int slab_max_order =
- IS_ENABLED(CONFIG_SLUB_TINY) ? 1 : PAGE_ALLOC_COSTLY_ORDER;
+static unsigned int slab_max_order = PAGE_ALLOC_COSTLY_ORDER;
static unsigned int slab_min_objects;
/*
@@ -7924,7 +7918,7 @@ static unsigned int calculate_sheaf_capacity(struct kmem_cache *s,
size_t size;
- if (IS_ENABLED(CONFIG_SLUB_TINY) || s->flags & SLAB_DEBUG_FLAGS)
+ if (slab_tiny_enabled || s->flags & SLAB_DEBUG_FLAGS)
return 0;
/*
@@ -8660,6 +8654,9 @@ void __init kmem_cache_init(void)
slab_obj_ext_has_codetag_init();
+ if (slab_tiny_enabled)
+ slab_max_order = 1;
+
if (slab_max_order_param <= MAX_PAGE_ORDER)
slab_max_order = slab_max_order_param;
@@ -8783,6 +8780,8 @@ int do_kmem_cache_create(struct kmem_cache *s, const char *name,
*/
s->min_partial = min_t(unsigned long, MAX_PARTIAL, ilog2(s->size) / 2);
s->min_partial = max_t(unsigned long, MIN_PARTIAL, s->min_partial);
+ if (slab_tiny_enabled)
+ s->min_partial = 0;
s->cpu_sheaves = alloc_percpu(struct slub_percpu_sheaves);
if (!s->cpu_sheaves) {
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 5/8] mm, slab: convert CONFIG_SLUB_TINY checks to kmem_cache_debug()
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
` (3 preceding siblings ...)
2026-09-23 15:45 ` [PATCH RFC 4/8] mm, slab: make SLUB_TINY handling dynamic for sizing decisions Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 6/8] mm, slab: remove remaining compile-time checks for CONFIG_SLUB_TINY Vlastimil Babka (SUSE)
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
CONFIG_SLUB_TINY shares several slowpaths with debugging as both of them
avoid percpu caching of objects. With the goal of replacing the config
with a boot-time decision, extend this sharing by hooking
slab_tiny_enabled into kmem_cache_debug() check itself.
This is made possible by the new SLAB_DEBUG_NOOP debug flag. Make
slub_debug_enabled static key always available (not just with
CONFIG_SLUB_DEBUG enabled) and have slab_tiny_enabled add
SLAB_DEBUG_NOOP to all caches in kmem_cache_flags(). Do this also in the
CONFIG_SLUB_DEBUG variant, which is currently exclusive with
CONFIG_SLUB_TINY, but that will be lifted later.
Remove the various IS_ENABLED(CONFIG_SLUB_TINY) checks that
complement kmem_cache_debug() checks as they are no longer necessary.
While removing/adjusting the CONFIG_SLUB_DEBUG #ifdefs, also convert
CONFIG_SLUB_DEBUG_ON to *_STATIC_KEY_MAYBE().
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
mm/slab.h | 18 ++++++------------
mm/slub.c | 38 ++++++++++++++++++--------------------
2 files changed, 24 insertions(+), 32 deletions(-)
diff --git a/mm/slab.h b/mm/slab.h
index 00d49ac0d93f..23017a5d10d1 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -520,26 +520,20 @@ struct slabinfo {
void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo);
-#ifdef CONFIG_SLUB_DEBUG
-#ifdef CONFIG_SLUB_DEBUG_ON
-DECLARE_STATIC_KEY_TRUE(slub_debug_enabled);
-#else
-DECLARE_STATIC_KEY_FALSE(slub_debug_enabled);
-#endif
-extern void print_tracking(struct kmem_cache *s, void *object);
-long validate_slab_cache(struct kmem_cache *s);
+DECLARE_STATIC_KEY_MAYBE(CONFIG_SLUB_DEBUG_ON, slub_debug_enabled);
+
static inline bool __slub_debug_enabled(void)
{
return static_branch_unlikely(&slub_debug_enabled);
}
+
+#ifdef CONFIG_SLUB_DEBUG
+extern void print_tracking(struct kmem_cache *s, void *object);
+long validate_slab_cache(struct kmem_cache *s);
#else
static inline void print_tracking(struct kmem_cache *s, void *object)
{
}
-static inline bool __slub_debug_enabled(void)
-{
- return false;
-}
#endif
/*
diff --git a/mm/slub.c b/mm/slub.c
index 2c8477033700..c6a0422e055d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -202,13 +202,7 @@ enum slab_flags {
#define __fastpath_inline
#endif
-#ifdef CONFIG_SLUB_DEBUG
-#ifdef CONFIG_SLUB_DEBUG_ON
-DEFINE_STATIC_KEY_TRUE(slub_debug_enabled);
-#else
-DEFINE_STATIC_KEY_FALSE(slub_debug_enabled);
-#endif
-#endif /* CONFIG_SLUB_DEBUG */
+DEFINE_STATIC_KEY_MAYBE(CONFIG_SLUB_DEBUG_ON, slub_debug_enabled);
#ifdef CONFIG_NUMA
static DEFINE_STATIC_KEY_FALSE(strict_numa);
@@ -1040,11 +1034,7 @@ static inline void *restore_red_left(struct kmem_cache *s, void *p)
/*
* Debug settings:
*/
-#if defined(CONFIG_SLUB_DEBUG_ON)
-static slab_flags_t slub_debug = DEBUG_DEFAULT_FLAGS;
-#else
-static slab_flags_t slub_debug;
-#endif
+static slab_flags_t slub_debug = IS_ENABLED(CONFIG_SLUB_DEBUG_ON) ? DEBUG_DEFAULT_FLAGS : 0;
static const char *slub_debug_string __ro_after_init;
static int disable_higher_order_debug;
@@ -2017,6 +2007,9 @@ slab_flags_t kmem_cache_flags(slab_flags_t flags, const char *name)
slab_flags_t block_flags;
slab_flags_t slub_debug_local = slub_debug;
+ if (slab_tiny_enabled)
+ flags |= SLAB_DEBUG_NOOP;
+
if (flags & SLAB_NO_USER_FLAGS)
return flags;
@@ -2087,6 +2080,9 @@ static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n,
struct slab *slab) {}
slab_flags_t kmem_cache_flags(slab_flags_t flags, const char *name)
{
+ if (slab_tiny_enabled)
+ flags |= SLAB_DEBUG_NOOP;
+
return flags;
}
#define slub_debug 0
@@ -3942,7 +3938,7 @@ static void *get_from_partial_node(struct kmem_cache *s,
if (!pfmemalloc_match(slab, gfp_flags))
continue;
- if (IS_ENABLED(CONFIG_SLUB_TINY) || kmem_cache_debug(s)) {
+ if (kmem_cache_debug(s)) {
object = alloc_single_from_partial(s, n, slab,
ac->orig_size);
if (object)
@@ -4556,7 +4552,7 @@ static unsigned int alloc_from_new_slab(struct kmem_cache *s, struct slab *slab,
/*
* Slow path. We failed to allocate via percpu sheaves or they are not available
- * due to bootstrap or debugging enabled or SLUB_TINY.
+ * due to bootstrap or debugging enabled.
*
* We try to allocate from partial slab lists and fall back to allocating a new
* slab.
@@ -4610,7 +4606,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
stat(s, ALLOC_SLAB);
- if (IS_ENABLED(CONFIG_SLUB_TINY) || kmem_cache_debug(s)) {
+ if (kmem_cache_debug(s)) {
object = alloc_single_from_new_slab(s, slab, ac);
if (likely(object))
@@ -5764,7 +5760,7 @@ static void __slab_free(struct kmem_cache *s, struct slab *slab,
unsigned long flags;
bool on_node_partial;
- if (IS_ENABLED(CONFIG_SLUB_TINY) || kmem_cache_debug(s)) {
+ if (kmem_cache_debug(s)) {
free_to_partial_list(s, slab, head, tail, cnt, addr);
return;
}
@@ -7471,7 +7467,7 @@ static bool __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags,
{
int i;
- if (IS_ENABLED(CONFIG_SLUB_TINY) || kmem_cache_debug(s)) {
+ if (kmem_cache_debug(s)) {
const struct slab_alloc_context ac = {
.caller_addr = _RET_IP_,
.orig_size = s->object_size,
@@ -7772,7 +7768,7 @@ static int init_percpu_sheaves(struct kmem_cache *s)
* cache.
*
* We keep bootstrap_sheaf for kmem_cache and kmem_cache_node,
- * caches with debug enabled, and all caches with SLUB_TINY.
+ * and caches with debugging enabled.
* For kmalloc caches it's used temporarily during the initial
* bootstrap.
*/
@@ -8588,7 +8584,7 @@ static void __init bootstrap_cache_sheaves(struct kmem_cache *s)
capacity = calculate_sheaf_capacity(s, &empty_args);
- /* capacity can be 0 due to debugging or SLUB_TINY */
+ /* capacity can be 0 due to debugging */
if (!capacity)
return;
@@ -8654,8 +8650,10 @@ void __init kmem_cache_init(void)
slab_obj_ext_has_codetag_init();
- if (slab_tiny_enabled)
+ if (slab_tiny_enabled) {
slab_max_order = 1;
+ static_branch_enable(&slub_debug_enabled);
+ }
if (slab_max_order_param <= MAX_PAGE_ORDER)
slab_max_order = slab_max_order_param;
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 6/8] mm, slab: remove remaining compile-time checks for CONFIG_SLUB_TINY
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
` (4 preceding siblings ...)
2026-09-23 15:45 ` [PATCH RFC 5/8] mm, slab: convert CONFIG_SLUB_TINY checks to kmem_cache_debug() Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 7/8] mm, slab: add slab_tiny boot param Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 8/8] mm, slab: deprecate CONFIG_SLUB_TINY and reduce its Kconfig effects Vlastimil Babka (SUSE)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
Remove several minor aspect of CONFIG_SLUB_TINY to allow it to be fully
a boot-time decision:
- remove check in cache_has_sheaves(), with no change to functionality
but only on code elimination
- remove SLAB_SUPPORTS_SYSFS dependency on !CONFIG_SLUB_TINY, thus
/sys/kernel/slab will exist as long as CONFIG_SYSFS is enabled
(for now leave SLAB_SUPPORTS_SYSFS around, can be cleaned up later)
- remove the control of __fastpath_inline so it's just a wrapper of
__always_inline. Leave it also around for documenting the intent, can
be revisited later.
- remove a comment for SLAB_NO_MERGE as we don't want new checks for
CONFIG_SLUB_TINY
This leaves the only usage of CONFIG_SLUB_TINY in slab code to set the
value of slab_tiny_enabled around.
net/core/skbuff.c keeps using it to control SLAB_NO_MERGE but that can
be dealt with independently after the config is deprecated.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
include/linux/slab.h | 2 +-
mm/slab.h | 7 +++----
mm/slub.c | 4 ----
3 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 930dd64b9ad6..ad645967a3ee 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -188,7 +188,7 @@ enum _slab_flag_bits {
* - general caches created and used by a subsystem, only when a
* (subsystem-specific) debug option is enabled
* - performance critical caches, should be very rare and consulted with slab
- * maintainers, and not used together with CONFIG_SLUB_TINY
+ * maintainers
*/
#define SLAB_NO_MERGE __SLAB_FLAG_BIT(_SLAB_NO_MERGE)
diff --git a/mm/slab.h b/mm/slab.h
index 23017a5d10d1..065de2b92586 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -296,16 +296,15 @@ struct kmem_cache {
/*
* Every cache has !NULL s->cpu_sheaves but they may point to the
* bootstrap_sheaf temporarily during init, or permanently for the boot caches
- * and caches with debugging enabled, or all caches with CONFIG_SLUB_TINY. This
+ * and caches with debugging enabled (or all caches with slab_tiny). This
* helper distinguishes whether cache has real non-bootstrap sheaves.
*/
static inline bool cache_has_sheaves(struct kmem_cache *s)
{
- /* Test CONFIG_SLUB_TINY for code elimination purposes */
- return !IS_ENABLED(CONFIG_SLUB_TINY) && s->sheaf_capacity;
+ return s->sheaf_capacity;
}
-#if defined(CONFIG_SYSFS) && !defined(CONFIG_SLUB_TINY)
+#ifdef CONFIG_SYSFS
#define SLAB_SUPPORTS_SYSFS 1
void sysfs_slab_unlink(struct kmem_cache *s);
void sysfs_slab_release(struct kmem_cache *s);
diff --git a/mm/slub.c b/mm/slub.c
index c6a0422e055d..4814f025fde5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -196,11 +196,7 @@ enum slab_flags {
SL_pfmemalloc = PG_active, /* Historical reasons for this bit */
};
-#ifndef CONFIG_SLUB_TINY
#define __fastpath_inline __always_inline
-#else
-#define __fastpath_inline
-#endif
DEFINE_STATIC_KEY_MAYBE(CONFIG_SLUB_DEBUG_ON, slub_debug_enabled);
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 7/8] mm, slab: add slab_tiny boot param
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
` (5 preceding siblings ...)
2026-09-23 15:45 ` [PATCH RFC 6/8] mm, slab: remove remaining compile-time checks for CONFIG_SLUB_TINY Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 8/8] mm, slab: deprecate CONFIG_SLUB_TINY and reduce its Kconfig effects Vlastimil Babka (SUSE)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
In order to deprecate the CONFIG_SLUB_TINY option, introduce an early
boot param slab_tiny to control the value of slab_tiny_enabled.
As long as CONFIG_SLUB_TINY is still around and enabled, this boot param
can also override it to be disabled.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
Documentation/admin-guide/kernel-parameters.txt | 4 ++++
Documentation/admin-guide/mm/slab.rst | 5 +++++
mm/slub.c | 7 +++++++
3 files changed, 16 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 33cd30996e47..0100ab00388a 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -7031,6 +7031,10 @@ Kernel parameters
NUMA kernel object placement which helps with slow
interconnects in NUMA systems.
+ slab_tiny= [MM, EARLY]
+ Minimize the slab allocator memory footprint at the
+ expense of SMP scalability.
+
slram= [HW,MTD]
smart2= [HW]
diff --git a/Documentation/admin-guide/mm/slab.rst b/Documentation/admin-guide/mm/slab.rst
index 0beeae71d472..6c005d3de0b2 100644
--- a/Documentation/admin-guide/mm/slab.rst
+++ b/Documentation/admin-guide/mm/slab.rst
@@ -94,6 +94,11 @@ kdump kernels where scalability is not a concern, but memory has to be
slab_debug=N
+Note that for this purpose you can instead use an option that can achieve
+slightly better memory savings (by not creating separate kmalloc-rcl caches)::
+
+ slab_tiny=1
+
You can apply different options to different list of slab names, using blocks
of options. This will enable red zoning for dentry and user tracking for
kmalloc. All other slabs will not get any debugging enabled::
diff --git a/mm/slub.c b/mm/slub.c
index 4814f025fde5..d672809fa2f6 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -8726,6 +8726,13 @@ void __init kmem_cache_init_late(void)
#endif
}
+static int __init early_slab_tiny(char *buf)
+{
+ return kstrtobool(buf, &slub_tiny_enabled);
+}
+
+early_param("slab_tiny", early_slab_tiny);
+
int do_kmem_cache_create(struct kmem_cache *s, const char *name,
unsigned int size, struct kmem_cache_args *args,
slab_flags_t flags)
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 8/8] mm, slab: deprecate CONFIG_SLUB_TINY and reduce its Kconfig effects
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
` (6 preceding siblings ...)
2026-09-23 15:45 ` [PATCH RFC 7/8] mm, slab: add slab_tiny boot param Vlastimil Babka (SUSE)
@ 2026-09-23 15:45 ` Vlastimil Babka (SUSE)
7 siblings, 0 replies; 9+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-09-23 15:45 UTC (permalink / raw)
To: Harry Yoo
Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
Geert Uytterhoeven, Conor Dooley, Damien Le Moal, linux-mm,
linux-kernel, Vlastimil Babka (SUSE)
At this point CONFIG_SLUB_TINY only affects the default value of
slab_tiny_enabled which has a boot-time parameter. Thus deprecate it in
the Kconfig description.
Also remove its interactions with other Kconfig option, as they are not
necessary:
- KASAN, SLUB_DEBUG or SLUB_STATS support does not need !SLUB_TINY
- KVFREE_RCU_BATCHED can simply depend on !TINY_RCU
- various hardening options do not need to be excluded, although it's
unlikely that somebody would enable those with extra memory overhead
together with slab_tiny
- SLAB_MERGE_DEFAULT does not need to be selected, although it's likely
to be used together
Keep the "depends on EXPERT && !COMPILE_TEST" as there's no point making
the deprecated option more visible.
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
lib/Kconfig.kasan | 2 +-
mm/Kconfig | 16 +++++++---------
mm/Kconfig.debug | 2 +-
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index a4bb610a7a6f..f20b574f6653 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -49,7 +49,7 @@ menuconfig KASAN
(HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)) && \
CC_HAS_WORKING_NOSANITIZE_ADDRESS) || \
HAVE_ARCH_KASAN_HW_TAGS
- depends on SYSFS && !SLUB_TINY
+ depends on SYSFS
select STACKDEPOT_ALWAYS_INIT
help
Enables KASAN (Kernel Address Sanitizer) - a dynamic memory safety
diff --git a/mm/Kconfig b/mm/Kconfig
index 604c58199acb..a1b1ff7db59f 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -167,16 +167,18 @@ config SLUB
config KVFREE_RCU_BATCHED
def_bool y
- depends on !SLUB_TINY && !TINY_RCU
+ depends on !TINY_RCU
depends on !RCU_STRICT_GRACE_PERIOD
config SLUB_TINY
- bool "Configure for minimal memory footprint"
+ bool "Enable slab_tiny by default"
depends on EXPERT && !COMPILE_TEST
- select SLAB_MERGE_DEFAULT
help
+ Deprecated option that enables the slab_tiny boot parameter by
+ default, and can be overridden by booting with slab_tiny=0.
+
Configures the slab allocator in a way to achieve minimal memory
- footprint, sacrificing scalability, debugging and other features.
+ footprint, sacrificing scalability.
This is intended only for the smallest system that had used the
SLOB allocator and is not recommended for systems with more than
16MB RAM.
@@ -199,7 +201,6 @@ config SLAB_MERGE_DEFAULT
config SLAB_FREELIST_RANDOM
bool "Randomize slab freelist"
- depends on !SLUB_TINY
help
Randomizes the freelist order used on creating new pages. This
security feature reduces the predictability of the kernel slab
@@ -207,7 +208,6 @@ config SLAB_FREELIST_RANDOM
config SLAB_FREELIST_HARDENED
bool "Harden slab freelist metadata"
- depends on !SLUB_TINY
help
Many kernel heap attacks try to target slab cache metadata and
other infrastructure. This options makes minor performance
@@ -216,7 +216,6 @@ config SLAB_FREELIST_HARDENED
config SLAB_BUCKETS
bool "Support allocation from separate kmalloc buckets"
- depends on !SLUB_TINY
default SLAB_FREELIST_HARDENED
help
Kernel heap attacks frequently depend on being able to create
@@ -234,7 +233,7 @@ config SLAB_BUCKETS
config SLUB_STATS
default n
bool "Enable performance statistics"
- depends on SYSFS && !SLUB_TINY
+ depends on SYSFS
help
The statistics are useful to debug slab allocation behavior in
order find ways to optimize the allocator. This should never be
@@ -245,7 +244,6 @@ config SLUB_STATS
Try running: slabinfo -DA
config KMALLOC_PARTITION_CACHES
- depends on !SLUB_TINY
bool "Partitioned slab caches for normal kmalloc"
default RANDOM_KMALLOC_CACHES
help
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index 15dca19dd07d..7fa01e48c9f0 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -48,7 +48,7 @@ config DEBUG_PAGEALLOC_ENABLE_DEFAULT
config SLUB_DEBUG
default y
bool "Enable SLUB debugging support" if EXPERT
- depends on SYSFS && !SLUB_TINY
+ depends on SYSFS
select STACKDEPOT if STACKTRACE_SUPPORT
help
SLUB has extensive debug support features. Disabling these can
--
2.55.0
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-23 15:45 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-23 15:45 [PATCH RFC 0/8] replace CONFIG_SLUB_TINY with a slab_tiny boot parameter Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 2/8] mm, slab: introduce slab_debug=N Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 3/8] mm, slab: rework KMALLOC_RECLAIM handling of SLUB_TINY Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 4/8] mm, slab: make SLUB_TINY handling dynamic for sizing decisions Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 5/8] mm, slab: convert CONFIG_SLUB_TINY checks to kmem_cache_debug() Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 6/8] mm, slab: remove remaining compile-time checks for CONFIG_SLUB_TINY Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 7/8] mm, slab: add slab_tiny boot param Vlastimil Babka (SUSE)
2026-09-23 15:45 ` [PATCH RFC 8/8] mm, slab: deprecate CONFIG_SLUB_TINY and reduce its Kconfig effects Vlastimil Babka (SUSE)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®