diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4f59fa29eda8..0ea758b898fd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -69,6 +69,7 @@ | |||
69 | 69 | ||
70 | /* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */ | 70 | /* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */ |
71 | static DEFINE_MUTEX(pcp_batch_high_lock); | 71 | static DEFINE_MUTEX(pcp_batch_high_lock); |
72 | #define MIN_PERCPU_PAGELIST_FRACTION (8) | ||
72 | 73 | ||
73 | #ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID | 74 | #ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID |
74 | DEFINE_PER_CPU(int, numa_node); | 75 | DEFINE_PER_CPU(int, numa_node); |
@@ -815,9 +816,21 @@ void __init init_cma_reserved_pageblock(struct page *page) | |||
815 | set_page_count(p, 0); | 816 | set_page_count(p, 0); |
816 | } while (++p, --i); | 817 | } while (++p, --i); |
817 | 818 | ||
818 | set_page_refcounted(page); | ||
819 | set_pageblock_migratetype(page, MIGRATE_CMA); | 819 | set_pageblock_migratetype(page, MIGRATE_CMA); |
820 | __free_pages(page, pageblock_order); | 820 | |
821 | if (pageblock_order >= MAX_ORDER) { | ||
822 | i = pageblock_nr_pages; | ||
823 | p = page; | ||
824 | do { | ||
825 | set_page_refcounted(p); | ||
826 | __free_pages(p, MAX_ORDER - 1); | ||
827 | p += MAX_ORDER_NR_PAGES; | ||
828 | } while (i -= MAX_ORDER_NR_PAGES); | ||
829 | } else { | ||
830 | set_page_refcounted(page); | ||
831 | __free_pages(page, pageblock_order); | ||
832 | } | ||
833 | |||
821 | adjust_managed_page_count(page, pageblock_nr_pages); | 834 | adjust_managed_page_count(page, pageblock_nr_pages); |
822 | } | 835 | } |
823 | #endif | 836 | #endif |
@@ -4145,7 +4158,7 @@ static void __meminit zone_init_free_lists(struct zone *zone) | |||
4145 | memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) | 4158 | memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) |
4146 | #endif | 4159 | #endif |
4147 | 4160 | ||
4148 | static int __meminit zone_batchsize(struct zone *zone) | 4161 | static int zone_batchsize(struct zone *zone) |
4149 | { | 4162 | { |
4150 | #ifdef CONFIG_MMU | 4163 | #ifdef CONFIG_MMU |
4151 | int batch; | 4164 | int batch; |
@@ -4261,8 +4274,8 @@ static void pageset_set_high(struct per_cpu_pageset *p, | |||
4261 | pageset_update(&p->pcp, high, batch); | 4274 | pageset_update(&p->pcp, high, batch); |
4262 | } | 4275 | } |
4263 | 4276 | ||
4264 | static void __meminit pageset_set_high_and_batch(struct zone *zone, | 4277 | static void pageset_set_high_and_batch(struct zone *zone, |
4265 | struct per_cpu_pageset *pcp) | 4278 | struct per_cpu_pageset *pcp) |
4266 | { | 4279 | { |
4267 | if (percpu_pagelist_fraction) | 4280 | if (percpu_pagelist_fraction) |
4268 | pageset_set_high(pcp, | 4281 | pageset_set_high(pcp, |
@@ -5881,23 +5894,38 @@ int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write, | |||
5881 | void __user *buffer, size_t *length, loff_t *ppos) | 5894 | void __user *buffer, size_t *length, loff_t *ppos) |
5882 | { | 5895 | { |
5883 | struct zone *zone; | 5896 | struct zone *zone; |
5884 | unsigned int cpu; | 5897 | int old_percpu_pagelist_fraction; |
5885 | int ret; | 5898 | int ret; |
5886 | 5899 | ||
5900 | mutex_lock(&pcp_batch_high_lock); | ||
5901 | old_percpu_pagelist_fraction = percpu_pagelist_fraction; | ||
5902 | |||
5887 | ret = proc_dointvec_minmax(table, write, buffer, length, ppos); | 5903 | ret = proc_dointvec_minmax(table, write, buffer, length, ppos); |
5888 | if (!write || (ret < 0)) | 5904 | if (!write || ret < 0) |
5889 | return ret; | 5905 | goto out; |
5906 | |||
5907 | /* Sanity checking to avoid pcp imbalance */ | ||
5908 | if (percpu_pagelist_fraction && | ||
5909 | percpu_pagelist_fraction < MIN_PERCPU_PAGELIST_FRACTION) { | ||
5910 | percpu_pagelist_fraction = old_percpu_pagelist_fraction; | ||
5911 | ret = -EINVAL; | ||
5912 | goto out; | ||
5913 | } | ||
5914 | |||
5915 | /* No change? */ | ||
5916 | if (percpu_pagelist_fraction == old_percpu_pagelist_fraction) | ||
5917 | goto out; | ||
5890 | 5918 | ||
5891 | mutex_lock(&pcp_batch_high_lock); | ||
5892 | for_each_populated_zone(zone) { | 5919 | for_each_populated_zone(zone) { |
5893 | unsigned long high; | 5920 | unsigned int cpu; |
5894 | high = zone->managed_pages / percpu_pagelist_fraction; | 5921 | |
5895 | for_each_possible_cpu(cpu) | 5922 | for_each_possible_cpu(cpu) |
5896 | pageset_set_high(per_cpu_ptr(zone->pageset, cpu), | 5923 | pageset_set_high_and_batch(zone, |
5897 | high); | 5924 | per_cpu_ptr(zone->pageset, cpu)); |
5898 | } | 5925 | } |
5926 | out: | ||
5899 | mutex_unlock(&pcp_batch_high_lock); | 5927 | mutex_unlock(&pcp_batch_high_lock); |
5900 | return 0; | 5928 | return ret; |
5901 | } | 5929 | } |
5902 | 5930 | ||
5903 | int hashdist = HASHDIST_DEFAULT; | 5931 | int hashdist = HASHDIST_DEFAULT; |