@@ -5480,6 +5480,92 @@ static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
}
}
+static int cmp_usage(const void *a, const void *b)
+{
+ struct mem_cgroup *memcg_a = *(struct mem_cgroup **)a;
+ struct mem_cgroup *memcg_b = *(struct mem_cgroup **)b;
+
+ return page_counter_read(&memcg_b->memory) -
+ page_counter_read(&memcg_a->memory);
+}
+
+static int child_memcg_css_count(struct cgroup_subsys_state *css)
+{
+ struct cgroup_subsys_state *child;
+ int count = 0;
+
+ css_for_each_child(child, css)
+ count++;
+
+ return count;
+}
+
+struct memory_top_info {
+ const char *name;
+ unsigned long idx;
+};
+
+static const struct memory_top_info memory_info[] = {
+ {"anon", NR_ANON_MAPPED},
+ {"file", NR_FILE_PAGES},
+ {"kernel", MEMCG_KMEM},
+};
+
+static void mem_cgroup_css_top(struct cgroup_subsys_state *css,
+ struct seq_file *seq)
+{
+ struct mem_cgroup **array;
+ struct cgroup_subsys_state *child;
+ int memcg_number = child_memcg_css_count(css);
+ int i, j;
+ int count = 0;
+
+ mem_cgroup_flush_stats();
+
+ array = kvmalloc_array(memcg_number, sizeof(struct mem_cgroup *),
+ GFP_KERNEL);
+ if (!array)
+ return;
+
+ css_for_each_child(child, css) {
+ struct mem_cgroup *memcg = mem_cgroup_from_css(child);
+
+ if (count == memcg_number)
+ break;
+ array[count++] = memcg;
+ }
+
+ sort(array, memcg_number, sizeof(struct mem_cgroup *), cmp_usage, NULL);
+
+ seq_printf(seq, "%s top:\n", css->ss->name);
+
+ seq_puts(seq, "name\t\tusage\t\t");
+ for (j = 0; j < ARRAY_SIZE(memory_info); j++)
+ seq_printf(seq, "%s\t\t", memory_info[j].name);
+ seq_puts(seq, "\n");
+
+ for (i = 0; i < memcg_number; i++) {
+ struct mem_cgroup *memcg = array[i];
+ unsigned long usage = page_counter_read(&memcg->memory);
+ struct cgroup *cgroup = memcg->css.cgroup;
+ const char *name = cgroup->kn->name;
+
+ seq_printf(seq, "%s\t\t%lu\t\t", name, usage * PAGE_SIZE);
+ for (j = 0; j < ARRAY_SIZE(memory_info); j++) {
+ u64 size;
+
+ size = memcg_page_state_output(memcg,
+ memory_info[j].idx);
+ seq_printf(seq, "%llu\t\t", size);
+ }
+ seq_puts(seq, "\n");
+ }
+
+ kvfree(array);
+
+}
+
+
#ifdef CONFIG_MMU
/* Handlers for move charge at task migration. */
static int mem_cgroup_do_precharge(unsigned long count)
@@ -6600,6 +6686,7 @@ struct cgroup_subsys memory_cgrp_subsys = {
.css_free = mem_cgroup_css_free,
.css_reset = mem_cgroup_css_reset,
.css_rstat_flush = mem_cgroup_css_rstat_flush,
+ .css_top = mem_cgroup_css_top,
.can_attach = mem_cgroup_can_attach,
.cancel_attach = mem_cgroup_cancel_attach,
.post_attach = mem_cgroup_move_task,