Number of arguments in vmalloc.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Some of the functions in vmalloc.c have as many as nine arguments.
So I thought I'd have a quick go at bundling the ones that make sense
into a struct and pass around a pointer to that struct.  Well, it made
the generated code worse, so I thought I'd share my attempt so nobody
else bothers (or soebody points out that I did something stupid).

I tried a few variations on this theme; bundling gfp_t and node into
the struct made it even worse, as did adding caller and vm_flags.  This
is the least bad version.

(Yes, the naming is bad; I'm not tidying this up for submission, I'm
showing an experiment that didn't work).

Nacked-by: Matthew Wilcox <willy@xxxxxxxxxxxxx>

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 97d4b25d0373..3bd9b1bcb702 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -395,13 +395,26 @@ static void purge_vmap_area_lazy(void);
 
 static BLOCKING_NOTIFIER_HEAD(vmap_notify_list);
 
+struct vm_args {
+	unsigned long size;
+	unsigned long align;
+	unsigned long start;
+	unsigned long end;
+};
+
+#define VM_ARGS(name, _size, _align, _start, _end)			\
+	struct vm_args name = {						\
+		.size = (_size),					\
+		.align = (_align),					\
+		.start = (_start),					\
+		.end = (_end),						\
+	}
+
 /*
  * Allocate a region of KVA of the specified size and alignment, within the
- * vstart and vend.
+ * args->start and args->end.
  */
-static struct vmap_area *alloc_vmap_area(unsigned long size,
-				unsigned long align,
-				unsigned long vstart, unsigned long vend,
+static struct vmap_area *alloc_vmap_area(struct vm_args *args,
 				int node, gfp_t gfp_mask)
 {
 	struct vmap_area *va;
@@ -409,10 +422,11 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	unsigned long addr;
 	int purged = 0;
 	struct vmap_area *first;
+	unsigned long size = args->size;
 
 	BUG_ON(!size);
 	BUG_ON(offset_in_page(size));
-	BUG_ON(!is_power_of_2(align));
+	BUG_ON(!is_power_of_2(args->align));
 
 	might_sleep();
 
@@ -433,34 +447,34 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	 * Invalidate cache if we have more permissive parameters.
 	 * cached_hole_size notes the largest hole noticed _below_
 	 * the vmap_area cached in free_vmap_cache: if size fits
-	 * into that hole, we want to scan from vstart to reuse
+	 * into that hole, we want to scan from args->start to reuse
 	 * the hole instead of allocating above free_vmap_cache.
 	 * Note that __free_vmap_area may update free_vmap_cache
 	 * without updating cached_hole_size or cached_align.
 	 */
 	if (!free_vmap_cache ||
 			size < cached_hole_size ||
-			vstart < cached_vstart ||
-			align < cached_align) {
+			args->start < cached_vstart ||
+			args->align < cached_align) {
 nocache:
 		cached_hole_size = 0;
 		free_vmap_cache = NULL;
 	}
 	/* record if we encounter less permissive parameters */
-	cached_vstart = vstart;
-	cached_align = align;
+	cached_vstart = args->start;
+	cached_align = args->align;
 
 	/* find starting point for our search */
 	if (free_vmap_cache) {
 		first = rb_entry(free_vmap_cache, struct vmap_area, rb_node);
-		addr = ALIGN(first->va_end, align);
-		if (addr < vstart)
+		addr = ALIGN(first->va_end, args->align);
+		if (addr < args->start)
 			goto nocache;
 		if (addr + size < addr)
 			goto overflow;
 
 	} else {
-		addr = ALIGN(vstart, align);
+		addr = ALIGN(args->start, args->align);
 		if (addr + size < addr)
 			goto overflow;
 
@@ -484,10 +498,10 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	}
 
 	/* from the starting point, walk areas until a suitable hole is found */
-	while (addr + size > first->va_start && addr + size <= vend) {
+	while (addr + size > first->va_start && addr + size <= args->end) {
 		if (addr + cached_hole_size < first->va_start)
 			cached_hole_size = first->va_start - addr;
-		addr = ALIGN(first->va_end, align);
+		addr = ALIGN(first->va_end, args->align);
 		if (addr + size < addr)
 			goto overflow;
 
@@ -498,7 +512,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	}
 
 found:
-	if (addr + size > vend)
+	if (addr + size > args->end)
 		goto overflow;
 
 	va->va_start = addr;
@@ -508,9 +522,9 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	free_vmap_cache = &va->rb_node;
 	spin_unlock(&vmap_area_lock);
 
-	BUG_ON(!IS_ALIGNED(va->va_start, align));
-	BUG_ON(va->va_start < vstart);
-	BUG_ON(va->va_end > vend);
+	BUG_ON(!IS_ALIGNED(va->va_start, args->align));
+	BUG_ON(va->va_start < args->start);
+	BUG_ON(va->va_end > args->end);
 
 	return va;
 
@@ -844,6 +858,8 @@ static void *vmap_block_vaddr(unsigned long va_start, unsigned long pages_off)
  */
 static void *new_vmap_block(unsigned int order, gfp_t gfp_mask)
 {
+	VM_ARGS(args, VMAP_BLOCK_SIZE, VMAP_BLOCK_SIZE,
+			VMALLOC_START, VMALLOC_END);
 	struct vmap_block_queue *vbq;
 	struct vmap_block *vb;
 	struct vmap_area *va;
@@ -858,9 +874,7 @@ static void *new_vmap_block(unsigned int order, gfp_t gfp_mask)
 	if (unlikely(!vb))
 		return ERR_PTR(-ENOMEM);
 
-	va = alloc_vmap_area(VMAP_BLOCK_SIZE, VMAP_BLOCK_SIZE,
-					VMALLOC_START, VMALLOC_END,
-					node, gfp_mask);
+	va = alloc_vmap_area(&args, node, gfp_mask);
 	if (IS_ERR(va)) {
 		kfree(vb);
 		return ERR_CAST(va);
@@ -1169,9 +1183,9 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
 			return NULL;
 		addr = (unsigned long)mem;
 	} else {
-		struct vmap_area *va;
-		va = alloc_vmap_area(size, PAGE_SIZE,
-				VMALLOC_START, VMALLOC_END, node, GFP_KERNEL);
+		VM_ARGS(args, size, PAGE_SIZE, VMALLOC_START, VMALLOC_END);
+		struct vmap_area *va = alloc_vmap_area(&args, node, GFP_KERNEL);
+
 		if (IS_ERR(va))
 			return NULL;
 
@@ -1370,56 +1384,57 @@ static void clear_vm_uninitialized_flag(struct vm_struct *vm)
 	vm->flags &= ~VM_UNINITIALIZED;
 }
 
-static struct vm_struct *__get_vm_area_node(unsigned long size,
-		unsigned long align, unsigned long flags, unsigned long start,
-		unsigned long end, int node, gfp_t gfp_mask, const void *caller)
+static struct vm_struct *__get_vm_area_node(struct vm_args *args, int node,
+		gfp_t gfp, unsigned long vm_flags, const void *caller)
 {
 	struct vmap_area *va;
 	struct vm_struct *area;
+	unsigned long size;
 
 	BUG_ON(in_interrupt());
-	size = PAGE_ALIGN(size);
+	size = PAGE_ALIGN(args->size);
 	if (unlikely(!size))
 		return NULL;
 
-	if (flags & VM_IOREMAP)
-		align = 1ul << clamp_t(int, get_count_order_long(size),
+	if (vm_flags & VM_IOREMAP)
+		args->align = 1ul << clamp_t(int, get_count_order_long(size),
 				       PAGE_SHIFT, IOREMAP_MAX_ORDER);
 
-	area = kzalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node);
+	area = kzalloc_node(sizeof(*area), gfp & GFP_RECLAIM_MASK, node);
 	if (unlikely(!area))
 		return NULL;
 
-	if (!(flags & VM_NO_GUARD))
+	if (!(vm_flags & VM_NO_GUARD))
 		size += PAGE_SIZE;
+	args->size = size;
 
-	va = alloc_vmap_area(size, align, start, end, node, gfp_mask);
+	va = alloc_vmap_area(args, node, gfp);
 	if (IS_ERR(va)) {
 		kfree(area);
 		return NULL;
 	}
 
-	setup_vmalloc_vm(area, va, flags, caller);
+	setup_vmalloc_vm(area, va, vm_flags, caller);
 
 	return area;
 }
 
-struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
-				unsigned long start, unsigned long end)
-{
-	return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE,
-				  GFP_KERNEL, __builtin_return_address(0));
-}
-EXPORT_SYMBOL_GPL(__get_vm_area);
-
 struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
 				       unsigned long start, unsigned long end,
 				       const void *caller)
 {
-	return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE,
-				  GFP_KERNEL, caller);
+	VM_ARGS(args, size, 1, start, end);
+	return __get_vm_area_node(&args, NUMA_NO_NODE, GFP_KERNEL, flags, caller);
 }
 
+struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
+				unsigned long start, unsigned long end)
+{
+	return __get_vm_area_caller(size, flags, start, end,
+					__builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(__get_vm_area);
+
 /**
  *	get_vm_area  -  reserve a contiguous kernel virtual area
  *	@size:		size of the area
@@ -1431,16 +1446,14 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
  */
 struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
 {
-	return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
-				  NUMA_NO_NODE, GFP_KERNEL,
-				  __builtin_return_address(0));
+	return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
 }
 
 struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
 				const void *caller)
 {
-	return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
-				  NUMA_NO_NODE, GFP_KERNEL, caller);
+	return __get_vm_area_caller(size, flags, VMALLOC_START, VMALLOC_END,
+					caller);
 }
 
 /**
@@ -1734,6 +1747,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
 			pgprot_t prot, unsigned long vm_flags, int node,
 			const void *caller)
 {
+	VM_ARGS(args, size, align, start, end);
 	struct vm_struct *area;
 	void *addr;
 	unsigned long real_size = size;
@@ -1741,9 +1755,10 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
 	size = PAGE_ALIGN(size);
 	if (!size || (size >> PAGE_SHIFT) > totalram_pages)
 		goto fail;
+	args.size = size;
 
-	area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
-				vm_flags, start, end, node, gfp_mask, caller);
+	area = __get_vm_area_node(&args, node, gfp_mask,
+			vm_flags | VM_ALLOC | VM_UNINITIALIZED, caller);
 	if (!area)
 		goto fail;
 




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux