diff options
author | Tejun Heo <tj@kernel.org> | 2013-12-06 15:11:55 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-12-06 15:11:55 -0500 |
commit | 87fb54f1b5a447662854f176eeb1ba92d5ffc1d5 (patch) | |
tree | 1f71a8a0173d19d94db417f4773056669394cd78 /kernel/cgroup.c | |
parent | e58e1ca438a51e7e5a28f8c9fb342d6f908d92c6 (diff) |
cgroup: css iterations and css_from_dir() are safe under cgroup_mutex
Currently, all css iterations and css_from_dir() require RCU read lock
whether the caller is holding cgroup_mutex or not, which is
unnecessarily restrictive. They are all safe to use under
cgroup_mutex without holding RCU read lock.
Factor out cgroup_assert_mutex_or_rcu_locked() from css_from_id() and
apply it to all css iteration functions and css_from_dir().
v2: cgroup_assert_mutex_or_rcu_locked() definition doesn't need to be
inside CONFIG_PROVE_RCU ifdef as rcu_lockdep_assert() is always
defined and conditionalized. Move it outside of the ifdef block.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2e5fbf9d63e9..c22eecbbbc1c 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -93,6 +93,11 @@ static DEFINE_MUTEX(cgroup_mutex); | |||
93 | 93 | ||
94 | static DEFINE_MUTEX(cgroup_root_mutex); | 94 | static DEFINE_MUTEX(cgroup_root_mutex); |
95 | 95 | ||
96 | #define cgroup_assert_mutex_or_rcu_locked() \ | ||
97 | rcu_lockdep_assert(rcu_read_lock_held() || \ | ||
98 | lockdep_is_held(&cgroup_mutex), \ | ||
99 | "cgroup_mutex or RCU read lock required"); | ||
100 | |||
96 | /* | 101 | /* |
97 | * cgroup destruction makes heavy use of work items and there can be a lot | 102 | * cgroup destruction makes heavy use of work items and there can be a lot |
98 | * of concurrent destructions. Use a separate workqueue so that cgroup | 103 | * of concurrent destructions. Use a separate workqueue so that cgroup |
@@ -2897,9 +2902,9 @@ static void cgroup_enable_task_cg_lists(void) | |||
2897 | * @parent_css: css whose children to walk | 2902 | * @parent_css: css whose children to walk |
2898 | * | 2903 | * |
2899 | * This function returns the next child of @parent_css and should be called | 2904 | * This function returns the next child of @parent_css and should be called |
2900 | * under RCU read lock. The only requirement is that @parent_css and | 2905 | * under either cgroup_mutex or RCU read lock. The only requirement is |
2901 | * @pos_css are accessible. The next sibling is guaranteed to be returned | 2906 | * that @parent_css and @pos_css are accessible. The next sibling is |
2902 | * regardless of their states. | 2907 | * guaranteed to be returned regardless of their states. |
2903 | */ | 2908 | */ |
2904 | struct cgroup_subsys_state * | 2909 | struct cgroup_subsys_state * |
2905 | css_next_child(struct cgroup_subsys_state *pos_css, | 2910 | css_next_child(struct cgroup_subsys_state *pos_css, |
@@ -2909,7 +2914,7 @@ css_next_child(struct cgroup_subsys_state *pos_css, | |||
2909 | struct cgroup *cgrp = parent_css->cgroup; | 2914 | struct cgroup *cgrp = parent_css->cgroup; |
2910 | struct cgroup *next; | 2915 | struct cgroup *next; |
2911 | 2916 | ||
2912 | WARN_ON_ONCE(!rcu_read_lock_held()); | 2917 | cgroup_assert_mutex_or_rcu_locked(); |
2913 | 2918 | ||
2914 | /* | 2919 | /* |
2915 | * @pos could already have been removed. Once a cgroup is removed, | 2920 | * @pos could already have been removed. Once a cgroup is removed, |
@@ -2956,10 +2961,10 @@ EXPORT_SYMBOL_GPL(css_next_child); | |||
2956 | * to visit for pre-order traversal of @root's descendants. @root is | 2961 | * to visit for pre-order traversal of @root's descendants. @root is |
2957 | * included in the iteration and the first node to be visited. | 2962 | * included in the iteration and the first node to be visited. |
2958 | * | 2963 | * |
2959 | * While this function requires RCU read locking, it doesn't require the | 2964 | * While this function requires cgroup_mutex or RCU read locking, it |
2960 | * whole traversal to be contained in a single RCU critical section. This | 2965 | * doesn't require the whole traversal to be contained in a single critical |
2961 | * function will return the correct next descendant as long as both @pos | 2966 | * section. This function will return the correct next descendant as long |
2962 | * and @root are accessible and @pos is a descendant of @root. | 2967 | * as both @pos and @root are accessible and @pos is a descendant of @root. |
2963 | */ | 2968 | */ |
2964 | struct cgroup_subsys_state * | 2969 | struct cgroup_subsys_state * |
2965 | css_next_descendant_pre(struct cgroup_subsys_state *pos, | 2970 | css_next_descendant_pre(struct cgroup_subsys_state *pos, |
@@ -2967,7 +2972,7 @@ css_next_descendant_pre(struct cgroup_subsys_state *pos, | |||
2967 | { | 2972 | { |
2968 | struct cgroup_subsys_state *next; | 2973 | struct cgroup_subsys_state *next; |
2969 | 2974 | ||
2970 | WARN_ON_ONCE(!rcu_read_lock_held()); | 2975 | cgroup_assert_mutex_or_rcu_locked(); |
2971 | 2976 | ||
2972 | /* if first iteration, visit @root */ | 2977 | /* if first iteration, visit @root */ |
2973 | if (!pos) | 2978 | if (!pos) |
@@ -2998,17 +3003,17 @@ EXPORT_SYMBOL_GPL(css_next_descendant_pre); | |||
2998 | * is returned. This can be used during pre-order traversal to skip | 3003 | * is returned. This can be used during pre-order traversal to skip |
2999 | * subtree of @pos. | 3004 | * subtree of @pos. |
3000 | * | 3005 | * |
3001 | * While this function requires RCU read locking, it doesn't require the | 3006 | * While this function requires cgroup_mutex or RCU read locking, it |
3002 | * whole traversal to be contained in a single RCU critical section. This | 3007 | * doesn't require the whole traversal to be contained in a single critical |
3003 | * function will return the correct rightmost descendant as long as @pos is | 3008 | * section. This function will return the correct rightmost descendant as |
3004 | * accessible. | 3009 | * long as @pos is accessible. |
3005 | */ | 3010 | */ |
3006 | struct cgroup_subsys_state * | 3011 | struct cgroup_subsys_state * |
3007 | css_rightmost_descendant(struct cgroup_subsys_state *pos) | 3012 | css_rightmost_descendant(struct cgroup_subsys_state *pos) |
3008 | { | 3013 | { |
3009 | struct cgroup_subsys_state *last, *tmp; | 3014 | struct cgroup_subsys_state *last, *tmp; |
3010 | 3015 | ||
3011 | WARN_ON_ONCE(!rcu_read_lock_held()); | 3016 | cgroup_assert_mutex_or_rcu_locked(); |
3012 | 3017 | ||
3013 | do { | 3018 | do { |
3014 | last = pos; | 3019 | last = pos; |
@@ -3044,10 +3049,11 @@ css_leftmost_descendant(struct cgroup_subsys_state *pos) | |||
3044 | * to visit for post-order traversal of @root's descendants. @root is | 3049 | * to visit for post-order traversal of @root's descendants. @root is |
3045 | * included in the iteration and the last node to be visited. | 3050 | * included in the iteration and the last node to be visited. |
3046 | * | 3051 | * |
3047 | * While this function requires RCU read locking, it doesn't require the | 3052 | * While this function requires cgroup_mutex or RCU read locking, it |
3048 | * whole traversal to be contained in a single RCU critical section. This | 3053 | * doesn't require the whole traversal to be contained in a single critical |
3049 | * function will return the correct next descendant as long as both @pos | 3054 | * section. This function will return the correct next descendant as long |
3050 | * and @cgroup are accessible and @pos is a descendant of @cgroup. | 3055 | * as both @pos and @cgroup are accessible and @pos is a descendant of |
3056 | * @cgroup. | ||
3051 | */ | 3057 | */ |
3052 | struct cgroup_subsys_state * | 3058 | struct cgroup_subsys_state * |
3053 | css_next_descendant_post(struct cgroup_subsys_state *pos, | 3059 | css_next_descendant_post(struct cgroup_subsys_state *pos, |
@@ -3055,7 +3061,7 @@ css_next_descendant_post(struct cgroup_subsys_state *pos, | |||
3055 | { | 3061 | { |
3056 | struct cgroup_subsys_state *next; | 3062 | struct cgroup_subsys_state *next; |
3057 | 3063 | ||
3058 | WARN_ON_ONCE(!rcu_read_lock_held()); | 3064 | cgroup_assert_mutex_or_rcu_locked(); |
3059 | 3065 | ||
3060 | /* if first iteration, visit leftmost descendant which may be @root */ | 3066 | /* if first iteration, visit leftmost descendant which may be @root */ |
3061 | if (!pos) | 3067 | if (!pos) |
@@ -5217,16 +5223,16 @@ __setup("cgroup_disable=", cgroup_disable); | |||
5217 | * @dentry: directory dentry of interest | 5223 | * @dentry: directory dentry of interest |
5218 | * @ss: subsystem of interest | 5224 | * @ss: subsystem of interest |
5219 | * | 5225 | * |
5220 | * Must be called under RCU read lock. The caller is responsible for | 5226 | * Must be called under cgroup_mutex or RCU read lock. The caller is |
5221 | * pinning the returned css if it needs to be accessed outside the RCU | 5227 | * responsible for pinning the returned css if it needs to be accessed |
5222 | * critical section. | 5228 | * outside the critical section. |
5223 | */ | 5229 | */ |
5224 | struct cgroup_subsys_state *css_from_dir(struct dentry *dentry, | 5230 | struct cgroup_subsys_state *css_from_dir(struct dentry *dentry, |
5225 | struct cgroup_subsys *ss) | 5231 | struct cgroup_subsys *ss) |
5226 | { | 5232 | { |
5227 | struct cgroup *cgrp; | 5233 | struct cgroup *cgrp; |
5228 | 5234 | ||
5229 | WARN_ON_ONCE(!rcu_read_lock_held()); | 5235 | cgroup_assert_mutex_or_rcu_locked(); |
5230 | 5236 | ||
5231 | /* is @dentry a cgroup dir? */ | 5237 | /* is @dentry a cgroup dir? */ |
5232 | if (!dentry->d_inode || | 5238 | if (!dentry->d_inode || |
@@ -5249,9 +5255,7 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss) | |||
5249 | { | 5255 | { |
5250 | struct cgroup *cgrp; | 5256 | struct cgroup *cgrp; |
5251 | 5257 | ||
5252 | rcu_lockdep_assert(rcu_read_lock_held() || | 5258 | cgroup_assert_mutex_or_rcu_locked(); |
5253 | lockdep_is_held(&cgroup_mutex), | ||
5254 | "css_from_id() needs proper protection"); | ||
5255 | 5259 | ||
5256 | cgrp = idr_find(&ss->root->cgroup_idr, id); | 5260 | cgrp = idr_find(&ss->root->cgroup_idr, id); |
5257 | if (cgrp) | 5261 | if (cgrp) |