at v6.11 17 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_VMSTAT_H 3#define _LINUX_VMSTAT_H 4 5#include <linux/types.h> 6#include <linux/percpu.h> 7#include <linux/mmzone.h> 8#include <linux/vm_event_item.h> 9#include <linux/atomic.h> 10#include <linux/static_key.h> 11#include <linux/mmdebug.h> 12 13extern int sysctl_stat_interval; 14 15#ifdef CONFIG_NUMA 16#define ENABLE_NUMA_STAT 1 17#define DISABLE_NUMA_STAT 0 18extern int sysctl_vm_numa_stat; 19DECLARE_STATIC_KEY_TRUE(vm_numa_stat_key); 20int sysctl_vm_numa_stat_handler(const struct ctl_table *table, int write, 21 void *buffer, size_t *length, loff_t *ppos); 22#endif 23 24struct reclaim_stat { 25 unsigned nr_dirty; 26 unsigned nr_unqueued_dirty; 27 unsigned nr_congested; 28 unsigned nr_writeback; 29 unsigned nr_immediate; 30 unsigned nr_pageout; 31 unsigned nr_activate[ANON_AND_FILE]; 32 unsigned nr_ref_keep; 33 unsigned nr_unmap_fail; 34 unsigned nr_lazyfree_fail; 35}; 36 37/* Stat data for system wide items */ 38enum vm_stat_item { 39 NR_DIRTY_THRESHOLD, 40 NR_DIRTY_BG_THRESHOLD, 41 NR_MEMMAP_PAGES, /* page metadata allocated through buddy allocator */ 42 NR_MEMMAP_BOOT_PAGES, /* page metadata allocated through boot allocator */ 43 NR_VM_STAT_ITEMS, 44}; 45 46#ifdef CONFIG_VM_EVENT_COUNTERS 47/* 48 * Light weight per cpu counter implementation. 49 * 50 * Counters should only be incremented and no critical kernel component 51 * should rely on the counter values. 52 * 53 * Counters are handled completely inline. On many platforms the code 54 * generated will simply be the increment of a global address. 55 */ 56 57struct vm_event_state { 58 unsigned long event[NR_VM_EVENT_ITEMS]; 59}; 60 61DECLARE_PER_CPU(struct vm_event_state, vm_event_states); 62 63/* 64 * vm counters are allowed to be racy. Use raw_cpu_ops to avoid the 65 * local_irq_disable overhead. 66 */ 67static inline void __count_vm_event(enum vm_event_item item) 68{ 69 raw_cpu_inc(vm_event_states.event[item]); 70} 71 72static inline void count_vm_event(enum vm_event_item item) 73{ 74 this_cpu_inc(vm_event_states.event[item]); 75} 76 77static inline void __count_vm_events(enum vm_event_item item, long delta) 78{ 79 raw_cpu_add(vm_event_states.event[item], delta); 80} 81 82static inline void count_vm_events(enum vm_event_item item, long delta) 83{ 84 this_cpu_add(vm_event_states.event[item], delta); 85} 86 87extern void all_vm_events(unsigned long *); 88 89extern void vm_events_fold_cpu(int cpu); 90 91#else 92 93/* Disable counters */ 94static inline void count_vm_event(enum vm_event_item item) 95{ 96} 97static inline void count_vm_events(enum vm_event_item item, long delta) 98{ 99} 100static inline void __count_vm_event(enum vm_event_item item) 101{ 102} 103static inline void __count_vm_events(enum vm_event_item item, long delta) 104{ 105} 106static inline void all_vm_events(unsigned long *ret) 107{ 108} 109static inline void vm_events_fold_cpu(int cpu) 110{ 111} 112 113#endif /* CONFIG_VM_EVENT_COUNTERS */ 114 115#ifdef CONFIG_NUMA_BALANCING 116#define count_vm_numa_event(x) count_vm_event(x) 117#define count_vm_numa_events(x, y) count_vm_events(x, y) 118#else 119#define count_vm_numa_event(x) do {} while (0) 120#define count_vm_numa_events(x, y) do { (void)(y); } while (0) 121#endif /* CONFIG_NUMA_BALANCING */ 122 123#ifdef CONFIG_DEBUG_TLBFLUSH 124#define count_vm_tlb_event(x) count_vm_event(x) 125#define count_vm_tlb_events(x, y) count_vm_events(x, y) 126#else 127#define count_vm_tlb_event(x) do {} while (0) 128#define count_vm_tlb_events(x, y) do { (void)(y); } while (0) 129#endif 130 131#ifdef CONFIG_PER_VMA_LOCK_STATS 132#define count_vm_vma_lock_event(x) count_vm_event(x) 133#else 134#define count_vm_vma_lock_event(x) do {} while (0) 135#endif 136 137#define __count_zid_vm_events(item, zid, delta) \ 138 __count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta) 139 140/* 141 * Zone and node-based page accounting with per cpu differentials. 142 */ 143extern atomic_long_t vm_zone_stat[NR_VM_ZONE_STAT_ITEMS]; 144extern atomic_long_t vm_node_stat[NR_VM_NODE_STAT_ITEMS]; 145extern atomic_long_t vm_numa_event[NR_VM_NUMA_EVENT_ITEMS]; 146 147#ifdef CONFIG_NUMA 148static inline void zone_numa_event_add(long x, struct zone *zone, 149 enum numa_stat_item item) 150{ 151 atomic_long_add(x, &zone->vm_numa_event[item]); 152 atomic_long_add(x, &vm_numa_event[item]); 153} 154 155static inline unsigned long zone_numa_event_state(struct zone *zone, 156 enum numa_stat_item item) 157{ 158 return atomic_long_read(&zone->vm_numa_event[item]); 159} 160 161static inline unsigned long 162global_numa_event_state(enum numa_stat_item item) 163{ 164 return atomic_long_read(&vm_numa_event[item]); 165} 166#endif /* CONFIG_NUMA */ 167 168static inline void zone_page_state_add(long x, struct zone *zone, 169 enum zone_stat_item item) 170{ 171 atomic_long_add(x, &zone->vm_stat[item]); 172 atomic_long_add(x, &vm_zone_stat[item]); 173} 174 175static inline void node_page_state_add(long x, struct pglist_data *pgdat, 176 enum node_stat_item item) 177{ 178 atomic_long_add(x, &pgdat->vm_stat[item]); 179 atomic_long_add(x, &vm_node_stat[item]); 180} 181 182static inline unsigned long global_zone_page_state(enum zone_stat_item item) 183{ 184 long x = atomic_long_read(&vm_zone_stat[item]); 185#ifdef CONFIG_SMP 186 if (x < 0) 187 x = 0; 188#endif 189 return x; 190} 191 192static inline 193unsigned long global_node_page_state_pages(enum node_stat_item item) 194{ 195 long x = atomic_long_read(&vm_node_stat[item]); 196#ifdef CONFIG_SMP 197 if (x < 0) 198 x = 0; 199#endif 200 return x; 201} 202 203static inline unsigned long global_node_page_state(enum node_stat_item item) 204{ 205 VM_WARN_ON_ONCE(vmstat_item_in_bytes(item)); 206 207 return global_node_page_state_pages(item); 208} 209 210static inline unsigned long zone_page_state(struct zone *zone, 211 enum zone_stat_item item) 212{ 213 long x = atomic_long_read(&zone->vm_stat[item]); 214#ifdef CONFIG_SMP 215 if (x < 0) 216 x = 0; 217#endif 218 return x; 219} 220 221/* 222 * More accurate version that also considers the currently pending 223 * deltas. For that we need to loop over all cpus to find the current 224 * deltas. There is no synchronization so the result cannot be 225 * exactly accurate either. 226 */ 227static inline unsigned long zone_page_state_snapshot(struct zone *zone, 228 enum zone_stat_item item) 229{ 230 long x = atomic_long_read(&zone->vm_stat[item]); 231 232#ifdef CONFIG_SMP 233 int cpu; 234 for_each_online_cpu(cpu) 235 x += per_cpu_ptr(zone->per_cpu_zonestats, cpu)->vm_stat_diff[item]; 236 237 if (x < 0) 238 x = 0; 239#endif 240 return x; 241} 242 243#ifdef CONFIG_NUMA 244/* See __count_vm_event comment on why raw_cpu_inc is used. */ 245static inline void 246__count_numa_event(struct zone *zone, enum numa_stat_item item) 247{ 248 struct per_cpu_zonestat __percpu *pzstats = zone->per_cpu_zonestats; 249 250 raw_cpu_inc(pzstats->vm_numa_event[item]); 251} 252 253static inline void 254__count_numa_events(struct zone *zone, enum numa_stat_item item, long delta) 255{ 256 struct per_cpu_zonestat __percpu *pzstats = zone->per_cpu_zonestats; 257 258 raw_cpu_add(pzstats->vm_numa_event[item], delta); 259} 260 261extern unsigned long sum_zone_node_page_state(int node, 262 enum zone_stat_item item); 263extern unsigned long sum_zone_numa_event_state(int node, enum numa_stat_item item); 264extern unsigned long node_page_state(struct pglist_data *pgdat, 265 enum node_stat_item item); 266extern unsigned long node_page_state_pages(struct pglist_data *pgdat, 267 enum node_stat_item item); 268extern void fold_vm_numa_events(void); 269#else 270#define sum_zone_node_page_state(node, item) global_zone_page_state(item) 271#define node_page_state(node, item) global_node_page_state(item) 272#define node_page_state_pages(node, item) global_node_page_state_pages(item) 273static inline void fold_vm_numa_events(void) 274{ 275} 276#endif /* CONFIG_NUMA */ 277 278#ifdef CONFIG_SMP 279void __mod_zone_page_state(struct zone *, enum zone_stat_item item, long); 280void __inc_zone_page_state(struct page *, enum zone_stat_item); 281void __dec_zone_page_state(struct page *, enum zone_stat_item); 282 283void __mod_node_page_state(struct pglist_data *, enum node_stat_item item, long); 284void __inc_node_page_state(struct page *, enum node_stat_item); 285void __dec_node_page_state(struct page *, enum node_stat_item); 286 287void mod_zone_page_state(struct zone *, enum zone_stat_item, long); 288void inc_zone_page_state(struct page *, enum zone_stat_item); 289void dec_zone_page_state(struct page *, enum zone_stat_item); 290 291void mod_node_page_state(struct pglist_data *, enum node_stat_item, long); 292void inc_node_page_state(struct page *, enum node_stat_item); 293void dec_node_page_state(struct page *, enum node_stat_item); 294 295extern void inc_node_state(struct pglist_data *, enum node_stat_item); 296extern void __inc_zone_state(struct zone *, enum zone_stat_item); 297extern void __inc_node_state(struct pglist_data *, enum node_stat_item); 298extern void dec_zone_state(struct zone *, enum zone_stat_item); 299extern void __dec_zone_state(struct zone *, enum zone_stat_item); 300extern void __dec_node_state(struct pglist_data *, enum node_stat_item); 301 302void quiet_vmstat(void); 303void cpu_vm_stats_fold(int cpu); 304void refresh_zone_stat_thresholds(void); 305 306struct ctl_table; 307int vmstat_refresh(const struct ctl_table *, int write, void *buffer, size_t *lenp, 308 loff_t *ppos); 309 310void drain_zonestat(struct zone *zone, struct per_cpu_zonestat *); 311 312int calculate_pressure_threshold(struct zone *zone); 313int calculate_normal_threshold(struct zone *zone); 314void set_pgdat_percpu_threshold(pg_data_t *pgdat, 315 int (*calculate_pressure)(struct zone *)); 316#else /* CONFIG_SMP */ 317 318/* 319 * We do not maintain differentials in a single processor configuration. 320 * The functions directly modify the zone and global counters. 321 */ 322static inline void __mod_zone_page_state(struct zone *zone, 323 enum zone_stat_item item, long delta) 324{ 325 zone_page_state_add(delta, zone, item); 326} 327 328static inline void __mod_node_page_state(struct pglist_data *pgdat, 329 enum node_stat_item item, int delta) 330{ 331 if (vmstat_item_in_bytes(item)) { 332 /* 333 * Only cgroups use subpage accounting right now; at 334 * the global level, these items still change in 335 * multiples of whole pages. Store them as pages 336 * internally to keep the per-cpu counters compact. 337 */ 338 VM_WARN_ON_ONCE(delta & (PAGE_SIZE - 1)); 339 delta >>= PAGE_SHIFT; 340 } 341 342 node_page_state_add(delta, pgdat, item); 343} 344 345static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) 346{ 347 atomic_long_inc(&zone->vm_stat[item]); 348 atomic_long_inc(&vm_zone_stat[item]); 349} 350 351static inline void __inc_node_state(struct pglist_data *pgdat, enum node_stat_item item) 352{ 353 atomic_long_inc(&pgdat->vm_stat[item]); 354 atomic_long_inc(&vm_node_stat[item]); 355} 356 357static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) 358{ 359 atomic_long_dec(&zone->vm_stat[item]); 360 atomic_long_dec(&vm_zone_stat[item]); 361} 362 363static inline void __dec_node_state(struct pglist_data *pgdat, enum node_stat_item item) 364{ 365 atomic_long_dec(&pgdat->vm_stat[item]); 366 atomic_long_dec(&vm_node_stat[item]); 367} 368 369static inline void __inc_zone_page_state(struct page *page, 370 enum zone_stat_item item) 371{ 372 __inc_zone_state(page_zone(page), item); 373} 374 375static inline void __inc_node_page_state(struct page *page, 376 enum node_stat_item item) 377{ 378 __inc_node_state(page_pgdat(page), item); 379} 380 381 382static inline void __dec_zone_page_state(struct page *page, 383 enum zone_stat_item item) 384{ 385 __dec_zone_state(page_zone(page), item); 386} 387 388static inline void __dec_node_page_state(struct page *page, 389 enum node_stat_item item) 390{ 391 __dec_node_state(page_pgdat(page), item); 392} 393 394 395/* 396 * We only use atomic operations to update counters. So there is no need to 397 * disable interrupts. 398 */ 399#define inc_zone_page_state __inc_zone_page_state 400#define dec_zone_page_state __dec_zone_page_state 401#define mod_zone_page_state __mod_zone_page_state 402 403#define inc_node_page_state __inc_node_page_state 404#define dec_node_page_state __dec_node_page_state 405#define mod_node_page_state __mod_node_page_state 406 407#define inc_zone_state __inc_zone_state 408#define inc_node_state __inc_node_state 409#define dec_zone_state __dec_zone_state 410 411#define set_pgdat_percpu_threshold(pgdat, callback) { } 412 413static inline void refresh_zone_stat_thresholds(void) { } 414static inline void cpu_vm_stats_fold(int cpu) { } 415static inline void quiet_vmstat(void) { } 416 417static inline void drain_zonestat(struct zone *zone, 418 struct per_cpu_zonestat *pzstats) { } 419#endif /* CONFIG_SMP */ 420 421static inline void __zone_stat_mod_folio(struct folio *folio, 422 enum zone_stat_item item, long nr) 423{ 424 __mod_zone_page_state(folio_zone(folio), item, nr); 425} 426 427static inline void __zone_stat_add_folio(struct folio *folio, 428 enum zone_stat_item item) 429{ 430 __mod_zone_page_state(folio_zone(folio), item, folio_nr_pages(folio)); 431} 432 433static inline void __zone_stat_sub_folio(struct folio *folio, 434 enum zone_stat_item item) 435{ 436 __mod_zone_page_state(folio_zone(folio), item, -folio_nr_pages(folio)); 437} 438 439static inline void zone_stat_mod_folio(struct folio *folio, 440 enum zone_stat_item item, long nr) 441{ 442 mod_zone_page_state(folio_zone(folio), item, nr); 443} 444 445static inline void zone_stat_add_folio(struct folio *folio, 446 enum zone_stat_item item) 447{ 448 mod_zone_page_state(folio_zone(folio), item, folio_nr_pages(folio)); 449} 450 451static inline void zone_stat_sub_folio(struct folio *folio, 452 enum zone_stat_item item) 453{ 454 mod_zone_page_state(folio_zone(folio), item, -folio_nr_pages(folio)); 455} 456 457static inline void __node_stat_mod_folio(struct folio *folio, 458 enum node_stat_item item, long nr) 459{ 460 __mod_node_page_state(folio_pgdat(folio), item, nr); 461} 462 463static inline void __node_stat_add_folio(struct folio *folio, 464 enum node_stat_item item) 465{ 466 __mod_node_page_state(folio_pgdat(folio), item, folio_nr_pages(folio)); 467} 468 469static inline void __node_stat_sub_folio(struct folio *folio, 470 enum node_stat_item item) 471{ 472 __mod_node_page_state(folio_pgdat(folio), item, -folio_nr_pages(folio)); 473} 474 475static inline void node_stat_mod_folio(struct folio *folio, 476 enum node_stat_item item, long nr) 477{ 478 mod_node_page_state(folio_pgdat(folio), item, nr); 479} 480 481static inline void node_stat_add_folio(struct folio *folio, 482 enum node_stat_item item) 483{ 484 mod_node_page_state(folio_pgdat(folio), item, folio_nr_pages(folio)); 485} 486 487static inline void node_stat_sub_folio(struct folio *folio, 488 enum node_stat_item item) 489{ 490 mod_node_page_state(folio_pgdat(folio), item, -folio_nr_pages(folio)); 491} 492 493extern const char * const vmstat_text[]; 494 495static inline const char *zone_stat_name(enum zone_stat_item item) 496{ 497 return vmstat_text[item]; 498} 499 500#ifdef CONFIG_NUMA 501static inline const char *numa_stat_name(enum numa_stat_item item) 502{ 503 return vmstat_text[NR_VM_ZONE_STAT_ITEMS + 504 item]; 505} 506#endif /* CONFIG_NUMA */ 507 508static inline const char *node_stat_name(enum node_stat_item item) 509{ 510 return vmstat_text[NR_VM_ZONE_STAT_ITEMS + 511 NR_VM_NUMA_EVENT_ITEMS + 512 item]; 513} 514 515static inline const char *lru_list_name(enum lru_list lru) 516{ 517 return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" 518} 519 520#if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG) 521static inline const char *vm_event_name(enum vm_event_item item) 522{ 523 return vmstat_text[NR_VM_ZONE_STAT_ITEMS + 524 NR_VM_NUMA_EVENT_ITEMS + 525 NR_VM_NODE_STAT_ITEMS + 526 NR_VM_STAT_ITEMS + 527 item]; 528} 529#endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */ 530 531#ifdef CONFIG_MEMCG 532 533void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, 534 int val); 535 536static inline void mod_lruvec_state(struct lruvec *lruvec, 537 enum node_stat_item idx, int val) 538{ 539 unsigned long flags; 540 541 local_irq_save(flags); 542 __mod_lruvec_state(lruvec, idx, val); 543 local_irq_restore(flags); 544} 545 546void __lruvec_stat_mod_folio(struct folio *folio, 547 enum node_stat_item idx, int val); 548 549static inline void lruvec_stat_mod_folio(struct folio *folio, 550 enum node_stat_item idx, int val) 551{ 552 unsigned long flags; 553 554 local_irq_save(flags); 555 __lruvec_stat_mod_folio(folio, idx, val); 556 local_irq_restore(flags); 557} 558 559static inline void mod_lruvec_page_state(struct page *page, 560 enum node_stat_item idx, int val) 561{ 562 lruvec_stat_mod_folio(page_folio(page), idx, val); 563} 564 565#else 566 567static inline void __mod_lruvec_state(struct lruvec *lruvec, 568 enum node_stat_item idx, int val) 569{ 570 __mod_node_page_state(lruvec_pgdat(lruvec), idx, val); 571} 572 573static inline void mod_lruvec_state(struct lruvec *lruvec, 574 enum node_stat_item idx, int val) 575{ 576 mod_node_page_state(lruvec_pgdat(lruvec), idx, val); 577} 578 579static inline void __lruvec_stat_mod_folio(struct folio *folio, 580 enum node_stat_item idx, int val) 581{ 582 __mod_node_page_state(folio_pgdat(folio), idx, val); 583} 584 585static inline void lruvec_stat_mod_folio(struct folio *folio, 586 enum node_stat_item idx, int val) 587{ 588 mod_node_page_state(folio_pgdat(folio), idx, val); 589} 590 591static inline void mod_lruvec_page_state(struct page *page, 592 enum node_stat_item idx, int val) 593{ 594 mod_node_page_state(page_pgdat(page), idx, val); 595} 596 597#endif /* CONFIG_MEMCG */ 598 599static inline void __lruvec_stat_add_folio(struct folio *folio, 600 enum node_stat_item idx) 601{ 602 __lruvec_stat_mod_folio(folio, idx, folio_nr_pages(folio)); 603} 604 605static inline void __lruvec_stat_sub_folio(struct folio *folio, 606 enum node_stat_item idx) 607{ 608 __lruvec_stat_mod_folio(folio, idx, -folio_nr_pages(folio)); 609} 610 611static inline void lruvec_stat_add_folio(struct folio *folio, 612 enum node_stat_item idx) 613{ 614 lruvec_stat_mod_folio(folio, idx, folio_nr_pages(folio)); 615} 616 617static inline void lruvec_stat_sub_folio(struct folio *folio, 618 enum node_stat_item idx) 619{ 620 lruvec_stat_mod_folio(folio, idx, -folio_nr_pages(folio)); 621} 622 623void memmap_boot_pages_add(long delta); 624void memmap_pages_add(long delta); 625#endif /* _LINUX_VMSTAT_H */