mm/vmstat: add helpers to get vmstat item names for each enum type
authorKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Thu, 5 Dec 2019 00:49:50 +0000 (16:49 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 5 Dec 2019 03:44:11 +0000 (19:44 -0800)
Statistics in vmstat is combined from counters with different structure,
but names for them are merged into one array.

This patch adds trivial helpers to get name for each item:

  const char *zone_stat_name(enum zone_stat_item item);
  const char *numa_stat_name(enum numa_stat_item item);
  const char *node_stat_name(enum node_stat_item item);
  const char *writeback_stat_name(enum writeback_stat_item item);
  const char *vm_event_name(enum vm_event_item item);

Names for enum writeback_stat_item are folded in the middle of
vmstat_text so this patch moves declaration into header to calculate
offset of following items.

Also this patch reuses piece of node stat names for lru list names:

  const char *lru_list_name(enum lru_list lru);

This returns common lru list names: "inactive_anon", "active_anon",
"inactive_file", "active_file", "unevictable".

[khlebnikov@yandex-team.ru: do not use size of vmstat_text as count of /proc/vmstat items]
Link: http://lkml.kernel.org/r/157152151769.4139.15423465513138349343.stgit@buzz
Link: https://lore.kernel.org/linux-mm/cd1c42ae-281f-c8a8-70ac-1d01d417b2e1@infradead.org/T/#u
Link: http://lkml.kernel.org/r/157113012325.453.562783073839432766.stgit@buzz
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: YueHaibing <yuehaibing@huawei.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/base/node.c
include/linux/vmstat.h
mm/vmstat.c

index 296546ffed6c124e949c47da292784958f4ca7b7..98a31bafc8a266ace27bf9002eaf9b0186a6fa96 100644 (file)
@@ -496,20 +496,17 @@ static ssize_t node_read_vmstat(struct device *dev,
        int n = 0;
 
        for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
-               n += sprintf(buf+n, "%s %lu\n", vmstat_text[i],
+               n += sprintf(buf+n, "%s %lu\n", zone_stat_name(i),
                             sum_zone_node_page_state(nid, i));
 
 #ifdef CONFIG_NUMA
        for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++)
-               n += sprintf(buf+n, "%s %lu\n",
-                            vmstat_text[i + NR_VM_ZONE_STAT_ITEMS],
+               n += sprintf(buf+n, "%s %lu\n", numa_stat_name(i),
                             sum_zone_numa_state(nid, i));
 #endif
 
        for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
-               n += sprintf(buf+n, "%s %lu\n",
-                            vmstat_text[i + NR_VM_ZONE_STAT_ITEMS +
-                            NR_VM_NUMA_STAT_ITEMS],
+               n += sprintf(buf+n, "%s %lu\n", node_stat_name(i),
                             node_page_state(pgdat, i));
 
        return n;
index bdeda4b079fe8987699fe620f3b1f51d2b875f2d..b995d8b680c2b54251b893b38bb58647ec8dc87c 100644 (file)
@@ -31,6 +31,12 @@ struct reclaim_stat {
        unsigned nr_unmap_fail;
 };
 
+enum writeback_stat_item {
+       NR_DIRTY_THRESHOLD,
+       NR_DIRTY_BG_THRESHOLD,
+       NR_VM_WRITEBACK_STAT_ITEMS,
+};
+
 #ifdef CONFIG_VM_EVENT_COUNTERS
 /*
  * Light weight per cpu counter implementation.
@@ -381,4 +387,48 @@ static inline void __mod_zone_freepage_state(struct zone *zone, int nr_pages,
 
 extern const char * const vmstat_text[];
 
+static inline const char *zone_stat_name(enum zone_stat_item item)
+{
+       return vmstat_text[item];
+}
+
+#ifdef CONFIG_NUMA
+static inline const char *numa_stat_name(enum numa_stat_item item)
+{
+       return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
+                          item];
+}
+#endif /* CONFIG_NUMA */
+
+static inline const char *node_stat_name(enum node_stat_item item)
+{
+       return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
+                          NR_VM_NUMA_STAT_ITEMS +
+                          item];
+}
+
+static inline const char *lru_list_name(enum lru_list lru)
+{
+       return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
+}
+
+static inline const char *writeback_stat_name(enum writeback_stat_item item)
+{
+       return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
+                          NR_VM_NUMA_STAT_ITEMS +
+                          NR_VM_NODE_STAT_ITEMS +
+                          item];
+}
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+static inline const char *vm_event_name(enum vm_event_item item)
+{
+       return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
+                          NR_VM_NUMA_STAT_ITEMS +
+                          NR_VM_NODE_STAT_ITEMS +
+                          NR_VM_WRITEBACK_STAT_ITEMS +
+                          item];
+}
+#endif /* CONFIG_VM_EVENT_COUNTERS */
+
 #endif /* _LINUX_VMSTAT_H */
index a8222041bd44d648a4c8b5a1e5e345314efb050e..fa627329428b082566a48932180e07abcc36e3ee 100644 (file)
@@ -1134,7 +1134,7 @@ const char * const vmstat_text[] = {
        "numa_other",
 #endif
 
-       /* Node-based counters */
+       /* enum node_stat_item counters */
        "nr_inactive_anon",
        "nr_active_anon",
        "nr_inactive_file",
@@ -1564,10 +1564,8 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
        if (is_zone_first_populated(pgdat, zone)) {
                seq_printf(m, "\n  per-node stats");
                for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
-                       seq_printf(m, "\n      %-12s %lu",
-                               vmstat_text[i + NR_VM_ZONE_STAT_ITEMS +
-                               NR_VM_NUMA_STAT_ITEMS],
-                               node_page_state(pgdat, i));
+                       seq_printf(m, "\n      %-12s %lu", node_stat_name(i),
+                                  node_page_state(pgdat, i));
                }
        }
        seq_printf(m,
@@ -1600,14 +1598,13 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
        }
 
        for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
-               seq_printf(m, "\n      %-12s %lu", vmstat_text[i],
-                               zone_page_state(zone, i));
+               seq_printf(m, "\n      %-12s %lu", zone_stat_name(i),
+                          zone_page_state(zone, i));
 
 #ifdef CONFIG_NUMA
        for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++)
-               seq_printf(m, "\n      %-12s %lu",
-                               vmstat_text[i + NR_VM_ZONE_STAT_ITEMS],
-                               zone_numa_state_snapshot(zone, i));
+               seq_printf(m, "\n      %-12s %lu", numa_stat_name(i),
+                          zone_numa_state_snapshot(zone, i));
 #endif
 
        seq_printf(m, "\n  pagesets");
@@ -1658,31 +1655,23 @@ static const struct seq_operations zoneinfo_op = {
        .show   = zoneinfo_show,
 };
 
-enum writeback_stat_item {
-       NR_DIRTY_THRESHOLD,
-       NR_DIRTY_BG_THRESHOLD,
-       NR_VM_WRITEBACK_STAT_ITEMS,
-};
+#define NR_VMSTAT_ITEMS (NR_VM_ZONE_STAT_ITEMS + \
+                        NR_VM_NUMA_STAT_ITEMS + \
+                        NR_VM_NODE_STAT_ITEMS + \
+                        NR_VM_WRITEBACK_STAT_ITEMS + \
+                        (IS_ENABLED(CONFIG_VM_EVENT_COUNTERS) ? \
+                         NR_VM_EVENT_ITEMS : 0))
 
 static void *vmstat_start(struct seq_file *m, loff_t *pos)
 {
        unsigned long *v;
-       int i, stat_items_size;
+       int i;
 
-       if (*pos >= ARRAY_SIZE(vmstat_text))
+       if (*pos >= NR_VMSTAT_ITEMS)
                return NULL;
-       stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +
-                         NR_VM_NUMA_STAT_ITEMS * sizeof(unsigned long) +
-                         NR_VM_NODE_STAT_ITEMS * sizeof(unsigned long) +
-                         NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long);
-
-#ifdef CONFIG_VM_EVENT_COUNTERS
-       stat_items_size += sizeof(struct vm_event_state);
-#endif
 
-       BUILD_BUG_ON(stat_items_size !=
-                    ARRAY_SIZE(vmstat_text) * sizeof(unsigned long));
-       v = kmalloc(stat_items_size, GFP_KERNEL);
+       BUILD_BUG_ON(ARRAY_SIZE(vmstat_text) < NR_VMSTAT_ITEMS);
+       v = kmalloc_array(NR_VMSTAT_ITEMS, sizeof(unsigned long), GFP_KERNEL);
        m->private = v;
        if (!v)
                return ERR_PTR(-ENOMEM);
@@ -1715,7 +1704,7 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)
 static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)
 {
        (*pos)++;
-       if (*pos >= ARRAY_SIZE(vmstat_text))
+       if (*pos >= NR_VMSTAT_ITEMS)
                return NULL;
        return (unsigned long *)m->private + *pos;
 }
@@ -1781,7 +1770,7 @@ int vmstat_refresh(struct ctl_table *table, int write,
                val = atomic_long_read(&vm_zone_stat[i]);
                if (val < 0) {
                        pr_warn("%s: %s %ld\n",
-                               __func__, vmstat_text[i], val);
+                               __func__, zone_stat_name(i), val);
                        err = -EINVAL;
                }
        }
@@ -1790,7 +1779,7 @@ int vmstat_refresh(struct ctl_table *table, int write,
                val = atomic_long_read(&vm_numa_stat[i]);
                if (val < 0) {
                        pr_warn("%s: %s %ld\n",
-                               __func__, vmstat_text[i + NR_VM_ZONE_STAT_ITEMS], val);
+                               __func__, numa_stat_name(i), val);
                        err = -EINVAL;
                }
        }