diff options
Diffstat (limited to 'mm/percpu-vm.c')
-rw-r--r-- | mm/percpu-vm.c | 22 |
1 files changed, 16 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 | |||
125 | err: | ||
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 | ||