[PATCH RFC 1/8] mm, slab: refactor slab_min/max_order handling
From: Vlastimil Babka (SUSE)
Date: Wed Sep 23 2026 - 13:25:45 EST
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@xxxxxxxxxx>
---
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