From 8aab139baf1dbf71151f4fb0dc848e459f6773b7 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 26 Sep 2007 10:46:42 -0700 Subject: [PATCH] vcompound_interrupt_alloc Virtual Compound page allocation from interrupt context. In an interrupt context we cannot wait for the vmlist_lock in __get_vm_area_node(). So use a trylock instead. If the trylock fails then the atomic allocation will fail and subsequently be retried. This only works because the flush_cache_vunmap in use for allocation is never performing any IPIs in contrast to flush_tlb_... in use for freeing. flush_cache_vunmap is only used on architectures with a virtually mapped cache (xtensa, pa-risc). [Note: Nick Piggin is working on a scheme to make this simpler by no longer requiring flushes] Signed-off-by: Christoph Lameter --- mm/vmalloc.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index dda9dca..a4fa811 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -289,7 +289,6 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl unsigned long align = 1; unsigned long addr; - BUG_ON(in_interrupt()); if (flags & VM_IOREMAP) { int bit = fls(size); @@ -314,7 +313,14 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl */ size += PAGE_SIZE; - write_lock(&vmlist_lock); + if (gfp_mask & __GFP_WAIT) + write_lock(&vmlist_lock); + else { + if (!write_trylock(&vmlist_lock)) { + kfree(area); + return NULL; + } + } for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) { if ((unsigned long)tmp->addr < addr) { if((unsigned long)tmp->addr + tmp->size >= addr) -- 1.5.4.1