aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-04-01 15:09:56 -0400
committerTejun Heo <tj@kernel.org>2012-04-01 15:09:56 -0400
commit79578621b4847afdef48d19a28d00e3b188c37e1 (patch)
treed66c0ba245841eefa75a2f79e5cd8e2be09385eb /kernel/cgroup.c
parent05ef1d7c4a5b6d09cadd2b8e9b3c395363d1a89c (diff)
cgroup: implement cgroup_rm_cftypes()
Implement cgroup_rm_cftypes() which removes an array of cftypes from a subsystem. It can be called whether the target subsys is attached or not. cgroup core will remove the specified file from all existing cgroups. This will be used to improve sub-subsys modularity and will be helpful for unified hierarchy. 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.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 7d5d1c927d9d..21bba7722350 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2690,17 +2690,20 @@ out:
2690 return error; 2690 return error;
2691} 2691}
2692 2692
2693static int cgroup_add_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, 2693static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
2694 const struct cftype cfts[]) 2694 const struct cftype cfts[], bool is_add)
2695{ 2695{
2696 const struct cftype *cft; 2696 const struct cftype *cft;
2697 int err, ret = 0; 2697 int err, ret = 0;
2698 2698
2699 for (cft = cfts; cft->name[0] != '\0'; cft++) { 2699 for (cft = cfts; cft->name[0] != '\0'; cft++) {
2700 err = cgroup_add_file(cgrp, subsys, cft); 2700 if (is_add)
2701 err = cgroup_add_file(cgrp, subsys, cft);
2702 else
2703 err = cgroup_rm_file(cgrp, cft);
2701 if (err) { 2704 if (err) {
2702 pr_warning("cgroup_add_files: failed to create %s, err=%d\n", 2705 pr_warning("cgroup_addrm_files: failed to %s %s, err=%d\n",
2703 cft->name, err); 2706 is_add ? "add" : "remove", cft->name, err);
2704 ret = err; 2707 ret = err;
2705 } 2708 }
2706 } 2709 }
@@ -2724,7 +2727,7 @@ static void cgroup_cfts_prepare(void)
2724} 2727}
2725 2728
2726static void cgroup_cfts_commit(struct cgroup_subsys *ss, 2729static void cgroup_cfts_commit(struct cgroup_subsys *ss,
2727 const struct cftype *cfts) 2730 const struct cftype *cfts, bool is_add)
2728 __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex) 2731 __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex)
2729{ 2732{
2730 LIST_HEAD(pending); 2733 LIST_HEAD(pending);
@@ -2750,7 +2753,7 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
2750 mutex_lock(&inode->i_mutex); 2753 mutex_lock(&inode->i_mutex);
2751 mutex_lock(&cgroup_mutex); 2754 mutex_lock(&cgroup_mutex);
2752 if (!cgroup_is_removed(cgrp)) 2755 if (!cgroup_is_removed(cgrp))
2753 cgroup_add_files(cgrp, ss, cfts); 2756 cgroup_addrm_files(cgrp, ss, cfts, is_add);
2754 mutex_unlock(&cgroup_mutex); 2757 mutex_unlock(&cgroup_mutex);
2755 mutex_unlock(&inode->i_mutex); 2758 mutex_unlock(&inode->i_mutex);
2756 2759
@@ -2786,13 +2789,44 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
2786 cgroup_cfts_prepare(); 2789 cgroup_cfts_prepare();
2787 set->cfts = cfts; 2790 set->cfts = cfts;
2788 list_add_tail(&set->node, &ss->cftsets); 2791 list_add_tail(&set->node, &ss->cftsets);
2789 cgroup_cfts_commit(ss, cfts); 2792 cgroup_cfts_commit(ss, cfts, true);
2790 2793
2791 return 0; 2794 return 0;
2792} 2795}
2793EXPORT_SYMBOL_GPL(cgroup_add_cftypes); 2796EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
2794 2797
2795/** 2798/**
2799 * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
2800 * @ss: target cgroup subsystem
2801 * @cfts: zero-length name terminated array of cftypes
2802 *
2803 * Unregister @cfts from @ss. Files described by @cfts are removed from
2804 * all existing cgroups to which @ss is attached and all future cgroups
2805 * won't have them either. This function can be called anytime whether @ss
2806 * is attached or not.
2807 *
2808 * Returns 0 on successful unregistration, -ENOENT if @cfts is not
2809 * registered with @ss.
2810 */
2811int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
2812{
2813 struct cftype_set *set;
2814
2815 cgroup_cfts_prepare();
2816
2817 list_for_each_entry(set, &ss->cftsets, node) {
2818 if (set->cfts == cfts) {
2819 list_del_init(&set->node);
2820 cgroup_cfts_commit(ss, cfts, false);
2821 return 0;
2822 }
2823 }
2824
2825 cgroup_cfts_commit(ss, NULL, false);
2826 return -ENOENT;
2827}
2828
2829/**
2796 * cgroup_task_count - count the number of tasks in a cgroup. 2830 * cgroup_task_count - count the number of tasks in a cgroup.
2797 * @cgrp: the cgroup in question 2831 * @cgrp: the cgroup in question
2798 * 2832 *
@@ -3784,7 +3818,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
3784 int err; 3818 int err;
3785 struct cgroup_subsys *ss; 3819 struct cgroup_subsys *ss;
3786 3820
3787 err = cgroup_add_files(cgrp, NULL, files); 3821 err = cgroup_addrm_files(cgrp, NULL, files, true);
3788 if (err < 0) 3822 if (err < 0)
3789 return err; 3823 return err;
3790 3824
@@ -3796,7 +3830,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp)
3796 return err; 3830 return err;
3797 3831
3798 list_for_each_entry(set, &ss->cftsets, node) 3832 list_for_each_entry(set, &ss->cftsets, node)
3799 cgroup_add_files(cgrp, ss, set->cfts); 3833 cgroup_addrm_files(cgrp, ss, set->cfts, true);
3800 } 3834 }
3801 3835
3802 /* This cgroup is ready now */ 3836 /* This cgroup is ready now */