lkml.org 
[lkml]   [1997]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectPatch for large kmalloc() problems
Date
There is a longstanding problem that kmalloc() often fails to allocate
big blocks of memory, due to memory fragmentation. While we can't do
much about it in the GFP_ATOMIC case, I think kmalloc() should try
a little harder to free some pages for normal GFP_KERNEL allocations.
For example, the ftape module often fails to load if the system has
been up for some time - needs three contiguous 32K DMA buffers, and
there are enough free pages, but they are too fragmented.

The following test module was used to test the patch. Without the
patch, trying to insmod it almost always fails (with a "Couldn't get
a free page..." printk), with the patch it works. The patch is at
the end of this mail.

/* big.c - kmalloc test module */
#define __KERNEL__
#define MODULE

#include <linux/module.h>
#include <linux/malloc.h>

/* can be changed via insmod, maximum kmalloc size is the default */
int size = 131048;
static void *p;

int
init_module(void)
{
p = kmalloc(size, GFP_KERNEL | GFP_DMA);
if (!p)
return -ENOMEM;
return 0;
}
void
cleanup_module(void)
{
kfree(p);
}
/* end of kmalloc test module */
Below is the patch (for 2.0.27 - but shouldn't be too hard to apply
to 2.1.xx by hand). Please test it and let me know if there are any
problems with it. If there will ever be another 2.0.xx kernel, and
the patch doesn't cause problems, I think this small patch should be
integrated in the stable kernel - otherwise it is problematic to use
ftape as a module: you never know if it will load this time or not
(loads fine at system startup - not much memory fragmentation yet).

Happy hacking,

Marek

--- linux/mm/page_alloc.c.orig Sat Aug 17 20:19:29 1996
+++ linux/mm/page_alloc.c Sat Jan 11 05:44:58 1997
@@ -210,11 +210,10 @@
cli();
if ((priority==GFP_ATOMIC) || nr_free_pages > reserved_pages) {
RMQUEUE(order, dma);
- restore_flags(flags);
- return 0;
}
restore_flags(flags);
- if (priority != GFP_BUFFER && try_to_free_page(priority, dma, 1))
+ if (priority != GFP_ATOMIC && priority != GFP_BUFFER &&
+ try_to_free_page(priority, dma, 1))
goto repeat;
return 0;
}
\
 
 \ /
  Last update: 2005-03-22 13:38    [from the cache]
©2003-2011 Jasper Spaans