summaryrefslogtreecommitdiffstats
path: root/mm/vmstat.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2017-05-03 17:52:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 18:52:08 -0400
commitb2bd8598195f1b2a72130592125ac6b4218988a2 (patch)
treee2d1699c6986748a69933bfc2362307594a2f7df /mm/vmstat.c
parentbbf9ce9719b5c64eac7f8483d1da6e8a3d4f98f5 (diff)
mm, vmstat: print non-populated zones in zoneinfo
Initscripts can use the information (protection levels) from /proc/zoneinfo to configure vm.lowmem_reserve_ratio at boot. vm.lowmem_reserve_ratio is an array of ratios for each configured zone on the system. If a zone is not populated on an arch, /proc/zoneinfo suppresses its output. This results in there not being a 1:1 mapping between the set of zones emitted by /proc/zoneinfo and the zones configured by vm.lowmem_reserve_ratio. This patch shows statistics for non-populated zones in /proc/zoneinfo. The zones exist and hold a spot in the vm.lowmem_reserve_ratio array. Without this patch, it is not possible to determine which index in the array controls which zone if one or more zones on the system are not populated. Remaining users of walk_zones_in_node() are unchanged. Files such as /proc/pagetypeinfo require certain zone data to be initialized properly for display, which is not done for unpopulated zones. Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1703031451310.98023@chino.kir.corp.google.com Signed-off-by: David Rientjes <rientjes@google.com> Reviewed-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r--mm/vmstat.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 828a36ea0584..a828b17ced1a 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1124,8 +1124,12 @@ static void frag_stop(struct seq_file *m, void *arg)
1124{ 1124{
1125} 1125}
1126 1126
1127/* Walk all the zones in a node and print using a callback */ 1127/*
1128 * Walk zones in a node and print using a callback.
1129 * If @assert_populated is true, only use callback for zones that are populated.
1130 */
1128static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat, 1131static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
1132 bool assert_populated,
1129 void (*print)(struct seq_file *m, pg_data_t *, struct zone *)) 1133 void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
1130{ 1134{
1131 struct zone *zone; 1135 struct zone *zone;
@@ -1133,7 +1137,7 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
1133 unsigned long flags; 1137 unsigned long flags;
1134 1138
1135 for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { 1139 for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
1136 if (!populated_zone(zone)) 1140 if (assert_populated && !populated_zone(zone))
1137 continue; 1141 continue;
1138 1142
1139 spin_lock_irqsave(&zone->lock, flags); 1143 spin_lock_irqsave(&zone->lock, flags);
@@ -1161,7 +1165,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
1161static int frag_show(struct seq_file *m, void *arg) 1165static int frag_show(struct seq_file *m, void *arg)
1162{ 1166{
1163 pg_data_t *pgdat = (pg_data_t *)arg; 1167 pg_data_t *pgdat = (pg_data_t *)arg;
1164 walk_zones_in_node(m, pgdat, frag_show_print); 1168 walk_zones_in_node(m, pgdat, true, frag_show_print);
1165 return 0; 1169 return 0;
1166} 1170}
1167 1171
@@ -1202,7 +1206,7 @@ static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
1202 seq_printf(m, "%6d ", order); 1206 seq_printf(m, "%6d ", order);
1203 seq_putc(m, '\n'); 1207 seq_putc(m, '\n');
1204 1208
1205 walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print); 1209 walk_zones_in_node(m, pgdat, true, pagetypeinfo_showfree_print);
1206 1210
1207 return 0; 1211 return 0;
1208} 1212}
@@ -1254,7 +1258,7 @@ static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
1254 for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) 1258 for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
1255 seq_printf(m, "%12s ", migratetype_names[mtype]); 1259 seq_printf(m, "%12s ", migratetype_names[mtype]);
1256 seq_putc(m, '\n'); 1260 seq_putc(m, '\n');
1257 walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print); 1261 walk_zones_in_node(m, pgdat, true, pagetypeinfo_showblockcount_print);
1258 1262
1259 return 0; 1263 return 0;
1260} 1264}
@@ -1280,7 +1284,7 @@ static void pagetypeinfo_showmixedcount(struct seq_file *m, pg_data_t *pgdat)
1280 seq_printf(m, "%12s ", migratetype_names[mtype]); 1284 seq_printf(m, "%12s ", migratetype_names[mtype]);
1281 seq_putc(m, '\n'); 1285 seq_putc(m, '\n');
1282 1286
1283 walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print); 1287 walk_zones_in_node(m, pgdat, true, pagetypeinfo_showmixedcount_print);
1284#endif /* CONFIG_PAGE_OWNER */ 1288#endif /* CONFIG_PAGE_OWNER */
1285} 1289}
1286 1290
@@ -1430,12 +1434,15 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1430} 1434}
1431 1435
1432/* 1436/*
1433 * Output information about zones in @pgdat. 1437 * Output information about zones in @pgdat. All zones are printed regardless
1438 * of whether they are populated or not: lowmem_reserve_ratio operates on the
1439 * set of all zones and userspace would not be aware of such zones if they are
1440 * suppressed here (zoneinfo displays the effect of lowmem_reserve_ratio).
1434 */ 1441 */
1435static int zoneinfo_show(struct seq_file *m, void *arg) 1442static int zoneinfo_show(struct seq_file *m, void *arg)
1436{ 1443{
1437 pg_data_t *pgdat = (pg_data_t *)arg; 1444 pg_data_t *pgdat = (pg_data_t *)arg;
1438 walk_zones_in_node(m, pgdat, zoneinfo_show_print); 1445 walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
1439 return 0; 1446 return 0;
1440} 1447}
1441 1448
@@ -1841,7 +1848,7 @@ static int unusable_show(struct seq_file *m, void *arg)
1841 if (!node_state(pgdat->node_id, N_MEMORY)) 1848 if (!node_state(pgdat->node_id, N_MEMORY))
1842 return 0; 1849 return 0;
1843 1850
1844 walk_zones_in_node(m, pgdat, unusable_show_print); 1851 walk_zones_in_node(m, pgdat, true, unusable_show_print);
1845 1852
1846 return 0; 1853 return 0;
1847} 1854}
@@ -1893,7 +1900,7 @@ static int extfrag_show(struct seq_file *m, void *arg)
1893{ 1900{
1894 pg_data_t *pgdat = (pg_data_t *)arg; 1901 pg_data_t *pgdat = (pg_data_t *)arg;
1895 1902
1896 walk_zones_in_node(m, pgdat, extfrag_show_print); 1903 walk_zones_in_node(m, pgdat, true, extfrag_show_print);
1897 1904
1898 return 0; 1905 return 0;
1899} 1906}