1f6ac2354SChristoph Lameter /* 2f6ac2354SChristoph Lameter * linux/mm/vmstat.c 3f6ac2354SChristoph Lameter * 4f6ac2354SChristoph Lameter * Manages VM statistics 5f6ac2354SChristoph Lameter * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 62244b95aSChristoph Lameter * 72244b95aSChristoph Lameter * zoned VM statistics 82244b95aSChristoph Lameter * Copyright (C) 2006 Silicon Graphics, Inc., 92244b95aSChristoph Lameter * Christoph Lameter <christoph@lameter.com> 10f6ac2354SChristoph Lameter */ 11f6ac2354SChristoph Lameter 12f6ac2354SChristoph Lameter #include <linux/mm.h> 132244b95aSChristoph Lameter #include <linux/module.h> 14df9ecabaSChristoph Lameter #include <linux/cpu.h> 15*e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 16f6ac2354SChristoph Lameter 17f8891e5eSChristoph Lameter #ifdef CONFIG_VM_EVENT_COUNTERS 18f8891e5eSChristoph Lameter DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; 19f8891e5eSChristoph Lameter EXPORT_PER_CPU_SYMBOL(vm_event_states); 20f8891e5eSChristoph Lameter 21f8891e5eSChristoph Lameter static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask) 22f8891e5eSChristoph Lameter { 23f8891e5eSChristoph Lameter int cpu = 0; 24f8891e5eSChristoph Lameter int i; 25f8891e5eSChristoph Lameter 26f8891e5eSChristoph Lameter memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long)); 27f8891e5eSChristoph Lameter 28f8891e5eSChristoph Lameter cpu = first_cpu(*cpumask); 29f8891e5eSChristoph Lameter while (cpu < NR_CPUS) { 30f8891e5eSChristoph Lameter struct vm_event_state *this = &per_cpu(vm_event_states, cpu); 31f8891e5eSChristoph Lameter 32f8891e5eSChristoph Lameter cpu = next_cpu(cpu, *cpumask); 33f8891e5eSChristoph Lameter 34f8891e5eSChristoph Lameter if (cpu < NR_CPUS) 35f8891e5eSChristoph Lameter prefetch(&per_cpu(vm_event_states, cpu)); 36f8891e5eSChristoph Lameter 37f8891e5eSChristoph Lameter 38f8891e5eSChristoph Lameter for (i = 0; i < NR_VM_EVENT_ITEMS; i++) 39f8891e5eSChristoph Lameter ret[i] += this->event[i]; 40f8891e5eSChristoph Lameter } 41f8891e5eSChristoph Lameter } 42f8891e5eSChristoph Lameter 43f8891e5eSChristoph Lameter /* 44f8891e5eSChristoph Lameter * Accumulate the vm event counters across all CPUs. 45f8891e5eSChristoph Lameter * The result is unavoidably approximate - it can change 46f8891e5eSChristoph Lameter * during and after execution of this function. 47f8891e5eSChristoph Lameter */ 48f8891e5eSChristoph Lameter void all_vm_events(unsigned long *ret) 49f8891e5eSChristoph Lameter { 50f8891e5eSChristoph Lameter sum_vm_events(ret, &cpu_online_map); 51f8891e5eSChristoph Lameter } 5232dd66fcSHeiko Carstens EXPORT_SYMBOL_GPL(all_vm_events); 53f8891e5eSChristoph Lameter 54f8891e5eSChristoph Lameter #ifdef CONFIG_HOTPLUG 55f8891e5eSChristoph Lameter /* 56f8891e5eSChristoph Lameter * Fold the foreign cpu events into our own. 57f8891e5eSChristoph Lameter * 58f8891e5eSChristoph Lameter * This is adding to the events on one processor 59f8891e5eSChristoph Lameter * but keeps the global counts constant. 60f8891e5eSChristoph Lameter */ 61f8891e5eSChristoph Lameter void vm_events_fold_cpu(int cpu) 62f8891e5eSChristoph Lameter { 63f8891e5eSChristoph Lameter struct vm_event_state *fold_state = &per_cpu(vm_event_states, cpu); 64f8891e5eSChristoph Lameter int i; 65f8891e5eSChristoph Lameter 66f8891e5eSChristoph Lameter for (i = 0; i < NR_VM_EVENT_ITEMS; i++) { 67f8891e5eSChristoph Lameter count_vm_events(i, fold_state->event[i]); 68f8891e5eSChristoph Lameter fold_state->event[i] = 0; 69f8891e5eSChristoph Lameter } 70f8891e5eSChristoph Lameter } 71f8891e5eSChristoph Lameter #endif /* CONFIG_HOTPLUG */ 72f8891e5eSChristoph Lameter 73f8891e5eSChristoph Lameter #endif /* CONFIG_VM_EVENT_COUNTERS */ 74f8891e5eSChristoph Lameter 752244b95aSChristoph Lameter /* 762244b95aSChristoph Lameter * Manage combined zone based / global counters 772244b95aSChristoph Lameter * 782244b95aSChristoph Lameter * vm_stat contains the global counters 792244b95aSChristoph Lameter */ 802244b95aSChristoph Lameter atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; 812244b95aSChristoph Lameter EXPORT_SYMBOL(vm_stat); 822244b95aSChristoph Lameter 832244b95aSChristoph Lameter #ifdef CONFIG_SMP 842244b95aSChristoph Lameter 85df9ecabaSChristoph Lameter static int calculate_threshold(struct zone *zone) 86df9ecabaSChristoph Lameter { 87df9ecabaSChristoph Lameter int threshold; 88df9ecabaSChristoph Lameter int mem; /* memory in 128 MB units */ 892244b95aSChristoph Lameter 902244b95aSChristoph Lameter /* 91df9ecabaSChristoph Lameter * The threshold scales with the number of processors and the amount 92df9ecabaSChristoph Lameter * of memory per zone. More memory means that we can defer updates for 93df9ecabaSChristoph Lameter * longer, more processors could lead to more contention. 94df9ecabaSChristoph Lameter * fls() is used to have a cheap way of logarithmic scaling. 952244b95aSChristoph Lameter * 96df9ecabaSChristoph Lameter * Some sample thresholds: 97df9ecabaSChristoph Lameter * 98df9ecabaSChristoph Lameter * Threshold Processors (fls) Zonesize fls(mem+1) 99df9ecabaSChristoph Lameter * ------------------------------------------------------------------ 100df9ecabaSChristoph Lameter * 8 1 1 0.9-1 GB 4 101df9ecabaSChristoph Lameter * 16 2 2 0.9-1 GB 4 102df9ecabaSChristoph Lameter * 20 2 2 1-2 GB 5 103df9ecabaSChristoph Lameter * 24 2 2 2-4 GB 6 104df9ecabaSChristoph Lameter * 28 2 2 4-8 GB 7 105df9ecabaSChristoph Lameter * 32 2 2 8-16 GB 8 106df9ecabaSChristoph Lameter * 4 2 2 <128M 1 107df9ecabaSChristoph Lameter * 30 4 3 2-4 GB 5 108df9ecabaSChristoph Lameter * 48 4 3 8-16 GB 8 109df9ecabaSChristoph Lameter * 32 8 4 1-2 GB 4 110df9ecabaSChristoph Lameter * 32 8 4 0.9-1GB 4 111df9ecabaSChristoph Lameter * 10 16 5 <128M 1 112df9ecabaSChristoph Lameter * 40 16 5 900M 4 113df9ecabaSChristoph Lameter * 70 64 7 2-4 GB 5 114df9ecabaSChristoph Lameter * 84 64 7 4-8 GB 6 115df9ecabaSChristoph Lameter * 108 512 9 4-8 GB 6 116df9ecabaSChristoph Lameter * 125 1024 10 8-16 GB 8 117df9ecabaSChristoph Lameter * 125 1024 10 16-32 GB 9 1182244b95aSChristoph Lameter */ 119df9ecabaSChristoph Lameter 120df9ecabaSChristoph Lameter mem = zone->present_pages >> (27 - PAGE_SHIFT); 121df9ecabaSChristoph Lameter 122df9ecabaSChristoph Lameter threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem)); 123df9ecabaSChristoph Lameter 124df9ecabaSChristoph Lameter /* 125df9ecabaSChristoph Lameter * Maximum threshold is 125 126df9ecabaSChristoph Lameter */ 127df9ecabaSChristoph Lameter threshold = min(125, threshold); 128df9ecabaSChristoph Lameter 129df9ecabaSChristoph Lameter return threshold; 130df9ecabaSChristoph Lameter } 131df9ecabaSChristoph Lameter 132df9ecabaSChristoph Lameter /* 133df9ecabaSChristoph Lameter * Refresh the thresholds for each zone. 134df9ecabaSChristoph Lameter */ 135df9ecabaSChristoph Lameter static void refresh_zone_stat_thresholds(void) 1362244b95aSChristoph Lameter { 137df9ecabaSChristoph Lameter struct zone *zone; 138df9ecabaSChristoph Lameter int cpu; 139df9ecabaSChristoph Lameter int threshold; 140df9ecabaSChristoph Lameter 141df9ecabaSChristoph Lameter for_each_zone(zone) { 142df9ecabaSChristoph Lameter 143df9ecabaSChristoph Lameter if (!zone->present_pages) 144df9ecabaSChristoph Lameter continue; 145df9ecabaSChristoph Lameter 146df9ecabaSChristoph Lameter threshold = calculate_threshold(zone); 147df9ecabaSChristoph Lameter 148df9ecabaSChristoph Lameter for_each_online_cpu(cpu) 149df9ecabaSChristoph Lameter zone_pcp(zone, cpu)->stat_threshold = threshold; 150df9ecabaSChristoph Lameter } 1512244b95aSChristoph Lameter } 1522244b95aSChristoph Lameter 1532244b95aSChristoph Lameter /* 1542244b95aSChristoph Lameter * For use when we know that interrupts are disabled. 1552244b95aSChristoph Lameter */ 1562244b95aSChristoph Lameter void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, 1572244b95aSChristoph Lameter int delta) 1582244b95aSChristoph Lameter { 159df9ecabaSChristoph Lameter struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); 160df9ecabaSChristoph Lameter s8 *p = pcp->vm_stat_diff + item; 1612244b95aSChristoph Lameter long x; 1622244b95aSChristoph Lameter 1632244b95aSChristoph Lameter x = delta + *p; 1642244b95aSChristoph Lameter 165df9ecabaSChristoph Lameter if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) { 1662244b95aSChristoph Lameter zone_page_state_add(x, zone, item); 1672244b95aSChristoph Lameter x = 0; 1682244b95aSChristoph Lameter } 1692244b95aSChristoph Lameter *p = x; 1702244b95aSChristoph Lameter } 1712244b95aSChristoph Lameter EXPORT_SYMBOL(__mod_zone_page_state); 1722244b95aSChristoph Lameter 1732244b95aSChristoph Lameter /* 1742244b95aSChristoph Lameter * For an unknown interrupt state 1752244b95aSChristoph Lameter */ 1762244b95aSChristoph Lameter void mod_zone_page_state(struct zone *zone, enum zone_stat_item item, 1772244b95aSChristoph Lameter int delta) 1782244b95aSChristoph Lameter { 1792244b95aSChristoph Lameter unsigned long flags; 1802244b95aSChristoph Lameter 1812244b95aSChristoph Lameter local_irq_save(flags); 1822244b95aSChristoph Lameter __mod_zone_page_state(zone, item, delta); 1832244b95aSChristoph Lameter local_irq_restore(flags); 1842244b95aSChristoph Lameter } 1852244b95aSChristoph Lameter EXPORT_SYMBOL(mod_zone_page_state); 1862244b95aSChristoph Lameter 1872244b95aSChristoph Lameter /* 1882244b95aSChristoph Lameter * Optimized increment and decrement functions. 1892244b95aSChristoph Lameter * 1902244b95aSChristoph Lameter * These are only for a single page and therefore can take a struct page * 1912244b95aSChristoph Lameter * argument instead of struct zone *. This allows the inclusion of the code 1922244b95aSChristoph Lameter * generated for page_zone(page) into the optimized functions. 1932244b95aSChristoph Lameter * 1942244b95aSChristoph Lameter * No overflow check is necessary and therefore the differential can be 1952244b95aSChristoph Lameter * incremented or decremented in place which may allow the compilers to 1962244b95aSChristoph Lameter * generate better code. 1972244b95aSChristoph Lameter * The increment or decrement is known and therefore one boundary check can 1982244b95aSChristoph Lameter * be omitted. 1992244b95aSChristoph Lameter * 200df9ecabaSChristoph Lameter * NOTE: These functions are very performance sensitive. Change only 201df9ecabaSChristoph Lameter * with care. 202df9ecabaSChristoph Lameter * 2032244b95aSChristoph Lameter * Some processors have inc/dec instructions that are atomic vs an interrupt. 2042244b95aSChristoph Lameter * However, the code must first determine the differential location in a zone 2052244b95aSChristoph Lameter * based on the processor number and then inc/dec the counter. There is no 2062244b95aSChristoph Lameter * guarantee without disabling preemption that the processor will not change 2072244b95aSChristoph Lameter * in between and therefore the atomicity vs. interrupt cannot be exploited 2082244b95aSChristoph Lameter * in a useful way here. 2092244b95aSChristoph Lameter */ 210c8785385SChristoph Lameter void __inc_zone_state(struct zone *zone, enum zone_stat_item item) 2112244b95aSChristoph Lameter { 212df9ecabaSChristoph Lameter struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); 213df9ecabaSChristoph Lameter s8 *p = pcp->vm_stat_diff + item; 2142244b95aSChristoph Lameter 2152244b95aSChristoph Lameter (*p)++; 2162244b95aSChristoph Lameter 217df9ecabaSChristoph Lameter if (unlikely(*p > pcp->stat_threshold)) { 218df9ecabaSChristoph Lameter int overstep = pcp->stat_threshold / 2; 219df9ecabaSChristoph Lameter 220df9ecabaSChristoph Lameter zone_page_state_add(*p + overstep, zone, item); 221df9ecabaSChristoph Lameter *p = -overstep; 2222244b95aSChristoph Lameter } 2232244b95aSChristoph Lameter } 224ca889e6cSChristoph Lameter 225ca889e6cSChristoph Lameter void __inc_zone_page_state(struct page *page, enum zone_stat_item item) 226ca889e6cSChristoph Lameter { 227ca889e6cSChristoph Lameter __inc_zone_state(page_zone(page), item); 228ca889e6cSChristoph Lameter } 2292244b95aSChristoph Lameter EXPORT_SYMBOL(__inc_zone_page_state); 2302244b95aSChristoph Lameter 231c8785385SChristoph Lameter void __dec_zone_state(struct zone *zone, enum zone_stat_item item) 2322244b95aSChristoph Lameter { 233df9ecabaSChristoph Lameter struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); 234df9ecabaSChristoph Lameter s8 *p = pcp->vm_stat_diff + item; 2352244b95aSChristoph Lameter 2362244b95aSChristoph Lameter (*p)--; 2372244b95aSChristoph Lameter 238df9ecabaSChristoph Lameter if (unlikely(*p < - pcp->stat_threshold)) { 239df9ecabaSChristoph Lameter int overstep = pcp->stat_threshold / 2; 240df9ecabaSChristoph Lameter 241df9ecabaSChristoph Lameter zone_page_state_add(*p - overstep, zone, item); 242df9ecabaSChristoph Lameter *p = overstep; 2432244b95aSChristoph Lameter } 2442244b95aSChristoph Lameter } 245c8785385SChristoph Lameter 246c8785385SChristoph Lameter void __dec_zone_page_state(struct page *page, enum zone_stat_item item) 247c8785385SChristoph Lameter { 248c8785385SChristoph Lameter __dec_zone_state(page_zone(page), item); 249c8785385SChristoph Lameter } 2502244b95aSChristoph Lameter EXPORT_SYMBOL(__dec_zone_page_state); 2512244b95aSChristoph Lameter 252ca889e6cSChristoph Lameter void inc_zone_state(struct zone *zone, enum zone_stat_item item) 253ca889e6cSChristoph Lameter { 254ca889e6cSChristoph Lameter unsigned long flags; 255ca889e6cSChristoph Lameter 256ca889e6cSChristoph Lameter local_irq_save(flags); 257ca889e6cSChristoph Lameter __inc_zone_state(zone, item); 258ca889e6cSChristoph Lameter local_irq_restore(flags); 259ca889e6cSChristoph Lameter } 260ca889e6cSChristoph Lameter 2612244b95aSChristoph Lameter void inc_zone_page_state(struct page *page, enum zone_stat_item item) 2622244b95aSChristoph Lameter { 2632244b95aSChristoph Lameter unsigned long flags; 2642244b95aSChristoph Lameter struct zone *zone; 2652244b95aSChristoph Lameter 2662244b95aSChristoph Lameter zone = page_zone(page); 2672244b95aSChristoph Lameter local_irq_save(flags); 268ca889e6cSChristoph Lameter __inc_zone_state(zone, item); 2692244b95aSChristoph Lameter local_irq_restore(flags); 2702244b95aSChristoph Lameter } 2712244b95aSChristoph Lameter EXPORT_SYMBOL(inc_zone_page_state); 2722244b95aSChristoph Lameter 2732244b95aSChristoph Lameter void dec_zone_page_state(struct page *page, enum zone_stat_item item) 2742244b95aSChristoph Lameter { 2752244b95aSChristoph Lameter unsigned long flags; 2762244b95aSChristoph Lameter 2772244b95aSChristoph Lameter local_irq_save(flags); 278a302eb4eSChristoph Lameter __dec_zone_page_state(page, item); 2792244b95aSChristoph Lameter local_irq_restore(flags); 2802244b95aSChristoph Lameter } 2812244b95aSChristoph Lameter EXPORT_SYMBOL(dec_zone_page_state); 2822244b95aSChristoph Lameter 2832244b95aSChristoph Lameter /* 2842244b95aSChristoph Lameter * Update the zone counters for one cpu. 2854037d452SChristoph Lameter * 2864037d452SChristoph Lameter * Note that refresh_cpu_vm_stats strives to only access 2874037d452SChristoph Lameter * node local memory. The per cpu pagesets on remote zones are placed 2884037d452SChristoph Lameter * in the memory local to the processor using that pageset. So the 2894037d452SChristoph Lameter * loop over all zones will access a series of cachelines local to 2904037d452SChristoph Lameter * the processor. 2914037d452SChristoph Lameter * 2924037d452SChristoph Lameter * The call to zone_page_state_add updates the cachelines with the 2934037d452SChristoph Lameter * statistics in the remote zone struct as well as the global cachelines 2944037d452SChristoph Lameter * with the global counters. These could cause remote node cache line 2954037d452SChristoph Lameter * bouncing and will have to be only done when necessary. 2962244b95aSChristoph Lameter */ 2972244b95aSChristoph Lameter void refresh_cpu_vm_stats(int cpu) 2982244b95aSChristoph Lameter { 2992244b95aSChristoph Lameter struct zone *zone; 3002244b95aSChristoph Lameter int i; 3012244b95aSChristoph Lameter unsigned long flags; 3022244b95aSChristoph Lameter 3032244b95aSChristoph Lameter for_each_zone(zone) { 3044037d452SChristoph Lameter struct per_cpu_pageset *p; 3052244b95aSChristoph Lameter 30639bbcb8fSChristoph Lameter if (!populated_zone(zone)) 30739bbcb8fSChristoph Lameter continue; 30839bbcb8fSChristoph Lameter 3094037d452SChristoph Lameter p = zone_pcp(zone, cpu); 3102244b95aSChristoph Lameter 3112244b95aSChristoph Lameter for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) 3124037d452SChristoph Lameter if (p->vm_stat_diff[i]) { 3132244b95aSChristoph Lameter local_irq_save(flags); 3144037d452SChristoph Lameter zone_page_state_add(p->vm_stat_diff[i], 3152244b95aSChristoph Lameter zone, i); 3164037d452SChristoph Lameter p->vm_stat_diff[i] = 0; 3174037d452SChristoph Lameter #ifdef CONFIG_NUMA 3184037d452SChristoph Lameter /* 3 seconds idle till flush */ 3194037d452SChristoph Lameter p->expire = 3; 3204037d452SChristoph Lameter #endif 3212244b95aSChristoph Lameter local_irq_restore(flags); 3222244b95aSChristoph Lameter } 3234037d452SChristoph Lameter #ifdef CONFIG_NUMA 3244037d452SChristoph Lameter /* 3254037d452SChristoph Lameter * Deal with draining the remote pageset of this 3264037d452SChristoph Lameter * processor 3274037d452SChristoph Lameter * 3284037d452SChristoph Lameter * Check if there are pages remaining in this pageset 3294037d452SChristoph Lameter * if not then there is nothing to expire. 3304037d452SChristoph Lameter */ 3314037d452SChristoph Lameter if (!p->expire || (!p->pcp[0].count && !p->pcp[1].count)) 3324037d452SChristoph Lameter continue; 3334037d452SChristoph Lameter 3344037d452SChristoph Lameter /* 3354037d452SChristoph Lameter * We never drain zones local to this processor. 3364037d452SChristoph Lameter */ 3374037d452SChristoph Lameter if (zone_to_nid(zone) == numa_node_id()) { 3384037d452SChristoph Lameter p->expire = 0; 3394037d452SChristoph Lameter continue; 3404037d452SChristoph Lameter } 3414037d452SChristoph Lameter 3424037d452SChristoph Lameter p->expire--; 3434037d452SChristoph Lameter if (p->expire) 3444037d452SChristoph Lameter continue; 3454037d452SChristoph Lameter 3464037d452SChristoph Lameter if (p->pcp[0].count) 3474037d452SChristoph Lameter drain_zone_pages(zone, p->pcp + 0); 3484037d452SChristoph Lameter 3494037d452SChristoph Lameter if (p->pcp[1].count) 3504037d452SChristoph Lameter drain_zone_pages(zone, p->pcp + 1); 3514037d452SChristoph Lameter #endif 3522244b95aSChristoph Lameter } 3532244b95aSChristoph Lameter } 3542244b95aSChristoph Lameter 3552244b95aSChristoph Lameter static void __refresh_cpu_vm_stats(void *dummy) 3562244b95aSChristoph Lameter { 3572244b95aSChristoph Lameter refresh_cpu_vm_stats(smp_processor_id()); 3582244b95aSChristoph Lameter } 3592244b95aSChristoph Lameter 3602244b95aSChristoph Lameter /* 3612244b95aSChristoph Lameter * Consolidate all counters. 3622244b95aSChristoph Lameter * 3632244b95aSChristoph Lameter * Note that the result is less inaccurate but still inaccurate 3642244b95aSChristoph Lameter * if concurrent processes are allowed to run. 3652244b95aSChristoph Lameter */ 3662244b95aSChristoph Lameter void refresh_vm_stats(void) 3672244b95aSChristoph Lameter { 3682244b95aSChristoph Lameter on_each_cpu(__refresh_cpu_vm_stats, NULL, 0, 1); 3692244b95aSChristoph Lameter } 3702244b95aSChristoph Lameter EXPORT_SYMBOL(refresh_vm_stats); 3712244b95aSChristoph Lameter 3722244b95aSChristoph Lameter #endif 3732244b95aSChristoph Lameter 374ca889e6cSChristoph Lameter #ifdef CONFIG_NUMA 375ca889e6cSChristoph Lameter /* 376ca889e6cSChristoph Lameter * zonelist = the list of zones passed to the allocator 377ca889e6cSChristoph Lameter * z = the zone from which the allocation occurred. 378ca889e6cSChristoph Lameter * 379ca889e6cSChristoph Lameter * Must be called with interrupts disabled. 380ca889e6cSChristoph Lameter */ 381ca889e6cSChristoph Lameter void zone_statistics(struct zonelist *zonelist, struct zone *z) 382ca889e6cSChristoph Lameter { 383ca889e6cSChristoph Lameter if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) { 384ca889e6cSChristoph Lameter __inc_zone_state(z, NUMA_HIT); 385ca889e6cSChristoph Lameter } else { 386ca889e6cSChristoph Lameter __inc_zone_state(z, NUMA_MISS); 387ca889e6cSChristoph Lameter __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN); 388ca889e6cSChristoph Lameter } 3895d292343SChristoph Lameter if (z->node == numa_node_id()) 390ca889e6cSChristoph Lameter __inc_zone_state(z, NUMA_LOCAL); 391ca889e6cSChristoph Lameter else 392ca889e6cSChristoph Lameter __inc_zone_state(z, NUMA_OTHER); 393ca889e6cSChristoph Lameter } 394ca889e6cSChristoph Lameter #endif 395ca889e6cSChristoph Lameter 396f6ac2354SChristoph Lameter #ifdef CONFIG_PROC_FS 397f6ac2354SChristoph Lameter 398f6ac2354SChristoph Lameter #include <linux/seq_file.h> 399f6ac2354SChristoph Lameter 400f6ac2354SChristoph Lameter static void *frag_start(struct seq_file *m, loff_t *pos) 401f6ac2354SChristoph Lameter { 402f6ac2354SChristoph Lameter pg_data_t *pgdat; 403f6ac2354SChristoph Lameter loff_t node = *pos; 404f6ac2354SChristoph Lameter for (pgdat = first_online_pgdat(); 405f6ac2354SChristoph Lameter pgdat && node; 406f6ac2354SChristoph Lameter pgdat = next_online_pgdat(pgdat)) 407f6ac2354SChristoph Lameter --node; 408f6ac2354SChristoph Lameter 409f6ac2354SChristoph Lameter return pgdat; 410f6ac2354SChristoph Lameter } 411f6ac2354SChristoph Lameter 412f6ac2354SChristoph Lameter static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) 413f6ac2354SChristoph Lameter { 414f6ac2354SChristoph Lameter pg_data_t *pgdat = (pg_data_t *)arg; 415f6ac2354SChristoph Lameter 416f6ac2354SChristoph Lameter (*pos)++; 417f6ac2354SChristoph Lameter return next_online_pgdat(pgdat); 418f6ac2354SChristoph Lameter } 419f6ac2354SChristoph Lameter 420f6ac2354SChristoph Lameter static void frag_stop(struct seq_file *m, void *arg) 421f6ac2354SChristoph Lameter { 422f6ac2354SChristoph Lameter } 423f6ac2354SChristoph Lameter 424f6ac2354SChristoph Lameter /* 425f6ac2354SChristoph Lameter * This walks the free areas for each zone. 426f6ac2354SChristoph Lameter */ 427f6ac2354SChristoph Lameter static int frag_show(struct seq_file *m, void *arg) 428f6ac2354SChristoph Lameter { 429f6ac2354SChristoph Lameter pg_data_t *pgdat = (pg_data_t *)arg; 430f6ac2354SChristoph Lameter struct zone *zone; 431f6ac2354SChristoph Lameter struct zone *node_zones = pgdat->node_zones; 432f6ac2354SChristoph Lameter unsigned long flags; 433f6ac2354SChristoph Lameter int order; 434f6ac2354SChristoph Lameter 435f6ac2354SChristoph Lameter for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { 436f6ac2354SChristoph Lameter if (!populated_zone(zone)) 437f6ac2354SChristoph Lameter continue; 438f6ac2354SChristoph Lameter 439f6ac2354SChristoph Lameter spin_lock_irqsave(&zone->lock, flags); 440f6ac2354SChristoph Lameter seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name); 441f6ac2354SChristoph Lameter for (order = 0; order < MAX_ORDER; ++order) 442f6ac2354SChristoph Lameter seq_printf(m, "%6lu ", zone->free_area[order].nr_free); 443f6ac2354SChristoph Lameter spin_unlock_irqrestore(&zone->lock, flags); 444f6ac2354SChristoph Lameter seq_putc(m, '\n'); 445f6ac2354SChristoph Lameter } 446f6ac2354SChristoph Lameter return 0; 447f6ac2354SChristoph Lameter } 448f6ac2354SChristoph Lameter 44915ad7cdcSHelge Deller const struct seq_operations fragmentation_op = { 450f6ac2354SChristoph Lameter .start = frag_start, 451f6ac2354SChristoph Lameter .next = frag_next, 452f6ac2354SChristoph Lameter .stop = frag_stop, 453f6ac2354SChristoph Lameter .show = frag_show, 454f6ac2354SChristoph Lameter }; 455f6ac2354SChristoph Lameter 4564b51d669SChristoph Lameter #ifdef CONFIG_ZONE_DMA 4574b51d669SChristoph Lameter #define TEXT_FOR_DMA(xx) xx "_dma", 4584b51d669SChristoph Lameter #else 4594b51d669SChristoph Lameter #define TEXT_FOR_DMA(xx) 4604b51d669SChristoph Lameter #endif 4614b51d669SChristoph Lameter 46227bf71c2SChristoph Lameter #ifdef CONFIG_ZONE_DMA32 46327bf71c2SChristoph Lameter #define TEXT_FOR_DMA32(xx) xx "_dma32", 46427bf71c2SChristoph Lameter #else 46527bf71c2SChristoph Lameter #define TEXT_FOR_DMA32(xx) 46627bf71c2SChristoph Lameter #endif 46727bf71c2SChristoph Lameter 46827bf71c2SChristoph Lameter #ifdef CONFIG_HIGHMEM 46927bf71c2SChristoph Lameter #define TEXT_FOR_HIGHMEM(xx) xx "_high", 47027bf71c2SChristoph Lameter #else 47127bf71c2SChristoph Lameter #define TEXT_FOR_HIGHMEM(xx) 47227bf71c2SChristoph Lameter #endif 47327bf71c2SChristoph Lameter 4744b51d669SChristoph Lameter #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \ 47527bf71c2SChristoph Lameter TEXT_FOR_HIGHMEM(xx) 47627bf71c2SChristoph Lameter 47715ad7cdcSHelge Deller static const char * const vmstat_text[] = { 4782244b95aSChristoph Lameter /* Zoned VM counters */ 479d23ad423SChristoph Lameter "nr_free_pages", 480c8785385SChristoph Lameter "nr_active", 481c8785385SChristoph Lameter "nr_inactive", 482f3dbd344SChristoph Lameter "nr_anon_pages", 48365ba55f5SChristoph Lameter "nr_mapped", 484347ce434SChristoph Lameter "nr_file_pages", 48551ed4491SChristoph Lameter "nr_dirty", 48651ed4491SChristoph Lameter "nr_writeback", 487972d1a7bSChristoph Lameter "nr_slab_reclaimable", 488972d1a7bSChristoph Lameter "nr_slab_unreclaimable", 489df849a15SChristoph Lameter "nr_page_table_pages", 490f6ac2354SChristoph Lameter "nr_unstable", 491d2c5e30cSChristoph Lameter "nr_bounce", 492e129b5c2SAndrew Morton "nr_vmscan_write", 493f6ac2354SChristoph Lameter 494ca889e6cSChristoph Lameter #ifdef CONFIG_NUMA 495ca889e6cSChristoph Lameter "numa_hit", 496ca889e6cSChristoph Lameter "numa_miss", 497ca889e6cSChristoph Lameter "numa_foreign", 498ca889e6cSChristoph Lameter "numa_interleave", 499ca889e6cSChristoph Lameter "numa_local", 500ca889e6cSChristoph Lameter "numa_other", 501ca889e6cSChristoph Lameter #endif 502ca889e6cSChristoph Lameter 503f8891e5eSChristoph Lameter #ifdef CONFIG_VM_EVENT_COUNTERS 504f6ac2354SChristoph Lameter "pgpgin", 505f6ac2354SChristoph Lameter "pgpgout", 506f6ac2354SChristoph Lameter "pswpin", 507f6ac2354SChristoph Lameter "pswpout", 508f6ac2354SChristoph Lameter 50927bf71c2SChristoph Lameter TEXTS_FOR_ZONES("pgalloc") 510f6ac2354SChristoph Lameter 511f6ac2354SChristoph Lameter "pgfree", 512f6ac2354SChristoph Lameter "pgactivate", 513f6ac2354SChristoph Lameter "pgdeactivate", 514f6ac2354SChristoph Lameter 515f6ac2354SChristoph Lameter "pgfault", 516f6ac2354SChristoph Lameter "pgmajfault", 517f6ac2354SChristoph Lameter 51827bf71c2SChristoph Lameter TEXTS_FOR_ZONES("pgrefill") 51927bf71c2SChristoph Lameter TEXTS_FOR_ZONES("pgsteal") 52027bf71c2SChristoph Lameter TEXTS_FOR_ZONES("pgscan_kswapd") 52127bf71c2SChristoph Lameter TEXTS_FOR_ZONES("pgscan_direct") 522f6ac2354SChristoph Lameter 523f6ac2354SChristoph Lameter "pginodesteal", 524f6ac2354SChristoph Lameter "slabs_scanned", 525f6ac2354SChristoph Lameter "kswapd_steal", 526f6ac2354SChristoph Lameter "kswapd_inodesteal", 527f6ac2354SChristoph Lameter "pageoutrun", 528f6ac2354SChristoph Lameter "allocstall", 529f6ac2354SChristoph Lameter 530f6ac2354SChristoph Lameter "pgrotated", 531f8891e5eSChristoph Lameter #endif 532f6ac2354SChristoph Lameter }; 533f6ac2354SChristoph Lameter 534f6ac2354SChristoph Lameter /* 535f6ac2354SChristoph Lameter * Output information about zones in @pgdat. 536f6ac2354SChristoph Lameter */ 537f6ac2354SChristoph Lameter static int zoneinfo_show(struct seq_file *m, void *arg) 538f6ac2354SChristoph Lameter { 539f6ac2354SChristoph Lameter pg_data_t *pgdat = arg; 540f6ac2354SChristoph Lameter struct zone *zone; 541f6ac2354SChristoph Lameter struct zone *node_zones = pgdat->node_zones; 542f6ac2354SChristoph Lameter unsigned long flags; 543f6ac2354SChristoph Lameter 544f6ac2354SChristoph Lameter for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) { 545f6ac2354SChristoph Lameter int i; 546f6ac2354SChristoph Lameter 547f6ac2354SChristoph Lameter if (!populated_zone(zone)) 548f6ac2354SChristoph Lameter continue; 549f6ac2354SChristoph Lameter 550f6ac2354SChristoph Lameter spin_lock_irqsave(&zone->lock, flags); 551f6ac2354SChristoph Lameter seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); 552f6ac2354SChristoph Lameter seq_printf(m, 553f6ac2354SChristoph Lameter "\n pages free %lu" 554f6ac2354SChristoph Lameter "\n min %lu" 555f6ac2354SChristoph Lameter "\n low %lu" 556f6ac2354SChristoph Lameter "\n high %lu" 557f6ac2354SChristoph Lameter "\n scanned %lu (a: %lu i: %lu)" 558f6ac2354SChristoph Lameter "\n spanned %lu" 559f6ac2354SChristoph Lameter "\n present %lu", 560d23ad423SChristoph Lameter zone_page_state(zone, NR_FREE_PAGES), 561f6ac2354SChristoph Lameter zone->pages_min, 562f6ac2354SChristoph Lameter zone->pages_low, 563f6ac2354SChristoph Lameter zone->pages_high, 564f6ac2354SChristoph Lameter zone->pages_scanned, 565f6ac2354SChristoph Lameter zone->nr_scan_active, zone->nr_scan_inactive, 566f6ac2354SChristoph Lameter zone->spanned_pages, 567f6ac2354SChristoph Lameter zone->present_pages); 5682244b95aSChristoph Lameter 5692244b95aSChristoph Lameter for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) 5702244b95aSChristoph Lameter seq_printf(m, "\n %-12s %lu", vmstat_text[i], 5712244b95aSChristoph Lameter zone_page_state(zone, i)); 5722244b95aSChristoph Lameter 573f6ac2354SChristoph Lameter seq_printf(m, 574f6ac2354SChristoph Lameter "\n protection: (%lu", 575f6ac2354SChristoph Lameter zone->lowmem_reserve[0]); 576f6ac2354SChristoph Lameter for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) 577f6ac2354SChristoph Lameter seq_printf(m, ", %lu", zone->lowmem_reserve[i]); 578f6ac2354SChristoph Lameter seq_printf(m, 579f6ac2354SChristoph Lameter ")" 580f6ac2354SChristoph Lameter "\n pagesets"); 581f6ac2354SChristoph Lameter for_each_online_cpu(i) { 582f6ac2354SChristoph Lameter struct per_cpu_pageset *pageset; 583f6ac2354SChristoph Lameter int j; 584f6ac2354SChristoph Lameter 585f6ac2354SChristoph Lameter pageset = zone_pcp(zone, i); 586f6ac2354SChristoph Lameter for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { 587f6ac2354SChristoph Lameter seq_printf(m, 588f6ac2354SChristoph Lameter "\n cpu: %i pcp: %i" 589f6ac2354SChristoph Lameter "\n count: %i" 590f6ac2354SChristoph Lameter "\n high: %i" 591f6ac2354SChristoph Lameter "\n batch: %i", 592f6ac2354SChristoph Lameter i, j, 593f6ac2354SChristoph Lameter pageset->pcp[j].count, 594f6ac2354SChristoph Lameter pageset->pcp[j].high, 595f6ac2354SChristoph Lameter pageset->pcp[j].batch); 596f6ac2354SChristoph Lameter } 597df9ecabaSChristoph Lameter #ifdef CONFIG_SMP 598df9ecabaSChristoph Lameter seq_printf(m, "\n vm stats threshold: %d", 599df9ecabaSChristoph Lameter pageset->stat_threshold); 600df9ecabaSChristoph Lameter #endif 601f6ac2354SChristoph Lameter } 602f6ac2354SChristoph Lameter seq_printf(m, 603f6ac2354SChristoph Lameter "\n all_unreclaimable: %u" 604f6ac2354SChristoph Lameter "\n prev_priority: %i" 605f6ac2354SChristoph Lameter "\n start_pfn: %lu", 606f6ac2354SChristoph Lameter zone->all_unreclaimable, 607f6ac2354SChristoph Lameter zone->prev_priority, 608f6ac2354SChristoph Lameter zone->zone_start_pfn); 609f6ac2354SChristoph Lameter spin_unlock_irqrestore(&zone->lock, flags); 610f6ac2354SChristoph Lameter seq_putc(m, '\n'); 611f6ac2354SChristoph Lameter } 612f6ac2354SChristoph Lameter return 0; 613f6ac2354SChristoph Lameter } 614f6ac2354SChristoph Lameter 61515ad7cdcSHelge Deller const struct seq_operations zoneinfo_op = { 616f6ac2354SChristoph Lameter .start = frag_start, /* iterate over all zones. The same as in 617f6ac2354SChristoph Lameter * fragmentation. */ 618f6ac2354SChristoph Lameter .next = frag_next, 619f6ac2354SChristoph Lameter .stop = frag_stop, 620f6ac2354SChristoph Lameter .show = zoneinfo_show, 621f6ac2354SChristoph Lameter }; 622f6ac2354SChristoph Lameter 623f6ac2354SChristoph Lameter static void *vmstat_start(struct seq_file *m, loff_t *pos) 624f6ac2354SChristoph Lameter { 6252244b95aSChristoph Lameter unsigned long *v; 626f8891e5eSChristoph Lameter #ifdef CONFIG_VM_EVENT_COUNTERS 627f8891e5eSChristoph Lameter unsigned long *e; 628f8891e5eSChristoph Lameter #endif 6292244b95aSChristoph Lameter int i; 630f6ac2354SChristoph Lameter 631f6ac2354SChristoph Lameter if (*pos >= ARRAY_SIZE(vmstat_text)) 632f6ac2354SChristoph Lameter return NULL; 633f6ac2354SChristoph Lameter 634f8891e5eSChristoph Lameter #ifdef CONFIG_VM_EVENT_COUNTERS 6352244b95aSChristoph Lameter v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) 636f8891e5eSChristoph Lameter + sizeof(struct vm_event_state), GFP_KERNEL); 637f8891e5eSChristoph Lameter #else 638f8891e5eSChristoph Lameter v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long), 639f8891e5eSChristoph Lameter GFP_KERNEL); 640f8891e5eSChristoph Lameter #endif 6412244b95aSChristoph Lameter m->private = v; 6422244b95aSChristoph Lameter if (!v) 643f6ac2354SChristoph Lameter return ERR_PTR(-ENOMEM); 6442244b95aSChristoph Lameter for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) 6452244b95aSChristoph Lameter v[i] = global_page_state(i); 646f8891e5eSChristoph Lameter #ifdef CONFIG_VM_EVENT_COUNTERS 647f8891e5eSChristoph Lameter e = v + NR_VM_ZONE_STAT_ITEMS; 648f8891e5eSChristoph Lameter all_vm_events(e); 649f8891e5eSChristoph Lameter e[PGPGIN] /= 2; /* sectors -> kbytes */ 650f8891e5eSChristoph Lameter e[PGPGOUT] /= 2; 651f8891e5eSChristoph Lameter #endif 6522244b95aSChristoph Lameter return v + *pos; 653f6ac2354SChristoph Lameter } 654f6ac2354SChristoph Lameter 655f6ac2354SChristoph Lameter static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) 656f6ac2354SChristoph Lameter { 657f6ac2354SChristoph Lameter (*pos)++; 658f6ac2354SChristoph Lameter if (*pos >= ARRAY_SIZE(vmstat_text)) 659f6ac2354SChristoph Lameter return NULL; 660f6ac2354SChristoph Lameter return (unsigned long *)m->private + *pos; 661f6ac2354SChristoph Lameter } 662f6ac2354SChristoph Lameter 663f6ac2354SChristoph Lameter static int vmstat_show(struct seq_file *m, void *arg) 664f6ac2354SChristoph Lameter { 665f6ac2354SChristoph Lameter unsigned long *l = arg; 666f6ac2354SChristoph Lameter unsigned long off = l - (unsigned long *)m->private; 667f6ac2354SChristoph Lameter 668f6ac2354SChristoph Lameter seq_printf(m, "%s %lu\n", vmstat_text[off], *l); 669f6ac2354SChristoph Lameter return 0; 670f6ac2354SChristoph Lameter } 671f6ac2354SChristoph Lameter 672f6ac2354SChristoph Lameter static void vmstat_stop(struct seq_file *m, void *arg) 673f6ac2354SChristoph Lameter { 674f6ac2354SChristoph Lameter kfree(m->private); 675f6ac2354SChristoph Lameter m->private = NULL; 676f6ac2354SChristoph Lameter } 677f6ac2354SChristoph Lameter 67815ad7cdcSHelge Deller const struct seq_operations vmstat_op = { 679f6ac2354SChristoph Lameter .start = vmstat_start, 680f6ac2354SChristoph Lameter .next = vmstat_next, 681f6ac2354SChristoph Lameter .stop = vmstat_stop, 682f6ac2354SChristoph Lameter .show = vmstat_show, 683f6ac2354SChristoph Lameter }; 684f6ac2354SChristoph Lameter 685f6ac2354SChristoph Lameter #endif /* CONFIG_PROC_FS */ 686f6ac2354SChristoph Lameter 687df9ecabaSChristoph Lameter #ifdef CONFIG_SMP 688d1187ed2SChristoph Lameter static DEFINE_PER_CPU(struct delayed_work, vmstat_work); 68977461ab3SChristoph Lameter int sysctl_stat_interval __read_mostly = HZ; 690d1187ed2SChristoph Lameter 691d1187ed2SChristoph Lameter static void vmstat_update(struct work_struct *w) 692d1187ed2SChristoph Lameter { 693d1187ed2SChristoph Lameter refresh_cpu_vm_stats(smp_processor_id()); 69477461ab3SChristoph Lameter schedule_delayed_work(&__get_cpu_var(vmstat_work), 69577461ab3SChristoph Lameter sysctl_stat_interval); 696d1187ed2SChristoph Lameter } 697d1187ed2SChristoph Lameter 698d1187ed2SChristoph Lameter static void __devinit start_cpu_timer(int cpu) 699d1187ed2SChristoph Lameter { 700d1187ed2SChristoph Lameter struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); 701d1187ed2SChristoph Lameter 70239bf6270SChristoph Lameter INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update); 703d1187ed2SChristoph Lameter schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu); 704d1187ed2SChristoph Lameter } 705d1187ed2SChristoph Lameter 706df9ecabaSChristoph Lameter /* 707df9ecabaSChristoph Lameter * Use the cpu notifier to insure that the thresholds are recalculated 708df9ecabaSChristoph Lameter * when necessary. 709df9ecabaSChristoph Lameter */ 710df9ecabaSChristoph Lameter static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, 711df9ecabaSChristoph Lameter unsigned long action, 712df9ecabaSChristoph Lameter void *hcpu) 713df9ecabaSChristoph Lameter { 714d1187ed2SChristoph Lameter long cpu = (long)hcpu; 715d1187ed2SChristoph Lameter 716df9ecabaSChristoph Lameter switch (action) { 717d1187ed2SChristoph Lameter case CPU_ONLINE: 718d1187ed2SChristoph Lameter case CPU_ONLINE_FROZEN: 719d1187ed2SChristoph Lameter start_cpu_timer(cpu); 720d1187ed2SChristoph Lameter break; 721d1187ed2SChristoph Lameter case CPU_DOWN_PREPARE: 722d1187ed2SChristoph Lameter case CPU_DOWN_PREPARE_FROZEN: 723d1187ed2SChristoph Lameter cancel_rearming_delayed_work(&per_cpu(vmstat_work, cpu)); 724d1187ed2SChristoph Lameter per_cpu(vmstat_work, cpu).work.func = NULL; 725d1187ed2SChristoph Lameter break; 726d1187ed2SChristoph Lameter case CPU_DOWN_FAILED: 727d1187ed2SChristoph Lameter case CPU_DOWN_FAILED_FROZEN: 728d1187ed2SChristoph Lameter start_cpu_timer(cpu); 729d1187ed2SChristoph Lameter break; 730df9ecabaSChristoph Lameter case CPU_DEAD: 7318bb78442SRafael J. Wysocki case CPU_DEAD_FROZEN: 732df9ecabaSChristoph Lameter refresh_zone_stat_thresholds(); 733df9ecabaSChristoph Lameter break; 734df9ecabaSChristoph Lameter default: 735df9ecabaSChristoph Lameter break; 736df9ecabaSChristoph Lameter } 737df9ecabaSChristoph Lameter return NOTIFY_OK; 738df9ecabaSChristoph Lameter } 739df9ecabaSChristoph Lameter 740df9ecabaSChristoph Lameter static struct notifier_block __cpuinitdata vmstat_notifier = 741df9ecabaSChristoph Lameter { &vmstat_cpuup_callback, NULL, 0 }; 742df9ecabaSChristoph Lameter 743df9ecabaSChristoph Lameter int __init setup_vmstat(void) 744df9ecabaSChristoph Lameter { 745d1187ed2SChristoph Lameter int cpu; 746d1187ed2SChristoph Lameter 747df9ecabaSChristoph Lameter refresh_zone_stat_thresholds(); 748df9ecabaSChristoph Lameter register_cpu_notifier(&vmstat_notifier); 749d1187ed2SChristoph Lameter 750d1187ed2SChristoph Lameter for_each_online_cpu(cpu) 751d1187ed2SChristoph Lameter start_cpu_timer(cpu); 752df9ecabaSChristoph Lameter return 0; 753df9ecabaSChristoph Lameter } 754df9ecabaSChristoph Lameter module_init(setup_vmstat) 755df9ecabaSChristoph Lameter #endif 756