All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: William Lee Irwin III <wli@holomorphy.com>
Cc: Russell King <rmk@arm.linux.org.uk>,
	"Dr. David Alan Gilbert" <gilbertd@treblig.org>,
	Dave Jones <davej@codemonkey.org.uk>,
	linux-kernel@vger.kernel.org
Subject: Re: lkml, bugme.osdl.org?
Date: Thu, 05 Dec 2002 09:34:22 +0000	[thread overview]
Message-ID: <3907.1039080862@passion.cambridge.redhat.com> (raw)
In-Reply-To: <20021205092523.GG9882@holomorphy.com>


wli@holomorphy.com said:
>  Is there any chance you can send a testcase my way? I've got some
> testboxen that are good at bringing out races (NUMA stuff is beautiful
> for that -- I don't consider anything racetested until it passes
> there.) 

The race in vmalloc is purely theoretical but blatantly obvious -- I don't
think anyone's actually triggered it though. You have already tried the fix
and reported it works fine. Apparently for akpm ioremap() returns a 
bogus value to the aic7xxx driver and the box locks up. I can't see why it 
could do that -- more eyes welcome...


===== include/linux/vmalloc.h 1.8 vs edited =====
--- 1.8/include/linux/vmalloc.h	Fri Nov  8 07:47:15 2002
+++ edited/include/linux/vmalloc.h	Wed Nov 20 14:27:09 2002
@@ -2,12 +2,14 @@
 #define _LINUX_VMALLOC_H
 
 #include <linux/spinlock.h>
+#include <linux/list.h>
 #include <asm/page.h>		/* pgprot_t */
 
 /* bits in vm_struct->flags */
 #define VM_IOREMAP	0x00000001	/* ioremap() and friends */
 #define VM_ALLOC	0x00000002	/* vmalloc() */
 #define VM_MAP		0x00000004	/* vmap()ed pages */
+#define VM_DELETING	0x00000008	/* Being removed */
 
 struct vm_struct {
 	void			*addr;
@@ -16,7 +18,7 @@
 	struct page		**pages;
 	unsigned int		nr_pages;
 	unsigned long		phys_addr;
-	struct vm_struct	*next;
+	struct list_head	list;
 };
 
 /*
@@ -40,9 +42,9 @@
 extern void unmap_vm_area(struct vm_struct *area);
 
 /*
- *	Internals.  Dont't use..
+ *	Internals.  Don't use.
  */
 extern rwlock_t vmlist_lock;
-extern struct vm_struct *vmlist;
+extern struct list_head vmlist;
 
 #endif /* _LINUX_VMALLOC_H */
===== mm/vmalloc.c 1.23 vs edited =====
--- 1.23/mm/vmalloc.c	Thu Oct 31 15:28:17 2002
+++ edited/mm/vmalloc.c	Wed Nov 20 14:27:09 2002
@@ -21,7 +21,7 @@
 
 
 rwlock_t vmlist_lock = RW_LOCK_UNLOCKED;
-struct vm_struct *vmlist;
+LIST_HEAD(vmlist);
 
 static void unmap_area_pte(pmd_t *pmd, unsigned long address,
 				  unsigned long size)
@@ -192,7 +192,7 @@
  */
 struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
 {
-	struct vm_struct **p, *tmp, *area;
+	struct vm_struct *tmp, *area;
 	unsigned long addr = VMALLOC_START;
 
 	area = kmalloc(sizeof(*area), GFP_KERNEL);
@@ -209,7 +209,7 @@
 	}
 
 	write_lock(&vmlist_lock);
-	for (p = &vmlist; (tmp = *p) ;p = &tmp->next) {
+	list_for_each_entry(tmp, &vmlist, list) {
 		if ((size + addr) < addr)
 			goto out;
 		if (size + addr <= (unsigned long)tmp->addr)
@@ -220,8 +220,7 @@
 	}
 
 found:
-	area->next = *p;
-	*p = area;
+	list_add_tail(&area->list, &tmp->list);
 
 	area->flags = flags;
 	area->addr = (void *)addr;
@@ -250,18 +249,23 @@
  */
 struct vm_struct *remove_vm_area(void *addr)
 {
-	struct vm_struct **p, *tmp;
+	struct vm_struct *tmp;
 
 	write_lock(&vmlist_lock);
-	for (p = &vmlist ; (tmp = *p) ;p = &tmp->next) {
+	list_for_each_entry(tmp, &vmlist, list) {
 		 if (tmp->addr == addr)
 			 goto found;
 	}
 	write_unlock(&vmlist_lock);
 	return NULL;
 
-found:
-	*p = tmp->next;
+ found:
+	if (tmp->flags & VM_DELETING) {
+		printk(KERN_ERR "Trying to vfree() region being freed (%p)\n", addr);
+		tmp = NULL;
+	}
+	else 
+		tmp->flags |= VM_DELETING;
 	write_unlock(&vmlist_lock);
 	return tmp;
 }
@@ -299,6 +303,10 @@
 		kfree(area->pages);
 	}
 
+	write_lock(&vmlist_lock);
+	list_del(&area->list);
+	write_unlock(&vmlist_lock);
+
 	kfree(area);
 	return;
 }
@@ -308,7 +316,7 @@
  *
  *	@addr:		memory base address
  *
- *	Free the virtually continguos memory area starting at @addr, as
+ *	Free the virtually contiguous memory area starting at @addr, as
  *	obtained from vmalloc(), vmalloc_32() or __vmalloc().
  *
  *	May not be called in interrupt context.
@@ -324,7 +332,7 @@
  *
  *	@addr:		memory base address
  *
- *	Free the virtually continguos memory area starting at @addr,
+ *	Free the virtually contiguous memory area starting at @addr,
  *	which was created from the page array passed to vmap().
  *
  *	May not be called in interrupt context.
@@ -336,12 +344,12 @@
 }
 
 /**
- *	vmap  -  map an array of pages into virtually continguos space
+ *	vmap  -  map an array of pages into virtually contiguous space
  *
  *	@pages:		array of page pointers
  *	@count:		number of pages to map
  *
- *	Maps @count pages from @pages into continguos kernel virtual
+ *	Maps @count pages from @pages into contiguous kernel virtual
  *	space.
  */
 void *vmap(struct page **pages, unsigned int count)
@@ -363,14 +371,14 @@
 }
 
 /**
- *	__vmalloc  -  allocate virtually continguos memory
+ *	__vmalloc  -  allocate virtually contiguous memory
  *
  *	@size:		allocation size
  *	@gfp_mask:	flags for the page level allocator
  *	@prot:		protection mask for the allocated pages
  *
  *	Allocate enough pages to cover @size from the page level
- *	allocator with @gfp_mask flags.  Map them into continguos
+ *	allocator with @gfp_mask flags.  Map them into contiguous
  *	kernel virtual space, using a pagetable protection of @prot.
  */
 void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
@@ -418,12 +426,12 @@
 }
 
 /**
- *	vmalloc  -  allocate virtually continguos memory
+ *	vmalloc  -  allocate virtually contiguous memory
  *
  *	@size:		allocation size
  *
  *	Allocate enough pages to cover @size from the page level
- *	allocator and map them into continguos kernel virtual space.
+ *	allocator and map them into contiguous kernel virtual space.
  *
  *	For tight cotrol over page level allocator and protection flags
  *	use __vmalloc() instead.
@@ -434,12 +442,12 @@
 }
 
 /**
- *	vmalloc_32  -  allocate virtually continguos memory (32bit addressable)
+ *	vmalloc_32  -  allocate virtually contiguous memory (32bit addressable)
  *
  *	@size:		allocation size
  *
  *	Allocate enough 32bit PA addressable pages to cover @size from the
- *	page level allocator and map them into continguos kernel virtual space.
+ *	page level allocator and map them into contiguous kernel virtual space.
  */
 void *vmalloc_32(unsigned long size)
 {
@@ -457,7 +465,7 @@
 		count = -(unsigned long) addr;
 
 	read_lock(&vmlist_lock);
-	for (tmp = vmlist; tmp; tmp = tmp->next) {
+	list_for_each_entry(tmp, &vmlist, list) {
 		vaddr = (char *) tmp->addr;
 		if (addr >= vaddr + tmp->size - PAGE_SIZE)
 			continue;
@@ -495,7 +503,7 @@
 		count = -(unsigned long) addr;
 
 	read_lock(&vmlist_lock);
-	for (tmp = vmlist; tmp; tmp = tmp->next) {
+	list_for_each_entry(tmp, &vmlist, list) {
 		vaddr = (char *) tmp->addr;
 		if (addr >= vaddr + tmp->size - PAGE_SIZE)
 			continue;
===== fs/proc/kcore.c 1.7 vs edited =====
--- 1.7/fs/proc/kcore.c	Tue Oct 29 00:51:13 2002
+++ edited/fs/proc/kcore.c	Wed Nov 20 14:27:09 2002
@@ -121,12 +121,12 @@
 
 	*num_vma = 0;
 	size = ((size_t)high_memory - KCORE_BASE + PAGE_SIZE);
-	if (!vmlist) {
+	if (list_empty(&vmlist)) {
 		*elf_buflen = PAGE_SIZE;
 		return (size);
 	}
 
-	for (m=vmlist; m; m=m->next) {
+	list_for_each_entry(m, &vmlist, list) {
 		try = (size_t)m->addr + m->size;
 		if (try > KCORE_BASE + size)
 			size = try - KCORE_BASE;
@@ -246,7 +246,7 @@
 	phdr->p_align	= PAGE_SIZE;
 
 	/* setup ELF PT_LOAD program header for every vmalloc'd area */
-	for (m=vmlist; m; m=m->next) {
+	list_for_each_entry(m, &vmlist, list) {
 		if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
 			continue;
 
@@ -406,11 +406,15 @@
 			memset(elf_buf, 0, tsz);
 
 			read_lock(&vmlist_lock);
-			for (m=vmlist; m && cursize; m=m->next) {
+			list_for_each_entry(m, &vmlist, list) {
 				unsigned long vmstart;
 				unsigned long vmsize;
-				unsigned long msize = m->size - PAGE_SIZE;
+				unsigned long msize;
 
+				if (!cursize)
+					break;
+
+				msize = m->size - PAGE_SIZE;
 				if (((unsigned long)m->addr + msize) < 
 								curstart)
 					continue;

--
dwmw2




  reply	other threads:[~2002-12-05  9:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-12-03  7:24 lkml, bugme.osdl.org? Valdis.Kletnieks
2002-12-03 12:15 ` Dave Jones
2002-12-03 14:13   ` bill davidsen
2002-12-03 18:09   ` Tupshin Harper
2002-12-04 11:58   ` Dr. David Alan Gilbert
2002-12-04 12:35     ` Russell King
2002-12-04 12:42     ` Dave Jones
2002-12-04 18:32       ` Dr. David Alan Gilbert
2002-12-04 22:20         ` Russell King
2002-12-05  9:15           ` David Woodhouse
2002-12-05  9:25             ` William Lee Irwin III
2002-12-05  9:34               ` David Woodhouse [this message]
2002-12-05  9:35                 ` William Lee Irwin III
2002-12-05 14:24       ` bill davidsen
2002-12-03 20:33 ` Martin J. Bligh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3907.1039080862@passion.cambridge.redhat.com \
    --to=dwmw2@infradead.org \
    --cc=davej@codemonkey.org.uk \
    --cc=gilbertd@treblig.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rmk@arm.linux.org.uk \
    --cc=wli@holomorphy.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.