Message ID | 20211011133245.1703103-2-brauner@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Introduce simple pidfd to task helper | expand |
On 11.10.21 15:32, Christian Brauner wrote: > From: Christian Brauner <christian.brauner@ubuntu.com> > > The number of system calls making use of pidfds is constantly > increasing. Some of those new system calls duplicate the code to turn a > pidfd into task_struct it refers to. Give them a simple helper for this. > > Link: https://lore.kernel.org/r/20211004125050.1153693-2-christian.brauner@ubuntu.com > Cc: Vlastimil Babka <vbabka@suse.cz> > Cc: Suren Baghdasaryan <surenb@google.com> > Cc: Matthew Bobrowski <repnop@google.com> > Cc: Alexander Duyck <alexander.h.duyck@linux.intel.com> > Cc: David Hildenbrand <david@redhat.com> > Cc: Jan Kara <jack@suse.cz> > Cc: Minchan Kim <minchan@kernel.org> > Reviewed-by: Matthew Bobrowski <repnop@google.com> > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com> > --- > /* v2 */ > - David Hildenbrand <david@redhat.com>: > - Also document that the caller is expected to decrease the reference > count on the returned task. > --- > include/linux/pid.h | 1 + > kernel/pid.c | 36 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 37 insertions(+) > > diff --git a/include/linux/pid.h b/include/linux/pid.h > index af308e15f174..343abf22092e 100644 > --- a/include/linux/pid.h > +++ b/include/linux/pid.h > @@ -78,6 +78,7 @@ struct file; > > extern struct pid *pidfd_pid(const struct file *file); > struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags); > +struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags); > int pidfd_create(struct pid *pid, unsigned int flags); > > static inline struct pid *get_pid(struct pid *pid) > diff --git a/kernel/pid.c b/kernel/pid.c > index efe87db44683..2fc0a16ec77b 100644 > --- a/kernel/pid.c > +++ b/kernel/pid.c > @@ -539,6 +539,42 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags) > return pid; > } > > +/** > + * pidfd_get_task() - Get the task associated with a pidfd > + * > + * @pidfd: pidfd for which to get the task > + * @flags: flags associated with this pidfd > + * > + * Return the task associated with @pidfd. The function takes a reference on > + * the returned task. The caller is responsible for releasing that reference. > + * > + * Currently, the process identified by @pidfd is always a thread-group leader. > + * This restriction currently exists for all aspects of pidfds including pidfd > + * creation (CLONE_PIDFD cannot be used with CLONE_THREAD) and pidfd polling > + * (only supports thread group leaders). > + * > + * Return: On success, the task_struct associated with the pidfd. > + * On error, a negative errno number will be returned. > + */ > +struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags) > +{ > + unsigned int f_flags; > + struct pid *pid; > + struct task_struct *task; > + > + pid = pidfd_get_pid(pidfd, &f_flags); > + if (IS_ERR(pid)) > + return ERR_CAST(pid); > + > + task = get_pid_task(pid, PIDTYPE_TGID); > + put_pid(pid); > + if (!task) > + return ERR_PTR(-ESRCH); > + > + *flags = f_flags; > + return task; > +} > + > /** > * pidfd_create() - Create a new pid file descriptor. > * > Acked-by: David Hildenbrand <david@redhat.com>
diff --git a/include/linux/pid.h b/include/linux/pid.h index af308e15f174..343abf22092e 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -78,6 +78,7 @@ struct file; extern struct pid *pidfd_pid(const struct file *file); struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags); +struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags); int pidfd_create(struct pid *pid, unsigned int flags); static inline struct pid *get_pid(struct pid *pid) diff --git a/kernel/pid.c b/kernel/pid.c index efe87db44683..2fc0a16ec77b 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -539,6 +539,42 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags) return pid; } +/** + * pidfd_get_task() - Get the task associated with a pidfd + * + * @pidfd: pidfd for which to get the task + * @flags: flags associated with this pidfd + * + * Return the task associated with @pidfd. The function takes a reference on + * the returned task. The caller is responsible for releasing that reference. + * + * Currently, the process identified by @pidfd is always a thread-group leader. + * This restriction currently exists for all aspects of pidfds including pidfd + * creation (CLONE_PIDFD cannot be used with CLONE_THREAD) and pidfd polling + * (only supports thread group leaders). + * + * Return: On success, the task_struct associated with the pidfd. + * On error, a negative errno number will be returned. + */ +struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags) +{ + unsigned int f_flags; + struct pid *pid; + struct task_struct *task; + + pid = pidfd_get_pid(pidfd, &f_flags); + if (IS_ERR(pid)) + return ERR_CAST(pid); + + task = get_pid_task(pid, PIDTYPE_TGID); + put_pid(pid); + if (!task) + return ERR_PTR(-ESRCH); + + *flags = f_flags; + return task; +} + /** * pidfd_create() - Create a new pid file descriptor. *