diff options
author | Tejun Heo <tj@kernel.org> | 2012-04-01 15:30:01 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-04-01 15:55:00 -0400 |
commit | 959d851caa48829eb85cb85aa949fd6b4c5d5bc6 (patch) | |
tree | 3ba9c94ec346275fb44c4f0d1cd2537cdff8d811 /kernel/fork.c | |
parent | a5567932fc926739e29e98487128080f40c61710 (diff) | |
parent | 48ddbe194623ae089cc0576e60363f2d2e85662a (diff) |
Merge branch 'for-3.5' of ../cgroup into block/for-3.5/core-merged
cgroup/for-3.5 contains the following changes which blk-cgroup needs
to proceed with the on-going cleanup.
* Dynamic addition and removal of cftypes to make config/stat file
handling modular for policies.
* cgroup removal update to not wait for css references to drain to fix
blkcg removal hang caused by cfq caching cfqgs.
Pull in cgroup/for-3.5 into block/for-3.5/core. This causes the
following conflicts in block/blk-cgroup.c.
* 761b3ef50e "cgroup: remove cgroup_subsys argument from callbacks"
conflicts with blkiocg_pre_destroy() addition and blkiocg_attach()
removal. Resolved by removing @subsys from all subsys methods.
* 676f7c8f84 "cgroup: relocate cftype and cgroup_subsys definitions in
controllers" conflicts with ->pre_destroy() and ->attach() updates
and removal of modular config. Resolved by dropping forward
declarations of the methods and applying updates to the relocated
blkio_subsys.
* 4baf6e3325 "cgroup: convert all non-memcg controllers to the new
cftype interface" builds upon the previous item. Resolved by adding
->base_cftypes to the relocated blkio_subsys.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 101 |
1 files changed, 74 insertions, 27 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index a1b632713e43..08eb8584e2a8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/user-return-notifier.h> | 66 | #include <linux/user-return-notifier.h> |
67 | #include <linux/oom.h> | 67 | #include <linux/oom.h> |
68 | #include <linux/khugepaged.h> | 68 | #include <linux/khugepaged.h> |
69 | #include <linux/signalfd.h> | ||
69 | 70 | ||
70 | #include <asm/pgtable.h> | 71 | #include <asm/pgtable.h> |
71 | #include <asm/pgalloc.h> | 72 | #include <asm/pgalloc.h> |
@@ -192,6 +193,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
192 | WARN_ON(atomic_read(&tsk->usage)); | 193 | WARN_ON(atomic_read(&tsk->usage)); |
193 | WARN_ON(tsk == current); | 194 | WARN_ON(tsk == current); |
194 | 195 | ||
196 | security_task_free(tsk); | ||
195 | exit_creds(tsk); | 197 | exit_creds(tsk); |
196 | delayacct_tsk_free(tsk); | 198 | delayacct_tsk_free(tsk); |
197 | put_signal_struct(tsk->signal); | 199 | put_signal_struct(tsk->signal); |
@@ -354,7 +356,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
354 | charge = 0; | 356 | charge = 0; |
355 | if (mpnt->vm_flags & VM_ACCOUNT) { | 357 | if (mpnt->vm_flags & VM_ACCOUNT) { |
356 | unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; | 358 | unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; |
357 | if (security_vm_enough_memory(len)) | 359 | if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ |
358 | goto fail_nomem; | 360 | goto fail_nomem; |
359 | charge = len; | 361 | charge = len; |
360 | } | 362 | } |
@@ -510,6 +512,23 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | |||
510 | return NULL; | 512 | return NULL; |
511 | } | 513 | } |
512 | 514 | ||
515 | static void check_mm(struct mm_struct *mm) | ||
516 | { | ||
517 | int i; | ||
518 | |||
519 | for (i = 0; i < NR_MM_COUNTERS; i++) { | ||
520 | long x = atomic_long_read(&mm->rss_stat.count[i]); | ||
521 | |||
522 | if (unlikely(x)) | ||
523 | printk(KERN_ALERT "BUG: Bad rss-counter state " | ||
524 | "mm:%p idx:%d val:%ld\n", mm, i, x); | ||
525 | } | ||
526 | |||
527 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
528 | VM_BUG_ON(mm->pmd_huge_pte); | ||
529 | #endif | ||
530 | } | ||
531 | |||
513 | /* | 532 | /* |
514 | * Allocate and initialize an mm_struct. | 533 | * Allocate and initialize an mm_struct. |
515 | */ | 534 | */ |
@@ -537,9 +556,7 @@ void __mmdrop(struct mm_struct *mm) | |||
537 | mm_free_pgd(mm); | 556 | mm_free_pgd(mm); |
538 | destroy_context(mm); | 557 | destroy_context(mm); |
539 | mmu_notifier_mm_destroy(mm); | 558 | mmu_notifier_mm_destroy(mm); |
540 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 559 | check_mm(mm); |
541 | VM_BUG_ON(mm->pmd_huge_pte); | ||
542 | #endif | ||
543 | free_mm(mm); | 560 | free_mm(mm); |
544 | } | 561 | } |
545 | EXPORT_SYMBOL_GPL(__mmdrop); | 562 | EXPORT_SYMBOL_GPL(__mmdrop); |
@@ -667,6 +684,38 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) | |||
667 | return mm; | 684 | return mm; |
668 | } | 685 | } |
669 | 686 | ||
687 | static void complete_vfork_done(struct task_struct *tsk) | ||
688 | { | ||
689 | struct completion *vfork; | ||
690 | |||
691 | task_lock(tsk); | ||
692 | vfork = tsk->vfork_done; | ||
693 | if (likely(vfork)) { | ||
694 | tsk->vfork_done = NULL; | ||
695 | complete(vfork); | ||
696 | } | ||
697 | task_unlock(tsk); | ||
698 | } | ||
699 | |||
700 | static int wait_for_vfork_done(struct task_struct *child, | ||
701 | struct completion *vfork) | ||
702 | { | ||
703 | int killed; | ||
704 | |||
705 | freezer_do_not_count(); | ||
706 | killed = wait_for_completion_killable(vfork); | ||
707 | freezer_count(); | ||
708 | |||
709 | if (killed) { | ||
710 | task_lock(child); | ||
711 | child->vfork_done = NULL; | ||
712 | task_unlock(child); | ||
713 | } | ||
714 | |||
715 | put_task_struct(child); | ||
716 | return killed; | ||
717 | } | ||
718 | |||
670 | /* Please note the differences between mmput and mm_release. | 719 | /* Please note the differences between mmput and mm_release. |
671 | * mmput is called whenever we stop holding onto a mm_struct, | 720 | * mmput is called whenever we stop holding onto a mm_struct, |
672 | * error success whatever. | 721 | * error success whatever. |
@@ -682,8 +731,6 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) | |||
682 | */ | 731 | */ |
683 | void mm_release(struct task_struct *tsk, struct mm_struct *mm) | 732 | void mm_release(struct task_struct *tsk, struct mm_struct *mm) |
684 | { | 733 | { |
685 | struct completion *vfork_done = tsk->vfork_done; | ||
686 | |||
687 | /* Get rid of any futexes when releasing the mm */ | 734 | /* Get rid of any futexes when releasing the mm */ |
688 | #ifdef CONFIG_FUTEX | 735 | #ifdef CONFIG_FUTEX |
689 | if (unlikely(tsk->robust_list)) { | 736 | if (unlikely(tsk->robust_list)) { |
@@ -703,17 +750,15 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
703 | /* Get rid of any cached register state */ | 750 | /* Get rid of any cached register state */ |
704 | deactivate_mm(tsk, mm); | 751 | deactivate_mm(tsk, mm); |
705 | 752 | ||
706 | /* notify parent sleeping on vfork() */ | 753 | if (tsk->vfork_done) |
707 | if (vfork_done) { | 754 | complete_vfork_done(tsk); |
708 | tsk->vfork_done = NULL; | ||
709 | complete(vfork_done); | ||
710 | } | ||
711 | 755 | ||
712 | /* | 756 | /* |
713 | * If we're exiting normally, clear a user-space tid field if | 757 | * If we're exiting normally, clear a user-space tid field if |
714 | * requested. We leave this alone when dying by signal, to leave | 758 | * requested. We leave this alone when dying by signal, to leave |
715 | * the value intact in a core dump, and to save the unnecessary | 759 | * the value intact in a core dump, and to save the unnecessary |
716 | * trouble otherwise. Userland only wants this done for a sys_exit. | 760 | * trouble, say, a killed vfork parent shouldn't touch this mm. |
761 | * Userland only wants this done for a sys_exit. | ||
717 | */ | 762 | */ |
718 | if (tsk->clear_child_tid) { | 763 | if (tsk->clear_child_tid) { |
719 | if (!(tsk->flags & PF_SIGNALED) && | 764 | if (!(tsk->flags & PF_SIGNALED) && |
@@ -934,8 +979,10 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | |||
934 | 979 | ||
935 | void __cleanup_sighand(struct sighand_struct *sighand) | 980 | void __cleanup_sighand(struct sighand_struct *sighand) |
936 | { | 981 | { |
937 | if (atomic_dec_and_test(&sighand->count)) | 982 | if (atomic_dec_and_test(&sighand->count)) { |
983 | signalfd_cleanup(sighand); | ||
938 | kmem_cache_free(sighand_cachep, sighand); | 984 | kmem_cache_free(sighand_cachep, sighand); |
985 | } | ||
939 | } | 986 | } |
940 | 987 | ||
941 | 988 | ||
@@ -1003,6 +1050,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
1003 | sig->oom_score_adj = current->signal->oom_score_adj; | 1050 | sig->oom_score_adj = current->signal->oom_score_adj; |
1004 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; | 1051 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; |
1005 | 1052 | ||
1053 | sig->has_child_subreaper = current->signal->has_child_subreaper || | ||
1054 | current->signal->is_child_subreaper; | ||
1055 | |||
1006 | mutex_init(&sig->cred_guard_mutex); | 1056 | mutex_init(&sig->cred_guard_mutex); |
1007 | 1057 | ||
1008 | return 0; | 1058 | return 0; |
@@ -1014,7 +1064,6 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
1014 | 1064 | ||
1015 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); | 1065 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); |
1016 | new_flags |= PF_FORKNOEXEC; | 1066 | new_flags |= PF_FORKNOEXEC; |
1017 | new_flags |= PF_STARTING; | ||
1018 | p->flags = new_flags; | 1067 | p->flags = new_flags; |
1019 | } | 1068 | } |
1020 | 1069 | ||
@@ -1191,6 +1240,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1191 | #ifdef CONFIG_CPUSETS | 1240 | #ifdef CONFIG_CPUSETS |
1192 | p->cpuset_mem_spread_rotor = NUMA_NO_NODE; | 1241 | p->cpuset_mem_spread_rotor = NUMA_NO_NODE; |
1193 | p->cpuset_slab_spread_rotor = NUMA_NO_NODE; | 1242 | p->cpuset_slab_spread_rotor = NUMA_NO_NODE; |
1243 | seqcount_init(&p->mems_allowed_seq); | ||
1194 | #endif | 1244 | #endif |
1195 | #ifdef CONFIG_TRACE_IRQFLAGS | 1245 | #ifdef CONFIG_TRACE_IRQFLAGS |
1196 | p->irq_events = 0; | 1246 | p->irq_events = 0; |
@@ -1309,7 +1359,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1309 | clear_all_latency_tracing(p); | 1359 | clear_all_latency_tracing(p); |
1310 | 1360 | ||
1311 | /* ok, now we should be set up.. */ | 1361 | /* ok, now we should be set up.. */ |
1312 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); | 1362 | if (clone_flags & CLONE_THREAD) |
1363 | p->exit_signal = -1; | ||
1364 | else if (clone_flags & CLONE_PARENT) | ||
1365 | p->exit_signal = current->group_leader->exit_signal; | ||
1366 | else | ||
1367 | p->exit_signal = (clone_flags & CSIGNAL); | ||
1368 | |||
1313 | p->pdeath_signal = 0; | 1369 | p->pdeath_signal = 0; |
1314 | p->exit_state = 0; | 1370 | p->exit_state = 0; |
1315 | 1371 | ||
@@ -1544,16 +1600,9 @@ long do_fork(unsigned long clone_flags, | |||
1544 | if (clone_flags & CLONE_VFORK) { | 1600 | if (clone_flags & CLONE_VFORK) { |
1545 | p->vfork_done = &vfork; | 1601 | p->vfork_done = &vfork; |
1546 | init_completion(&vfork); | 1602 | init_completion(&vfork); |
1603 | get_task_struct(p); | ||
1547 | } | 1604 | } |
1548 | 1605 | ||
1549 | /* | ||
1550 | * We set PF_STARTING at creation in case tracing wants to | ||
1551 | * use this to distinguish a fully live task from one that | ||
1552 | * hasn't finished SIGSTOP raising yet. Now we clear it | ||
1553 | * and set the child going. | ||
1554 | */ | ||
1555 | p->flags &= ~PF_STARTING; | ||
1556 | |||
1557 | wake_up_new_task(p); | 1606 | wake_up_new_task(p); |
1558 | 1607 | ||
1559 | /* forking complete and child started to run, tell ptracer */ | 1608 | /* forking complete and child started to run, tell ptracer */ |
@@ -1561,10 +1610,8 @@ long do_fork(unsigned long clone_flags, | |||
1561 | ptrace_event(trace, nr); | 1610 | ptrace_event(trace, nr); |
1562 | 1611 | ||
1563 | if (clone_flags & CLONE_VFORK) { | 1612 | if (clone_flags & CLONE_VFORK) { |
1564 | freezer_do_not_count(); | 1613 | if (!wait_for_vfork_done(p, &vfork)) |
1565 | wait_for_completion(&vfork); | 1614 | ptrace_event(PTRACE_EVENT_VFORK_DONE, nr); |
1566 | freezer_count(); | ||
1567 | ptrace_event(PTRACE_EVENT_VFORK_DONE, nr); | ||
1568 | } | 1615 | } |
1569 | } else { | 1616 | } else { |
1570 | nr = PTR_ERR(p); | 1617 | nr = PTR_ERR(p); |