aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r--mm/vmstat.c75
1 files changed, 36 insertions, 39 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 809025ed97ea..f5fa1bd1eb16 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -954,7 +954,6 @@ const char * const vmstat_text[] = {
954 "nr_unevictable", 954 "nr_unevictable",
955 "nr_isolated_anon", 955 "nr_isolated_anon",
956 "nr_isolated_file", 956 "nr_isolated_file",
957 "nr_pages_scanned",
958 "workingset_refault", 957 "workingset_refault",
959 "workingset_activate", 958 "workingset_activate",
960 "workingset_nodereclaim", 959 "workingset_nodereclaim",
@@ -992,6 +991,7 @@ const char * const vmstat_text[] = {
992 "pgfree", 991 "pgfree",
993 "pgactivate", 992 "pgactivate",
994 "pgdeactivate", 993 "pgdeactivate",
994 "pglazyfree",
995 995
996 "pgfault", 996 "pgfault",
997 "pgmajfault", 997 "pgmajfault",
@@ -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
@@ -1378,7 +1382,6 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1378 "\n min %lu" 1382 "\n min %lu"
1379 "\n low %lu" 1383 "\n low %lu"
1380 "\n high %lu" 1384 "\n high %lu"
1381 "\n node_scanned %lu"
1382 "\n spanned %lu" 1385 "\n spanned %lu"
1383 "\n present %lu" 1386 "\n present %lu"
1384 "\n managed %lu", 1387 "\n managed %lu",
@@ -1386,23 +1389,28 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1386 min_wmark_pages(zone), 1389 min_wmark_pages(zone),
1387 low_wmark_pages(zone), 1390 low_wmark_pages(zone),
1388 high_wmark_pages(zone), 1391 high_wmark_pages(zone),
1389 node_page_state(zone->zone_pgdat, NR_PAGES_SCANNED),
1390 zone->spanned_pages, 1392 zone->spanned_pages,
1391 zone->present_pages, 1393 zone->present_pages,
1392 zone->managed_pages); 1394 zone->managed_pages);
1393 1395
1394 for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
1395 seq_printf(m, "\n %-12s %lu", vmstat_text[i],
1396 zone_page_state(zone, i));
1397
1398 seq_printf(m, 1396 seq_printf(m,
1399 "\n protection: (%ld", 1397 "\n protection: (%ld",
1400 zone->lowmem_reserve[0]); 1398 zone->lowmem_reserve[0]);
1401 for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) 1399 for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
1402 seq_printf(m, ", %ld", zone->lowmem_reserve[i]); 1400 seq_printf(m, ", %ld", zone->lowmem_reserve[i]);
1403 seq_printf(m, 1401 seq_putc(m, ')');
1404 ")" 1402
1405 "\n pagesets"); 1403 /* If unpopulated, no other information is useful */
1404 if (!populated_zone(zone)) {
1405 seq_putc(m, '\n');
1406 return;
1407 }
1408
1409 for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
1410 seq_printf(m, "\n %-12s %lu", vmstat_text[i],
1411 zone_page_state(zone, i));
1412
1413 seq_printf(m, "\n pagesets");
1406 for_each_online_cpu(i) { 1414 for_each_online_cpu(i) {
1407 struct per_cpu_pageset *pageset; 1415 struct per_cpu_pageset *pageset;
1408 1416
@@ -1425,19 +1433,22 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1425 "\n node_unreclaimable: %u" 1433 "\n node_unreclaimable: %u"
1426 "\n start_pfn: %lu" 1434 "\n start_pfn: %lu"
1427 "\n node_inactive_ratio: %u", 1435 "\n node_inactive_ratio: %u",
1428 !pgdat_reclaimable(zone->zone_pgdat), 1436 pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES,
1429 zone->zone_start_pfn, 1437 zone->zone_start_pfn,
1430 zone->zone_pgdat->inactive_ratio); 1438 zone->zone_pgdat->inactive_ratio);
1431 seq_putc(m, '\n'); 1439 seq_putc(m, '\n');
1432} 1440}
1433 1441
1434/* 1442/*
1435 * Output information about zones in @pgdat. 1443 * Output information about zones in @pgdat. All zones are printed regardless
1444 * of whether they are populated or not: lowmem_reserve_ratio operates on the
1445 * set of all zones and userspace would not be aware of such zones if they are
1446 * suppressed here (zoneinfo displays the effect of lowmem_reserve_ratio).
1436 */ 1447 */
1437static int zoneinfo_show(struct seq_file *m, void *arg) 1448static int zoneinfo_show(struct seq_file *m, void *arg)
1438{ 1449{
1439 pg_data_t *pgdat = (pg_data_t *)arg; 1450 pg_data_t *pgdat = (pg_data_t *)arg;
1440 walk_zones_in_node(m, pgdat, zoneinfo_show_print); 1451 walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
1441 return 0; 1452 return 0;
1442} 1453}
1443 1454
@@ -1586,22 +1597,9 @@ int vmstat_refresh(struct ctl_table *table, int write,
1586 for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) { 1597 for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) {
1587 val = atomic_long_read(&vm_zone_stat[i]); 1598 val = atomic_long_read(&vm_zone_stat[i]);
1588 if (val < 0) { 1599 if (val < 0) {
1589 switch (i) { 1600 pr_warn("%s: %s %ld\n",
1590 case NR_PAGES_SCANNED: 1601 __func__, vmstat_text[i], val);
1591 /* 1602 err = -EINVAL;
1592 * This is often seen to go negative in
1593 * recent kernels, but not to go permanently
1594 * negative. Whilst it would be nicer not to
1595 * have exceptions, rooting them out would be
1596 * another task, of rather low priority.
1597 */
1598 break;
1599 default:
1600 pr_warn("%s: %s %ld\n",
1601 __func__, vmstat_text[i], val);
1602 err = -EINVAL;
1603 break;
1604 }
1605 } 1603 }
1606 } 1604 }
1607 if (err) 1605 if (err)
@@ -1768,8 +1766,7 @@ void __init init_mm_internals(void)
1768{ 1766{
1769 int ret __maybe_unused; 1767 int ret __maybe_unused;
1770 1768
1771 mm_percpu_wq = alloc_workqueue("mm_percpu_wq", 1769 mm_percpu_wq = alloc_workqueue("mm_percpu_wq", WQ_MEM_RECLAIM, 0);
1772 WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
1773 1770
1774#ifdef CONFIG_SMP 1771#ifdef CONFIG_SMP
1775 ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead", 1772 ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
@@ -1857,7 +1854,7 @@ static int unusable_show(struct seq_file *m, void *arg)
1857 if (!node_state(pgdat->node_id, N_MEMORY)) 1854 if (!node_state(pgdat->node_id, N_MEMORY))
1858 return 0; 1855 return 0;
1859 1856
1860 walk_zones_in_node(m, pgdat, unusable_show_print); 1857 walk_zones_in_node(m, pgdat, true, unusable_show_print);
1861 1858
1862 return 0; 1859 return 0;
1863} 1860}
@@ -1909,7 +1906,7 @@ static int extfrag_show(struct seq_file *m, void *arg)
1909{ 1906{
1910 pg_data_t *pgdat = (pg_data_t *)arg; 1907 pg_data_t *pgdat = (pg_data_t *)arg;
1911 1908
1912 walk_zones_in_node(m, pgdat, extfrag_show_print); 1909 walk_zones_in_node(m, pgdat, true, extfrag_show_print);
1913 1910
1914 return 0; 1911 return 0;
1915} 1912}