All of 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:09 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.