From: William Lee Irwin III My current attempt at quickfixing this, which raised the questions about the module and non-i386 arch code, but works (i.e. prevents the oops and/or alloc_area_pte printk) is: arch/i386/mm/ioremap.c | 1 - arch/sparc64/kernel/module.c | 2 ++ arch/x86_64/kernel/module.c | 2 +- arch/x86_64/mm/ioremap.c | 1 - mm/vmalloc.c | 3 +-- 5 files changed, 4 insertions(+), 5 deletions(-) diff -puN arch/i386/mm/ioremap.c~vmalloc-race-fix arch/i386/mm/ioremap.c --- 25/arch/i386/mm/ioremap.c~vmalloc-race-fix 2003-05-07 22:30:11.000000000 -0700 +++ 25-akpm/arch/i386/mm/ioremap.c 2003-05-07 22:30:11.000000000 -0700 @@ -222,7 +222,6 @@ void iounmap(void *addr) return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -puN arch/sparc64/kernel/module.c~vmalloc-race-fix arch/sparc64/kernel/module.c --- 25/arch/sparc64/kernel/module.c~vmalloc-race-fix 2003-05-07 22:30:11.000000000 -0700 +++ 25-akpm/arch/sparc64/kernel/module.c 2003-05-07 22:30:11.000000000 -0700 @@ -138,7 +138,9 @@ void *module_alloc(unsigned long size) /* Free memory returned from module_core_alloc/module_init_alloc */ void module_free(struct module *mod, void *module_region) { + write_lock(&vmlist_lock); module_unmap(module_region); + write_unlock(&vmlist_lock); /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } diff -puN arch/x86_64/kernel/module.c~vmalloc-race-fix arch/x86_64/kernel/module.c --- 25/arch/x86_64/kernel/module.c~vmalloc-race-fix 2003-05-07 22:30:11.000000000 -0700 +++ 25-akpm/arch/x86_64/kernel/module.c 2003-05-07 22:30:11.000000000 -0700 @@ -48,7 +48,6 @@ void module_free(struct module *mod, voi for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) { if ((unsigned long)map->addr == addr) { *prevp = map->next; - write_unlock(&vmlist_lock); goto found; } } @@ -57,6 +56,7 @@ void module_free(struct module *mod, voi return; found: unmap_vm_area(map); + write_unlock(&vmlist_lock); if (map->pages) { for (i = 0; i < map->nr_pages; i++) if (map->pages[i]) diff -puN arch/x86_64/mm/ioremap.c~vmalloc-race-fix arch/x86_64/mm/ioremap.c --- 25/arch/x86_64/mm/ioremap.c~vmalloc-race-fix 2003-05-07 22:30:11.000000000 -0700 +++ 25-akpm/arch/x86_64/mm/ioremap.c 2003-05-07 22:30:11.000000000 -0700 @@ -222,7 +222,6 @@ void iounmap(void *addr) return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -puN mm/vmalloc.c~vmalloc-race-fix mm/vmalloc.c --- 25/mm/vmalloc.c~vmalloc-race-fix 2003-05-07 22:30:11.000000000 -0700 +++ 25-akpm/mm/vmalloc.c 2003-05-07 22:30:11.000000000 -0700 @@ -260,6 +260,7 @@ struct vm_struct *remove_vm_area(void *a return NULL; found: + unmap_vm_area(tmp); *p = tmp->next; write_unlock(&vmlist_lock); return tmp; @@ -283,8 +284,6 @@ void __vunmap(void *addr, int deallocate addr); return; } - - unmap_vm_area(area); if (deallocate_pages) { int i; _