Skip to contentSkip to conversation

Fix for annoying problem with hostfs readdir problems.

PATCH In review Oleg Drokin 2 participants 4 messages Apr 15, 2004 – Apr 18, 2004 User-mode Linux (UML)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix for annoying problem with hostfs readdir problems.

Hello!

So the annoying problem with readdir not working on hostfs (on 2.6 host kernel only for me) was finally hunted to memory allocation problem during opendir.

The patch below is a working and tested attempt at fixing it. It is againt 2.4.20-something, but is pretty straightforward and probably should apply everywhere else.

Bye,
Oleg

arch/um/kernel/process_kern.c renamed from arch/um/kernel/process_kern.c.orig +6 -0
@@ -16,6 +16,7 @@
 #include "linux/module.h"
 #include "linux/init.h"
 #include "linux/capability.h"
+#include "linux/vmalloc.h"
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -279,6 +280,11 @@ void *um_kmalloc(int size)
 	return(kmalloc(size, GFP_KERNEL));
 }
 
+void *um_vmalloc(int size)
+{
+	return(vmalloc(size));
+}
+
 void *um_kmalloc_atomic(int size)
 {
 	return(kmalloc(size, GFP_ATOMIC));
arch/um/main.c renamed from arch/um/main.c.orig +2 -2
@@ -161,7 +161,7 @@ extern void *__real_malloc(int);
 void *__wrap_malloc(int size)
 {
 	if(CAN_KMALLOC())
-		return(um_kmalloc(size));
+		return(um_vmalloc(size));
 	else
 		return(__real_malloc(size));
 }
@@ -179,7 +179,7 @@ extern void __real_free(void *);
 
 void __wrap_free(void *ptr)
 {
-	if(CAN_KMALLOC()) kfree(ptr);
+	if(CAN_KMALLOC()) vfree(ptr);
 	else __real_free(ptr);
 }
 
arch/um/include/user.h renamed from arch/um/include/user.h.orig +1 -0
@@ -12,6 +12,7 @@ extern void schedule(void);
 extern void *um_kmalloc(int size);
 extern void *um_kmalloc_atomic(int size);
 extern void kfree(void *ptr);
+extern void vfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
 
#1 lore raw

Hello!

Quoted 7 lines · Oleg Drokin

So the annoying problem with readdir not working on hostfs (on 2.6 host kernel only for me) was finally hunted to memory allocation problem during opendir.

The patch below is a working and tested attempt at fixing it. It is againt 2.4.20-something, but is pretty straightforward and probably should apply everywhere else.

This is corrected version that sets errno on malloc failure and as a bonus - um_vmalloc is now also declared in header file and therefore no edtra warning in main.c ;)

Bye,
Oleg

arch/um/kernel/process_kern.c renamed from arch/um/kernel/process_kern.c.orig +6 -0
@@ -16,6 +16,7 @@
 #include "linux/module.h"
 #include "linux/init.h"
 #include "linux/capability.h"
+#include "linux/vmalloc.h"
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -279,6 +280,11 @@ void *um_kmalloc(int size)
 	return(kmalloc(size, GFP_KERNEL));
 }
 
+void *um_vmalloc(int size)
+{
+	return(vmalloc(size));
+}
+
 void *um_kmalloc_atomic(int size)
 {
 	return(kmalloc(size, GFP_ATOMIC));
arch/um/main.c renamed from arch/um/main.c.orig +11 -4
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <sys/user.h>
@@ -160,10 +161,16 @@ extern void *__real_malloc(int);
 
 void *__wrap_malloc(int size)
 {
-	if(CAN_KMALLOC())
-		return(um_kmalloc(size));
-	else
+	if(CAN_KMALLOC()) {
+		/* glibc people insist that if malloc fails, errno should be
+		   set by malloc as well. So we do. */
+		void *ret = um_vmalloc(size);
+		if (!ret)
+			errno = ENOMEM;
+		return(ret);
+	} else {
 		return(__real_malloc(size));
+	}
 }
 
 void *__wrap_calloc(int n, int size)
@@ -179,7 +186,7 @@ extern void __real_free(void *);
 
 void __wrap_free(void *ptr)
 {
-	if(CAN_KMALLOC()) kfree(ptr);
+	if(CAN_KMALLOC()) vfree(ptr);
 	else __real_free(ptr);
 }
 
arch/um/include/user.h renamed from arch/um/include/user.h.orig +2 -0
@@ -10,8 +10,10 @@ extern void panic(const char *fmt, ...);
 extern int printk(const char *fmt, ...);
 extern void schedule(void);
 extern void *um_kmalloc(int size);
+extern void *um_vmalloc(int size);
 extern void *um_kmalloc_atomic(int size);
 extern void kfree(void *ptr);
+extern void vfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
 
#2 lore raw

Alle 23:46, giovedì 15 aprile 2004, Oleg Drokin ha scritto:

Quoted 6 lines

Hello!

Quoted 3 lines · Oleg Drokin

So the annoying problem with readdir not working on hostfs (on 2.6
host kernel only for me) was finally hunted to memory allocation
problem during opendir.

I've experienced it too onto 2.6 and someone else had the same problem - but that patch is not perfect. Using always vmalloc() instead of kmalloc() is wrong - vmalloc is slower, and Linus spoke against vmalloc(); it would also slow down everything using malloc().

Probably you should use vmalloc() only if size is > the size limit (if this is the problem, as I guess). When you come at free() it is a bit hard, but IIRC vmalloc() can return pointers inside a certain, known memory area, right? So it is possible to understand what function to call.

Bye

Signature · 14 lines
Paolo Giarrusso, aka Blaisorblade
Linux registered user n. 292729



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&opÌk
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#3 lore raw

Hello!

Quoted 7 lines · BlaisorBlade
Quoted 3 lines
Quoted 3 lines

So the annoying problem with readdir not working on hostfs (on 2.6
host kernel only for me) was finally hunted to memory allocation
problem during opendir.

I've experienced it too onto 2.6 and someone else had the same problem - but that patch is not perfect. Using always vmalloc() instead of kmalloc() is wrong - vmalloc is slower, and Linus spoke against vmalloc(); it would also slow down everything using malloc().

Well, speed is not of much an issue there, that function is only used for glibc allocations. And that read_dir() is probably the only place that causes glibc to allocate something.

Quoted 4 lines

Probably you should use vmalloc() only if size is > the size limit (if this is the problem, as I guess). When you come at free() it is a bit hard, but IIRC vmalloc() can return pointers inside a certain, known memory area, right? So it is possible to understand what function to call.

I am sure that all of the complexity you propose to implement won't pay off in the end.

Bye,
Oleg

-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel