mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-28 19:06:51 +01:00
Mateusz reported performance penalties [1] during task creation because pidfs uses pidmap_lock to add elements into the rbtree. Switch to an rhashtable to have separate fine-grained locking and to decouple from pidmap_lock moving all heavy manipulations outside of it. Convert the pidfs inode-to-pid mapping from an rb-tree with seqcount protection to an rhashtable. This removes the global pidmap_lock contention from pidfs_ino_get_pid() lookups and allows the hashtable insert to happen outside the pidmap_lock. pidfs_add_pid() is split. pidfs_prepare_pid() allocates inode number and initializes pid fields and is called inside pidmap_lock. pidfs_add_pid() inserts pid into rhashtable and is called outside pidmap_lock. Insertion into the rhashtable can fail and memory allocation may happen so we need to drop the spinlock. To guard against accidently opening an already reaped task pidfs_ino_get_pid() uses additional checks beyond pid_vnr(). If pid->attr is PIDFS_PID_DEAD or NULL the pid either never had a pidfd or it already went through pidfs_exit() aka the process as already reaped. If pid->attr is valid check PIDFS_ATTR_BIT_EXIT to figure out whether the task has exited. This slightly changes visibility semantics: pidfd creation is denied after pidfs_exit() runs, which is just before the pid number is removed from the via free_pid(). That should not be an issue though. Link: https://lore.kernel.org/20251206131955.780557-1-mjguzik@gmail.com [1] Link: https://patch.msgid.link/20260120-work-pidfs-rhashtable-v2-1-d593c4d0f576@kernel.org Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org>
21 lines
629 B
C
21 lines
629 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_PID_FS_H
|
|
#define _LINUX_PID_FS_H
|
|
|
|
struct coredump_params;
|
|
|
|
struct file *pidfs_alloc_file(struct pid *pid, unsigned int flags);
|
|
void __init pidfs_init(void);
|
|
void pidfs_prepare_pid(struct pid *pid);
|
|
int pidfs_add_pid(struct pid *pid);
|
|
void pidfs_remove_pid(struct pid *pid);
|
|
void pidfs_exit(struct task_struct *tsk);
|
|
#ifdef CONFIG_COREDUMP
|
|
void pidfs_coredump(const struct coredump_params *cprm);
|
|
#endif
|
|
extern const struct dentry_operations pidfs_dentry_operations;
|
|
int pidfs_register_pid(struct pid *pid);
|
|
void pidfs_free_pid(struct pid *pid);
|
|
|
|
#endif /* _LINUX_PID_FS_H */
|