diff options
-rw-r--r-- | fs/proc/base.c | 27 | ||||
-rw-r--r-- | include/linux/proc_fs.h | 4 | ||||
-rw-r--r-- | kernel/exit.c | 2 |
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 | */ |
2207 | void proc_flush_task(struct task_struct *task) | 2208 | static 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 | |||
2260 | void 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 | |||
2253 | static struct dentry *proc_pid_instantiate(struct inode *dir, | 2266 | static 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; }) |
208 | static inline void proc_net_remove(struct net *net, const char *name) {} | 208 | static inline void proc_net_remove(struct net *net, const char *name) {} |
209 | 209 | ||
210 | static inline void proc_flush_task(struct task_struct *task) { } | 210 | static inline void proc_flush_task(struct task_struct *task) |
211 | { | ||
212 | } | ||
211 | 213 | ||
212 | static inline struct proc_dir_entry *create_proc_entry(const char *name, | 214 | static 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; |
149 | repeat: | 149 | repeat: |
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 | ||