aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-09-07 23:10:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-09-07 23:10:06 -0400
commit6a5c75ce10cbfc805a4e6305638d6329a3beb77a (patch)
tree7b29fbf21ee68f0979964b87154ef5538a4cdc8d /mm
parentcfa7c641ded6e67a8d8fc54bd24f53a60465e68f (diff)
parent3189eddbcafcc4d827f7f19facbeddec4424eba8 (diff)
Merge branch 'for-3.17-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
Pull percpu fixes from Tejun Heo: "One patch to fix a failure path in the alloc path. The bug is dangerous but probably not too likely to actually trigger in the wild given that there hasn't been any report yet. The other two are low impact fixes" * 'for-3.17-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu: percpu: free percpu allocation info for uniprocessor system percpu: perform tlb flush after pcpu_map_pages() failure percpu: fix pcpu_alloc_pages() failure path
Diffstat (limited to 'mm')
-rw-r--r--mm/percpu-vm.c22
-rw-r--r--mm/percpu.c2
2 files changed, 18 insertions, 6 deletions
diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c
index 3707c71ae4cd..51108165f829 100644
--- a/mm/percpu-vm.c
+++ b/mm/percpu-vm.c
@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
108 int page_start, int page_end) 108 int page_start, int page_end)
109{ 109{
110 const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; 110 const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
111 unsigned int cpu; 111 unsigned int cpu, tcpu;
112 int i; 112 int i;
113 113
114 for_each_possible_cpu(cpu) { 114 for_each_possible_cpu(cpu) {
@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
116 struct page **pagep = &pages[pcpu_page_idx(cpu, i)]; 116 struct page **pagep = &pages[pcpu_page_idx(cpu, i)];
117 117
118 *pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0); 118 *pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0);
119 if (!*pagep) { 119 if (!*pagep)
120 pcpu_free_pages(chunk, pages, populated, 120 goto err;
121 page_start, page_end);
122 return -ENOMEM;
123 }
124 } 121 }
125 } 122 }
126 return 0; 123 return 0;
124
125err:
126 while (--i >= page_start)
127 __free_page(pages[pcpu_page_idx(cpu, i)]);
128
129 for_each_possible_cpu(tcpu) {
130 if (tcpu == cpu)
131 break;
132 for (i = page_start; i < page_end; i++)
133 __free_page(pages[pcpu_page_idx(tcpu, i)]);
134 }
135 return -ENOMEM;
127} 136}
128 137
129/** 138/**
@@ -263,6 +272,7 @@ err:
263 __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start), 272 __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
264 page_end - page_start); 273 page_end - page_start);
265 } 274 }
275 pcpu_post_unmap_tlb_flush(chunk, page_start, page_end);
266 return err; 276 return err;
267} 277}
268 278
diff --git a/mm/percpu.c b/mm/percpu.c
index 2139e30a4b44..da997f9800bd 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1932,6 +1932,8 @@ void __init setup_per_cpu_areas(void)
1932 1932
1933 if (pcpu_setup_first_chunk(ai, fc) < 0) 1933 if (pcpu_setup_first_chunk(ai, fc) < 0)
1934 panic("Failed to initialize percpu areas."); 1934 panic("Failed to initialize percpu areas.");
1935
1936 pcpu_free_alloc_info(ai);
1935} 1937}
1936 1938
1937#endif /* CONFIG_SMP */ 1939#endif /* CONFIG_SMP */