diff options
| -rw-r--r-- | include/linux/gfp.h | 2 | ||||
| -rw-r--r-- | mm/page_alloc.c | 49 |
2 files changed, 39 insertions, 12 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index bfb8f934521e..56d8fc87fbbc 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
| @@ -353,6 +353,8 @@ extern unsigned long get_zeroed_page(gfp_t gfp_mask); | |||
| 353 | 353 | ||
| 354 | void *alloc_pages_exact(size_t size, gfp_t gfp_mask); | 354 | void *alloc_pages_exact(size_t size, gfp_t gfp_mask); |
| 355 | void free_pages_exact(void *virt, size_t size); | 355 | void free_pages_exact(void *virt, size_t size); |
| 356 | /* This is different from alloc_pages_exact_node !!! */ | ||
| 357 | void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask); | ||
| 356 | 358 | ||
| 357 | #define __get_free_page(gfp_mask) \ | 359 | #define __get_free_page(gfp_mask) \ |
| 358 | __get_free_pages((gfp_mask), 0) | 360 | __get_free_pages((gfp_mask), 0) |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 454191a25173..570d944daeb5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -2317,6 +2317,21 @@ void free_pages(unsigned long addr, unsigned int order) | |||
| 2317 | 2317 | ||
| 2318 | EXPORT_SYMBOL(free_pages); | 2318 | EXPORT_SYMBOL(free_pages); |
| 2319 | 2319 | ||
| 2320 | static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size) | ||
| 2321 | { | ||
| 2322 | if (addr) { | ||
| 2323 | unsigned long alloc_end = addr + (PAGE_SIZE << order); | ||
| 2324 | unsigned long used = addr + PAGE_ALIGN(size); | ||
| 2325 | |||
| 2326 | split_page(virt_to_page((void *)addr), order); | ||
| 2327 | while (used < alloc_end) { | ||
| 2328 | free_page(used); | ||
| 2329 | used += PAGE_SIZE; | ||
| 2330 | } | ||
| 2331 | } | ||
| 2332 | return (void *)addr; | ||
| 2333 | } | ||
| 2334 | |||
| 2320 | /** | 2335 | /** |
| 2321 | * alloc_pages_exact - allocate an exact number physically-contiguous pages. | 2336 | * alloc_pages_exact - allocate an exact number physically-contiguous pages. |
| 2322 | * @size: the number of bytes to allocate | 2337 | * @size: the number of bytes to allocate |
| @@ -2336,22 +2351,32 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask) | |||
| 2336 | unsigned long addr; | 2351 | unsigned long addr; |
| 2337 | 2352 | ||
| 2338 | addr = __get_free_pages(gfp_mask, order); | 2353 | addr = __get_free_pages(gfp_mask, order); |
| 2339 | if (addr) { | 2354 | return make_alloc_exact(addr, order, size); |
| 2340 | unsigned long alloc_end = addr + (PAGE_SIZE << order); | ||
| 2341 | unsigned long used = addr + PAGE_ALIGN(size); | ||
| 2342 | |||
| 2343 | split_page(virt_to_page((void *)addr), order); | ||
| 2344 | while (used < alloc_end) { | ||
| 2345 | free_page(used); | ||
| 2346 | used += PAGE_SIZE; | ||
| 2347 | } | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | return (void *)addr; | ||
| 2351 | } | 2355 | } |
| 2352 | EXPORT_SYMBOL(alloc_pages_exact); | 2356 | EXPORT_SYMBOL(alloc_pages_exact); |
| 2353 | 2357 | ||
| 2354 | /** | 2358 | /** |
| 2359 | * alloc_pages_exact_nid - allocate an exact number of physically-contiguous | ||
| 2360 | * pages on a node. | ||
| 2361 | * @size: the number of bytes to allocate | ||
| 2362 | * @gfp_mask: GFP flags for the allocation | ||
| 2363 | * | ||
| 2364 | * Like alloc_pages_exact(), but try to allocate on node nid first before falling | ||
| 2365 | * back. | ||
| 2366 | * Note this is not alloc_pages_exact_node() which allocates on a specific node, | ||
| 2367 | * but is not exact. | ||
| 2368 | */ | ||
| 2369 | void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask) | ||
| 2370 | { | ||
| 2371 | unsigned order = get_order(size); | ||
| 2372 | struct page *p = alloc_pages_node(nid, gfp_mask, order); | ||
| 2373 | if (!p) | ||
| 2374 | return NULL; | ||
| 2375 | return make_alloc_exact((unsigned long)page_address(p), order, size); | ||
| 2376 | } | ||
| 2377 | EXPORT_SYMBOL(alloc_pages_exact_nid); | ||
| 2378 | |||
| 2379 | /** | ||
| 2355 | * free_pages_exact - release memory allocated via alloc_pages_exact() | 2380 | * free_pages_exact - release memory allocated via alloc_pages_exact() |
| 2356 | * @virt: the value returned by alloc_pages_exact. | 2381 | * @virt: the value returned by alloc_pages_exact. |
| 2357 | * @size: size of allocation, same value as passed to alloc_pages_exact(). | 2382 | * @size: size of allocation, same value as passed to alloc_pages_exact(). |
