diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 2b44d82b8237..0276c30401a0 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <linux/taskstats_kern.h> | 59 | #include <linux/taskstats_kern.h> |
60 | #include <linux/random.h> | 60 | #include <linux/random.h> |
61 | #include <linux/tty.h> | 61 | #include <linux/tty.h> |
62 | #include <linux/proc_fs.h> | ||
63 | #include <linux/blkdev.h> | 62 | #include <linux/blkdev.h> |
64 | #include <linux/fs_struct.h> | 63 | #include <linux/fs_struct.h> |
65 | #include <linux/magic.h> | 64 | #include <linux/magic.h> |
@@ -383,15 +382,14 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
383 | get_file(file); | 382 | get_file(file); |
384 | if (tmp->vm_flags & VM_DENYWRITE) | 383 | if (tmp->vm_flags & VM_DENYWRITE) |
385 | atomic_dec(&inode->i_writecount); | 384 | atomic_dec(&inode->i_writecount); |
386 | spin_lock(&mapping->i_mmap_lock); | 385 | mutex_lock(&mapping->i_mmap_mutex); |
387 | if (tmp->vm_flags & VM_SHARED) | 386 | if (tmp->vm_flags & VM_SHARED) |
388 | mapping->i_mmap_writable++; | 387 | mapping->i_mmap_writable++; |
389 | tmp->vm_truncate_count = mpnt->vm_truncate_count; | ||
390 | flush_dcache_mmap_lock(mapping); | 388 | flush_dcache_mmap_lock(mapping); |
391 | /* insert tmp into the share list, just after mpnt */ | 389 | /* insert tmp into the share list, just after mpnt */ |
392 | vma_prio_tree_add(tmp, mpnt); | 390 | vma_prio_tree_add(tmp, mpnt); |
393 | flush_dcache_mmap_unlock(mapping); | 391 | flush_dcache_mmap_unlock(mapping); |
394 | spin_unlock(&mapping->i_mmap_lock); | 392 | mutex_unlock(&mapping->i_mmap_mutex); |
395 | } | 393 | } |
396 | 394 | ||
397 | /* | 395 | /* |
@@ -522,11 +520,12 @@ struct mm_struct * mm_alloc(void) | |||
522 | struct mm_struct * mm; | 520 | struct mm_struct * mm; |
523 | 521 | ||
524 | mm = allocate_mm(); | 522 | mm = allocate_mm(); |
525 | if (mm) { | 523 | if (!mm) |
526 | memset(mm, 0, sizeof(*mm)); | 524 | return NULL; |
527 | mm = mm_init(mm, current); | 525 | |
528 | } | 526 | memset(mm, 0, sizeof(*mm)); |
529 | return mm; | 527 | mm_init_cpumask(mm); |
528 | return mm_init(mm, current); | ||
530 | } | 529 | } |
531 | 530 | ||
532 | /* | 531 | /* |
@@ -573,6 +572,57 @@ void mmput(struct mm_struct *mm) | |||
573 | } | 572 | } |
574 | EXPORT_SYMBOL_GPL(mmput); | 573 | EXPORT_SYMBOL_GPL(mmput); |
575 | 574 | ||
575 | /* | ||
576 | * We added or removed a vma mapping the executable. The vmas are only mapped | ||
577 | * during exec and are not mapped with the mmap system call. | ||
578 | * Callers must hold down_write() on the mm's mmap_sem for these | ||
579 | */ | ||
580 | void added_exe_file_vma(struct mm_struct *mm) | ||
581 | { | ||
582 | mm->num_exe_file_vmas++; | ||
583 | } | ||
584 | |||
585 | void removed_exe_file_vma(struct mm_struct *mm) | ||
586 | { | ||
587 | mm->num_exe_file_vmas--; | ||
588 | if ((mm->num_exe_file_vmas == 0) && mm->exe_file){ | ||
589 | fput(mm->exe_file); | ||
590 | mm->exe_file = NULL; | ||
591 | } | ||
592 | |||
593 | } | ||
594 | |||
595 | void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) | ||
596 | { | ||
597 | if (new_exe_file) | ||
598 | get_file(new_exe_file); | ||
599 | if (mm->exe_file) | ||
600 | fput(mm->exe_file); | ||
601 | mm->exe_file = new_exe_file; | ||
602 | mm->num_exe_file_vmas = 0; | ||
603 | } | ||
604 | |||
605 | struct file *get_mm_exe_file(struct mm_struct *mm) | ||
606 | { | ||
607 | struct file *exe_file; | ||
608 | |||
609 | /* We need mmap_sem to protect against races with removal of | ||
610 | * VM_EXECUTABLE vmas */ | ||
611 | down_read(&mm->mmap_sem); | ||
612 | exe_file = mm->exe_file; | ||
613 | if (exe_file) | ||
614 | get_file(exe_file); | ||
615 | up_read(&mm->mmap_sem); | ||
616 | return exe_file; | ||
617 | } | ||
618 | |||
619 | static void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) | ||
620 | { | ||
621 | /* It's safe to write the exe_file pointer without exe_file_lock because | ||
622 | * this is called during fork when the task is not yet in /proc */ | ||
623 | newmm->exe_file = get_mm_exe_file(oldmm); | ||
624 | } | ||
625 | |||
576 | /** | 626 | /** |
577 | * get_task_mm - acquire a reference to the task's mm | 627 | * get_task_mm - acquire a reference to the task's mm |
578 | * | 628 | * |
@@ -679,6 +729,7 @@ struct mm_struct *dup_mm(struct task_struct *tsk) | |||
679 | goto fail_nomem; | 729 | goto fail_nomem; |
680 | 730 | ||
681 | memcpy(mm, oldmm, sizeof(*mm)); | 731 | memcpy(mm, oldmm, sizeof(*mm)); |
732 | mm_init_cpumask(mm); | ||
682 | 733 | ||
683 | /* Initializing for Swap token stuff */ | 734 | /* Initializing for Swap token stuff */ |
684 | mm->token_priority = 0; | 735 | mm->token_priority = 0; |
@@ -927,6 +978,10 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
927 | tty_audit_fork(sig); | 978 | tty_audit_fork(sig); |
928 | sched_autogroup_fork(sig); | 979 | sched_autogroup_fork(sig); |
929 | 980 | ||
981 | #ifdef CONFIG_CGROUPS | ||
982 | init_rwsem(&sig->threadgroup_fork_lock); | ||
983 | #endif | ||
984 | |||
930 | sig->oom_adj = current->signal->oom_adj; | 985 | sig->oom_adj = current->signal->oom_adj; |
931 | sig->oom_score_adj = current->signal->oom_score_adj; | 986 | sig->oom_score_adj = current->signal->oom_score_adj; |
932 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; | 987 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; |
@@ -1108,6 +1163,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1108 | monotonic_to_bootbased(&p->real_start_time); | 1163 | monotonic_to_bootbased(&p->real_start_time); |
1109 | p->io_context = NULL; | 1164 | p->io_context = NULL; |
1110 | p->audit_context = NULL; | 1165 | p->audit_context = NULL; |
1166 | if (clone_flags & CLONE_THREAD) | ||
1167 | threadgroup_fork_read_lock(current); | ||
1111 | cgroup_fork(p); | 1168 | cgroup_fork(p); |
1112 | #ifdef CONFIG_NUMA | 1169 | #ifdef CONFIG_NUMA |
1113 | p->mempolicy = mpol_dup(p->mempolicy); | 1170 | p->mempolicy = mpol_dup(p->mempolicy); |
@@ -1193,12 +1250,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1193 | if (clone_flags & CLONE_THREAD) | 1250 | if (clone_flags & CLONE_THREAD) |
1194 | p->tgid = current->tgid; | 1251 | p->tgid = current->tgid; |
1195 | 1252 | ||
1196 | if (current->nsproxy != p->nsproxy) { | ||
1197 | retval = ns_cgroup_clone(p, pid); | ||
1198 | if (retval) | ||
1199 | goto bad_fork_free_pid; | ||
1200 | } | ||
1201 | |||
1202 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | 1253 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
1203 | /* | 1254 | /* |
1204 | * Clear TID on mm_release()? | 1255 | * Clear TID on mm_release()? |
@@ -1312,6 +1363,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1312 | write_unlock_irq(&tasklist_lock); | 1363 | write_unlock_irq(&tasklist_lock); |
1313 | proc_fork_connector(p); | 1364 | proc_fork_connector(p); |
1314 | cgroup_post_fork(p); | 1365 | cgroup_post_fork(p); |
1366 | if (clone_flags & CLONE_THREAD) | ||
1367 | threadgroup_fork_read_unlock(current); | ||
1315 | perf_event_fork(p); | 1368 | perf_event_fork(p); |
1316 | return p; | 1369 | return p; |
1317 | 1370 | ||
@@ -1350,6 +1403,8 @@ bad_fork_cleanup_policy: | |||
1350 | mpol_put(p->mempolicy); | 1403 | mpol_put(p->mempolicy); |
1351 | bad_fork_cleanup_cgroup: | 1404 | bad_fork_cleanup_cgroup: |
1352 | #endif | 1405 | #endif |
1406 | if (clone_flags & CLONE_THREAD) | ||
1407 | threadgroup_fork_read_unlock(current); | ||
1353 | cgroup_exit(p, cgroup_callbacks_done); | 1408 | cgroup_exit(p, cgroup_callbacks_done); |
1354 | delayacct_tsk_free(p); | 1409 | delayacct_tsk_free(p); |
1355 | module_put(task_thread_info(p)->exec_domain->module); | 1410 | module_put(task_thread_info(p)->exec_domain->module); |
@@ -1507,6 +1562,13 @@ void __init proc_caches_init(void) | |||
1507 | fs_cachep = kmem_cache_create("fs_cache", | 1562 | fs_cachep = kmem_cache_create("fs_cache", |
1508 | sizeof(struct fs_struct), 0, | 1563 | sizeof(struct fs_struct), 0, |
1509 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); | 1564 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |
1565 | /* | ||
1566 | * FIXME! The "sizeof(struct mm_struct)" currently includes the | ||
1567 | * whole struct cpumask for the OFFSTACK case. We could change | ||
1568 | * this to *only* allocate as much of it as required by the | ||
1569 | * maximum number of CPU's we can ever have. The cpumask_allocation | ||
1570 | * is at the end of the structure, exactly for that reason. | ||
1571 | */ | ||
1510 | mm_cachep = kmem_cache_create("mm_struct", | 1572 | mm_cachep = kmem_cache_create("mm_struct", |
1511 | sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, | 1573 | sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, |
1512 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); | 1574 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |