diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 1020977b57ca..166b8c49257c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/fs_struct.h> | 63 | #include <linux/fs_struct.h> |
64 | #include <linux/magic.h> | 64 | #include <linux/magic.h> |
65 | #include <linux/perf_event.h> | 65 | #include <linux/perf_event.h> |
66 | #include <linux/posix-timers.h> | ||
66 | 67 | ||
67 | #include <asm/pgtable.h> | 68 | #include <asm/pgtable.h> |
68 | #include <asm/pgalloc.h> | 69 | #include <asm/pgalloc.h> |
@@ -90,7 +91,7 @@ int nr_processes(void) | |||
90 | int cpu; | 91 | int cpu; |
91 | int total = 0; | 92 | int total = 0; |
92 | 93 | ||
93 | for_each_online_cpu(cpu) | 94 | for_each_possible_cpu(cpu) |
94 | total += per_cpu(process_counts, cpu); | 95 | total += per_cpu(process_counts, cpu); |
95 | 96 | ||
96 | return total; | 97 | return total; |
@@ -433,6 +434,14 @@ __setup("coredump_filter=", coredump_filter_setup); | |||
433 | 434 | ||
434 | #include <linux/init_task.h> | 435 | #include <linux/init_task.h> |
435 | 436 | ||
437 | static void mm_init_aio(struct mm_struct *mm) | ||
438 | { | ||
439 | #ifdef CONFIG_AIO | ||
440 | spin_lock_init(&mm->ioctx_lock); | ||
441 | INIT_HLIST_HEAD(&mm->ioctx_list); | ||
442 | #endif | ||
443 | } | ||
444 | |||
436 | static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | 445 | static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) |
437 | { | 446 | { |
438 | atomic_set(&mm->mm_users, 1); | 447 | atomic_set(&mm->mm_users, 1); |
@@ -446,10 +455,9 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | |||
446 | set_mm_counter(mm, file_rss, 0); | 455 | set_mm_counter(mm, file_rss, 0); |
447 | set_mm_counter(mm, anon_rss, 0); | 456 | set_mm_counter(mm, anon_rss, 0); |
448 | spin_lock_init(&mm->page_table_lock); | 457 | spin_lock_init(&mm->page_table_lock); |
449 | spin_lock_init(&mm->ioctx_lock); | ||
450 | INIT_HLIST_HEAD(&mm->ioctx_list); | ||
451 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 458 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
452 | mm->cached_hole_size = ~0UL; | 459 | mm->cached_hole_size = ~0UL; |
460 | mm_init_aio(mm); | ||
453 | mm_init_owner(mm, p); | 461 | mm_init_owner(mm, p); |
454 | 462 | ||
455 | if (likely(!mm_alloc_pgd(mm))) { | 463 | if (likely(!mm_alloc_pgd(mm))) { |
@@ -510,6 +518,8 @@ void mmput(struct mm_struct *mm) | |||
510 | spin_unlock(&mmlist_lock); | 518 | spin_unlock(&mmlist_lock); |
511 | } | 519 | } |
512 | put_swap_token(mm); | 520 | put_swap_token(mm); |
521 | if (mm->binfmt) | ||
522 | module_put(mm->binfmt->module); | ||
513 | mmdrop(mm); | 523 | mmdrop(mm); |
514 | } | 524 | } |
515 | } | 525 | } |
@@ -560,12 +570,18 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
560 | 570 | ||
561 | /* Get rid of any futexes when releasing the mm */ | 571 | /* Get rid of any futexes when releasing the mm */ |
562 | #ifdef CONFIG_FUTEX | 572 | #ifdef CONFIG_FUTEX |
563 | if (unlikely(tsk->robust_list)) | 573 | if (unlikely(tsk->robust_list)) { |
564 | exit_robust_list(tsk); | 574 | exit_robust_list(tsk); |
575 | tsk->robust_list = NULL; | ||
576 | } | ||
565 | #ifdef CONFIG_COMPAT | 577 | #ifdef CONFIG_COMPAT |
566 | if (unlikely(tsk->compat_robust_list)) | 578 | if (unlikely(tsk->compat_robust_list)) { |
567 | compat_exit_robust_list(tsk); | 579 | compat_exit_robust_list(tsk); |
580 | tsk->compat_robust_list = NULL; | ||
581 | } | ||
568 | #endif | 582 | #endif |
583 | if (unlikely(!list_empty(&tsk->pi_state_list))) | ||
584 | exit_pi_state_list(tsk); | ||
569 | #endif | 585 | #endif |
570 | 586 | ||
571 | /* Get rid of any cached register state */ | 587 | /* Get rid of any cached register state */ |
@@ -635,9 +651,14 @@ struct mm_struct *dup_mm(struct task_struct *tsk) | |||
635 | mm->hiwater_rss = get_mm_rss(mm); | 651 | mm->hiwater_rss = get_mm_rss(mm); |
636 | mm->hiwater_vm = mm->total_vm; | 652 | mm->hiwater_vm = mm->total_vm; |
637 | 653 | ||
654 | if (mm->binfmt && !try_module_get(mm->binfmt->module)) | ||
655 | goto free_pt; | ||
656 | |||
638 | return mm; | 657 | return mm; |
639 | 658 | ||
640 | free_pt: | 659 | free_pt: |
660 | /* don't put binfmt in mmput, we haven't got module yet */ | ||
661 | mm->binfmt = NULL; | ||
641 | mmput(mm); | 662 | mmput(mm); |
642 | 663 | ||
643 | fail_nomem: | 664 | fail_nomem: |
@@ -805,10 +826,10 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) | |||
805 | thread_group_cputime_init(sig); | 826 | thread_group_cputime_init(sig); |
806 | 827 | ||
807 | /* Expiration times and increments. */ | 828 | /* Expiration times and increments. */ |
808 | sig->it_virt_expires = cputime_zero; | 829 | sig->it[CPUCLOCK_PROF].expires = cputime_zero; |
809 | sig->it_virt_incr = cputime_zero; | 830 | sig->it[CPUCLOCK_PROF].incr = cputime_zero; |
810 | sig->it_prof_expires = cputime_zero; | 831 | sig->it[CPUCLOCK_VIRT].expires = cputime_zero; |
811 | sig->it_prof_incr = cputime_zero; | 832 | sig->it[CPUCLOCK_VIRT].incr = cputime_zero; |
812 | 833 | ||
813 | /* Cached expiration times. */ | 834 | /* Cached expiration times. */ |
814 | sig->cputime_expires.prof_exp = cputime_zero; | 835 | sig->cputime_expires.prof_exp = cputime_zero; |
@@ -866,6 +887,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
866 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; | 887 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; |
867 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; | 888 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; |
868 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; | 889 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; |
890 | sig->maxrss = sig->cmaxrss = 0; | ||
869 | task_io_accounting_init(&sig->ioac); | 891 | task_io_accounting_init(&sig->ioac); |
870 | sig->sum_sched_runtime = 0; | 892 | sig->sum_sched_runtime = 0; |
871 | taskstats_tgid_init(sig); | 893 | taskstats_tgid_init(sig); |
@@ -977,6 +999,16 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
977 | if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) | 999 | if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) |
978 | return ERR_PTR(-EINVAL); | 1000 | return ERR_PTR(-EINVAL); |
979 | 1001 | ||
1002 | /* | ||
1003 | * Siblings of global init remain as zombies on exit since they are | ||
1004 | * not reaped by their parent (swapper). To solve this and to avoid | ||
1005 | * multi-rooted process trees, prevent global and container-inits | ||
1006 | * from creating siblings. | ||
1007 | */ | ||
1008 | if ((clone_flags & CLONE_PARENT) && | ||
1009 | current->signal->flags & SIGNAL_UNKILLABLE) | ||
1010 | return ERR_PTR(-EINVAL); | ||
1011 | |||
980 | retval = security_task_create(clone_flags); | 1012 | retval = security_task_create(clone_flags); |
981 | if (retval) | 1013 | if (retval) |
982 | goto fork_out; | 1014 | goto fork_out; |
@@ -1018,9 +1050,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1018 | if (!try_module_get(task_thread_info(p)->exec_domain->module)) | 1050 | if (!try_module_get(task_thread_info(p)->exec_domain->module)) |
1019 | goto bad_fork_cleanup_count; | 1051 | goto bad_fork_cleanup_count; |
1020 | 1052 | ||
1021 | if (p->binfmt && !try_module_get(p->binfmt->module)) | ||
1022 | goto bad_fork_cleanup_put_domain; | ||
1023 | |||
1024 | p->did_exec = 0; | 1053 | p->did_exec = 0; |
1025 | delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ | 1054 | delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ |
1026 | copy_flags(clone_flags, p); | 1055 | copy_flags(clone_flags, p); |
@@ -1094,6 +1123,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1094 | 1123 | ||
1095 | p->bts = NULL; | 1124 | p->bts = NULL; |
1096 | 1125 | ||
1126 | p->stack_start = stack_start; | ||
1127 | |||
1097 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1128 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
1098 | sched_fork(p, clone_flags); | 1129 | sched_fork(p, clone_flags); |
1099 | 1130 | ||
@@ -1306,9 +1337,6 @@ bad_fork_cleanup_cgroup: | |||
1306 | #endif | 1337 | #endif |
1307 | cgroup_exit(p, cgroup_callbacks_done); | 1338 | cgroup_exit(p, cgroup_callbacks_done); |
1308 | delayacct_tsk_free(p); | 1339 | delayacct_tsk_free(p); |
1309 | if (p->binfmt) | ||
1310 | module_put(p->binfmt->module); | ||
1311 | bad_fork_cleanup_put_domain: | ||
1312 | module_put(task_thread_info(p)->exec_domain->module); | 1340 | module_put(task_thread_info(p)->exec_domain->module); |
1313 | bad_fork_cleanup_count: | 1341 | bad_fork_cleanup_count: |
1314 | atomic_dec(&p->cred->user->processes); | 1342 | atomic_dec(&p->cred->user->processes); |