unsigned int flags;
/*
- * The subsys this file belongs to. Initialized automatically
- * during registration. NULL for cgroup core files.
+ * Fields used for internal bookkeeping. Initialized automatically
+ * during registration.
*/
- struct cgroup_subsys *ss;
-
- /* kernfs_ops to use, initialized automatically during registration */
+ struct cgroup_subsys *ss; /* NULL for cgroup core files */
+ struct list_head node; /* anchored at ss->cfts */
struct kernfs_ops *kf_ops;
/*
#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
* function can be called as long as @cgrp is accessible.
/* link to parent, protected by cgroup_lock() */
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 */
struct cftype *base_cftypes;
int i;
for_each_subsys(ss, i) {
- struct cftype_set *set;
+ struct cftype *cfts;
if (!test_bit(i, &subsys_mask))
continue;
- list_for_each_entry(set, &ss->cftsets, node)
- cgroup_addrm_files(cgrp, set->cfts, false);
+ list_for_each_entry(cfts, &ss->cfts, node)
+ cgroup_addrm_files(cgrp, cfts, false);
}
}
for (cft = cfts; cft->name[0] != '\0'; cft++) {
struct kernfs_ops *kf_ops;
+ WARN_ON(cft->ss || cft->kf_ops);
+
if (cft->seq_start)
kf_ops = &cgroup_kf_ops;
else
*/
int cgroup_rm_cftypes(struct cftype *cfts)
{
- struct cftype *found = NULL;
- struct cftype_set *set;
-
if (!cfts || !cfts[0].ss)
return -ENOENT;
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);
- return found ? 0 : -ENOENT;
+ return 0;
}
/**
*/
int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{
- struct cftype_set *set;
int ret;
- set = kzalloc(sizeof(*set), GFP_KERNEL);
- if (!set)
- return -ENOMEM;
-
ret = cgroup_init_cftypes(ss, cfts);
if (ret)
return ret;
cgroup_cfts_prepare();
- set->cfts = cfts;
- list_add_tail(&set->node, &ss->cftsets);
+ list_add_tail(&cfts->node, &ss->cfts);
ret = cgroup_cfts_commit(cfts, true);
if (ret)
cgroup_rm_cftypes(cfts);
/* process cftsets of each subsystem */
for_each_subsys(ss, i) {
- struct cftype_set *set;
+ struct cftype *cfts;
if (!test_bit(i, &subsys_mask))
continue;
- list_for_each_entry(set, &ss->cftsets, node) {
- ret = cgroup_addrm_files(cgrp, set->cfts, true);
+ list_for_each_entry(cfts, &ss->cfts, node) {
+ ret = cgroup_addrm_files(cgrp, cfts, true);
if (ret < 0)
goto err;
}
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
- INIT_LIST_HEAD(&ss->cftsets);
+ INIT_LIST_HEAD(&ss->cfts);
/* Create the top cgroup state for this subsystem */
ss->root = &cgroup_dummy_root;