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); ...@@ -15,6 +15,8 @@ extern void kfree(void *ptr);
extern int in_aton(char *str); extern int in_aton(char *str);
extern int open_gdb_chan(void); extern int open_gdb_chan(void);
extern int strlcpy(char *, const char *, int); extern int strlcpy(char *, const char *, int);
extern void *um_vmalloc(int size);
extern void vfree(void *ptr);
#endif #endif
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "linux/module.h" #include "linux/module.h"
#include "linux/init.h" #include "linux/init.h"
#include "linux/capability.h" #include "linux/capability.h"
#include "linux/vmalloc.h"
#include "linux/spinlock.h" #include "linux/spinlock.h"
#include "asm/unistd.h" #include "asm/unistd.h"
#include "asm/mman.h" #include "asm/mman.h"
...@@ -301,6 +302,11 @@ void *um_kmalloc_atomic(int size) ...@@ -301,6 +302,11 @@ void *um_kmalloc_atomic(int size)
return(kmalloc(size, GFP_ATOMIC)); return(kmalloc(size, GFP_ATOMIC));
} }
void *um_vmalloc(int size)
{
return(vmalloc(size));
}
unsigned long get_fault_addr(void) unsigned long get_fault_addr(void)
{ {
return((unsigned long) current->thread.fault_addr); return((unsigned long) current->thread.fault_addr);
......
...@@ -163,10 +163,21 @@ extern void *__real_malloc(int); ...@@ -163,10 +163,21 @@ extern void *__real_malloc(int);
void *__wrap_malloc(int size) void *__wrap_malloc(int size)
{ {
if(CAN_KMALLOC()) void *ret;
return(um_kmalloc(size));
else if(!CAN_KMALLOC())
return(__real_malloc(size)); 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) void *__wrap_calloc(int n, int size)
...@@ -180,9 +191,30 @@ void *__wrap_calloc(int n, int size) ...@@ -180,9 +191,30 @@ void *__wrap_calloc(int n, int size)
extern void __real_free(void *); extern void __real_free(void *);
extern unsigned long high_physmem;
void __wrap_free(void *ptr) 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); 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