Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[linux-2.6-block.git] / kernel / cgroup / cgroup.c
index 9f617605dacbfe5b2c75f0e04d88ad77e6922531..cef98502b124b8fc60c62b39b61f0d53334ce23c 100644 (file)
@@ -1927,7 +1927,7 @@ void init_cgroup_root(struct cgroup_root *root, struct cgroup_sb_opts *opts)
                set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags);
 }
 
-int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask, int ref_flags)
+int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
 {
        LIST_HEAD(tmp_links);
        struct cgroup *root_cgrp = &root->cgrp;
@@ -1944,7 +1944,7 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask, int ref_flags)
        root_cgrp->ancestor_ids[0] = ret;
 
        ret = percpu_ref_init(&root_cgrp->self.refcnt, css_release,
-                             ref_flags, GFP_KERNEL);
+                             0, GFP_KERNEL);
        if (ret)
                goto out;
 
@@ -2033,7 +2033,7 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
                               struct cgroup_namespace *ns)
 {
        struct dentry *dentry;
-       bool new_sb;
+       bool new_sb = false;
 
        dentry = kernfs_mount(fs_type, flags, root->kf_root, magic, &new_sb);
 
@@ -2043,6 +2043,7 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
         */
        if (!IS_ERR(dentry) && ns != &init_cgroup_ns) {
                struct dentry *nsdentry;
+               struct super_block *sb = dentry->d_sb;
                struct cgroup *cgrp;
 
                mutex_lock(&cgroup_mutex);
@@ -2053,12 +2054,14 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
                spin_unlock_irq(&css_set_lock);
                mutex_unlock(&cgroup_mutex);
 
-               nsdentry = kernfs_node_dentry(cgrp->kn, dentry->d_sb);
+               nsdentry = kernfs_node_dentry(cgrp->kn, sb);
                dput(dentry);
+               if (IS_ERR(nsdentry))
+                       deactivate_locked_super(sb);
                dentry = nsdentry;
        }
 
-       if (IS_ERR(dentry) || !new_sb)
+       if (!new_sb)
                cgroup_put(&root->cgrp);
 
        return dentry;
@@ -2118,18 +2121,16 @@ static void cgroup_kill_sb(struct super_block *sb)
        struct cgroup_root *root = cgroup_root_from_kf(kf_root);
 
        /*
-        * If @root doesn't have any mounts or children, start killing it.
+        * If @root doesn't have any children, start killing it.
         * This prevents new mounts by disabling percpu_ref_tryget_live().
         * cgroup_mount() may wait for @root's release.
         *
         * And don't kill the default root.
         */
-       if (!list_empty(&root->cgrp.self.children) ||
-           root == &cgrp_dfl_root)
-               cgroup_put(&root->cgrp);
-       else
+       if (list_empty(&root->cgrp.self.children) && root != &cgrp_dfl_root &&
+           !percpu_ref_is_dying(&root->cgrp.self.refcnt))
                percpu_ref_kill(&root->cgrp.self.refcnt);
-
+       cgroup_put(&root->cgrp);
        kernfs_kill_sb(sb);
 }
 
@@ -5399,7 +5400,7 @@ int __init cgroup_init(void)
        hash_add(css_set_table, &init_css_set.hlist,
                 css_set_hash(init_css_set.subsys));
 
-       BUG_ON(cgroup_setup_root(&cgrp_dfl_root, 0, 0));
+       BUG_ON(cgroup_setup_root(&cgrp_dfl_root, 0));
 
        mutex_unlock(&cgroup_mutex);