diff options
author | Tejun Heo <tj@kernel.org> | 2014-09-02 14:46:01 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-09-02 14:46:01 -0400 |
commit | fbbb7f4e149f6dd19a8dbebc9fa5c5b72173c6de (patch) | |
tree | ee7783159a8faaec07c66c42e20ae5833e2c897c /mm | |
parent | 3189eddbcafcc4d827f7f19facbeddec4424eba8 (diff) |
percpu: remove the usage of separate populated bitmap in percpu-vm
percpu-vm uses pcpu_get_pages_and_bitmap() to acquire temp pages array
and populated bitmap and uses the two during [de]population. The temp
bitmap is used only to build the new bitmap that is copied to
chunk->populated after the operation succeeds; however, the new bitmap
can be trivially set after success without using the temp bitmap.
This patch removes the temp populated bitmap usage from percpu-vm.c.
* pcpu_get_pages_and_bitmap() is renamed to pcpu_get_pages() and no
longer hands out the temp bitmap.
* @populated arugment is dropped from all the related functions.
@populated updates in pcpu_[un]map_pages() are dropped.
* Two loops in pcpu_map_pages() are merged.
* pcpu_[de]populated_chunk() modify chunk->populated bitmap directly
from @page_start and @page_end after success.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Christoph Lameter <cl@linux.com>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/percpu-vm.c | 93 |
1 files changed, 25 insertions, 68 deletions
diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c index 51108165f829..47b47bfbcb66 100644 --- a/mm/percpu-vm.c +++ b/mm/percpu-vm.c | |||
@@ -20,46 +20,24 @@ static struct page *pcpu_chunk_page(struct pcpu_chunk *chunk, | |||
20 | } | 20 | } |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * pcpu_get_pages_and_bitmap - get temp pages array and bitmap | 23 | * pcpu_get_pages - get temp pages array |
24 | * @chunk: chunk of interest | 24 | * @chunk: chunk of interest |
25 | * @bitmapp: output parameter for bitmap | ||
26 | * @may_alloc: may allocate the array | 25 | * @may_alloc: may allocate the array |
27 | * | 26 | * |
28 | * Returns pointer to array of pointers to struct page and bitmap, | 27 | * Returns pointer to array of pointers to struct page which can be indexed |
29 | * both of which can be indexed with pcpu_page_idx(). The returned | 28 | * with pcpu_page_idx(). Note that there is only one array and access |
30 | * array is cleared to zero and *@bitmapp is copied from | 29 | * exclusion is the caller's responsibility. |
31 | * @chunk->populated. Note that there is only one array and bitmap | ||
32 | * and access exclusion is the caller's responsibility. | ||
33 | * | ||
34 | * CONTEXT: | ||
35 | * pcpu_alloc_mutex and does GFP_KERNEL allocation if @may_alloc. | ||
36 | * Otherwise, don't care. | ||
37 | * | 30 | * |
38 | * RETURNS: | 31 | * RETURNS: |
39 | * Pointer to temp pages array on success, NULL on failure. | 32 | * Pointer to temp pages array on success. |
40 | */ | 33 | */ |
41 | static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk, | 34 | static struct page **pcpu_get_pages(struct pcpu_chunk *chunk, bool may_alloc) |
42 | unsigned long **bitmapp, | ||
43 | bool may_alloc) | ||
44 | { | 35 | { |
45 | static struct page **pages; | 36 | static struct page **pages; |
46 | static unsigned long *bitmap; | ||
47 | size_t pages_size = pcpu_nr_units * pcpu_unit_pages * sizeof(pages[0]); | 37 | size_t pages_size = pcpu_nr_units * pcpu_unit_pages * sizeof(pages[0]); |
48 | size_t bitmap_size = BITS_TO_LONGS(pcpu_unit_pages) * | ||
49 | sizeof(unsigned long); | ||
50 | |||
51 | if (!pages || !bitmap) { | ||
52 | if (may_alloc && !pages) | ||
53 | pages = pcpu_mem_zalloc(pages_size); | ||
54 | if (may_alloc && !bitmap) | ||
55 | bitmap = pcpu_mem_zalloc(bitmap_size); | ||
56 | if (!pages || !bitmap) | ||
57 | return NULL; | ||
58 | } | ||
59 | 38 | ||
60 | bitmap_copy(bitmap, chunk->populated, pcpu_unit_pages); | 39 | if (!pages && may_alloc) |
61 | 40 | pages = pcpu_mem_zalloc(pages_size); | |
62 | *bitmapp = bitmap; | ||
63 | return pages; | 41 | return pages; |
64 | } | 42 | } |
65 | 43 | ||
@@ -67,7 +45,6 @@ static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk, | |||
67 | * pcpu_free_pages - free pages which were allocated for @chunk | 45 | * pcpu_free_pages - free pages which were allocated for @chunk |
68 | * @chunk: chunk pages were allocated for | 46 | * @chunk: chunk pages were allocated for |
69 | * @pages: array of pages to be freed, indexed by pcpu_page_idx() | 47 | * @pages: array of pages to be freed, indexed by pcpu_page_idx() |
70 | * @populated: populated bitmap | ||
71 | * @page_start: page index of the first page to be freed | 48 | * @page_start: page index of the first page to be freed |
72 | * @page_end: page index of the last page to be freed + 1 | 49 | * @page_end: page index of the last page to be freed + 1 |
73 | * | 50 | * |
@@ -75,8 +52,7 @@ static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk, | |||
75 | * The pages were allocated for @chunk. | 52 | * The pages were allocated for @chunk. |
76 | */ | 53 | */ |
77 | static void pcpu_free_pages(struct pcpu_chunk *chunk, | 54 | static void pcpu_free_pages(struct pcpu_chunk *chunk, |
78 | struct page **pages, unsigned long *populated, | 55 | struct page **pages, int page_start, int page_end) |
79 | int page_start, int page_end) | ||
80 | { | 56 | { |
81 | unsigned int cpu; | 57 | unsigned int cpu; |
82 | int i; | 58 | int i; |
@@ -95,7 +71,6 @@ static void pcpu_free_pages(struct pcpu_chunk *chunk, | |||
95 | * pcpu_alloc_pages - allocates pages for @chunk | 71 | * pcpu_alloc_pages - allocates pages for @chunk |
96 | * @chunk: target chunk | 72 | * @chunk: target chunk |
97 | * @pages: array to put the allocated pages into, indexed by pcpu_page_idx() | 73 | * @pages: array to put the allocated pages into, indexed by pcpu_page_idx() |
98 | * @populated: populated bitmap | ||
99 | * @page_start: page index of the first page to be allocated | 74 | * @page_start: page index of the first page to be allocated |
100 | * @page_end: page index of the last page to be allocated + 1 | 75 | * @page_end: page index of the last page to be allocated + 1 |
101 | * | 76 | * |
@@ -104,8 +79,7 @@ static void pcpu_free_pages(struct pcpu_chunk *chunk, | |||
104 | * content of @pages and will pass it verbatim to pcpu_map_pages(). | 79 | * content of @pages and will pass it verbatim to pcpu_map_pages(). |
105 | */ | 80 | */ |
106 | static int pcpu_alloc_pages(struct pcpu_chunk *chunk, | 81 | static int pcpu_alloc_pages(struct pcpu_chunk *chunk, |
107 | struct page **pages, unsigned long *populated, | 82 | struct page **pages, int page_start, int page_end) |
108 | int page_start, int page_end) | ||
109 | { | 83 | { |
110 | const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; | 84 | const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; |
111 | unsigned int cpu, tcpu; | 85 | unsigned int cpu, tcpu; |
@@ -164,7 +138,6 @@ static void __pcpu_unmap_pages(unsigned long addr, int nr_pages) | |||
164 | * pcpu_unmap_pages - unmap pages out of a pcpu_chunk | 138 | * pcpu_unmap_pages - unmap pages out of a pcpu_chunk |
165 | * @chunk: chunk of interest | 139 | * @chunk: chunk of interest |
166 | * @pages: pages array which can be used to pass information to free | 140 | * @pages: pages array which can be used to pass information to free |
167 | * @populated: populated bitmap | ||
168 | * @page_start: page index of the first page to unmap | 141 | * @page_start: page index of the first page to unmap |
169 | * @page_end: page index of the last page to unmap + 1 | 142 | * @page_end: page index of the last page to unmap + 1 |
170 | * | 143 | * |
@@ -175,8 +148,7 @@ static void __pcpu_unmap_pages(unsigned long addr, int nr_pages) | |||
175 | * proper pre/post flush functions. | 148 | * proper pre/post flush functions. |
176 | */ | 149 | */ |
177 | static void pcpu_unmap_pages(struct pcpu_chunk *chunk, | 150 | static void pcpu_unmap_pages(struct pcpu_chunk *chunk, |
178 | struct page **pages, unsigned long *populated, | 151 | struct page **pages, int page_start, int page_end) |
179 | int page_start, int page_end) | ||
180 | { | 152 | { |
181 | unsigned int cpu; | 153 | unsigned int cpu; |
182 | int i; | 154 | int i; |
@@ -192,8 +164,6 @@ static void pcpu_unmap_pages(struct pcpu_chunk *chunk, | |||
192 | __pcpu_unmap_pages(pcpu_chunk_addr(chunk, cpu, page_start), | 164 | __pcpu_unmap_pages(pcpu_chunk_addr(chunk, cpu, page_start), |
193 | page_end - page_start); | 165 | page_end - page_start); |
194 | } | 166 | } |
195 | |||
196 | bitmap_clear(populated, page_start, page_end - page_start); | ||
197 | } | 167 | } |
198 | 168 | ||
199 | /** | 169 | /** |
@@ -228,7 +198,6 @@ static int __pcpu_map_pages(unsigned long addr, struct page **pages, | |||
228 | * pcpu_map_pages - map pages into a pcpu_chunk | 198 | * pcpu_map_pages - map pages into a pcpu_chunk |
229 | * @chunk: chunk of interest | 199 | * @chunk: chunk of interest |
230 | * @pages: pages array containing pages to be mapped | 200 | * @pages: pages array containing pages to be mapped |
231 | * @populated: populated bitmap | ||
232 | * @page_start: page index of the first page to map | 201 | * @page_start: page index of the first page to map |
233 | * @page_end: page index of the last page to map + 1 | 202 | * @page_end: page index of the last page to map + 1 |
234 | * | 203 | * |
@@ -236,13 +205,11 @@ static int __pcpu_map_pages(unsigned long addr, struct page **pages, | |||
236 | * caller is responsible for calling pcpu_post_map_flush() after all | 205 | * caller is responsible for calling pcpu_post_map_flush() after all |
237 | * mappings are complete. | 206 | * mappings are complete. |
238 | * | 207 | * |
239 | * This function is responsible for setting corresponding bits in | 208 | * This function is responsible for setting up whatever is necessary for |
240 | * @chunk->populated bitmap and whatever is necessary for reverse | 209 | * reverse lookup (addr -> chunk). |
241 | * lookup (addr -> chunk). | ||
242 | */ | 210 | */ |
243 | static int pcpu_map_pages(struct pcpu_chunk *chunk, | 211 | static int pcpu_map_pages(struct pcpu_chunk *chunk, |
244 | struct page **pages, unsigned long *populated, | 212 | struct page **pages, int page_start, int page_end) |
245 | int page_start, int page_end) | ||
246 | { | 213 | { |
247 | unsigned int cpu, tcpu; | 214 | unsigned int cpu, tcpu; |
248 | int i, err; | 215 | int i, err; |
@@ -253,18 +220,12 @@ static int pcpu_map_pages(struct pcpu_chunk *chunk, | |||
253 | page_end - page_start); | 220 | page_end - page_start); |
254 | if (err < 0) | 221 | if (err < 0) |
255 | goto err; | 222 | goto err; |
256 | } | ||
257 | 223 | ||
258 | /* mapping successful, link chunk and mark populated */ | 224 | for (i = page_start; i < page_end; i++) |
259 | for (i = page_start; i < page_end; i++) { | ||
260 | for_each_possible_cpu(cpu) | ||
261 | pcpu_set_page_chunk(pages[pcpu_page_idx(cpu, i)], | 225 | pcpu_set_page_chunk(pages[pcpu_page_idx(cpu, i)], |
262 | chunk); | 226 | chunk); |
263 | __set_bit(i, populated); | ||
264 | } | 227 | } |
265 | |||
266 | return 0; | 228 | return 0; |
267 | |||
268 | err: | 229 | err: |
269 | for_each_possible_cpu(tcpu) { | 230 | for_each_possible_cpu(tcpu) { |
270 | if (tcpu == cpu) | 231 | if (tcpu == cpu) |
@@ -314,7 +275,6 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) | |||
314 | int page_end = PFN_UP(off + size); | 275 | int page_end = PFN_UP(off + size); |
315 | int free_end = page_start, unmap_end = page_start; | 276 | int free_end = page_start, unmap_end = page_start; |
316 | struct page **pages; | 277 | struct page **pages; |
317 | unsigned long *populated; | ||
318 | unsigned int cpu; | 278 | unsigned int cpu; |
319 | int rs, re, rc; | 279 | int rs, re, rc; |
320 | 280 | ||
@@ -327,28 +287,27 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) | |||
327 | /* need to allocate and map pages, this chunk can't be immutable */ | 287 | /* need to allocate and map pages, this chunk can't be immutable */ |
328 | WARN_ON(chunk->immutable); | 288 | WARN_ON(chunk->immutable); |
329 | 289 | ||
330 | pages = pcpu_get_pages_and_bitmap(chunk, &populated, true); | 290 | pages = pcpu_get_pages(chunk, true); |
331 | if (!pages) | 291 | if (!pages) |
332 | return -ENOMEM; | 292 | return -ENOMEM; |
333 | 293 | ||
334 | /* alloc and map */ | 294 | /* alloc and map */ |
335 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { | 295 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { |
336 | rc = pcpu_alloc_pages(chunk, pages, populated, rs, re); | 296 | rc = pcpu_alloc_pages(chunk, pages, rs, re); |
337 | if (rc) | 297 | if (rc) |
338 | goto err_free; | 298 | goto err_free; |
339 | free_end = re; | 299 | free_end = re; |
340 | } | 300 | } |
341 | 301 | ||
342 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { | 302 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { |
343 | rc = pcpu_map_pages(chunk, pages, populated, rs, re); | 303 | rc = pcpu_map_pages(chunk, pages, rs, re); |
344 | if (rc) | 304 | if (rc) |
345 | goto err_unmap; | 305 | goto err_unmap; |
346 | unmap_end = re; | 306 | unmap_end = re; |
347 | } | 307 | } |
348 | pcpu_post_map_flush(chunk, page_start, page_end); | 308 | pcpu_post_map_flush(chunk, page_start, page_end); |
349 | 309 | ||
350 | /* commit new bitmap */ | 310 | bitmap_set(chunk->populated, page_start, page_end - page_start); |
351 | bitmap_copy(chunk->populated, populated, pcpu_unit_pages); | ||
352 | clear: | 311 | clear: |
353 | for_each_possible_cpu(cpu) | 312 | for_each_possible_cpu(cpu) |
354 | memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size); | 313 | memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size); |
@@ -357,11 +316,11 @@ clear: | |||
357 | err_unmap: | 316 | err_unmap: |
358 | pcpu_pre_unmap_flush(chunk, page_start, unmap_end); | 317 | pcpu_pre_unmap_flush(chunk, page_start, unmap_end); |
359 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, unmap_end) | 318 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, unmap_end) |
360 | pcpu_unmap_pages(chunk, pages, populated, rs, re); | 319 | pcpu_unmap_pages(chunk, pages, rs, re); |
361 | pcpu_post_unmap_tlb_flush(chunk, page_start, unmap_end); | 320 | pcpu_post_unmap_tlb_flush(chunk, page_start, unmap_end); |
362 | err_free: | 321 | err_free: |
363 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, free_end) | 322 | pcpu_for_each_unpop_region(chunk, rs, re, page_start, free_end) |
364 | pcpu_free_pages(chunk, pages, populated, rs, re); | 323 | pcpu_free_pages(chunk, pages, rs, re); |
365 | return rc; | 324 | return rc; |
366 | } | 325 | } |
367 | 326 | ||
@@ -383,7 +342,6 @@ static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size) | |||
383 | int page_start = PFN_DOWN(off); | 342 | int page_start = PFN_DOWN(off); |
384 | int page_end = PFN_UP(off + size); | 343 | int page_end = PFN_UP(off + size); |
385 | struct page **pages; | 344 | struct page **pages; |
386 | unsigned long *populated; | ||
387 | int rs, re; | 345 | int rs, re; |
388 | 346 | ||
389 | /* quick path, check whether it's empty already */ | 347 | /* quick path, check whether it's empty already */ |
@@ -400,22 +358,21 @@ static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size) | |||
400 | * successful population attempt so the temp pages array must | 358 | * successful population attempt so the temp pages array must |
401 | * be available now. | 359 | * be available now. |
402 | */ | 360 | */ |
403 | pages = pcpu_get_pages_and_bitmap(chunk, &populated, false); | 361 | pages = pcpu_get_pages(chunk, false); |
404 | BUG_ON(!pages); | 362 | BUG_ON(!pages); |
405 | 363 | ||
406 | /* unmap and free */ | 364 | /* unmap and free */ |
407 | pcpu_pre_unmap_flush(chunk, page_start, page_end); | 365 | pcpu_pre_unmap_flush(chunk, page_start, page_end); |
408 | 366 | ||
409 | pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) | 367 | pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) |
410 | pcpu_unmap_pages(chunk, pages, populated, rs, re); | 368 | pcpu_unmap_pages(chunk, pages, rs, re); |
411 | 369 | ||
412 | /* no need to flush tlb, vmalloc will handle it lazily */ | 370 | /* no need to flush tlb, vmalloc will handle it lazily */ |
413 | 371 | ||
414 | pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) | 372 | pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) |
415 | pcpu_free_pages(chunk, pages, populated, rs, re); | 373 | pcpu_free_pages(chunk, pages, rs, re); |
416 | 374 | ||
417 | /* commit new bitmap */ | 375 | bitmap_clear(chunk->populated, page_start, page_end - page_start); |
418 | bitmap_copy(chunk->populated, populated, pcpu_unit_pages); | ||
419 | } | 376 | } |
420 | 377 | ||
421 | static struct pcpu_chunk *pcpu_create_chunk(void) | 378 | static struct pcpu_chunk *pcpu_create_chunk(void) |