Messages in this thread Patch in this message | | | Date | Tue, 10 Nov 2009 15:04:04 +0900 | From | Tejun Heo <> | Subject | [GIT PULL] percpu fixes for 2.6.32-rc6 |
| |
Hello, Linus.
Please pull from the following percpu fix branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git for-linus
It fixes a possible deadlock caused by lock ordering inversion through irq.
Thanks. --- Tejun Heo (1): percpu: fix possible deadlock via irq lock inversion
mm/percpu.c | 17 +++++++++++++++--
diff --git a/mm/percpu.c b/mm/percpu.c index d907971..30cd343 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -372,7 +372,7 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr) static int pcpu_extend_area_map(struct pcpu_chunk *chunk, unsigned long *flags) { int new_alloc; - int *new; + int *new, *old = NULL; size_t size;
/* has enough? */ @@ -407,10 +407,23 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, unsigned long *flags) * one of the first chunks and still using static map. */ if (chunk->map_alloc >= PCPU_DFL_MAP_ALLOC) - pcpu_mem_free(chunk->map, size); + old = chunk->map;
chunk->map_alloc = new_alloc; chunk->map = new; + + /* + * pcpu_mem_free() might end up calling vfree() which uses + * IRQ-unsafe lock and thus can't be called with pcpu_lock + * held. Release and reacquire pcpu_lock if old map needs to + * be freed. + */ + if (old) { + spin_unlock_irqrestore(&pcpu_lock, *flags); + pcpu_mem_free(old, size); + spin_lock_irqsave(&pcpu_lock, *flags); + } + return 0; }
-- tejun
| |