[PATCH] vmstat: don't auto expand the sysfs files

From: Pasha Tatashin
Date: Mon Dec 11 2023 - 10:46:56 EST


Whenever a new fields are added one of the following: node_stat_item
numa_stat_item zone_stat_item, the /sys/devices/system/node/nodeX/vmstat
files are auto expanded.

This is a problem, as sysfs files should be only one value per file.
Also, once a field is exported via vmstat it is hard to remove it as
there could be user applications that rely on this field. This is why
we still cary "nr_unstable 0" in /proc/vmstat that is not used.

Also, since vmstat is auto-expanded the fields are not documented, so
users do not know whether they are counted in bytes/kilobytes/pages,
and the exact meaning of these fields.

Modify the code that the new fields do not auto-expand the vmstat in
sysfs. The new fields can still be exported via their own files in
sysfs, and be properly documents.

vmstat values are named using vmstat_text[] array, which contains names
for zone_stat, numa_stat, node_stat, lru_list, writeback_stat,
vm_event.

Change vmstat_text[] to be an array of structs that contain two values:
name, and flags. The new flags field contains information whether to
show stat value in vmstat files in sysfs (VMSTAT_SHOW_SYSFS), and in
procfs (VMSTAT_SHOW_PROCFS). The comment above VMSTAT_SHOW_SYSFS
documents that this flag should not be used for new stat values when
they are added.

Signed-off-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
---
drivers/base/node.c | 34 ++--
include/linux/vmstat.h | 48 ++++--
mm/vmstat.c | 377 +++++++++++++++++++++--------------------
3 files changed, 244 insertions(+), 215 deletions(-)

Examples of the projects that are currently under review and that add new
fields to the one of the vmstat items:

[1] mm: report per-page metadata information
https://lore.kernel.org/all/20231205223118.3575485-1-souravpanda@xxxxxxxxxx

[2] IOMMU memory observability
https://lore.kernel.org/all/20231130201504.2322355-1-pasha.tatashin@xxxxxxxxxx

Greg KH has been requesting for these files not to grow:
https://lore.kernel.org/all/2023120731-deception-handmade-8d49@gregkh

diff --git a/drivers/base/node.c b/drivers/base/node.c
index 493d533f8375..f139d7ab58f5 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -520,26 +520,34 @@ static ssize_t node_read_vmstat(struct device *dev,
int i;
int len = 0;

- for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
- len += sysfs_emit_at(buf, len, "%s %lu\n",
- zone_stat_name(i),
- sum_zone_node_page_state(nid, i));
+ for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) {
+ if (vmstat_text[ZONE_STAT_NAME_IDX(i)].flags & VMSTAT_SHOW_SYSFS) {
+ len += sysfs_emit_at(buf, len, "%s %lu\n",
+ zone_stat_name(i),
+ sum_zone_node_page_state(nid, i));
+ }
+ }

#ifdef CONFIG_NUMA
fold_vm_numa_events();
- for (i = 0; i < NR_VM_NUMA_EVENT_ITEMS; i++)
- len += sysfs_emit_at(buf, len, "%s %lu\n",
- numa_stat_name(i),
- sum_zone_numa_event_state(nid, i));
+ for (i = 0; i < NR_VM_NUMA_EVENT_ITEMS; i++) {
+ if (vmstat_text[NUMA_STAT_NAME_IDX(i)].flags & VMSTAT_SHOW_SYSFS) {
+ len += sysfs_emit_at(buf, len, "%s %lu\n",
+ numa_stat_name(i),
+ sum_zone_numa_event_state(nid, i));
+ }
+ }

#endif
for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
- unsigned long pages = node_page_state_pages(pgdat, i);
+ if (vmstat_text[NODE_STAT_NAME_IDX(i)].flags & VMSTAT_SHOW_SYSFS) {
+ unsigned long pages = node_page_state_pages(pgdat, i);

- if (vmstat_item_print_in_thp(i))
- pages /= HPAGE_PMD_NR;
- len += sysfs_emit_at(buf, len, "%s %lu\n", node_stat_name(i),
- pages);
+ if (vmstat_item_print_in_thp(i))
+ pages /= HPAGE_PMD_NR;
+ len += sysfs_emit_at(buf, len, "%s %lu\n", node_stat_name(i),
+ pages);
+ }
}

