Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=60347f6716aa49831ac311e04d77ccdc50dc024a
Commit:     60347f6716aa49831ac311e04d77ccdc50dc024a
Parent:     8bf9725c29f2589237dd696d06a204230add0ba3
Author:     Pavel Emelyanov <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 23:40:03 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri Oct 19 11:53:38 2007 -0700

    pid namespaces: prepare proc_flust_task() to flush entries from multiple 
proc trees
    
    The first part is trivial - we just make the proc_flush_task() to operate on
    arbitrary vfsmount with arbitrary ids and pass the pid and global proc_mnt 
to
    it.
    
    The other change is more tricky: I moved the proc_flush_task() call in
    release_task() higher to address the following problem.
    
    When flushing task from many proc trees we need to know the set of ids (not
    just one pid) to find the dentries' names to flush.  Thus we need to pass 
the
    task's pid to proc_flush_task() as struct pid is the only object that can
    provide all the pid numbers.  But after __exit_signal() task has detached 
all
    his pids and this information is lost.
    
    This creates a tiny gap for proc_pid_lookup() to bring some dentries back to
    tree and keep them in hash (since pids are still alive before 
__exit_signal())
    till the next shrink, but since proc_flush_task() does not provide a 100%
    guarantee that the dentries will be flushed, this is OK to do so.
    
    Signed-off-by: Pavel Emelyanov <[EMAIL PROTECTED]>
    Cc: Oleg Nesterov <[EMAIL PROTECTED]>
    Cc: Sukadev Bhattiprolu <[EMAIL PROTECTED]>
    Cc: Paul Menage <[EMAIL PROTECTED]>
    Cc: "Eric W. Biederman" <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/proc/base.c          |   27 ++++++++++++++++++++-------
 include/linux/proc_fs.h |    4 +++-
 kernel/exit.c           |    2 +-
 3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6afca09..36983e7 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -74,6 +74,7 @@
 #include <linux/nsproxy.h>
 #include <linux/oom.h>
 #include <linux/elf.h>
+#include <linux/pid_namespace.h>
 #include "internal.h"
 
 /* NOTE:
@@ -2204,27 +2205,27 @@ static const struct inode_operations 
proc_tgid_base_inode_operations = {
  *       that no dcache entries will exist at process exit time it
  *       just makes it very unlikely that any will persist.
  */
-void proc_flush_task(struct task_struct *task)
+static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
 {
        struct dentry *dentry, *leader, *dir;
        char buf[PROC_NUMBUF];
        struct qstr name;
 
        name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
-       dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+       name.len = snprintf(buf, sizeof(buf), "%d", pid);
+       dentry = d_hash_and_lookup(mnt->mnt_root, &name);
        if (dentry) {
                shrink_dcache_parent(dentry);
                d_drop(dentry);
                dput(dentry);
        }
 
-       if (thread_group_leader(task))
+       if (tgid == 0)
                goto out;
 
        name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%d", task->tgid);
-       leader = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+       name.len = snprintf(buf, sizeof(buf), "%d", tgid);
+       leader = d_hash_and_lookup(mnt->mnt_root, &name);
        if (!leader)
                goto out;
 
@@ -2235,7 +2236,7 @@ void proc_flush_task(struct task_struct *task)
                goto out_put_leader;
 
        name.name = buf;
-       name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
+       name.len = snprintf(buf, sizeof(buf), "%d", pid);
        dentry = d_hash_and_lookup(dir, &name);
        if (dentry) {
                shrink_dcache_parent(dentry);
@@ -2250,6 +2251,18 @@ out:
        return;
 }
 
+/*
+ * when flushing dentries from proc one need to flush them from global
+ * proc (proc_mnt) and from all the namespaces' procs this task was seen
+ * in. this call is supposed to make all this job.
+ */
+
+void proc_flush_task(struct task_struct *task)
+{
+       proc_flush_task_mnt(proc_mnt, task->pid,
+                       thread_group_leader(task) ? 0 : task->tgid);
+}
+
 static struct dentry *proc_pid_instantiate(struct inode *dir,
                                           struct dentry * dentry,
                                           struct task_struct *task, const void 
*ptr)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 20741f6..dbd601c 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -207,7 +207,9 @@ extern void proc_net_remove(struct net *net, const char 
*name);
 #define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; })
 static inline void proc_net_remove(struct net *net, const char *name) {}
 
-static inline void proc_flush_task(struct task_struct *task) { }
+static inline void proc_flush_task(struct task_struct *task)
+{
+}
 
 static inline struct proc_dir_entry *create_proc_entry(const char *name,
        mode_t mode, struct proc_dir_entry *parent) { return NULL; }
diff --git a/kernel/exit.c b/kernel/exit.c
index df2eee9..d9e8e5e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -148,6 +148,7 @@ void release_task(struct task_struct * p)
        int zap_leader;
 repeat:
        atomic_dec(&p->user->processes);
+       proc_flush_task(p);
        write_lock_irq(&tasklist_lock);
        ptrace_unlink(p);
        BUG_ON(!list_empty(&p->ptrace_list) || 
!list_empty(&p->ptrace_children));
@@ -175,7 +176,6 @@ repeat:
        }
 
        write_unlock_irq(&tasklist_lock);
-       proc_flush_task(p);
        release_thread(p);
        call_rcu(&p->rcu, delayed_put_task_struct);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to