patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / mm / page_alloc.c
index ff2ffbe..d7270d7 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/topology.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
+#include <linux/vs_base.h>
+#include <linux/vs_limit.h>
 
 #include <asm/tlbflush.h>
 
@@ -73,9 +75,9 @@ static void bad_page(const char *function, struct page *page)
 {
        printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
                function, current->comm, page);
-       printk(KERN_EMERG "flags:0x%08lx mapping:%p mapped:%d count:%d\n",
+       printk(KERN_EMERG "flags:0x%08lx mapping:%p mapcount:%d count:%d\n",
                (unsigned long)page->flags, page->mapping,
-               page_mapped(page), page_count(page));
+               (int)page->mapcount, page_count(page));
        printk(KERN_EMERG "Backtrace:\n");
        dump_stack();
        printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
@@ -90,6 +92,7 @@ static void bad_page(const char *function, struct page *page)
                        1 << PG_writeback);
        set_page_count(page, 0);
        page->mapping = NULL;
+       page->mapcount = 0;
 }
 
 #ifndef CONFIG_HUGETLB_PAGE
@@ -460,6 +463,32 @@ void drain_local_pages(void)
 }
 #endif /* CONFIG_PM */
 
+static void zone_statistics(struct zonelist *zonelist, struct zone *z)
+{
+#ifdef CONFIG_NUMA
+       unsigned long flags;
+       int cpu;
+       pg_data_t *pg = z->zone_pgdat;
+       pg_data_t *orig = zonelist->zones[0]->zone_pgdat;
+       struct per_cpu_pageset *p;
+
+       local_irq_save(flags);
+       cpu = smp_processor_id();
+       p = &z->pageset[cpu];
+       if (pg == orig) {
+               z->pageset[cpu].numa_hit++;
+       } else {
+               p->numa_miss++;
+               zonelist->zones[0]->pageset[cpu].numa_foreign++;
+       }
+       if (pg == NODE_DATA(numa_node_id()))
+               p->local_node++;
+       else
+               p->other_node++;
+       local_irq_restore(flags);
+#endif
+}
+
 /*
  * Free a 0-order page
  */
@@ -593,8 +622,10 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
                if (z->free_pages >= min ||
                                (!wait && z->free_pages >= z->pages_high)) {
                        page = buffered_rmqueue(z, order, gfp_mask);
-                       if (page)
+                       if (page) {
+                               zone_statistics(zonelist, z);
                                goto got_pg;
+                       }
                }
        }
 
@@ -616,8 +647,10 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
                if (z->free_pages >= min ||
                                (!wait && z->free_pages >= z->pages_high)) {
                        page = buffered_rmqueue(z, order, gfp_mask);
-                       if (page)
+                       if (page) {
+                               zone_statistics(zonelist, z);
                                goto got_pg;
+                       }
                }
        }
 
@@ -630,8 +663,10 @@ rebalance:
                        struct zone *z = zones[i];
 
                        page = buffered_rmqueue(z, order, gfp_mask);
-                       if (page)
+                       if (page) {
+                               zone_statistics(zonelist, z);
                                goto got_pg;
+                       }
                }
                goto nopage;
        }
@@ -658,8 +693,10 @@ rebalance:
                if (z->free_pages >= min ||
                                (!wait && z->free_pages >= z->pages_high)) {
                        page = buffered_rmqueue(z, order, gfp_mask);
-                       if (page)
+                       if (page) {
+                               zone_statistics(zonelist, z);
                                goto got_pg;
+                       }
                }
        }
 
@@ -953,6 +990,23 @@ void get_full_page_state(struct page_state *ret)
        __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
 }
 
+unsigned long __read_page_state(unsigned offset)
+{
+       unsigned long ret = 0;
+       int cpu;
+
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               unsigned long in;
+
+               if (!cpu_possible(cpu))
+                       continue;
+
+               in = (unsigned long)&per_cpu(page_states, cpu) + offset;
+               ret += *((unsigned long *)in);
+       }
+       return ret;
+}
+
 void get_zone_counts(unsigned long *active,
                unsigned long *inactive, unsigned long *free)
 {
@@ -1286,7 +1340,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
                for (node = 0; node < local_node; node++)
                        j = build_zonelists_node(NODE_DATA(node), zonelist, j, k);
  
-               zonelist->zones[j++] = NULL;
+               zonelist->zones[j] = NULL;
        }
 }