return len;
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index fed855bae6d8..2dd46daf69aa 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -495,26 +495,44 @@ static inline void __mod_zone_freepage_state(struct zone *zone, int nr_pages,
__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, nr_pages);
}

-extern const char * const vmstat_text[];

+/*
+ * Show this stat in /sys/devices/system/node/nodeX/vmstat
+ * IMPORTANT: Don't use this flag for new stats, as the right way to output only
+ * one stat per file in sysfs. Instead, add new individual sysfs files for new
+ * stats, and document them in Documentation/ABI/TYPE/sysfs-new_field_name.
+ */
+#define VMSTAT_SHOW_SYSFS BIT(0)
+
+/* Show this stat in /proc/vmstat */
+#define VMSTAT_SHOW_PROCFS BIT(1)
+
+struct vmstat_text {
+ const char *name;
+ char flags;
+};
+
+extern const struct vmstat_text vmstat_text[];
+
+#define ZONE_STAT_NAME_IDX(item) ((int)(item))
static inline const char *zone_stat_name(enum zone_stat_item item)
{
- return vmstat_text[item];
+ return vmstat_text[ZONE_STAT_NAME_IDX(item)].name;
}

#ifdef CONFIG_NUMA
+#define NUMA_STAT_NAME_IDX(item) (NR_VM_ZONE_STAT_ITEMS + (int)(item))
static inline const char *numa_stat_name(enum numa_stat_item item)
{
- return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
- item];
+ return vmstat_text[NUMA_STAT_NAME_IDX(item)].name;
}
#endif /* CONFIG_NUMA */

+#define NODE_STAT_NAME_IDX(item) (NR_VM_NUMA_EVENT_ITEMS + \
+ NR_VM_ZONE_STAT_ITEMS + (int)(item))
static inline const char *node_stat_name(enum node_stat_item item)
{
- return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
- NR_VM_NUMA_EVENT_ITEMS +
- item];
+ return vmstat_text[NODE_STAT_NAME_IDX(item)].name;
}

static inline const char *lru_list_name(enum lru_list lru)
@@ -522,22 +540,20 @@ static inline const char *lru_list_name(enum lru_list lru)
return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
}

+#define WRITEBACK_STAT_NAME_IDX(item) (NR_VM_NODE_STAT_ITEMS + \
+ NR_VM_NUMA_EVENT_ITEMS + NR_VM_ZONE_STAT_ITEMS + (int)(item))
static inline const char *writeback_stat_name(enum writeback_stat_item item)
{
- return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
- NR_VM_NUMA_EVENT_ITEMS +
- NR_VM_NODE_STAT_ITEMS +
- item];
+ return vmstat_text[WRITEBACK_STAT_NAME_IDX(item)].name;
}

#if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG)
+#define VM_EVENT_NAME_IDX(item) (NR_VM_WRITEBACK_STAT_ITEMS + \
+ NR_VM_NODE_STAT_ITEMS + NR_VM_NUMA_EVENT_ITEMS + \
+ NR_VM_ZONE_STAT_ITEMS + (int)(item))
static inline const char *vm_event_name(enum vm_event_item item)
{
- return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
- NR_VM_NUMA_EVENT_ITEMS +
- NR_VM_NODE_STAT_ITEMS +
- NR_VM_WRITEBACK_STAT_ITEMS +
- item];
+ return vmstat_text[VM_EVENT_NAME_IDX(item)].name;
}
#endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */

diff --git a/mm/vmstat.c b/mm/vmstat.c
index 359460deb377..691d8c90b4ac 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1142,278 +1142,281 @@ int fragmentation_index(struct zone *zone, unsigned int order)
#if defined(CONFIG_PROC_FS) || defined(CONFIG_SYSFS) || \
defined(CONFIG_NUMA) || defined(CONFIG_MEMCG)
#ifdef CONFIG_ZONE_DMA
-#define TEXT_FOR_DMA(xx) xx "_dma",
+#define TEXT_FOR_DMA(xx) {xx "_dma", VMSTAT_SHOW_PROCFS},
#else
#define TEXT_FOR_DMA(xx)
#endif

#ifdef CONFIG_ZONE_DMA32
-#define TEXT_FOR_DMA32(xx) xx "_dma32",
+#define TEXT_FOR_DMA32(xx) {xx "_dma32", VMSTAT_SHOW_PROCFS},
#else
#define TEXT_FOR_DMA32(xx)
#endif

#ifdef CONFIG_HIGHMEM
-#define TEXT_FOR_HIGHMEM(xx) xx "_high",
+#define TEXT_FOR_HIGHMEM(xx) {xx "_high", VMSTAT_SHOW_PROCFS},
#else
#define TEXT_FOR_HIGHMEM(xx)
#endif

#ifdef CONFIG_ZONE_DEVICE
-#define TEXT_FOR_DEVICE(xx) xx "_device",
+#define TEXT_FOR_DEVICE(xx) {xx "_device", VMSTAT_SHOW_PROCFS},
#else
#define TEXT_FOR_DEVICE(xx)
#endif

-#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
- TEXT_FOR_HIGHMEM(xx) xx "_movable", \
- TEXT_FOR_DEVICE(xx)
+#define TEXT_FOR_NORMAL(xx) {xx "_normal", VMSTAT_SHOW_PROCFS},
+#define TEXT_FOR_MOVABLE(xx) {xx "_movable", VMSTAT_SHOW_PROCFS},

