Skip to content

Commit 50f4f2d

Browse files
committed
pidfd: move struct pidfd_fops
Move the pidfd file operations over to their own file in preparation of implementing pidfs and to isolate them from other mostly unrelated functionality in other files. Link: https://lore.kernel.org/r/20240213-vfs-pidfd_fs-v1-1-f863f58cfce1@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent e1fb1dc commit 50f4f2d

File tree

3 files changed

+123
-111
lines changed

3 files changed

+123
-111
lines changed

fs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ obj-y := open.o read_write.o file_table.o super.o \
1515
pnode.o splice.o sync.o utimes.o d_path.o \
1616
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
1717
fs_types.o fs_context.o fs_parser.o fsopen.o init.o \
18-
kernel_read_file.o mnt_idmapping.o remap_range.o
18+
kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o
1919

2020
obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o
2121
obj-$(CONFIG_PROC_FS) += proc_namespace.o

fs/pidfs.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/file.h>
3+
#include <linux/fs.h>
4+
#include <linux/magic.h>
5+
#include <linux/mount.h>
6+
#include <linux/pid.h>
7+
#include <linux/pid_namespace.h>
8+
#include <linux/poll.h>
9+
#include <linux/proc_fs.h>
10+
#include <linux/proc_ns.h>
11+
#include <linux/pseudo_fs.h>
12+
#include <linux/seq_file.h>
13+
#include <uapi/linux/pidfd.h>
14+
15+
static int pidfd_release(struct inode *inode, struct file *file)
16+
{
17+
struct pid *pid = file->private_data;
18+
19+
file->private_data = NULL;
20+
put_pid(pid);
21+
return 0;
22+
}
23+
24+
#ifdef CONFIG_PROC_FS
25+
/**
26+
* pidfd_show_fdinfo - print information about a pidfd
27+
* @m: proc fdinfo file
28+
* @f: file referencing a pidfd
29+
*
30+
* Pid:
31+
* This function will print the pid that a given pidfd refers to in the
32+
* pid namespace of the procfs instance.
33+
* If the pid namespace of the process is not a descendant of the pid
34+
* namespace of the procfs instance 0 will be shown as its pid. This is
35+
* similar to calling getppid() on a process whose parent is outside of
36+
* its pid namespace.
37+
*
38+
* NSpid:
39+
* If pid namespaces are supported then this function will also print
40+
* the pid of a given pidfd refers to for all descendant pid namespaces
41+
* starting from the current pid namespace of the instance, i.e. the
42+
* Pid field and the first entry in the NSpid field will be identical.
43+
* If the pid namespace of the process is not a descendant of the pid
44+
* namespace of the procfs instance 0 will be shown as its first NSpid
45+
* entry and no others will be shown.
46+
* Note that this differs from the Pid and NSpid fields in
47+
* /proc/<pid>/status where Pid and NSpid are always shown relative to
48+
* the pid namespace of the procfs instance. The difference becomes
49+
* obvious when sending around a pidfd between pid namespaces from a
50+
* different branch of the tree, i.e. where no ancestral relation is
51+
* present between the pid namespaces:
52+
* - create two new pid namespaces ns1 and ns2 in the initial pid
53+
* namespace (also take care to create new mount namespaces in the
54+
* new pid namespace and mount procfs)
55+
* - create a process with a pidfd in ns1
56+
* - send pidfd from ns1 to ns2
57+
* - read /proc/self/fdinfo/<pidfd> and observe that both Pid and NSpid
58+
* have exactly one entry, which is 0
59+
*/
60+
static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
61+
{
62+
struct pid *pid = f->private_data;
63+
struct pid_namespace *ns;
64+
pid_t nr = -1;
65+
66+
if (likely(pid_has_task(pid, PIDTYPE_PID))) {
67+
ns = proc_pid_ns(file_inode(m->file)->i_sb);
68+
nr = pid_nr_ns(pid, ns);
69+
}
70+
71+
seq_put_decimal_ll(m, "Pid:\t", nr);
72+
73+
#ifdef CONFIG_PID_NS
74+
seq_put_decimal_ll(m, "\nNSpid:\t", nr);
75+
if (nr > 0) {
76+
int i;
77+
78+
/* If nr is non-zero it means that 'pid' is valid and that
79+
* ns, i.e. the pid namespace associated with the procfs
80+
* instance, is in the pid namespace hierarchy of pid.
81+
* Start at one below the already printed level.
82+
*/
83+
for (i = ns->level + 1; i <= pid->level; i++)
84+
seq_put_decimal_ll(m, "\t", pid->numbers[i].nr);
85+
}
86+
#endif
87+
seq_putc(m, '\n');
88+
}
89+
#endif
90+
91+
/*
92+
* Poll support for process exit notification.
93+
*/
94+
static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
95+
{
96+
struct pid *pid = file->private_data;
97+
bool thread = file->f_flags & PIDFD_THREAD;
98+
struct task_struct *task;
99+
__poll_t poll_flags = 0;
100+
101+
poll_wait(file, &pid->wait_pidfd, pts);
102+
/*
103+
* Depending on PIDFD_THREAD, inform pollers when the thread
104+
* or the whole thread-group exits.
105+
*/
106+
guard(rcu)();
107+
task = pid_task(pid, PIDTYPE_PID);
108+
if (!task)
109+
poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP;
110+
else if (task->exit_state && (thread || thread_group_empty(task)))
111+
poll_flags = EPOLLIN | EPOLLRDNORM;
112+
113+
return poll_flags;
114+
}
115+
116+
const struct file_operations pidfd_fops = {
117+
.release = pidfd_release,
118+
.poll = pidfd_poll,
119+
#ifdef CONFIG_PROC_FS
120+
.show_fdinfo = pidfd_show_fdinfo,
121+
#endif
122+
};

