pidfs: use private inode slab cache

Introduce a private inode slab cache for pidfs. In follow-up patches
pidfs will gain the ability to provide exit information to userspace
after the task has been reaped. This means storing exit information even
after the task has already been released and struct pid's task linkage
is gone. Store that information alongside the inode.

Link: https://lore.kernel.org/r/20250305-work-pidfs-kill_on_last_close-v3-4-c8c3d8361705@kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2025-03-05 11:08:14 +01:00
parent 3155a19407
commit 0b4200381e
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -24,6 +24,27 @@
#include "internal.h"
#include "mount.h"
static struct kmem_cache *pidfs_cachep __ro_after_init;
/*
* Stashes information that userspace needs to access even after the
* process has been reaped.
*/
struct pidfs_exit_info {
__u64 cgroupid;
__s32 exit_code;
};
struct pidfs_inode {
struct pidfs_exit_info exit_info;
struct inode vfs_inode;
};
static inline struct pidfs_inode *pidfs_i(struct inode *inode)
{
return container_of(inode, struct pidfs_inode, vfs_inode);
}
static struct rb_root pidfs_ino_tree = RB_ROOT;
#if BITS_PER_LONG == 32
@ -492,9 +513,29 @@ static void pidfs_evict_inode(struct inode *inode)
put_pid(pid);
}
static struct inode *pidfs_alloc_inode(struct super_block *sb)
{
struct pidfs_inode *pi;
pi = alloc_inode_sb(sb, pidfs_cachep, GFP_KERNEL);
if (!pi)
return NULL;
memset(&pi->exit_info, 0, sizeof(pi->exit_info));
return &pi->vfs_inode;
}
static void pidfs_free_inode(struct inode *inode)
{
kmem_cache_free(pidfs_cachep, pidfs_i(inode));
}
static const struct super_operations pidfs_sops = {
.alloc_inode = pidfs_alloc_inode,
.drop_inode = generic_delete_inode,
.evict_inode = pidfs_evict_inode,
.free_inode = pidfs_free_inode,
.statfs = simple_statfs,
};
@ -704,8 +745,19 @@ struct file *pidfs_alloc_file(struct pid *pid, unsigned int flags)
return pidfd_file;
}
static void pidfs_inode_init_once(void *data)
{
struct pidfs_inode *pi = data;
inode_init_once(&pi->vfs_inode);
}
void __init pidfs_init(void)
{
pidfs_cachep = kmem_cache_create("pidfs_cache", sizeof(struct pidfs_inode), 0,
(SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT |
SLAB_ACCOUNT | SLAB_PANIC),
pidfs_inode_init_once);
pidfs_mnt = kern_mount(&pidfs_type);
if (IS_ERR(pidfs_mnt))
panic("Failed to mount pidfs pseudo filesystem");