-const char * const vmstat_text[] = {
+#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) \
+ TEXT_FOR_NORMAL(xx) TEXT_FOR_HIGHMEM(xx) TEXT_FOR_MOVABLE(xx) \
+ TEXT_FOR_DEVICE(xx)
+
+const struct vmstat_text vmstat_text[] = {
/* enum zone_stat_item counters */
- "nr_free_pages",
- "nr_zone_inactive_anon",
- "nr_zone_active_anon",
- "nr_zone_inactive_file",
- "nr_zone_active_file",
- "nr_zone_unevictable",
- "nr_zone_write_pending",
- "nr_mlock",
- "nr_bounce",
+ {"nr_free_pages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_inactive_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_active_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_inactive_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_active_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_unevictable", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_zone_write_pending", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_mlock", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_bounce", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#if IS_ENABLED(CONFIG_ZSMALLOC)
- "nr_zspages",
+ {"nr_zspages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif
- "nr_free_cma",
+ {"nr_free_cma", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#ifdef CONFIG_UNACCEPTED_MEMORY
- "nr_unaccepted",
+ {"nr_unaccepted", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif

/* enum numa_stat_item counters */
#ifdef CONFIG_NUMA
- "numa_hit",
- "numa_miss",
- "numa_foreign",
- "numa_interleave",
- "numa_local",
- "numa_other",
+ {"numa_hit", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"numa_miss", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"numa_foreign", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"numa_interleave", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"numa_local", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"numa_other", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif
-
/* enum node_stat_item counters */
- "nr_inactive_anon",
- "nr_active_anon",
- "nr_inactive_file",
- "nr_active_file",
- "nr_unevictable",
- "nr_slab_reclaimable",
- "nr_slab_unreclaimable",
- "nr_isolated_anon",
- "nr_isolated_file",
- "workingset_nodes",
- "workingset_refault_anon",
- "workingset_refault_file",
- "workingset_activate_anon",
- "workingset_activate_file",
- "workingset_restore_anon",
- "workingset_restore_file",
- "workingset_nodereclaim",
- "nr_anon_pages",
- "nr_mapped",
- "nr_file_pages",
- "nr_dirty",
- "nr_writeback",
- "nr_writeback_temp",
- "nr_shmem",
- "nr_shmem_hugepages",
- "nr_shmem_pmdmapped",
- "nr_file_hugepages",
- "nr_file_pmdmapped",
- "nr_anon_transparent_hugepages",
- "nr_vmscan_write",
- "nr_vmscan_immediate_reclaim",
- "nr_dirtied",
- "nr_written",
- "nr_throttled_written",
- "nr_kernel_misc_reclaimable",
- "nr_foll_pin_acquired",
- "nr_foll_pin_released",
- "nr_kernel_stack",
+ {"nr_inactive_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_active_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_inactive_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_active_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_unevictable", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_slab_reclaimable", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_slab_unreclaimable", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_isolated_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_isolated_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_nodes", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_refault_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_refault_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_activate_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_activate_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_restore_anon", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_restore_file", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"workingset_nodereclaim", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_anon_pages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_mapped", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_file_pages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_dirty", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_writeback", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_writeback_temp", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_shmem", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_shmem_hugepages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_shmem_pmdmapped", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_file_hugepages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_file_pmdmapped", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_anon_transparent_hugepages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_vmscan_write", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_vmscan_immediate_reclaim", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_dirtied", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_written", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_throttled_written", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_kernel_misc_reclaimable", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_foll_pin_acquired", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_foll_pin_released", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_kernel_stack", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
- "nr_shadow_call_stack",
+ {"nr_shadow_call_stack", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif
- "nr_page_table_pages",
- "nr_sec_page_table_pages",
+ {"nr_page_table_pages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"nr_sec_page_table_pages", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#ifdef CONFIG_SWAP
- "nr_swapcached",
+ {"nr_swapcached", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif
#ifdef CONFIG_NUMA_BALANCING
- "pgpromote_success",
- "pgpromote_candidate",
+ {"pgpromote_success", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
+ {"pgpromote_candidate", VMSTAT_SHOW_PROCFS | VMSTAT_SHOW_SYSFS},
#endif

/* enum writeback_stat_item counters */
- "nr_dirty_threshold",
- "nr_dirty_background_threshold",
+ {"nr_dirty_threshold", VMSTAT_SHOW_PROCFS},
+ {"nr_dirty_background_threshold", VMSTAT_SHOW_PROCFS},

#if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG)
/* enum vm_event_item counters */
- "pgpgin",
- "pgpgout",
- "pswpin",
- "pswpout",
+ {"pgpgin", VMSTAT_SHOW_PROCFS},
+ {"pgpgout", VMSTAT_SHOW_PROCFS},
+ {"pswpin", VMSTAT_SHOW_PROCFS},
+ {"pswpout", VMSTAT_SHOW_PROCFS},

TEXTS_FOR_ZONES("pgalloc")
TEXTS_FOR_ZONES("allocstall")
TEXTS_FOR_ZONES("pgskip")

- "pgfree",
- "pgactivate",
- "pgdeactivate",
- "pglazyfree",
-
- "pgfault",
- "pgmajfault",
- "pglazyfreed",
-
- "pgrefill",
- "pgreuse",
- "pgsteal_kswapd",
- "pgsteal_direct",
- "pgsteal_khugepaged",
- "pgdemote_kswapd",
- "pgdemote_direct",
- "pgdemote_khugepaged",
- "pgscan_kswapd",
- "pgscan_direct",
- "pgscan_khugepaged",
- "pgscan_direct_throttle",
- "pgscan_anon",
- "pgscan_file",
- "pgsteal_anon",
- "pgsteal_file",
+ {"pgfree", VMSTAT_SHOW_PROCFS},
+ {"pgactivate", VMSTAT_SHOW_PROCFS},
+ {"pgdeactivate", VMSTAT_SHOW_PROCFS},
+ {"pglazyfree", VMSTAT_SHOW_PROCFS},
+
+ {"pgfault", VMSTAT_SHOW_PROCFS},
+ {"pgmajfault", VMSTAT_SHOW_PROCFS},
+ {"pglazyfreed", VMSTAT_SHOW_PROCFS},
+
+ {"pgrefill", VMSTAT_SHOW_PROCFS},
+ {"pgreuse", VMSTAT_SHOW_PROCFS},
+ {"pgsteal_kswapd", VMSTAT_SHOW_PROCFS},
+ {"pgsteal_direct", VMSTAT_SHOW_PROCFS},
+ {"pgsteal_khugepaged", VMSTAT_SHOW_PROCFS},
+ {"pgdemote_kswapd", VMSTAT_SHOW_PROCFS},
+ {"pgdemote_direct", VMSTAT_SHOW_PROCFS},
+ {"pgdemote_khugepaged", VMSTAT_SHOW_PROCFS},
+ {"pgscan_kswapd", VMSTAT_SHOW_PROCFS},
+ {"pgscan_direct", VMSTAT_SHOW_PROCFS},
+ {"pgscan_khugepaged", VMSTAT_SHOW_PROCFS},
+ {"pgscan_direct_throttle", VMSTAT_SHOW_PROCFS},
+ {"pgscan_anon", VMSTAT_SHOW_PROCFS},
+ {"pgscan_file", VMSTAT_SHOW_PROCFS},
+ {"pgsteal_anon", VMSTAT_SHOW_PROCFS},
+ {"pgsteal_file", VMSTAT_SHOW_PROCFS},

#ifdef CONFIG_NUMA
- "zone_reclaim_failed",
+ {"zone_reclaim_failed", VMSTAT_SHOW_PROCFS},
#endif
- "pginodesteal",
- "slabs_scanned",
- "kswapd_inodesteal",
- "kswapd_low_wmark_hit_quickly",
- "kswapd_high_wmark_hit_quickly",
- "pageoutrun",
+ {"pginodesteal", VMSTAT_SHOW_PROCFS},
+ {"slabs_scanned", VMSTAT_SHOW_PROCFS},
+ {"kswapd_inodesteal", VMSTAT_SHOW_PROCFS},
+ {"kswapd_low_wmark_hit_quickly", VMSTAT_SHOW_PROCFS},
+ {"kswapd_high_wmark_hit_quickly", VMSTAT_SHOW_PROCFS},
+ {"pageoutrun", VMSTAT_SHOW_PROCFS},

- "pgrotated",
+ {"pgrotated", VMSTAT_SHOW_PROCFS},

- "drop_pagecache",
- "drop_slab",
- "oom_kill",
+ {"drop_pagecache", VMSTAT_SHOW_PROCFS},
+ {"drop_slab", VMSTAT_SHOW_PROCFS},
+ {"oom_kill", VMSTAT_SHOW_PROCFS},

#ifdef CONFIG_NUMA_BALANCING
- "numa_pte_updates",
- "numa_huge_pte_updates",
- "numa_hint_faults",
- "numa_hint_faults_local",
- "numa_pages_migrated",
+ {"numa_pte_updates", VMSTAT_SHOW_PROCFS},
+ {"numa_huge_pte_updates", VMSTAT_SHOW_PROCFS},
+ {"numa_hint_faults", VMSTAT_SHOW_PROCFS},
+ {"numa_hint_faults_local", VMSTAT_SHOW_PROCFS},
+ {"numa_pages_migrated", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_MIGRATION
- "pgmigrate_success",
- "pgmigrate_fail",
- "thp_migration_success",
- "thp_migration_fail",
- "thp_migration_split",
+ {"pgmigrate_success", VMSTAT_SHOW_PROCFS},
+ {"pgmigrate_fail", VMSTAT_SHOW_PROCFS},
+ {"thp_migration_success", VMSTAT_SHOW_PROCFS},
+ {"thp_migration_fail", VMSTAT_SHOW_PROCFS},
+ {"thp_migration_split", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_COMPACTION
- "compact_migrate_scanned",
- "compact_free_scanned",
- "compact_isolated",
- "compact_stall",
- "compact_fail",
- "compact_success",
- "compact_daemon_wake",
- "compact_daemon_migrate_scanned",
- "compact_daemon_free_scanned",
+ {"compact_migrate_scanned", VMSTAT_SHOW_PROCFS},
+ {"compact_free_scanned", VMSTAT_SHOW_PROCFS},
+ {"compact_isolated", VMSTAT_SHOW_PROCFS},
+ {"compact_stall", VMSTAT_SHOW_PROCFS},
+ {"compact_fail", VMSTAT_SHOW_PROCFS},
+ {"compact_success", VMSTAT_SHOW_PROCFS},
+ {"compact_daemon_wake", VMSTAT_SHOW_PROCFS},
+ {"compact_daemon_migrate_scanned", VMSTAT_SHOW_PROCFS},
+ {"compact_daemon_free_scanned", VMSTAT_SHOW_PROCFS},
#endif

#ifdef CONFIG_HUGETLB_PAGE
- "htlb_buddy_alloc_success",
- "htlb_buddy_alloc_fail",
+ {"htlb_buddy_alloc_success", VMSTAT_SHOW_PROCFS},
+ {"htlb_buddy_alloc_fail", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_CMA
- "cma_alloc_success",
- "cma_alloc_fail",
+ {"cma_alloc_success", VMSTAT_SHOW_PROCFS},
+ {"cma_alloc_fail", VMSTAT_SHOW_PROCFS},
#endif
- "unevictable_pgs_culled",
- "unevictable_pgs_scanned",
- "unevictable_pgs_rescued",
- "unevictable_pgs_mlocked",
- "unevictable_pgs_munlocked",
- "unevictable_pgs_cleared",
- "unevictable_pgs_stranded",
+ {"unevictable_pgs_culled", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_scanned", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_rescued", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_mlocked", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_munlocked", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_cleared", VMSTAT_SHOW_PROCFS},
+ {"unevictable_pgs_stranded", VMSTAT_SHOW_PROCFS},

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- "thp_fault_alloc",
- "thp_fault_fallback",
- "thp_fault_fallback_charge",
- "thp_collapse_alloc",
- "thp_collapse_alloc_failed",
- "thp_file_alloc",
- "thp_file_fallback",
- "thp_file_fallback_charge",
- "thp_file_mapped",
- "thp_split_page",
- "thp_split_page_failed",
- "thp_deferred_split_page",
- "thp_split_pmd",
- "thp_scan_exceed_none_pte",
- "thp_scan_exceed_swap_pte",
- "thp_scan_exceed_share_pte",
+ {"thp_fault_alloc", VMSTAT_SHOW_PROCFS},
+ {"thp_fault_fallback", VMSTAT_SHOW_PROCFS},
+ {"thp_fault_fallback_charge", VMSTAT_SHOW_PROCFS},
+ {"thp_collapse_alloc", VMSTAT_SHOW_PROCFS},
+ {"thp_collapse_alloc_failed", VMSTAT_SHOW_PROCFS},
+ {"thp_file_alloc", VMSTAT_SHOW_PROCFS},
+ {"thp_file_fallback", VMSTAT_SHOW_PROCFS},
+ {"thp_file_fallback_charge", VMSTAT_SHOW_PROCFS},
+ {"thp_file_mapped", VMSTAT_SHOW_PROCFS},
+ {"thp_split_page", VMSTAT_SHOW_PROCFS},
+ {"thp_split_page_failed", VMSTAT_SHOW_PROCFS},
+ {"thp_deferred_split_page", VMSTAT_SHOW_PROCFS},
+ {"thp_split_pmd", VMSTAT_SHOW_PROCFS},
+ {"thp_scan_exceed_none_pte", VMSTAT_SHOW_PROCFS},
+ {"thp_scan_exceed_swap_pte", VMSTAT_SHOW_PROCFS},
+ {"thp_scan_exceed_share_pte", VMSTAT_SHOW_PROCFS},
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
- "thp_split_pud",
+ {"thp_split_pud", VMSTAT_SHOW_PROCFS},
#endif
- "thp_zero_page_alloc",
- "thp_zero_page_alloc_failed",
- "thp_swpout",
- "thp_swpout_fallback",
+ {"thp_zero_page_alloc", VMSTAT_SHOW_PROCFS},
+ {"thp_zero_page_alloc_failed", VMSTAT_SHOW_PROCFS},
+ {"thp_swpout", VMSTAT_SHOW_PROCFS},
+ {"thp_swpout_fallback", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_MEMORY_BALLOON
- "balloon_inflate",
- "balloon_deflate",
+ {"balloon_inflate", VMSTAT_SHOW_PROCFS},
+ {"balloon_deflate", VMSTAT_SHOW_PROCFS},
#ifdef CONFIG_BALLOON_COMPACTION
- "balloon_migrate",
+ {"balloon_migrate", VMSTAT_SHOW_PROCFS},
#endif
#endif /* CONFIG_MEMORY_BALLOON */
#ifdef CONFIG_DEBUG_TLBFLUSH
- "nr_tlb_remote_flush",
- "nr_tlb_remote_flush_received",
- "nr_tlb_local_flush_all",
- "nr_tlb_local_flush_one",
+ {"nr_tlb_remote_flush", VMSTAT_SHOW_PROCFS},
+ {"nr_tlb_remote_flush_received", VMSTAT_SHOW_PROCFS},
+ {"nr_tlb_local_flush_all", VMSTAT_SHOW_PROCFS},
+ {"nr_tlb_local_flush_one", VMSTAT_SHOW_PROCFS},
#endif /* CONFIG_DEBUG_TLBFLUSH */

#ifdef CONFIG_SWAP
- "swap_ra",
- "swap_ra_hit",
+ {"swap_ra", VMSTAT_SHOW_PROCFS},
+ {"swap_ra_hit", VMSTAT_SHOW_PROCFS},
#ifdef CONFIG_KSM
- "ksm_swpin_copy",
+ {"ksm_swpin_copy", VMSTAT_SHOW_PROCFS},
#endif
#endif
#ifdef CONFIG_KSM
- "cow_ksm",
+ {"cow_ksm", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_ZSWAP
- "zswpin",
- "zswpout",
+ {"zswpin", VMSTAT_SHOW_PROCFS},
+ {"zswpout", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_X86
- "direct_map_level2_splits",
- "direct_map_level3_splits",
+ {"direct_map_level2_splits", VMSTAT_SHOW_PROCFS},
+ {"direct_map_level3_splits", VMSTAT_SHOW_PROCFS},
#endif
#ifdef CONFIG_PER_VMA_LOCK_STATS
- "vma_lock_success",
- "vma_lock_abort",
- "vma_lock_retry",
- "vma_lock_miss",
+ {"vma_lock_success", VMSTAT_SHOW_PROCFS},
+ {"vma_lock_abort", VMSTAT_SHOW_PROCFS},
+ {"vma_lock_retry", VMSTAT_SHOW_PROCFS},
+ {"vma_lock_miss", VMSTAT_SHOW_PROCFS},
#endif
#endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */
};
+
#endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA || CONFIG_MEMCG */

#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)) || \
@@ -1845,9 +1848,11 @@ static int vmstat_show(struct seq_file *m, void *arg)
unsigned long *l = arg;
unsigned long off = l - (unsigned long *)m->private;

- seq_puts(m, vmstat_text[off]);
- seq_put_decimal_ull(m, " ", *l);
- seq_putc(m, '\n');
+ if (vmstat_text[off].flags & VMSTAT_SHOW_PROCFS) {
+ seq_puts(m, vmstat_text[off].name);
+ seq_put_decimal_ull(m, " ", *l);
+ seq_putc(m, '\n');
+ }

if (off == NR_VMSTAT_ITEMS - 1) {
/*
--
2.43.0.472.g3155946c3a-goog