cgroup: allow ->post_create() to fail
authorTejun Heo <tj@kernel.org>
Mon, 19 Nov 2012 16:13:38 +0000 (08:13 -0800)
committerTejun Heo <tj@kernel.org>
Mon, 19 Nov 2012 16:13:38 +0000 (08:13 -0800)
There could be cases where controllers want to do initialization
operations which may fail from ->post_create().  This patch makes
->post_create() return -errno to indicate failure and online_css()
relay such failures.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Cc: Glauber Costa <glommer@parallels.com>
include/linux/cgroup.h
kernel/cgroup.c
kernel/cgroup_freezer.c

index f4a9c9836906710ba74035e5ee0db6b6276e3685..03d8a92786daff039c5b22af023d2ea98bbd7d02 100644 (file)
@@ -440,7 +440,7 @@ int cgroup_taskset_size(struct cgroup_taskset *tset);
 
 struct cgroup_subsys {
        struct cgroup_subsys_state *(*create)(struct cgroup *cgrp);
-       void (*post_create)(struct cgroup *cgrp);
+       int (*post_create)(struct cgroup *cgrp);
        void (*pre_destroy)(struct cgroup *cgrp);
        void (*destroy)(struct cgroup *cgrp);
        int (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
index 027b66e66698706ae88611a4b903f752624273f5..c389f4258681b669168cc3a12523baeb0ca1cc26 100644 (file)
@@ -4041,14 +4041,18 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
        INIT_WORK(&css->dput_work, css_dput_fn);
 }
 
-/* invoke ->post_create() on a new CSS and mark it online */
-static void online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
+/* invoke ->post_create() on a new CSS and mark it online if successful */
+static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
 {
+       int ret = 0;
+
        lockdep_assert_held(&cgroup_mutex);
 
        if (ss->post_create)
-               ss->post_create(cgrp);
-       cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE;
+               ret = ss->post_create(cgrp);
+       if (!ret)
+               cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE;
+       return ret;
 }
 
 /* if the CSS is online, invoke ->pre_destory() on it and mark it offline */
@@ -4174,12 +4178,15 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       for_each_subsys(root, ss) {
-               /* each css holds a ref to the cgroup's dentry */
+       /* each css holds a ref to the cgroup's dentry */
+       for_each_subsys(root, ss)
                dget(dentry);
 
-               /* creation succeeded, notify subsystems */
-               online_css(ss, cgrp);
+       /* creation succeeded, notify subsystems */
+       for_each_subsys(root, ss) {
+               err = online_css(ss, cgrp);
+               if (err)
+                       goto err_destroy;
        }
 
        err = cgroup_populate_dir(cgrp, true, root->subsys_mask);
@@ -4393,7 +4400,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
        BUG_ON(!list_empty(&init_task.tasks));
 
        ss->active = 1;
-       online_css(ss, dummytop);
+       BUG_ON(online_css(ss, dummytop));
 
        mutex_unlock(&cgroup_mutex);
 
@@ -4500,7 +4507,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        write_unlock(&css_set_lock);
 
        ss->active = 1;
-       online_css(ss, dummytop);
+       ret = online_css(ss, dummytop);
+       if (ret)
+               goto err_unload;
 
        /* success! */
        mutex_unlock(&cgroup_mutex);
index 670a4af7dc94d0e0f0974c0e69ce3d62cee7e186..ee8bb671688ce89e852a5a0b4976bb42d0f364d1 100644 (file)
@@ -112,7 +112,7 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
  * parent's freezing state while holding both parent's and our
  * freezer->lock.
  */
-static void freezer_post_create(struct cgroup *cgroup)
+static int freezer_post_create(struct cgroup *cgroup)
 {
        struct freezer *freezer = cgroup_freezer(cgroup);
        struct freezer *parent = parent_freezer(freezer);
@@ -136,6 +136,8 @@ static void freezer_post_create(struct cgroup *cgroup)
        spin_unlock(&freezer->lock);
        if (parent)
                spin_unlock_irq(&parent->lock);
+
+       return 0;
 }
 
 /**