rpms/kernel/devel kernel.spec, 1.535, 1.536 linux-2.6-utrace.patch, 1.72, 1.73

Roland McGrath (roland) fedora-extras-commits at redhat.com
Tue Mar 25 03:20:50 UTC 2008


Author: roland

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv9493

Modified Files:
	kernel.spec linux-2.6-utrace.patch 
Log Message:
utrace update


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.535
retrieving revision 1.536
diff -u -r1.535 -r1.536
--- kernel.spec	25 Mar 2008 02:47:31 -0000	1.535
+++ kernel.spec	25 Mar 2008 03:19:46 -0000	1.536
@@ -1751,6 +1751,9 @@
 %kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL} -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.conf %{with_xen} xen
 
 %changelog
+* Mon Mar 24 2008 Roland McGrath <roland at redhat.com>
+- utrace update
+
 * Mon Mar 24 2008 Tom "spot" Callaway <tcallawa at redhat.com>
 - Add linux-2.6-sparc64-big-kernel.patch, to support bigger sparc64 kernels (DaveM)
 

linux-2.6-utrace.patch:

Index: linux-2.6-utrace.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-utrace.patch,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- linux-2.6-utrace.patch	23 Mar 2008 21:11:47 -0000	1.72
+++ linux-2.6-utrace.patch	25 Mar 2008 03:19:46 -0000	1.73
@@ -10,9 +10,7 @@
  arch/powerpc/kernel/signal_32.c     |   19 +-
  arch/powerpc/kernel/sys_ppc32.c     |    5 -
  arch/sparc64/kernel/binfmt_aout32.c |    2 -
- arch/sparc64/kernel/process.c       |   23 +-
  arch/sparc64/kernel/ptrace.c        |   28 +-
- arch/sparc64/kernel/sys_sparc32.c   |   41 +-
  arch/x86/ia32/ia32_aout.c           |    6 -
  arch/x86/ia32/ia32_signal.c         |   10 -
  arch/x86/ia32/ia32entry.S           |   14 +-
@@ -42,15 +40,15 @@
  include/asm-x86/ptrace.h            |    2 +
  include/linux/init_task.h           |    3 -
  include/linux/ptrace.h              |   71 +-
- include/linux/sched.h               |   22 +-
+ include/linux/sched.h               |   46 +-
  include/linux/thread_info.h         |   10 +-
  include/linux/tracehook.h           |  493 ++++++++
  include/linux/utrace.h              |  544 ++++++++
  init/Kconfig                        |   29 +
  kernel/Makefile                     |    1 +
  kernel/compat.c                     |    3 +-
- kernel/exit.c                       |  189 +--
- kernel/fork.c                       |   70 +-
+ kernel/exit.c                       |  371 +++---
+ kernel/fork.c                       |   72 +-
  kernel/ptrace.c                     | 2112 +++++++++++++++++++++++++-------
  kernel/signal.c                     |  288 +----
  kernel/sys_ni.c                     |    4 +
@@ -58,7 +56,7 @@
  mm/nommu.c                          |    4 +-
  security/selinux/hooks.c            |   59 +-
  security/selinux/include/objsec.h   |    1 -
- 60 files changed, 6209 insertions(+), 1240 deletions(-)
+ 58 files changed, 6306 insertions(+), 1287 deletions(-)
 
 diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
 index 300e170..7cf3afc 100644  
@@ -75,7 +73,7 @@
  	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl
 new file mode 100644
-index ...00213c2 100644  
+index ...f185043 100644  
 --- /dev/null
 +++ b/Documentation/DocBook/utrace.tmpl
 @@ -0,0 +1,23 @@
@@ -96,9 +94,9 @@
 +    </chapter>
 +
 +<chapter><title>Machine state access via utrace</title>
-+!Finclude/linux/tracehook.h struct utrace_regset
-+!Finclude/linux/tracehook.h struct utrace_regset_view
-+!Finclude/linux/tracehook.h utrace_native_view
++!Finclude/linux/regset.h struct user_regset
++!Finclude/linux/regset.h struct user_regset_view
++!Finclude/linux/regset.h task_user_regset_view
 +    </chapter>
 +
 +</book>
@@ -921,20 +919,6 @@
  	return 0;
  }
  
-diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
-index e116e38..c80d850 100644  
---- a/arch/sparc64/kernel/process.c
-+++ b/arch/sparc64/kernel/process.c
-@@ -731,9 +731,6 @@ asmlinkage int sparc_execve(struct pt_re
- 		current_thread_info()->xfsr[0] = 0;
- 		current_thread_info()->fpsaved[0] = 0;
- 		regs->tstate &= ~TSTATE_PEF;
--		task_lock(current);
--		current->ptrace &= ~PT_DTRACE;
--		task_unlock(current);
- 	}
- out:
- 	return error;
 diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
 index 9a1ba1f..453023b 100644  
 --- a/arch/sparc64/kernel/ptrace.c
@@ -997,20 +981,6 @@
  	if (unlikely(current->audit_context) && !syscall_exit_p)
  		audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
  				     AUDIT_ARCH_SPARC :
-diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
-index deaba2b..41cbc6b 100644  
---- a/arch/sparc64/kernel/sys_sparc32.c
-+++ b/arch/sparc64/kernel/sys_sparc32.c
-@@ -678,9 +678,6 @@ asmlinkage long sparc32_execve(struct pt
- 		current_thread_info()->xfsr[0] = 0;
- 		current_thread_info()->fpsaved[0] = 0;
- 		regs->tstate &= ~TSTATE_PEF;
--		task_lock(current);
--		current->ptrace &= ~PT_DTRACE;
--		task_unlock(current);
- 	}
- out:
- 	return error;
 diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
 index 58cccb6..a0e1dbe 100644  
 --- a/arch/x86/ia32/ia32_aout.c
@@ -2075,7 +2045,7 @@
  
  /*
 diff --git a/include/linux/sched.h b/include/linux/sched.h
-index fed07d0..8681933 100644  
+index fed07d0..8b552ea 100644  
 --- a/include/linux/sched.h
 +++ b/include/linux/sched.h
 @@ -996,7 +996,6 @@ struct task_struct {
@@ -2099,15 +2069,39 @@
  
  	struct mm_struct *mm, *active_mm;
  
-@@ -1073,7 +1066,6 @@ struct task_struct {
- 	 * p->parent->pid)
+@@ -1070,18 +1063,26 @@ struct task_struct {
+ 	/* 
+ 	 * pointers to (original) parent process, youngest child, younger sibling,
+ 	 * older sibling, respectively.  (p->father can be replaced with 
+-	 * p->parent->pid)
++	 * p->real_parent->pid)
  	 */
- 	struct task_struct *real_parent; /* real parent process (when being debugged) */
+-	struct task_struct *real_parent; /* real parent process (when being debugged) */
 -	struct task_struct *parent;	/* parent process */
++	struct task_struct *real_parent; /* real parent process */
  	/*
- 	 * children/sibling forms the list of my children plus the
- 	 * tasks I'm ptracing.
-@@ -1162,6 +1154,11 @@ struct task_struct {
+-	 * children/sibling forms the list of my children plus the
+-	 * tasks I'm ptracing.
++	 * children/sibling forms the list of my natural children
+ 	 */
+ 	struct list_head children;	/* list of my children */
+ 	struct list_head sibling;	/* linkage in my parent's children list */
+ 	struct task_struct *group_leader;	/* threadgroup leader */
+ 
++
++	/*
++	 * ptrace_attached is the list of tasks I have PTRACE_ATTACH'd to,
++	 * excluding my own natural children.
++	 * ptrace_list is my own link on my PTRACE_ATTACHer's list,
++	 * which is p->parent->ptrace_attached.
++	 */
++	struct list_head ptrace_attached;
++	struct list_head ptrace_list;
++
+ 	/* PID/PID hash table linkage. */
+ 	struct pid_link pids[PIDTYPE_MAX];
+ 	struct list_head thread_group;
+@@ -1162,6 +1163,11 @@ struct task_struct {
  #endif
  	seccomp_t seccomp;
  
@@ -2119,7 +2113,7 @@
  /* Thread group tracking */
     	u32 parent_exec_id;
     	u32 self_exec_id;
-@@ -1218,8 +1215,6 @@ struct task_struct {
+@@ -1218,8 +1224,6 @@ struct task_struct {
  
  	struct io_context *io_context;
  
@@ -2128,7 +2122,7 @@
  #ifdef CONFIG_TASK_XACCT
  /* i/o counters(bytes read/written, #syscalls */
  	u64 rchar, wchar, syscr, syscw;
-@@ -1256,6 +1251,10 @@ struct task_struct {
+@@ -1256,6 +1260,10 @@ struct task_struct {
  	atomic_t fs_excl;	/* holding fs exclusive resources */
  	struct rcu_head rcu;
  
@@ -2139,7 +2133,7 @@
  	/*
  	 * cache last used pipe for splice
  	 */
-@@ -1700,6 +1699,7 @@ extern int kill_pgrp(struct pid *pid, in
+@@ -1700,6 +1708,7 @@ extern int kill_pgrp(struct pid *pid, in
  extern int kill_pid(struct pid *pid, int sig, int priv);
  extern int kill_proc_info(int, struct siginfo *, pid_t);
  extern void do_notify_parent(struct task_struct *, int);
@@ -2147,15 +2141,16 @@
  extern void force_sig(int, struct task_struct *);
  extern void force_sig_specific(int, struct task_struct *);
  extern int send_sig(int, struct task_struct *, int);
-@@ -1789,7 +1789,7 @@ extern void wait_task_inactive(struct ta
+@@ -1788,9 +1797,6 @@ extern void wait_task_inactive(struct ta
+ #define wait_task_inactive(p)	do { } while (0)
  #endif
  
- #define remove_parent(p)	list_del_init(&(p)->sibling)
+-#define remove_parent(p)	list_del_init(&(p)->sibling)
 -#define add_parent(p)		list_add_tail(&(p)->sibling,&(p)->parent->children)
-+#define add_parent(p)		list_add_tail(&(p)->sibling,&(p)->real_parent->children)
- 
+-
  #define next_task(p)	list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
  
+ #define for_each_process(p) \
 diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
 index 421323e..6ce2c42 100644  
 --- a/include/linux/thread_info.h
@@ -3291,7 +3286,7 @@
  }
  #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
 diff --git a/kernel/exit.c b/kernel/exit.c
-index 53872bf..fb3b1c0 100644  
+index 53872bf..bb79240 100644  
 --- a/kernel/exit.c
 +++ b/kernel/exit.c
 @@ -44,6 +44,7 @@
@@ -3302,6 +3297,15 @@
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
+@@ -64,7 +65,7 @@ static void __unhash_process(struct task
+ 		__get_cpu_var(process_counts)--;
+ 	}
+ 	list_del_rcu(&p->thread_group);
+-	remove_parent(p);
++	list_del_init(&p->sibling);
+ }
+ 
+ /*
 @@ -144,12 +145,13 @@ void release_task(struct task_struct * p
  {
  	struct task_struct *leader;
@@ -3348,19 +3352,21 @@
  }
  
  /*
-@@ -301,10 +314,9 @@ static void reparent_to_kthreadd(void)
+@@ -301,11 +314,9 @@ static void reparent_to_kthreadd(void)
  {
  	write_lock_irq(&tasklist_lock);
  
 -	ptrace_unlink(current);
  	/* Reparent to init */
- 	remove_parent(current);
+-	remove_parent(current);
 -	current->real_parent = current->parent = kthreadd_task;
+-	add_parent(current);
 +	current->real_parent = kthreadd_task;
- 	add_parent(current);
++	list_move_tail(&current->sibling, &current->real_parent->children);
  
  	/* Set the exit signal to SIGCHLD so we signal init on exit */
-@@ -616,37 +628,14 @@ static void exit_mm(struct task_struct *
+ 	current->exit_signal = SIGCHLD;
+@@ -616,37 +627,13 @@ static void exit_mm(struct task_struct *
  	mmput(mm);
  }
  
@@ -3372,7 +3378,7 @@
  		/* We already hold the tasklist_lock here.  */
  		group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
  
- 	/* Move the child from its dying parent to the new one.  */
+-	/* Move the child from its dying parent to the new one.  */
 -	if (unlikely(traced)) {
 -		/* Preserve ptrace links if someone else is tracing this child.  */
 -		list_del_init(&p->ptrace_list);
@@ -3400,7 +3406,7 @@
  
  	/* If this is a threaded reparent there is no need to
  	 * notify anyone anything has happened.
-@@ -661,7 +650,8 @@ reparent_thread(struct task_struct *p, s
+@@ -661,7 +648,8 @@ reparent_thread(struct task_struct *p, s
  	/* If we'd notified the old parent about this child's death,
  	 * also notify the new parent.
  	 */
@@ -3410,7 +3416,7 @@
  	    p->exit_signal != -1 && thread_group_empty(p))
  		do_notify_parent(p, p->exit_signal);
  
-@@ -678,9 +668,6 @@ reparent_thread(struct task_struct *p, s
+@@ -678,9 +666,6 @@ reparent_thread(struct task_struct *p, s
  static void forget_original_parent(struct task_struct *father)
  {
  	struct task_struct *p, *n, *reaper = father;
@@ -3420,8 +3426,17 @@
  
  	write_lock_irq(&tasklist_lock);
  
-@@ -701,49 +688,12 @@ static void forget_original_parent(struc
- 	 * Search them and reparent children.
+@@ -693,57 +678,15 @@ static void forget_original_parent(struc
+ 	} while (reaper->flags & PF_EXITING);
+ 
+ 	/*
+-	 * There are only two places where our children can be:
+-	 *
+-	 * - in our child list
+-	 * - in our ptraced child list
+-	 *
+-	 * Search them and reparent children.
++	 * Reparent our natural children.
  	 */
  	list_for_each_entry_safe(p, n, &father->children, sibling) {
 -		int ptrace;
@@ -3471,7 +3486,7 @@
  }
  
  /*
-@@ -753,6 +703,8 @@ static void forget_original_parent(struc
+@@ -753,6 +696,8 @@ static void forget_original_parent(struc
  static void exit_notify(struct task_struct *tsk, int group_dead)
  {
  	int state;
@@ -3480,7 +3495,7 @@
  
  	/*
  	 * This does two things:
-@@ -789,20 +741,12 @@ static void exit_notify(struct task_stru
+@@ -789,20 +734,12 @@ static void exit_notify(struct task_stru
  	    && !capable(CAP_KILL))
  		tsk->exit_signal = SIGCHLD;
  
@@ -3505,7 +3520,7 @@
  		state = EXIT_DEAD;
  	tsk->exit_state = state;
  
-@@ -813,6 +757,8 @@ static void exit_notify(struct task_stru
+@@ -813,6 +750,8 @@ static void exit_notify(struct task_stru
  
  	write_unlock_irq(&tasklist_lock);
  
@@ -3514,7 +3529,7 @@
  	/* If the process is dead, release it - nobody will wait for it */
  	if (state == EXIT_DEAD)
  		release_task(tsk);
-@@ -893,10 +839,7 @@ NORET_TYPE void do_exit(long code)
+@@ -893,10 +832,7 @@ NORET_TYPE void do_exit(long code)
  	if (unlikely(!tsk->pid))
  		panic("Attempted to kill the idle task!");
  
@@ -3526,7 +3541,7 @@
  
  	/*
  	 * We're taking recursive faults here in do_exit. Safest is to just
-@@ -929,6 +872,8 @@ NORET_TYPE void do_exit(long code)
+@@ -929,6 +865,8 @@ NORET_TYPE void do_exit(long code)
  	smp_mb();
  	spin_unlock_wait(&tsk->pi_lock);
  
@@ -3535,7 +3550,7 @@
  	if (unlikely(in_atomic()))
  		printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
  				current->comm, task_pid_nr(current),
-@@ -1103,10 +1048,9 @@ static int eligible_child(enum pid_type 
+@@ -1103,10 +1041,9 @@ static int eligible_child(enum pid_type 
  	}
  
  	/*
@@ -3548,7 +3563,7 @@
  		return 0;
  
  	/* Wait for all children (clone and not) if __WALL is set;
-@@ -1196,8 +1140,7 @@ static int wait_task_zombie(struct task_
+@@ -1196,8 +1133,7 @@ static int wait_task_zombie(struct task_
  		return 0;
  	}
  
@@ -3558,7 +3573,7 @@
  
  	if (likely(!traced)) {
  		struct signal_struct *psig;
-@@ -1218,8 +1161,8 @@ static int wait_task_zombie(struct task_
+@@ -1218,8 +1154,8 @@ static int wait_task_zombie(struct task_
  		 * as other threads in the parent group can be right
  		 * here reaping other children at the same time.
  		 */
@@ -3569,7 +3584,7 @@
  		sig = p->signal;
  		psig->cutime =
  			cputime_add(psig->cutime,
-@@ -1250,7 +1193,7 @@ static int wait_task_zombie(struct task_
+@@ -1250,7 +1186,7 @@ static int wait_task_zombie(struct task_
  		psig->coublock +=
  			task_io_get_oublock(p) +
  			sig->oublock + sig->coublock;
@@ -3578,7 +3593,7 @@
  	}
  
  	/*
-@@ -1289,24 +1232,6 @@ static int wait_task_zombie(struct task_
+@@ -1289,24 +1225,6 @@ static int wait_task_zombie(struct task_
  	if (!retval)
  		retval = pid;
  
@@ -3603,7 +3618,7 @@
  	if (p != NULL)
  		release_task(p);
  
-@@ -1333,7 +1258,7 @@ static int wait_task_stopped(struct task
+@@ -1333,7 +1251,7 @@ static int wait_task_stopped(struct task
  	if (unlikely(!task_is_stopped_or_traced(p)))
  		goto unlock_sig;
  
@@ -3612,7 +3627,7 @@
  		/*
  		 * A group stop is in progress and this is the group leader.
  		 * We won't report until all threads have stopped.
-@@ -1362,7 +1287,7 @@ unlock_sig:
+@@ -1362,7 +1280,7 @@ unlock_sig:
  	 */
  	get_task_struct(p);
  	pid = task_pid_vnr(p);
@@ -3621,45 +3636,201 @@
  	read_unlock(&tasklist_lock);
  
  	if (unlikely(noreap))
-@@ -1481,8 +1406,8 @@ repeat:
- 				 * continue, exit, or stop again.
- 				 */
- 				flag = 1;
+@@ -1442,89 +1360,144 @@ static int wait_task_continued(struct ta
+ 	return retval;
+ }
+ 
++/*
++ * Consider @p for a wait by @parent.
++ * Returns -ECHILD if @p is not a child that counts for this wait.
++ * For an -ECHILD return due to security_task_wait refusal, *@enone is
++ * set to the error code if it is not already zero.
++ * Returns 0 if @p is eligible but we have nothing to report about it now.
++ * Returns pid or a different error if we tried to handle @p; in that
++ * case we unlock tasklist_lock before return.
++ */
++static int wait_consider_task(struct task_struct *parent,
++			      struct task_struct *p,
++			      int *enone,
++			      enum pid_type type, struct pid *pid, int options,
++			      struct siginfo __user *infop,
++			      int __user *stat_addr, struct rusage __user *ru)
++{
++	int ret = eligible_child(type, pid, options, p);
++	if (!ret)
++		return -ECHILD;
++
++	if (unlikely(ret < 0)) {
++		if (*enone)
++			*enone = ret;
++		return -ECHILD;
++	}
++
++	if (task_is_stopped_or_traced(p)) {
++		/*
++		 * It's stopped now, so it might later
++		 * continue, exit, or stop again.
++		 */
++		if (tracehook_inhibit_wait_stopped(p, !(options & WUNTRACED)))
++			return 0;
++
++		return wait_task_stopped(p, (options & WNOWAIT),
++					 infop, stat_addr, ru);
++	}
++
++	if (p->exit_state == EXIT_ZOMBIE && !delay_group_leader(p)) {
++		/*
++		 * We don't reap group leaders with subthreads.
++		 */
++		if (!likely(options & WEXITED))
++			return 0;
++
++		if (tracehook_inhibit_wait_zombie(p))
++			/*
++			 * We're prevented from seeing it,
++			 * but we will see it eventually.
++			 */
++			return 0;
++
++		return wait_task_zombie(p, (options & WNOWAIT),
++					infop, stat_addr, ru);
++	}
++
++	if (p->exit_state != EXIT_DEAD) {
++		/*
++		 * It's running now, so it might later
++		 * exit, stop, or stop and then continue.
++		 */
++		if (!unlikely(options & WCONTINUED))
++			return 0;
++
++		if (tracehook_inhibit_wait_continued(p))
++			return 0;
++
++		return wait_task_continued(p, (options & WNOWAIT),
++					   infop, stat_addr, ru);
++	}
++
++	return -ECHILD;
++}
++
++/*
++ * Do the work of do_wait() for one thread in the group, @tsk.
++ * -ECHILD should be in *@retval before the first call.
++ * Returns nonzero if we have unlocked tasklist_lock and have
++ * the final return value ready in *@retval.
++ * Returns zero if the search for a child should continue; then
++ * *@retval is 0 if there are any eligible children, or another
++ * code that security_task_wait returned, or still -ECHILD.
++ */
++static int do_wait_thread(struct task_struct *tsk, int *retval,
++			  enum pid_type type, struct pid *pid, int options,
++			  struct siginfo __user *infop, int __user *stat_addr,
++			  struct rusage __user *ru)
++{
++	struct task_struct *p;
++	int ret;
++
++	list_for_each_entry(p, &tsk->children, sibling) {
++		ret = wait_consider_task(tsk, p, retval, type, pid, options,
++					 infop, stat_addr, ru);
++		if (ret != -ECHILD) {
++			*retval = ret;
++			if (ret)
++				return ret;
++		}
++	}
++
++	ret = ptrace_do_wait(tsk, type, pid, options, infop, stat_addr, ru);
++	if (ret != -ECHILD) {
++		*retval = ret;
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
+ static long do_wait(enum pid_type type, struct pid *pid, int options,
+ 		    struct siginfo __user *infop, int __user *stat_addr,
+ 		    struct rusage __user *ru)
+ {
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	struct task_struct *tsk;
+-	int flag, retval;
++	int retval;
+ 
+ 	add_wait_queue(&current->signal->wait_chldexit,&wait);
+ repeat:
+-	/* If there is nothing that can match our critier just get out */
++	/*
++	 * If there is nothing that can match our critiera just get out.
++	 * We will clear @retval to zero if we see any child that might later
++	 * match our criteria, even if we are not able to reap it yet.
++	 */
+ 	retval = -ECHILD;
+ 	if ((type < PIDTYPE_MAX) && (!pid || hlist_empty(&pid->tasks[type])))
+ 		goto end;
+ 
+-	/*
+-	 * We will set this flag if we see any child that might later
+-	 * match our criteria, even if we are not able to reap it yet.
+-	 */
+-	flag = retval = 0;
+ 	current->state = TASK_INTERRUPTIBLE;
+ 	read_lock(&tasklist_lock);
+ 	tsk = current;
+ 	do {
+-		struct task_struct *p;
++		if (do_wait_thread(tsk, &retval, type, pid, options,
++				   infop, stat_addr, ru))
++			goto end;
+ 
+-		list_for_each_entry(p, &tsk->children, sibling) {
+-			int ret = eligible_child(type, pid, options, p);
+-			if (!ret)
+-				continue;
+-
+-			if (unlikely(ret < 0)) {
+-				retval = ret;
+-			} else if (task_is_stopped_or_traced(p)) {
+-				/*
+-				 * It's stopped now, so it might later
+-				 * continue, exit, or stop again.
+-				 */
+-				flag = 1;
 -				if (!(p->ptrace & PT_PTRACED) &&
 -				    !(options & WUNTRACED))
-+				if (tracehook_inhibit_wait_stopped(
-+					    p, !(options & WUNTRACED)))
- 					continue;
- 
- 				retval = wait_task_stopped(p,
-@@ -1495,6 +1420,14 @@ repeat:
- 				 */
- 				if (!likely(options & WEXITED))
- 					continue;
-+				if (tracehook_inhibit_wait_zombie(p)) {
-+					/*
-+					 * We're prevented from seeing it,
-+					 * but we will see it eventually.
-+					 */
-+					flag = 1;
-+					continue;
-+				}
- 				retval = wait_task_zombie(p,
- 						(options & WNOWAIT), infop,
- 						stat_addr, ru);
-@@ -1506,6 +1439,8 @@ repeat:
- 				flag = 1;
- 				if (!unlikely(options & WCONTINUED))
- 					continue;
-+				if (tracehook_inhibit_wait_continued(p))
-+					continue;
- 				retval = wait_task_continued(p,
- 						(options & WNOWAIT), infop,
- 						stat_addr, ru);
-@@ -1513,18 +1448,15 @@ repeat:
- 			if (retval != 0) /* tasklist_lock released */
- 				goto end;
- 		}
+-					continue;
+-
+-				retval = wait_task_stopped(p,
+-						(options & WNOWAIT), infop,
+-						stat_addr, ru);
+-			} else if (p->exit_state == EXIT_ZOMBIE &&
+-					!delay_group_leader(p)) {
+-				/*
+-				 * We don't reap group leaders with subthreads.
+-				 */
+-				if (!likely(options & WEXITED))
+-					continue;
+-				retval = wait_task_zombie(p,
+-						(options & WNOWAIT), infop,
+-						stat_addr, ru);
+-			} else if (p->exit_state != EXIT_DEAD) {
+-				/*
+-				 * It's running now, so it might later
+-				 * exit, stop, or stop and then continue.
+-				 */
+-				flag = 1;
+-				if (!unlikely(options & WCONTINUED))
+-					continue;
+-				retval = wait_task_continued(p,
+-						(options & WNOWAIT), infop,
+-						stat_addr, ru);
+-			}
+-			if (retval != 0) /* tasklist_lock released */
+-				goto end;
+-		}
 -		if (!flag) {
 -			list_for_each_entry(p, &tsk->ptrace_children,
 -								ptrace_list) {
@@ -3669,29 +3840,37 @@
 -				if (likely(flag > 0))
 -					break;
 -				retval = flag;
-+
-+		retval = ptrace_do_wait(tsk, type, pid, options,
-+					infop, stat_addr, ru);
-+		if (retval != -ECHILD) {
-+			flag = 1;
-+			if (retval != 0) /* He released the lock.  */
- 				goto end;
+-				goto end;
 -			}
- 		}
-+
+-		}
  		if (options & __WNOTHREAD)
  			break;
  		tsk = next_thread(tsk);
-@@ -1533,6 +1465,7 @@ repeat:
+@@ -1532,16 +1505,14 @@ repeat:
+ 	} while (tsk != current);
  	read_unlock(&tasklist_lock);
  
- 	if (flag) {
-+		retval = 0;
- 		if (options & WNOHANG)
- 			goto end;
+-	if (flag) {
+-		if (options & WNOHANG)
+-			goto end;
++	if (!retval && !(options & WNOHANG)) {
  		retval = -ERESTARTSYS;
+-		if (signal_pending(current))
+-			goto end;
+-		schedule();
+-		goto repeat;
++		if (!signal_pending(current)) {
++			schedule();
++			goto repeat;
++		}
+ 	}
+-	retval = -ECHILD;
++
+ end:
+ 	current->state = TASK_RUNNING;
+ 	remove_wait_queue(&current->signal->wait_chldexit,&wait);
 diff --git a/kernel/fork.c b/kernel/fork.c
-index dd249c3..15fc4f5 100644  
+index dd249c3..d090075 100644  
 --- a/kernel/fork.c
 +++ b/kernel/fork.c
 @@ -50,9 +50,11 @@
@@ -3751,12 +3930,14 @@
  
  	spin_lock(&current->sighand->siglock);
  
-@@ -1330,8 +1330,7 @@ static struct task_struct *copy_process(
+@@ -1329,9 +1329,8 @@ static struct task_struct *copy_process(
+ 	}
  
  	if (likely(p->pid)) {
- 		add_parent(p);
+-		add_parent(p);
 -		if (unlikely(p->ptrace & PT_PTRACED))
 -			__ptrace_link(p, current->parent);
++		list_add_tail(&p->sibling, &p->real_parent->children);
 +		tracehook_clone_attach(p, trace);
  
  		if (thread_group_leader(p)) {




More information about the fedora-extras-commits mailing list