diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-08-25 13:09:58 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-08-25 13:10:00 +0200 |
commit | 7de5d895b2020260190db0021de646f3f22f755e (patch) | |
tree | 51d012f0b76a2ec1bd3b4837690faf1087f37056 /mm/memory.c | |
parent | 04fba67163a9e6132614b72b33bb2743bd33ffb3 (diff) | |
parent | 502adf5778f4151dcba3f64dd6ed322151f3712c (diff) | |
download | linux-7de5d895b2020260190db0021de646f3f22f755e.tar.bz2 |
Merge branch 'linus' into perf/core
Merge reason: pick up perf fixes
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/mm/memory.c b/mm/memory.c index b6e5fd23cc5a..6b2ab1051851 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2760,21 +2760,35 @@ out_release: } /* - * This is like a special single-page "expand_downwards()", - * except we must first make sure that 'address-PAGE_SIZE' + * This is like a special single-page "expand_{down|up}wards()", + * except we must first make sure that 'address{-|+}PAGE_SIZE' * doesn't hit another vma. - * - * The "find_vma()" will do the right thing even if we wrap */ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) { address &= PAGE_MASK; if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { - address -= PAGE_SIZE; - if (find_vma(vma->vm_mm, address) != vma) - return -ENOMEM; + struct vm_area_struct *prev = vma->vm_prev; + + /* + * Is there a mapping abutting this one below? + * + * That's only ok if it's the same stack mapping + * that has gotten split.. + */ + if (prev && prev->vm_end == address) + return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; + + expand_stack(vma, address - PAGE_SIZE); + } + if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { + struct vm_area_struct *next = vma->vm_next; + + /* As VM_GROWSDOWN but s/below/above/ */ + if (next && next->vm_start == address + PAGE_SIZE) + return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; - expand_stack(vma, address); + expand_upwards(vma, address + PAGE_SIZE); } return 0; } |