Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d427dfeb authored by Tejun Heo's avatar Tejun Heo
Browse files

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
Loading
Loading
Loading
Loading
+113 −98
Original line number Diff line number Diff line
@@ -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);