aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-03-19 10:23:54 -0400
committerTejun Heo <tj@kernel.org>2014-03-19 10:23:54 -0400
commit944196278d3dea0cece1636de417b56897d9a108 (patch)
tree5751584bf0c343aec51b662641ec71acb79a762e
parent5df3603229e520442502ff7fc5715c77bbf61912 (diff)
cgroup: move ->subsys_mask from cgroupfs_root to cgroup
cgroupfs_root->subsys_mask represents the controllers attached to the hierarchy. This patch moves the field to cgroup. Subsystem initialization and rebinding updates the top cgroup's subsys_mask. For !root cgroups, the subsys_mask bits are set from create_css() and cleared from kill_css(), which effectively means that all cgroups will have the same subsys_mask as the top cgroup. While this doesn't make any difference now, this will help implementation of the default unified hierarchy where !root cgroups may have subsets of the top_cgroup's subsys_mask. While at it, __kill_css() is split out of kill_css(). The former doesn't care about the subsys_mask while the latter becomes noop if the controller is already killed and clears the matching bit if not before proceeding to killing the css. This will be used later by the default unified hierarchy implementation. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--include/linux/cgroup.h6
-rw-r--r--kernel/cgroup.c61
2 files changed, 42 insertions, 25 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 9f4f253f0e47..3752a0182c94 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -173,6 +173,9 @@ struct cgroup {
173 */ 173 */
174 u64 serial_nr; 174 u64 serial_nr;
175 175
176 /* The bitmask of subsystems attached to this cgroup */
177 unsigned long subsys_mask;
178
176 /* Private pointers for each registered subsystem */ 179 /* Private pointers for each registered subsystem */
177 struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT]; 180 struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
178 181
@@ -276,9 +279,6 @@ enum {
276struct cgroupfs_root { 279struct cgroupfs_root {
277 struct kernfs_root *kf_root; 280 struct kernfs_root *kf_root;
278 281
279 /* The bitmask of subsystems attached to this hierarchy */
280 unsigned long subsys_mask;
281
282 /* Unique id for this hierarchy. */ 282 /* Unique id for this hierarchy. */
283 int hierarchy_id; 283 int hierarchy_id;
284 284
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index b632981bd9c7..807f88dbda51 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -526,7 +526,7 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset,
526 * won't change, so no need for locking. 526 * won't change, so no need for locking.
527 */ 527 */
528 for_each_subsys(ss, i) { 528 for_each_subsys(ss, i) {
529 if (root->subsys_mask & (1UL << i)) { 529 if (root->top_cgroup.subsys_mask & (1UL << i)) {
530 /* Subsystem is in this hierarchy. So we want 530 /* Subsystem is in this hierarchy. So we want
531 * the subsystem state from the new 531 * the subsystem state from the new
532 * cgroup */ 532 * cgroup */
@@ -739,7 +739,7 @@ static void cgroup_destroy_root(struct cgroupfs_root *root)
739 BUG_ON(!list_empty(&cgrp->children)); 739 BUG_ON(!list_empty(&cgrp->children));
740 740
741 /* Rebind all subsystems back to the default hierarchy */ 741 /* Rebind all subsystems back to the default hierarchy */
742 rebind_subsystems(&cgroup_dummy_root, root->subsys_mask); 742 rebind_subsystems(&cgroup_dummy_root, cgrp->subsys_mask);
743 743
744 /* 744 /*
745 * Release all the links from cset_links to this hierarchy's 745 * Release all the links from cset_links to this hierarchy's
@@ -1038,8 +1038,8 @@ static int rebind_subsystems(struct cgroupfs_root *dst_root,
1038 ss->root = dst_root; 1038 ss->root = dst_root;
1039 css->cgroup = dst_top; 1039 css->cgroup = dst_top;
1040 1040
1041 src_root->subsys_mask &= ~(1 << ssid); 1041 src_top->subsys_mask &= ~(1 << ssid);
1042 dst_root->subsys_mask |= 1 << ssid; 1042 dst_top->subsys_mask |= 1 << ssid;
1043 1043
1044 if (ss->bind) 1044 if (ss->bind)
1045 ss->bind(css); 1045 ss->bind(css);
@@ -1058,7 +1058,7 @@ static int cgroup_show_options(struct seq_file *seq,
1058 int ssid; 1058 int ssid;
1059 1059
1060 for_each_subsys(ss, ssid) 1060 for_each_subsys(ss, ssid)
1061 if (root->subsys_mask & (1 << ssid)) 1061 if (root->top_cgroup.subsys_mask & (1 << ssid))
1062 seq_printf(seq, ",%s", ss->name); 1062 seq_printf(seq, ",%s", ss->name);
1063 if (root->flags & CGRP_ROOT_SANE_BEHAVIOR) 1063 if (root->flags & CGRP_ROOT_SANE_BEHAVIOR)
1064 seq_puts(seq, ",sane_behavior"); 1064 seq_puts(seq, ",sane_behavior");
@@ -1262,12 +1262,12 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
1262 if (ret) 1262 if (ret)
1263 goto out_unlock; 1263 goto out_unlock;
1264 1264
1265 if (opts.subsys_mask != root->subsys_mask || opts.release_agent) 1265 if (opts.subsys_mask != root->top_cgroup.subsys_mask || opts.release_agent)
1266 pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n", 1266 pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n",
1267 task_tgid_nr(current), current->comm); 1267 task_tgid_nr(current), current->comm);
1268 1268
1269 added_mask = opts.subsys_mask & ~root->subsys_mask; 1269 added_mask = opts.subsys_mask & ~root->top_cgroup.subsys_mask;
1270 removed_mask = root->subsys_mask & ~opts.subsys_mask; 1270 removed_mask = root->top_cgroup.subsys_mask & ~opts.subsys_mask;
1271 1271
1272 /* Don't allow flags or name to change at remount */ 1272 /* Don't allow flags or name to change at remount */
1273 if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) || 1273 if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) ||
@@ -1515,7 +1515,7 @@ retry:
1515 * subsystems) then they must match. 1515 * subsystems) then they must match.
1516 */ 1516 */
1517 if ((opts.subsys_mask || opts.none) && 1517 if ((opts.subsys_mask || opts.none) &&
1518 (opts.subsys_mask != root->subsys_mask)) { 1518 (opts.subsys_mask != root->top_cgroup.subsys_mask)) {
1519 if (!name_match) 1519 if (!name_match)
1520 continue; 1520 continue;
1521 ret = -EBUSY; 1521 ret = -EBUSY;
@@ -3594,6 +3594,8 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
3594 cgroup_get(cgrp); 3594 cgroup_get(cgrp);
3595 css_get(css->parent); 3595 css_get(css->parent);
3596 3596
3597 cgrp->subsys_mask |= 1 << ss->id;
3598
3597 if (ss->broken_hierarchy && !ss->warned_broken_hierarchy && 3599 if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
3598 parent->parent) { 3600 parent->parent) {
3599 pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n", 3601 pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -3700,7 +3702,7 @@ static long cgroup_create(struct cgroup *parent, const char *name,
3700 3702
3701 /* let's create and online css's */ 3703 /* let's create and online css's */
3702 for_each_subsys(ss, ssid) { 3704 for_each_subsys(ss, ssid) {
3703 if (root->subsys_mask & (1 << ssid)) { 3705 if (root->top_cgroup.subsys_mask & (1 << ssid)) {
3704 err = create_css(cgrp, ss); 3706 err = create_css(cgrp, ss);
3705 if (err) 3707 if (err)
3706 goto err_destroy; 3708 goto err_destroy;
@@ -3788,17 +3790,10 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
3788 queue_work(cgroup_destroy_wq, &css->destroy_work); 3790 queue_work(cgroup_destroy_wq, &css->destroy_work);
3789} 3791}
3790 3792
3791/** 3793static void __kill_css(struct cgroup_subsys_state *css)
3792 * kill_css - destroy a css
3793 * @css: css to destroy
3794 *
3795 * This function initiates destruction of @css by removing cgroup interface
3796 * files and putting its base reference. ->css_offline() will be invoked
3797 * asynchronously once css_tryget() is guaranteed to fail and when the
3798 * reference count reaches zero, @css will be released.
3799 */
3800static void kill_css(struct cgroup_subsys_state *css)
3801{ 3794{
3795 lockdep_assert_held(&cgroup_tree_mutex);
3796
3802 /* 3797 /*
3803 * This must happen before css is disassociated with its cgroup. 3798 * This must happen before css is disassociated with its cgroup.
3804 * See seq_css() for details. 3799 * See seq_css() for details.
@@ -3825,6 +3820,28 @@ static void kill_css(struct cgroup_subsys_state *css)
3825} 3820}
3826 3821
3827/** 3822/**
3823 * kill_css - destroy a css
3824 * @css: css to destroy
3825 *
3826 * This function initiates destruction of @css by removing cgroup interface
3827 * files and putting its base reference. ->css_offline() will be invoked
3828 * asynchronously once css_tryget() is guaranteed to fail and when the
3829 * reference count reaches zero, @css will be released.
3830 */
3831static void kill_css(struct cgroup_subsys_state *css)
3832{
3833 struct cgroup *cgrp = css->cgroup;
3834
3835 lockdep_assert_held(&cgroup_tree_mutex);
3836
3837 /* if already killed, noop */
3838 if (cgrp->subsys_mask & (1 << css->ss->id)) {
3839 cgrp->subsys_mask &= ~(1 << css->ss->id);
3840 __kill_css(css);
3841 }
3842}
3843
3844/**
3828 * cgroup_destroy_locked - the first stage of cgroup destruction 3845 * cgroup_destroy_locked - the first stage of cgroup destruction
3829 * @cgrp: cgroup to be destroyed 3846 * @cgrp: cgroup to be destroyed
3830 * 3847 *
@@ -4036,7 +4053,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4036 4053
4037 BUG_ON(online_css(css)); 4054 BUG_ON(online_css(css));
4038 4055
4039 cgroup_dummy_root.subsys_mask |= 1 << ss->id; 4056 cgroup_dummy_root.top_cgroup.subsys_mask |= 1 << ss->id;
4040 4057
4041 mutex_unlock(&cgroup_mutex); 4058 mutex_unlock(&cgroup_mutex);
4042 mutex_unlock(&cgroup_tree_mutex); 4059 mutex_unlock(&cgroup_tree_mutex);
@@ -4192,7 +4209,7 @@ int proc_cgroup_show(struct seq_file *m, void *v)
4192 4209
4193 seq_printf(m, "%d:", root->hierarchy_id); 4210 seq_printf(m, "%d:", root->hierarchy_id);
4194 for_each_subsys(ss, ssid) 4211 for_each_subsys(ss, ssid)
4195 if (root->subsys_mask & (1 << ssid)) 4212 if (root->top_cgroup.subsys_mask & (1 << ssid))
4196 seq_printf(m, "%s%s", count++ ? "," : "", ss->name); 4213 seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
4197 if (strlen(root->name)) 4214 if (strlen(root->name))
4198 seq_printf(m, "%sname=%s", count ? "," : "", 4215 seq_printf(m, "%sname=%s", count ? "," : "",