diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/huge_memory.c | 49 | ||||
-rw-r--r-- | mm/memory.c | 28 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 2 | ||||
-rw-r--r-- | mm/mlock.c | 13 | ||||
-rw-r--r-- | mm/mmap.c | 15 | ||||
-rw-r--r-- | mm/oom_kill.c | 28 | ||||
-rw-r--r-- | mm/page_alloc.c | 2 | ||||
-rw-r--r-- | mm/shmem.c | 6 | ||||
-rw-r--r-- | mm/vmscan.c | 24 | ||||
-rw-r--r-- | mm/vmstat.c | 18 |
10 files changed, 97 insertions, 88 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0a619e0e2e0b..470dcda10add 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -244,24 +244,28 @@ static ssize_t single_flag_show(struct kobject *kobj, | |||
244 | struct kobj_attribute *attr, char *buf, | 244 | struct kobj_attribute *attr, char *buf, |
245 | enum transparent_hugepage_flag flag) | 245 | enum transparent_hugepage_flag flag) |
246 | { | 246 | { |
247 | if (test_bit(flag, &transparent_hugepage_flags)) | 247 | return sprintf(buf, "%d\n", |
248 | return sprintf(buf, "[yes] no\n"); | 248 | !!test_bit(flag, &transparent_hugepage_flags)); |
249 | else | ||
250 | return sprintf(buf, "yes [no]\n"); | ||
251 | } | 249 | } |
250 | |||
252 | static ssize_t single_flag_store(struct kobject *kobj, | 251 | static ssize_t single_flag_store(struct kobject *kobj, |
253 | struct kobj_attribute *attr, | 252 | struct kobj_attribute *attr, |
254 | const char *buf, size_t count, | 253 | const char *buf, size_t count, |
255 | enum transparent_hugepage_flag flag) | 254 | enum transparent_hugepage_flag flag) |
256 | { | 255 | { |
257 | if (!memcmp("yes", buf, | 256 | unsigned long value; |
258 | min(sizeof("yes")-1, count))) { | 257 | int ret; |
258 | |||
259 | ret = kstrtoul(buf, 10, &value); | ||
260 | if (ret < 0) | ||
261 | return ret; | ||
262 | if (value > 1) | ||
263 | return -EINVAL; | ||
264 | |||
265 | if (value) | ||
259 | set_bit(flag, &transparent_hugepage_flags); | 266 | set_bit(flag, &transparent_hugepage_flags); |
260 | } else if (!memcmp("no", buf, | 267 | else |
261 | min(sizeof("no")-1, count))) { | ||
262 | clear_bit(flag, &transparent_hugepage_flags); | 268 | clear_bit(flag, &transparent_hugepage_flags); |
263 | } else | ||
264 | return -EINVAL; | ||
265 | 269 | ||
266 | return count; | 270 | return count; |
267 | } | 271 | } |
@@ -680,8 +684,11 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
680 | return VM_FAULT_OOM; | 684 | return VM_FAULT_OOM; |
681 | page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), | 685 | page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), |
682 | vma, haddr, numa_node_id(), 0); | 686 | vma, haddr, numa_node_id(), 0); |
683 | if (unlikely(!page)) | 687 | if (unlikely(!page)) { |
688 | count_vm_event(THP_FAULT_FALLBACK); | ||
684 | goto out; | 689 | goto out; |
690 | } | ||
691 | count_vm_event(THP_FAULT_ALLOC); | ||
685 | if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) { | 692 | if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) { |
686 | put_page(page); | 693 | put_page(page); |
687 | goto out; | 694 | goto out; |
@@ -909,11 +916,13 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
909 | new_page = NULL; | 916 | new_page = NULL; |
910 | 917 | ||
911 | if (unlikely(!new_page)) { | 918 | if (unlikely(!new_page)) { |
919 | count_vm_event(THP_FAULT_FALLBACK); | ||
912 | ret = do_huge_pmd_wp_page_fallback(mm, vma, address, | 920 | ret = do_huge_pmd_wp_page_fallback(mm, vma, address, |
913 | pmd, orig_pmd, page, haddr); | 921 | pmd, orig_pmd, page, haddr); |
914 | put_page(page); | 922 | put_page(page); |
915 | goto out; | 923 | goto out; |
916 | } | 924 | } |
925 | count_vm_event(THP_FAULT_ALLOC); | ||
917 | 926 | ||
918 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { | 927 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { |
919 | put_page(new_page); | 928 | put_page(new_page); |
@@ -1390,6 +1399,7 @@ int split_huge_page(struct page *page) | |||
1390 | 1399 | ||
1391 | BUG_ON(!PageSwapBacked(page)); | 1400 | BUG_ON(!PageSwapBacked(page)); |
1392 | __split_huge_page(page, anon_vma); | 1401 | __split_huge_page(page, anon_vma); |
1402 | count_vm_event(THP_SPLIT); | ||
1393 | 1403 | ||
1394 | BUG_ON(PageCompound(page)); | 1404 | BUG_ON(PageCompound(page)); |
1395 | out_unlock: | 1405 | out_unlock: |
@@ -1784,9 +1794,11 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1784 | node, __GFP_OTHER_NODE); | 1794 | node, __GFP_OTHER_NODE); |
1785 | if (unlikely(!new_page)) { | 1795 | if (unlikely(!new_page)) { |
1786 | up_read(&mm->mmap_sem); | 1796 | up_read(&mm->mmap_sem); |
1797 | count_vm_event(THP_COLLAPSE_ALLOC_FAILED); | ||
1787 | *hpage = ERR_PTR(-ENOMEM); | 1798 | *hpage = ERR_PTR(-ENOMEM); |
1788 | return; | 1799 | return; |
1789 | } | 1800 | } |
1801 | count_vm_event(THP_COLLAPSE_ALLOC); | ||
1790 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { | 1802 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { |
1791 | up_read(&mm->mmap_sem); | 1803 | up_read(&mm->mmap_sem); |
1792 | put_page(new_page); | 1804 | put_page(new_page); |
@@ -2151,8 +2163,11 @@ static void khugepaged_do_scan(struct page **hpage) | |||
2151 | #ifndef CONFIG_NUMA | 2163 | #ifndef CONFIG_NUMA |
2152 | if (!*hpage) { | 2164 | if (!*hpage) { |
2153 | *hpage = alloc_hugepage(khugepaged_defrag()); | 2165 | *hpage = alloc_hugepage(khugepaged_defrag()); |
2154 | if (unlikely(!*hpage)) | 2166 | if (unlikely(!*hpage)) { |
2167 | count_vm_event(THP_COLLAPSE_ALLOC_FAILED); | ||
2155 | break; | 2168 | break; |
2169 | } | ||
2170 | count_vm_event(THP_COLLAPSE_ALLOC); | ||
2156 | } | 2171 | } |
2157 | #else | 2172 | #else |
2158 | if (IS_ERR(*hpage)) | 2173 | if (IS_ERR(*hpage)) |
@@ -2192,8 +2207,11 @@ static struct page *khugepaged_alloc_hugepage(void) | |||
2192 | 2207 | ||
2193 | do { | 2208 | do { |
2194 | hpage = alloc_hugepage(khugepaged_defrag()); | 2209 | hpage = alloc_hugepage(khugepaged_defrag()); |
2195 | if (!hpage) | 2210 | if (!hpage) { |
2211 | count_vm_event(THP_COLLAPSE_ALLOC_FAILED); | ||
2196 | khugepaged_alloc_sleep(); | 2212 | khugepaged_alloc_sleep(); |
2213 | } else | ||
2214 | count_vm_event(THP_COLLAPSE_ALLOC); | ||
2197 | } while (unlikely(!hpage) && | 2215 | } while (unlikely(!hpage) && |
2198 | likely(khugepaged_enabled())); | 2216 | likely(khugepaged_enabled())); |
2199 | return hpage; | 2217 | return hpage; |
@@ -2210,8 +2228,11 @@ static void khugepaged_loop(void) | |||
2210 | while (likely(khugepaged_enabled())) { | 2228 | while (likely(khugepaged_enabled())) { |
2211 | #ifndef CONFIG_NUMA | 2229 | #ifndef CONFIG_NUMA |
2212 | hpage = khugepaged_alloc_hugepage(); | 2230 | hpage = khugepaged_alloc_hugepage(); |
2213 | if (unlikely(!hpage)) | 2231 | if (unlikely(!hpage)) { |
2232 | count_vm_event(THP_COLLAPSE_ALLOC_FAILED); | ||
2214 | break; | 2233 | break; |
2234 | } | ||
2235 | count_vm_event(THP_COLLAPSE_ALLOC); | ||
2215 | #else | 2236 | #else |
2216 | if (IS_ERR(hpage)) { | 2237 | if (IS_ERR(hpage)) { |
2217 | khugepaged_alloc_sleep(); | 2238 | khugepaged_alloc_sleep(); |
diff --git a/mm/memory.c b/mm/memory.c index 9da8cab1b1b0..ce22a250926f 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1410,6 +1410,13 @@ no_page_table: | |||
1410 | return page; | 1410 | return page; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | ||
1414 | { | ||
1415 | return (vma->vm_flags & VM_GROWSDOWN) && | ||
1416 | (vma->vm_start == addr) && | ||
1417 | !vma_stack_continue(vma->vm_prev, addr); | ||
1418 | } | ||
1419 | |||
1413 | /** | 1420 | /** |
1414 | * __get_user_pages() - pin user pages in memory | 1421 | * __get_user_pages() - pin user pages in memory |
1415 | * @tsk: task_struct of target task | 1422 | * @tsk: task_struct of target task |
@@ -1488,7 +1495,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1488 | vma = find_extend_vma(mm, start); | 1495 | vma = find_extend_vma(mm, start); |
1489 | if (!vma && in_gate_area(mm, start)) { | 1496 | if (!vma && in_gate_area(mm, start)) { |
1490 | unsigned long pg = start & PAGE_MASK; | 1497 | unsigned long pg = start & PAGE_MASK; |
1491 | struct vm_area_struct *gate_vma = get_gate_vma(mm); | ||
1492 | pgd_t *pgd; | 1498 | pgd_t *pgd; |
1493 | pud_t *pud; | 1499 | pud_t *pud; |
1494 | pmd_t *pmd; | 1500 | pmd_t *pmd; |
@@ -1513,10 +1519,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1513 | pte_unmap(pte); | 1519 | pte_unmap(pte); |
1514 | return i ? : -EFAULT; | 1520 | return i ? : -EFAULT; |
1515 | } | 1521 | } |
1522 | vma = get_gate_vma(mm); | ||
1516 | if (pages) { | 1523 | if (pages) { |
1517 | struct page *page; | 1524 | struct page *page; |
1518 | 1525 | ||
1519 | page = vm_normal_page(gate_vma, start, *pte); | 1526 | page = vm_normal_page(vma, start, *pte); |
1520 | if (!page) { | 1527 | if (!page) { |
1521 | if (!(gup_flags & FOLL_DUMP) && | 1528 | if (!(gup_flags & FOLL_DUMP) && |
1522 | is_zero_pfn(pte_pfn(*pte))) | 1529 | is_zero_pfn(pte_pfn(*pte))) |
@@ -1530,12 +1537,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1530 | get_page(page); | 1537 | get_page(page); |
1531 | } | 1538 | } |
1532 | pte_unmap(pte); | 1539 | pte_unmap(pte); |
1533 | if (vmas) | 1540 | goto next_page; |
1534 | vmas[i] = gate_vma; | ||
1535 | i++; | ||
1536 | start += PAGE_SIZE; | ||
1537 | nr_pages--; | ||
1538 | continue; | ||
1539 | } | 1541 | } |
1540 | 1542 | ||
1541 | if (!vma || | 1543 | if (!vma || |
@@ -1549,6 +1551,13 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1549 | continue; | 1551 | continue; |
1550 | } | 1552 | } |
1551 | 1553 | ||
1554 | /* | ||
1555 | * If we don't actually want the page itself, | ||
1556 | * and it's the stack guard page, just skip it. | ||
1557 | */ | ||
1558 | if (!pages && stack_guard_page(vma, start)) | ||
1559 | goto next_page; | ||
1560 | |||
1552 | do { | 1561 | do { |
1553 | struct page *page; | 1562 | struct page *page; |
1554 | unsigned int foll_flags = gup_flags; | 1563 | unsigned int foll_flags = gup_flags; |
@@ -1631,6 +1640,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1631 | flush_anon_page(vma, page, start); | 1640 | flush_anon_page(vma, page, start); |
1632 | flush_dcache_page(page); | 1641 | flush_dcache_page(page); |
1633 | } | 1642 | } |
1643 | next_page: | ||
1634 | if (vmas) | 1644 | if (vmas) |
1635 | vmas[i] = vma; | 1645 | vmas[i] = vma; |
1636 | i++; | 1646 | i++; |
@@ -3678,7 +3688,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, | |||
3678 | */ | 3688 | */ |
3679 | #ifdef CONFIG_HAVE_IOREMAP_PROT | 3689 | #ifdef CONFIG_HAVE_IOREMAP_PROT |
3680 | vma = find_vma(mm, addr); | 3690 | vma = find_vma(mm, addr); |
3681 | if (!vma) | 3691 | if (!vma || vma->vm_start > addr) |
3682 | break; | 3692 | break; |
3683 | if (vma->vm_ops && vma->vm_ops->access) | 3693 | if (vma->vm_ops && vma->vm_ops->access) |
3684 | ret = vma->vm_ops->access(vma, addr, buf, | 3694 | ret = vma->vm_ops->access(vma, addr, buf, |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a2acaf820fe5..9ca1d604f7cd 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -375,7 +375,7 @@ void online_page(struct page *page) | |||
375 | #endif | 375 | #endif |
376 | 376 | ||
377 | #ifdef CONFIG_FLATMEM | 377 | #ifdef CONFIG_FLATMEM |
378 | max_mapnr = max(page_to_pfn(page), max_mapnr); | 378 | max_mapnr = max(pfn, max_mapnr); |
379 | #endif | 379 | #endif |
380 | 380 | ||
381 | ClearPageReserved(page); | 381 | ClearPageReserved(page); |
diff --git a/mm/mlock.c b/mm/mlock.c index 2689a08c79af..6b55e3efe0df 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
@@ -135,13 +135,6 @@ void munlock_vma_page(struct page *page) | |||
135 | } | 135 | } |
136 | } | 136 | } |
137 | 137 | ||
138 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | ||
139 | { | ||
140 | return (vma->vm_flags & VM_GROWSDOWN) && | ||
141 | (vma->vm_start == addr) && | ||
142 | !vma_stack_continue(vma->vm_prev, addr); | ||
143 | } | ||
144 | |||
145 | /** | 138 | /** |
146 | * __mlock_vma_pages_range() - mlock a range of pages in the vma. | 139 | * __mlock_vma_pages_range() - mlock a range of pages in the vma. |
147 | * @vma: target vma | 140 | * @vma: target vma |
@@ -188,12 +181,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, | |||
188 | if (vma->vm_flags & VM_LOCKED) | 181 | if (vma->vm_flags & VM_LOCKED) |
189 | gup_flags |= FOLL_MLOCK; | 182 | gup_flags |= FOLL_MLOCK; |
190 | 183 | ||
191 | /* We don't try to access the guard page of a stack vma */ | ||
192 | if (stack_guard_page(vma, start)) { | ||
193 | addr += PAGE_SIZE; | ||
194 | nr_pages--; | ||
195 | } | ||
196 | |||
197 | return __get_user_pages(current, mm, addr, nr_pages, gup_flags, | 184 | return __get_user_pages(current, mm, addr, nr_pages, gup_flags, |
198 | NULL, NULL, nonblocking); | 185 | NULL, NULL, nonblocking); |
199 | } | 186 | } |
@@ -259,7 +259,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) | |||
259 | * randomize_va_space to 2, which will still cause mm->start_brk | 259 | * randomize_va_space to 2, which will still cause mm->start_brk |
260 | * to be arbitrarily shifted | 260 | * to be arbitrarily shifted |
261 | */ | 261 | */ |
262 | if (mm->start_brk > PAGE_ALIGN(mm->end_data)) | 262 | if (current->brk_randomized) |
263 | min_brk = mm->start_brk; | 263 | min_brk = mm->start_brk; |
264 | else | 264 | else |
265 | min_brk = mm->end_data; | 265 | min_brk = mm->end_data; |
@@ -1814,11 +1814,14 @@ static int expand_downwards(struct vm_area_struct *vma, | |||
1814 | size = vma->vm_end - address; | 1814 | size = vma->vm_end - address; |
1815 | grow = (vma->vm_start - address) >> PAGE_SHIFT; | 1815 | grow = (vma->vm_start - address) >> PAGE_SHIFT; |
1816 | 1816 | ||
1817 | error = acct_stack_growth(vma, size, grow); | 1817 | error = -ENOMEM; |
1818 | if (!error) { | 1818 | if (grow <= vma->vm_pgoff) { |
1819 | vma->vm_start = address; | 1819 | error = acct_stack_growth(vma, size, grow); |
1820 | vma->vm_pgoff -= grow; | 1820 | if (!error) { |
1821 | perf_event_mmap(vma); | 1821 | vma->vm_start = address; |
1822 | vma->vm_pgoff -= grow; | ||
1823 | perf_event_mmap(vma); | ||
1824 | } | ||
1822 | } | 1825 | } |
1823 | } | 1826 | } |
1824 | vma_unlock_anon_vma(vma); | 1827 | vma_unlock_anon_vma(vma); |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 6a819d1b2c7d..83fb72c108b7 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -84,24 +84,6 @@ static bool has_intersects_mems_allowed(struct task_struct *tsk, | |||
84 | #endif /* CONFIG_NUMA */ | 84 | #endif /* CONFIG_NUMA */ |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * If this is a system OOM (not a memcg OOM) and the task selected to be | ||
88 | * killed is not already running at high (RT) priorities, speed up the | ||
89 | * recovery by boosting the dying task to the lowest FIFO priority. | ||
90 | * That helps with the recovery and avoids interfering with RT tasks. | ||
91 | */ | ||
92 | static void boost_dying_task_prio(struct task_struct *p, | ||
93 | struct mem_cgroup *mem) | ||
94 | { | ||
95 | struct sched_param param = { .sched_priority = 1 }; | ||
96 | |||
97 | if (mem) | ||
98 | return; | ||
99 | |||
100 | if (!rt_task(p)) | ||
101 | sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * The process p may have detached its own ->mm while exiting or through | 87 | * The process p may have detached its own ->mm while exiting or through |
106 | * use_mm(), but one or more of its subthreads may still have a valid | 88 | * use_mm(), but one or more of its subthreads may still have a valid |
107 | * pointer. Return p, or any of its subthreads with a valid ->mm, with | 89 | * pointer. Return p, or any of its subthreads with a valid ->mm, with |
@@ -452,13 +434,6 @@ static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem) | |||
452 | set_tsk_thread_flag(p, TIF_MEMDIE); | 434 | set_tsk_thread_flag(p, TIF_MEMDIE); |
453 | force_sig(SIGKILL, p); | 435 | force_sig(SIGKILL, p); |
454 | 436 | ||
455 | /* | ||
456 | * We give our sacrificial lamb high priority and access to | ||
457 | * all the memory it needs. That way it should be able to | ||
458 | * exit() and clear out its resources quickly... | ||
459 | */ | ||
460 | boost_dying_task_prio(p, mem); | ||
461 | |||
462 | return 0; | 437 | return 0; |
463 | } | 438 | } |
464 | #undef K | 439 | #undef K |
@@ -482,7 +457,6 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
482 | */ | 457 | */ |
483 | if (p->flags & PF_EXITING) { | 458 | if (p->flags & PF_EXITING) { |
484 | set_tsk_thread_flag(p, TIF_MEMDIE); | 459 | set_tsk_thread_flag(p, TIF_MEMDIE); |
485 | boost_dying_task_prio(p, mem); | ||
486 | return 0; | 460 | return 0; |
487 | } | 461 | } |
488 | 462 | ||
@@ -556,7 +530,6 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) | |||
556 | */ | 530 | */ |
557 | if (fatal_signal_pending(current)) { | 531 | if (fatal_signal_pending(current)) { |
558 | set_thread_flag(TIF_MEMDIE); | 532 | set_thread_flag(TIF_MEMDIE); |
559 | boost_dying_task_prio(current, NULL); | ||
560 | return; | 533 | return; |
561 | } | 534 | } |
562 | 535 | ||
@@ -712,7 +685,6 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, | |||
712 | */ | 685 | */ |
713 | if (fatal_signal_pending(current)) { | 686 | if (fatal_signal_pending(current)) { |
714 | set_thread_flag(TIF_MEMDIE); | 687 | set_thread_flag(TIF_MEMDIE); |
715 | boost_dying_task_prio(current, NULL); | ||
716 | return; | 688 | return; |
717 | } | 689 | } |
718 | 690 | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2747f5e5abc1..9f8a97b9a350 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -3176,7 +3176,7 @@ static __init_refok int __build_all_zonelists(void *data) | |||
3176 | * Called with zonelists_mutex held always | 3176 | * Called with zonelists_mutex held always |
3177 | * unless system_state == SYSTEM_BOOTING. | 3177 | * unless system_state == SYSTEM_BOOTING. |
3178 | */ | 3178 | */ |
3179 | void build_all_zonelists(void *data) | 3179 | void __ref build_all_zonelists(void *data) |
3180 | { | 3180 | { |
3181 | set_zonelist_order(); | 3181 | set_zonelist_order(); |
3182 | 3182 | ||
diff --git a/mm/shmem.c b/mm/shmem.c index 58da7c150ba6..8fa27e4e582a 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -421,7 +421,8 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long | |||
421 | * a waste to allocate index if we cannot allocate data. | 421 | * a waste to allocate index if we cannot allocate data. |
422 | */ | 422 | */ |
423 | if (sbinfo->max_blocks) { | 423 | if (sbinfo->max_blocks) { |
424 | if (percpu_counter_compare(&sbinfo->used_blocks, (sbinfo->max_blocks - 1)) > 0) | 424 | if (percpu_counter_compare(&sbinfo->used_blocks, |
425 | sbinfo->max_blocks - 1) >= 0) | ||
425 | return ERR_PTR(-ENOSPC); | 426 | return ERR_PTR(-ENOSPC); |
426 | percpu_counter_inc(&sbinfo->used_blocks); | 427 | percpu_counter_inc(&sbinfo->used_blocks); |
427 | spin_lock(&inode->i_lock); | 428 | spin_lock(&inode->i_lock); |
@@ -1397,7 +1398,8 @@ repeat: | |||
1397 | shmem_swp_unmap(entry); | 1398 | shmem_swp_unmap(entry); |
1398 | sbinfo = SHMEM_SB(inode->i_sb); | 1399 | sbinfo = SHMEM_SB(inode->i_sb); |
1399 | if (sbinfo->max_blocks) { | 1400 | if (sbinfo->max_blocks) { |
1400 | if ((percpu_counter_compare(&sbinfo->used_blocks, sbinfo->max_blocks) > 0) || | 1401 | if (percpu_counter_compare(&sbinfo->used_blocks, |
1402 | sbinfo->max_blocks) >= 0 || | ||
1401 | shmem_acct_block(info->flags)) { | 1403 | shmem_acct_block(info->flags)) { |
1402 | spin_unlock(&info->lock); | 1404 | spin_unlock(&info->lock); |
1403 | error = -ENOSPC; | 1405 | error = -ENOSPC; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index c7f5a6d4b75b..f6b435c80079 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/memcontrol.h> | 41 | #include <linux/memcontrol.h> |
42 | #include <linux/delayacct.h> | 42 | #include <linux/delayacct.h> |
43 | #include <linux/sysctl.h> | 43 | #include <linux/sysctl.h> |
44 | #include <linux/oom.h> | ||
44 | 45 | ||
45 | #include <asm/tlbflush.h> | 46 | #include <asm/tlbflush.h> |
46 | #include <asm/div64.h> | 47 | #include <asm/div64.h> |
@@ -1988,17 +1989,12 @@ static bool zone_reclaimable(struct zone *zone) | |||
1988 | return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; | 1989 | return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; |
1989 | } | 1990 | } |
1990 | 1991 | ||
1991 | /* | 1992 | /* All zones in zonelist are unreclaimable? */ |
1992 | * As hibernation is going on, kswapd is freezed so that it can't mark | ||
1993 | * the zone into all_unreclaimable. It can't handle OOM during hibernation. | ||
1994 | * So let's check zone's unreclaimable in direct reclaim as well as kswapd. | ||
1995 | */ | ||
1996 | static bool all_unreclaimable(struct zonelist *zonelist, | 1993 | static bool all_unreclaimable(struct zonelist *zonelist, |
1997 | struct scan_control *sc) | 1994 | struct scan_control *sc) |
1998 | { | 1995 | { |
1999 | struct zoneref *z; | 1996 | struct zoneref *z; |
2000 | struct zone *zone; | 1997 | struct zone *zone; |
2001 | bool all_unreclaimable = true; | ||
2002 | 1998 | ||
2003 | for_each_zone_zonelist_nodemask(zone, z, zonelist, | 1999 | for_each_zone_zonelist_nodemask(zone, z, zonelist, |
2004 | gfp_zone(sc->gfp_mask), sc->nodemask) { | 2000 | gfp_zone(sc->gfp_mask), sc->nodemask) { |
@@ -2006,13 +2002,11 @@ static bool all_unreclaimable(struct zonelist *zonelist, | |||
2006 | continue; | 2002 | continue; |
2007 | if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) | 2003 | if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) |
2008 | continue; | 2004 | continue; |
2009 | if (zone_reclaimable(zone)) { | 2005 | if (!zone->all_unreclaimable) |
2010 | all_unreclaimable = false; | 2006 | return false; |
2011 | break; | ||
2012 | } | ||
2013 | } | 2007 | } |
2014 | 2008 | ||
2015 | return all_unreclaimable; | 2009 | return true; |
2016 | } | 2010 | } |
2017 | 2011 | ||
2018 | /* | 2012 | /* |
@@ -2108,6 +2102,14 @@ out: | |||
2108 | if (sc->nr_reclaimed) | 2102 | if (sc->nr_reclaimed) |
2109 | return sc->nr_reclaimed; | 2103 | return sc->nr_reclaimed; |
2110 | 2104 | ||
2105 | /* | ||
2106 | * As hibernation is going on, kswapd is freezed so that it can't mark | ||
2107 | * the zone into all_unreclaimable. Thus bypassing all_unreclaimable | ||
2108 | * check. | ||
2109 | */ | ||
2110 | if (oom_killer_disabled) | ||
2111 | return 0; | ||
2112 | |||
2111 | /* top priority shrink_zones still had more to do? don't OOM, then */ | 2113 | /* top priority shrink_zones still had more to do? don't OOM, then */ |
2112 | if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc)) | 2114 | if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc)) |
2113 | return 1; | 2115 | return 1; |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 772b39b87d95..897ea9e88238 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -321,9 +321,12 @@ static inline void mod_state(struct zone *zone, | |||
321 | /* | 321 | /* |
322 | * The fetching of the stat_threshold is racy. We may apply | 322 | * The fetching of the stat_threshold is racy. We may apply |
323 | * a counter threshold to the wrong the cpu if we get | 323 | * a counter threshold to the wrong the cpu if we get |
324 | * rescheduled while executing here. However, the following | 324 | * rescheduled while executing here. However, the next |
325 | * will apply the threshold again and therefore bring the | 325 | * counter update will apply the threshold again and |
326 | * counter under the threshold. | 326 | * therefore bring the counter under the threshold again. |
327 | * | ||
328 | * Most of the time the thresholds are the same anyways | ||
329 | * for all cpus in a zone. | ||
327 | */ | 330 | */ |
328 | t = this_cpu_read(pcp->stat_threshold); | 331 | t = this_cpu_read(pcp->stat_threshold); |
329 | 332 | ||
@@ -945,7 +948,16 @@ static const char * const vmstat_text[] = { | |||
945 | "unevictable_pgs_cleared", | 948 | "unevictable_pgs_cleared", |
946 | "unevictable_pgs_stranded", | 949 | "unevictable_pgs_stranded", |
947 | "unevictable_pgs_mlockfreed", | 950 | "unevictable_pgs_mlockfreed", |
951 | |||
952 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
953 | "thp_fault_alloc", | ||
954 | "thp_fault_fallback", | ||
955 | "thp_collapse_alloc", | ||
956 | "thp_collapse_alloc_failed", | ||
957 | "thp_split", | ||
948 | #endif | 958 | #endif |
959 | |||
960 | #endif /* CONFIG_VM_EVENTS_COUNTERS */ | ||
949 | }; | 961 | }; |
950 | 962 | ||
951 | static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, | 963 | static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, |