aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup/debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cgroup/debug.c')
-rw-r--r--kernel/cgroup/debug.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/kernel/cgroup/debug.c b/kernel/cgroup/debug.c
new file mode 100644
index 000000000000..1c209aa43733
--- /dev/null
+++ b/kernel/cgroup/debug.c
@@ -0,0 +1,153 @@
1#include <linux/ctype.h>
2#include <linux/mm.h>
3#include <linux/slab.h>
4
5#include "cgroup-internal.h"
6
7static struct cgroup_subsys_state *
8debug_css_alloc(struct cgroup_subsys_state *parent_css)
9{
10 struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
11
12 if (!css)
13 return ERR_PTR(-ENOMEM);
14
15 return css;
16}
17
18static void debug_css_free(struct cgroup_subsys_state *css)
19{
20 kfree(css);
21}
22
23/*
24 * debug_taskcount_read - return the number of tasks in a cgroup.
25 * @cgrp: the cgroup in question
26 */
27static u64 debug_taskcount_read(struct cgroup_subsys_state *css,
28 struct cftype *cft)
29{
30 return cgroup_task_count(css->cgroup);
31}
32
33static u64 current_css_set_read(struct cgroup_subsys_state *css,
34 struct cftype *cft)
35{
36 return (u64)(unsigned long)current->cgroups;
37}
38
39static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
40 struct cftype *cft)
41{
42 u64 count;
43
44 rcu_read_lock();
45 count = refcount_read(&task_css_set(current)->refcount);
46 rcu_read_unlock();
47 return count;
48}
49
50static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
51{
52 struct cgrp_cset_link *link;
53 struct css_set *cset;
54 char *name_buf;
55
56 name_buf = kmalloc(NAME_MAX + 1, GFP_KERNEL);
57 if (!name_buf)
58 return -ENOMEM;
59
60 spin_lock_irq(&css_set_lock);
61 rcu_read_lock();
62 cset = rcu_dereference(current->cgroups);
63 list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
64 struct cgroup *c = link->cgrp;
65
66 cgroup_name(c, name_buf, NAME_MAX + 1);
67 seq_printf(seq, "Root %d group %s\n",
68 c->root->hierarchy_id, name_buf);
69 }
70 rcu_read_unlock();
71 spin_unlock_irq(&css_set_lock);
72 kfree(name_buf);
73 return 0;
74}
75
76#define MAX_TASKS_SHOWN_PER_CSS 25
77static int cgroup_css_links_read(struct seq_file *seq, void *v)
78{
79 struct cgroup_subsys_state *css = seq_css(seq);
80 struct cgrp_cset_link *link;
81
82 spin_lock_irq(&css_set_lock);
83 list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
84 struct css_set *cset = link->cset;
85 struct task_struct *task;
86 int count = 0;
87
88 seq_printf(seq, "css_set %pK\n", cset);
89
90 list_for_each_entry(task, &cset->tasks, cg_list) {
91 if (count++ > MAX_TASKS_SHOWN_PER_CSS)
92 goto overflow;
93 seq_printf(seq, " task %d\n", task_pid_vnr(task));
94 }
95
96 list_for_each_entry(task, &cset->mg_tasks, cg_list) {
97 if (count++ > MAX_TASKS_SHOWN_PER_CSS)
98 goto overflow;
99 seq_printf(seq, " task %d\n", task_pid_vnr(task));
100 }
101 continue;
102 overflow:
103 seq_puts(seq, " ...\n");
104 }
105 spin_unlock_irq(&css_set_lock);
106 return 0;
107}
108
109static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft)
110{
111 return (!cgroup_is_populated(css->cgroup) &&
112 !css_has_online_children(&css->cgroup->self));
113}
114
115static struct cftype debug_files[] = {
116 {
117 .name = "taskcount",
118 .read_u64 = debug_taskcount_read,
119 },
120
121 {
122 .name = "current_css_set",
123 .read_u64 = current_css_set_read,
124 },
125
126 {
127 .name = "current_css_set_refcount",
128 .read_u64 = current_css_set_refcount_read,
129 },
130
131 {
132 .name = "current_css_set_cg_links",
133 .seq_show = current_css_set_cg_links_read,
134 },
135
136 {
137 .name = "cgroup_css_links",
138 .seq_show = cgroup_css_links_read,
139 },
140
141 {
142 .name = "releasable",
143 .read_u64 = releasable_read,
144 },
145
146 { } /* terminate */
147};
148
149struct cgroup_subsys debug_cgrp_subsys = {
150 .css_alloc = debug_css_alloc,
151 .css_free = debug_css_free,
152 .legacy_cftypes = debug_files,
153};