* [PATCH] mm: fix oom roll-back of __vmalloc_area_node
@ 2006-07-11 19:37 Jan Kiszka
2006-07-13 7:14 ` Andrew Morton
0 siblings, 1 reply; 4+ messages in thread
From: Jan Kiszka @ 2006-07-11 19:37 UTC (permalink / raw)
To: linux-kernel
__vunmap must not rely on area->nr_pages when picking the
release methode for area->pages. It may be too small when
__vmalloc_area_node failed early due to lacking memory.
Instead, use a flag in vmstruct to differentiate.
Applies against 2.6.18-rc1, but sighted, developed, and
tested on a 2.6.16 kernel.
Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
---
include/linux/vmalloc.h | 1 +
mm/vmalloc.c | 7 ++++---
2 files changed, 5 insertions(+), 3 deletions(-)
Index: linux-2.6/include/linux/vmalloc.h
===================================================================
--- linux-2.6.orig/include/linux/vmalloc.h
+++ linux-2.6/include/linux/vmalloc.h
@@ -11,6 +11,7 @@ struct vm_area_struct;
#define VM_ALLOC 0x00000002 /* vmalloc() */
#define VM_MAP 0x00000004 /* vmap()ed pages */
#define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */
+#define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */
/* bits [20..32] reserved for arch specific ioremap internals */
/*
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -340,7 +340,7 @@ void __vunmap(void *addr, int deallocate
__free_page(area->pages[i]);
}
- if (area->nr_pages > PAGE_SIZE/sizeof(struct page *))
+ if (area->flags & VM_VPAGES)
vfree(area->pages);
else
kfree(area->pages);
@@ -427,9 +427,10 @@ void *__vmalloc_area_node(struct vm_stru
area->nr_pages = nr_pages;
/* Please note that the recursion is strictly bounded. */
- if (array_size > PAGE_SIZE)
+ if (array_size > PAGE_SIZE) {
pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
- else
+ area->flags |= VM_VPAGES;
+ } else
pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node);
area->pages = pages;
if (!area->pages) {
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm: fix oom roll-back of __vmalloc_area_node
2006-07-11 19:37 [PATCH] mm: fix oom roll-back of __vmalloc_area_node Jan Kiszka
@ 2006-07-13 7:14 ` Andrew Morton
2006-07-13 7:38 ` Jan Kiszka
0 siblings, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2006-07-13 7:14 UTC (permalink / raw)
To: Jan Kiszka; +Cc: linux-kernel
On Tue, 11 Jul 2006 21:37:08 +0200
Jan Kiszka <jan.kiszka@web.de> wrote:
> __vunmap must not rely on area->nr_pages when picking the
> release methode for area->pages. It may be too small when
> __vmalloc_area_node failed early due to lacking memory.
> Instead, use a flag in vmstruct to differentiate.
So you mean that when this:
if (unlikely(!area->pages[i])) {
/* Successfully allocated i pages, free them in __vunmap() */
area->nr_pages = i;
goto fail;
happens, it could be that i <= PAGE_SIZE/sizeof(struct page *) and __vunmap
kfree()s something which it should have vfree()d, yes?
That sounds like a dead box, or worse.
I think the change would be a good one even if it didn't fix a bug, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm: fix oom roll-back of __vmalloc_area_node
2006-07-13 7:14 ` Andrew Morton
@ 2006-07-13 7:38 ` Jan Kiszka
2006-07-13 7:47 ` Andrew Morton
0 siblings, 1 reply; 4+ messages in thread
From: Jan Kiszka @ 2006-07-13 7:38 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel
Andrew Morton wrote:
> On Tue, 11 Jul 2006 21:37:08 +0200
> Jan Kiszka <jan.kiszka@web.de> wrote:
>
>
>> __vunmap must not rely on area->nr_pages when picking the
>> release methode for area->pages. It may be too small when
>> __vmalloc_area_node failed early due to lacking memory.
>> Instead, use a flag in vmstruct to differentiate.
>>
>
> So you mean that when this:
>
> if (unlikely(!area->pages[i])) {
> /* Successfully allocated i pages, free them in __vunmap() */
> area->nr_pages = i;
> goto fail;
>
> happens, it could be that i <= PAGE_SIZE/sizeof(struct page *) and __vunmap
> kfree()s something which it should have vfree()d, yes?
>
>
Yes, exactly. It then causes some BUG in kfree during unroll.
> That sounds like a dead box, or worse.
>
>
Someone triggered a too large vmalloc request, that was the scenario here.
> I think the change would be a good one even if it didn't fix a bug, thanks.
>
>
Meanwhile I thought about an even simpler solution:
__vunmap must not rely on area->nr_pages when picking the
release methode for area->pages. It may be too small when
__vmalloc_area_node failed due to lacking memory. Check
for the vmalloc address range instead.
Signed-off by: Jan Kiszka <jan.kiszka@web.de>
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -340,7 +340,7 @@ void __vunmap(void *addr, int deallocate
__free_page(area->pages[i]);
}
- if (area->nr_pages > PAGE_SIZE/sizeof(struct page *))
+ if (area->pages >= VMALLOC_START && area->pages < VMALLOC_END)
vfree(area->pages);
else
kfree(area->pages);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm: fix oom roll-back of __vmalloc_area_node
2006-07-13 7:38 ` Jan Kiszka
@ 2006-07-13 7:47 ` Andrew Morton
0 siblings, 0 replies; 4+ messages in thread
From: Andrew Morton @ 2006-07-13 7:47 UTC (permalink / raw)
To: Jan Kiszka; +Cc: linux-kernel
On Thu, 13 Jul 2006 09:38:38 +0200
Jan Kiszka <jan.kiszka@web.de> wrote:
> > I think the change would be a good one even if it didn't fix a bug, thanks.
> >
> >
> Meanwhile I thought about an even simpler solution:
>
>
> __vunmap must not rely on area->nr_pages when picking the
> release methode for area->pages. It may be too small when
> __vmalloc_area_node failed due to lacking memory. Check
> for the vmalloc address range instead.
>
> Signed-off by: Jan Kiszka <jan.kiszka@web.de>
>
> Index: linux-2.6/mm/vmalloc.c
> ===================================================================
> --- linux-2.6.orig/mm/vmalloc.c
> +++ linux-2.6/mm/vmalloc.c
> @@ -340,7 +340,7 @@ void __vunmap(void *addr, int deallocate
> __free_page(area->pages[i]);
> }
>
> - if (area->nr_pages > PAGE_SIZE/sizeof(struct page *))
> + if (area->pages >= VMALLOC_START && area->pages < VMALLOC_END)
> vfree(area->pages);
> else
> kfree(area->pages);
Nah, your first patch was better. Very clear, direct, explicit.
It even had a comment.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-07-13 7:47 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-11 19:37 [PATCH] mm: fix oom roll-back of __vmalloc_area_node Jan Kiszka
2006-07-13 7:14 ` Andrew Morton
2006-07-13 7:38 ` Jan Kiszka
2006-07-13 7:47 ` Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox