diff options
Diffstat (limited to 'kernel/cgroup/debug.c')
-rw-r--r-- | kernel/cgroup/debug.c | 52 |
1 files changed, 38 insertions, 14 deletions
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) |