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

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Mon Sep 9 07:33:43 MSK 2024



On 9/7/24 01:34, Konstantin Khorenko wrote:
> 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;

Maybe rename from setup_unlimited_slabs_cmd to unlimited_slabs_default?

> +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);


Maybe we can use typesafe module_param here? Note: that noaliencache and 
slab_max_order in this file use __setup instead of module_param likely 
only because they do non linear conversion of arguments.

static bool __read_mostly unlimited_slabs_default = false;
module_param(unlimited_slabs_default, bool, 0);

> +#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);
>   }
>   
>   /*

-- 
Best regards, Tikhomirov Pavel
Senior Software Developer, Virtuozzo.


More information about the Devel mailing list