aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2011-05-11 18:13:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-11 21:50:45 -0400
commitee85c2e1454603ebb9f8d87223ac79dcdc87fa32 (patch)
tree1e5f85fcd35083116e6bc88f6e995b4351e987f1 /mm
parent71a6d0af5b031d27029fda64fbab9b9d953d2b33 (diff)
mm: add alloc_pages_exact_nid()
Add a alloc_pages_exact_nid() that allocates on a specific node. The naming is quite broken, but fixing that would need a larger renaming action. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: tweak comment] Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Michal Hocko <mhocko@suse.cz> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Dave Hansen <dave@linux.vnet.ibm.com> Cc: David Rientjes <rientjes@google.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c49
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
2318EXPORT_SYMBOL(free_pages); 2318EXPORT_SYMBOL(free_pages);
2319 2319
2320static 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}
2352EXPORT_SYMBOL(alloc_pages_exact); 2356EXPORT_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 */
2369void *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}
2377EXPORT_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().