cpuset: introduce ->css_on/offline()
[~shefty/rdma-dev.git] / kernel / cpuset.c
index 5372b6f5e5b3ed91224b55f41ab4d0a2ded1557c..1d7a611ff771cbd5be792e41ce05d90bfa2d60bf 100644 (file)
@@ -1790,15 +1790,12 @@ static struct cftype files[] = {
 
 static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont)
 {
-       struct cgroup *parent_cg = cont->parent;
-       struct cgroup *tmp_cg;
-       struct cpuset *parent, *cs;
+       struct cpuset *cs;
 
-       if (!parent_cg)
+       if (!cont->parent)
                return &top_cpuset.css;
-       parent = cgroup_cs(parent_cg);
 
-       cs = kmalloc(sizeof(*cs), GFP_KERNEL);
+       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
        if (!cs)
                return ERR_PTR(-ENOMEM);
        if (!alloc_cpumask_var(&cs->cpus_allowed, GFP_KERNEL)) {
@@ -1806,22 +1803,34 @@ static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont)
                return ERR_PTR(-ENOMEM);
        }
 
-       cs->flags = 0;
-       if (is_spread_page(parent))
-               set_bit(CS_SPREAD_PAGE, &cs->flags);
-       if (is_spread_slab(parent))
-               set_bit(CS_SPREAD_SLAB, &cs->flags);
        set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
        cpumask_clear(cs->cpus_allowed);
        nodes_clear(cs->mems_allowed);
        fmeter_init(&cs->fmeter);
        cs->relax_domain_level = -1;
+       cs->parent = cgroup_cs(cont->parent);
+
+       return &cs->css;
+}
+
+static int cpuset_css_online(struct cgroup *cgrp)
+{
+       struct cpuset *cs = cgroup_cs(cgrp);
+       struct cpuset *parent = cs->parent;
+       struct cgroup *tmp_cg;
+
+       if (!parent)
+               return 0;
+
+       if (is_spread_page(parent))
+               set_bit(CS_SPREAD_PAGE, &cs->flags);
+       if (is_spread_slab(parent))
+               set_bit(CS_SPREAD_SLAB, &cs->flags);
 
-       cs->parent = parent;
        number_of_cpusets++;
 
-       if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &cont->flags))
-               goto skip_clone;
+       if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags))
+               return 0;
 
        /*
         * Clone @parent's configuration if CGRP_CPUSET_CLONE_CHILDREN is
@@ -1836,19 +1845,34 @@ static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont)
         * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
         * (and likewise for mems) to the new cgroup.
         */
-       list_for_each_entry(tmp_cg, &parent_cg->children, sibling) {
+       list_for_each_entry(tmp_cg, &cgrp->parent->children, sibling) {
                struct cpuset *tmp_cs = cgroup_cs(tmp_cg);
 
                if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs))
-                       goto skip_clone;
+                       return 0;
        }
 
        mutex_lock(&callback_mutex);
        cs->mems_allowed = parent->mems_allowed;
        cpumask_copy(cs->cpus_allowed, parent->cpus_allowed);
        mutex_unlock(&callback_mutex);
-skip_clone:
-       return &cs->css;
+
+       return 0;
+}
+
+static void cpuset_css_offline(struct cgroup *cgrp)
+{
+       struct cpuset *cs = cgroup_cs(cgrp);
+
+       /* css_offline is called w/o cgroup_mutex, grab it */
+       cgroup_lock();
+
+       if (is_sched_load_balance(cs))
+               update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
+
+       number_of_cpusets--;
+
+       cgroup_unlock();
 }
 
 /*
@@ -1861,10 +1885,6 @@ static void cpuset_css_free(struct cgroup *cont)
 {
        struct cpuset *cs = cgroup_cs(cont);
 
-       if (is_sched_load_balance(cs))
-               update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
-
-       number_of_cpusets--;
        free_cpumask_var(cs->cpus_allowed);
        kfree(cs);
 }
@@ -1872,6 +1892,8 @@ static void cpuset_css_free(struct cgroup *cont)
 struct cgroup_subsys cpuset_subsys = {
        .name = "cpuset",
        .css_alloc = cpuset_css_alloc,
+       .css_online = cpuset_css_online,
+       .css_offline = cpuset_css_offline,
        .css_free = cpuset_css_free,
        .can_attach = cpuset_can_attach,
        .attach = cpuset_attach,