Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: linux-mm@kvack.org
Cc: Vlastimil Babka <vbabka@suse.cz>,
	Harry Yoo <harry.yoo@oracle.com>,
	linux-fsdevel@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
	Mateusz Guzik <mjguzik@gmail.com>,
	linux-kernel@vger.kernel.org
Subject: [RFC PATCH v3 01/10] static kmem_cache instances for core caches: infrastructure
Date: Sat, 13 Jun 2026 06:09:42 +0100	[thread overview]
Message-ID: <20260613050951.855141-2-viro@zeniv.linux.org.uk> (raw)
In-Reply-To: <20260613050951.855141-1-viro@zeniv.linux.org.uk>

        kmem_cache_create() and friends create new instances of
struct kmem_cache and return pointers to those.  Quite a few things in
core kernel are allocated from such caches; each allocation involves
dereferencing an assign-once pointer and for sufficiently hot ones that
dereferencing does show in profiles.

        There had been patches floating around switching some of those
to runtime_const infrastructure.  Unfortunately, it's arch-specific
and most of the architectures lack it.

        There's an alternative approach applicable at least to the caches
that are never destroyed, which covers a lot of them.  No matter what,
runtime_const for pointers is not going to be faster than plain &,
so if we had struct kmem_cache instances with static storage duration, we
would be at least no worse off than we are with runtime_const variants.

        There are obstacles to doing that, but they turn out to be easy
to deal with.

	First of all, struct kmem_cache is opaque for anything outside
of a few files in mm/*; that avoids serious headache with header dependencies,
etc., and it's not something we want to lose.

	Solution: struct kmem_cache_opaque, with the size and alignment
identical to struct kmem_cache.  Calculation of size and alignment can be
done via the same mechanism we use for asm-offsets.h and rq-offsets.h,
with build-time check for mismatches.  With that done, we get an opaque type
defined in linux/slab-static.h that can be used for declaring those caches.
In linux/slab.h we add a forward declaration of kmem_cache_opaque +
helper (to_kmem_cache()) converting a pointer to kmem_cache_opaque
into the corresponding pointer to kmem_cache.

	At that point we can't actually *do* anything with those statically
allocated instances - the primitives for setting them up are going to be
added in the next commits.  Declarations of those primitives will also go
into linux/slab-static.h.

	Note that this header is needed only in places that define and
initialize statically allocated kmem_cache instances; users of such
instances need only slab.h.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Kbuild                      | 14 +++++++++++++-
 include/linux/slab-static.h | 13 +++++++++++++
 include/linux/slab.h        |  6 ++++++
 mm/kmem_cache_size.c        | 20 ++++++++++++++++++++
 mm/slub.c                   |  7 +++++++
 5 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/slab-static.h
 create mode 100644 mm/kmem_cache_size.c

diff --git a/Kbuild b/Kbuild
index a6a0192dea08..64f29f1f0e71 100644
--- a/Kbuild
+++ b/Kbuild
@@ -45,6 +45,17 @@ kernel/sched/rq-offsets.s: $(offsets-file)
 $(rq-offsets-file): kernel/sched/rq-offsets.s FORCE
 	$(call filechk,offsets,__RQ_OFFSETS_H__)
 
+# generate kmem_cache_size.h
+
+kmem_cache_size-file := include/generated/kmem_cache_size.h
+
+targets += mm/kmem_cache_size.s
+
+mm/kmem_cache_size.s: $(rq-offsets-file)
+
+$(kmem_cache_size-file): mm/kmem_cache_size.s FORCE
+	$(call filechk,offsets,__KMEM_CACHE_SIZE_H__)
+
 # Check for missing system calls
 
 missing-syscalls-file := .tmp_missing-syscalls$(missing_syscalls_instance)
@@ -58,7 +69,8 @@ $(missing-syscalls-file): scripts/checksyscalls.sh $(rq-offsets-file) FORCE
 	$(call if_changed_dep,syscalls)
 
 PHONY += missing-syscalls
-missing-syscalls: $(missing-syscalls-file)
+missing-syscalls: $(missing-syscalls-file) $(kmem_cache_size-file)
+	$(call cmd,syscalls)
 
 # Check the manual modification of atomic headers
 
diff --git a/include/linux/slab-static.h b/include/linux/slab-static.h
new file mode 100644
index 000000000000..07aca67facee
--- /dev/null
+++ b/include/linux/slab-static.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_SLAB_STATIC_H
+#define _LINUX_SLAB_STATIC_H
+
+#include <linux/init.h>
+#include <generated/kmem_cache_size.h>
+
+/* same size and alignment as struct kmem_cache: */
+struct kmem_cache_opaque {
+	unsigned char opaque[KMEM_CACHE_SIZE];
+} __aligned(KMEM_CACHE_ALIGN);
+
+#endif
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2b5ab488e96b..a43d31eec06c 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -265,11 +265,17 @@ enum _slab_flag_bits {
 
 struct list_lru;
 struct mem_cgroup;
+struct kmem_cache_opaque;
 /*
  * struct kmem_cache related prototypes
  */
 bool slab_is_available(void);
 
+static inline struct kmem_cache *to_kmem_cache(struct kmem_cache_opaque *p)
+{
+	return (struct kmem_cache *)p;
+}
+
 /**
  * struct kmem_cache_args - Less common arguments for kmem_cache_create()
  *
diff --git a/mm/kmem_cache_size.c b/mm/kmem_cache_size.c
new file mode 100644
index 000000000000..1ddbfa41a507
--- /dev/null
+++ b/mm/kmem_cache_size.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generate definitions needed by the preprocessor.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#define COMPILE_OFFSETS
+#include <linux/kbuild.h>
+#include "slab.h"
+
+int main(void)
+{
+	/* The constants to put into include/generated/kmem_cache_size.h */
+	DEFINE(KMEM_CACHE_SIZE, sizeof(struct kmem_cache));
+	DEFINE(KMEM_CACHE_ALIGN, __alignof(struct kmem_cache));
+	/* End of constants */
+
+	return 0;
+}
diff --git a/mm/slub.c b/mm/slub.c
index a2bf3756ca7d..c0765173911d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -50,6 +50,7 @@
 #include <linux/irq_work.h>
 #include <linux/kprobes.h>
 #include <linux/debugfs.h>
