diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index f6083561dfe0..7b93da72d4a2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -40,12 +40,14 @@ | |||
| 40 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
| 41 | #include <linux/tracehook.h> | 41 | #include <linux/tracehook.h> |
| 42 | #include <linux/futex.h> | 42 | #include <linux/futex.h> |
| 43 | #include <linux/compat.h> | ||
| 43 | #include <linux/task_io_accounting_ops.h> | 44 | #include <linux/task_io_accounting_ops.h> |
| 44 | #include <linux/rcupdate.h> | 45 | #include <linux/rcupdate.h> |
| 45 | #include <linux/ptrace.h> | 46 | #include <linux/ptrace.h> |
| 46 | #include <linux/mount.h> | 47 | #include <linux/mount.h> |
| 47 | #include <linux/audit.h> | 48 | #include <linux/audit.h> |
| 48 | #include <linux/memcontrol.h> | 49 | #include <linux/memcontrol.h> |
| 50 | #include <linux/ftrace.h> | ||
| 49 | #include <linux/profile.h> | 51 | #include <linux/profile.h> |
| 50 | #include <linux/rmap.h> | 52 | #include <linux/rmap.h> |
| 51 | #include <linux/acct.h> | 53 | #include <linux/acct.h> |
| @@ -79,6 +81,8 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0; | |||
| 79 | 81 | ||
| 80 | __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ | 82 | __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ |
| 81 | 83 | ||
| 84 | DEFINE_TRACE(sched_process_fork); | ||
| 85 | |||
| 82 | int nr_processes(void) | 86 | int nr_processes(void) |
| 83 | { | 87 | { |
| 84 | int cpu; | 88 | int cpu; |
| @@ -136,6 +140,7 @@ void free_task(struct task_struct *tsk) | |||
| 136 | prop_local_destroy_single(&tsk->dirties); | 140 | prop_local_destroy_single(&tsk->dirties); |
| 137 | free_thread_info(tsk->stack); | 141 | free_thread_info(tsk->stack); |
| 138 | rt_mutex_debug_task_free(tsk); | 142 | rt_mutex_debug_task_free(tsk); |
| 143 | ftrace_graph_exit_task(tsk); | ||
| 139 | free_task_struct(tsk); | 144 | free_task_struct(tsk); |
| 140 | } | 145 | } |
| 141 | EXPORT_SYMBOL(free_task); | 146 | EXPORT_SYMBOL(free_task); |
| @@ -314,17 +319,20 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 314 | file = tmp->vm_file; | 319 | file = tmp->vm_file; |
| 315 | if (file) { | 320 | if (file) { |
| 316 | struct inode *inode = file->f_path.dentry->d_inode; | 321 | struct inode *inode = file->f_path.dentry->d_inode; |
| 322 | struct address_space *mapping = file->f_mapping; | ||
| 323 | |||
| 317 | get_file(file); | 324 | get_file(file); |
| 318 | if (tmp->vm_flags & VM_DENYWRITE) | 325 | if (tmp->vm_flags & VM_DENYWRITE) |
| 319 | atomic_dec(&inode->i_writecount); | 326 | atomic_dec(&inode->i_writecount); |
| 320 | 327 | spin_lock(&mapping->i_mmap_lock); | |
| 321 | /* insert tmp into the share list, just after mpnt */ | 328 | if (tmp->vm_flags & VM_SHARED) |
| 322 | spin_lock(&file->f_mapping->i_mmap_lock); | 329 | mapping->i_mmap_writable++; |
| 323 | tmp->vm_truncate_count = mpnt->vm_truncate_count; | 330 | tmp->vm_truncate_count = mpnt->vm_truncate_count; |
| 324 | flush_dcache_mmap_lock(file->f_mapping); | 331 | flush_dcache_mmap_lock(mapping); |
| 332 | /* insert tmp into the share list, just after mpnt */ | ||
| 325 | vma_prio_tree_add(tmp, mpnt); | 333 | vma_prio_tree_add(tmp, mpnt); |
| 326 | flush_dcache_mmap_unlock(file->f_mapping); | 334 | flush_dcache_mmap_unlock(mapping); |
| 327 | spin_unlock(&file->f_mapping->i_mmap_lock); | 335 | spin_unlock(&mapping->i_mmap_lock); |
| 328 | } | 336 | } |
| 329 | 337 | ||
| 330 | /* | 338 | /* |
| @@ -519,6 +527,16 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
| 519 | { | 527 | { |
| 520 | struct completion *vfork_done = tsk->vfork_done; | 528 | struct completion *vfork_done = tsk->vfork_done; |
| 521 | 529 | ||
| 530 | /* Get rid of any futexes when releasing the mm */ | ||
| 531 | #ifdef CONFIG_FUTEX | ||
| 532 | if (unlikely(tsk->robust_list)) | ||
| 533 | exit_robust_list(tsk); | ||
| 534 | #ifdef CONFIG_COMPAT | ||
| 535 | if (unlikely(tsk->compat_robust_list)) | ||
| 536 | compat_exit_robust_list(tsk); | ||
| 537 | #endif | ||
| 538 | #endif | ||
| 539 | |||
| 522 | /* Get rid of any cached register state */ | 540 | /* Get rid of any cached register state */ |
| 523 | deactivate_mm(tsk, mm); | 541 | deactivate_mm(tsk, mm); |
| 524 | 542 | ||
| @@ -1122,6 +1140,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1122 | } | 1140 | } |
| 1123 | } | 1141 | } |
| 1124 | 1142 | ||
| 1143 | ftrace_graph_init_task(p); | ||
| 1144 | |||
| 1125 | p->pid = pid_nr(pid); | 1145 | p->pid = pid_nr(pid); |
| 1126 | p->tgid = p->pid; | 1146 | p->tgid = p->pid; |
| 1127 | if (clone_flags & CLONE_THREAD) | 1147 | if (clone_flags & CLONE_THREAD) |
| @@ -1130,7 +1150,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1130 | if (current->nsproxy != p->nsproxy) { | 1150 | if (current->nsproxy != p->nsproxy) { |
| 1131 | retval = ns_cgroup_clone(p, pid); | 1151 | retval = ns_cgroup_clone(p, pid); |
| 1132 | if (retval) | 1152 | if (retval) |
| 1133 | goto bad_fork_free_pid; | 1153 | goto bad_fork_free_graph; |
| 1134 | } | 1154 | } |
| 1135 | 1155 | ||
| 1136 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | 1156 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
| @@ -1223,7 +1243,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1223 | spin_unlock(¤t->sighand->siglock); | 1243 | spin_unlock(¤t->sighand->siglock); |
| 1224 | write_unlock_irq(&tasklist_lock); | 1244 | write_unlock_irq(&tasklist_lock); |
| 1225 | retval = -ERESTARTNOINTR; | 1245 | retval = -ERESTARTNOINTR; |
| 1226 | goto bad_fork_free_pid; | 1246 | goto bad_fork_free_graph; |
| 1227 | } | 1247 | } |
| 1228 | 1248 | ||
| 1229 | if (clone_flags & CLONE_THREAD) { | 1249 | if (clone_flags & CLONE_THREAD) { |
| @@ -1260,6 +1280,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1260 | cgroup_post_fork(p); | 1280 | cgroup_post_fork(p); |
| 1261 | return p; | 1281 | return p; |
| 1262 | 1282 | ||
| 1283 | bad_fork_free_graph: | ||
| 1284 | ftrace_graph_exit_task(p); | ||
| 1263 | bad_fork_free_pid: | 1285 | bad_fork_free_pid: |
| 1264 | if (pid != &init_struct_pid) | 1286 | if (pid != &init_struct_pid) |
| 1265 | free_pid(pid); | 1287 | free_pid(pid); |
| @@ -1387,6 +1409,7 @@ long do_fork(unsigned long clone_flags, | |||
| 1387 | init_completion(&vfork); | 1409 | init_completion(&vfork); |
| 1388 | } | 1410 | } |
| 1389 | 1411 | ||
| 1412 | audit_finish_fork(p); | ||
| 1390 | tracehook_report_clone(trace, regs, clone_flags, nr, p); | 1413 | tracehook_report_clone(trace, regs, clone_flags, nr, p); |
| 1391 | 1414 | ||
| 1392 | /* | 1415 | /* |
