diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 2ce28f165e31..e7c181454dca 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -30,6 +30,7 @@ #include <linux/capability.h> #include <linux/cpu.h> #include <linux/cpuset.h> +#include <linux/cgroup.h> #include <linux/security.h> #include <linux/swap.h> #include <linux/syscalls.h> @@ -979,6 +980,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, { int retval; struct task_struct *p = NULL; + int cgroup_callbacks_done = 0; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); @@ -1088,12 +1090,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->io_context = NULL; p->audit_context = NULL; cpuset_fork(p); + cgroup_fork(p); #ifdef CONFIG_NUMA p->mempolicy = mpol_copy(p->mempolicy); if (IS_ERR(p->mempolicy)) { retval = PTR_ERR(p->mempolicy); p->mempolicy = NULL; - goto bad_fork_cleanup_cpuset; + goto bad_fork_cleanup_cgroup; } mpol_fix_fork_child_flag(p); #endif @@ -1204,6 +1207,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, /* Perform scheduler related setup. Assign this task to a CPU. */ sched_fork(p, clone_flags); + /* Now that the task is set up, run cgroup callbacks if + * necessary. We need to run them before the task is visible + * on the tasklist. */ + cgroup_fork_callbacks(p); + cgroup_callbacks_done = 1; + /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); @@ -1318,9 +1327,10 @@ bad_fork_cleanup_security: bad_fork_cleanup_policy: #ifdef CONFIG_NUMA mpol_free(p->mempolicy); -bad_fork_cleanup_cpuset: +bad_fork_cleanup_cgroup: #endif cpuset_exit(p); + cgroup_exit(p, cgroup_callbacks_done); bad_fork_cleanup_delays_binfmt: delayacct_tsk_free(p); if (p->binfmt) |