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>
This commit is contained in:
parent
5e1182deb8
commit
af4b8a83ad
@ -72,18 +72,6 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
|
||||
list_del_rcu(&p->tasks);
|
||||
list_del_init(&p->sibling);
|
||||
__this_cpu_dec(process_counts);
|
||||
/*
|
||||
* If we are the last child process in a pid namespace to be
|
||||
* reaped, notify the reaper sleeping zap_pid_ns_processes().
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PID_NS)) {
|
||||
struct task_struct *parent = p->real_parent;
|
||||
|
||||
if ((task_active_pid_ns(parent)->child_reaper == parent) &&
|
||||
list_empty(&parent->children) &&
|
||||
(parent->flags & PF_EXITING))
|
||||
wake_up_process(parent);
|
||||
}
|
||||
}
|
||||
list_del_rcu(&p->thread_group);
|
||||
}
|
||||
|
16
kernel/pid.c
16
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);
|
||||
|
@ -217,22 +217,15 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
|
||||
|
||||
/*
|
||||
* sys_wait4() above can't reap the TASK_DEAD children.
|
||||
* Make sure they all go away, see __unhash_process().
|
||||
* Make sure they all go away, see free_pid().
|
||||
*/
|
||||
for (;;) {
|
||||
bool need_wait = false;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
if (!list_empty(¤t->children)) {
|
||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
need_wait = true;
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
if (!need_wait)
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
if (pid_ns->nr_hashed == 1)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
if (pid_ns->reboot)
|
||||
current->signal->group_exit_code = pid_ns->reboot;
|
||||
|
Loading…
Reference in New Issue
Block a user