+#include <linux/slab-static.h>
 #include <trace/events/kmem.h>
 
 #include "internal.h"
@@ -8484,6 +8485,12 @@ void __init kmem_cache_init(void)
 		boot_kmem_cache_node;
 	int node;
 
+	/* verify that kmem_cache_opaque is correct */
+	BUILD_BUG_ON(sizeof(struct kmem_cache) !=
+		     sizeof(struct kmem_cache_opaque));
+	BUILD_BUG_ON(__alignof(struct kmem_cache) !=
+		     __alignof(struct kmem_cache_opaque));
+
 	if (debug_guardpage_minorder())
 		slub_max_order = 0;
 
-- 
2.47.3



  reply	other threads:[~2026-06-13  5:10 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-10  4:02 [RFC PATCH 00/15] kmem_cache instances with static storage duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 01/15] static kmem_cache instances for core caches Al Viro
2026-01-10  5:40   ` Matthew Wilcox
2026-01-10  6:23     ` Al Viro
2026-01-14  7:30   ` Harry Yoo
2026-01-14  7:38     ` Al Viro
2026-01-15 16:59     ` Vlastimil Babka
2026-06-11 17:13       ` Al Viro
2026-06-11 17:14         ` [PATCH v2 0/9] kmem_cache instances with static storage duration Al Viro
2026-06-11 17:14           ` [PATCH v2 1/9] static kmem_cache instances for core caches Al Viro
2026-06-11 17:14           ` [PATCH v2 2/9] allow static-duration kmem_cache in modules Al Viro
2026-06-11 17:14           ` [PATCH v2 3/9] VFS caches: switch from runtime_const() machinery to slab-static.h Al Viro
2026-06-11 17:14           ` [PATCH v2 4/9] make inode_cache statically allocated Al Viro
2026-06-11 17:14           ` [PATCH v2 5/9] make mnt_cache " Al Viro
2026-06-11 17:14           ` [PATCH v2 6/9] make bh_cachep " Al Viro
2026-06-11 17:14           ` [PATCH v2 7/9] make seq_file_cache " Al Viro
2026-06-11 17:14           ` [PATCH v2 8/9] make thread component caches (fs_cachep, files_cachep, etc.) " Al Viro
2026-06-11 17:14           ` [PATCH v2 9/9] make ufs_inode_cache " Al Viro
2026-06-13  5:09           ` [RFC PATCH v3 00/10] kmem_cache instances with static storage duration Al Viro
2026-06-13  5:09             ` Al Viro [this message]
2026-06-13  5:09             ` [RFC PATCH v3 02/10] static kmem_cache instances for core caches: setup primitives Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 03/10] allow preallocated kmem_cache instances in modules Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 04/10] VFS caches: switch from runtime_const() machinery to slab-static.h Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 05/10] make inode_cache statically allocated Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 06/10] make mnt_cache " Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 07/10] make bh_cachep " Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 08/10] make seq_file_cache " Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 09/10] make thread component caches (fs_cachep, files_cachep, etc.) " Al Viro
2026-06-13  5:09             ` [RFC PATCH v3 10/10] make ufs_inode_cache " Al Viro
2026-06-23  8:09             ` [RFC PATCH v3 00/10] kmem_cache instances with static storage duration Vlastimil Babka (SUSE)
2026-06-24  0:48               ` Al Viro
2026-01-10  4:02 ` [RFC PATCH 02/15] allow static-duration kmem_cache in modules Al Viro
2026-01-10  4:02 ` [RFC PATCH 03/15] make mnt_cache static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 04/15] turn thread_cache static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 05/15] turn signal_cache static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 06/15] turn bh_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 07/15] turn dentry_cache static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 08/15] turn files_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 09/15] make filp and bfilp caches static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 10/15] turn sighand_cache static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 11/15] turn mm_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 12/15] turn task_struct_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 13/15] turn fs_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 14/15] turn inode_cachep static-duration Al Viro
2026-01-10  4:02 ` [RFC PATCH 15/15] turn ufs_inode_cache static-duration Al Viro
2026-01-10  5:33 ` [RFC PATCH 00/15] kmem_cache instances with static storage duration Linus Torvalds
2026-01-10  6:16   ` Al Viro
2026-01-14  7:12     ` Harry Yoo
2026-01-15  0:46 ` Christoph Lameter (Ampere)
2026-01-15  2:08   ` Al Viro
2026-01-15 19:10     ` Christoph Lameter (Ampere)
2026-01-15 19:44       ` Al Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260613050951.855141-2-viro@zeniv.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=brauner@kernel.org \
    --cc=harry.yoo@oracle.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mjguzik@gmail.com \
    --cc=torvalds@linux-foundation.org \
    --cc=vbabka@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox