summaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-08-25 13:09:58 +0200
committerIngo Molnar <mingo@elte.hu>2010-08-25 13:10:00 +0200
commit7de5d895b2020260190db0021de646f3f22f755e (patch)
tree51d012f0b76a2ec1bd3b4837690faf1087f37056 /mm/memory.c
parent04fba67163a9e6132614b72b33bb2743bd33ffb3 (diff)
parent502adf5778f4151dcba3f64dd6ed322151f3712c (diff)
downloadlinux-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.c30
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;
}