diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2016-01-20 18:03:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-20 20:09:18 -0500 |
commit | 587d9f726aaec52157e4156e50363dbe6cb82bdb (patch) | |
tree | bd3afd21baa9d5032fb30754aa88485f3ae64a2a | |
parent | 44b7a8d33d666268062e0f725d5f14813a63a6ea (diff) |
mm: memcontrol: basic memory statistics in cgroup2 memory controller
Provide a cgroup2 memory.stat that provides statistics on LRU memory
and fault event counters. More consumers and breakdowns will follow.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | Documentation/cgroup-v2.txt | 56 | ||||
-rw-r--r-- | mm/memcontrol.c | 68 |
2 files changed, 124 insertions, 0 deletions
diff --git a/Documentation/cgroup-v2.txt b/Documentation/cgroup-v2.txt index f441564023e1..65b3eac8856c 100644 --- a/Documentation/cgroup-v2.txt +++ b/Documentation/cgroup-v2.txt | |||
@@ -819,6 +819,62 @@ PAGE_SIZE multiple when read back. | |||
819 | the cgroup. This may not exactly match the number of | 819 | the cgroup. This may not exactly match the number of |
820 | processes killed but should generally be close. | 820 | processes killed but should generally be close. |
821 | 821 | ||
822 | memory.stat | ||
823 | |||
824 | A read-only flat-keyed file which exists on non-root cgroups. | ||
825 | |||
826 | This breaks down the cgroup's memory footprint into different | ||
827 | types of memory, type-specific details, and other information | ||
828 | on the state and past events of the memory management system. | ||
829 | |||
830 | All memory amounts are in bytes. | ||
831 | |||
832 | The entries are ordered to be human readable, and new entries | ||
833 | can show up in the middle. Don't rely on items remaining in a | ||
834 | fixed position; use the keys to look up specific values! | ||
835 | |||
836 | anon | ||
837 | |||
838 | Amount of memory used in anonymous mappings such as | ||
839 | brk(), sbrk(), and mmap(MAP_ANONYMOUS) | ||
840 | |||
841 | file | ||
842 | |||
843 | Amount of memory used to cache filesystem data, | ||
844 | including tmpfs and shared memory. | ||
845 | |||
846 | file_mapped | ||
847 | |||
848 | Amount of cached filesystem data mapped with mmap() | ||
849 | |||
850 | file_dirty | ||
851 | |||
852 | Amount of cached filesystem data that was modified but | ||
853 | not yet written back to disk | ||
854 | |||
855 | file_writeback | ||
856 | |||
857 | Amount of cached filesystem data that was modified and | ||
858 | is currently being written back to disk | ||
859 | |||
860 | inactive_anon | ||
861 | active_anon | ||
862 | inactive_file | ||
863 | active_file | ||
864 | unevictable | ||
865 | |||
866 | Amount of memory, swap-backed and filesystem-backed, | ||
867 | on the internal memory management lists used by the | ||
868 | page reclaim algorithm | ||
869 | |||
870 | pgfault | ||
871 | |||
872 | Total number of page faults incurred | ||
873 | |||
874 | pgmajfault | ||
875 | |||
876 | Number of major page faults incurred | ||
877 | |||
822 | memory.swap.current | 878 | memory.swap.current |
823 | 879 | ||
824 | A read-only single value file which exists on non-root | 880 | A read-only single value file which exists on non-root |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bf35bff282fc..98f4109bff6c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -2767,6 +2767,18 @@ static unsigned long tree_stat(struct mem_cgroup *memcg, | |||
2767 | return val; | 2767 | return val; |
2768 | } | 2768 | } |
2769 | 2769 | ||
2770 | static unsigned long tree_events(struct mem_cgroup *memcg, | ||
2771 | enum mem_cgroup_events_index idx) | ||
2772 | { | ||
2773 | struct mem_cgroup *iter; | ||
2774 | unsigned long val = 0; | ||
2775 | |||
2776 | for_each_mem_cgroup_tree(iter, memcg) | ||
2777 | val += mem_cgroup_read_events(iter, idx); | ||
2778 | |||
2779 | return val; | ||
2780 | } | ||
2781 | |||
2770 | static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) | 2782 | static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) |
2771 | { | 2783 | { |
2772 | unsigned long val; | 2784 | unsigned long val; |
@@ -5096,6 +5108,57 @@ static int memory_events_show(struct seq_file *m, void *v) | |||
5096 | return 0; | 5108 | return 0; |
5097 | } | 5109 | } |
5098 | 5110 | ||
5111 | static int memory_stat_show(struct seq_file *m, void *v) | ||
5112 | { | ||
5113 | struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m)); | ||
5114 | int i; | ||
5115 | |||
5116 | /* | ||
5117 | * Provide statistics on the state of the memory subsystem as | ||
5118 | * well as cumulative event counters that show past behavior. | ||
5119 | * | ||
5120 | * This list is ordered following a combination of these gradients: | ||
5121 | * 1) generic big picture -> specifics and details | ||
5122 | * 2) reflecting userspace activity -> reflecting kernel heuristics | ||
5123 | * | ||
5124 | * Current memory state: | ||
5125 | */ | ||
5126 | |||
5127 | seq_printf(m, "anon %llu\n", | ||
5128 | (u64)tree_stat(memcg, MEM_CGROUP_STAT_RSS) * PAGE_SIZE); | ||
5129 | seq_printf(m, "file %llu\n", | ||
5130 | (u64)tree_stat(memcg, MEM_CGROUP_STAT_CACHE) * PAGE_SIZE); | ||
5131 | |||
5132 | seq_printf(m, "file_mapped %llu\n", | ||
5133 | (u64)tree_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED) * | ||
5134 | PAGE_SIZE); | ||
5135 | seq_printf(m, "file_dirty %llu\n", | ||
5136 | (u64)tree_stat(memcg, MEM_CGROUP_STAT_DIRTY) * | ||
5137 | PAGE_SIZE); | ||
5138 | seq_printf(m, "file_writeback %llu\n", | ||
5139 | (u64)tree_stat(memcg, MEM_CGROUP_STAT_WRITEBACK) * | ||
5140 | PAGE_SIZE); | ||
5141 | |||
5142 | for (i = 0; i < NR_LRU_LISTS; i++) { | ||
5143 | struct mem_cgroup *mi; | ||
5144 | unsigned long val = 0; | ||
5145 | |||
5146 | for_each_mem_cgroup_tree(mi, memcg) | ||
5147 | val += mem_cgroup_nr_lru_pages(mi, BIT(i)); | ||
5148 | seq_printf(m, "%s %llu\n", | ||
5149 | mem_cgroup_lru_names[i], (u64)val * PAGE_SIZE); | ||
5150 | } | ||
5151 | |||
5152 | /* Accumulated memory events */ | ||
5153 | |||
5154 | seq_printf(m, "pgfault %lu\n", | ||
5155 | tree_events(memcg, MEM_CGROUP_EVENTS_PGFAULT)); | ||
5156 | seq_printf(m, "pgmajfault %lu\n", | ||
5157 | tree_events(memcg, MEM_CGROUP_EVENTS_PGMAJFAULT)); | ||
5158 | |||
5159 | return 0; | ||
5160 | } | ||
5161 | |||
5099 | static struct cftype memory_files[] = { | 5162 | static struct cftype memory_files[] = { |
5100 | { | 5163 | { |
5101 | .name = "current", | 5164 | .name = "current", |
@@ -5126,6 +5189,11 @@ static struct cftype memory_files[] = { | |||
5126 | .file_offset = offsetof(struct mem_cgroup, events_file), | 5189 | .file_offset = offsetof(struct mem_cgroup, events_file), |
5127 | .seq_show = memory_events_show, | 5190 | .seq_show = memory_events_show, |
5128 | }, | 5191 | }, |
5192 | { | ||
5193 | .name = "stat", | ||
5194 | .flags = CFTYPE_NOT_ON_ROOT, | ||
5195 | .seq_show = memory_stat_show, | ||
5196 | }, | ||
5129 | { } /* terminate */ | 5197 | { } /* terminate */ |
5130 | }; | 5198 | }; |
5131 | 5199 | ||