aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-04-01 15:09:55 -0400
committerTejun Heo <tj@kernel.org>2012-04-01 15:09:55 -0400
commit8e3f6541d45e1a002801e56a19530a90f775deba (patch)
tree5342d7afce759252f5204c7e33283879cca0490d /kernel/cgroup.c
parentb0ca5a84fc3ad8f75bb2b7ac3dc6a77151cd3906 (diff)
cgroup: implement cgroup_add_cftypes() and friends
Currently, cgroup directories are populated by subsys->populate() callback explicitly creating files on each cgroup creation. This level of flexibility isn't needed or desirable. It provides largely unused flexibility which call for abuses while severely limiting what the core layer can do through the lack of structure and conventions. Per each cgroup file type, the only distinction that cgroup users is making is whether a cgroup is root or not, which can easily be expressed with flags. This patch introduces cgroup_add_cftypes(). These deal with cftypes instead of individual files - controllers indicate that certain types of files exist for certain subsystem. Newly added CFTYPE_*_ON_ROOT flags indicate whether a cftype should be excluded or created only on the root cgroup. cgroup_add_cftypes() can be called any time whether the target subsystem is currently attached or not. cgroup core will create files on the existing cgroups as necessary. Also, cgroup_subsys->base_cftypes is added to ease registration of the base files for the subsystem. If non-NULL on subsys init, the cftypes pointed to by ->base_cftypes are automatically registered on subsys init / load. Further patches will convert the existing users and remove the file based interface. Note that this interface allows dynamic addition of files to an active controller. This will be used for sub-controller modularity and unified hierarchy in the longer term. This patch implements the new mechanism but doesn't apply it to any user. v2: replaced DECLARE_CGROUP_CFTYPES[_COND]() with cgroup_subsys->base_cftypes, which works better for cgroup_subsys which is loaded as module. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c132
1 files changed, 131 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index db4319c030d0..df8fb82ef350 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2623,8 +2623,14 @@ int cgroup_add_file(struct cgroup *cgrp,
2623 struct dentry *dentry; 2623 struct dentry *dentry;
2624 int error; 2624 int error;
2625 umode_t mode; 2625 umode_t mode;
2626
2627 char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; 2626 char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
2627
2628 /* does @cft->flags tell us to skip creation on @cgrp? */
2629 if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent)
2630 return 0;
2631 if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent)
2632 return 0;
2633
2628 if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) { 2634 if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
2629 strcpy(name, subsys->name); 2635 strcpy(name, subsys->name);
2630 strcat(name, "."); 2636 strcat(name, ".");
@@ -2660,6 +2666,95 @@ int cgroup_add_files(struct cgroup *cgrp,
2660} 2666}
2661EXPORT_SYMBOL_GPL(cgroup_add_files); 2667EXPORT_SYMBOL_GPL(cgroup_add_files);
2662 2668
2669static DEFINE_MUTEX(cgroup_cft_mutex);
2670
2671static void cgroup_cfts_prepare(void)
2672 __acquires(&cgroup_cft_mutex) __acquires(&cgroup_mutex)
2673{
2674 /*
2675 * Thanks to the entanglement with vfs inode locking, we can't walk
2676 * the existing cgroups under cgroup_mutex and create files.
2677 * Instead, we increment reference on all cgroups and build list of
2678 * them using @cgrp->cft_q_node. Grab cgroup_cft_mutex to ensure
2679 * exclusive access to the field.
2680 */
2681 mutex_lock(&cgroup_cft_mutex);
2682 mutex_lock(&cgroup_mutex);
2683}
2684
2685static void cgroup_cfts_commit(struct cgroup_subsys *ss,
2686 const struct cftype *cfts)
2687 __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex)
2688{
2689 LIST_HEAD(pending);
2690 struct cgroup *cgrp, *n;
2691 int count = 0;
2692
2693 while (cfts[count].name[0] != '\0')
2694 count++;
2695
2696 /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
2697 if (cfts && ss->root != &rootnode) {
2698 list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) {
2699 dget(cgrp->dentry);
2700 list_add_tail(&cgrp->cft_q_node, &pending);
2701 }
2702 }
2703
2704 mutex_unlock(&cgroup_mutex);
2705
2706 /*
2707 * All new cgroups will see @cfts update on @ss->cftsets. Add/rm
2708 * files for all cgroups which were created before.
2709 */
2710 list_for_each_entry_safe(cgrp, n, &pending, cft_q_node) {
2711 struct inode *inode = cgrp->dentry->d_inode;
2712
2713 mutex_lock(&inode->i_mutex);
2714 mutex_lock(&cgroup_mutex);
2715 if (!cgroup_is_removed(cgrp))
2716 cgroup_add_files(cgrp, ss, cfts, count);
2717 mutex_unlock(&cgroup_mutex);
2718 mutex_unlock(&inode->i_mutex);
2719
2720 list_del_init(&cgrp->cft_q_node);
2721 dput(cgrp->dentry);
2722 }
2723
2724 mutex_unlock(&cgroup_cft_mutex);
2725}
2726
2727/**
2728 * cgroup_add_cftypes - add an array of cftypes to a subsystem
2729 * @ss: target cgroup subsystem
2730 * @cfts: zero-length name terminated array of cftypes
2731 *
2732 * Register @cfts to @ss. Files described by @cfts are created for all
2733 * existing cgroups to which @ss is attached and all future cgroups will
2734 * have them too. This function can be called anytime whether @ss is
2735 * attached or not.
2736 *
2737 * Returns 0 on successful registration, -errno on failure. Note that this
2738 * function currently returns 0 as long as @cfts registration is successful
2739 * even if some file creation attempts on existing cgroups fail.
2740 */
2741int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
2742{
2743 struct cftype_set *set;
2744
2745 set = kzalloc(sizeof(*set), GFP_KERNEL);
2746 if (!set)
2747 return -ENOMEM;
2748
2749 cgroup_cfts_prepare();
2750 set->cfts = cfts;
2751 list_add_tail(&set->node, &ss->cftsets);
2752 cgroup_cfts_commit(ss, cfts);
2753
2754 return 0;
2755}
2756EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
2757
2663/** 2758/**
2664 * cgroup_task_count - count the number of tasks in a cgroup. 2759 * cgroup_task_count - count the number of tasks in a cgroup.
2665 * @cgrp: the cgroup in question 2760 * @cgrp: the cgroup in question
@@ -3660,10 +3755,25 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
3660 return err; 3755 return err;
3661 } 3756 }
3662 3757
3758 /* process cftsets of each subsystem */
3663 for_each_subsys(cgrp->root, ss) { 3759 for_each_subsys(cgrp->root, ss) {
3760 struct cftype_set *set;
3761
3664 if (ss->populate && (err = ss->populate(ss, cgrp)) < 0) 3762 if (ss->populate && (err = ss->populate(ss, cgrp)) < 0)
3665 return err; 3763 return err;
3764
3765 list_for_each_entry(set, &ss->cftsets, node) {
3766 const struct cftype *cft;
3767
3768 for (cft = set->cfts; cft->name[0] != '\0'; cft++) {
3769 err = cgroup_add_file(cgrp, ss, cft);
3770 if (err)
3771 pr_warning("cgroup_populate_dir: failed to create %s, err=%d\n",
3772 cft->name, err);
3773 }
3774 }
3666 } 3775 }
3776
3667 /* This cgroup is ready now */ 3777 /* This cgroup is ready now */
3668 for_each_subsys(cgrp->root, ss) { 3778 for_each_subsys(cgrp->root, ss) {
3669 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; 3779 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
@@ -4034,12 +4144,29 @@ again:
4034 return 0; 4144 return 0;
4035} 4145}
4036 4146
4147static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
4148{
4149 INIT_LIST_HEAD(&ss->cftsets);
4150
4151 /*
4152 * base_cftset is embedded in subsys itself, no need to worry about
4153 * deregistration.
4154 */
4155 if (ss->base_cftypes) {
4156 ss->base_cftset.cfts = ss->base_cftypes;
4157 list_add_tail(&ss->base_cftset.node, &ss->cftsets);
4158 }
4159}
4160
4037static void __init cgroup_init_subsys(struct cgroup_subsys *ss) 4161static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4038{ 4162{
4039 struct cgroup_subsys_state *css; 4163 struct cgroup_subsys_state *css;
4040 4164
4041 printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name); 4165 printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
4042 4166
4167 /* init base cftset */
4168 cgroup_init_cftsets(ss);
4169
4043 /* Create the top cgroup state for this subsystem */ 4170 /* Create the top cgroup state for this subsystem */
4044 list_add(&ss->sibling, &rootnode.subsys_list); 4171 list_add(&ss->sibling, &rootnode.subsys_list);
4045 ss->root = &rootnode; 4172 ss->root = &rootnode;
@@ -4109,6 +4236,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4109 return 0; 4236 return 0;
4110 } 4237 }
4111 4238
4239 /* init base cftset */
4240 cgroup_init_cftsets(ss);
4241
4112 /* 4242 /*
4113 * need to register a subsys id before anything else - for example, 4243 * need to register a subsys id before anything else - for example,
4114 * init_cgroup_css needs it. 4244 * init_cgroup_css needs it.