From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932361AbWEVBgu (ORCPT ); Sun, 21 May 2006 21:36:50 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932420AbWEVBgu (ORCPT ); Sun, 21 May 2006 21:36:50 -0400 Received: from lmcgw.cs.sunysb.edu ([130.245.128.4]:52901 "EHLO smtp.lmc.cs.sunysb.edu") by vger.kernel.org with ESMTP id S932361AbWEVBgt (ORCPT ); Sun, 21 May 2006 21:36:49 -0400 Date: Sun, 21 May 2006 21:36:48 -0400 From: Giridhar Pemmasani To: linux-kernel@vger.kernel.org Subject: __vmalloc with GFP_ATOMIC causes 'sleeping from invalid context' User-Agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.8 (=?ISO-8859-4?Q?Shij=F2?=) APEL/10.6 MULE XEmacs/21.4 (patch 19) (Constant Variable) (i386-debian-linux) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Message-Id: <20060522013648.6FCEAEE9EE@wolfe.lmc.cs.sunysb.edu> Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org If __vmalloc is called in atomic context with GFP_ATOMIC flags, __get_vm_area_node is called, which calls kmalloc_node with GFP_KERNEL flags. This causes 'sleeping function called from invalid context at mm/slab.c:2729' with 2.6.16-rc4 kernel. A simple solution is to use proper flags in __get_vm_area_node, depending on the context: diff -Naur linux.orig/mm/vmalloc.c linux/mm/vmalloc.c --- linux.orig/mm/vmalloc.c 2006-05-19 01:22:00.000000000 -0400 +++ linux/mm/vmalloc.c 2006-05-19 01:53:05.000000000 -0400 @@ -177,7 +177,10 @@ addr = ALIGN(start, align); size = PAGE_ALIGN(size); - area = kmalloc_node(sizeof(*area), GFP_KERNEL, node); + if (in_atomic() || in_interrupt()) + area = kmalloc_node(sizeof(*area), GFP_ATOMIC, node); + else + area = kmalloc_node(sizeof(*area), GFP_KERNEL, node); if (unlikely(!area)) return NULL; An alternate solution is to pass flags to __get_vm_area_node what was passed to __vmalloc so it can call kmalloc_node with either GFP_KERNEL or GFP_ATOMIC, but that changes signature of get_vm_area_node and __get_vm_area_node which may affect other parts of kernel / modules. Another point: In include/linux/kernel.h, might_resched() is defined as #ifdef CONFIG_PREEMPT_VOLUNTARY extern int cond_resched(void); # define might_resched() cond_resched() #else # define might_resched() do { } while (0) #endif Why is cond_resched() used only if CONFIG_PREEMPT_VOLUNTARY and not if CONFIG_PREEMPT is enabled? i.e., shouldn't it be defined as #if defined(CONFIG_PREEMPT_VOLUNTARY) || defined(CONFIG_PREEMPT) extern int cond_resched(void); # define might_resched() cond_resched() #else # define might_resched() do { } while (0) #endif Thanks, Giri