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

Konstantin Khorenko khorenko at virtuozzo.com
Fri Sep 6 20:34:10 MSK 2024


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

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

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

The "unlimited_slabs" functionality is disabled by default.

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

Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 mm/slub.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/mm/slub.c b/mm/slub.c
index ea3e20e73fe6..a7d6da9b528c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -34,6 +34,7 @@
 #include <linux/stacktrace.h>
 #include <linux/prefetch.h>
 #include <linux/memcontrol.h>
+#include <linux/debugfs.h>
 
 #include <trace/events/kmem.h>
 
@@ -2466,6 +2467,59 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
 	return freelist;
 }
 
+struct static_key unlimited_slabs = STATIC_KEY_INIT_FALSE;
+EXPORT_SYMBOL(unlimited_slabs);
+
+#ifdef CONFIG_DEBUG_FS
+static int unlimited_slabs_get(void *data, u64 *val)
+{
+	*val = static_key_false(&unlimited_slabs);
+	return 0;
+}
+
+static int unlimited_slabs_set(void *data, u64 val)
+{
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	if (static_key_false(&unlimited_slabs) && !val) {
+		static_key_slow_dec(&unlimited_slabs);
+		printk("unlimited_slabs tweak has been disabled\n");
+	} else if (!static_key_false(&unlimited_slabs) && val) {
+		static_key_slow_inc(&unlimited_slabs);
+		printk("unlimited_slabs tweak has been enabled\n");
+	}
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(unlimited_slabs_fops,
+		unlimited_slabs_get, unlimited_slabs_set, "%llu\n");
+
+bool setup_unlimited_slabs_cmd;
+static int __init unlimited_slabs_debugfs(void)
+{
+	void *ret;
+
+	ret = debugfs_create_file("unlimited_slabs", 0644, NULL, NULL,
+				  &unlimited_slabs_fops);
+	if (!ret)
+		pr_warn("Failed to create unlimited_slabs in debugfs");
+	if (setup_unlimited_slabs_cmd) {
+		static_key_slow_inc(&unlimited_slabs);
+		printk("unlimited_slabs tweak has been enabled "
+		       "due to unlimited_slabs=1 kernel boot option\n");
+	}
+	return 0;
+}
+late_initcall(unlimited_slabs_debugfs);
+
+static int __init setup_unlimited_slabs(char *str)
+{
+	return (kstrtobool(str, &setup_unlimited_slabs_cmd) == 0);
+}
+__setup("unlimited_slabs=", setup_unlimited_slabs);
+#endif
+
 /*
  * Slow path. The lockless freelist is empty or we need to perform
  * debugging duties.
@@ -2619,7 +2673,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))
+		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