diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 60 |
1 files changed, 20 insertions, 40 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index bd2959228871..bfee931ee3fb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -152,8 +152,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
152 | WARN_ON(atomic_read(&tsk->usage)); | 152 | WARN_ON(atomic_read(&tsk->usage)); |
153 | WARN_ON(tsk == current); | 153 | WARN_ON(tsk == current); |
154 | 154 | ||
155 | put_cred(tsk->real_cred); | 155 | exit_creds(tsk); |
156 | put_cred(tsk->cred); | ||
157 | delayacct_tsk_free(tsk); | 156 | delayacct_tsk_free(tsk); |
158 | 157 | ||
159 | if (!profile_handoff_task(tsk)) | 158 | if (!profile_handoff_task(tsk)) |
@@ -567,18 +566,18 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
567 | * the value intact in a core dump, and to save the unnecessary | 566 | * the value intact in a core dump, and to save the unnecessary |
568 | * trouble otherwise. Userland only wants this done for a sys_exit. | 567 | * trouble otherwise. Userland only wants this done for a sys_exit. |
569 | */ | 568 | */ |
570 | if (tsk->clear_child_tid | 569 | if (tsk->clear_child_tid) { |
571 | && !(tsk->flags & PF_SIGNALED) | 570 | if (!(tsk->flags & PF_SIGNALED) && |
572 | && atomic_read(&mm->mm_users) > 1) { | 571 | atomic_read(&mm->mm_users) > 1) { |
573 | u32 __user * tidptr = tsk->clear_child_tid; | 572 | /* |
573 | * We don't check the error code - if userspace has | ||
574 | * not set up a proper pointer then tough luck. | ||
575 | */ | ||
576 | put_user(0, tsk->clear_child_tid); | ||
577 | sys_futex(tsk->clear_child_tid, FUTEX_WAKE, | ||
578 | 1, NULL, NULL, 0); | ||
579 | } | ||
574 | tsk->clear_child_tid = NULL; | 580 | tsk->clear_child_tid = NULL; |
575 | |||
576 | /* | ||
577 | * We don't check the error code - if userspace has | ||
578 | * not set up a proper pointer then tough luck. | ||
579 | */ | ||
580 | put_user(0, tidptr); | ||
581 | sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0); | ||
582 | } | 581 | } |
583 | } | 582 | } |
584 | 583 | ||
@@ -815,11 +814,8 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
815 | { | 814 | { |
816 | struct signal_struct *sig; | 815 | struct signal_struct *sig; |
817 | 816 | ||
818 | if (clone_flags & CLONE_THREAD) { | 817 | if (clone_flags & CLONE_THREAD) |
819 | atomic_inc(¤t->signal->count); | ||
820 | atomic_inc(¤t->signal->live); | ||
821 | return 0; | 818 | return 0; |
822 | } | ||
823 | 819 | ||
824 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); | 820 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); |
825 | tsk->signal = sig; | 821 | tsk->signal = sig; |
@@ -877,16 +873,6 @@ void __cleanup_signal(struct signal_struct *sig) | |||
877 | kmem_cache_free(signal_cachep, sig); | 873 | kmem_cache_free(signal_cachep, sig); |
878 | } | 874 | } |
879 | 875 | ||
880 | static void cleanup_signal(struct task_struct *tsk) | ||
881 | { | ||
882 | struct signal_struct *sig = tsk->signal; | ||
883 | |||
884 | atomic_dec(&sig->live); | ||
885 | |||
886 | if (atomic_dec_and_test(&sig->count)) | ||
887 | __cleanup_signal(sig); | ||
888 | } | ||
889 | |||
890 | static void copy_flags(unsigned long clone_flags, struct task_struct *p) | 876 | static void copy_flags(unsigned long clone_flags, struct task_struct *p) |
891 | { | 877 | { |
892 | unsigned long new_flags = p->flags; | 878 | unsigned long new_flags = p->flags; |
@@ -1021,10 +1007,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1021 | copy_flags(clone_flags, p); | 1007 | copy_flags(clone_flags, p); |
1022 | INIT_LIST_HEAD(&p->children); | 1008 | INIT_LIST_HEAD(&p->children); |
1023 | INIT_LIST_HEAD(&p->sibling); | 1009 | INIT_LIST_HEAD(&p->sibling); |
1024 | #ifdef CONFIG_PREEMPT_RCU | 1010 | rcu_copy_process(p); |
1025 | p->rcu_read_lock_nesting = 0; | ||
1026 | p->rcu_flipctr_idx = 0; | ||
1027 | #endif /* #ifdef CONFIG_PREEMPT_RCU */ | ||
1028 | p->vfork_done = NULL; | 1011 | p->vfork_done = NULL; |
1029 | spin_lock_init(&p->alloc_lock); | 1012 | spin_lock_init(&p->alloc_lock); |
1030 | 1013 | ||
@@ -1239,6 +1222,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1239 | } | 1222 | } |
1240 | 1223 | ||
1241 | if (clone_flags & CLONE_THREAD) { | 1224 | if (clone_flags & CLONE_THREAD) { |
1225 | atomic_inc(¤t->signal->count); | ||
1226 | atomic_inc(¤t->signal->live); | ||
1242 | p->group_leader = current->group_leader; | 1227 | p->group_leader = current->group_leader; |
1243 | list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); | 1228 | list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); |
1244 | } | 1229 | } |
@@ -1268,6 +1253,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1268 | write_unlock_irq(&tasklist_lock); | 1253 | write_unlock_irq(&tasklist_lock); |
1269 | proc_fork_connector(p); | 1254 | proc_fork_connector(p); |
1270 | cgroup_post_fork(p); | 1255 | cgroup_post_fork(p); |
1256 | perf_counter_fork(p); | ||
1271 | return p; | 1257 | return p; |
1272 | 1258 | ||
1273 | bad_fork_free_pid: | 1259 | bad_fork_free_pid: |
@@ -1281,7 +1267,8 @@ bad_fork_cleanup_mm: | |||
1281 | if (p->mm) | 1267 | if (p->mm) |
1282 | mmput(p->mm); | 1268 | mmput(p->mm); |
1283 | bad_fork_cleanup_signal: | 1269 | bad_fork_cleanup_signal: |
1284 | cleanup_signal(p); | 1270 | if (!(clone_flags & CLONE_THREAD)) |
1271 | __cleanup_signal(p->signal); | ||
1285 | bad_fork_cleanup_sighand: | 1272 | bad_fork_cleanup_sighand: |
1286 | __cleanup_sighand(p->sighand); | 1273 | __cleanup_sighand(p->sighand); |
1287 | bad_fork_cleanup_fs: | 1274 | bad_fork_cleanup_fs: |
@@ -1306,8 +1293,7 @@ bad_fork_cleanup_put_domain: | |||
1306 | module_put(task_thread_info(p)->exec_domain->module); | 1293 | module_put(task_thread_info(p)->exec_domain->module); |
1307 | bad_fork_cleanup_count: | 1294 | bad_fork_cleanup_count: |
1308 | atomic_dec(&p->cred->user->processes); | 1295 | atomic_dec(&p->cred->user->processes); |
1309 | put_cred(p->real_cred); | 1296 | exit_creds(p); |
1310 | put_cred(p->cred); | ||
1311 | bad_fork_free: | 1297 | bad_fork_free: |
1312 | free_task(p); | 1298 | free_task(p); |
1313 | fork_out: | 1299 | fork_out: |
@@ -1407,12 +1393,6 @@ long do_fork(unsigned long clone_flags, | |||
1407 | if (clone_flags & CLONE_VFORK) { | 1393 | if (clone_flags & CLONE_VFORK) { |
1408 | p->vfork_done = &vfork; | 1394 | p->vfork_done = &vfork; |
1409 | init_completion(&vfork); | 1395 | init_completion(&vfork); |
1410 | } else if (!(clone_flags & CLONE_VM)) { | ||
1411 | /* | ||
1412 | * vfork will do an exec which will call | ||
1413 | * set_task_comm() | ||
1414 | */ | ||
1415 | perf_counter_fork(p); | ||
1416 | } | 1396 | } |
1417 | 1397 | ||
1418 | audit_finish_fork(p); | 1398 | audit_finish_fork(p); |