diff options
author | Mark Brown <broonie@kernel.org> | 2015-01-16 22:06:57 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-01-16 22:06:57 +0000 |
commit | a47897538c3e1f71c35691a1f73e73dd9149977c (patch) | |
tree | 462c858397564058dbc996c6ab71613b6d1e35c8 /mm | |
parent | 7368857a8eed5144e56e65713970764ef0f2f0b8 (diff) | |
parent | a2ab9187600ddca13da9e5c20e3abb92ea885ddd (diff) |
Merge tag 'v3.14.29' into linux-linaro-lsk-v3.14
This is the 3.14.29 stable release
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memory.c | 4 | ||||
-rw-r--r-- | mm/mmap.c | 7 | ||||
-rw-r--r-- | mm/vmscan.c | 24 |
3 files changed, 20 insertions, 15 deletions
diff --git a/mm/memory.c b/mm/memory.c index 4f5c392ef9b5..fcc849d1eb5a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3206,7 +3206,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo if (prev && prev->vm_end == address) return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; - expand_downwards(vma, address - PAGE_SIZE); + return expand_downwards(vma, address - PAGE_SIZE); } if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { struct vm_area_struct *next = vma->vm_next; @@ -3215,7 +3215,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo if (next && next->vm_start == address + PAGE_SIZE) return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; - expand_upwards(vma, address + PAGE_SIZE); + return expand_upwards(vma, address + PAGE_SIZE); } return 0; } diff --git a/mm/mmap.c b/mm/mmap.c index b91ac800d7b7..085bcd890ad2 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2058,14 +2058,17 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns { struct mm_struct *mm = vma->vm_mm; struct rlimit *rlim = current->signal->rlim; - unsigned long new_start; + unsigned long new_start, actual_size; /* address space limit tests */ if (!may_expand_vm(mm, grow)) return -ENOMEM; /* Stack limit test */ - if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + actual_size = size; + if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) + actual_size -= PAGE_SIZE; + if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) return -ENOMEM; /* mlock limit tests */ diff --git a/mm/vmscan.c b/mm/vmscan.c index deb139e6b8ed..be6a689a71a6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2860,18 +2860,20 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, return false; /* - * There is a potential race between when kswapd checks its watermarks - * and a process gets throttled. There is also a potential race if - * processes get throttled, kswapd wakes, a large process exits therby - * balancing the zones that causes kswapd to miss a wakeup. If kswapd - * is going to sleep, no process should be sleeping on pfmemalloc_wait - * so wake them now if necessary. If necessary, processes will wake - * kswapd and get throttled again + * The throttled processes are normally woken up in balance_pgdat() as + * soon as pfmemalloc_watermark_ok() is true. But there is a potential + * race between when kswapd checks the watermarks and a process gets + * throttled. There is also a potential race if processes get + * throttled, kswapd wakes, a large process exits thereby balancing the + * zones, which causes kswapd to exit balance_pgdat() before reaching + * the wake up checks. If kswapd is going to sleep, no process should + * be sleeping on pfmemalloc_wait, so wake them now if necessary. If + * the wake up is premature, processes will wake kswapd and get + * throttled again. The difference from wake ups in balance_pgdat() is + * that here we are under prepare_to_wait(). */ - if (waitqueue_active(&pgdat->pfmemalloc_wait)) { - wake_up(&pgdat->pfmemalloc_wait); - return false; - } + if (waitqueue_active(&pgdat->pfmemalloc_wait)) + wake_up_all(&pgdat->pfmemalloc_wait); return pgdat_balanced(pgdat, order, classzone_idx); } |