Merge tag 'nfsd-5.7' of git://git.linux-nfs.org/projects/cel/cel-2.6
[linux-block.git] / fs / proc / base.c
index c7c64272b0fa6c57822a234616565896e7afd1ae..74f948a6b621f418c71803a2350f22a0dfade809 100644 (file)
@@ -405,11 +405,11 @@ print0:
 
 static int lock_trace(struct task_struct *task)
 {
-       int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+       int err = mutex_lock_killable(&task->signal->exec_update_mutex);
        if (err)
                return err;
        if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
-               mutex_unlock(&task->signal->cred_guard_mutex);
+               mutex_unlock(&task->signal->exec_update_mutex);
                return -EPERM;
        }
        return 0;
@@ -417,7 +417,7 @@ static int lock_trace(struct task_struct *task)
 
 static void unlock_trace(struct task_struct *task)
 {
-       mutex_unlock(&task->signal->cred_guard_mutex);
+       mutex_unlock(&task->signal->exec_update_mutex);
 }
 
 #ifdef CONFIG_STACKTRACE
@@ -1834,11 +1834,25 @@ void task_dump_owner(struct task_struct *task, umode_t mode,
        *rgid = gid;
 }
 
+void proc_pid_evict_inode(struct proc_inode *ei)
+{
+       struct pid *pid = ei->pid;
+
+       if (S_ISDIR(ei->vfs_inode.i_mode)) {
+               spin_lock(&pid->wait_pidfd.lock);
+               hlist_del_init_rcu(&ei->sibling_inodes);
+               spin_unlock(&pid->wait_pidfd.lock);
+       }
+
+       put_pid(pid);
+}
+
 struct inode *proc_pid_make_inode(struct super_block * sb,
                                  struct task_struct *task, umode_t mode)
 {
        struct inode * inode;
        struct proc_inode *ei;
+       struct pid *pid;
 
        /* We need a new inode */
 
@@ -1856,10 +1870,18 @@ struct inode *proc_pid_make_inode(struct super_block * sb,
        /*
         * grab the reference to task.
         */
-       ei->pid = get_task_pid(task, PIDTYPE_PID);
-       if (!ei->pid)
+       pid = get_task_pid(task, PIDTYPE_PID);
+       if (!pid)
                goto out_unlock;
 
+       /* Let the pid remember us for quick removal */
+       ei->pid = pid;
+       if (S_ISDIR(mode)) {
+               spin_lock(&pid->wait_pidfd.lock);
+               hlist_add_head_rcu(&ei->sibling_inodes, &pid->inodes);
+               spin_unlock(&pid->wait_pidfd.lock);
+       }
+
        task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
        security_task_to_inode(task, inode);
 
@@ -2861,7 +2883,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int wh
        unsigned long flags;
        int result;
 
-       result = mutex_lock_killable(&task->signal->cred_guard_mutex);
+       result = mutex_lock_killable(&task->signal->exec_update_mutex);
        if (result)
                return result;
 
@@ -2897,7 +2919,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int wh
        result = 0;
 
 out_unlock:
-       mutex_unlock(&task->signal->cred_guard_mutex);
+       mutex_unlock(&task->signal->exec_update_mutex);
        return result;
 }
 
@@ -3230,90 +3252,29 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
        .permission     = proc_pid_permission,
 };
 
-static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
-{
-       struct dentry *dentry, *leader, *dir;
-       char buf[10 + 1];
-       struct qstr name;
-
-       name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%u", pid);
-       /* no ->d_hash() rejects on procfs */
-       dentry = d_hash_and_lookup(mnt->mnt_root, &name);
-       if (dentry) {
-               d_invalidate(dentry);
-               dput(dentry);
-       }
-
-       if (pid == tgid)
-               return;
-
-       name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%u", tgid);
-       leader = d_hash_and_lookup(mnt->mnt_root, &name);
-       if (!leader)
-               goto out;
-
-       name.name = "task";
-       name.len = strlen(name.name);
-       dir = d_hash_and_lookup(leader, &name);
-       if (!dir)
-               goto out_put_leader;
-
-       name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%u", pid);
-       dentry = d_hash_and_lookup(dir, &name);
-       if (dentry) {
-               d_invalidate(dentry);
-               dput(dentry);
-       }
-
-       dput(dir);
-out_put_leader:
-       dput(leader);
-out:
-       return;
-}
-
 /**
- * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
- * @task: task that should be flushed.
+ * proc_flush_pid -  Remove dcache entries for @pid from the /proc dcache.
+ * @pid: pid that should be flushed.
  *
- * When flushing dentries from proc, one needs to flush them from global
- * proc (proc_mnt) and from all the namespaces' procs this task was seen
- * in. This call is supposed to do all of this job.
- *
- * Looks in the dcache for
- * /proc/@pid
- * /proc/@tgid/task/@pid
- * if either directory is present flushes it and all of it'ts children
- * from the dcache.
+ * This function walks a list of inodes (that belong to any proc
+ * filesystem) that are attached to the pid and flushes them from
+ * the dentry cache.
  *
  * It is safe and reasonable to cache /proc entries for a task until
  * that task exits.  After that they just clog up the dcache with
  * useless entries, possibly causing useful dcache entries to be
- * flushed instead.  This routine is proved to flush those useless
- * dcache entries at process exit time.
+ * flushed instead.  This routine is provided to flush those useless
+ * dcache entries when a process is reaped.
  *
  * NOTE: This routine is just an optimization so it does not guarantee
- *       that no dcache entries will exist at process exit time it
- *       just makes it very unlikely that any will persist.
+ *       that no dcache entries will exist after a process is reaped
+ *       it just makes it very unlikely that any will persist.
  */
 
-void proc_flush_task(struct task_struct *task)
+void proc_flush_pid(struct pid *pid)
 {
-       int i;
-       struct pid *pid, *tgid;
-       struct upid *upid;
-
-       pid = task_pid(task);
-       tgid = task_tgid(task);
-
-       for (i = 0; i <= pid->level; i++) {
-               upid = &pid->numbers[i];
-               proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
-                                       tgid->numbers[i].nr);
-       }
+       proc_invalidate_siblings_dcache(&pid->inodes, &pid->wait_pidfd.lock);
+       put_pid(pid);
 }
 
 static struct dentry *proc_pid_instantiate(struct dentry * dentry,