From 47e503cb3129ca7298d18de24e3345911d58c50f Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 26 Sep 2007 10:46:42 -0700 Subject: [PATCH] vcompound_interrupt_free Virtual compound page freeing in interrupt context If we are in an interrupt context then simply defer the free via a workqueue. Removing a virtual mappping *must* be done with interrupts enabled since tlb_xx functions are called that rely on interrupts for processor to processor communications. Signed-off-by: Christoph Lameter --- mm/page_alloc.c | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 55a5eea..dd17628 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1294,7 +1294,12 @@ abort: return NULL; } -static void vcompound_free(void *addr) +/* + * Virtual Compound freeing functions. This is complicated by the vmalloc + * layer not being able to free virtual allocations when interrupts are + * disabled. So we defer the frees via a workqueue if necessary. + */ +static void __vcompound_free(void *addr) { struct page **pages; int i; @@ -1319,6 +1324,22 @@ static void vcompound_free(void *addr) kfree(pages); } +static void vcompound_free_work(struct work_struct *w) +{ + __vcompound_free((void *)w); +} + +static noinline void vcompound_free(void *addr) +{ + if (in_interrupt()) { + struct work_struct *w = addr; + + INIT_WORK(w, vcompound_free_work); + schedule_work(w); + } else + __vcompound_free(addr); +} + /* * This is the 'heart' of the zoned buddy allocator. */ -- 1.5.4.1