[PATCH] x86_64: Fixed guard page handling again in iounmap

Caused oopses again.  Also fix potential mismatch in checking if
change_page_attr was needed.

To do it without races I needed to change mm/vmalloc.c to export a
__remove_vm_area that does not take vmlist lock.

Noticed by Terence Ripperda and based on a patch of his.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Andi Kleen
2005-05-20 14:27:57 -07:00
committed by Linus Torvalds
parent c4d1fcf3a2
commit 7856dfeb23
3 changed files with 35 additions and 40 deletions

View File

@@ -248,6 +248,28 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
}
/* Caller must hold vmlist_lock */
struct vm_struct *__remove_vm_area(void *addr)
{
struct vm_struct **p, *tmp;
for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) {
if (tmp->addr == addr)
goto found;
}
return NULL;
found:
unmap_vm_area(tmp);
*p = tmp->next;
/*
* Remove the guard page.
*/
tmp->size -= PAGE_SIZE;
return tmp;
}
/**
* remove_vm_area - find and remove a contingous kernel virtual area
*
@@ -255,30 +277,15 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
*
* Search for the kernel VM area starting at @addr, and remove it.
* This function returns the found VM area, but using it is NOT safe
* on SMP machines.
* on SMP machines, except for its size or flags.
*/
struct vm_struct *remove_vm_area(void *addr)
{
struct vm_struct **p, *tmp;
struct vm_struct *v;
write_lock(&vmlist_lock);
for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) {
if (tmp->addr == addr)
goto found;
}
v = __remove_vm_area(addr);
write_unlock(&vmlist_lock);
return NULL;
found:
unmap_vm_area(tmp);
*p = tmp->next;
write_unlock(&vmlist_lock);
/*
* Remove the guard page.
*/
tmp->size -= PAGE_SIZE;
return tmp;
return v;
}
void __vunmap(void *addr, int deallocate_pages)