]> err.no Git - linux-2.6/blobdiff - mm/vmstat.c
Make vm statistics update interval configurable
[linux-2.6] / mm / vmstat.c
index 5462106725d719de129ec92ec5d8bd977cad6a29..006eb7621869946141d7e159372d9661939f07a7 100644 (file)
 #include <linux/module.h>
 #include <linux/cpu.h>
 
-void __get_zone_counts(unsigned long *active, unsigned long *inactive,
-                       unsigned long *free, struct pglist_data *pgdat)
-{
-       struct zone *zones = pgdat->node_zones;
-       int i;
-
-       *active = node_page_state(pgdat->node_id, NR_ACTIVE);
-       *inactive = node_page_state(pgdat->node_id, NR_INACTIVE);
-       *free = 0;
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               *free += zones[i].free_pages;
-       }
-}
-
-void get_zone_counts(unsigned long *active,
-               unsigned long *inactive, unsigned long *free)
-{
-       struct pglist_data *pgdat;
-
-       *active = global_page_state(NR_ACTIVE);
-       *inactive = global_page_state(NR_INACTIVE);
-       *free = 0;
-       for_each_online_pgdat(pgdat) {
-               unsigned long l, m, n;
-               __get_zone_counts(&l, &m, &n, pgdat);
-               *free += n;
-       }
-}
-
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
 EXPORT_PER_CPU_SYMBOL(vm_event_states);
@@ -437,6 +408,12 @@ const struct seq_operations fragmentation_op = {
        .show   = frag_show,
 };
 
+#ifdef CONFIG_ZONE_DMA
+#define TEXT_FOR_DMA(xx) xx "_dma",
+#else
+#define TEXT_FOR_DMA(xx)
+#endif
+
 #ifdef CONFIG_ZONE_DMA32
 #define TEXT_FOR_DMA32(xx) xx "_dma32",
 #else
@@ -449,21 +426,22 @@ const struct seq_operations fragmentation_op = {
 #define TEXT_FOR_HIGHMEM(xx)
 #endif
 
-#define TEXTS_FOR_ZONES(xx) xx "_dma", TEXT_FOR_DMA32(xx) xx "_normal", \
+#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
                                        TEXT_FOR_HIGHMEM(xx)
 
 static const char * const vmstat_text[] = {
        /* Zoned VM counters */
+       "nr_free_pages",
        "nr_active",
        "nr_inactive",
        "nr_anon_pages",
        "nr_mapped",
        "nr_file_pages",
+       "nr_dirty",
+       "nr_writeback",
        "nr_slab_reclaimable",
        "nr_slab_unreclaimable",
        "nr_page_table_pages",
-       "nr_dirty",
-       "nr_writeback",
        "nr_unstable",
        "nr_bounce",
        "nr_vmscan_write",
@@ -534,7 +512,7 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
                           "\n        scanned  %lu (a: %lu i: %lu)"
                           "\n        spanned  %lu"
                           "\n        present  %lu",
-                          zone->free_pages,
+                          zone_page_state(zone, NR_FREE_PAGES),
                           zone->pages_min,
                           zone->pages_low,
                           zone->pages_high,
@@ -662,6 +640,24 @@ const struct seq_operations vmstat_op = {
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
+int sysctl_stat_interval __read_mostly = HZ;
+
+static void vmstat_update(struct work_struct *w)
+{
+       refresh_cpu_vm_stats(smp_processor_id());
+       schedule_delayed_work(&__get_cpu_var(vmstat_work),
+               sysctl_stat_interval);
+}
+
+static void __devinit start_cpu_timer(int cpu)
+{
+       struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
+
+       INIT_DELAYED_WORK(vmstat_work, vmstat_update);
+       schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu);
+}
+
 /*
  * Use the cpu notifier to insure that the thresholds are recalculated
  * when necessary.
@@ -670,10 +666,24 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
                unsigned long action,
                void *hcpu)
 {
+       long cpu = (long)hcpu;
+
        switch (action) {
-       case CPU_UP_PREPARE:
-       case CPU_UP_CANCELED:
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               start_cpu_timer(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
+               cancel_rearming_delayed_work(&per_cpu(vmstat_work, cpu));
+               per_cpu(vmstat_work, cpu).work.func = NULL;
+               break;
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               start_cpu_timer(cpu);
+               break;
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                refresh_zone_stat_thresholds();
                break;
        default:
@@ -687,8 +697,13 @@ static struct notifier_block __cpuinitdata vmstat_notifier =
 
 int __init setup_vmstat(void)
 {
+       int cpu;
+
        refresh_zone_stat_thresholds();
        register_cpu_notifier(&vmstat_notifier);
+
+       for_each_online_cpu(cpu)
+               start_cpu_timer(cpu);
        return 0;
 }
 module_init(setup_vmstat)