2006-10-23 06:13:51

by Giridhar Pemmasani

[permalink] [raw]
Subject: __vmalloc with GFP_ATOMIC causes 'sleeping from invalid context'


This is follow up of earlier patch:

http://marc.theaimsgroup.com/?l=linux-kernel&m=114833505625992&w=2

Apparently the patch has not been merged (yet), so resending it. The
patch is against 2.6.19-rc2.

Synopsis of patch: If __vmalloc is called to allocate memory with
GFP_ATOMIC in atomic context, the chain of calls results in
__get_vm_area_node allocating memory for vm_struct with GFP_KERNEL,
causing the 'sleeping from invalid context' warning. This patch fixes
it by passing the gfp flags along so __get_vm_area_node allocates
memory for vm_struct with the same flags.

Thanks,
Giri

diff -Naur linux-2.6.19-rc2.orig/include/linux/vmalloc.h linux-2.6.19-rc2/include/linux/vmalloc.h
--- linux-2.6.19-rc2.orig/include/linux/vmalloc.h 2006-10-23 01:43:35.000000000 -0400
+++ linux-2.6.19-rc2/include/linux/vmalloc.h 2006-10-23 01:45:24.000000000 -0400
@@ -60,7 +60,8 @@
extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end);
extern struct vm_struct *get_vm_area_node(unsigned long size,
- unsigned long flags, int node);
+ unsigned long flags, int node,
+ gfp_t gfp_mask);
extern struct vm_struct *remove_vm_area(void *addr);
extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
struct page ***pages);
diff -Naur linux-2.6.19-rc2.orig/mm/vmalloc.c linux-2.6.19-rc2/mm/vmalloc.c
--- linux-2.6.19-rc2.orig/mm/vmalloc.c 2006-10-23 01:43:55.000000000 -0400
+++ linux-2.6.19-rc2/mm/vmalloc.c 2006-10-23 01:45:24.000000000 -0400
@@ -160,13 +160,15 @@
return err;
}

-struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags,
- unsigned long start, unsigned long end, int node)
+static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags,
+ unsigned long start, unsigned long end,
+ int node, gfp_t gfp_mask)
{
struct vm_struct **p, *tmp, *area;
unsigned long align = 1;
unsigned long addr;

+ BUG_ON(in_interrupt());
if (flags & VM_IOREMAP) {
int bit = fls(size);

@@ -180,7 +182,7 @@
addr = ALIGN(start, align);
size = PAGE_ALIGN(size);

- area = kmalloc_node(sizeof(*area), GFP_KERNEL, node);
+ area = kmalloc_node(sizeof(*area), gfp_mask, node);
if (unlikely(!area))
return NULL;

@@ -236,7 +238,7 @@
struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end)
{
- return __get_vm_area_node(size, flags, start, end, -1);
+ return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL);
}

/**
@@ -253,9 +255,11 @@
return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
}

-struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags, int node)
+struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
+ int node, gfp_t gfp_mask)
{
- return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node);
+ return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node,
+ gfp_mask);
}

/* Caller must hold vmlist_lock */
@@ -484,7 +488,7 @@
if (!size || (size >> PAGE_SHIFT) > num_physpages)
return NULL;

- area = get_vm_area_node(size, VM_ALLOC, node);
+ area = get_vm_area_node(size, VM_ALLOC, node, gfp_mask);
if (!area)
return NULL;


2006-10-23 10:35:10

by Alan

[permalink] [raw]
Subject: Re: __vmalloc with GFP_ATOMIC causes 'sleeping from invalid context'

Ar Llu, 2006-10-23 am 02:13 -0400, ysgrifennodd Giridhar Pemmasani:
> Synopsis of patch: If __vmalloc is called to allocate memory with
> GFP_ATOMIC in atomic context, the chain of calls results in
> __get_vm_area_node allocating memory for vm_struct with GFP_KERNEL

You are not allowed to call vmalloc in atomic context, especially in
interrupt paths. Vmalloc has to do TLB handling work and that can
involve cross calls and other stuff that isn't IRQ friendly on all
platforms.


2006-10-23 11:11:47

by Giridhar Pemmasani

[permalink] [raw]
Subject: Re: __vmalloc with GFP_ATOMIC causes 'sleeping from invalid context'

--- Alan Cox <[email protected]> wrote:

> You are not allowed to call vmalloc in atomic context, especially in
> interrupt paths. Vmalloc has to do TLB handling work and that can
> involve cross calls and other stuff that isn't IRQ friendly on all
> platforms.

This has been discussed before:

http://marc.theaimsgroup.com/?l=linux-kernel&m=114831100404677&w=2

The problem is not with calling vmalloc in atomic context, but __vmalloc,
which can be. The proposed patch makes sure __vmalloc is not supposed to be
called in interrupt context.

Giri

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com