1 #include <linux/ctype.h> 2 #include <linux/mm.h> 3 #include <linux/slab.h> 4 5 #include "cgroup-internal.h" 6 7 static struct cgroup_subsys_state * 8 debug_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 18 static 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 */ 27 static u64 debug_taskcount_read(struct cgroup_subsys_state *css, 28 struct cftype *cft) 29 { 30 return cgroup_task_count(css->cgroup); 31 } 32 33 static u64 current_css_set_read(struct cgroup_subsys_state *css, 34 struct cftype *cft) 35 { 36 return (u64)(unsigned long)current->cgroups; 37 } 38 39 static 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 50 static 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 77 static 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 109 static 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 115 static 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 149 struct cgroup_subsys debug_cgrp_subsys = { 150 .css_alloc = debug_css_alloc, 151 .css_free = debug_css_free, 152 .legacy_cftypes = debug_files, 153 }; 154