debugfs: separate cache for debugfs inodes
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Jan 2025 08:06:45 +0000 (08:06 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Jan 2025 12:14:35 +0000 (13:14 +0100)
Embed them into container (struct debugfs_inode_info, with nothing
else in it at the moment), set the cache up, etc.

Just the infrastructure changes letting us augment debugfs inodes
here; adding stuff will come at the next step.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/r/20250112080705.141166-1-viro@zeniv.linux.org.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/debugfs/inode.c
fs/debugfs/internal.h

index e752009de9292dbac2691b1ccc2bdfe379b2e52e..5d423bd92f93475bf96f575ffef1d2596d0b7cef 100644 (file)
@@ -208,16 +208,34 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
        return 0;
 }
 
+static struct kmem_cache *debugfs_inode_cachep __ro_after_init;
+
+static void init_once(void *foo)
+{
+       struct debugfs_inode_info *info = foo;
+       inode_init_once(&info->vfs_inode);
+}
+
+static struct inode *debugfs_alloc_inode(struct super_block *sb)
+{
+       struct debugfs_inode_info *info;
+       info = alloc_inode_sb(sb, debugfs_inode_cachep, GFP_KERNEL);
+       if (!info)
+               return NULL;
+       return &info->vfs_inode;
+}
+
 static void debugfs_free_inode(struct inode *inode)
 {
        if (S_ISLNK(inode->i_mode))
                kfree(inode->i_link);
-       free_inode_nonrcu(inode);
+       kmem_cache_free(debugfs_inode_cachep, DEBUGFS_I(inode));
 }
 
 static const struct super_operations debugfs_super_operations = {
        .statfs         = simple_statfs,
        .show_options   = debugfs_show_options,
+       .alloc_inode    = debugfs_alloc_inode,
        .free_inode     = debugfs_free_inode,
 };
 
@@ -939,12 +957,22 @@ static int __init debugfs_init(void)
        if (retval)
                return retval;
 
-       retval = register_filesystem(&debug_fs_type);
-       if (retval)
+       debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
+                               sizeof(struct debugfs_inode_info), 0,
+                               SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
+                               init_once);
+       if (debugfs_inode_cachep == NULL) {
                sysfs_remove_mount_point(kernel_kobj, "debug");
-       else
-               debugfs_registered = true;
+               return -ENOMEM;
+       }
 
-       return retval;
+       retval = register_filesystem(&debug_fs_type);
+       if (retval) { // Really not going to happen
+               sysfs_remove_mount_point(kernel_kobj, "debug");
+               kmem_cache_destroy(debugfs_inode_cachep);
+               return retval;
+       }
+       debugfs_registered = true;
+       return 0;
 }
 core_initcall(debugfs_init);
index bbae4a228ef4e280d1638b3634e8a73ec473abb0..5cb940b0b8f67bb9939aefda39f8520885d4c77e 100644 (file)
 
 struct file_operations;
 
+struct debugfs_inode_info {
+       struct inode vfs_inode;
+};
+
+static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
+{
+       return container_of(inode, struct debugfs_inode_info, vfs_inode);
+}
+
 /* declared over in file.c */
 extern const struct file_operations debugfs_noop_file_operations;
 extern const struct file_operations debugfs_open_proxy_file_operations;