diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index df54e2fc8ee0..234bd4895d14 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -56,6 +56,7 @@ long nr_swap_pages; | |||
| 56 | int percpu_pagelist_fraction; | 56 | int percpu_pagelist_fraction; |
| 57 | 57 | ||
| 58 | static void fastcall free_hot_cold_page(struct page *page, int cold); | 58 | static void fastcall free_hot_cold_page(struct page *page, int cold); |
| 59 | static void __free_pages_ok(struct page *page, unsigned int order); | ||
| 59 | 60 | ||
| 60 | /* | 61 | /* |
| 61 | * results with 256, 32 in the lowmem_reserve sysctl: | 62 | * results with 256, 32 in the lowmem_reserve sysctl: |
| @@ -169,20 +170,23 @@ static void bad_page(struct page *page) | |||
| 169 | * All pages have PG_compound set. All pages have their ->private pointing at | 170 | * All pages have PG_compound set. All pages have their ->private pointing at |
| 170 | * the head page (even the head page has this). | 171 | * the head page (even the head page has this). |
| 171 | * | 172 | * |
| 172 | * The first tail page's ->mapping, if non-zero, holds the address of the | 173 | * The first tail page's ->lru.next holds the address of the compound page's |
| 173 | * compound page's put_page() function. | 174 | * put_page() function. Its ->lru.prev holds the order of allocation. |
| 174 | * | 175 | * This usage means that zero-order pages may not be compound. |
| 175 | * The order of the allocation is stored in the first tail page's ->index | ||
| 176 | * This is only for debug at present. This usage means that zero-order pages | ||
| 177 | * may not be compound. | ||
| 178 | */ | 176 | */ |
| 177 | |||
| 178 | static void free_compound_page(struct page *page) | ||
| 179 | { | ||
| 180 | __free_pages_ok(page, (unsigned long)page[1].lru.prev); | ||
| 181 | } | ||
| 182 | |||
| 179 | static void prep_compound_page(struct page *page, unsigned long order) | 183 | static void prep_compound_page(struct page *page, unsigned long order) |
| 180 | { | 184 | { |
| 181 | int i; | 185 | int i; |
| 182 | int nr_pages = 1 << order; | 186 | int nr_pages = 1 << order; |
| 183 | 187 | ||
| 184 | page[1].mapping = NULL; | 188 | page[1].lru.next = (void *)free_compound_page; /* set dtor */ |
| 185 | page[1].index = order; | 189 | page[1].lru.prev = (void *)order; |
| 186 | for (i = 0; i < nr_pages; i++) { | 190 | for (i = 0; i < nr_pages; i++) { |
| 187 | struct page *p = page + i; | 191 | struct page *p = page + i; |
| 188 | 192 | ||
| @@ -196,7 +200,7 @@ static void destroy_compound_page(struct page *page, unsigned long order) | |||
| 196 | int i; | 200 | int i; |
| 197 | int nr_pages = 1 << order; | 201 | int nr_pages = 1 << order; |
| 198 | 202 | ||
| 199 | if (unlikely(page[1].index != order)) | 203 | if (unlikely((unsigned long)page[1].lru.prev != order)) |
| 200 | bad_page(page); | 204 | bad_page(page); |
| 201 | 205 | ||
| 202 | for (i = 0; i < nr_pages; i++) { | 206 | for (i = 0; i < nr_pages; i++) { |
| @@ -586,21 +590,20 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, | |||
| 586 | } | 590 | } |
| 587 | 591 | ||
| 588 | #ifdef CONFIG_NUMA | 592 | #ifdef CONFIG_NUMA |
| 589 | /* Called from the slab reaper to drain remote pagesets */ | 593 | /* |
| 590 | void drain_remote_pages(void) | 594 | * Called from the slab reaper to drain pagesets on a particular node that |
| 595 | * belong to the currently executing processor. | ||
| 596 | */ | ||
| 597 | void drain_node_pages(int nodeid) | ||
| 591 | { | 598 | { |
| 592 | struct zone *zone; | 599 | int i, z; |
| 593 | int i; | ||
| 594 | unsigned long flags; | 600 | unsigned long flags; |
| 595 | 601 | ||
| 596 | local_irq_save(flags); | 602 | local_irq_save(flags); |
| 597 | for_each_zone(zone) { | 603 | for (z = 0; z < MAX_NR_ZONES; z++) { |
| 604 | struct zone *zone = NODE_DATA(nodeid)->node_zones + z; | ||
| 598 | struct per_cpu_pageset *pset; | 605 | struct per_cpu_pageset *pset; |
| 599 | 606 | ||
| 600 | /* Do not drain local pagesets */ | ||
| 601 | if (zone->zone_pgdat->node_id == numa_node_id()) | ||
| 602 | continue; | ||
| 603 | |||
| 604 | pset = zone_pcp(zone, smp_processor_id()); | 607 | pset = zone_pcp(zone, smp_processor_id()); |
| 605 | for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { | 608 | for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { |
| 606 | struct per_cpu_pages *pcp; | 609 | struct per_cpu_pages *pcp; |
| @@ -1011,7 +1014,7 @@ rebalance: | |||
| 1011 | if (page) | 1014 | if (page) |
| 1012 | goto got_pg; | 1015 | goto got_pg; |
| 1013 | 1016 | ||
| 1014 | out_of_memory(gfp_mask, order); | 1017 | out_of_memory(zonelist, gfp_mask, order); |
| 1015 | goto restart; | 1018 | goto restart; |
| 1016 | } | 1019 | } |
| 1017 | 1020 | ||
| @@ -1213,18 +1216,21 @@ static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) | |||
| 1213 | { | 1216 | { |
| 1214 | int cpu = 0; | 1217 | int cpu = 0; |
| 1215 | 1218 | ||
| 1216 | memset(ret, 0, sizeof(*ret)); | 1219 | memset(ret, 0, nr * sizeof(unsigned long)); |
| 1217 | cpus_and(*cpumask, *cpumask, cpu_online_map); | 1220 | cpus_and(*cpumask, *cpumask, cpu_online_map); |
| 1218 | 1221 | ||
| 1219 | cpu = first_cpu(*cpumask); | 1222 | cpu = first_cpu(*cpumask); |
| 1220 | while (cpu < NR_CPUS) { | 1223 | while (cpu < NR_CPUS) { |
| 1221 | unsigned long *in, *out, off; | 1224 | unsigned long *in, *out, off; |
| 1222 | 1225 | ||
| 1226 | if (!cpu_isset(cpu, *cpumask)) | ||
| 1227 | continue; | ||
| 1228 | |||
| 1223 | in = (unsigned long *)&per_cpu(page_states, cpu); | 1229 | in = (unsigned long *)&per_cpu(page_states, cpu); |
| 1224 | 1230 | ||
| 1225 | cpu = next_cpu(cpu, *cpumask); | 1231 | cpu = next_cpu(cpu, *cpumask); |
| 1226 | 1232 | ||
| 1227 | if (cpu < NR_CPUS) | 1233 | if (likely(cpu < NR_CPUS)) |
| 1228 | prefetch(&per_cpu(page_states, cpu)); | 1234 | prefetch(&per_cpu(page_states, cpu)); |
| 1229 | 1235 | ||
| 1230 | out = (unsigned long *)ret; | 1236 | out = (unsigned long *)ret; |
| @@ -1534,29 +1540,29 @@ static int __initdata node_load[MAX_NUMNODES]; | |||
| 1534 | */ | 1540 | */ |
| 1535 | static int __init find_next_best_node(int node, nodemask_t *used_node_mask) | 1541 | static int __init find_next_best_node(int node, nodemask_t *used_node_mask) |
| 1536 | { | 1542 | { |
| 1537 | int i, n, val; | 1543 | int n, val; |
| 1538 | int min_val = INT_MAX; | 1544 | int min_val = INT_MAX; |
| 1539 | int best_node = -1; | 1545 | int best_node = -1; |
| 1540 | 1546 | ||
| 1541 | for_each_online_node(i) { | 1547 | /* Use the local node if we haven't already */ |
| 1542 | cpumask_t tmp; | 1548 | if (!node_isset(node, *used_node_mask)) { |
| 1549 | node_set(node, *used_node_mask); | ||
| 1550 | return node; | ||
| 1551 | } | ||
| 1543 | 1552 | ||
| 1544 | /* Start from local node */ | 1553 | for_each_online_node(n) { |
| 1545 | n = (node+i) % num_online_nodes(); | 1554 | cpumask_t tmp; |
| 1546 | 1555 | ||
| 1547 | /* Don't want a node to appear more than once */ | 1556 | /* Don't want a node to appear more than once */ |
| 1548 | if (node_isset(n, *used_node_mask)) | 1557 | if (node_isset(n, *used_node_mask)) |
| 1549 | continue; | 1558 | continue; |
| 1550 | 1559 | ||
| 1551 | /* Use the local node if we haven't already */ | ||
| 1552 | if (!node_isset(node, *used_node_mask)) { | ||
| 1553 | best_node = node; | ||
| 1554 | break; | ||
| 1555 | } | ||
| 1556 | |||
| 1557 | /* Use the distance array to find the distance */ | 1560 | /* Use the distance array to find the distance */ |
| 1558 | val = node_distance(node, n); | 1561 | val = node_distance(node, n); |
| 1559 | 1562 | ||
| 1563 | /* Penalize nodes under us ("prefer the next node") */ | ||
| 1564 | val += (n < node); | ||
| 1565 | |||
| 1560 | /* Give preference to headless and unused nodes */ | 1566 | /* Give preference to headless and unused nodes */ |
| 1561 | tmp = node_to_cpumask(n); | 1567 | tmp = node_to_cpumask(n); |
| 1562 | if (!cpus_empty(tmp)) | 1568 | if (!cpus_empty(tmp)) |
| @@ -1799,7 +1805,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, | |||
| 1799 | memmap_init_zone((size), (nid), (zone), (start_pfn)) | 1805 | memmap_init_zone((size), (nid), (zone), (start_pfn)) |
| 1800 | #endif | 1806 | #endif |
| 1801 | 1807 | ||
| 1802 | static int __meminit zone_batchsize(struct zone *zone) | 1808 | static int __cpuinit zone_batchsize(struct zone *zone) |
| 1803 | { | 1809 | { |
| 1804 | int batch; | 1810 | int batch; |
| 1805 | 1811 | ||
| @@ -1886,14 +1892,13 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p, | |||
| 1886 | * not check if the processor is online before following the pageset pointer. | 1892 | * not check if the processor is online before following the pageset pointer. |
| 1887 | * Other parts of the kernel may not check if the zone is available. | 1893 | * Other parts of the kernel may not check if the zone is available. |
| 1888 | */ | 1894 | */ |
| 1889 | static struct per_cpu_pageset | 1895 | static struct per_cpu_pageset boot_pageset[NR_CPUS]; |
| 1890 | boot_pageset[NR_CPUS]; | ||
| 1891 | 1896 | ||
| 1892 | /* | 1897 | /* |
| 1893 | * Dynamically allocate memory for the | 1898 | * Dynamically allocate memory for the |
| 1894 | * per cpu pageset array in struct zone. | 1899 | * per cpu pageset array in struct zone. |
| 1895 | */ | 1900 | */ |
| 1896 | static int __meminit process_zones(int cpu) | 1901 | static int __cpuinit process_zones(int cpu) |
| 1897 | { | 1902 | { |
| 1898 | struct zone *zone, *dzone; | 1903 | struct zone *zone, *dzone; |
| 1899 | 1904 | ||
| @@ -1934,7 +1939,7 @@ static inline void free_zone_pagesets(int cpu) | |||
| 1934 | } | 1939 | } |
| 1935 | } | 1940 | } |
| 1936 | 1941 | ||
| 1937 | static int __meminit pageset_cpuup_callback(struct notifier_block *nfb, | 1942 | static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb, |
| 1938 | unsigned long action, | 1943 | unsigned long action, |
| 1939 | void *hcpu) | 1944 | void *hcpu) |
| 1940 | { | 1945 | { |
