diff options
| author | David Rientjes <rientjes@google.com> | 2011-01-13 15:46:02 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 17:32:34 -0800 | 
| commit | d0a21265dfb5fa8ae54e90d0fb6d1c215b10a28a (patch) | |
| tree | a3bf2c96ad8e180f32a52e208667a40bb972275b | |
| parent | ec3f64fc9c196a304c4b7db3e1ff56d640628509 (diff) | |
| download | olio-linux-3.10-d0a21265dfb5fa8ae54e90d0fb6d1c215b10a28a.tar.xz olio-linux-3.10-d0a21265dfb5fa8ae54e90d0fb6d1c215b10a28a.zip  | |
mm: unify module_alloc code for vmalloc
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>
| -rw-r--r-- | arch/arm/kernel/module.c | 14 | ||||
| -rw-r--r-- | arch/mips/kernel/module.c | 14 | ||||
| -rw-r--r-- | arch/sparc/kernel/module.c | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/module.c | 17 | ||||
| -rw-r--r-- | include/linux/vmalloc.h | 5 | ||||
| -rw-r--r-- | mm/vmalloc.c | 50 | 
6 files changed, 46 insertions, 68 deletions
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 0c1bb68ff4a..2cfe8161b47 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -38,17 +38,9 @@  #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) diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index 6f51dda87fc..d87a72e9fac 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -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; diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index ee3c7dde8d9..8d348c474a2 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -23,17 +23,11 @@  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) diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 8f295609173..ab23f1ad4bf 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -37,20 +37,11 @@  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 */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index c7348b8d0a8..4ed6fcd6b72 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -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, diff --git a/mm/vmalloc.c b/mm/vmalloc.c index f6754663632..284346ee0e9 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -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,  |