SLAB_BUCKETS gives allocations with user-controlled size and contents, like memdup_user() and msg_msg, their own set of kmalloc caches, at the cost of the memory for those caches. It can only be chosen at build time, so hosts which want it and hosts which would rather not pay for it need separate kernels. Add a slab_buckets= early parameter, enabled by default on kernels built with CONFIG_SLAB_BUCKETS=y, so that it can be turned off at boot. Signed-off-by: Chris Down --- .../admin-guide/kernel-parameters.txt | 8 ++++++ mm/Kconfig | 4 +++ mm/slab_common.c | 26 +++++++++++++++---- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 0b3c140babd9..c27bbe205051 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6990,6 +6990,14 @@ Kernel parameters apic=verbose is specified. Example: apic=debug show_lapic=all + slab_buckets= [MM,EARLY] + Format: + Enable or disable separate kmalloc buckets on kernels + built with CONFIG_SLAB_BUCKETS=y. When disabled, + allocations use regular kmalloc caches. Ignored + without that option. + Default: on. + slab_debug[=options[,slabs][;[options[,slabs]]...]] [MM] Enabling slab_debug allows one to determine the culprit if slab objects become corrupted. Enabling diff --git a/mm/Kconfig b/mm/Kconfig index d174537d941e..e602ebabd6e4 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -231,6 +231,10 @@ config SLAB_BUCKETS of extra pages since the bulk of user-controlled allocations are relatively long-lived. + The separate buckets can be disabled at boot with the + "slab_buckets=0" kernel parameter, in which case these + allocations use the regular kmalloc caches. + If unsure, say Y. config SLUB_STATS diff --git a/mm/slab_common.c b/mm/slab_common.c index 01c64ef661e7..272d22f411c2 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -410,6 +410,16 @@ EXPORT_SYMBOL(__kmem_cache_create_args); static struct kmem_cache *kmem_buckets_cache __ro_after_init; +static bool slab_buckets_enabled __ro_after_init = IS_ENABLED(CONFIG_SLAB_BUCKETS); + +static int __init setup_slab_buckets(char *str) +{ + if (!IS_ENABLED(CONFIG_SLAB_BUCKETS)) + return 0; + return kstrtobool(str, &slab_buckets_enabled); +} +early_param("slab_buckets", setup_slab_buckets); + /** * kmem_buckets_create - Create a set of caches that handle dynamic sized * allocations via kmem_buckets_alloc() @@ -424,10 +434,12 @@ static struct kmem_cache *kmem_buckets_cache __ro_after_init; * * Context: Cannot be called within an interrupt, but can be interrupted. * - * Return: a pointer to the cache on success, NULL on failure. When - * CONFIG_SLAB_BUCKETS is not enabled, ZERO_SIZE_PTR is returned, and - * subsequent calls to kmem_buckets_alloc() will fall back to kmalloc(). - * (i.e. callers only need to check for NULL on failure.) + * Return: a pointer to the cache on success, NULL on failure or when the + * separate buckets were disabled with the "slab_buckets=0" boot parameter. + * When CONFIG_SLAB_BUCKETS is not enabled, ZERO_SIZE_PTR is returned. In all + * of these cases subsequent calls to kmem_buckets_alloc() with the returned + * value fall back to kmalloc(), so callers that can live without separate + * buckets do not need to check the return value. */ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, unsigned int useroffset, @@ -448,6 +460,10 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags, if (!IS_ENABLED(CONFIG_SLAB_BUCKETS)) return ZERO_SIZE_PTR; + /* NULL makes kmalloc_slab() use the regular kmalloc caches. */ + if (!slab_buckets_enabled) + return NULL; + if (WARN_ON(!kmem_buckets_cache)) return NULL; @@ -1059,7 +1075,7 @@ void __init create_kmalloc_caches(void) /* Kmalloc array is now usable */ slab_state = UP; - if (IS_ENABLED(CONFIG_SLAB_BUCKETS)) + if (IS_ENABLED(CONFIG_SLAB_BUCKETS) && slab_buckets_enabled) kmem_buckets_cache = kmem_cache_create("kmalloc_buckets", sizeof(kmem_buckets), 0, SLAB_NO_MERGE, NULL); -- 2.56.1