]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
mm: unify module_alloc code for vmalloc
authorDavid Rientjes <rientjes@google.com>
Thu, 13 Jan 2011 23:46:02 +0000 (15:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Jan 2011 01:32:34 +0000 (17:32 -0800)
Four architectures (arm, mips, sparc, x86) use __vmalloc_area() for
module_init().  Much of the code is duplicated and can be generalized in a
globally accessible function, __vmalloc_node_range().

__vmalloc_node() now calls into __vmalloc_node_range() with a range of
[VMALLOC_START, VMALLOC_END) for functionally equivalent behavior.

Each architecture may then use __vmalloc_node_range() directly to remove
the duplication of code.

Signed-off-by: David Rientjes <rientjes@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/arm/kernel/module.c
arch/mips/kernel/module.c
arch/sparc/kernel/module.c
arch/x86/kernel/module.c
include/linux/vmalloc.h
mm/vmalloc.c

index 0c1bb68ff4a8449b5884949dc3498404532bb293..2cfe8161b47838ee407bac9a433e1d9117cfd707 100644 (file)
 #ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
-       struct vm_struct *area;
-
-       size = PAGE_ALIGN(size);
-       if (!size)
-               return NULL;
-
-       area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-       if (!area)
-               return NULL;
-
-       return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
+       return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+                               GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
+                               __builtin_return_address(0));
 }
 #else /* CONFIG_MMU */
 void *module_alloc(unsigned long size)
index 6f51dda87fce8869dec4697046bcee532e14a9ee..d87a72e9fac714bd2d1f73b564426f7a77e2dcc5 100644 (file)
@@ -46,17 +46,9 @@ static DEFINE_SPINLOCK(dbe_lock);
 void *module_alloc(unsigned long size)
 {
 #ifdef MODULE_START
-       struct vm_struct *area;
-
-       size = PAGE_ALIGN(size);
-       if (!size)
-               return NULL;
-
-       area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
-       if (!area)
-               return NULL;
-
-       return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+       return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
+                               GFP_KERNEL, PAGE_KERNEL, -1,
+                               __builtin_return_address(0));
 #else
        if (size == 0)
                return NULL;
index ee3c7dde8d9fbd5af21f5dbf555628eff1c64b9c..8d348c474a2f3b7ffde344246c0e41856f3988fe 100644 (file)
 
 static void *module_map(unsigned long size)
 {
-       struct vm_struct *area;
-
-       size = PAGE_ALIGN(size);
-       if (!size || size > MODULES_LEN)
-               return NULL;
-
-       area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-       if (!area)
+       if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
-
-       return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+       return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+                               GFP_KERNEL, PAGE_KERNEL, -1,
+                               __builtin_return_address(0));
 }
 
 static char *dot2underscore(char *name)
index 8f295609173524cdf06a20c6c0ad4fbe1de12263..ab23f1ad4bf1054fd069132ef750f2d88a7f6852 100644 (file)
 
 void *module_alloc(unsigned long size)
 {
-       struct vm_struct *area;
-
-       if (!size)
-               return NULL;
-       size = PAGE_ALIGN(size);
-       if (size > MODULES_LEN)
+       if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
-
-       area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-       if (!area)
-               return NULL;
-
-       return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM,
-                                       PAGE_KERNEL_EXEC);
+       return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+                               GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
+                               -1, __builtin_return_address(0));
 }
 
 /* Free memory returned from module_alloc */
index c7348b8d0a812d872993b1b4441e18e68b11453c..4ed6fcd6b7263c3e38953e536f4cd07a290c61e7 100644 (file)
@@ -59,8 +59,9 @@ extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
 extern void *vmalloc_32_user(unsigned long size);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
-extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask,
-                               pgprot_t prot);
+extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
+                       unsigned long start, unsigned long end, gfp_t gfp_mask,
+                       pgprot_t prot, int node, void *caller);
 extern void vfree(const void *addr);
 
 extern void *vmap(struct page **pages, unsigned int count,
index f6754663632272cfc555cea9ae282575b9d163e4..284346ee0e917cc7bc7f4ee6326751eb8d1677c6 100644 (file)
@@ -1530,25 +1530,12 @@ fail:
        return NULL;
 }
 
-void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
-{
-       void *addr = __vmalloc_area_node(area, gfp_mask, prot, -1,
-                                        __builtin_return_address(0));
-
-       /*
-        * A ref_count = 3 is needed because the vm_struct and vmap_area
-        * structures allocated in the __get_vm_area_node() function contain
-        * references to the virtual address of the vmalloc'ed block.
-        */
-       kmemleak_alloc(addr, area->size - PAGE_SIZE, 3, gfp_mask);
-
-       return addr;
-}
-
 /**
- *     __vmalloc_node  -  allocate virtually contiguous memory
+ *     __vmalloc_node_range  -  allocate virtually contiguous memory
  *     @size:          allocation size
  *     @align:         desired alignment
+ *     @start:         vm area range start
+ *     @end:           vm area range end
  *     @gfp_mask:      flags for the page level allocator
  *     @prot:          protection mask for the allocated pages
  *     @node:          node to use for allocation or -1
@@ -1558,9 +1545,9 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
  *     allocator with @gfp_mask flags.  Map them into contiguous
  *     kernel virtual space, using a pagetable protection of @prot.
  */
-static void *__vmalloc_node(unsigned long size, unsigned long align,
-                           gfp_t gfp_mask, pgprot_t prot,
-                           int node, void *caller)
+void *__vmalloc_node_range(unsigned long size, unsigned long align,
+                       unsigned long start, unsigned long end, gfp_t gfp_mask,
+                       pgprot_t prot, int node, void *caller)
 {
        struct vm_struct *area;
        void *addr;
@@ -1570,8 +1557,8 @@ static void *__vmalloc_node(unsigned long size, unsigned long align,
        if (!size || (size >> PAGE_SHIFT) > totalram_pages)
                return NULL;
 
-       area = __get_vm_area_node(size, align, VM_ALLOC, VMALLOC_START,
-                                 VMALLOC_END, node, gfp_mask, caller);
+       area = __get_vm_area_node(size, align, VM_ALLOC, start, end, node,
+                                 gfp_mask, caller);
 
        if (!area)
                return NULL;
@@ -1588,6 +1575,27 @@ static void *__vmalloc_node(unsigned long size, unsigned long align,
        return addr;
 }
 
+/**
+ *     __vmalloc_node  -  allocate virtually contiguous memory
+ *     @size:          allocation size
+ *     @align:         desired alignment
+ *     @gfp_mask:      flags for the page level allocator
+ *     @prot:          protection mask for the allocated pages
+ *     @node:          node to use for allocation or -1
+ *     @caller:        caller's return address
+ *
+ *     Allocate enough pages to cover @size from the page level
+ *     allocator with @gfp_mask flags.  Map them into contiguous
+ *     kernel virtual space, using a pagetable protection of @prot.
+ */
+static void *__vmalloc_node(unsigned long size, unsigned long align,
+                           gfp_t gfp_mask, pgprot_t prot,
+                           int node, void *caller)
+{
+       return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
+                               gfp_mask, prot, node, caller);
+}
+
 void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
 {
        return __vmalloc_node(size, 1, gfp_mask, prot, -1,