Commit d427dfeb authored by Tejun Heo's avatar Tejun Heo

cgroup: factor out cgroup_setup_root() from cgroup_mount()

Factor out new root initialization into cgroup_setup_root() from
cgroup_mount().  This makes it easier to follow and will ease kernfs
conversion.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
parent 8e30e2b8
......@@ -1455,67 +1455,30 @@ static int cgroup_get_rootdir(struct super_block *sb)
return 0;
}
static struct dentry *cgroup_mount(struct file_system_type *fs_type,
int flags, const char *unused_dev_name,
void *data)
static int cgroup_setup_root(struct cgroupfs_root *root)
{
LIST_HEAD(tmp_links);
struct super_block *sb = NULL;
struct inode *inode = NULL;
struct cgroupfs_root *root = NULL;
struct cgroup_sb_opts opts;
struct cgroupfs_root *new_root;
const struct cred *cred;
int ret;
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
/* First find the desired set of subsystems */
ret = parse_cgroupfs_options(data, &opts);
if (ret)
goto out_unlock;
/*
* Allocate a new cgroup root. We may not need it if we're
* reusing an existing hierarchy.
*/
new_root = cgroup_root_from_opts(&opts);
if (IS_ERR(new_root)) {
ret = PTR_ERR(new_root);
goto out_unlock;
}
opts.new_root = new_root;
/* Locate an existing or new sb for this hierarchy */
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgroup_tree_mutex);
sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts);
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
if (IS_ERR(sb)) {
ret = PTR_ERR(sb);
cgroup_free_root(opts.new_root);
goto out_unlock;
}
root = sb->s_fs_info;
BUG_ON(!root);
if (root == opts.new_root) {
/* We used the new root structure, so this is a new hierarchy */
struct super_block *sb = root->sb;
struct cgroup *root_cgrp = &root->top_cgroup;
struct cgroupfs_root *existing_root;
int i;
struct css_set *cset;
struct inode *inode;
const struct cred *cred;
int i, ret;
lockdep_assert_held(&cgroup_tree_mutex);
lockdep_assert_held(&cgroup_mutex);
BUG_ON(sb->s_root != NULL);
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgroup_tree_mutex);
ret = cgroup_get_rootdir(sb);
if (ret)
goto out_unlock;
if (ret) {
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
return ret;
}
inode = sb->s_root->d_inode;
mutex_lock(&inode->i_mutex);
......@@ -1527,7 +1490,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
goto out_unlock;
root_cgrp->id = ret;
/* Check for name clashes with existing mounts */
/* check for name clashes with existing mounts */
ret = -EBUSY;
if (strlen(root->name))
for_each_active_root(existing_root)
......@@ -1535,10 +1498,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
goto out_unlock;
/*
* We're accessing css_set_count without locking
* css_set_lock here, but that's OK - it can only be
* increased by someone holding cgroup_lock, and
* that's us. The worst that can happen is that we
* We're accessing css_set_count without locking css_set_lock here,
* but that's OK - it can only be increased by someone holding
* cgroup_lock, and that's us. The worst that can happen is that we
* have some link structures left over
*/
ret = allocate_cgrp_cset_links(css_set_count, &tmp_links);
......@@ -1554,11 +1516,11 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
root_cgrp->dentry = sb->s_root;
/*
* We're inside get_sb() and will call lookup_one_len() to
* create the root files, which doesn't work if SELinux is
* in use. The following cred dancing somehow works around
* it. See 2ce9738ba ("cgroupfs: use init_cred when
* populating new cgroupfs mount") for more details.
* We're inside get_sb() and will call lookup_one_len() to create
* the root files, which doesn't work if SELinux is in use. The
* following cred dancing somehow works around it. See 2ce9738ba
* ("cgroupfs: use init_cred when populating new cgroupfs mount")
* for more details.
*/
cred = override_creds(&init_cred);
......@@ -1573,16 +1535,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
revert_creds(cred);
/*
* There must be no failure case after here, since rebinding
* takes care of subsystems' refcounts, which are explicitly
* dropped in the failure exit path.
* There must be no failure case after here, since rebinding takes
* care of subsystems' refcounts, which are explicitly dropped in
* the failure exit path.
*/
list_add(&root->root_list, &cgroup_roots);
cgroup_root_count++;
/* Link the top cgroup in this hierarchy into all
* the css_set objects */
/*
* Link the top cgroup in this hierarchy into all the css_set
* objects.
*/
write_lock(&css_set_lock);
hash_for_each(css_set_table, i, cset, hlist)
link_css_set(&tmp_links, cset, root_cgrp);
......@@ -1590,6 +1553,67 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
BUG_ON(!list_empty(&root_cgrp->children));
BUG_ON(root->number_of_cgroups != 1);
ret = 0;
goto out_unlock;
rm_base_files:
cgroup_addrm_files(&root->top_cgroup, cgroup_base_files, false);
revert_creds(cred);
cgroup_exit_root_id(root);
out_unlock:
mutex_unlock(&inode->i_mutex);
free_cgrp_cset_links(&tmp_links);
return ret;
}
static struct dentry *cgroup_mount(struct file_system_type *fs_type,
int flags, const char *unused_dev_name,
void *data)
{
struct super_block *sb = NULL;
struct cgroupfs_root *root = NULL;
struct cgroup_sb_opts opts;
struct cgroupfs_root *new_root;
int ret;
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
/* First find the desired set of subsystems */
ret = parse_cgroupfs_options(data, &opts);
if (ret)
goto out_unlock;
/*
* Allocate a new cgroup root. We may not need it if we're
* reusing an existing hierarchy.
*/
new_root = cgroup_root_from_opts(&opts);
if (IS_ERR(new_root)) {
ret = PTR_ERR(new_root);
goto out_unlock;
}
opts.new_root = new_root;
/* Locate an existing or new sb for this hierarchy */
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgroup_tree_mutex);
sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts);
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
if (IS_ERR(sb)) {
ret = PTR_ERR(sb);
cgroup_free_root(opts.new_root);
goto out_unlock;
}
root = sb->s_fs_info;
BUG_ON(!root);
if (root == opts.new_root) {
ret = cgroup_setup_root(root);
if (ret)
goto out_unlock;
} else {
/*
* We re-used an existing hierarchy - the new root (if
......@@ -1609,22 +1633,13 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
}
ret = 0;
goto out_unlock;
rm_base_files:
cgroup_addrm_files(&root->top_cgroup, cgroup_base_files, false);
revert_creds(cred);
cgroup_exit_root_id(root);
out_unlock:
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgroup_tree_mutex);
if (inode)
mutex_unlock(&inode->i_mutex);
if (ret && !IS_ERR_OR_NULL(sb))
deactivate_locked_super(sb);
free_cgrp_cset_links(&tmp_links);
kfree(opts.release_agent);
kfree(opts.name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment