diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page_alloc.c | 49 |
1 files changed, 37 insertions, 12 deletions
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(). |