aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/node.c2
-rw-r--r--include/linux/mm.h6
-rw-r--r--include/linux/mmzone.h11
-rw-r--r--init/main.c1
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/page_alloc.c211
6 files changed, 195 insertions, 38 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 5d4517ccc422..904b27caf697 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -87,7 +87,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
87 for (i = 0; i < MAX_NR_ZONES; i++) { 87 for (i = 0; i < MAX_NR_ZONES; i++) {
88 struct zone *z = &pg->node_zones[i]; 88 struct zone *z = &pg->node_zones[i];
89 for (cpu = 0; cpu < NR_CPUS; cpu++) { 89 for (cpu = 0; cpu < NR_CPUS; cpu++) {
90 struct per_cpu_pageset *ps = &z->pageset[cpu]; 90 struct per_cpu_pageset *ps = zone_pcp(z,cpu);
91 numa_hit += ps->numa_hit; 91 numa_hit += ps->numa_hit;
92 numa_miss += ps->numa_miss; 92 numa_miss += ps->numa_miss;
93 numa_foreign += ps->numa_foreign; 93 numa_foreign += ps->numa_foreign;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 17518fe0b311..1813b162b0a8 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -691,6 +691,12 @@ extern void show_mem(void);
691extern void si_meminfo(struct sysinfo * val); 691extern void si_meminfo(struct sysinfo * val);
692extern void si_meminfo_node(struct sysinfo *val, int nid); 692extern void si_meminfo_node(struct sysinfo *val, int nid);
693 693
694#ifdef CONFIG_NUMA
695extern void setup_per_cpu_pageset(void);
696#else
697static inline void setup_per_cpu_pageset(void) {}
698#endif
699
694/* prio_tree.c */ 700/* prio_tree.c */
695void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old); 701void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
696void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *); 702void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 18fed8b67943..4733d35d8223 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -63,6 +63,12 @@ struct per_cpu_pageset {
63#endif 63#endif
64} ____cacheline_aligned_in_smp; 64} ____cacheline_aligned_in_smp;
65 65
66#ifdef CONFIG_NUMA
67#define zone_pcp(__z, __cpu) ((__z)->pageset[(__cpu)])
68#else
69#define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
70#endif
71
66#define ZONE_DMA 0 72#define ZONE_DMA 0
67#define ZONE_NORMAL 1 73#define ZONE_NORMAL 1
68#define ZONE_HIGHMEM 2 74#define ZONE_HIGHMEM 2
@@ -122,8 +128,11 @@ struct zone {
122 */ 128 */
123 unsigned long lowmem_reserve[MAX_NR_ZONES]; 129 unsigned long lowmem_reserve[MAX_NR_ZONES];
124 130
131#ifdef CONFIG_NUMA
132 struct per_cpu_pageset *pageset[NR_CPUS];
133#else
125 struct per_cpu_pageset pageset[NR_CPUS]; 134 struct per_cpu_pageset pageset[NR_CPUS];
126 135#endif
127 /* 136 /*
128 * free areas of different sizes 137 * free areas of different sizes
129 */ 138 */
diff --git a/init/main.c b/init/main.c
index 40bf367ffdf1..d324801729ba 100644
--- a/init/main.c
+++ b/init/main.c
@@ -490,6 +490,7 @@ asmlinkage void __init start_kernel(void)
490 vfs_caches_init_early(); 490 vfs_caches_init_early();
491 mem_init(); 491 mem_init();
492 kmem_cache_init(); 492 kmem_cache_init();
493 setup_per_cpu_pageset();
493 numa_policy_init(); 494 numa_policy_init();
494 if (late_time_init) 495 if (late_time_init)
495 late_time_init(); 496 late_time_init();
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 08c41da429cf..39252c732db2 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -721,7 +721,7 @@ static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned or
721 zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK); 721 zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
722 page = __alloc_pages(gfp, order, zl); 722 page = __alloc_pages(gfp, order, zl);
723 if (page && page_zone(page) == zl->zones[0]) { 723 if (page && page_zone(page) == zl->zones[0]) {
724 zl->zones[0]->pageset[get_cpu()].interleave_hit++; 724 zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
725 put_cpu(); 725 put_cpu();
726 } 726 }
727 return page; 727 return page;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2019c1b19254..95cbd30a67b8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -71,6 +71,11 @@ EXPORT_SYMBOL(nr_swap_pages);
71struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)]; 71struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)];
72EXPORT_SYMBOL(zone_table); 72EXPORT_SYMBOL(zone_table);
73 73
74#ifdef CONFIG_NUMA
75static struct per_cpu_pageset
76 pageset_table[MAX_NR_ZONES*MAX_NUMNODES*NR_CPUS] __initdata;
77#endif
78
74static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; 79static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
75int min_free_kbytes = 1024; 80int min_free_kbytes = 1024;
76 81
@@ -520,7 +525,7 @@ static void __drain_pages(unsigned int cpu)
520 for_each_zone(zone) { 525 for_each_zone(zone) {
521 struct per_cpu_pageset *pset; 526 struct per_cpu_pageset *pset;
522 527
523 pset = &zone->pageset[cpu]; 528 pset = zone_pcp(zone, cpu);
524 for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { 529 for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
525 struct per_cpu_pages *pcp; 530 struct per_cpu_pages *pcp;
526 531
@@ -583,12 +588,12 @@ static void zone_statistics(struct zonelist *zonelist, struct zone *z)
583 588
584 local_irq_save(flags); 589 local_irq_save(flags);
585 cpu = smp_processor_id(); 590 cpu = smp_processor_id();
586 p = &z->pageset[cpu]; 591 p = zone_pcp(z,cpu);
587 if (pg == orig) { 592 if (pg == orig) {
588 z->pageset[cpu].numa_hit++; 593 p->numa_hit++;
589 } else { 594 } else {
590 p->numa_miss++; 595 p->numa_miss++;
591 zonelist->zones[0]->pageset[cpu].numa_foreign++; 596 zone_pcp(zonelist->zones[0], cpu)->numa_foreign++;
592 } 597 }
593 if (pg == NODE_DATA(numa_node_id())) 598 if (pg == NODE_DATA(numa_node_id()))
594 p->local_node++; 599 p->local_node++;
@@ -615,7 +620,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
615 if (PageAnon(page)) 620 if (PageAnon(page))
616 page->mapping = NULL; 621 page->mapping = NULL;
617 free_pages_check(__FUNCTION__, page); 622 free_pages_check(__FUNCTION__, page);
618 pcp = &zone->pageset[get_cpu()].pcp[cold]; 623 pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
619 local_irq_save(flags); 624 local_irq_save(flags);
620 if (pcp->count >= pcp->high) 625 if (pcp->count >= pcp->high)
621 pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0); 626 pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
@@ -659,7 +664,7 @@ buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags)
659 if (order == 0) { 664 if (order == 0) {
660 struct per_cpu_pages *pcp; 665 struct per_cpu_pages *pcp;
661 666
662 pcp = &zone->pageset[get_cpu()].pcp[cold]; 667 pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
663 local_irq_save(flags); 668 local_irq_save(flags);
664 if (pcp->count <= pcp->low) 669 if (pcp->count <= pcp->low)
665 pcp->count += rmqueue_bulk(zone, 0, 670 pcp->count += rmqueue_bulk(zone, 0,
@@ -1262,7 +1267,7 @@ void show_free_areas(void)
1262 if (!cpu_possible(cpu)) 1267 if (!cpu_possible(cpu))
1263 continue; 1268 continue;
1264 1269
1265 pageset = zone->pageset + cpu; 1270 pageset = zone_pcp(zone, cpu);
1266 1271
1267 for (temperature = 0; temperature < 2; temperature++) 1272 for (temperature = 0; temperature < 2; temperature++)
1268 printk("cpu %d %s: low %d, high %d, batch %d\n", 1273 printk("cpu %d %s: low %d, high %d, batch %d\n",
@@ -1645,6 +1650,157 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
1645 memmap_init_zone((size), (nid), (zone), (start_pfn)) 1650 memmap_init_zone((size), (nid), (zone), (start_pfn))
1646#endif 1651#endif
1647 1652
1653static int __devinit zone_batchsize(struct zone *zone)
1654{
1655 int batch;
1656
1657 /*
1658 * The per-cpu-pages pools are set to around 1000th of the
1659 * size of the zone. But no more than 1/4 of a meg - there's
1660 * no point in going beyond the size of L2 cache.
1661 *
1662 * OK, so we don't know how big the cache is. So guess.
1663 */
1664 batch = zone->present_pages / 1024;
1665 if (batch * PAGE_SIZE > 256 * 1024)
1666 batch = (256 * 1024) / PAGE_SIZE;
1667 batch /= 4; /* We effectively *= 4 below */
1668 if (batch < 1)
1669 batch = 1;
1670