Commit 0083d27b authored by Tejun Heo's avatar Tejun Heo
Browse files

cgroup: Improve cftype add/rm error handling



Let's track whether a cftype is currently added or not using a new flag
__CFTYPE_ADDED so that duplicate operations can be failed safely and
consistently allow using empty cftypes.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent a8c52eba
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ enum {
	/* internal flags, do not use outside cgroup core proper */
	__CFTYPE_ONLY_ON_DFL	= (1 << 16),	/* only on default hierarchy */
	__CFTYPE_NOT_ON_DFL	= (1 << 17),	/* not on default hierarchy */
	__CFTYPE_ADDED		= (1 << 18),
};

/*
+20 −7
Original line number Diff line number Diff line
@@ -4198,19 +4198,26 @@ static void cgroup_exit_cftypes(struct cftype *cfts)
		cft->ss = NULL;

		/* revert flags set by cgroup core while adding @cfts */
		cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
		cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL |
				__CFTYPE_ADDED);
	}
}

static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{
	struct cftype *cft;
	int ret = 0;

	for (cft = cfts; cft->name[0] != '\0'; cft++) {
		struct kernfs_ops *kf_ops;

		WARN_ON(cft->ss || cft->kf_ops);

		if (cft->flags & __CFTYPE_ADDED) {
			ret = -EBUSY;
			break;
		}

		if ((cft->flags & CFTYPE_PRESSURE) && !cgroup_psi_enabled())
			continue;

@@ -4226,26 +4233,26 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
		if (cft->max_write_len && cft->max_write_len != PAGE_SIZE) {
			kf_ops = kmemdup(kf_ops, sizeof(*kf_ops), GFP_KERNEL);
			if (!kf_ops) {
				cgroup_exit_cftypes(cfts);
				return -ENOMEM;
				ret = -ENOMEM;
				break;
			}
			kf_ops->atomic_write_len = cft->max_write_len;
		}

		cft->kf_ops = kf_ops;
		cft->ss = ss;
		cft->flags |= __CFTYPE_ADDED;
	}

	return 0;
	if (ret)
		cgroup_exit_cftypes(cfts);
	return ret;
}

static int cgroup_rm_cftypes_locked(struct cftype *cfts)
{
	lockdep_assert_held(&cgroup_mutex);

	if (!cfts || !cfts[0].ss)
		return -ENOENT;

	list_del(&cfts->node);
	cgroup_apply_cftypes(cfts, false);
	cgroup_exit_cftypes(cfts);
@@ -4267,6 +4274,12 @@ int cgroup_rm_cftypes(struct cftype *cfts)
{
	int ret;

	if (!cfts || cfts[0].name[0] == '\0')
		return 0;

	if (!(cfts[0].flags & __CFTYPE_ADDED))
		return -ENOENT;

	mutex_lock(&cgroup_mutex);
	ret = cgroup_rm_cftypes_locked(cfts);
	mutex_unlock(&cgroup_mutex);