diff options
author | Waiman Long <longman@redhat.com> | 2017-07-21 11:14:51 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2017-07-21 11:14:51 -0400 |
commit | 7a0cf0e74ab6cfd8e561f5f12860d4ff8844905a (patch) | |
tree | a4fb0b9648bc07969beffbe350005fecd4ade14f | |
parent | 8cfd8147df67e741d93b8783a3ea8f3c74f93a0e (diff) |
cgroup: update debug controller to print out thread mode information
Update debug controller so that it prints out debug info about thread
mode.
1) The relationship between proc_cset and threaded_csets are displayed.
2) The status of being a thread root or threaded cgroup is displayed.
This patch is extracted from Waiman's larger patch.
v2: - Removed [thread root] / [threaded] from debug.cgroup_css_links
file as the same information is available from cgroup.type.
Suggested by Waiman.
- Threaded marking is moved to the previous patch.
Patch-originally-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r-- | kernel/cgroup/cgroup-internal.h | 2 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 4 | ||||
-rw-r--r-- | kernel/cgroup/debug.c | 52 |
3 files changed, 42 insertions, 16 deletions
diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h index f10eb19ddf04..c167a40278e6 100644 --- a/kernel/cgroup/cgroup-internal.h +++ b/kernel/cgroup/cgroup-internal.h | |||
@@ -153,6 +153,8 @@ static inline void get_css_set(struct css_set *cset) | |||
153 | 153 | ||
154 | bool cgroup_ssid_enabled(int ssid); | 154 | bool cgroup_ssid_enabled(int ssid); |
155 | bool cgroup_on_dfl(const struct cgroup *cgrp); | 155 | bool cgroup_on_dfl(const struct cgroup *cgrp); |
156 | bool cgroup_is_thread_root(struct cgroup *cgrp); | ||
157 | bool cgroup_is_threaded(struct cgroup *cgrp); | ||
156 | 158 | ||
157 | struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root); | 159 | struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root); |
158 | struct cgroup *task_cgroup_from_root(struct task_struct *task, | 160 | struct cgroup *task_cgroup_from_root(struct task_struct *task, |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index c396e701c206..e9a377dc5bdb 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -333,7 +333,7 @@ static bool cgroup_has_tasks(struct cgroup *cgrp) | |||
333 | return cgrp->nr_populated_csets; | 333 | return cgrp->nr_populated_csets; |
334 | } | 334 | } |
335 | 335 | ||
336 | static bool cgroup_is_threaded(struct cgroup *cgrp) | 336 | bool cgroup_is_threaded(struct cgroup *cgrp) |
337 | { | 337 | { |
338 | return cgrp->dom_cgrp != cgrp; | 338 | return cgrp->dom_cgrp != cgrp; |
339 | } | 339 | } |
@@ -372,7 +372,7 @@ static bool cgroup_can_be_thread_root(struct cgroup *cgrp) | |||
372 | } | 372 | } |
373 | 373 | ||
374 | /* is @cgrp root of a threaded subtree? */ | 374 | /* is @cgrp root of a threaded subtree? */ |
375 | static bool cgroup_is_thread_root(struct cgroup *cgrp) | 375 | bool cgroup_is_thread_root(struct cgroup *cgrp) |
376 | { | 376 | { |
377 | /* thread root should be a domain */ | 377 | /* thread root should be a domain */ |
378 | if (cgroup_is_threaded(cgrp)) | 378 | if (cgroup_is_threaded(cgrp)) |
diff --git a/kernel/cgroup/debug.c b/kernel/cgroup/debug.c index 787a242fa69d..f661b4cc5efd 100644 --- a/kernel/cgroup/debug.c +++ b/kernel/cgroup/debug.c | |||
@@ -114,27 +114,49 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) | |||
114 | { | 114 | { |
115 | struct cgroup_subsys_state *css = seq_css(seq); | 115 | struct cgroup_subsys_state *css = seq_css(seq); |
116 | struct cgrp_cset_link *link; | 116 | struct cgrp_cset_link *link; |
117 | int dead_cnt = 0, extra_refs = 0; | 117 | int dead_cnt = 0, extra_refs = 0, threaded_csets = 0; |
118 | 118 | ||
119 | spin_lock_irq(&css_set_lock); | 119 | spin_lock_irq(&css_set_lock); |
120 | |||
120 | list_for_each_entry(link, &css->cgroup->cset_links, cset_link) { | 121 | list_for_each_entry(link, &css->cgroup->cset_links, cset_link) { |
121 | struct css_set *cset = link->cset; | 122 | struct css_set *cset = link->cset; |
122 | struct task_struct *task; | 123 | struct task_struct *task; |
123 | int count = 0; | 124 | int count = 0; |
124 | int refcnt = refcount_read(&cset->refcount); | 125 | int refcnt = refcount_read(&cset->refcount); |
125 | 126 | ||
126 | seq_printf(seq, " %d", refcnt); | 127 | /* |
127 | if (refcnt - cset->nr_tasks > 0) { | 128 | * Print out the proc_cset and threaded_cset relationship |
128 | int extra = refcnt - cset->nr_tasks; | 129 | * and highlight difference between refcount and task_count. |
129 | 130 | */ | |
130 | seq_printf(seq, " +%d", extra); | 131 | seq_printf(seq, "css_set %pK", cset); |
131 | /* | 132 | if (rcu_dereference_protected(cset->dom_cset, 1) != cset) { |
132 | * Take out the one additional reference in | 133 | threaded_csets++; |
133 | * init_css_set. | 134 | seq_printf(seq, "=>%pK", cset->dom_cset); |
134 | */ | 135 | } |
135 | if (cset == &init_css_set) | 136 | if (!list_empty(&cset->threaded_csets)) { |
136 | extra--; | 137 | struct css_set *tcset; |
137 | extra_refs += extra; | 138 | int idx = 0; |
139 | |||
140 | list_for_each_entry(tcset, &cset->threaded_csets, | ||
141 | threaded_csets_node) { | ||
142 | seq_puts(seq, idx ? "," : "<="); | ||
143 | seq_printf(seq, "%pK", tcset); | ||
144 | idx++; | ||
145 | } | ||
146 | } else { | ||
147 | seq_printf(seq, " %d", refcnt); | ||
148 | if (refcnt - cset->nr_tasks > 0) { | ||
149 | int extra = refcnt - cset->nr_tasks; | ||
150 | |||
151 | seq_printf(seq, " +%d", extra); | ||
152 | /* | ||
153 | * Take out the one additional reference in | ||
154 | * init_css_set. | ||
155 | */ | ||
156 | if (cset == &init_css_set) | ||
157 | extra--; | ||
158 | extra_refs += extra; | ||
159 | } | ||
138 | } | 160 | } |
139 | seq_puts(seq, "\n"); | 161 | seq_puts(seq, "\n"); |
140 | 162 | ||
@@ -163,10 +185,12 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) | |||
163 | } | 185 | } |
164 | spin_unlock_irq(&css_set_lock); | 186 | spin_unlock_irq(&css_set_lock); |
165 | 187 | ||
166 | if (!dead_cnt && !extra_refs) | 188 | if (!dead_cnt && !extra_refs && !threaded_csets) |
167 | return 0; | 189 | return 0; |
168 | 190 | ||
169 | seq_puts(seq, "\n"); | 191 | seq_puts(seq, "\n"); |
192 | if (threaded_csets) | ||
193 | seq_printf(seq, "threaded css_sets = %d\n", threaded_csets); | ||
170 | if (extra_refs) | 194 | if (extra_refs) |
171 | seq_printf(seq, "extra references = %d\n", extra_refs); | 195 | seq_printf(seq, "extra references = %d\n", extra_refs); |
172 | if (dead_cnt) | 196 | if (dead_cnt) |