Commit 2bb566cb authored by Tejun Heo's avatar Tejun Heo

cgroup: add subsys backlink pointer to cftype

cgroup is transitioning to using css (cgroup_subsys_state) instead of
cgroup as the primary subsystem handle.  The cgroupfs file interface
will be converted to use css's which requires finding out the
subsystem from cftype so that the matching css can be determined from
the cgroup.

This patch adds cftype->ss which points to the subsystem the file
belongs to.  The field is initialized while a cftype is being
registered.  This makes it unnecessary to explicitly specify the
subsystem for other cftype handling functions.  @ss argument dropped
from various cftype handling functions.

This patch shouldn't introduce any behavior differences.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
Acked-by: default avatarVivek Goyal <vgoyal@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>
parent eb95419b
...@@ -1128,7 +1128,7 @@ void blkcg_policy_unregister(struct blkcg_policy *pol) ...@@ -1128,7 +1128,7 @@ void blkcg_policy_unregister(struct blkcg_policy *pol)
/* kill the intf files first */ /* kill the intf files first */
if (pol->cftypes) if (pol->cftypes)
cgroup_rm_cftypes(&blkio_subsys, pol->cftypes); cgroup_rm_cftypes(pol->cftypes);
/* unregister and update blkgs */ /* unregister and update blkgs */
blkcg_policy[pol->plid] = NULL; blkcg_policy[pol->plid] = NULL;
......
...@@ -429,6 +429,12 @@ struct cftype { ...@@ -429,6 +429,12 @@ struct cftype {
/* CFTYPE_* flags */ /* CFTYPE_* flags */
unsigned int flags; unsigned int flags;
/*
* The subsys this file belongs to. Initialized automatically
* during registration. NULL for cgroup core files.
*/
struct cgroup_subsys *ss;
int (*open)(struct inode *inode, struct file *file); int (*open)(struct inode *inode, struct file *file);
ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
struct file *file, struct file *file,
...@@ -542,7 +548,7 @@ static inline const char *cgroup_name(const struct cgroup *cgrp) ...@@ -542,7 +548,7 @@ static inline const char *cgroup_name(const struct cgroup *cgrp)
} }
int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); int cgroup_rm_cftypes(struct cftype *cfts);
bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor); bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
......
...@@ -219,8 +219,8 @@ static struct cftype cgroup_base_files[]; ...@@ -219,8 +219,8 @@ static struct cftype cgroup_base_files[];
static void cgroup_offline_fn(struct work_struct *work); static void cgroup_offline_fn(struct work_struct *work);
static int cgroup_destroy_locked(struct cgroup *cgrp); static int cgroup_destroy_locked(struct cgroup *cgrp);
static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
struct cftype cfts[], bool is_add); bool is_add);
/* convenient tests for these bits */ /* convenient tests for these bits */
static inline bool cgroup_is_dead(const struct cgroup *cgrp) 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) ...@@ -974,7 +974,7 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
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(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, ...@@ -1623,7 +1623,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
*/ */
cred = override_creds(&init_cred); 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) if (ret)
goto rm_base_files; goto rm_base_files;
...@@ -1681,7 +1681,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1681,7 +1681,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
rm_base_files: rm_base_files:
free_cgrp_cset_links(&tmp_links); 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); revert_creds(cred);
unlock_drop: unlock_drop:
cgroup_exit_root_id(root); cgroup_exit_root_id(root);
...@@ -2694,8 +2694,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft) ...@@ -2694,8 +2694,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
return mode; return mode;
} }
static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
struct cftype *cft)
{ {
struct dentry *dir = cgrp->dentry; struct dentry *dir = cgrp->dentry;
struct cgroup *parent = __d_cgrp(dir); struct cgroup *parent = __d_cgrp(dir);
...@@ -2705,8 +2704,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, ...@@ -2705,8 +2704,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
umode_t mode; umode_t mode;
char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) { if (cft->ss && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
strcpy(name, subsys->name); strcpy(name, cft->ss->name);
strcat(name, "."); strcat(name, ".");
} }
strcat(name, cft->name); strcat(name, cft->name);
...@@ -2743,17 +2742,16 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, ...@@ -2743,17 +2742,16 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
/** /**
* cgroup_addrm_files - add or remove files to a cgroup directory * cgroup_addrm_files - add or remove files to a cgroup directory
* @cgrp: the target cgroup * @cgrp: the target cgroup
* @subsys: the subsystem of files to be added
* @cfts: array of cftypes to be added * @cfts: array of cftypes to be added
* @is_add: whether to add or remove * @is_add: whether to add or remove
* *
* Depending on @is_add, add or remove files defined by @cfts on @cgrp. * Depending on @is_add, add or remove files defined by @cfts on @cgrp.
* All @cfts should belong to @subsys. For removals, this function never * For removals, this function never fails. If addition fails, this
* fails. If addition fails, this function doesn't remove files already * function doesn't remove files already added. The caller is responsible
* added. The caller is responsible for cleaning up. * for cleaning up.
*/ */
static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
struct cftype cfts[], bool is_add) bool is_add)
{ {
struct cftype *cft; struct cftype *cft;
int ret; int ret;
...@@ -2771,7 +2769,7 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, ...@@ -2771,7 +2769,7 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
continue; continue;
if (is_add) { if (is_add) {
ret = cgroup_add_file(cgrp, subsys, cft); ret = cgroup_add_file(cgrp, cft);
if (ret) { if (ret) {
pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n", pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n",
cft->name, ret); cft->name, ret);
...@@ -2796,11 +2794,11 @@ static void cgroup_cfts_prepare(void) ...@@ -2796,11 +2794,11 @@ static void cgroup_cfts_prepare(void)
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
} }
static int cgroup_cfts_commit(struct cgroup_subsys *ss, static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
struct cftype *cfts, bool is_add)
__releases(&cgroup_mutex) __releases(&cgroup_mutex)
{ {
LIST_HEAD(pending); LIST_HEAD(pending);
struct cgroup_subsys *ss = cfts[0].ss;
struct cgroup *cgrp, *root = &ss->root->top_cgroup; struct cgroup *cgrp, *root = &ss->root->top_cgroup;
struct super_block *sb = ss->root->sb; struct super_block *sb = ss->root->sb;
struct dentry *prev = NULL; struct dentry *prev = NULL;
...@@ -2828,7 +2826,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss, ...@@ -2828,7 +2826,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
inode = root->dentry->d_inode; inode = root->dentry->d_inode;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
mutex_lock(&cgroup_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(&cgroup_mutex);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
...@@ -2851,7 +2849,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss, ...@@ -2851,7 +2849,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) 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(&cgroup_mutex);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
...@@ -2883,51 +2881,56 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss, ...@@ -2883,51 +2881,56 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
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; struct cftype_set *set;
struct cftype *cft;
int ret; int ret;
set = kzalloc(sizeof(*set), GFP_KERNEL); set = kzalloc(sizeof(*set), GFP_KERNEL);
if (!set) if (!set)
return -ENOMEM; return -ENOMEM;
for (cft = cfts; cft->name[0] != '\0'; cft++)
cft->ss = ss;
cgroup_cfts_prepare(); cgroup_cfts_prepare();
set->cfts = cfts; set->cfts = cfts;
list_add_tail(&set->node, &ss->cftsets); list_add_tail(&set->node, &ss->cftsets);
ret = cgroup_cfts_commit(ss, cfts, true); ret = cgroup_cfts_commit(cfts, true);
if (ret) if (ret)
cgroup_rm_cftypes(ss, cfts); cgroup_rm_cftypes(cfts);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cgroup_add_cftypes); EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
/** /**
* cgroup_rm_cftypes - remove an array of cftypes from a subsystem * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
* @ss: target cgroup subsystem
* @cfts: zero-length name terminated array of cftypes * @cfts: zero-length name terminated array of cftypes
* *
* Unregister @cfts from @ss. Files described by @cfts are removed from * Unregister @cfts. Files described by @cfts are removed from all
* all existing cgroups to which @ss is attached and all future cgroups * existing cgroups and all future cgroups won't have them either. This
* won't have them either. This function can be called anytime whether @ss * function can be called anytime whether @cfts' subsys is attached or not.
* is attached or not.
* *
* Returns 0 on successful unregistration, -ENOENT if @cfts is 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; struct cftype_set *set;
if (!cfts || !cfts[0].ss)
return -ENOENT;
cgroup_cfts_prepare(); 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) { if (set->cfts == cfts) {
list_del(&set->node); list_del(&set->node);
kfree(set); kfree(set);
cgroup_cfts_commit(ss, cfts, false); cgroup_cfts_commit(cfts, false);
return 0; return 0;
} }
} }
cgroup_cfts_commit(ss, NULL, false); cgroup_cfts_commit(NULL, false);
return -ENOENT; return -ENOENT;
} }
...@@ -4148,7 +4151,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) ...@@ -4148,7 +4151,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
continue; continue;
list_for_each_entry(set, &ss->cftsets, node) { 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) if (ret < 0)
goto err; goto err;
} }
...@@ -4377,7 +4380,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, ...@@ -4377,7 +4380,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
idr_replace(&root->cgroup_idr, cgrp, cgrp->id); 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) if (err)
goto err_destroy; goto err_destroy;
...@@ -4538,7 +4541,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) ...@@ -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. * but we aren't quite done with @cgrp yet, so hold onto it.
*/ */
cgroup_clear_dir(cgrp, cgrp->root->subsys_mask); 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); dget(d);
cgroup_d_remove_dir(d); cgroup_d_remove_dir(d);
...@@ -4632,6 +4635,11 @@ static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss) ...@@ -4632,6 +4635,11 @@ static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
* deregistration. * deregistration.
*/ */
if (ss->base_cftypes) { 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; ss->base_cftset.cfts = ss->base_cftypes;
list_add_tail(&ss->base_cftset.node, &ss->cftsets); list_add_tail(&ss->base_cftset.node, &ss->cftsets);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment