From 5c5e357704ebb0ede3501276217e0c7a6bf2a34d Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 23 Sep 2009 15:56:46 -0700 Subject: [PATCH] --- yaml --- r: 165674 b: refs/heads/master c: 0b7570e77f7c3abd43107dabc47ea89daf9a1cba h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/kernel/exit.c | 25 +++++++++++++++++++++---- trunk/security/selinux/hooks.c | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 4282ca08d56c..a71672a23e43 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a2322e1d272938d192d8c24cdacf57c0c7a2683f +refs/heads/master: 0b7570e77f7c3abd43107dabc47ea89daf9a1cba diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index ef2dfa818bf1..7838b4d68774 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -1097,6 +1097,7 @@ struct wait_opts { int __user *wo_stat; struct rusage __user *wo_rusage; + wait_queue_t child_wait; int notask_error; }; @@ -1570,20 +1571,35 @@ static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk) return 0; } +static int child_wait_callback(wait_queue_t *wait, unsigned mode, + int sync, void *key) +{ + struct wait_opts *wo = container_of(wait, struct wait_opts, + child_wait); + struct task_struct *p = key; + + if (!eligible_child(wo, p)) + return 0; + + return default_wake_function(wait, mode, sync, key); +} + void __wake_up_parent(struct task_struct *p, struct task_struct *parent) { - wake_up_interruptible_sync(&parent->signal->wait_chldexit); + __wake_up_sync_key(&parent->signal->wait_chldexit, + TASK_INTERRUPTIBLE, 1, p); } static long do_wait(struct wait_opts *wo) { - DECLARE_WAITQUEUE(wait, current); struct task_struct *tsk; int retval; trace_sched_process_wait(wo->wo_pid); - add_wait_queue(¤t->signal->wait_chldexit,&wait); + init_waitqueue_func_entry(&wo->child_wait, child_wait_callback); + wo->child_wait.private = current; + add_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait); repeat: /* * If there is nothing that can match our critiera just get out. @@ -1624,7 +1640,8 @@ static long do_wait(struct wait_opts *wo) } end: __set_current_state(TASK_RUNNING); - remove_wait_queue(¤t->signal->wait_chldexit,&wait); + remove_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait); + if (wo->wo_info) { struct siginfo __user *infop = wo->wo_info; diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 417f7c994522..bb230d5d7085 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -2411,7 +2411,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) /* Wake up the parent if it is waiting so that it can recheck * wait permission to the new task SID. */ read_lock(&tasklist_lock); - wake_up_interruptible(¤t->real_parent->signal->wait_chldexit); + __wake_up_parent(current, current->real_parent); read_unlock(&tasklist_lock); }