diff options
author | Tejun Heo <tj@kernel.org> | 2017-06-14 16:01:41 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2017-06-14 16:01:41 -0400 |
commit | b6053d40e3387c916d56d319ba6bfdb2c42a67c7 (patch) | |
tree | 5f45453c0f4675950f56ee4ef1fdb16057eb6552 /kernel/cgroup/debug.c | |
parent | 2866c0b4cf25274040f0b4cc045ad1f44b885dd8 (diff) |
cgroup: fix lockdep warning in debug controller
The debug controller grabs cgroup_mutex from interface file show
functions which can deadlock and triggers lockdep warnings. Fix it by
using cgroup_kn_lock_live()/cgroup_kn_unlock() instead.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Diffstat (limited to 'kernel/cgroup/debug.c')
-rw-r--r-- | kernel/cgroup/debug.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/kernel/cgroup/debug.c b/kernel/cgroup/debug.c index 163fdbd7adf6..dac46af22782 100644 --- a/kernel/cgroup/debug.c +++ b/kernel/cgroup/debug.c | |||
@@ -38,12 +38,15 @@ static u64 debug_taskcount_read(struct cgroup_subsys_state *css, | |||
38 | 38 | ||
39 | static int current_css_set_read(struct seq_file *seq, void *v) | 39 | static int current_css_set_read(struct seq_file *seq, void *v) |
40 | { | 40 | { |
41 | struct kernfs_open_file *of = seq->private; | ||
41 | struct css_set *cset; | 42 | struct css_set *cset; |
42 | struct cgroup_subsys *ss; | 43 | struct cgroup_subsys *ss; |
43 | struct cgroup_subsys_state *css; | 44 | struct cgroup_subsys_state *css; |
44 | int i, refcnt; | 45 | int i, refcnt; |
45 | 46 | ||
46 | mutex_lock(&cgroup_mutex); | 47 | if (!cgroup_kn_lock_live(of->kn, false)) |
48 | return -ENODEV; | ||
49 | |||
47 | spin_lock_irq(&css_set_lock); | 50 | spin_lock_irq(&css_set_lock); |
48 | rcu_read_lock(); | 51 | rcu_read_lock(); |
49 | cset = rcu_dereference(current->cgroups); | 52 | cset = rcu_dereference(current->cgroups); |
@@ -65,7 +68,7 @@ static int current_css_set_read(struct seq_file *seq, void *v) | |||
65 | } | 68 | } |
66 | rcu_read_unlock(); | 69 | rcu_read_unlock(); |
67 | spin_unlock_irq(&css_set_lock); | 70 | spin_unlock_irq(&css_set_lock); |
68 | mutex_unlock(&cgroup_mutex); | 71 | cgroup_kn_unlock(of->kn); |
69 | return 0; | 72 | return 0; |
70 | } | 73 | } |
71 | 74 | ||
@@ -174,13 +177,17 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) | |||
174 | 177 | ||
175 | static int cgroup_subsys_states_read(struct seq_file *seq, void *v) | 178 | static int cgroup_subsys_states_read(struct seq_file *seq, void *v) |
176 | { | 179 | { |
177 | struct cgroup *cgrp = seq_css(seq)->cgroup; | 180 | struct kernfs_open_file *of = seq->private; |
181 | struct cgroup *cgrp; | ||
178 | struct cgroup_subsys *ss; | 182 | struct cgroup_subsys *ss; |
179 | struct cgroup_subsys_state *css; | 183 | struct cgroup_subsys_state *css; |
180 | char pbuf[16]; | 184 | char pbuf[16]; |
181 | int i; | 185 | int i; |
182 | 186 | ||
183 | mutex_lock(&cgroup_mutex); | 187 | cgrp = cgroup_kn_lock_live(of->kn, false); |
188 | if (!cgrp) | ||
189 | return -ENODEV; | ||
190 | |||
184 | for_each_subsys(ss, i) { | 191 | for_each_subsys(ss, i) { |
185 | css = rcu_dereference_check(cgrp->subsys[ss->id], true); | 192 | css = rcu_dereference_check(cgrp->subsys[ss->id], true); |
186 | if (!css) | 193 | if (!css) |
@@ -196,7 +203,8 @@ static int cgroup_subsys_states_read(struct seq_file *seq, void *v) | |||
196 | (unsigned long)css, css->id, | 203 | (unsigned long)css, css->id, |
197 | atomic_read(&css->online_cnt), pbuf); | 204 | atomic_read(&css->online_cnt), pbuf); |
198 | } | 205 | } |
199 | mutex_unlock(&cgroup_mutex); | 206 | |
207 | cgroup_kn_unlock(of->kn); | ||
200 | return 0; | 208 | return 0; |
201 | } | 209 | } |
202 | 210 | ||
@@ -221,12 +229,17 @@ static void cgroup_masks_read_one(struct seq_file *seq, const char *name, | |||
221 | 229 | ||
222 | static int cgroup_masks_read(struct seq_file *seq, void *v) | 230 | static int cgroup_masks_read(struct seq_file *seq, void *v) |
223 | { | 231 | { |
224 | struct cgroup *cgrp = seq_css(seq)->cgroup; | 232 | struct kernfs_open_file *of = seq->private; |
233 | struct cgroup *cgrp; | ||
234 | |||
235 | cgrp = cgroup_kn_lock_live(of->kn, false); | ||
236 | if (!cgrp) | ||
237 | return -ENODEV; | ||
225 | 238 | ||
226 | mutex_lock(&cgroup_mutex); | ||
227 | cgroup_masks_read_one(seq, "subtree_control", cgrp->subtree_control); | 239 | cgroup_masks_read_one(seq, "subtree_control", cgrp->subtree_control); |
228 | cgroup_masks_read_one(seq, "subtree_ss_mask", cgrp->subtree_ss_mask); | 240 | cgroup_masks_read_one(seq, "subtree_ss_mask", cgrp->subtree_ss_mask); |
229 | mutex_unlock(&cgroup_mutex); | 241 | |
242 | cgroup_kn_unlock(of->kn); | ||
230 | return 0; | 243 | return 0; |
231 | } | 244 | } |
232 | 245 | ||