.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * linux/mm/vmstat.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
75 | 76 | static DEFINE_MUTEX(vm_numa_stat_lock); |
---|
76 | 77 | |
---|
77 | 78 | int sysctl_vm_numa_stat_handler(struct ctl_table *table, int write, |
---|
78 | | - void __user *buffer, size_t *length, loff_t *ppos) |
---|
| 79 | + void *buffer, size_t *length, loff_t *ppos) |
---|
79 | 80 | { |
---|
80 | 81 | int ret, oldval; |
---|
81 | 82 | |
---|
.. | .. |
---|
227 | 228 | * 125 1024 10 16-32 GB 9 |
---|
228 | 229 | */ |
---|
229 | 230 | |
---|
230 | | - mem = zone->managed_pages >> (27 - PAGE_SHIFT); |
---|
| 231 | + mem = zone_managed_pages(zone) >> (27 - PAGE_SHIFT); |
---|
231 | 232 | |
---|
232 | 233 | threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem)); |
---|
233 | 234 | |
---|
.. | .. |
---|
320 | 321 | long x; |
---|
321 | 322 | long t; |
---|
322 | 323 | |
---|
| 324 | + preempt_disable_rt(); |
---|
323 | 325 | x = delta + __this_cpu_read(*p); |
---|
324 | 326 | |
---|
325 | 327 | t = __this_cpu_read(pcp->stat_threshold); |
---|
326 | 328 | |
---|
327 | | - if (unlikely(x > t || x < -t)) { |
---|
| 329 | + if (unlikely(abs(x) > t)) { |
---|
328 | 330 | zone_page_state_add(x, zone, item); |
---|
329 | 331 | x = 0; |
---|
330 | 332 | } |
---|
331 | 333 | __this_cpu_write(*p, x); |
---|
| 334 | + preempt_enable_rt(); |
---|
332 | 335 | } |
---|
333 | 336 | EXPORT_SYMBOL(__mod_zone_page_state); |
---|
334 | 337 | |
---|
.. | .. |
---|
340 | 343 | long x; |
---|
341 | 344 | long t; |
---|
342 | 345 | |
---|
| 346 | + if (vmstat_item_in_bytes(item)) { |
---|
| 347 | + VM_WARN_ON_ONCE(delta & (PAGE_SIZE - 1)); |
---|
| 348 | + delta >>= PAGE_SHIFT; |
---|
| 349 | + } |
---|
| 350 | + |
---|
| 351 | + preempt_disable_rt(); |
---|
343 | 352 | x = delta + __this_cpu_read(*p); |
---|
344 | 353 | |
---|
345 | 354 | t = __this_cpu_read(pcp->stat_threshold); |
---|
346 | 355 | |
---|
347 | | - if (unlikely(x > t || x < -t)) { |
---|
| 356 | + if (unlikely(abs(x) > t)) { |
---|
348 | 357 | node_page_state_add(x, pgdat, item); |
---|
349 | 358 | x = 0; |
---|
350 | 359 | } |
---|
351 | 360 | __this_cpu_write(*p, x); |
---|
| 361 | + preempt_enable_rt(); |
---|
352 | 362 | } |
---|
353 | 363 | EXPORT_SYMBOL(__mod_node_page_state); |
---|
354 | 364 | |
---|
.. | .. |
---|
381 | 391 | s8 __percpu *p = pcp->vm_stat_diff + item; |
---|
382 | 392 | s8 v, t; |
---|
383 | 393 | |
---|
| 394 | + preempt_disable_rt(); |
---|
384 | 395 | v = __this_cpu_inc_return(*p); |
---|
385 | 396 | t = __this_cpu_read(pcp->stat_threshold); |
---|
386 | 397 | if (unlikely(v > t)) { |
---|
.. | .. |
---|
389 | 400 | zone_page_state_add(v + overstep, zone, item); |
---|
390 | 401 | __this_cpu_write(*p, -overstep); |
---|
391 | 402 | } |
---|
| 403 | + preempt_enable_rt(); |
---|
392 | 404 | } |
---|
393 | 405 | |
---|
394 | 406 | void __inc_node_state(struct pglist_data *pgdat, enum node_stat_item item) |
---|
.. | .. |
---|
397 | 409 | s8 __percpu *p = pcp->vm_node_stat_diff + item; |
---|
398 | 410 | s8 v, t; |
---|
399 | 411 | |
---|
| 412 | + VM_WARN_ON_ONCE(vmstat_item_in_bytes(item)); |
---|
| 413 | + |
---|
| 414 | + preempt_disable_rt(); |
---|
400 | 415 | v = __this_cpu_inc_return(*p); |
---|
401 | 416 | t = __this_cpu_read(pcp->stat_threshold); |
---|
402 | 417 | if (unlikely(v > t)) { |
---|
.. | .. |
---|
405 | 420 | node_page_state_add(v + overstep, pgdat, item); |
---|
406 | 421 | __this_cpu_write(*p, -overstep); |
---|
407 | 422 | } |
---|
| 423 | + preempt_enable_rt(); |
---|
408 | 424 | } |
---|
409 | 425 | |
---|
410 | 426 | void __inc_zone_page_state(struct page *page, enum zone_stat_item item) |
---|
.. | .. |
---|
425 | 441 | s8 __percpu *p = pcp->vm_stat_diff + item; |
---|
426 | 442 | s8 v, t; |
---|
427 | 443 | |
---|
| 444 | + preempt_disable_rt(); |
---|
428 | 445 | v = __this_cpu_dec_return(*p); |
---|
429 | 446 | t = __this_cpu_read(pcp->stat_threshold); |
---|
430 | 447 | if (unlikely(v < - t)) { |
---|
.. | .. |
---|
433 | 450 | zone_page_state_add(v - overstep, zone, item); |
---|
434 | 451 | __this_cpu_write(*p, overstep); |
---|
435 | 452 | } |
---|
| 453 | + preempt_enable_rt(); |
---|
436 | 454 | } |
---|
437 | 455 | |
---|
438 | 456 | void __dec_node_state(struct pglist_data *pgdat, enum node_stat_item item) |
---|
.. | .. |
---|
441 | 459 | s8 __percpu *p = pcp->vm_node_stat_diff + item; |
---|
442 | 460 | s8 v, t; |
---|
443 | 461 | |
---|
| 462 | + VM_WARN_ON_ONCE(vmstat_item_in_bytes(item)); |
---|
| 463 | + |
---|
| 464 | + preempt_disable_rt(); |
---|
444 | 465 | v = __this_cpu_dec_return(*p); |
---|
445 | 466 | t = __this_cpu_read(pcp->stat_threshold); |
---|
446 | 467 | if (unlikely(v < - t)) { |
---|
.. | .. |
---|
449 | 470 | node_page_state_add(v - overstep, pgdat, item); |
---|
450 | 471 | __this_cpu_write(*p, overstep); |
---|
451 | 472 | } |
---|
| 473 | + preempt_enable_rt(); |
---|
452 | 474 | } |
---|
453 | 475 | |
---|
454 | 476 | void __dec_zone_page_state(struct page *page, enum zone_stat_item item) |
---|
.. | .. |
---|
501 | 523 | o = this_cpu_read(*p); |
---|
502 | 524 | n = delta + o; |
---|
503 | 525 | |
---|
504 | | - if (n > t || n < -t) { |
---|
| 526 | + if (abs(n) > t) { |
---|
505 | 527 | int os = overstep_mode * (t >> 1) ; |
---|
506 | 528 | |
---|
507 | 529 | /* Overflow must be added to zone counters */ |
---|
.. | .. |
---|
540 | 562 | s8 __percpu *p = pcp->vm_node_stat_diff + item; |
---|
541 | 563 | long o, n, t, z; |
---|
542 | 564 | |
---|
| 565 | + if (vmstat_item_in_bytes(item)) { |
---|
| 566 | + VM_WARN_ON_ONCE(delta & (PAGE_SIZE - 1)); |
---|
| 567 | + delta >>= PAGE_SHIFT; |
---|
| 568 | + } |
---|
| 569 | + |
---|
543 | 570 | do { |
---|
544 | 571 | z = 0; /* overflow to node counters */ |
---|
545 | 572 | |
---|
.. | .. |
---|
558 | 585 | o = this_cpu_read(*p); |
---|
559 | 586 | n = delta + o; |
---|
560 | 587 | |
---|
561 | | - if (n > t || n < -t) { |
---|
| 588 | + if (abs(n) > t) { |
---|
562 | 589 | int os = overstep_mode * (t >> 1) ; |
---|
563 | 590 | |
---|
564 | 591 | /* Overflow must be added to node counters */ |
---|
.. | .. |
---|
988 | 1015 | /* |
---|
989 | 1016 | * Determine the per node value of a stat item. |
---|
990 | 1017 | */ |
---|
991 | | -unsigned long node_page_state(struct pglist_data *pgdat, |
---|
992 | | - enum node_stat_item item) |
---|
| 1018 | +unsigned long node_page_state_pages(struct pglist_data *pgdat, |
---|
| 1019 | + enum node_stat_item item) |
---|
993 | 1020 | { |
---|
994 | 1021 | long x = atomic_long_read(&pgdat->vm_stat[item]); |
---|
995 | 1022 | #ifdef CONFIG_SMP |
---|
.. | .. |
---|
997 | 1024 | x = 0; |
---|
998 | 1025 | #endif |
---|
999 | 1026 | return x; |
---|
| 1027 | +} |
---|
| 1028 | + |
---|
| 1029 | +unsigned long node_page_state(struct pglist_data *pgdat, |
---|
| 1030 | + enum node_stat_item item) |
---|
| 1031 | +{ |
---|
| 1032 | + VM_WARN_ON_ONCE(vmstat_item_in_bytes(item)); |
---|
| 1033 | + |
---|
| 1034 | + return node_page_state_pages(pgdat, item); |
---|
1000 | 1035 | } |
---|
1001 | 1036 | #endif |
---|
1002 | 1037 | |
---|
.. | .. |
---|
1073 | 1108 | return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total); |
---|
1074 | 1109 | } |
---|
1075 | 1110 | |
---|
| 1111 | +/* |
---|
| 1112 | + * Calculates external fragmentation within a zone wrt the given order. |
---|
| 1113 | + * It is defined as the percentage of pages found in blocks of size |
---|
| 1114 | + * less than 1 << order. It returns values in range [0, 100]. |
---|
| 1115 | + */ |
---|
| 1116 | +unsigned int extfrag_for_order(struct zone *zone, unsigned int order) |
---|
| 1117 | +{ |
---|
| 1118 | + struct contig_page_info info; |
---|
| 1119 | + |
---|
| 1120 | + fill_contig_page_info(zone, order, &info); |
---|
| 1121 | + if (info.free_pages == 0) |
---|
| 1122 | + return 0; |
---|
| 1123 | + |
---|
| 1124 | + return div_u64((info.free_pages - |
---|
| 1125 | + (info.free_blocks_suitable << order)) * 100, |
---|
| 1126 | + info.free_pages); |
---|
| 1127 | +} |
---|
| 1128 | + |
---|
1076 | 1129 | /* Same as __fragmentation index but allocs contig_page_info on stack */ |
---|
1077 | 1130 | int fragmentation_index(struct zone *zone, unsigned int order) |
---|
1078 | 1131 | { |
---|
.. | .. |
---|
1083 | 1136 | } |
---|
1084 | 1137 | #endif |
---|
1085 | 1138 | |
---|
1086 | | -#if defined(CONFIG_PROC_FS) || defined(CONFIG_SYSFS) || defined(CONFIG_NUMA) |
---|
| 1139 | +#if defined(CONFIG_PROC_FS) || defined(CONFIG_SYSFS) || \ |
---|
| 1140 | + defined(CONFIG_NUMA) || defined(CONFIG_MEMCG) |
---|
1087 | 1141 | #ifdef CONFIG_ZONE_DMA |
---|
1088 | 1142 | #define TEXT_FOR_DMA(xx) xx "_dma", |
---|
1089 | 1143 | #else |
---|
.. | .. |
---|
1106 | 1160 | TEXT_FOR_HIGHMEM(xx) xx "_movable", |
---|
1107 | 1161 | |
---|
1108 | 1162 | const char * const vmstat_text[] = { |
---|
1109 | | - /* enum zone_stat_item countes */ |
---|
| 1163 | + /* enum zone_stat_item counters */ |
---|
1110 | 1164 | "nr_free_pages", |
---|
1111 | 1165 | "nr_zone_inactive_anon", |
---|
1112 | 1166 | "nr_zone_active_anon", |
---|
.. | .. |
---|
1116 | 1170 | "nr_zone_write_pending", |
---|
1117 | 1171 | "nr_mlock", |
---|
1118 | 1172 | "nr_page_table_pages", |
---|
1119 | | - "nr_kernel_stack", |
---|
1120 | | -#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) |
---|
1121 | | - "nr_shadow_call_stack_bytes", |
---|
1122 | | -#endif |
---|
1123 | 1173 | "nr_bounce", |
---|
1124 | | -#if IS_ENABLED(CONFIG_ZSMALLOC) |
---|
1125 | 1174 | "nr_zspages", |
---|
1126 | | -#endif |
---|
1127 | 1175 | "nr_free_cma", |
---|
1128 | 1176 | |
---|
1129 | 1177 | /* enum numa_stat_item counters */ |
---|
.. | .. |
---|
1136 | 1184 | "numa_other", |
---|
1137 | 1185 | #endif |
---|
1138 | 1186 | |
---|
1139 | | - /* Node-based counters */ |
---|
| 1187 | + /* enum node_stat_item counters */ |
---|
1140 | 1188 | "nr_inactive_anon", |
---|
1141 | 1189 | "nr_active_anon", |
---|
1142 | 1190 | "nr_inactive_file", |
---|
.. | .. |
---|
1146 | 1194 | "nr_slab_unreclaimable", |
---|
1147 | 1195 | "nr_isolated_anon", |
---|
1148 | 1196 | "nr_isolated_file", |
---|
1149 | | - "workingset_refault", |
---|
1150 | | - "workingset_activate", |
---|
1151 | | - "workingset_restore", |
---|
| 1197 | + "workingset_nodes", |
---|
| 1198 | + "workingset_refault_anon", |
---|
| 1199 | + "workingset_refault_file", |
---|
| 1200 | + "workingset_activate_anon", |
---|
| 1201 | + "workingset_activate_file", |
---|
| 1202 | + "workingset_restore_anon", |
---|
| 1203 | + "workingset_restore_file", |
---|
1152 | 1204 | "workingset_nodereclaim", |
---|
1153 | 1205 | "nr_anon_pages", |
---|
1154 | 1206 | "nr_mapped", |
---|
.. | .. |
---|
1159 | 1211 | "nr_shmem", |
---|
1160 | 1212 | "nr_shmem_hugepages", |
---|
1161 | 1213 | "nr_shmem_pmdmapped", |
---|
| 1214 | + "nr_file_hugepages", |
---|
| 1215 | + "nr_file_pmdmapped", |
---|
1162 | 1216 | "nr_anon_transparent_hugepages", |
---|
1163 | | - "nr_unstable", |
---|
1164 | 1217 | "nr_vmscan_write", |
---|
1165 | 1218 | "nr_vmscan_immediate_reclaim", |
---|
1166 | 1219 | "nr_dirtied", |
---|
1167 | 1220 | "nr_written", |
---|
1168 | 1221 | "nr_kernel_misc_reclaimable", |
---|
1169 | | - "nr_unreclaimable_pages", |
---|
| 1222 | + "nr_foll_pin_acquired", |
---|
| 1223 | + "nr_foll_pin_released", |
---|
| 1224 | + "nr_kernel_stack", |
---|
| 1225 | +#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) |
---|
| 1226 | + "nr_shadow_call_stack", |
---|
| 1227 | +#endif |
---|
1170 | 1228 | |
---|
1171 | | - |
---|
1172 | | - "nr_ion_heap", |
---|
1173 | | - "nr_ion_heap_pool", |
---|
1174 | | - "nr_gpu_heap", |
---|
1175 | 1229 | /* enum writeback_stat_item counters */ |
---|
1176 | 1230 | "nr_dirty_threshold", |
---|
1177 | 1231 | "nr_dirty_background_threshold", |
---|
1178 | 1232 | |
---|
1179 | | -#ifdef CONFIG_VM_EVENT_COUNTERS |
---|
| 1233 | +#if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG) |
---|
1180 | 1234 | /* enum vm_event_item counters */ |
---|
1181 | 1235 | "pgpgin", |
---|
1182 | 1236 | "pgpgout", |
---|
1183 | | - "pgpgoutclean", |
---|
1184 | 1237 | "pswpin", |
---|
1185 | 1238 | "pswpout", |
---|
1186 | 1239 | |
---|
.. | .. |
---|
1198 | 1251 | "pglazyfreed", |
---|
1199 | 1252 | |
---|
1200 | 1253 | "pgrefill", |
---|
| 1254 | + "pgreuse", |
---|
1201 | 1255 | "pgsteal_kswapd", |
---|
1202 | 1256 | "pgsteal_direct", |
---|
1203 | 1257 | "pgscan_kswapd", |
---|
1204 | 1258 | "pgscan_direct", |
---|
1205 | 1259 | "pgscan_direct_throttle", |
---|
| 1260 | + "pgscan_anon", |
---|
| 1261 | + "pgscan_file", |
---|
| 1262 | + "pgsteal_anon", |
---|
| 1263 | + "pgsteal_file", |
---|
1206 | 1264 | |
---|
1207 | 1265 | #ifdef CONFIG_NUMA |
---|
1208 | 1266 | "zone_reclaim_failed", |
---|
.. | .. |
---|
1230 | 1288 | #ifdef CONFIG_MIGRATION |
---|
1231 | 1289 | "pgmigrate_success", |
---|
1232 | 1290 | "pgmigrate_fail", |
---|
| 1291 | + "thp_migration_success", |
---|
| 1292 | + "thp_migration_fail", |
---|
| 1293 | + "thp_migration_split", |
---|
1233 | 1294 | #endif |
---|
1234 | 1295 | #ifdef CONFIG_COMPACTION |
---|
1235 | 1296 | "compact_migrate_scanned", |
---|
.. | .. |
---|
1247 | 1308 | "htlb_buddy_alloc_success", |
---|
1248 | 1309 | "htlb_buddy_alloc_fail", |
---|
1249 | 1310 | #endif |
---|
| 1311 | +#ifdef CONFIG_CMA |
---|
| 1312 | + "cma_alloc_success", |
---|
| 1313 | + "cma_alloc_fail", |
---|
| 1314 | +#endif |
---|
1250 | 1315 | "unevictable_pgs_culled", |
---|
1251 | 1316 | "unevictable_pgs_scanned", |
---|
1252 | 1317 | "unevictable_pgs_rescued", |
---|
.. | .. |
---|
1258 | 1323 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
---|
1259 | 1324 | "thp_fault_alloc", |
---|
1260 | 1325 | "thp_fault_fallback", |
---|
| 1326 | + "thp_fault_fallback_charge", |
---|
1261 | 1327 | "thp_collapse_alloc", |
---|
1262 | 1328 | "thp_collapse_alloc_failed", |
---|
1263 | 1329 | "thp_file_alloc", |
---|
| 1330 | + "thp_file_fallback", |
---|
| 1331 | + "thp_file_fallback_charge", |
---|
1264 | 1332 | "thp_file_mapped", |
---|
1265 | 1333 | "thp_split_page", |
---|
1266 | 1334 | "thp_split_page_failed", |
---|
.. | .. |
---|
1296 | 1364 | "swap_ra", |
---|
1297 | 1365 | "swap_ra_hit", |
---|
1298 | 1366 | #endif |
---|
1299 | | -#endif /* CONFIG_VM_EVENTS_COUNTERS */ |
---|
| 1367 | +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT |
---|
| 1368 | + "speculative_pgfault", |
---|
| 1369 | + "speculative_pgfault_file" |
---|
| 1370 | +#endif |
---|
| 1371 | +#endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */ |
---|
1300 | 1372 | }; |
---|
1301 | | -#endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA */ |
---|
| 1373 | +#endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA || CONFIG_MEMCG */ |
---|
1302 | 1374 | |
---|
1303 | 1375 | #if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)) || \ |
---|
1304 | 1376 | defined(CONFIG_PROC_FS) |
---|
.. | .. |
---|
1388 | 1460 | unsigned long freecount = 0; |
---|
1389 | 1461 | struct free_area *area; |
---|
1390 | 1462 | struct list_head *curr; |
---|
| 1463 | + bool overflow = false; |
---|
1391 | 1464 | |
---|
1392 | 1465 | area = &(zone->free_area[order]); |
---|
1393 | 1466 | |
---|
1394 | | - list_for_each(curr, &area->free_list[mtype]) |
---|
1395 | | - freecount++; |
---|
1396 | | - seq_printf(m, "%6lu ", freecount); |
---|
| 1467 | + list_for_each(curr, &area->free_list[mtype]) { |
---|
| 1468 | + /* |
---|
| 1469 | + * Cap the free_list iteration because it might |
---|
| 1470 | + * be really large and we are under a spinlock |
---|
| 1471 | + * so a long time spent here could trigger a |
---|
| 1472 | + * hard lockup detector. Anyway this is a |
---|
| 1473 | + * debugging tool so knowing there is a handful |
---|
| 1474 | + * of pages of this order should be more than |
---|
| 1475 | + * sufficient. |
---|
| 1476 | + */ |
---|
| 1477 | + if (++freecount >= 100000) { |
---|
| 1478 | + overflow = true; |
---|
| 1479 | + break; |
---|
| 1480 | + } |
---|
| 1481 | + } |
---|
| 1482 | + seq_printf(m, "%s%6lu ", overflow ? ">" : "", freecount); |
---|
1397 | 1483 | spin_unlock_irq(&zone->lock); |
---|
1398 | 1484 | cond_resched(); |
---|
1399 | 1485 | spin_lock_irq(&zone->lock); |
---|
.. | .. |
---|
1433 | 1519 | |
---|
1434 | 1520 | page = pfn_to_online_page(pfn); |
---|
1435 | 1521 | if (!page) |
---|
1436 | | - continue; |
---|
1437 | | - |
---|
1438 | | - /* Watch for unexpected holes punched in the memmap */ |
---|
1439 | | - if (!memmap_valid_within(pfn, page, zone)) |
---|
1440 | 1522 | continue; |
---|
1441 | 1523 | |
---|
1442 | 1524 | if (page_zone(page) != zone) |
---|
.. | .. |
---|
1555 | 1637 | if (is_zone_first_populated(pgdat, zone)) { |
---|
1556 | 1638 | seq_printf(m, "\n per-node stats"); |
---|
1557 | 1639 | for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) { |
---|
1558 | | - /* Skip hidden vmstat items. */ |
---|
1559 | | - if (*vmstat_text[i + NR_VM_ZONE_STAT_ITEMS + |
---|
1560 | | - NR_VM_NUMA_STAT_ITEMS] == '\0') |
---|
1561 | | - continue; |
---|
1562 | | - seq_printf(m, "\n %-12s %lu", |
---|
1563 | | - vmstat_text[i + NR_VM_ZONE_STAT_ITEMS + |
---|
1564 | | - NR_VM_NUMA_STAT_ITEMS], |
---|
1565 | | - node_page_state(pgdat, i)); |
---|
| 1640 | + seq_printf(m, "\n %-12s %lu", node_stat_name(i), |
---|
| 1641 | + node_page_state_pages(pgdat, i)); |
---|
1566 | 1642 | } |
---|
1567 | 1643 | } |
---|
1568 | 1644 | seq_printf(m, |
---|
.. | .. |
---|
1572 | 1648 | "\n high %lu" |
---|
1573 | 1649 | "\n spanned %lu" |
---|
1574 | 1650 | "\n present %lu" |
---|
1575 | | - "\n managed %lu", |
---|
| 1651 | + "\n managed %lu" |
---|
| 1652 | + "\n cma %lu", |
---|
1576 | 1653 | zone_page_state(zone, NR_FREE_PAGES), |
---|
1577 | 1654 | min_wmark_pages(zone), |
---|
1578 | 1655 | low_wmark_pages(zone), |
---|
1579 | 1656 | high_wmark_pages(zone), |
---|
1580 | 1657 | zone->spanned_pages, |
---|
1581 | 1658 | zone->present_pages, |
---|
1582 | | - zone->managed_pages); |
---|
| 1659 | + zone_managed_pages(zone), |
---|
| 1660 | + zone_cma_pages(zone)); |
---|
1583 | 1661 | |
---|
1584 | 1662 | seq_printf(m, |
---|
1585 | 1663 | "\n protection: (%ld", |
---|
.. | .. |
---|
1595 | 1673 | } |
---|
1596 | 1674 | |
---|
1597 | 1675 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) |
---|
1598 | | - seq_printf(m, "\n %-12s %lu", vmstat_text[i], |
---|
1599 | | - zone_page_state(zone, i)); |
---|
| 1676 | + seq_printf(m, "\n %-12s %lu", zone_stat_name(i), |
---|
| 1677 | + zone_page_state(zone, i)); |
---|
1600 | 1678 | |
---|
1601 | 1679 | #ifdef CONFIG_NUMA |
---|
1602 | 1680 | for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++) |
---|
1603 | | - seq_printf(m, "\n %-12s %lu", |
---|
1604 | | - vmstat_text[i + NR_VM_ZONE_STAT_ITEMS], |
---|
1605 | | - zone_numa_state_snapshot(zone, i)); |
---|
| 1681 | + seq_printf(m, "\n %-12s %lu", numa_stat_name(i), |
---|
| 1682 | + zone_numa_state_snapshot(zone, i)); |
---|
1606 | 1683 | #endif |
---|
1607 | 1684 | |
---|
1608 | 1685 | seq_printf(m, "\n pagesets"); |
---|
.. | .. |
---|
1653 | 1730 | .show = zoneinfo_show, |
---|
1654 | 1731 | }; |
---|
1655 | 1732 | |
---|
1656 | | -enum writeback_stat_item { |
---|
1657 | | - NR_DIRTY_THRESHOLD, |
---|
1658 | | - NR_DIRTY_BG_THRESHOLD, |
---|
1659 | | - NR_VM_WRITEBACK_STAT_ITEMS, |
---|
1660 | | -}; |
---|
| 1733 | +#define NR_VMSTAT_ITEMS (NR_VM_ZONE_STAT_ITEMS + \ |
---|
| 1734 | + NR_VM_NUMA_STAT_ITEMS + \ |
---|
| 1735 | + NR_VM_NODE_STAT_ITEMS + \ |
---|
| 1736 | + NR_VM_WRITEBACK_STAT_ITEMS + \ |
---|
| 1737 | + (IS_ENABLED(CONFIG_VM_EVENT_COUNTERS) ? \ |
---|
| 1738 | + NR_VM_EVENT_ITEMS : 0)) |
---|
1661 | 1739 | |
---|
1662 | 1740 | static void *vmstat_start(struct seq_file *m, loff_t *pos) |
---|
1663 | 1741 | { |
---|
1664 | 1742 | unsigned long *v; |
---|
1665 | | - int i, stat_items_size; |
---|
| 1743 | + int i; |
---|
1666 | 1744 | |
---|
1667 | | - if (*pos >= ARRAY_SIZE(vmstat_text)) |
---|
| 1745 | + if (*pos >= NR_VMSTAT_ITEMS) |
---|
1668 | 1746 | return NULL; |
---|
1669 | | - stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) + |
---|
1670 | | - NR_VM_NUMA_STAT_ITEMS * sizeof(unsigned long) + |
---|
1671 | | - NR_VM_NODE_STAT_ITEMS * sizeof(unsigned long) + |
---|
1672 | | - NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long); |
---|
1673 | 1747 | |
---|
1674 | | -#ifdef CONFIG_VM_EVENT_COUNTERS |
---|
1675 | | - stat_items_size += sizeof(struct vm_event_state); |
---|
1676 | | -#endif |
---|
1677 | | - |
---|
1678 | | - v = kmalloc(stat_items_size, GFP_KERNEL); |
---|
| 1748 | + BUILD_BUG_ON(ARRAY_SIZE(vmstat_text) < NR_VMSTAT_ITEMS); |
---|
| 1749 | + v = kmalloc_array(NR_VMSTAT_ITEMS, sizeof(unsigned long), GFP_KERNEL); |
---|
1679 | 1750 | m->private = v; |
---|
1680 | 1751 | if (!v) |
---|
1681 | 1752 | return ERR_PTR(-ENOMEM); |
---|
.. | .. |
---|
1690 | 1761 | #endif |
---|
1691 | 1762 | |
---|
1692 | 1763 | for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) |
---|
1693 | | - v[i] = global_node_page_state(i); |
---|
| 1764 | + v[i] = global_node_page_state_pages(i); |
---|
1694 | 1765 | v += NR_VM_NODE_STAT_ITEMS; |
---|
1695 | 1766 | |
---|
1696 | 1767 | global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD, |
---|
.. | .. |
---|
1708 | 1779 | static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) |
---|
1709 | 1780 | { |
---|
1710 | 1781 | (*pos)++; |
---|
1711 | | - //nr_gpu_heap is out-of-tree now so we don't want to export it. |
---|
1712 | | - if (*pos == NR_VM_ZONE_STAT_ITEMS + NR_VM_NUMA_STAT_ITEMS + NR_GPU_HEAP) |
---|
1713 | | - (*pos)++; |
---|
1714 | | - if (*pos >= ARRAY_SIZE(vmstat_text)) |
---|
| 1782 | + if (*pos >= NR_VMSTAT_ITEMS) |
---|
1715 | 1783 | return NULL; |
---|
1716 | 1784 | return (unsigned long *)m->private + *pos; |
---|
1717 | 1785 | } |
---|
.. | .. |
---|
1724 | 1792 | seq_puts(m, vmstat_text[off]); |
---|
1725 | 1793 | seq_put_decimal_ull(m, " ", *l); |
---|
1726 | 1794 | seq_putc(m, '\n'); |
---|
| 1795 | + |
---|
| 1796 | + if (off == NR_VMSTAT_ITEMS - 1) { |
---|
| 1797 | + /* |
---|
| 1798 | + * We've come to the end - add any deprecated counters to avoid |
---|
| 1799 | + * breaking userspace which might depend on them being present. |
---|
| 1800 | + */ |
---|
| 1801 | + seq_puts(m, "nr_unstable 0\n"); |
---|
| 1802 | + } |
---|
1727 | 1803 | return 0; |
---|
1728 | 1804 | } |
---|
1729 | 1805 | |
---|
.. | .. |
---|
1752 | 1828 | } |
---|
1753 | 1829 | |
---|
1754 | 1830 | int vmstat_refresh(struct ctl_table *table, int write, |
---|
1755 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
---|
| 1831 | + void *buffer, size_t *lenp, loff_t *ppos) |
---|
1756 | 1832 | { |
---|
1757 | 1833 | long val; |
---|
1758 | 1834 | int err; |
---|
.. | .. |
---|
1777 | 1853 | val = atomic_long_read(&vm_zone_stat[i]); |
---|
1778 | 1854 | if (val < 0) { |
---|
1779 | 1855 | pr_warn("%s: %s %ld\n", |
---|
1780 | | - __func__, vmstat_text[i], val); |
---|
| 1856 | + __func__, zone_stat_name(i), val); |
---|
1781 | 1857 | err = -EINVAL; |
---|
1782 | 1858 | } |
---|
1783 | 1859 | } |
---|
.. | .. |
---|
1786 | 1862 | val = atomic_long_read(&vm_numa_stat[i]); |
---|
1787 | 1863 | if (val < 0) { |
---|
1788 | 1864 | pr_warn("%s: %s %ld\n", |
---|
1789 | | - __func__, vmstat_text[i + NR_VM_ZONE_STAT_ITEMS], val); |
---|
| 1865 | + __func__, numa_stat_name(i), val); |
---|
1790 | 1866 | err = -EINVAL; |
---|
1791 | 1867 | } |
---|
1792 | 1868 | } |
---|
.. | .. |
---|
2056 | 2132 | return 0; |
---|
2057 | 2133 | } |
---|
2058 | 2134 | |
---|
2059 | | -static const struct seq_operations unusable_op = { |
---|
| 2135 | +static const struct seq_operations unusable_sops = { |
---|
2060 | 2136 | .start = frag_start, |
---|
2061 | 2137 | .next = frag_next, |
---|
2062 | 2138 | .stop = frag_stop, |
---|
2063 | 2139 | .show = unusable_show, |
---|
2064 | 2140 | }; |
---|
2065 | 2141 | |
---|
2066 | | -static int unusable_open(struct inode *inode, struct file *file) |
---|
2067 | | -{ |
---|
2068 | | - return seq_open(file, &unusable_op); |
---|
2069 | | -} |
---|
2070 | | - |
---|
2071 | | -static const struct file_operations unusable_file_ops = { |
---|
2072 | | - .open = unusable_open, |
---|
2073 | | - .read = seq_read, |
---|
2074 | | - .llseek = seq_lseek, |
---|
2075 | | - .release = seq_release, |
---|
2076 | | -}; |
---|
| 2142 | +DEFINE_SEQ_ATTRIBUTE(unusable); |
---|
2077 | 2143 | |
---|
2078 | 2144 | static void extfrag_show_print(struct seq_file *m, |
---|
2079 | 2145 | pg_data_t *pgdat, struct zone *zone) |
---|
.. | .. |
---|
2108 | 2174 | return 0; |
---|
2109 | 2175 | } |
---|
2110 | 2176 | |
---|
2111 | | -static const struct seq_operations extfrag_op = { |
---|
| 2177 | +static const struct seq_operations extfrag_sops = { |
---|
2112 | 2178 | .start = frag_start, |
---|
2113 | 2179 | .next = frag_next, |
---|
2114 | 2180 | .stop = frag_stop, |
---|
2115 | 2181 | .show = extfrag_show, |
---|
2116 | 2182 | }; |
---|
2117 | 2183 | |
---|
2118 | | -static int extfrag_open(struct inode *inode, struct file *file) |
---|
2119 | | -{ |
---|
2120 | | - return seq_open(file, &extfrag_op); |
---|
2121 | | -} |
---|
2122 | | - |
---|
2123 | | -static const struct file_operations extfrag_file_ops = { |
---|
2124 | | - .open = extfrag_open, |
---|
2125 | | - .read = seq_read, |
---|
2126 | | - .llseek = seq_lseek, |
---|
2127 | | - .release = seq_release, |
---|
2128 | | -}; |
---|
| 2184 | +DEFINE_SEQ_ATTRIBUTE(extfrag); |
---|
2129 | 2185 | |
---|
2130 | 2186 | static int __init extfrag_debug_init(void) |
---|
2131 | 2187 | { |
---|
2132 | 2188 | struct dentry *extfrag_debug_root; |
---|
2133 | 2189 | |
---|
2134 | 2190 | extfrag_debug_root = debugfs_create_dir("extfrag", NULL); |
---|
2135 | | - if (!extfrag_debug_root) |
---|
2136 | | - return -ENOMEM; |
---|
2137 | 2191 | |
---|
2138 | | - if (!debugfs_create_file("unusable_index", 0444, |
---|
2139 | | - extfrag_debug_root, NULL, &unusable_file_ops)) |
---|
2140 | | - goto fail; |
---|
| 2192 | + debugfs_create_file("unusable_index", 0444, extfrag_debug_root, NULL, |
---|
| 2193 | + &unusable_fops); |
---|
2141 | 2194 | |
---|
2142 | | - if (!debugfs_create_file("extfrag_index", 0444, |
---|
2143 | | - extfrag_debug_root, NULL, &extfrag_file_ops)) |
---|
2144 | | - goto fail; |
---|
| 2195 | + debugfs_create_file("extfrag_index", 0444, extfrag_debug_root, NULL, |
---|
| 2196 | + &extfrag_fops); |
---|
2145 | 2197 | |
---|
2146 | 2198 | return 0; |
---|
2147 | | -fail: |
---|
2148 | | - debugfs_remove_recursive(extfrag_debug_root); |
---|
2149 | | - return -ENOMEM; |
---|
2150 | 2199 | } |
---|
2151 | 2200 | |
---|
2152 | 2201 | module_init(extfrag_debug_init); |
---|