From: Michel Lespinasse <walken@google.com>
To: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>,
Daniel Forrest <dan.forrest@ssec.wisc.edu>,
Andrea Arcangeli <aarcange@redhat.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: [RFC PATCH] Re: Repeated fork() causes SLAB to grow without bound
Date: Tue, 21 Aug 2012 20:20:57 -0700 [thread overview]
Message-ID: <20120822032057.GA30871@google.com> (raw)
In-Reply-To: <CANN689Ej7XLh8VKuaPrTttDrtDGQbXuYJgS2uKnZL2EYVTM3Dg@mail.gmail.com>
On Mon, Aug 20, 2012 at 02:39:26AM -0700, Michel Lespinasse wrote:
> Instead of adding an atomic count for page references, we could limit
> the anon_vma stacking depth. In fork, we would only clone anon_vmas
> that have a low enough generation count. I think that's not great
> (adds a special case for the deep-fork-without-exec behavior), but
> still better than the atomic page reference counter.
Here is an attached patch to demonstrate the idea.
anon_vma_clone() is modified to return the length of the existing same_vma
anon vma chain, and we create a new anon_vma in the child only on the first
fork (this could be tweaked to allow up to a set number of forks, but
I think the first fork would cover all the common forking server cases).
Signed-off-by: Michel Lespinasse <walken@google.com>
---
mm/mmap.c | 6 +++---
mm/rmap.c | 18 ++++++++++++++----
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index 3edfcdfa42d9..e14b19a838cb 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -539,7 +539,7 @@ again: remove_next = 1 + (end > next->vm_end);
* shrinking vma had, to cover any anon pages imported.
*/
if (exporter && exporter->anon_vma && !importer->anon_vma) {
- if (anon_vma_clone(importer, exporter))
+ if (anon_vma_clone(importer, exporter) < 0)
return -ENOMEM;
importer->anon_vma = exporter->anon_vma;
}
@@ -1988,7 +1988,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
}
vma_set_policy(new, pol);
- if (anon_vma_clone(new, vma))
+ if (anon_vma_clone(new, vma) < 0)
goto out_free_mpol;
if (new->vm_file) {
@@ -2409,7 +2409,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
if (IS_ERR(pol))
goto out_free_vma;
INIT_LIST_HEAD(&new_vma->anon_vma_chain);
- if (anon_vma_clone(new_vma, vma))
+ if (anon_vma_clone(new_vma, vma) < 0)
goto out_free_mempol;
vma_set_policy(new_vma, pol);
new_vma->vm_start = addr;
diff --git a/mm/rmap.c b/mm/rmap.c
index 0f3b7cda2a24..ba8a726aaee6 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -238,12 +238,13 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
/*
* Attach the anon_vmas from src to dst.
- * Returns 0 on success, -ENOMEM on failure.
+ * Returns length of the anon_vma chain on success, -ENOMEM on failure.
*/
int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
{
struct anon_vma_chain *avc, *pavc;
struct anon_vma *root = NULL;
+ int length = 0;
list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
struct anon_vma *anon_vma;
@@ -259,9 +260,10 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
anon_vma = pavc->anon_vma;
root = lock_anon_vma_root(root, anon_vma);
anon_vma_chain_link(dst, avc, anon_vma);
+ length++;
}
unlock_anon_vma_root(root);
- return 0;
+ return length;
enomem_failure:
unlink_anon_vmas(dst);
@@ -322,6 +324,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
{
struct anon_vma_chain *avc;
struct anon_vma *anon_vma;
+ int length;
/* Don't bother if the parent process has no anon_vma here. */
if (!pvma->anon_vma)
@@ -331,10 +334,17 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
* First, attach the new VMA to the parent VMA's anon_vmas,
* so rmap can find non-COWed pages in child processes.
*/
- if (anon_vma_clone(vma, pvma))
+ length = anon_vma_clone(vma, pvma);
+ if (length < 0)
return -ENOMEM;
+ else if (length > 1)
+ return 0;
- /* Then add our own anon_vma. */
+ /*
+ * Then add our own anon_vma. We do this only on the first fork after
+ * the anon_vma is created, as we don't want the same_vma chain to
+ * grow arbitrarily large.
+ */
anon_vma = anon_vma_alloc();
if (!anon_vma)
goto out_error;
--
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2012-08-22 3:21 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20120816024610.GA5350@evergreen.ssec.wisc.edu>
2012-08-16 18:58 ` Repeated fork() causes SLAB to grow without bound Rik van Riel
2012-08-18 0:03 ` Daniel Forrest
2012-08-18 3:46 ` Rik van Riel
2012-08-18 4:07 ` Daniel Forrest
2012-08-18 4:10 ` Rik van Riel
2012-08-20 8:00 ` Hugh Dickins
2012-08-20 9:39 ` Michel Lespinasse
2012-08-20 11:11 ` Andi Kleen
2012-08-20 11:17 ` Rik van Riel
2012-08-20 11:53 ` Michel Lespinasse
2012-08-20 19:11 ` Michel Lespinasse
2012-08-22 3:20 ` Michel Lespinasse [this message]
2012-08-22 3:29 ` [RFC PATCH] " Rik van Riel
2013-06-03 19:50 ` Daniel Forrest
2013-06-04 10:37 ` Rik van Riel
2013-06-05 14:02 ` Andrea Arcangeli
2014-11-14 16:30 ` [PATCH] " Daniel Forrest
2014-11-18 0:02 ` Andrew Morton
2014-11-18 1:41 ` Daniel Forrest
2014-11-18 2:41 ` Rik van Riel
2014-11-18 20:19 ` Andrew Morton
2014-11-18 22:15 ` Konstantin Khlebnikov
2014-11-18 23:02 ` Konstantin Khlebnikov
2014-11-18 23:50 ` Vlastimil Babka
2014-11-19 14:36 ` Konstantin Khlebnikov
2014-11-19 16:09 ` Vlastimil Babka
2014-11-19 16:58 ` Konstantin Khlebnikov
2014-11-19 23:14 ` Michel Lespinasse
2014-11-20 14:42 ` Konstantin Khlebnikov
2014-11-20 14:50 ` Rik van Riel
2014-11-20 15:03 ` Konstantin Khlebnikov
2014-11-24 7:09 ` Konstantin Khlebnikov
2014-11-25 10:59 ` Michal Hocko
2014-11-25 12:13 ` Konstantin Khlebnikov
2014-11-25 15:00 ` Michal Hocko
2014-11-26 17:35 ` Michal Hocko
2014-12-05 15:44 ` Jerome Marchand
2014-11-20 15:27 ` Michel Lespinasse
2014-11-19 2:48 ` Rik van Riel
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=20120822032057.GA30871@google.com \
--to=walken@google.com \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=dan.forrest@ssec.wisc.edu \
--cc=hughd@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=riel@redhat.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).