aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c27
-rw-r--r--include/linux/proc_fs.h4
-rw-r--r--kernel/exit.c2
3 files changed, 24 insertions, 9 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6afca09a6534..36983e7bb2c1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -74,6 +74,7 @@
74#include <linux/nsproxy.h> 74#include <linux/nsproxy.h>
75#include <linux/oom.h> 75#include <linux/oom.h>
76#include <linux/elf.h> 76#include <linux/elf.h>
77#include <linux/pid_namespace.h>
77#include "internal.h" 78#include "internal.h"
78 79
79/* NOTE: 80/* NOTE:
@@ -2204,27 +2205,27 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
2204 * that no dcache entries will exist at process exit time it 2205 * that no dcache entries will exist at process exit time it
2205 * just makes it very unlikely that any will persist. 2206 * just makes it very unlikely that any will persist.
2206 */ 2207 */
2207void proc_flush_task(struct task_struct *task) 2208static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
2208{ 2209{
2209 struct dentry *dentry, *leader, *dir; 2210 struct dentry *dentry, *leader, *dir;
2210 char buf[PROC_NUMBUF]; 2211 char buf[PROC_NUMBUF];
2211 struct qstr name; 2212 struct qstr name;
2212 2213
2213 name.name = buf; 2214 name.name = buf;
2214 name.len = snprintf(buf, sizeof(buf), "%d", task->pid); 2215 name.len = snprintf(buf, sizeof(buf), "%d", pid);
2215 dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name); 2216 dentry = d_hash_and_lookup(mnt->mnt_root, &name);
2216 if (dentry) { 2217 if (dentry) {
2217 shrink_dcache_parent(dentry); 2218 shrink_dcache_parent(dentry);
2218 d_drop(dentry); 2219 d_drop(dentry);
2219 dput(dentry); 2220 dput(dentry);
2220 } 2221 }
2221 2222
2222 if (thread_group_leader(task)) 2223 if (tgid == 0)
2223 goto out; 2224 goto out;
2224 2225
2225 name.name = buf; 2226 name.name = buf;
2226 name.len = snprintf(buf, sizeof(buf), "%d", task->tgid); 2227 name.len = snprintf(buf, sizeof(buf), "%d", tgid);
2227 leader = d_hash_and_lookup(proc_mnt->mnt_root, &name); 2228 leader = d_hash_and_lookup(mnt->mnt_root, &name);
2228 if (!leader) 2229 if (!leader)
2229 goto out; 2230 goto out;
2230 2231
@@ -2235,7 +2236,7 @@ void proc_flush_task(struct task_struct *task)
2235 goto out_put_leader; 2236 goto out_put_leader;
2236 2237
2237 name.name = buf; 2238 name.name = buf;
2238 name.len = snprintf(buf, sizeof(buf), "%d", task->pid); 2239 name.len = snprintf(buf, sizeof(buf), "%d", pid);
2239 dentry = d_hash_and_lookup(dir, &name); 2240 dentry = d_hash_and_lookup(dir, &name);
2240 if (dentry) { 2241 if (dentry) {
2241 shrink_dcache_parent(dentry); 2242 shrink_dcache_parent(dentry);
@@ -2250,6 +2251,18 @@ out:
2250 return; 2251 return;
2251} 2252}
2252 2253
2254/*
2255 * when flushing dentries from proc one need to flush them from global
2256 * proc (proc_mnt) and from all the namespaces' procs this task was seen
2257 * in. this call is supposed to make all this job.
2258 */
2259
2260void proc_flush_task(struct task_struct *task)
2261{
2262 proc_flush_task_mnt(proc_mnt, task->pid,
2263 thread_group_leader(task) ? 0 : task->tgid);
2264}
2265
2253static struct dentry *proc_pid_instantiate(struct inode *dir, 2266static struct dentry *proc_pid_instantiate(struct inode *dir,
2254 struct dentry * dentry, 2267 struct dentry * dentry,
2255 struct task_struct *task, const void *ptr) 2268 struct task_struct *task, const void *ptr)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 20741f668f7b..dbd601c7244c 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);
207#define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; }) 207#define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; })
208static inline void proc_net_remove(struct net *net, const char *name) {} 208static inline void proc_net_remove(struct net *net, const char *name) {}
209 209
210static inline void proc_flush_task(struct task_struct *task) { } 210static inline void proc_flush_task(struct task_struct *task)
211{
212}
211 213
212static inline struct proc_dir_entry *create_proc_entry(const char *name, 214static inline struct proc_dir_entry *create_proc_entry(const char *name,
213 mode_t mode, struct proc_dir_entry *parent) { return NULL; } 215 mode_t mode, struct proc_dir_entry *parent) { return NULL; }
diff --git a/kernel/exit.c b/kernel/exit.c
index df2eee9c68ce..d9e8e5ee9d7f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -148,6 +148,7 @@ void release_task(struct task_struct * p)
148 int zap_leader; 148 int zap_leader;
149repeat: 149repeat:
150 atomic_dec(&p->user->processes); 150 atomic_dec(&p->user->processes);
151 proc_flush_task(p);
151 write_lock_irq(&tasklist_lock); 152 write_lock_irq(&tasklist_lock);
152 ptrace_unlink(p); 153 ptrace_unlink(p);
153 BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); 154 BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
@@ -175,7 +176,6 @@ repeat:
175 } 176 }
176 177
177 write_unlock_irq(&tasklist_lock); 178 write_unlock_irq(&tasklist_lock);
178 proc_flush_task(p);
179 release_thread(p); 179 release_thread(p);
180 call_rcu(&p->rcu, delayed_put_task_struct); 180 call_rcu(&p->rcu, delayed_put_task_struct);
181 181