[PATCH] Allow __vmalloc with GFP_ATOMIC

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

 



Until 2.6.19, __vmalloc with GFP_ATOMIC was possible, but __get_vm_area_node
would allocate the node itself with GFP_KERNEL, causing a warning. In 2.6.19,
this was "fixed" by using the same flags that were passed to __vmalloc also
in __get_vm_area_node. However, __get_vm_area_node does
BUG_ON(in_interrupt()) now, since vmlist_lock is obtained without disabling
bottom-half's. The patch below uses bh disabled lock for vmlist_lock, so that
__vmalloc can be used in interrupt context.

In 2.6.21, __vmalloc with GFP_ATOMIC is used by arch/um/kernel/process.c;
__vmalloc is also used in ntfs, xfs, but it is not clear to me if they use it
with GFP_ATOMIC or GFP_KERNEL.

Thanks,
Giri

Signed-off-by: Giridhar Pemmasani <[email protected]>
---
--- linux-2.6.21.orig/./arch/arm/mm/ioremap.c	2007-04-25 23:08:32.000000000
-0400
+++ linux-2.6.21.new/./arch/arm/mm/ioremap.c	2007-04-27 23:29:27.000000000
-0400
@@ -363,7 +363,7 @@
 	 * all the mappings before the area can be reclaimed
 	 * by someone else.
 	 */
-	write_lock(&vmlist_lock);
+	write_lock_bh(&vmlist_lock);
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
 		if((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
 			if (tmp->flags & VM_ARM_SECTION_MAPPING) {
@@ -376,7 +376,7 @@
 			break;
 		}
 	}
-	write_unlock(&vmlist_lock);
+	write_unlock_bh(&vmlist_lock);
 #endif
 
 	if (!section_mapping)
--- linux-2.6.21.orig/./arch/i386/mm/ioremap.c	2007-04-25 23:08:32.000000000
-0400
+++ linux-2.6.21.new/./arch/i386/mm/ioremap.c	2007-04-27 23:29:27.000000000
-0400
@@ -180,12 +180,12 @@
 	   in parallel. Reuse of the virtual address is prevented by
 	   leaving it in the global lists until we're done with it.
 	   cpa takes care of the direct mappings. */
-	read_lock(&vmlist_lock);
+	read_lock_bh(&vmlist_lock);
 	for (p = vmlist; p; p = p->next) {
 		if (p->addr == addr)
 			break;
 	}
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 
 	if (!p) {
 		printk("iounmap: bad address %p\n", addr);
--- linux-2.6.21.orig/./arch/x86_64/mm/ioremap.c	2007-04-25
23:08:32.000000000 -0400
+++ linux-2.6.21.new/./arch/x86_64/mm/ioremap.c	2007-04-27 23:29:27.000000000
-0400
@@ -175,12 +175,12 @@
 	   in parallel. Reuse of the virtual address is prevented by
 	   leaving it in the global lists until we're done with it.
 	   cpa takes care of the direct mappings. */
-	read_lock(&vmlist_lock);
+	read_lock_bh(&vmlist_lock);
 	for (p = vmlist; p; p = p->next) {
 		if (p->addr == addr)
 			break;
 	}
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 
 	if (!p) {
 		printk("iounmap: bad address %p\n", addr);
--- linux-2.6.21.orig/./fs/proc/kcore.c	2007-04-25 23:08:32.000000000 -0400
+++ linux-2.6.21.new/./fs/proc/kcore.c	2007-04-27 23:29:27.000000000 -0400
@@ -335,7 +335,7 @@
 			if (!elf_buf)
 				return -ENOMEM;
 
-			read_lock(&vmlist_lock);
+			read_lock_bh(&vmlist_lock);
 			for (m=vmlist; m && cursize; m=m->next) {
 				unsigned long vmstart;
 				unsigned long vmsize;
@@ -363,7 +363,7 @@
 				memcpy(elf_buf + (vmstart - start),
 					(char *)vmstart, vmsize);
 			}
-			read_unlock(&vmlist_lock);
+			read_unlock_bh(&vmlist_lock);
 			if (copy_to_user(buffer, elf_buf, tsz)) {
 				kfree(elf_buf);
 				return -EFAULT;
--- linux-2.6.21.orig/./fs/proc/mmu.c	2007-04-25 23:08:32.000000000 -0400
+++ linux-2.6.21.new/./fs/proc/mmu.c	2007-04-27 23:29:41.000000000 -0400
@@ -47,7 +47,7 @@
 
 		prev_end = VMALLOC_START;
 
-		read_lock(&vmlist_lock);
+		read_lock_bh(&vmlist_lock);
 
 		for (vma = vmlist; vma; vma = vma->next) {
 			unsigned long addr = (unsigned long) vma->addr;
@@ -72,6 +72,6 @@
 		if (VMALLOC_END - prev_end > vmi->largest_chunk)
 			vmi->largest_chunk = VMALLOC_END - prev_end;
 
-		read_unlock(&vmlist_lock);
+		read_unlock_bh(&vmlist_lock);
 	}
 }
--- linux-2.6.21.orig/./mm/vmalloc.c	2007-04-25 23:08:32.000000000 -0400
+++ linux-2.6.21.new/./mm/vmalloc.c	2007-04-27 23:33:17.000000000 -0400
@@ -168,7 +168,7 @@
 	unsigned long align = 1;
 	unsigned long addr;
 
-	BUG_ON(in_interrupt());
+	BUG_ON(in_irq());
 	if (flags & VM_IOREMAP) {
 		int bit = fls(size);
 
@@ -193,7 +193,7 @@
 	 */
 	size += PAGE_SIZE;
 
-	write_lock(&vmlist_lock);
+	write_lock_bh(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
 		if ((unsigned long)tmp->addr < addr) {
 			if((unsigned long)tmp->addr + tmp->size >= addr)
@@ -220,12 +220,12 @@
 	area->pages = NULL;
 	area->nr_pages = 0;
 	area->phys_addr = 0;
-	write_unlock(&vmlist_lock);
+	write_unlock_bh(&vmlist_lock);
 
 	return area;
 
 out:
-	write_unlock(&vmlist_lock);
+	write_unlock_bh(&vmlist_lock);
 	kfree(area);
 	if (printk_ratelimit())
 		printk(KERN_WARNING "allocation failed: out of vmalloc space - use
vmalloc=<size> to increase size.\n");
@@ -305,9 +305,9 @@
 struct vm_struct *remove_vm_area(void *addr)
 {
 	struct vm_struct *v;
-	write_lock(&vmlist_lock);
+	write_lock_bh(&vmlist_lock);
 	v = __remove_vm_area(addr);
-	write_unlock(&vmlist_lock);
+	write_unlock_bh(&vmlist_lock);
 	return v;
 }
 
@@ -364,7 +364,7 @@
  */
 void vfree(void *addr)
 {
-	BUG_ON(in_interrupt());
+	BUG_ON(in_irq());
 	__vunmap(addr, 1);
 }
 EXPORT_SYMBOL(vfree);
@@ -380,7 +380,7 @@
  */
 void vunmap(void *addr)
 {
-	BUG_ON(in_interrupt());
+	BUG_ON(in_irq());
 	__vunmap(addr, 0);
 }
 EXPORT_SYMBOL(vunmap);
@@ -530,10 +530,10 @@
 
 	ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
PAGE_KERNEL);
 	if (ret) {
-		write_lock(&vmlist_lock);
+		write_lock_bh(&vmlist_lock);
 		area = __find_vm_area(ret);
 		area->flags |= VM_USERMAP;
-		write_unlock(&vmlist_lock);
+		write_unlock_bh(&vmlist_lock);
 	}
 	return ret;
 }
@@ -604,10 +604,10 @@
 
 	ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
 	if (ret) {
-		write_lock(&vmlist_lock);
+		write_lock_bh(&vmlist_lock);
 		area = __find_vm_area(ret);
 		area->flags |= VM_USERMAP;
-		write_unlock(&vmlist_lock);
+		write_unlock_bh(&vmlist_lock);
 	}
 	return ret;
 }
@@ -623,7 +623,7 @@
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
 
-	read_lock(&vmlist_lock);
+	read_lock_bh(&vmlist_lock);
 	for (tmp = vmlist; tmp; tmp = tmp->next) {
 		vaddr = (char *) tmp->addr;
 		if (addr >= vaddr + tmp->size - PAGE_SIZE)
@@ -647,7 +647,7 @@
 		} while (--n > 0);
 	}
 finished:
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 	return buf - buf_start;
 }
 
@@ -661,7 +661,7 @@
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
 
-	read_lock(&vmlist_lock);
+	read_lock_bh(&vmlist_lock);
 	for (tmp = vmlist; tmp; tmp = tmp->next) {
 		vaddr = (char *) tmp->addr;
 		if (addr >= vaddr + tmp->size - PAGE_SIZE)
@@ -684,7 +684,7 @@
 		} while (--n > 0);
 	}
 finished:
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 	return buf - buf_start;
 }
 
@@ -712,7 +712,7 @@
 	if ((PAGE_SIZE-1) & (unsigned long)addr)
 		return -EINVAL;
 
-	read_lock(&vmlist_lock);
+	read_lock_bh(&vmlist_lock);
 	area = __find_vm_area(addr);
 	if (!area)
 		goto out_einval_locked;
@@ -722,7 +722,7 @@
 
 	if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
 		goto out_einval_locked;
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 
 	addr += pgoff << PAGE_SHIFT;
 	do {
@@ -742,7 +742,7 @@
 	return ret;
 
 out_einval_locked:
-	read_unlock(&vmlist_lock);
+	read_unlock_bh(&vmlist_lock);
 	return -EINVAL;
 }
 EXPORT_SYMBOL(remap_vmalloc_range);


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux