|
|
@@ -1072,6 +1072,7 @@ struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
|
|
|
struct cgroup_subsys *ss;
|
|
|
struct dentry *dentry;
|
|
|
int i, ret;
|
|
|
+ bool new_root = false;
|
|
|
|
|
|
cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
|
|
|
|
|
|
@@ -1181,10 +1182,11 @@ struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
|
|
|
ret = -ENOMEM;
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
+ new_root = true;
|
|
|
|
|
|
init_cgroup_root(root, &opts);
|
|
|
|
|
|
- ret = cgroup_setup_root(root, opts.subsys_mask);
|
|
|
+ ret = cgroup_setup_root(root, opts.subsys_mask, PERCPU_REF_INIT_DEAD);
|
|
|
if (ret)
|
|
|
cgroup_free_root(root);
|
|
|
|
|
|
@@ -1200,6 +1202,18 @@ out_free:
|
|
|
dentry = cgroup_do_mount(&cgroup_fs_type, flags, root,
|
|
|
CGROUP_SUPER_MAGIC, ns);
|
|
|
|
|
|
+ /*
|
|
|
+ * There's a race window after we release cgroup_mutex and before
|
|
|
+ * allocating a superblock. Make sure a concurrent process won't
|
|
|
+ * be able to re-use the root during this window by delaying the
|
|
|
+ * initialization of root refcnt.
|
|
|
+ */
|
|
|
+ if (new_root) {
|
|
|
+ mutex_lock(&cgroup_mutex);
|
|
|
+ percpu_ref_reinit(&root->cgrp.self.refcnt);
|
|
|
+ mutex_unlock(&cgroup_mutex);
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* If @pinned_sb, we're reusing an existing root and holding an
|
|
|
* extra ref on its sb. Mount is complete. Put the extra ref.
|