Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Mikulas Patocka and committed by
Linus Torvalds
a09a79f6 26822eeb

+37 -15
+7 -5
fs/proc/task_mmu.c
··· 214 214 int flags = vma->vm_flags; 215 215 unsigned long ino = 0; 216 216 unsigned long long pgoff = 0; 217 - unsigned long start; 217 + unsigned long start, end; 218 218 dev_t dev = 0; 219 219 int len; 220 220 ··· 227 227 228 228 /* We don't show the stack guard page in /proc/maps */ 229 229 start = vma->vm_start; 230 - if (vma->vm_flags & VM_GROWSDOWN) 231 - if (!vma_stack_continue(vma->vm_prev, vma->vm_start)) 232 - start += PAGE_SIZE; 230 + if (stack_guard_page_start(vma, start)) 231 + start += PAGE_SIZE; 232 + end = vma->vm_end; 233 + if (stack_guard_page_end(vma, end)) 234 + end -= PAGE_SIZE; 233 235 234 236 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", 235 237 start, 236 - vma->vm_end, 238 + end, 237 239 flags & VM_READ ? 'r' : '-', 238 240 flags & VM_WRITE ? 'w' : '-', 239 241 flags & VM_EXEC ? 'x' : '-',
+23 -1
include/linux/mm.h
··· 1011 1011 int clear_page_dirty_for_io(struct page *page); 1012 1012 1013 1013 /* Is the vma a continuation of the stack vma above it? */ 1014 - static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) 1014 + static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) 1015 1015 { 1016 1016 return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); 1017 + } 1018 + 1019 + static inline int stack_guard_page_start(struct vm_area_struct *vma, 1020 + unsigned long addr) 1021 + { 1022 + return (vma->vm_flags & VM_GROWSDOWN) && 1023 + (vma->vm_start == addr) && 1024 + !vma_growsdown(vma->vm_prev, addr); 1025 + } 1026 + 1027 + /* Is the vma a continuation of the stack vma below it? */ 1028 + static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr) 1029 + { 1030 + return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP); 1031 + } 1032 + 1033 + static inline int stack_guard_page_end(struct vm_area_struct *vma, 1034 + unsigned long addr) 1035 + { 1036 + return (vma->vm_flags & VM_GROWSUP) && 1037 + (vma->vm_end == addr) && 1038 + !vma_growsup(vma->vm_next, addr); 1017 1039 } 1018 1040 1019 1041 extern unsigned long move_page_tables(struct vm_area_struct *vma,
+7 -9
mm/memory.c
··· 1412 1412 1413 1413 static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) 1414 1414 { 1415 - return (vma->vm_flags & VM_GROWSDOWN) && 1416 - (vma->vm_start == addr) && 1417 - !vma_stack_continue(vma->vm_prev, addr); 1415 + return stack_guard_page_start(vma, addr) || 1416 + stack_guard_page_end(vma, addr+PAGE_SIZE); 1418 1417 } 1419 1418 1420 1419 /** ··· 1550 1551 continue; 1551 1552 } 1552 1553 1553 - /* 1554 - * For mlock, just skip the stack guard page. 1555 - */ 1556 - if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start)) 1557 - goto next_page; 1558 - 1559 1554 do { 1560 1555 struct page *page; 1561 1556 unsigned int foll_flags = gup_flags; ··· 1566 1573 int ret; 1567 1574 unsigned int fault_flags = 0; 1568 1575 1576 + /* For mlock, just skip the stack guard page. */ 1577 + if (foll_flags & FOLL_MLOCK) { 1578 + if (stack_guard_page(vma, start)) 1579 + goto next_page; 1580 + } 1569 1581 if (foll_flags & FOLL_WRITE) 1570 1582 fault_flags |= FAULT_FLAG_WRITE; 1571 1583 if (nonblocking)