aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 5c372c954f3b..0d62524c6660 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2062,6 +2062,8 @@ long _do_fork(unsigned long clone_flags,
2062 int __user *child_tidptr, 2062 int __user *child_tidptr,
2063 unsigned long tls) 2063 unsigned long tls)
2064{ 2064{
2065 struct completion vfork;
2066 struct pid *pid;
2065 struct task_struct *p; 2067 struct task_struct *p;
2066 int trace = 0; 2068 int trace = 0;
2067 long nr; 2069 long nr;
@@ -2087,43 +2089,40 @@ long _do_fork(unsigned long clone_flags,
2087 p = copy_process(clone_flags, stack_start, stack_size, 2089 p = copy_process(clone_flags, stack_start, stack_size,
2088 child_tidptr, NULL, trace, tls, NUMA_NO_NODE); 2090 child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
2089 add_latent_entropy(); 2091 add_latent_entropy();
2092
2093 if (IS_ERR(p))
2094 return PTR_ERR(p);
2095
2090 /* 2096 /*
2091 * Do this prior waking up the new thread - the thread pointer 2097 * Do this prior waking up the new thread - the thread pointer
2092 * might get invalid after that point, if the thread exits quickly. 2098 * might get invalid after that point, if the thread exits quickly.
2093 */ 2099 */
2094 if (!IS_ERR(p)) { 2100 trace_sched_process_fork(current, p);
2095 struct completion vfork;
2096 struct pid *pid;
2097
2098 trace_sched_process_fork(current, p);
2099 2101
2100 pid = get_task_pid(p, PIDTYPE_PID); 2102 pid = get_task_pid(p, PIDTYPE_PID);
2101 nr = pid_vnr(pid); 2103 nr = pid_vnr(pid);
2102 2104
2103 if (clone_flags & CLONE_PARENT_SETTID) 2105 if (clone_flags & CLONE_PARENT_SETTID)
2104 put_user(nr, parent_tidptr); 2106 put_user(nr, parent_tidptr);
2105
2106 if (clone_flags & CLONE_VFORK) {
2107 p->vfork_done = &vfork;
2108 init_completion(&vfork);
2109 get_task_struct(p);
2110 }
2111 2107
2112 wake_up_new_task(p); 2108 if (clone_flags & CLONE_VFORK) {
2109 p->vfork_done = &vfork;
2110 init_completion(&vfork);
2111 get_task_struct(p);
2112 }
2113 2113
2114 /* forking complete and child started to run, tell ptracer */ 2114 wake_up_new_task(p);
2115 if (unlikely(trace))
2116 ptrace_event_pid(trace, pid);
2117 2115
2118 if (clone_flags & CLONE_VFORK) { 2116 /* forking complete and child started to run, tell ptracer */
2119 if (!wait_for_vfork_done(p, &vfork)) 2117 if (unlikely(trace))
2120 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); 2118 ptrace_event_pid(trace, pid);
2121 }
2122 2119
2123 put_pid(pid); 2120 if (clone_flags & CLONE_VFORK) {
2124 } else { 2121 if (!wait_for_vfork_done(p, &vfork))
2125 nr = PTR_ERR(p); 2122 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
2126 } 2123 }
2124
2125 put_pid(pid);
2127 return nr; 2126 return nr;
2128} 2127}
2129 2128