aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu-vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/percpu-vm.c')
-rw-r--r--mm/percpu-vm.c22
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
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