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

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

cgroup: implement cgroup_rm_cftypes()



Implement cgroup_rm_cftypes() which removes an array of cftypes from a
subsystem.  It can be called whether the target subsys is attached or
not.  cgroup core will remove the specified file from all existing
cgroups.

This will be used to improve sub-subsys modularity and will be helpful
for unified hierarchy.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
parent 05ef1d7c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ struct cgroup_scanner {
};

int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);

int cgroup_is_removed(const struct cgroup *cgrp);

+44 −10
Original line number Diff line number Diff line
@@ -2690,17 +2690,20 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
	return error;
}

static int cgroup_add_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
			    const struct cftype cfts[])
static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
			      const struct cftype cfts[], bool is_add)
{
	const struct cftype *cft;
	int err, ret = 0;

	for (cft = cfts; cft->name[0] != '\0'; cft++) {
		if (is_add)
			err = cgroup_add_file(cgrp, subsys, cft);
		else
			err = cgroup_rm_file(cgrp, cft);
		if (err) {
			pr_warning("cgroup_add_files: failed to create %s, err=%d\n",
				   cft->name, err);
			pr_warning("cgroup_addrm_files: failed to %s %s, err=%d\n",
				   is_add ? "add" : "remove", cft->name, err);
			ret = err;
		}
	}
@@ -2724,7 +2727,7 @@ static void cgroup_cfts_prepare(void)
}

static void cgroup_cfts_commit(struct cgroup_subsys *ss,
			       const struct cftype *cfts)
			       const struct cftype *cfts, bool is_add)
	__releases(&cgroup_mutex) __releases(&cgroup_cft_mutex)
{
	LIST_HEAD(pending);
@@ -2750,7 +2753,7 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
		mutex_lock(&inode->i_mutex);
		mutex_lock(&cgroup_mutex);
		if (!cgroup_is_removed(cgrp))
			cgroup_add_files(cgrp, ss, cfts);
			cgroup_addrm_files(cgrp, ss, cfts, is_add);
		mutex_unlock(&cgroup_mutex);
		mutex_unlock(&inode->i_mutex);

@@ -2786,12 +2789,43 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
	cgroup_cfts_prepare();
	set->cfts = cfts;
	list_add_tail(&set->node, &ss->cftsets);
	cgroup_cfts_commit(ss, cfts);
	cgroup_cfts_commit(ss, cfts, true);

	return 0;
}
EXPORT_SYMBOL_GPL(cgroup_add_cftypes);

/**
 * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
 * @ss: target cgroup subsystem
 * @cfts: zero-length name terminated array of cftypes
 *
 * Unregister @cfts from @ss.  Files described by @cfts are removed from
 * all existing cgroups to which @ss is attached and all future cgroups
 * won't have them either.  This function can be called anytime whether @ss
 * is attached or not.
 *
 * Returns 0 on successful unregistration, -ENOENT if @cfts is not
 * registered with @ss.
 */
int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
{
	struct cftype_set *set;

	cgroup_cfts_prepare();

	list_for_each_entry(set, &ss->cftsets, node) {
		if (set->cfts == cfts) {
			list_del_init(&set->node);
			cgroup_cfts_commit(ss, cfts, false);
			return 0;
		}
	}

	cgroup_cfts_commit(ss, NULL, false);
	return -ENOENT;
}

/**
 * cgroup_task_count - count the number of tasks in a cgroup.
 * @cgrp: the cgroup in question
@@ -3784,7 +3818,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
	int err;
	struct cgroup_subsys *ss;

	err = cgroup_add_files(cgrp, NULL, files);
	err = cgroup_addrm_files(cgrp, NULL, files, true);
	if (err < 0)
		return err;

@@ -3796,7 +3830,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
			return err;

		list_for_each_entry(set, &ss->cftsets, node)
			cgroup_add_files(cgrp, ss, set->cfts);
			cgroup_addrm_files(cgrp, ss, set->cfts, true);
	}

	/* This cgroup is ready now */