From: From: Oleg Drokin , Jeff Dike , 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: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton --- 25-akpm/arch/um/include/user.h | 2 + 25-akpm/arch/um/kernel/process_kern.c | 6 +++++ 25-akpm/arch/um/main.c | 40 ++++++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 4 deletions(-) diff -puN arch/um/include/user.h~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host arch/um/include/user.h --- 25/arch/um/include/user.h~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host 2004-07-05 16:00:50.507342168 -0700 +++ 25-akpm/arch/um/include/user.h 2004-07-05 16:00:50.693313896 -0700 @@ -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 diff -puN arch/um/kernel/process_kern.c~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host arch/um/kernel/process_kern.c --- 25/arch/um/kernel/process_kern.c~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host 2004-07-05 16:00:50.509341864 -0700 +++ 25-akpm/arch/um/kernel/process_kern.c 2004-07-05 16:00:50.694313744 -0700 @@ -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); diff -puN arch/um/main.c~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host arch/um/main.c --- 25/arch/um/main.c~uml-make-malloc-call-vmalloc-if-needed-needed-for-hostfs-on-26-host 2004-07-05 16:00:50.678316176 -0700 +++ 25-akpm/arch/um/main.c 2004-07-05 16:00:50.694313744 -0700 @@ -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); } _