aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c39
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
84DEFINE_TRACE(sched_process_fork);
85
82int nr_processes(void) 86int 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}
141EXPORT_SYMBOL(free_task); 146EXPORT_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(&current->sighand->siglock); 1243 spin_unlock(&current->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
1283bad_fork_free_graph:
1284 ftrace_graph_exit_task(p);
1263bad_fork_free_pid: 1285bad_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 /*