summaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-09-03 22:38:52 +0200
committerTakashi Iwai <tiwai@suse.de>2010-09-03 22:38:52 +0200
commit68885a3ff38ed51fa02f241feb405c9922a90ee0 (patch)
tree2fc626df39d5e0e1f6b065238141f7d49187c737 /mm/memory.c
parent7b28079b3284ccb15ad4f003fb7073890600d0c1 (diff)
parenta2acad8298a42b7be684a32fafaf83332bba9c2b (diff)
downloadop-kernel-dev-68885a3ff38ed51fa02f241feb405c9922a90ee0.zip
op-kernel-dev-68885a3ff38ed51fa02f241feb405c9922a90ee0.tar.gz
Merge branch 'fix/misc' into topic/misc
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 b6e5fd2..6b2ab10 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;
}
OpenPOWER on IntegriCloud