[Devel] [PATCH rh7 v3] slub: introduce static_key switch for unlimited_slabs tweak

Konstantin Khorenko khorenko at virtuozzo.com
Wed Sep 11 15:40:45 MSK 2024


Introduce 2 ways to setup/configure "unlimited_slabs" tweak:

1. "slub.unlimited_slabs=" kernel boot option
    * "slub.unlimited_slabs=1" to enable  the tweak
    * "slub.unlimited_slabs=0" to disable the tweak

2. /sys/kernel/debug/unlimited_slabs entry
    * echo 1 > /sys/module/slub/parameters/unlimited_slabs to enable  the tweak
    * echo 0 > /sys/module/slub/parameters/unlimited_slabs to disable the tweak

The module parameter is BOOL, you can use [yYnN01] values.
The "unlimited_slabs" functionality is disabled by default.

Note: do not forget to mark SLABs with "pf_malloc" flag
      (use slub_debug=M to mark all SLABs by default on boot).

https://virtuozzo.atlassian.net/browse/PSBM-155867

Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
v2:
 * static key renamed from "unlimited_slabs" to "unlimited_slabs_key"
 * scheme of using __setup() for kernel boot option and manually created
   debugfs entry has been substituted by module_param_cb() which automatically
   creates debugfs entry for module parameter.
 * kernel boot option changed from "unlimited_slabs" to "slub.unlimited_slabs"
   as it's now module parameter
 * the module parameter is BOOL, so [yYnN01] values can be used
 * static keys cannot be switched during kernel boot option parsing, so the
   actual switch is delayed to late_init stag

v3:
 * use late_param_cb() instead of module_param_cb(), it allows to avoid using
   separate boot option parsing and using a separate delayed static_key
   configuration function.

 mm/slub.c | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/mm/slub.c b/mm/slub.c
index ea3e20e73fe6..ec823232923e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2466,6 +2466,40 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
 	return freelist;
 }
 
+struct static_key unlimited_slabs_key = STATIC_KEY_INIT_FALSE;
+static bool __read_mostly unlimited_slabs = false;
+
+static int unlimited_slabs_set(const char *val, const struct kernel_param *kp)
+{
+	/* One of =[yYnN01] */
+	if (strtobool(val, &unlimited_slabs) < 0)
+		return -EINVAL;
+
+	if (static_key_false(&unlimited_slabs_key) && !unlimited_slabs) {
+		static_key_slow_dec(&unlimited_slabs_key);
+		printk("unlimited_slabs tweak has been disabled\n");
+	} else if (!static_key_false(&unlimited_slabs_key) && unlimited_slabs) {
+		static_key_slow_inc(&unlimited_slabs_key);
+		printk("unlimited_slabs tweak has been enabled\n");
+	}
+
+	return 0;
+}
+
+static const struct kernel_param_ops unlimited_slabs_ops = {
+	.set = unlimited_slabs_set,
+	.get = param_get_bool,
+};
+
+/*
+ * static_keys cannot be switched during early boot stage,
+ * so delay the setup till late_initcall
+ */
+late_param_cb(unlimited_slabs, &unlimited_slabs_ops, &unlimited_slabs, 0644);
+__MODULE_PARM_TYPE(unlimited_slabs, "bool");
+MODULE_PARM_DESC(unlimited_slabs,
+		 "SLABs marked with pf_memalloc flag ignore memcg limits");
+
 /*
  * Slow path. The lockless freelist is empty or we need to perform
  * debugging duties.
@@ -2619,7 +2653,10 @@ static void *___slab_alloc_unlimited(struct kmem_cache *s, gfp_t gfpflags, int n
 static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 			   unsigned long addr, struct kmem_cache_cpu *c)
 {
-	return ___slab_alloc_unlimited(s, gfpflags, node, addr, c);
+	if (static_key_false(&unlimited_slabs_key))
+		return ___slab_alloc_unlimited(s, gfpflags, node, addr, c);
+	else
+		return ___slab_alloc_limited(s, gfpflags, node, addr, c);
 }
 
 /*
-- 
2.24.3



More information about the Devel mailing list