[PATCH] fork failures on ix86, try 2

Kip Rugger (kbr@pangea.ca)
8 Jul 1998 02:23:07 -0500


In article <199807080150.SAA15896@dm.cobaltmicro.com>,
David S. Miller <davem@dm.cobaltmicro.com> wrote:
> From: rugger@rugger.nodomain.ca (Kip Rugger)
> Date: 7 Jul 1998 20:32:58 -0500
>
>[ BTW: nice email address, how do you expect people to respond to you? ]

hopefully reads kbr@pangea.ca

>
> Recent 2.1 kernels suffer memory fragmentation, eventually requests
> >4kB start failing. Among these are the requests made by fork for
> an 8kB kernel stack.
>
> This little hack changes fork to use the vmalloc service, so that
> the 8kB fork request can be satisfied with 2 non-contiguous 4kB
> pages.
>
>This patch is broken and will kill performance.
>
>It would be one thing to, when gfp() fails, use vmalloc() as a backup
>plan. Doing it all the time is totally unacceptable.

Agreed.

>
>Later,
>David S. Miller
>davem@dm.cobaltmicro.com
>
>-
>To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>the body of a message to majordomo@vger.rutgers.edu
>

===========================================================================

diff -ru /user/linux/linux-2.1.108/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- /user/linux/linux-2.1.108/include/asm-i386/processor.h Tue Jul 7 10:54:58 1998
+++ linux/include/asm-i386/processor.h Wed Jul 8 00:50:23 1998
@@ -217,9 +217,21 @@
/*
* NOTE! The task struct and the stack go together
*/
+
#define alloc_task_struct() \
- ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long)(p),1)
+({ \
+ struct task_struct * ts; \
+ ts = (struct task_struct *) __get_free_pages(GFP_KERNEL,1); \
+ if (!ts) ts = vmalloc(8192); \
+ ts; \
+})
+
+#define free_task_struct(p) do { \
+ if (VMALLOC_VMADDR(p) < VMALLOC_START) \
+ free_pages((unsigned long)(p),1); \
+ else \
+ vfree(p); \
+ } while(0)

#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
diff -ru /user/linux/linux-2.1.108/kernel/exit.c linux/kernel/exit.c
--- /user/linux/linux-2.1.108/kernel/exit.c Fri May 15 15:26:11 1998
+++ linux/kernel/exit.c Tue Jul 7 13:15:03 1998
@@ -23,6 +23,7 @@
#ifdef CONFIG_BSD_PROCESS_ACCT
#include <linux/acct.h>
#endif
+#include <linux/vmalloc.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>
diff -ru /user/linux/linux-2.1.108/kernel/fork.c linux/kernel/fork.c
--- /user/linux/linux-2.1.108/kernel/fork.c Tue Jul 7 10:47:02 1998
+++ linux/kernel/fork.c Tue Jul 7 13:14:40 1998
@@ -23,6 +23,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
+#include <linux/vmalloc.h>

#include <asm/system.h>
#include <asm/pgtable.h>
diff -ru /user/linux/linux-2.1.108/mm/vmalloc.c linux/mm/vmalloc.c
--- /user/linux/linux-2.1.108/mm/vmalloc.c Sat Jul 4 21:32:01 1998
+++ linux/mm/vmalloc.c Tue Jul 7 19:50:42 1998
@@ -159,10 +159,13 @@
if (!area)
return NULL;
addr = (void *) VMALLOC_START;
+ if ((unsigned long)addr & PAGE_SIZE) addr += PAGE_SIZE;
for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
if (size + (unsigned long) addr < (unsigned long) tmp->addr)
break;
addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+ /* ugly hack to allocate kernel stacks on 8k boundaries */
+ if ((unsigned long)addr & PAGE_SIZE) addr += PAGE_SIZE;
}
area->addr = addr;
area->size = size + PAGE_SIZE;
======= end of patch

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu