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. Implementation details: static keys cannot be switched during kernel boot option parsing, so the actual switch is delayed to late_init stage. https://virtuozzo.atlassian.net/browse/PSBM-155867 Signed-off-by: Konstantin Khorenko <khore...@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 mm/slub.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index ea3e20e73fe6..cf3e8f759234 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2466,6 +2466,58 @@ 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 bool unlimited_slabs_boot = false; + +static int unlimited_slabs_set(const char *val, const struct kernel_param *kp); +static const struct kernel_param_ops unlimited_slabs_ops = { + .set = unlimited_slabs_set, + .get = param_get_bool, +}; + +module_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"); + +/* + * static_keys cannot be switched during early boot stage, + * so delay the setup till late_initcall + */ +static int __init unlimited_slabs_set_boot(void) +{ + if (unlimited_slabs_boot) { + static_key_slow_inc(&unlimited_slabs_key); + printk("unlimited_slabs tweak has been enabled " + "due to slub.unlimited_slabs=1 kernel boot option\n"); + } + return 0; +} +late_initcall(unlimited_slabs_set_boot); + +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) { + if (unlikely(system_state < SYSTEM_RUNNING)) + unlimited_slabs_boot = true; + else { + static_key_slow_inc(&unlimited_slabs_key); + printk("unlimited_slabs tweak has been enabled\n"); + } + } + + return 0; +} + /* * Slow path. The lockless freelist is empty or we need to perform * debugging duties. @@ -2619,7 +2671,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 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel