Re: get_vm_area needs spin lock

Andrea Arcangeli (andrea@e-mind.com)
Thu, 31 Dec 1998 18:56:14 +0100 (CET)


On Wed, 30 Dec 1998, David Grothe wrote:

> I am enclosing a patch for 2.2.0pre1 (mm/vmalloc.c) that I think fixes
> this problem. The patch is enclosed as a MIME attachment to avoid

There is no need for irqsave since vmalloc can be used only from a normal
kernel context (noirq and nobh). And there's no reason for GFP_ATOMIC I
think. So I changed a bit your patch this way:

Index: linux/mm/vmalloc.c
diff -u linux/mm/vmalloc.c:1.1.1.2 linux/mm/vmalloc.c:1.1.1.1.2.3
--- linux/mm/vmalloc.c:1.1.1.2 Fri Nov 27 11:19:11 1998
+++ linux/mm/vmalloc.c Thu Dec 31 18:55:11 1998
@@ -10,6 +10,7 @@
#include <asm/uaccess.h>

static struct vm_struct * vmlist = NULL;
+static spinlock_t vmlist_spinlock;

static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
{
@@ -158,17 +159,21 @@
if (!area)
return NULL;
addr = VMALLOC_START;
+ spin_lock(&vmlist_spinlock);
for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
if (size + addr < (unsigned long) tmp->addr)
break;
- if (addr > VMALLOC_END-size)
+ if (addr > VMALLOC_END-size) {
+ spin_unlock(&vmlist_spinlock);
return NULL;
+ }
addr = tmp->size + (unsigned long) tmp->addr;
}
area->addr = (void *)addr;
area->size = size + PAGE_SIZE;
area->next = *p;
*p = area;
+ spin_unlock(&vmlist_spinlock);
return area;
}

@@ -182,14 +187,18 @@
printk("Trying to vfree() bad address (%p)\n", addr);
return;
}
+ spin_lock(&vmlist_spinlock);
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
- vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+ spin_unlock(&vmlist_spinlock);
+ vmfree_area_pages(VMALLOC_VMADDR(tmp->addr),
+ tmp->size - PAGE_SIZE);
kfree(tmp);
return;
}
}
+ spin_unlock(&vmlist_spinlock);
printk("Trying to vfree() nonexistent vm area (%p)\n", addr);
}

@@ -222,6 +231,7 @@
if ((unsigned long) addr + count < count)
count = -(unsigned long) addr;

+ spin_lock(&vmlist_spinlock);
for (tmp = vmlist; tmp; tmp = tmp->next) {
vaddr = (char *) tmp->addr;
if (addr >= vaddr + tmp->size - PAGE_SIZE)
@@ -245,5 +255,6 @@
} while (--n > 0);
}
finished:
+ spin_unlock(&vmlist_spinlock);
return buf - buf_start;
}

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/