forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cgroup: Move debug cgroup to its own file
The debug cgroup currently resides within cgroup-v1.c and is enabled only for v1 cgroup. To enable the debug cgroup also for v2, it makes sense to put the code into its own file as it will no longer be v1 specific. There is no change to the debug cgroup specific code. Signed-off-by: Waiman Long <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
- Loading branch information
1 parent
73a7242
commit a28f8f5
Showing
4 changed files
with
157 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
#include <linux/ctype.h> | ||
#include <linux/mm.h> | ||
#include <linux/slab.h> | ||
|
||
#include "cgroup-internal.h" | ||
|
||
static struct cgroup_subsys_state * | ||
debug_css_alloc(struct cgroup_subsys_state *parent_css) | ||
{ | ||
struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL); | ||
|
||
if (!css) | ||
return ERR_PTR(-ENOMEM); | ||
|
||
return css; | ||
} | ||
|
||
static void debug_css_free(struct cgroup_subsys_state *css) | ||
{ | ||
kfree(css); | ||
} | ||
|
||
/* | ||
* debug_taskcount_read - return the number of tasks in a cgroup. | ||
* @cgrp: the cgroup in question | ||
*/ | ||
static u64 debug_taskcount_read(struct cgroup_subsys_state *css, | ||
struct cftype *cft) | ||
{ | ||
return cgroup_task_count(css->cgroup); | ||
} | ||
|
||
static u64 current_css_set_read(struct cgroup_subsys_state *css, | ||
struct cftype *cft) | ||
{ | ||
return (u64)(unsigned long)current->cgroups; | ||
} | ||
|
||
static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css, | ||
struct cftype *cft) | ||
{ | ||
u64 count; | ||
|
||
rcu_read_lock(); | ||
count = refcount_read(&task_css_set(current)->refcount); | ||
rcu_read_unlock(); | ||
return count; | ||
} | ||
|
||
static int current_css_set_cg_links_read(struct seq_file *seq, void *v) | ||
{ | ||
struct cgrp_cset_link *link; | ||
struct css_set *cset; | ||
char *name_buf; | ||
|
||
name_buf = kmalloc(NAME_MAX + 1, GFP_KERNEL); | ||
if (!name_buf) | ||
return -ENOMEM; | ||
|
||
spin_lock_irq(&css_set_lock); | ||
rcu_read_lock(); | ||
cset = rcu_dereference(current->cgroups); | ||
list_for_each_entry(link, &cset->cgrp_links, cgrp_link) { | ||
struct cgroup *c = link->cgrp; | ||
|
||
cgroup_name(c, name_buf, NAME_MAX + 1); | ||
seq_printf(seq, "Root %d group %s\n", | ||
c->root->hierarchy_id, name_buf); | ||
} | ||
rcu_read_unlock(); | ||
spin_unlock_irq(&css_set_lock); | ||
kfree(name_buf); | ||
return 0; | ||
} | ||
|
||
#define MAX_TASKS_SHOWN_PER_CSS 25 | ||
static int cgroup_css_links_read(struct seq_file *seq, void *v) | ||
{ | ||
struct cgroup_subsys_state *css = seq_css(seq); | ||
struct cgrp_cset_link *link; | ||
|
||
spin_lock_irq(&css_set_lock); | ||
list_for_each_entry(link, &css->cgroup->cset_links, cset_link) { | ||
struct css_set *cset = link->cset; | ||
struct task_struct *task; | ||
int count = 0; | ||
|
||
seq_printf(seq, "css_set %pK\n", cset); | ||
|
||
list_for_each_entry(task, &cset->tasks, cg_list) { | ||
if (count++ > MAX_TASKS_SHOWN_PER_CSS) | ||
goto overflow; | ||
seq_printf(seq, " task %d\n", task_pid_vnr(task)); | ||
} | ||
|
||
list_for_each_entry(task, &cset->mg_tasks, cg_list) { | ||
if (count++ > MAX_TASKS_SHOWN_PER_CSS) | ||
goto overflow; | ||
seq_printf(seq, " task %d\n", task_pid_vnr(task)); | ||
} | ||
continue; | ||
overflow: | ||
seq_puts(seq, " ...\n"); | ||
} | ||
spin_unlock_irq(&css_set_lock); | ||
return 0; | ||
} | ||
|
||
static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft) | ||
{ | ||
return (!cgroup_is_populated(css->cgroup) && | ||
!css_has_online_children(&css->cgroup->self)); | ||
} | ||
|
||
static struct cftype debug_files[] = { | ||
{ | ||
.name = "taskcount", | ||
.read_u64 = debug_taskcount_read, | ||
}, | ||
|
||
{ | ||
.name = "current_css_set", | ||
.read_u64 = current_css_set_read, | ||
}, | ||
|
||
{ | ||
.name = "current_css_set_refcount", | ||
.read_u64 = current_css_set_refcount_read, | ||
}, | ||
|
||
{ | ||
.name = "current_css_set_cg_links", | ||
.seq_show = current_css_set_cg_links_read, | ||
}, | ||
|
||
{ | ||
.name = "cgroup_css_links", | ||
.seq_show = cgroup_css_links_read, | ||
}, | ||
|
||
{ | ||
.name = "releasable", | ||
.read_u64 = releasable_read, | ||
}, | ||
|
||
{ } /* terminate */ | ||
}; | ||
|
||
struct cgroup_subsys debug_cgrp_subsys = { | ||
.css_alloc = debug_css_alloc, | ||
.css_free = debug_css_free, | ||
.legacy_cftypes = debug_files, | ||
}; |