|
@@ -2317,6 +2317,21 @@ void free_pages(unsigned long addr, unsigned int order)
|
|
|
|
|
|
EXPORT_SYMBOL(free_pages);
|
|
EXPORT_SYMBOL(free_pages);
|
|
|
|
|
|
|
|
+static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size)
|
|
|
|
+{
|
|
|
|
+ if (addr) {
|
|
|
|
+ unsigned long alloc_end = addr + (PAGE_SIZE << order);
|
|
|
|
+ unsigned long used = addr + PAGE_ALIGN(size);
|
|
|
|
+
|
|
|
|
+ split_page(virt_to_page((void *)addr), order);
|
|
|
|
+ while (used < alloc_end) {
|
|
|
|
+ free_page(used);
|
|
|
|
+ used += PAGE_SIZE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return (void *)addr;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* alloc_pages_exact - allocate an exact number physically-contiguous pages.
|
|
* alloc_pages_exact - allocate an exact number physically-contiguous pages.
|
|
* @size: the number of bytes to allocate
|
|
* @size: the number of bytes to allocate
|
|
@@ -2336,21 +2351,31 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
|
|
unsigned long addr;
|
|
unsigned long addr;
|
|
|
|
|
|
addr = __get_free_pages(gfp_mask, order);
|
|
addr = __get_free_pages(gfp_mask, order);
|
|
- if (addr) {
|
|
|
|
- unsigned long alloc_end = addr + (PAGE_SIZE << order);
|
|
|
|
- unsigned long used = addr + PAGE_ALIGN(size);
|
|
|
|
-
|
|
|
|
- split_page(virt_to_page((void *)addr), order);
|
|
|
|
- while (used < alloc_end) {
|
|
|
|
- free_page(used);
|
|
|
|
- used += PAGE_SIZE;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return (void *)addr;
|
|
|
|
|
|
+ return make_alloc_exact(addr, order, size);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(alloc_pages_exact);
|
|
EXPORT_SYMBOL(alloc_pages_exact);
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * alloc_pages_exact_nid - allocate an exact number of physically-contiguous
|
|
|
|
+ * pages on a node.
|
|
|
|
+ * @size: the number of bytes to allocate
|
|
|
|
+ * @gfp_mask: GFP flags for the allocation
|
|
|
|
+ *
|
|
|
|
+ * Like alloc_pages_exact(), but try to allocate on node nid first before falling
|
|
|
|
+ * back.
|
|
|
|
+ * Note this is not alloc_pages_exact_node() which allocates on a specific node,
|
|
|
|
+ * but is not exact.
|
|
|
|
+ */
|
|
|
|
+void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask)
|
|
|
|
+{
|
|
|
|
+ unsigned order = get_order(size);
|
|
|
|
+ struct page *p = alloc_pages_node(nid, gfp_mask, order);
|
|
|
|
+ if (!p)
|
|
|
|
+ return NULL;
|
|
|
|
+ return make_alloc_exact((unsigned long)page_address(p), order, size);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(alloc_pages_exact_nid);
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* free_pages_exact - release memory allocated via alloc_pages_exact()
|
|
* free_pages_exact - release memory allocated via alloc_pages_exact()
|
|
* @virt: the value returned by alloc_pages_exact.
|
|
* @virt: the value returned by alloc_pages_exact.
|