aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c168
1 files changed, 66 insertions, 102 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 1118e02a40b6..35e008e25422 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -91,6 +91,13 @@ enum mem_cgroup_stat_index {
91 MEM_CGROUP_STAT_NSTATS, 91 MEM_CGROUP_STAT_NSTATS,
92}; 92};
93 93
94static const char * const mem_cgroup_stat_names[] = {
95 "cache",
96 "rss",
97 "mapped_file",
98 "swap",
99};
100
94enum mem_cgroup_events_index { 101enum mem_cgroup_events_index {
95 MEM_CGROUP_EVENTS_PGPGIN, /* # of pages paged in */ 102 MEM_CGROUP_EVENTS_PGPGIN, /* # of pages paged in */
96 MEM_CGROUP_EVENTS_PGPGOUT, /* # of pages paged out */ 103 MEM_CGROUP_EVENTS_PGPGOUT, /* # of pages paged out */
@@ -98,6 +105,14 @@ enum mem_cgroup_events_index {
98 MEM_CGROUP_EVENTS_PGMAJFAULT, /* # of major page-faults */ 105 MEM_CGROUP_EVENTS_PGMAJFAULT, /* # of major page-faults */
99 MEM_CGROUP_EVENTS_NSTATS, 106 MEM_CGROUP_EVENTS_NSTATS,
100}; 107};
108
109static const char * const mem_cgroup_events_names[] = {
110 "pgpgin",
111 "pgpgout",
112 "pgfault",
113 "pgmajfault",
114};
115
101/* 116/*
102 * Per memcg event counter is incremented at every pagein/pageout. With THP, 117 * Per memcg event counter is incremented at every pagein/pageout. With THP,
103 * it will be incremated by the number of pages. This counter is used for 118 * it will be incremated by the number of pages. This counter is used for
@@ -4037,92 +4052,6 @@ static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
4037} 4052}
4038#endif 4053#endif
4039 4054
4040
4041/* For read statistics */
4042enum {
4043 MCS_CACHE,
4044 MCS_RSS,
4045 MCS_FILE_MAPPED,
4046 MCS_SWAP,
4047 MCS_PGPGIN,
4048 MCS_PGPGOUT,
4049 MCS_PGFAULT,
4050 MCS_PGMAJFAULT,
4051 MCS_INACTIVE_ANON,
4052 MCS_ACTIVE_ANON,
4053 MCS_INACTIVE_FILE,
4054 MCS_ACTIVE_FILE,
4055 MCS_UNEVICTABLE,
4056 NR_MCS_STAT,
4057};
4058
4059struct mcs_total_stat {
4060 s64 stat[NR_MCS_STAT];
4061};
4062
4063static const char *memcg_stat_strings[NR_MCS_STAT] = {
4064 "cache",
4065 "rss",
4066 "mapped_file",
4067 "swap",
4068 "pgpgin",
4069 "pgpgout",
4070 "pgfault",
4071 "pgmajfault",
4072 "inactive_anon",
4073 "active_anon",
4074 "inactive_file",
4075 "active_file",
4076 "unevictable",
4077};
4078
4079static void
4080mem_cgroup_get_local_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s)
4081{
4082 s64 val;
4083
4084 /* per cpu stat */
4085 val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_CACHE);
4086 s->stat[MCS_CACHE] += val * PAGE_SIZE;
4087 val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_RSS);
4088 s->stat[MCS_RSS] += val * PAGE_SIZE;
4089 val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
4090 s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE;
4091 val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGPGIN);
4092 s->stat[MCS_PGPGIN] += val;
4093 val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGPGOUT);
4094 s->stat[MCS_PGPGOUT] += val;
4095 if (do_swap_account) {
4096 val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_SWAPOUT);
4097 s->stat[MCS_SWAP] += val * PAGE_SIZE;
4098 }
4099 val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGFAULT);
4100 s->stat[MCS_PGFAULT] += val;
4101 val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGMAJFAULT);
4102 s->stat[MCS_PGMAJFAULT] += val;
4103
4104 /* per zone stat */
4105 val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_ANON));
4106 s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE;
4107 val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_ANON));
4108 s->stat[MCS_ACTIVE_ANON] += val * PAGE_SIZE;
4109 val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_FILE));
4110 s->stat[MCS_INACTIVE_FILE] += val * PAGE_SIZE;
4111 val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_FILE));
4112 s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE;
4113 val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
4114 s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE;
4115}
4116
4117static void
4118mem_cgroup_get_total_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s)
4119{
4120 struct mem_cgroup *iter;
4121
4122 for_each_mem_cgroup_tree(iter, memcg)
4123 mem_cgroup_get_local_stat(iter, s);
4124}
4125
4126#ifdef CONFIG_NUMA 4055#ifdef CONFIG_NUMA
4127static int mem_control_numa_stat_show(struct cgroup *cont, struct cftype *cft, 4056static int mem_control_numa_stat_show(struct cgroup *cont, struct cftype *cft,
4128 struct seq_file *m) 4057 struct seq_file *m)
@@ -4170,24 +4099,41 @@ static int mem_control_numa_stat_show(struct cgroup *cont, struct cftype *cft,
4170} 4099}
4171#endif /* CONFIG_NUMA */ 4100#endif /* CONFIG_NUMA */
4172 4101
4102static const char * const mem_cgroup_lru_names[] = {
4103 "inactive_anon",
4104 "active_anon",
4105 "inactive_file",
4106 "active_file",
4107 "unevictable",
4108};
4109
4110static inline void mem_cgroup_lru_names_not_uptodate(void)
4111{
4112 BUILD_BUG_ON(ARRAY_SIZE(mem_cgroup_lru_names) != NR_LRU_LISTS);
4113}
4114
4173static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, 4115static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
4174 struct seq_file *m) 4116 struct seq_file *m)
4175{ 4117{
4176 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); 4118 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
4177 struct mcs_total_stat mystat; 4119 struct mem_cgroup *mi;
4178 int i; 4120 unsigned int i;
4179
4180 memset(&mystat, 0, sizeof(mystat));
4181 mem_cgroup_get_local_stat(memcg, &mystat);
4182
4183 4121
4184 for (i = 0; i < NR_MCS_STAT; i++) { 4122 for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) {
4185 if (i == MCS_SWAP && !do_swap_account) 4123 if (i == MEM_CGROUP_STAT_SWAPOUT && !do_swap_account)
4186 continue; 4124 continue;
4187 seq_printf(m, "%s %llu\n", memcg_stat_strings[i], 4125 seq_printf(m, "%s %ld\n", mem_cgroup_stat_names[i],
4188 (unsigned long long)mystat.stat[i]); 4126 mem_cgroup_read_stat(memcg, i) * PAGE_SIZE);
4189 } 4127 }
4190 4128
4129 for (i = 0; i < MEM_CGROUP_EVENTS_NSTATS; i++)
4130 seq_printf(m, "%s %lu\n", mem_cgroup_events_names[i],
4131 mem_cgroup_read_events(memcg, i));
4132
4133 for (i = 0; i < NR_LRU_LISTS; i++)
4134 seq_printf(m, "%s %lu\n", mem_cgroup_lru_names[i],
4135 mem_cgroup_nr_lru_pages(memcg, BIT(i)) * PAGE_SIZE);
4136
4191 /* Hierarchical information */ 4137 /* Hierarchical information */
4192 { 4138 {
4193 unsigned long long limit, memsw_limit; 4139 unsigned long long limit, memsw_limit;
@@ -4198,13 +4144,31 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
4198 memsw_limit); 4144 memsw_limit);
4199 } 4145 }
4200 4146
4201 memset(&mystat, 0, sizeof(mystat)); 4147 for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) {
4202 mem_cgroup_get_total_stat(memcg, &mystat); 4148 long long val = 0;
4203 for (i = 0; i < NR_MCS_STAT; i++) { 4149
4204 if (i == MCS_SWAP && !do_swap_account) 4150 if (i == MEM_CGROUP_STAT_SWAPOUT && !do_swap_account)
4205 continue; 4151 continue;
4206 seq_printf(m, "total_%s %llu\n", memcg_stat_strings[i], 4152 for_each_mem_cgroup_tree(mi, memcg)
4207 (unsigned long long)mystat.stat[i]); 4153 val += mem_cgroup_read_stat(mi, i) * PAGE_SIZE;
4154 seq_printf(m, "total_%s %lld\n", mem_cgroup_stat_names[i], val);
4155 }
4156
4157 for (i = 0; i < MEM_CGROUP_EVENTS_NSTATS; i++) {
4158 unsigned long long val = 0;
4159
4160 for_each_mem_cgroup_tree(mi, memcg)
4161 val += mem_cgroup_read_events(mi, i);
4162 seq_printf(m, "total_%s %llu\n",
4163 mem_cgroup_events_names[i], val);
4164 }
4165
4166 for (i = 0; i < NR_LRU_LISTS; i++) {
4167 unsigned long long val = 0;
4168
4169 for_each_mem_cgroup_tree(mi, memcg)
4170 val += mem_cgroup_nr_lru_pages(mi, BIT(i)) * PAGE_SIZE;
4171 seq_printf(m, "total_%s %llu\n", mem_cgroup_lru_names[i], val);
4208 } 4172 }
4209 4173
4210#ifdef CONFIG_DEBUG_VM 4174#ifdef CONFIG_DEBUG_VM