4 * WARNING: This controller is for cgroup core debugging only.
5 * Its interfaces are unstable and subject to changes at any time.
7 #include <linux/ctype.h>
9 #include <linux/slab.h>
11 #include "cgroup-internal.h"
13 static struct cgroup_subsys_state
*
14 debug_css_alloc(struct cgroup_subsys_state
*parent_css
)
16 struct cgroup_subsys_state
*css
= kzalloc(sizeof(*css
), GFP_KERNEL
);
19 return ERR_PTR(-ENOMEM
);
24 static void debug_css_free(struct cgroup_subsys_state
*css
)
30 * debug_taskcount_read - return the number of tasks in a cgroup.
31 * @cgrp: the cgroup in question
33 static u64
debug_taskcount_read(struct cgroup_subsys_state
*css
,
36 return cgroup_task_count(css
->cgroup
);
39 static int current_css_set_read(struct seq_file
*seq
, void *v
)
41 struct kernfs_open_file
*of
= seq
->private;
43 struct cgroup_subsys
*ss
;
44 struct cgroup_subsys_state
*css
;
47 if (!cgroup_kn_lock_live(of
->kn
, false))
50 spin_lock_irq(&css_set_lock
);
52 cset
= rcu_dereference(current
->cgroups
);
53 refcnt
= refcount_read(&cset
->refcount
);
54 seq_printf(seq
, "css_set %pK %d", cset
, refcnt
);
55 if (refcnt
> cset
->nr_tasks
)
56 seq_printf(seq
, " +%d", refcnt
- cset
->nr_tasks
);
60 * Print the css'es stored in the current css_set.
62 for_each_subsys(ss
, i
) {
63 css
= cset
->subsys
[ss
->id
];
66 seq_printf(seq
, "%2d: %-4s\t- %lx[%d]\n", ss
->id
, ss
->name
,
67 (unsigned long)css
, css
->id
);
70 spin_unlock_irq(&css_set_lock
);
71 cgroup_kn_unlock(of
->kn
);
75 static u64
current_css_set_refcount_read(struct cgroup_subsys_state
*css
,
81 count
= refcount_read(&task_css_set(current
)->refcount
);
86 static int current_css_set_cg_links_read(struct seq_file
*seq
, void *v
)
88 struct cgrp_cset_link
*link
;
92 name_buf
= kmalloc(NAME_MAX
+ 1, GFP_KERNEL
);
96 spin_lock_irq(&css_set_lock
);
98 cset
= rcu_dereference(current
->cgroups
);
99 list_for_each_entry(link
, &cset
->cgrp_links
, cgrp_link
) {
100 struct cgroup
*c
= link
->cgrp
;
102 cgroup_name(c
, name_buf
, NAME_MAX
+ 1);
103 seq_printf(seq
, "Root %d group %s\n",
104 c
->root
->hierarchy_id
, name_buf
);
107 spin_unlock_irq(&css_set_lock
);
112 #define MAX_TASKS_SHOWN_PER_CSS 25
113 static int cgroup_css_links_read(struct seq_file
*seq
, void *v
)
115 struct cgroup_subsys_state
*css
= seq_css(seq
);
116 struct cgrp_cset_link
*link
;
117 int dead_cnt
= 0, extra_refs
= 0;
119 spin_lock_irq(&css_set_lock
);
120 list_for_each_entry(link
, &css
->cgroup
->cset_links
, cset_link
) {
121 struct css_set
*cset
= link
->cset
;
122 struct task_struct
*task
;
124 int refcnt
= refcount_read(&cset
->refcount
);
126 seq_printf(seq
, " %d", refcnt
);
127 if (refcnt
- cset
->nr_tasks
> 0) {
128 int extra
= refcnt
- cset
->nr_tasks
;
130 seq_printf(seq
, " +%d", extra
);
132 * Take out the one additional reference in
135 if (cset
== &init_css_set
)
141 list_for_each_entry(task
, &cset
->tasks
, cg_list
) {
142 if (count
++ <= MAX_TASKS_SHOWN_PER_CSS
)
143 seq_printf(seq
, " task %d\n",
147 list_for_each_entry(task
, &cset
->mg_tasks
, cg_list
) {
148 if (count
++ <= MAX_TASKS_SHOWN_PER_CSS
)
149 seq_printf(seq
, " task %d\n",
152 /* show # of overflowed tasks */
153 if (count
> MAX_TASKS_SHOWN_PER_CSS
)
154 seq_printf(seq
, " ... (%d)\n",
155 count
- MAX_TASKS_SHOWN_PER_CSS
);
158 seq_puts(seq
, " [dead]\n");
162 WARN_ON(count
!= cset
->nr_tasks
);
164 spin_unlock_irq(&css_set_lock
);
166 if (!dead_cnt
&& !extra_refs
)
171 seq_printf(seq
, "extra references = %d\n", extra_refs
);
173 seq_printf(seq
, "dead css_sets = %d\n", dead_cnt
);
178 static int cgroup_subsys_states_read(struct seq_file
*seq
, void *v
)
180 struct kernfs_open_file
*of
= seq
->private;
182 struct cgroup_subsys
*ss
;
183 struct cgroup_subsys_state
*css
;
187 cgrp
= cgroup_kn_lock_live(of
->kn
, false);
191 for_each_subsys(ss
, i
) {
192 css
= rcu_dereference_check(cgrp
->subsys
[ss
->id
], true);
198 /* Show the parent CSS if applicable*/
200 snprintf(pbuf
, sizeof(pbuf
) - 1, " P=%d",
202 seq_printf(seq
, "%2d: %-4s\t- %lx[%d] %d%s\n", ss
->id
, ss
->name
,
203 (unsigned long)css
, css
->id
,
204 atomic_read(&css
->online_cnt
), pbuf
);
207 cgroup_kn_unlock(of
->kn
);
211 static void cgroup_masks_read_one(struct seq_file
*seq
, const char *name
,
214 struct cgroup_subsys
*ss
;
218 seq_printf(seq
, "%-17s: ", name
);
219 for_each_subsys(ss
, ssid
) {
220 if (!(mask
& (1 << ssid
)))
224 seq_puts(seq
, ss
->name
);
230 static int cgroup_masks_read(struct seq_file
*seq
, void *v
)
232 struct kernfs_open_file
*of
= seq
->private;
235 cgrp
= cgroup_kn_lock_live(of
->kn
, false);
239 cgroup_masks_read_one(seq
, "subtree_control", cgrp
->subtree_control
);
240 cgroup_masks_read_one(seq
, "subtree_ss_mask", cgrp
->subtree_ss_mask
);
242 cgroup_kn_unlock(of
->kn
);
246 static u64
releasable_read(struct cgroup_subsys_state
*css
, struct cftype
*cft
)
248 return (!cgroup_is_populated(css
->cgroup
) &&
249 !css_has_online_children(&css
->cgroup
->self
));
252 static struct cftype debug_legacy_files
[] = {
255 .read_u64
= debug_taskcount_read
,
259 .name
= "current_css_set",
260 .seq_show
= current_css_set_read
,
261 .flags
= CFTYPE_ONLY_ON_ROOT
,
265 .name
= "current_css_set_refcount",
266 .read_u64
= current_css_set_refcount_read
,
267 .flags
= CFTYPE_ONLY_ON_ROOT
,
271 .name
= "current_css_set_cg_links",
272 .seq_show
= current_css_set_cg_links_read
,
273 .flags
= CFTYPE_ONLY_ON_ROOT
,
277 .name
= "cgroup_css_links",
278 .seq_show
= cgroup_css_links_read
,
282 .name
= "cgroup_subsys_states",
283 .seq_show
= cgroup_subsys_states_read
,
287 .name
= "cgroup_masks",
288 .seq_show
= cgroup_masks_read
,
292 .name
= "releasable",
293 .read_u64
= releasable_read
,
299 static struct cftype debug_files
[] = {
302 .read_u64
= debug_taskcount_read
,
306 .name
= "current_css_set",
307 .seq_show
= current_css_set_read
,
308 .flags
= CFTYPE_ONLY_ON_ROOT
,
312 .name
= "current_css_set_refcount",
313 .read_u64
= current_css_set_refcount_read
,
314 .flags
= CFTYPE_ONLY_ON_ROOT
,
318 .name
= "current_css_set_cg_links",
319 .seq_show
= current_css_set_cg_links_read
,
320 .flags
= CFTYPE_ONLY_ON_ROOT
,
325 .seq_show
= cgroup_css_links_read
,
330 .seq_show
= cgroup_subsys_states_read
,
335 .seq_show
= cgroup_masks_read
,
341 struct cgroup_subsys debug_cgrp_subsys
= {
342 .css_alloc
= debug_css_alloc
,
343 .css_free
= debug_css_free
,
344 .legacy_cftypes
= debug_legacy_files
,
348 * On v2, debug is an implicit controller enabled by "cgroup_debug" boot
351 static int __init
enable_cgroup_debug(char *str
)
353 debug_cgrp_subsys
.dfl_cftypes
= debug_files
;
354 debug_cgrp_subsys
.implicit_on_dfl
= true;
357 __setup("cgroup_debug", enable_cgroup_debug
);