lkml.org 
[lkml]   [2010]   [Apr]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 2/4] vma_adjust: fix the copying of anon_vma chains

    From: Linus Torvalds <torvalds@linux-foundation.org>
    Date: Sat, 10 Apr 2010 15:22:30 -0700
    Subject: [PATCH 2/4] vma_adjust: fix the copying of anon_vma chains

    When we move the boundaries between two vma's due to things like
    mprotect, we need to make sure that the anon_vma of the pages that got
    moved from one vma to another gets properly copied around. And that was
    not always the case, in this rather hard-to-follow code sequence.

    Clarify the code, and fix it so that it copies the anon_vma from the
    right source.

    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    ---
    mm/mmap.c | 24 ++++++++----------------
    1 files changed, 8 insertions(+), 16 deletions(-)

    diff --git a/mm/mmap.c b/mm/mmap.c
    index acb023e..f90ea92 100644
    --- a/mm/mmap.c
    +++ b/mm/mmap.c
    @@ -507,11 +507,12 @@ int vma_adjust(struct vm_area_struct *vma, unsigned long start,
    struct address_space *mapping = NULL;
    struct prio_tree_root *root = NULL;
    struct file *file = vma->vm_file;
    - struct anon_vma *anon_vma = NULL;
    long adjust_next = 0;
    int remove_next = 0;

    if (next && !insert) {
    + struct vm_area_struct *exporter = NULL;
    +
    if (end >= next->vm_end) {
    /*
    * vma expands, overlapping all the next, and
    @@ -519,7 +520,7 @@ int vma_adjust(struct vm_area_struct *vma, unsigned long start,
    */
    again: remove_next = 1 + (end > next->vm_end);
    end = next->vm_end;
    - anon_vma = next->anon_vma;
    + exporter = next;
    importer = vma;
    } else if (end > next->vm_start) {
    /*
    @@ -527,7 +528,7 @@ again: remove_next = 1 + (end > next->vm_end);
    * mprotect case 5 shifting the boundary up.
    */
    adjust_next = (end - next->vm_start) >> PAGE_SHIFT;
    - anon_vma = next->anon_vma;
    + exporter = next;
    importer = vma;
    } else if (end < vma->vm_end) {
    /*
    @@ -536,28 +537,19 @@ again: remove_next = 1 + (end > next->vm_end);
    * mprotect case 4 shifting the boundary down.
    */
    adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);
    - anon_vma = next->anon_vma;
    + exporter = vma;
    importer = next;
    }
    - }

    - /*
    - * When changing only vma->vm_end, we don't really need anon_vma lock.
    - */
    - if (vma->anon_vma && (insert || importer || start != vma->vm_start))
    - anon_vma = vma->anon_vma;
    - if (anon_vma) {
    /*
    * Easily overlooked: when mprotect shifts the boundary,
    * make sure the expanding vma has anon_vma set if the
    * shrinking vma had, to cover any anon pages imported.
    */
    - if (importer && !importer->anon_vma) {
    - /* Block reverse map lookups until things are set up. */
    - if (anon_vma_clone(importer, vma)) {
    + if (exporter && exporter->anon_vma && !importer->anon_vma) {
    + if (anon_vma_clone(importer, exporter))
    return -ENOMEM;
    - }
    - importer->anon_vma = anon_vma;
    + importer->anon_vma = exporter->anon_vma;
    }
    }

    --
    1.7.1.rc1.dirty


    \
     
     \ /
      Last update: 2010-04-12 22:31    [W:0.025 / U:0.716 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site