summaryrefslogtreecommitdiffstats
path: root/kernel/pid.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-08-02 00:03:42 +0200
committerEric W. Biederman <ebiederm@xmission.com>2012-11-19 14:59:12 +0100
commitaf4b8a83add95ef40716401395b44a1b579965f4 (patch)
tree2f3f606b7327f74c1c1beb8a75886318c51c838a /kernel/pid.c
parentpidns: Don't allow new processes in a dead pid namespace. (diff)
downloadlinux-af4b8a83add95ef40716401395b44a1b579965f4.tar.xz
linux-af4b8a83add95ef40716401395b44a1b579965f4.zip
pidns: Wait in zap_pid_ns_processes until pid_ns->nr_hashed == 1
Looking at pid_ns->nr_hashed is a bit simpler and it works for disjoint process trees that an unshare or a join of a pid_namespace may create. Acked-by: "Serge E. Hallyn" <serge@hallyn.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/pid.c')
-rw-r--r--kernel/pid.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/kernel/pid.c b/kernel/pid.c
index 9c219117af36..6e8da291de49 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -273,10 +273,20 @@ void free_pid(struct pid *pid)
spin_lock_irqsave(&pidmap_lock, flags);
for (i = 0; i <= pid->level; i++) {
struct upid *upid = pid->numbers + i;
+ struct pid_namespace *ns = upid->ns;
hlist_del_rcu(&upid->pid_chain);
- if (--upid->ns->nr_hashed == 0) {
- upid->ns->nr_hashed = -1;
- schedule_work(&upid->ns->proc_work);
+ switch(--ns->nr_hashed) {
+ case 1:
+ /* When all that is left in the pid namespace
+ * is the reaper wake up the reaper. The reaper
+ * may be sleeping in zap_pid_ns_processes().
+ */
+ wake_up_process(ns->child_reaper);
+ break;
+ case 0:
+ ns->nr_hashed = -1;
+ schedule_work(&ns->proc_work);
+ break;
}
}
spin_unlock_irqrestore(&pidmap_lock, flags);