diff options
-rw-r--r-- | include/linux/cgroup.h | 11 | ||||
-rw-r--r-- | kernel/cgroup.c | 11 |
2 files changed, 17 insertions, 5 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 76dadd77a120..1737db0c63fe 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -77,6 +77,7 @@ struct cgroup_subsys_state { | |||
77 | 77 | ||
78 | /* bits in struct cgroup_subsys_state flags field */ | 78 | /* bits in struct cgroup_subsys_state flags field */ |
79 | enum { | 79 | enum { |
80 | CSS_NO_REF = (1 << 0), /* no reference counting for this css */ | ||
80 | CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */ | 81 | CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */ |
81 | }; | 82 | }; |
82 | 83 | ||
@@ -88,7 +89,8 @@ enum { | |||
88 | */ | 89 | */ |
89 | static inline void css_get(struct cgroup_subsys_state *css) | 90 | static inline void css_get(struct cgroup_subsys_state *css) |
90 | { | 91 | { |
91 | percpu_ref_get(&css->refcnt); | 92 | if (!(css->flags & CSS_NO_REF)) |
93 | percpu_ref_get(&css->refcnt); | ||
92 | } | 94 | } |
93 | 95 | ||
94 | /** | 96 | /** |
@@ -103,7 +105,9 @@ static inline void css_get(struct cgroup_subsys_state *css) | |||
103 | */ | 105 | */ |
104 | static inline bool css_tryget_online(struct cgroup_subsys_state *css) | 106 | static inline bool css_tryget_online(struct cgroup_subsys_state *css) |
105 | { | 107 | { |
106 | return percpu_ref_tryget_live(&css->refcnt); | 108 | if (!(css->flags & CSS_NO_REF)) |
109 | return percpu_ref_tryget_live(&css->refcnt); | ||
110 | return true; | ||
107 | } | 111 | } |
108 | 112 | ||
109 | /** | 113 | /** |
@@ -114,7 +118,8 @@ static inline bool css_tryget_online(struct cgroup_subsys_state *css) | |||
114 | */ | 118 | */ |
115 | static inline void css_put(struct cgroup_subsys_state *css) | 119 | static inline void css_put(struct cgroup_subsys_state *css) |
116 | { | 120 | { |
117 | percpu_ref_put(&css->refcnt); | 121 | if (!(css->flags & CSS_NO_REF)) |
122 | percpu_ref_put(&css->refcnt); | ||
118 | } | 123 | } |
119 | 124 | ||
120 | /* bits in struct cgroup flags field */ | 125 | /* bits in struct cgroup flags field */ |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c01e8e8dfad0..0343d7ee6d62 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4593,11 +4593,17 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) | |||
4593 | /* We don't handle early failures gracefully */ | 4593 | /* We don't handle early failures gracefully */ |
4594 | BUG_ON(IS_ERR(css)); | 4594 | BUG_ON(IS_ERR(css)); |
4595 | init_and_link_css(css, ss, &cgrp_dfl_root.cgrp); | 4595 | init_and_link_css(css, ss, &cgrp_dfl_root.cgrp); |
4596 | |||
4597 | /* | ||
4598 | * Root csses are never destroyed and we can't initialize | ||
4599 | * percpu_ref during early init. Disable refcnting. | ||
4600 | */ | ||
4601 | css->flags |= CSS_NO_REF; | ||
4602 | |||
4596 | if (early) { | 4603 | if (early) { |
4597 | /* allocation can't be done safely during early init */ | 4604 | /* allocation can't be done safely during early init */ |
4598 | css->id = 1; | 4605 | css->id = 1; |
4599 | } else { | 4606 | } else { |
4600 | BUG_ON(percpu_ref_init(&css->refcnt, css_release)); | ||
4601 | css->id = cgroup_idr_alloc(&ss->css_idr, css, 1, 2, GFP_KERNEL); | 4607 | css->id = cgroup_idr_alloc(&ss->css_idr, css, 1, 2, GFP_KERNEL); |
4602 | BUG_ON(css->id < 0); | 4608 | BUG_ON(css->id < 0); |
4603 | } | 4609 | } |
@@ -4636,6 +4642,8 @@ int __init cgroup_init_early(void) | |||
4636 | int i; | 4642 | int i; |
4637 | 4643 | ||
4638 | init_cgroup_root(&cgrp_dfl_root, &opts); | 4644 | init_cgroup_root(&cgrp_dfl_root, &opts); |
4645 | cgrp_dfl_root.cgrp.self.flags |= CSS_NO_REF; | ||
4646 | |||
4639 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); | 4647 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); |
4640 | 4648 | ||
4641 | for_each_subsys(ss, i) { | 4649 | for_each_subsys(ss, i) { |
@@ -4684,7 +4692,6 @@ int __init cgroup_init(void) | |||
4684 | struct cgroup_subsys_state *css = | 4692 | struct cgroup_subsys_state *css = |
4685 | init_css_set.subsys[ss->id]; | 4693 | init_css_set.subsys[ss->id]; |
4686 | 4694 | ||
4687 | BUG_ON(percpu_ref_init(&css->refcnt, css_release)); | ||
4688 | css->id = cgroup_idr_alloc(&ss->css_idr, css, 1, 2, | 4695 | css->id = cgroup_idr_alloc(&ss->css_idr, css, 1, 2, |
4689 | GFP_KERNEL); | 4696 | GFP_KERNEL); |
4690 | BUG_ON(css->id < 0); | 4697 | BUG_ON(css->id < 0); |