cgroup: remove cftype_set

cftype_set was added primarily to allow registering the same cftype
array more than once for different subsystems.  Nobody uses or needs
such thing and it's already broken because each cftype has ->ss
pointer which is initialized during registration.

Let's add list_head ->node to cftype and use the first cftype entry in
the array to link them instead of allocating separate cftype_set.
While at it, trigger WARN if cft seems previously initialized during
registration.

This simplifies cftype handling a bit.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
This commit is contained in:
Tejun Heo 2014-02-12 09:29:48 -05:00
parent 80b1358699
commit 0adb070426
2 changed files with 22 additions and 45 deletions

View File

@ -412,12 +412,11 @@ struct cftype {
unsigned int flags; unsigned int flags;
/* /*
* The subsys this file belongs to. Initialized automatically * Fields used for internal bookkeeping. Initialized automatically
* during registration. NULL for cgroup core files. * during registration.
*/ */
struct cgroup_subsys *ss; struct cgroup_subsys *ss; /* NULL for cgroup core files */
struct list_head node; /* anchored at ss->cfts */
/* kernfs_ops to use, initialized automatically during registration */
struct kernfs_ops *kf_ops; struct kernfs_ops *kf_ops;
/* /*
@ -471,16 +470,6 @@ struct cftype {
#endif #endif
}; };
/*
* cftype_sets describe cftypes belonging to a subsystem and are chained at
* cgroup_subsys->cftsets. Each cftset points to an array of cftypes
* terminated by zero length name.
*/
struct cftype_set {
struct list_head node; /* chained at subsys->cftsets */
struct cftype *cfts;
};
/* /*
* See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This
* function can be called as long as @cgrp is accessible. * function can be called as long as @cgrp is accessible.
@ -597,8 +586,11 @@ struct cgroup_subsys {
/* link to parent, protected by cgroup_lock() */ /* link to parent, protected by cgroup_lock() */
struct cgroupfs_root *root; struct cgroupfs_root *root;
/* list of cftype_sets */ /*
struct list_head cftsets; * List of cftypes. Each entry is the first entry of an array
* terminated by zero length name.
*/
struct list_head cfts;
/* base cftypes, automatically registered with subsys itself */ /* base cftypes, automatically registered with subsys itself */
struct cftype *base_cftypes; struct cftype *base_cftypes;

View File

@ -1016,12 +1016,12 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
int i; int i;
for_each_subsys(ss, i) { for_each_subsys(ss, i) {
struct cftype_set *set; struct cftype *cfts;
if (!test_bit(i, &subsys_mask)) if (!test_bit(i, &subsys_mask))
continue; continue;
list_for_each_entry(set, &ss->cftsets, node) list_for_each_entry(cfts, &ss->cfts, node)
cgroup_addrm_files(cgrp, set->cfts, false); cgroup_addrm_files(cgrp, cfts, false);
} }
} }
@ -2392,6 +2392,8 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
for (cft = cfts; cft->name[0] != '\0'; cft++) { for (cft = cfts; cft->name[0] != '\0'; cft++) {
struct kernfs_ops *kf_ops; struct kernfs_ops *kf_ops;
WARN_ON(cft->ss || cft->kf_ops);
if (cft->seq_start) if (cft->seq_start)
kf_ops = &cgroup_kf_ops; kf_ops = &cgroup_kf_ops;
else else
@ -2430,26 +2432,15 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
*/ */
int cgroup_rm_cftypes(struct cftype *cfts) int cgroup_rm_cftypes(struct cftype *cfts)
{ {
struct cftype *found = NULL;
struct cftype_set *set;
if (!cfts || !cfts[0].ss) if (!cfts || !cfts[0].ss)
return -ENOENT; return -ENOENT;
cgroup_cfts_prepare(); cgroup_cfts_prepare();
list_del(&cfts->node);
cgroup_cfts_commit(cfts, false);
list_for_each_entry(set, &cfts[0].ss->cftsets, node) {
if (set->cfts == cfts) {
list_del(&set->node);
kfree(set);
found = cfts;
break;
}
}
cgroup_cfts_commit(found, false);
cgroup_exit_cftypes(cfts); cgroup_exit_cftypes(cfts);
return found ? 0 : -ENOENT; return 0;
} }
/** /**
@ -2468,20 +2459,14 @@ int cgroup_rm_cftypes(struct cftype *cfts)
*/ */
int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{ {
struct cftype_set *set;
int ret; int ret;
set = kzalloc(sizeof(*set), GFP_KERNEL);
if (!set)
return -ENOMEM;
ret = cgroup_init_cftypes(ss, cfts); ret = cgroup_init_cftypes(ss, cfts);
if (ret) if (ret)
return ret; return ret;
cgroup_cfts_prepare(); cgroup_cfts_prepare();
set->cfts = cfts; list_add_tail(&cfts->node, &ss->cfts);
list_add_tail(&set->node, &ss->cftsets);
ret = cgroup_cfts_commit(cfts, true); ret = cgroup_cfts_commit(cfts, true);
if (ret) if (ret)
cgroup_rm_cftypes(cfts); cgroup_rm_cftypes(cfts);
@ -3574,13 +3559,13 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
/* process cftsets of each subsystem */ /* process cftsets of each subsystem */
for_each_subsys(ss, i) { for_each_subsys(ss, i) {
struct cftype_set *set; struct cftype *cfts;
if (!test_bit(i, &subsys_mask)) if (!test_bit(i, &subsys_mask))
continue; continue;
list_for_each_entry(set, &ss->cftsets, node) { list_for_each_entry(cfts, &ss->cfts, node) {
ret = cgroup_addrm_files(cgrp, set->cfts, true); ret = cgroup_addrm_files(cgrp, cfts, true);
if (ret < 0) if (ret < 0)
goto err; goto err;
} }
@ -4169,7 +4154,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
mutex_lock(&cgroup_tree_mutex); mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
INIT_LIST_HEAD(&ss->cftsets); INIT_LIST_HEAD(&ss->cfts);
/* Create the top cgroup state for this subsystem */ /* Create the top cgroup state for this subsystem */
ss->root = &cgroup_dummy_root; ss->root = &cgroup_dummy_root;