#endif
 };
 
-/**
- * pidfd_create() - Create a new pid file descriptor.
- *
- * @pid:  struct pid that the pidfd will reference
- *
- * This creates a new pid file descriptor with the O_CLOEXEC flag set.
- *
- * Note, that this function can only be called after the fd table has
- * been unshared to avoid leaking the pidfd to the new process.
- *
- * Return: On success, a cloexec pidfd is returned.
- *         On error, a negative errno number will be returned.
- */
-static int pidfd_create(struct pid *pid)
-{
-       int fd;
-
-       fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid),
-                             O_RDWR | O_CLOEXEC);
-       if (fd < 0)
-               put_pid(pid);
-
-       return fd;
-}
-
 static void __delayed_free_task(struct rcu_head *rhp)
 {
        struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
        int pidfd = -1, retval;
        struct task_struct *p;
        struct multiprocess_signals delayed;
+       struct file *pidfile = NULL;
 
        /*
         * Don't allow sharing the root directory with processes in a different
         * if the fd table isn't shared).
         */
        if (clone_flags & CLONE_PIDFD) {
-               retval = pidfd_create(pid);
+               retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
                if (retval < 0)
                        goto bad_fork_free_pid;
 
                pidfd = retval;
+
+               pidfile = anon_inode_getfile("[pidfd]", &pidfd_fops, pid,
+                                             O_RDWR | O_CLOEXEC);
+               if (IS_ERR(pidfile)) {
+                       put_unused_fd(pidfd);
+                       goto bad_fork_free_pid;
+               }
+               get_pid(pid);   /* held by pidfile now */
+
                retval = put_user(pidfd, parent_tidptr);
                if (retval)
                        goto bad_fork_put_pidfd;
                goto bad_fork_cancel_cgroup;
        }
 
+       /* past the last point of failure */
+       if (pidfile)
+               fd_install(pidfd, pidfile);
 
        init_task_pid_links(p);
        if (likely(p->pid)) {
 bad_fork_cgroup_threadgroup_change_end:
        cgroup_threadgroup_change_end(current);
 bad_fork_put_pidfd:
-       if (clone_flags & CLONE_PIDFD)
-               ksys_close(pidfd);
+       if (clone_flags & CLONE_PIDFD) {
+               fput(pidfile);
+               put_unused_fd(pidfd);
+       }
 bad_fork_free_pid:
        if (pid != &init_struct_pid)
                free_pid(pid);