From: Bernd Schmidt <bernds_cb1@t-online.de>
To: David Howells <dhowells@redhat.com>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
"Wu, Bryan" <Bryan.Wu@analog.com>
Subject: Re: [PATCH] NOMMU: Separate out VMAs
Date: Fri, 17 Aug 2007 13:49:34 +0200 [thread overview]
Message-ID: <46C58B4E.4080803@t-online.de> (raw)
In-Reply-To: <23350.1186492903@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1334 bytes --]
David Howells wrote:
> David Howells <dhowells@redhat.com> wrote:
>
>> Yes. I found the major leak this morning. There may be a minor leak, but I'm
>> not convinced it's in the mmap stuff. See revised patch.
>
> Oops. That was the old patch. Try this one instead.
>
Here are some changes to make it more stable on my system. In
do_mmap_private, I've commented out the logic to free excess pages, as
it fragments terribly and causes a simple
while true; do cat /proc/buddyinfo; done
loop to go oom. Also, I think you're freeing high-order pages unaligned
to their order?
In shrink_vma, we must save the mm across calls to remove_vma_from_mm
(oops when telnetting into the box).
In do_munmap, we can deal with freeing more than one vma. I've not
touched the rb-tree logic in the shared file case, as I have no idea
what it's trying to do given that only exact matches are allowed.
It still does not survive my mmap stress-tester, so I'll keep looking.
Why do we need vm_regions for anonymous memory? Wouldn't it be enough
to just have a VMA?
Bernd
--
This footer brought to you by insane German lawmakers.
Analog Devices GmbH Wilhelm-Wagenfeld-Str. 6 80807 Muenchen
Sitz der Gesellschaft Muenchen, Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, William A. Martin, Margaret Seif
[-- Attachment #2: fish.diff --]
[-- Type: text/plain, Size: 3892 bytes --]
diff --width=180 -x '*~' -x '.*' -x 'Sys*' -dru linux-2.6.x-daves-baseline/mm/nommu.c linux-2.6.x/mm/nommu.c
--- linux-2.6.x-daves-baseline/mm/nommu.c 2007-08-14 21:20:43.000000000 +0200
+++ linux-2.6.x/mm/nommu.c 2007-08-16 19:11:29.000000000 +0200
@@ -922,19 +931,23 @@
total = 1 << order;
atomic_add(total, &mmap_pages_allocated);
- point = len >> PAGE_SHIFT;
- while (point < total) {
- order = ilog2(total - point);
- _debug("shave %u/%lu", 1 << order, total - point);
- atomic_sub(1 << order, &mmap_pages_allocated);
- __free_pages(pages + point, order);
- point += 1 << order;
+ len = PAGE_SIZE << order;
+#if 0
+ while (total > (len >> PAGE_SHIFT)) {
+ unsigned long to_free;
+ order = ilog2(total - (len >> PAGE_SHIFT));
+ to_free = 1 << order;
+ _debug("shave %u/%lu", to_free, total - (len >> PAGE_SHIFT));
+ atomic_sub(to_free, &mmap_pages_allocated);
+ __free_pages(pages + total - to_free, order);
+ total -= to_free;
}
total = len >> PAGE_SHIFT;
for (point = 1; point < total; point++)
set_page_refcounted(&pages[point]);
-
+#endif
+ split_page(pages, order);
base = page_address(pages);
region->vm_start = vma->vm_start = (unsigned long) base;
region->vm_end = vma->vm_end = vma->vm_start + len;
@@ -1294,6 +1307,7 @@
unsigned long from, unsigned long to)
{
struct vm_region *region;
+ struct mm_struct *mm = vma->vm_mm;
_enter("");
@@ -1304,7 +1318,7 @@
vma->vm_end = from;
else
vma->vm_start = to;
- add_vma_to_mm(vma->vm_mm, vma);
+ add_vma_to_mm(mm, vma);
/* cut the region down to size */
region = vma->vm_region;
@@ -1337,44 +1351,59 @@
_enter(",%lx,%zx", start, len);
- /* find the first potentially overlapping VMA */
- vma = find_vma(mm, start);
- if (!vma) {
- _leave(" = -EINVAL [no]");
- return -EINVAL;
- }
-
- /* we're allowed to split an anonymous VMA but not a file-backed one */
- if (vma->vm_file) {
- do {
- if (start > vma->vm_start) {
- _leave(" = -EINVAL [miss]");
- return -EINVAL;
- }
- if (end == vma->vm_end)
- goto erase_whole_vma;
- rb = rb_next(&vma->vm_rb);
- vma = rb_entry(rb, struct vm_area_struct, vm_rb);
- } while (rb);
- _leave(" = -EINVAL [split file]");
- return -EINVAL;
- } else {
- /* the region must be a subset of the VMA found */
- if (start == vma->vm_start && end == vma->vm_end)
- goto erase_whole_vma;
- if (start < vma->vm_start || end > vma->vm_end) {
+ while (start < end) {
+ unsigned long this_end;
+ /* find the first potentially overlapping VMA */
+ vma = find_vma(mm, start);
+ if (!vma) {
+ _leave(" = -EINVAL [no]");
+ return -EINVAL;
+ }
+ if (start < vma->vm_start) {
_leave(" = -EINVAL [superset]");
return -EINVAL;
}
- if (start != vma->vm_start && end != vma->vm_end) {
+
+ this_end = vma->vm_end;
+
+ /* See if we can delete the entire VMA. */
+ if (start == vma->vm_start && end >= this_end) {
+ delete_vma_from_mm(vma);
+ put_vma(vma);
+ start = this_end;
+ continue;
+ }
+
+ /* we're allowed to split an anonymous VMA but not a file-backed one */
+ if (vma->vm_file) {
+ do {
+ if (start > vma->vm_start) {
+ _leave(" = -EINVAL [miss]");
+ return -EINVAL;
+ }
+ if (end == vma->vm_end)
+ goto erase_whole_vma;
+ rb = rb_next(&vma->vm_rb);
+ vma = rb_entry(rb, struct vm_area_struct, vm_rb);
+ } while (rb);
+ _leave(" = -EINVAL [split file]");
+ return -EINVAL;
+ } else {
+ if (start > vma->vm_start && end >= this_end) {
+ shrink_vma(vma, start, this_end);
+ start = this_end;
+ } else if (start == vma->vm_start && end < this_end) {
+ shrink_vma(vma, start, end);
+ break;
+ }
ret = split_vma(mm, vma, start, 1);
if (ret < 0) {
_leave(" = %d [split]", ret);
return ret;
- }
+ }
}
- return shrink_vma(vma, start, end);
}
+ return 0;
erase_whole_vma:
delete_vma_from_mm(vma);
next prev parent reply other threads:[~2007-08-17 11:50 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-08 13:53 [PATCH, RFD]: Unbreak no-mmu mmap Bernd Schmidt
2007-06-09 19:10 ` Matt Mackall
2007-06-11 21:08 ` Robin Getz
2007-06-11 22:09 ` Mike Frysinger
2007-06-11 23:04 ` Bernd Schmidt
2007-06-11 23:22 ` Mike Frysinger
2007-06-19 23:26 ` Robin Getz
2007-06-20 2:38 ` Bryan Wu
2007-06-20 3:00 ` Paul Mundt
2007-06-20 3:18 ` Bryan Wu
2007-06-27 5:50 ` Greg Ungerer
2007-06-22 12:59 ` David Howells
2007-06-22 13:35 ` David Howells
2007-06-22 14:29 ` [PATCH] NOMMU: " David Howells
2007-08-01 12:29 ` [PATCH, RFD]: " David Howells
2007-08-03 14:03 ` [PATCH] NOMMU: Separate out VMAs David Howells
2007-08-07 13:12 ` Bernd Schmidt
2007-08-07 13:17 ` David Howells
2007-08-07 13:21 ` David Howells
2007-08-07 13:37 ` Bernd Schmidt
2007-08-07 14:03 ` David Howells
2007-08-17 11:49 ` Bernd Schmidt [this message]
2007-08-20 15:12 ` David Howells
2007-08-20 16:02 ` Bernd Schmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46C58B4E.4080803@t-online.de \
--to=bernds_cb1@t-online.de \
--cc=Bryan.Wu@analog.com \
--cc=dhowells@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.