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_rcu(&p->tasks);
|
||||||
list_del_init(&p->sibling);
|
list_del_init(&p->sibling);
|
||||||
__this_cpu_dec(process_counts);
|
__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);
|
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);
|
spin_lock_irqsave(&pidmap_lock, flags);
|
||||||
for (i = 0; i <= pid->level; i++) {
|
for (i = 0; i <= pid->level; i++) {
|
||||||
struct upid *upid = pid->numbers + i;
|
struct upid *upid = pid->numbers + i;
|
||||||
|
struct pid_namespace *ns = upid->ns;
|
||||||
hlist_del_rcu(&upid->pid_chain);
|
hlist_del_rcu(&upid->pid_chain);
|
||||||
if (--upid->ns->nr_hashed == 0) {
|
switch(--ns->nr_hashed) {
|
||||||
upid->ns->nr_hashed = -1;
|
case 1:
|
||||||
schedule_work(&upid->ns->proc_work);
|
/* 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);
|
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.
|
* 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 (;;) {
|
for (;;) {
|
||||||
bool need_wait = false;
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
|
if (pid_ns->nr_hashed == 1)
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
if (!list_empty(¤t->children)) {
|
|
||||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
|
||||||
need_wait = true;
|
|
||||||
}
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
|
|
||||||
if (!need_wait)
|
|
||||||
break;
|
break;
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
if (pid_ns->reboot)
|
if (pid_ns->reboot)
|
||||||
current->signal->group_exit_code = pid_ns->reboot;
|
current->signal->group_exit_code = pid_ns->reboot;
|
||||||
|
Loading…
Reference in New Issue
Block a user