diff options
author | Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> | 2011-05-09 07:01:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-09 19:22:07 -0400 |
commit | a09a79f66874c905af35d5bb5e5f2fdc7b6b894d (patch) | |
tree | 9cb2ae1fef7083af91a49c19411e9871e0e59a37 /mm/memory.c | |
parent | 26822eebb25500fb0776c7c256a6af041e9f538b (diff) |
Don't lock guardpage if the stack is growing up
Linux kernel excludes guard page when performing mlock on a VMA with
down-growing stack. However, some architectures have up-growing stack
and locking the guard page should be excluded in this case too.
This patch fixes lvm2 on PA-RISC (and possibly other architectures with
up-growing stack). lvm2 calculates number of used pages when locking and
when unlocking and reports an internal error if the numbers mismatch.
[ Patch changed fairly extensively to also fix /proc/<pid>/maps for the
grows-up case, and to move things around a bit to clean it all up and
share the infrstructure with the /proc bits.
Tested on ia64 that has both grow-up and grow-down segments - Linus ]
Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
Tested-by: Tony Luck <tony.luck@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/mm/memory.c b/mm/memory.c index 27f425378112..61e66f026563 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1412,9 +1412,8 @@ no_page_table: | |||
1412 | 1412 | ||
1413 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | 1413 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) |
1414 | { | 1414 | { |
1415 | return (vma->vm_flags & VM_GROWSDOWN) && | 1415 | return stack_guard_page_start(vma, addr) || |
1416 | (vma->vm_start == addr) && | 1416 | stack_guard_page_end(vma, addr+PAGE_SIZE); |
1417 | !vma_stack_continue(vma->vm_prev, addr); | ||
1418 | } | 1417 | } |
1419 | 1418 | ||
1420 | /** | 1419 | /** |
@@ -1551,12 +1550,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1551 | continue; | 1550 | continue; |
1552 | } | 1551 | } |
1553 | 1552 | ||
1554 | /* | ||
1555 | * For mlock, just skip the stack guard page. | ||
1556 | */ | ||
1557 | if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start)) | ||
1558 | goto next_page; | ||
1559 | |||
1560 | do { | 1553 | do { |
1561 | struct page *page; | 1554 | struct page *page; |
1562 | unsigned int foll_flags = gup_flags; | 1555 | unsigned int foll_flags = gup_flags; |
@@ -1573,6 +1566,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1573 | int ret; | 1566 | int ret; |
1574 | unsigned int fault_flags = 0; | 1567 | unsigned int fault_flags = 0; |
1575 | 1568 | ||
1569 | /* For mlock, just skip the stack guard page. */ | ||
1570 | if (foll_flags & FOLL_MLOCK) { | ||
1571 | if (stack_guard_page(vma, start)) | ||
1572 | goto next_page; | ||
1573 | } | ||
1576 | if (foll_flags & FOLL_WRITE) | 1574 | if (foll_flags & FOLL_WRITE) |
1577 | fault_flags |= FAULT_FLAG_WRITE; | 1575 | fault_flags |= FAULT_FLAG_WRITE; |
1578 | if (nonblocking) | 1576 | if (nonblocking) |