diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5eeeadd9f66a..2c46f697e8ff 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -53,6 +53,7 @@ struct pglist_data *pgdat_list __read_mostly; | |||
53 | unsigned long totalram_pages __read_mostly; | 53 | unsigned long totalram_pages __read_mostly; |
54 | unsigned long totalhigh_pages __read_mostly; | 54 | unsigned long totalhigh_pages __read_mostly; |
55 | long nr_swap_pages; | 55 | long nr_swap_pages; |
56 | int percpu_pagelist_fraction; | ||
56 | 57 | ||
57 | 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); |
58 | 59 | ||
@@ -1831,6 +1832,24 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) | |||
1831 | INIT_LIST_HEAD(&pcp->list); | 1832 | INIT_LIST_HEAD(&pcp->list); |
1832 | } | 1833 | } |
1833 | 1834 | ||
1835 | /* | ||
1836 | * setup_pagelist_highmark() sets the high water mark for hot per_cpu_pagelist | ||
1837 | * to the value high for the pageset p. | ||
1838 | */ | ||
1839 | |||
1840 | static void setup_pagelist_highmark(struct per_cpu_pageset *p, | ||
1841 | unsigned long high) | ||
1842 | { | ||
1843 | struct per_cpu_pages *pcp; | ||
1844 | |||
1845 | pcp = &p->pcp[0]; /* hot list */ | ||
1846 | pcp->high = high; | ||
1847 | pcp->batch = max(1UL, high/4); | ||
1848 | if ((high/4) > (PAGE_SHIFT * 8)) | ||
1849 | pcp->batch = PAGE_SHIFT * 8; | ||
1850 | } | ||
1851 | |||
1852 | |||
1834 | #ifdef CONFIG_NUMA | 1853 | #ifdef CONFIG_NUMA |
1835 | /* | 1854 | /* |
1836 | * Boot pageset table. One per cpu which is going to be used for all | 1855 | * Boot pageset table. One per cpu which is going to be used for all |
@@ -1868,6 +1887,10 @@ static int __devinit process_zones(int cpu) | |||
1868 | goto bad; | 1887 | goto bad; |
1869 | 1888 | ||
1870 | setup_pageset(zone->pageset[cpu], zone_batchsize(zone)); | 1889 | setup_pageset(zone->pageset[cpu], zone_batchsize(zone)); |
1890 | |||
1891 | if (percpu_pagelist_fraction) | ||
1892 | setup_pagelist_highmark(zone_pcp(zone, cpu), | ||
1893 | (zone->present_pages / percpu_pagelist_fraction)); | ||
1871 | } | 1894 | } |
1872 | 1895 | ||
1873 | return 0; | 1896 | return 0; |
@@ -2567,6 +2590,32 @@ int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write, | |||
2567 | return 0; | 2590 | return 0; |
2568 | } | 2591 | } |
2569 | 2592 | ||
2593 | /* | ||
2594 | * percpu_pagelist_fraction - changes the pcp->high for each zone on each | ||
2595 | * cpu. It is the fraction of total pages in each zone that a hot per cpu pagelist | ||
2596 | * can have before it gets flushed back to buddy allocator. | ||
2597 | */ | ||
2598 | |||
2599 | int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write, | ||
2600 | struct file *file, void __user *buffer, size_t *length, loff_t *ppos) | ||
2601 | { | ||
2602 | struct zone *zone; | ||
2603 | unsigned int cpu; | ||
2604 | int ret; | ||
2605 | |||
2606 | ret = proc_dointvec_minmax(table, write, file, buffer, length, ppos); | ||
2607 | if (!write || (ret == -EINVAL)) | ||
2608 | return ret; | ||
2609 | for_each_zone(zone) { | ||
2610 | for_each_online_cpu(cpu) { | ||
2611 | unsigned long high; | ||
2612 | high = zone->present_pages / percpu_pagelist_fraction; | ||
2613 | setup_pagelist_highmark(zone_pcp(zone, cpu), high); | ||
2614 | } | ||
2615 | } | ||
2616 | return 0; | ||
2617 | } | ||
2618 | |||
2570 | __initdata int hashdist = HASHDIST_DEFAULT; | 2619 | __initdata int hashdist = HASHDIST_DEFAULT; |
2571 | 2620 | ||
2572 | #ifdef CONFIG_NUMA | 2621 | #ifdef CONFIG_NUMA |