|
@@ -219,8 +219,8 @@ static struct cftype cgroup_base_files[];
|
|
|
|
|
|
static void cgroup_offline_fn(struct work_struct *work);
|
|
|
static int cgroup_destroy_locked(struct cgroup *cgrp);
|
|
|
-static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
|
|
|
- struct cftype cfts[], bool is_add);
|
|
|
+static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
|
|
|
+ bool is_add);
|
|
|
|
|
|
/* convenient tests for these bits */
|
|
|
static inline bool cgroup_is_dead(const struct cgroup *cgrp)
|
|
@@ -974,7 +974,7 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
|
|
|
if (!test_bit(i, &subsys_mask))
|
|
|
continue;
|
|
|
list_for_each_entry(set, &ss->cftsets, node)
|
|
|
- cgroup_addrm_files(cgrp, NULL, set->cfts, false);
|
|
|
+ cgroup_addrm_files(cgrp, set->cfts, false);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1623,7 +1623,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|
|
*/
|
|
|
cred = override_creds(&init_cred);
|
|
|
|
|
|
- ret = cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true);
|
|
|
+ ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
|
|
|
if (ret)
|
|
|
goto rm_base_files;
|
|
|
|
|
@@ -1681,7 +1681,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|
|
|
|
|
rm_base_files:
|
|
|
free_cgrp_cset_links(&tmp_links);
|
|
|
- cgroup_addrm_files(&root->top_cgroup, NULL, cgroup_base_files, false);
|
|
|
+ cgroup_addrm_files(&root->top_cgroup, cgroup_base_files, false);
|
|
|
revert_creds(cred);
|
|
|
unlock_drop:
|
|
|
cgroup_exit_root_id(root);
|
|
@@ -2694,8 +2694,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
|
|
|
return mode;
|
|
|
}
|
|
|
|
|
|
-static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
|
|
|
- struct cftype *cft)
|
|
|
+static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
|
|
|
{
|
|
|
struct dentry *dir = cgrp->dentry;
|
|
|
struct cgroup *parent = __d_cgrp(dir);
|
|
@@ -2705,8 +2704,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
|
|
|
umode_t mode;
|
|
|
char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
|
|
|
|
|
|
- if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
|
|
|
- strcpy(name, subsys->name);
|
|
|
+ if (cft->ss && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
|
|
|
+ strcpy(name, cft->ss->name);
|
|
|
strcat(name, ".");
|
|
|
}
|
|
|
strcat(name, cft->name);
|
|
@@ -2743,17 +2742,16 @@ out:
|
|
|
/**
|
|
|
* cgroup_addrm_files - add or remove files to a cgroup directory
|
|
|
* @cgrp: the target cgroup
|
|
|
- * @subsys: the subsystem of files to be added
|
|
|
* @cfts: array of cftypes to be added
|
|
|
* @is_add: whether to add or remove
|
|
|
*
|
|
|
* Depending on @is_add, add or remove files defined by @cfts on @cgrp.
|
|
|
- * All @cfts should belong to @subsys. For removals, this function never
|
|
|
- * fails. If addition fails, this function doesn't remove files already
|
|
|
- * added. The caller is responsible for cleaning up.
|
|
|
+ * For removals, this function never fails. If addition fails, this
|
|
|
+ * function doesn't remove files already added. The caller is responsible
|
|
|
+ * for cleaning up.
|
|
|
*/
|
|
|
-static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
|
|
|
- struct cftype cfts[], bool is_add)
|
|
|
+static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
|
|
|
+ bool is_add)
|
|
|
{
|
|
|
struct cftype *cft;
|
|
|
int ret;
|
|
@@ -2771,7 +2769,7 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
|
|
|
continue;
|
|
|
|
|
|
if (is_add) {
|
|
|
- ret = cgroup_add_file(cgrp, subsys, cft);
|
|
|
+ ret = cgroup_add_file(cgrp, cft);
|
|
|
if (ret) {
|
|
|
pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n",
|
|
|
cft->name, ret);
|
|
@@ -2796,11 +2794,11 @@ static void cgroup_cfts_prepare(void)
|
|
|
mutex_lock(&cgroup_mutex);
|
|
|
}
|
|
|
|
|
|
-static int cgroup_cfts_commit(struct cgroup_subsys *ss,
|
|
|
- struct cftype *cfts, bool is_add)
|
|
|
+static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
|
|
|
__releases(&cgroup_mutex)
|
|
|
{
|
|
|
LIST_HEAD(pending);
|
|
|
+ struct cgroup_subsys *ss = cfts[0].ss;
|
|
|
struct cgroup *cgrp, *root = &ss->root->top_cgroup;
|
|
|
struct super_block *sb = ss->root->sb;
|
|
|
struct dentry *prev = NULL;
|
|
@@ -2828,7 +2826,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
|
|
|
inode = root->dentry->d_inode;
|
|
|
mutex_lock(&inode->i_mutex);
|
|
|
mutex_lock(&cgroup_mutex);
|
|
|
- ret = cgroup_addrm_files(root, ss, cfts, is_add);
|
|
|
+ ret = cgroup_addrm_files(root, cfts, is_add);
|
|
|
mutex_unlock(&cgroup_mutex);
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
|
|
|
@@ -2851,7 +2849,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
|
|
|
mutex_lock(&inode->i_mutex);
|
|
|
mutex_lock(&cgroup_mutex);
|
|
|
if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
|
|
|
- ret = cgroup_addrm_files(cgrp, ss, cfts, is_add);
|
|
|
+ ret = cgroup_addrm_files(cgrp, cfts, is_add);
|
|
|
mutex_unlock(&cgroup_mutex);
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
|
|
|
@@ -2883,51 +2881,56 @@ out_deact:
|
|
|
int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
|
|
|
{
|
|
|
struct cftype_set *set;
|
|
|
+ struct cftype *cft;
|
|
|
int ret;
|
|
|
|
|
|
set = kzalloc(sizeof(*set), GFP_KERNEL);
|
|
|
if (!set)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ for (cft = cfts; cft->name[0] != '\0'; cft++)
|
|
|
+ cft->ss = ss;
|
|
|
+
|
|
|
cgroup_cfts_prepare();
|
|
|
set->cfts = cfts;
|
|
|
list_add_tail(&set->node, &ss->cftsets);
|
|
|
- ret = cgroup_cfts_commit(ss, cfts, true);
|
|
|
+ ret = cgroup_cfts_commit(cfts, true);
|
|
|
if (ret)
|
|
|
- cgroup_rm_cftypes(ss, cfts);
|
|
|
+ cgroup_rm_cftypes(cfts);
|
|
|
return ret;
|
|
|
}
|
|
|
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.
|
|
|
+ * Unregister @cfts. Files described by @cfts are removed from all
|
|
|
+ * existing cgroups and all future cgroups won't have them either. This
|
|
|
+ * function can be called anytime whether @cfts' subsys is attached or not.
|
|
|
*
|
|
|
* Returns 0 on successful unregistration, -ENOENT if @cfts is not
|
|
|
- * registered with @ss.
|
|
|
+ * registered.
|
|
|
*/
|
|
|
-int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
|
|
|
+int cgroup_rm_cftypes(struct cftype *cfts)
|
|
|
{
|
|
|
struct cftype_set *set;
|
|
|
|
|
|
+ if (!cfts || !cfts[0].ss)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
cgroup_cfts_prepare();
|
|
|
|
|
|
- list_for_each_entry(set, &ss->cftsets, node) {
|
|
|
+ list_for_each_entry(set, &cfts[0].ss->cftsets, node) {
|
|
|
if (set->cfts == cfts) {
|
|
|
list_del(&set->node);
|
|
|
kfree(set);
|
|
|
- cgroup_cfts_commit(ss, cfts, false);
|
|
|
+ cgroup_cfts_commit(cfts, false);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- cgroup_cfts_commit(ss, NULL, false);
|
|
|
+ cgroup_cfts_commit(NULL, false);
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
|
|
@@ -4148,7 +4151,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
|
|
|
continue;
|
|
|
|
|
|
list_for_each_entry(set, &ss->cftsets, node) {
|
|
|
- ret = cgroup_addrm_files(cgrp, ss, set->cfts, true);
|
|
|
+ ret = cgroup_addrm_files(cgrp, set->cfts, true);
|
|
|
if (ret < 0)
|
|
|
goto err;
|
|
|
}
|
|
@@ -4377,7 +4380,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
|
|
|
|
|
|
idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
|
|
|
|
|
|
- err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true);
|
|
|
+ err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
|
|
|
if (err)
|
|
|
goto err_destroy;
|
|
|
|
|
@@ -4538,7 +4541,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|
|
* but we aren't quite done with @cgrp yet, so hold onto it.
|
|
|
*/
|
|
|
cgroup_clear_dir(cgrp, cgrp->root->subsys_mask);
|
|
|
- cgroup_addrm_files(cgrp, NULL, cgroup_base_files, false);
|
|
|
+ cgroup_addrm_files(cgrp, cgroup_base_files, false);
|
|
|
dget(d);
|
|
|
cgroup_d_remove_dir(d);
|
|
|
|
|
@@ -4632,6 +4635,11 @@ static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
|
|
|
* deregistration.
|
|
|
*/
|
|
|
if (ss->base_cftypes) {
|
|
|
+ struct cftype *cft;
|
|
|
+
|
|
|
+ for (cft = ss->base_cftypes; cft->name[0] != '\0'; cft++)
|
|
|
+ cft->ss = ss;
|
|
|
+
|
|
|
ss->base_cftset.cfts = ss->base_cftypes;
|
|
|
list_add_tail(&ss->base_cftset.node, &ss->cftsets);
|
|
|
}
|