kernel/fork.c

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,116 +1993,6 @@ struct pid *pidfd_pid(const struct file *file)
19931993
return ERR_PTR(-EBADF);
19941994
}
19951995

1996-
static int pidfd_release(struct inode *inode, struct file *file)
1997-
{
1998-
struct pid *pid = file->private_data;
1999-
2000-
file->private_data = NULL;
2001-
put_pid(pid);
2002-
return 0;
2003-
}
2004-
2005-
#ifdef CONFIG_PROC_FS
2006-
/**
2007-
* pidfd_show_fdinfo - print information about a pidfd
2008-
* @m: proc fdinfo file
2009-
* @f: file referencing a pidfd
2010-
*
2011-
* Pid:
2012-
* This function will print the pid that a given pidfd refers to in the
2013-
* pid namespace of the procfs instance.
2014-
* If the pid namespace of the process is not a descendant of the pid
2015-
* namespace of the procfs instance 0 will be shown as its pid. This is
2016-
* similar to calling getppid() on a process whose parent is outside of
2017-
* its pid namespace.
2018-
*
2019-
* NSpid:
2020-
* If pid namespaces are supported then this function will also print
2021-
* the pid of a given pidfd refers to for all descendant pid namespaces
2022-
* starting from the current pid namespace of the instance, i.e. the
2023-
* Pid field and the first entry in the NSpid field will be identical.
2024-
* If the pid namespace of the process is not a descendant of the pid
2025-
* namespace of the procfs instance 0 will be shown as its first NSpid
2026-
* entry and no others will be shown.
2027-
* Note that this differs from the Pid and NSpid fields in
2028-
* /proc/<pid>/status where Pid and NSpid are always shown relative to
2029-
* the pid namespace of the procfs instance. The difference becomes
2030-
* obvious when sending around a pidfd between pid namespaces from a
2031-
* different branch of the tree, i.e. where no ancestral relation is
2032-
* present between the pid namespaces:
2033-
* - create two new pid namespaces ns1 and ns2 in the initial pid
2034-
* namespace (also take care to create new mount namespaces in the
2035-
* new pid namespace and mount procfs)
2036-
* - create a process with a pidfd in ns1
2037-
* - send pidfd from ns1 to ns2
2038-
* - read /proc/self/fdinfo/<pidfd> and observe that both Pid and NSpid
2039-
* have exactly one entry, which is 0
2040-
*/
2041-
static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
2042-
{
2043-
struct pid *pid = f->private_data;
2044-
struct pid_namespace *ns;
2045-
pid_t nr = -1;
2046-
2047-
if (likely(pid_has_task(pid, PIDTYPE_PID))) {
2048-
ns = proc_pid_ns(file_inode(m->file)->i_sb);
2049-
nr = pid_nr_ns(pid, ns);
2050-
}
2051-
2052-
seq_put_decimal_ll(m, "Pid:\t", nr);
2053-
2054-
#ifdef CONFIG_PID_NS
2055-
seq_put_decimal_ll(m, "\nNSpid:\t", nr);
2056-
if (nr > 0) {
2057-
int i;
2058-
2059-
/* If nr is non-zero it means that 'pid' is valid and that
2060-
* ns, i.e. the pid namespace associated with the procfs
2061-
* instance, is in the pid namespace hierarchy of pid.
2062-
* Start at one below the already printed level.
2063-
*/
2064-
for (i = ns->level + 1; i <= pid->level; i++)
2065-
seq_put_decimal_ll(m, "\t", pid->numbers[i].nr);
2066-
}
2067-
#endif
2068-
seq_putc(m, '\n');
2069-
}
2070-
#endif
2071-
2072-
/*
2073-
* Poll support for process exit notification.
2074-
*/
2075-
static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
2076-
{
2077-
struct pid *pid = file->private_data;
2078-
bool thread = file->f_flags & PIDFD_THREAD;
2079-
struct task_struct *task;
2080-
__poll_t poll_flags = 0;
2081-
2082-
poll_wait(file, &pid->wait_pidfd, pts);
2083-
/*
2084-
* Depending on PIDFD_THREAD, inform pollers when the thread
2085-
* or the whole thread-group exits.
2086-
*/
2087-
rcu_read_lock();
2088-
task = pid_task(pid, PIDTYPE_PID);
2089-
if (!task)
2090-
poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP;
2091-
else if (task->exit_state && (thread || thread_group_empty(task)))
2092-
poll_flags = EPOLLIN | EPOLLRDNORM;
2093-
rcu_read_unlock();
2094-
2095-
return poll_flags;
2096-
}
2097-
2098-
const struct file_operations pidfd_fops = {
2099-
.release = pidfd_release,
2100-
.poll = pidfd_poll,
2101-
#ifdef CONFIG_PROC_FS
2102-
.show_fdinfo = pidfd_show_fdinfo,
2103-
#endif
2104-
};
2105-
21061996
/**
21071997
* __pidfd_prepare - allocate a new pidfd_file and reserve a pidfd
21081998
* @pid: the struct pid for which to create a pidfd

0 commit comments

Comments
 (0)