vmstat: create separate function to fold per cpu diffs into local counters
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / vmstat.c
index 00382c5..aaee663 100644 (file)
@@ -415,11 +415,7 @@ EXPORT_SYMBOL(dec_zone_page_state);
 #endif
 
 /*
- * Update the zone counters for one cpu.
- *
- * The cpu specified must be either the current cpu or a processor that
- * is not online. If it is the current cpu then the execution thread must
- * be pinned to the current cpu.
+ * Update the zone counters for the current cpu.
  *
  * Note that refresh_cpu_vm_stats strives to only access
  * node local memory. The per cpu pagesets on remote zones are placed
@@ -432,7 +428,7 @@ EXPORT_SYMBOL(dec_zone_page_state);
  * with the global counters. These could cause remote node cache line
  * bouncing and will have to be only done when necessary.
  */
-void refresh_cpu_vm_stats(int cpu)
+static void refresh_cpu_vm_stats(int cpu)
 {
        struct zone *zone;
        int i;
@@ -494,6 +490,38 @@ void refresh_cpu_vm_stats(int cpu)
 }
 
 /*
+ * Fold the data for an offline cpu into the global array.
+ * There cannot be any access by the offline cpu and therefore
+ * synchronization is simplified.
+ */
+void cpu_vm_stats_fold(int cpu)
+{
+       struct zone *zone;
+       int i;
+       int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
+
+       for_each_populated_zone(zone) {
+               struct per_cpu_pageset *p;
+
+               p = per_cpu_ptr(zone->pageset, cpu);
+
+               for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+                       if (p->vm_stat_diff[i]) {
+                               int v;
+
+                               v = p->vm_stat_diff[i];
+                               p->vm_stat_diff[i] = 0;
+                               atomic_long_add(v, &zone->vm_stat[i]);
+                               global_diff[i] += v;
+                       }
+       }
+
+       for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+               if (global_diff[i])
+                       atomic_long_add(global_diff[i], &vm_stat[i]);
+}
+
+/*
  * this is only called if !populated_zone(zone), which implies no other users of
  * pset->vm_stat_diff[] exsist.
  */
@@ -703,6 +731,7 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
 const char * const vmstat_text[] = {
        /* Zoned VM counters */
        "nr_free_pages",
+       "nr_alloc_batch",
        "nr_inactive_anon",
        "nr_active_anon",
        "nr_inactive_file",
@@ -817,11 +846,12 @@ const char * const vmstat_text[] = {
        "thp_zero_page_alloc",
        "thp_zero_page_alloc_failed",
 #endif
+#ifdef CONFIG_SMP
        "nr_tlb_remote_flush",
        "nr_tlb_remote_flush_received",
+#endif
        "nr_tlb_local_flush_all",
        "nr_tlb_local_flush_one",
-       "nr_tlb_local_flush_one_kernel",
 
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
 };