[real fix] Re: [patch] fix for cc1 Out of memory [Re: [TESTCASE] `Out of memory

Andrea Arcangeli (andrea@e-mind.com)
Tue, 13 Apr 1999 03:46:35 +0200 (CEST)


On Mon, 12 Apr 1999, Linus Torvalds wrote:

>Think about it. free_pgtables() only gets rid of page directories that
>have no mappings, and as such they must be clear. No?

Yes.

>Think something on the order of (written on-the-fly, I won't guarantee
>this is correct, but I think you'll get the idea).

Fine I understood the whole point of starting with a PGD gap and then
shrinking the size according to prev/next vmas.

But I couldn't find anything wrong in shm (except that everything there is
a tricky hack).

So I tried to reproduce the bug without shm and I am been succesfully:

#include <sys/types.h>
#include <sys/mman.h>

/* try attaching a single segment to multiple addresses */
#define segsize 0x10000
#define attaches 128
#define base_addr 0x01000000
main ()
{
int i; char* addr; char* result;
for (i=0, addr = (char*)base_addr; i<attaches; i++, addr += segsize)
{
if ((result = mmap(addr, segsize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE,
-1, 0)) != addr)
{
printf("not fixed %p\n", result);
break;
}
#if 0
printf("%p %p\n", result, result+segsize);
#endif
bzero(result, segsize);
}
for (i=0, addr = (char*)base_addr; i<attaches; i++, addr += segsize)
{
munmap(addr, segsize);
#if 0
printf("%p %p\n", addr, addr+segsize);
#endif
}
exit(result == (char*)(-1));
}

The one above is MikeG testcase converted by me from using shm vma to
ANON|FIXED mmap vma.

And now that I understood the point (thanks to you ;) of free_pgtables() I
am been able to understand it and to find the bug. Here it is the bug-fix
for 2.2.5:

Index: mmap.c
===================================================================
RCS file: /var/cvs/linux/mm/mmap.c,v
retrieving revision 1.1.2.15
diff -u -r1.1.2.15 mmap.c
--- mmap.c 1999/04/09 16:53:46 1.1.2.15
+++ linux/mm/mmap.c 1999/04/13 01:29:08
@@ -565,8 +565,8 @@
if (!prev)
goto no_mmaps;
if (prev->vm_end > start) {
- if (last > prev->vm_end)
- last = prev->vm_end;
+ if (last > prev->vm_start)
+ last = prev->vm_start;
goto no_mmaps;
}
}

Well, while the above is the standalone-bugfix, I think that if prev is
null we just know that mm->mmap will be after our start-end space. The
same is true for next, if we have a next it will be after us. So I think
this second patch will improve the code:

Index: mm/mmap.c
===================================================================
RCS file: /var/cvs/linux/mm/mmap.c,v
retrieving revision 1.1.2.15
diff -u -r1.1.2.15 mmap.c
--- mmap.c 1999/04/09 16:53:46 1.1.2.15
+++ linux/mm/mmap.c 1999/04/13 01:42:52
@@ -564,26 +564,19 @@
prev = mm->mmap;
if (!prev)
goto no_mmaps;
- if (prev->vm_end > start) {
- if (last > prev->vm_end)
- last = prev->vm_end;
- goto no_mmaps;
- }
+ if (last > prev->vm_start)
+ last = prev->vm_start;
+ goto no_mmaps;
}
- for (;;) {
+ {
struct vm_area_struct *next = prev->vm_next;

if (next) {
- if (next->vm_start < start) {
- prev = next;
- continue;
- }
if (last > next->vm_start)
last = next->vm_start;
}
if (prev->vm_end > first)
first = prev->vm_end + PGDIR_SIZE - 1;
- break;
}
no_mmaps:
first = first >> PGDIR_SHIFT;

but I have not tested this second patch because it's really late and I
need to sleep some hour also this night ;).

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/