Commit fbb214aa authored by Paolo \'Blaisorblade\' Giarrusso's avatar Paolo \'Blaisorblade\' Giarrusso Committed by Linus Torvalds

[PATCH] uml: Make malloc() call vmalloc if needed. Needed for hostfs on 2.6 host.

From: Oleg Drokin <green@linuxhacker.ru>, Jeff Dike <jdike@addtoit.com>, and
me

If size > 128K, with this patch malloc will call vmalloc; free will detect
whether to call vfree or kfree or __real_free().  The 2.4 version could forget
free()ing something; this has been fixed.
Signed-off-by: default avatarPaolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d32870ad
......@@ -15,6 +15,8 @@ extern void kfree(void *ptr);
extern int in_aton(char *str);
extern int open_gdb_chan(void);
extern int strlcpy(char *, const char *, int);
extern void *um_vmalloc(int size);
extern void vfree(void *ptr);
#endif
......
......@@ -16,6 +16,7 @@
#include "linux/module.h"
#include "linux/init.h"
#include "linux/capability.h"
#include "linux/vmalloc.h"
#include "linux/spinlock.h"
#include "asm/unistd.h"
#include "asm/mman.h"
......@@ -301,6 +302,11 @@ void *um_kmalloc_atomic(int size)
return(kmalloc(size, GFP_ATOMIC));
}
void *um_vmalloc(int size)
{
return(vmalloc(size));
}
unsigned long get_fault_addr(void)
{
return((unsigned long) current->thread.fault_addr);
......
......@@ -163,10 +163,21 @@ extern void *__real_malloc(int);
void *__wrap_malloc(int size)
{
if(CAN_KMALLOC())
return(um_kmalloc(size));
else
void *ret;
if(!CAN_KMALLOC())
return(__real_malloc(size));
else if(size <= 128 * 1024) /* kmalloc is good for only 128K */
ret = um_kmalloc(size);
else ret = um_vmalloc(size);
/* glibc people insist that if malloc fails, errno should be
* set by malloc as well. So we do.
*/
if(ret == NULL)
errno = ENOMEM;
return(ret);
}
void *__wrap_calloc(int n, int size)
......@@ -180,9 +191,30 @@ void *__wrap_calloc(int n, int size)
extern void __real_free(void *);
extern unsigned long high_physmem;
void __wrap_free(void *ptr)
{
if(CAN_KMALLOC()) kfree(ptr);
unsigned long addr = (unsigned long) ptr;
/* We need to know how the allocation happened, so it can be correctly
* freed. This is done by seeing what region of memory the pointer is
* in -
* physical memory - kmalloc/kfree
* kernel virtual memory - vmalloc/vfree
* anywhere else - malloc/free
* If kmalloc is not yet possible, then the kernel memory regions
* may not be set up yet, and the variables not initialized. So,
* free is called.
*/
if(CAN_KMALLOC()){
if((addr >= uml_physmem) && (addr <= high_physmem))
kfree(ptr);
else if((addr >= start_vm) && (addr <= end_vm))
vfree(ptr);
else
__real_free(ptr);
}
else __real_free(ptr);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment