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