diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/Kconfig | 4 | ||||
| -rw-r--r-- | mm/memory-failure.c | 59 | ||||
| -rw-r--r-- | mm/memory.c | 14 | ||||
| -rw-r--r-- | mm/mempolicy.c | 13 | ||||
| -rw-r--r-- | mm/page_alloc.c | 3 | ||||
| -rw-r--r-- | mm/vmscan.c | 14 |
6 files changed, 62 insertions, 45 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index 57963c6063d1..fd3386242cf0 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -67,7 +67,7 @@ config DISCONTIGMEM | |||
| 67 | 67 | ||
| 68 | config SPARSEMEM | 68 | config SPARSEMEM |
| 69 | def_bool y | 69 | def_bool y |
| 70 | depends on SPARSEMEM_MANUAL | 70 | depends on (!SELECT_MEMORY_MODEL && ARCH_SPARSEMEM_ENABLE) || SPARSEMEM_MANUAL |
| 71 | 71 | ||
| 72 | config FLATMEM | 72 | config FLATMEM |
| 73 | def_bool y | 73 | def_bool y |
| @@ -129,7 +129,7 @@ config MEMORY_HOTPLUG | |||
| 129 | bool "Allow for memory hot-add" | 129 | bool "Allow for memory hot-add" |
| 130 | depends on SPARSEMEM || X86_64_ACPI_NUMA | 130 | depends on SPARSEMEM || X86_64_ACPI_NUMA |
| 131 | depends on HOTPLUG && !(HIBERNATION && !S390) && ARCH_ENABLE_MEMORY_HOTPLUG | 131 | depends on HOTPLUG && !(HIBERNATION && !S390) && ARCH_ENABLE_MEMORY_HOTPLUG |
| 132 | depends on (IA64 || X86 || PPC64 || SUPERH || S390) | 132 | depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390) |
| 133 | 133 | ||
| 134 | comment "Memory hotplug is currently incompatible with Software Suspend" | 134 | comment "Memory hotplug is currently incompatible with Software Suspend" |
| 135 | depends on SPARSEMEM && HOTPLUG && HIBERNATION && !S390 | 135 | depends on SPARSEMEM && HOTPLUG && HIBERNATION && !S390 |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 729d4b15b645..dacc64183874 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
| 36 | #include <linux/page-flags.h> | 36 | #include <linux/page-flags.h> |
| 37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
| 38 | #include <linux/ksm.h> | ||
| 38 | #include <linux/rmap.h> | 39 | #include <linux/rmap.h> |
| 39 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
| 40 | #include <linux/swap.h> | 41 | #include <linux/swap.h> |
| @@ -370,9 +371,6 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn) | |||
| 370 | int ret = FAILED; | 371 | int ret = FAILED; |
| 371 | struct address_space *mapping; | 372 | struct address_space *mapping; |
| 372 | 373 | ||
| 373 | if (!isolate_lru_page(p)) | ||
| 374 | page_cache_release(p); | ||
| 375 | |||
| 376 | /* | 374 | /* |
| 377 | * For anonymous pages we're done the only reference left | 375 | * For anonymous pages we're done the only reference left |
| 378 | * should be the one m_f() holds. | 376 | * should be the one m_f() holds. |
| @@ -498,30 +496,18 @@ static int me_pagecache_dirty(struct page *p, unsigned long pfn) | |||
| 498 | */ | 496 | */ |
| 499 | static int me_swapcache_dirty(struct page *p, unsigned long pfn) | 497 | static int me_swapcache_dirty(struct page *p, unsigned long pfn) |
| 500 | { | 498 | { |
| 501 | int ret = FAILED; | ||
| 502 | |||
| 503 | ClearPageDirty(p); | 499 | ClearPageDirty(p); |
| 504 | /* Trigger EIO in shmem: */ | 500 | /* Trigger EIO in shmem: */ |
| 505 | ClearPageUptodate(p); | 501 | ClearPageUptodate(p); |
| 506 | 502 | ||
| 507 | if (!isolate_lru_page(p)) { | 503 | return DELAYED; |
| 508 | page_cache_release(p); | ||
| 509 | ret = DELAYED; | ||
| 510 | } | ||
| 511 | |||
| 512 | return ret; | ||
| 513 | } | 504 | } |
| 514 | 505 | ||
| 515 | static int me_swapcache_clean(struct page *p, unsigned long pfn) | 506 | static int me_swapcache_clean(struct page *p, unsigned long pfn) |
| 516 | { | 507 | { |
| 517 | int ret = FAILED; | ||
| 518 | |||
| 519 | if (!isolate_lru_page(p)) { | ||
| 520 | page_cache_release(p); | ||
| 521 | ret = RECOVERED; | ||
| 522 | } | ||
| 523 | delete_from_swap_cache(p); | 508 | delete_from_swap_cache(p); |
| 524 | return ret; | 509 | |
| 510 | return RECOVERED; | ||
| 525 | } | 511 | } |
| 526 | 512 | ||
| 527 | /* | 513 | /* |
| @@ -611,8 +597,6 @@ static struct page_state { | |||
| 611 | { 0, 0, "unknown page state", me_unknown }, | 597 | { 0, 0, "unknown page state", me_unknown }, |
| 612 | }; | 598 | }; |
| 613 | 599 | ||
| 614 | #undef lru | ||
| 615 | |||
| 616 | static void action_result(unsigned long pfn, char *msg, int result) | 600 | static void action_result(unsigned long pfn, char *msg, int result) |
| 617 | { | 601 | { |
| 618 | struct page *page = NULL; | 602 | struct page *page = NULL; |
| @@ -629,13 +613,16 @@ static int page_action(struct page_state *ps, struct page *p, | |||
| 629 | unsigned long pfn, int ref) | 613 | unsigned long pfn, int ref) |
| 630 | { | 614 | { |
| 631 | int result; | 615 | int result; |
| 616 | int count; | ||
| 632 | 617 | ||
| 633 | result = ps->action(p, pfn); | 618 | result = ps->action(p, pfn); |
| 634 | action_result(pfn, ps->msg, result); | 619 | action_result(pfn, ps->msg, result); |
| 635 | if (page_count(p) != 1 + ref) | 620 | |
| 621 | count = page_count(p) - 1 - ref; | ||
| 622 | if (count != 0) | ||
| 636 | printk(KERN_ERR | 623 | printk(KERN_ERR |
| 637 | "MCE %#lx: %s page still referenced by %d users\n", | 624 | "MCE %#lx: %s page still referenced by %d users\n", |
| 638 | pfn, ps->msg, page_count(p) - 1); | 625 | pfn, ps->msg, count); |
| 639 | 626 | ||
| 640 | /* Could do more checks here if page looks ok */ | 627 | /* Could do more checks here if page looks ok */ |
| 641 | /* | 628 | /* |
| @@ -661,12 +648,9 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 661 | int i; | 648 | int i; |
| 662 | int kill = 1; | 649 | int kill = 1; |
| 663 | 650 | ||
| 664 | if (PageReserved(p) || PageCompound(p) || PageSlab(p)) | 651 | if (PageReserved(p) || PageCompound(p) || PageSlab(p) || PageKsm(p)) |
| 665 | return; | 652 | return; |
| 666 | 653 | ||
| 667 | if (!PageLRU(p)) | ||
| 668 | lru_add_drain_all(); | ||
| 669 | |||
| 670 | /* | 654 | /* |
| 671 | * This check implies we don't kill processes if their pages | 655 | * This check implies we don't kill processes if their pages |
| 672 | * are in the swap cache early. Those are always late kills. | 656 | * are in the swap cache early. Those are always late kills. |
| @@ -738,6 +722,7 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 738 | 722 | ||
| 739 | int __memory_failure(unsigned long pfn, int trapno, int ref) | 723 | int __memory_failure(unsigned long pfn, int trapno, int ref) |
| 740 | { | 724 | { |
| 725 | unsigned long lru_flag; | ||
| 741 | struct page_state *ps; | 726 | struct page_state *ps; |
| 742 | struct page *p; | 727 | struct page *p; |
| 743 | int res; | 728 | int res; |
| @@ -775,6 +760,24 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 775 | } | 760 | } |
| 776 | 761 | ||
| 777 | /* | 762 | /* |
| 763 | * We ignore non-LRU pages for good reasons. | ||
| 764 | * - PG_locked is only well defined for LRU pages and a few others | ||
| 765 | * - to avoid races with __set_page_locked() | ||
| 766 | * - to avoid races with __SetPageSlab*() (and more non-atomic ops) | ||
| 767 | * The check (unnecessarily) ignores LRU pages being isolated and | ||
| 768 | * walked by the page reclaim code, however that's not a big loss. | ||
| 769 | */ | ||
| 770 | if (!PageLRU(p)) | ||
| 771 | lru_add_drain_all(); | ||
| 772 | lru_flag = p->flags & lru; | ||
| 773 | if (isolate_lru_page(p)) { | ||
| 774 | action_result(pfn, "non LRU", IGNORED); | ||
| 775 | put_page(p); | ||
| 776 | return -EBUSY; | ||
| 777 | } | ||
| 778 | page_cache_release(p); | ||
| 779 | |||
| 780 | /* | ||
| 778 | * Lock the page and wait for writeback to finish. | 781 | * Lock the page and wait for writeback to finish. |
| 779 | * It's very difficult to mess with pages currently under IO | 782 | * It's very difficult to mess with pages currently under IO |
| 780 | * and in many cases impossible, so we just avoid it here. | 783 | * and in many cases impossible, so we just avoid it here. |
| @@ -790,7 +793,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 790 | /* | 793 | /* |
| 791 | * Torn down by someone else? | 794 | * Torn down by someone else? |
| 792 | */ | 795 | */ |
| 793 | if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) { | 796 | if ((lru_flag & lru) && !PageSwapCache(p) && p->mapping == NULL) { |
| 794 | action_result(pfn, "already truncated LRU", IGNORED); | 797 | action_result(pfn, "already truncated LRU", IGNORED); |
| 795 | res = 0; | 798 | res = 0; |
| 796 | goto out; | 799 | goto out; |
| @@ -798,7 +801,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 798 | 801 | ||
| 799 | res = -EBUSY; | 802 | res = -EBUSY; |
| 800 | for (ps = error_states;; ps++) { | 803 | for (ps = error_states;; ps++) { |
| 801 | if ((p->flags & ps->mask) == ps->res) { | 804 | if (((p->flags | lru_flag)& ps->mask) == ps->res) { |
| 802 | res = page_action(ps, p, pfn, ref); | 805 | res = page_action(ps, p, pfn, ref); |
| 803 | break; | 806 | break; |
| 804 | } | 807 | } |
diff --git a/mm/memory.c b/mm/memory.c index 7e91b5f9f690..6ab19dd4a199 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -641,6 +641,7 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 641 | pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma, | 641 | pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma, |
| 642 | unsigned long addr, unsigned long end) | 642 | unsigned long addr, unsigned long end) |
| 643 | { | 643 | { |
| 644 | pte_t *orig_src_pte, *orig_dst_pte; | ||
| 644 | pte_t *src_pte, *dst_pte; | 645 | pte_t *src_pte, *dst_pte; |
| 645 | spinlock_t *src_ptl, *dst_ptl; | 646 | spinlock_t *src_ptl, *dst_ptl; |
| 646 | int progress = 0; | 647 | int progress = 0; |
| @@ -654,6 +655,8 @@ again: | |||
| 654 | src_pte = pte_offset_map_nested(src_pmd, addr); | 655 | src_pte = pte_offset_map_nested(src_pmd, addr); |
| 655 | src_ptl = pte_lockptr(src_mm, src_pmd); | 656 | src_ptl = pte_lockptr(src_mm, src_pmd); |
| 656 | spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); | 657 | spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); |
| 658 | orig_src_pte = src_pte; | ||
| 659 | orig_dst_pte = dst_pte; | ||
| 657 | arch_enter_lazy_mmu_mode(); | 660 | arch_enter_lazy_mmu_mode(); |
| 658 | 661 | ||
| 659 | do { | 662 | do { |
| @@ -677,9 +680,9 @@ again: | |||
| 677 | 680 | ||
| 678 | arch_leave_lazy_mmu_mode(); | 681 | arch_leave_lazy_mmu_mode(); |
| 679 | spin_unlock(src_ptl); | 682 | spin_unlock(src_ptl); |
| 680 | pte_unmap_nested(src_pte - 1); | 683 | pte_unmap_nested(orig_src_pte); |
| 681 | add_mm_rss(dst_mm, rss[0], rss[1]); | 684 | add_mm_rss(dst_mm, rss[0], rss[1]); |
| 682 | pte_unmap_unlock(dst_pte - 1, dst_ptl); | 685 | pte_unmap_unlock(orig_dst_pte, dst_ptl); |
| 683 | cond_resched(); | 686 | cond_resched(); |
| 684 | if (addr != end) | 687 | if (addr != end) |
| 685 | goto again; | 688 | goto again; |
| @@ -1820,10 +1823,10 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
| 1820 | token = pmd_pgtable(*pmd); | 1823 | token = pmd_pgtable(*pmd); |
| 1821 | 1824 | ||
| 1822 | do { | 1825 | do { |
| 1823 | err = fn(pte, token, addr, data); | 1826 | err = fn(pte++, token, addr, data); |
| 1824 | if (err) | 1827 | if (err) |
| 1825 | break; | 1828 | break; |
| 1826 | } while (pte++, addr += PAGE_SIZE, addr != end); | 1829 | } while (addr += PAGE_SIZE, addr != end); |
| 1827 | 1830 | ||
| 1828 | arch_leave_lazy_mmu_mode(); | 1831 | arch_leave_lazy_mmu_mode(); |
| 1829 | 1832 | ||
| @@ -2539,7 +2542,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2539 | } else if (PageHWPoison(page)) { | 2542 | } else if (PageHWPoison(page)) { |
| 2540 | ret = VM_FAULT_HWPOISON; | 2543 | ret = VM_FAULT_HWPOISON; |
| 2541 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 2544 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
| 2542 | goto out; | 2545 | goto out_release; |
| 2543 | } | 2546 | } |
| 2544 | 2547 | ||
| 2545 | lock_page(page); | 2548 | lock_page(page); |
| @@ -2611,6 +2614,7 @@ out_nomap: | |||
| 2611 | pte_unmap_unlock(page_table, ptl); | 2614 | pte_unmap_unlock(page_table, ptl); |
| 2612 | out_page: | 2615 | out_page: |
| 2613 | unlock_page(page); | 2616 | unlock_page(page); |
| 2617 | out_release: | ||
| 2614 | page_cache_release(page); | 2618 | page_cache_release(page); |
| 2615 | return ret; | 2619 | return ret; |
| 2616 | } | 2620 | } |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 7dd9d9f80694..4545d5944243 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
| @@ -1024,7 +1024,7 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
| 1024 | 1024 | ||
| 1025 | err = migrate_prep(); | 1025 | err = migrate_prep(); |
| 1026 | if (err) | 1026 | if (err) |
| 1027 | return err; | 1027 | goto mpol_out; |
| 1028 | } | 1028 | } |
| 1029 | { | 1029 | { |
| 1030 | NODEMASK_SCRATCH(scratch); | 1030 | NODEMASK_SCRATCH(scratch); |
| @@ -1039,10 +1039,9 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
| 1039 | err = -ENOMEM; | 1039 | err = -ENOMEM; |
| 1040 | NODEMASK_SCRATCH_FREE(scratch); | 1040 | NODEMASK_SCRATCH_FREE(scratch); |
| 1041 | } | 1041 | } |
| 1042 | if (err) { | 1042 | if (err) |
| 1043 | mpol_put(new); | 1043 | goto mpol_out; |
| 1044 | return err; | 1044 | |
| 1045 | } | ||
| 1046 | vma = check_range(mm, start, end, nmask, | 1045 | vma = check_range(mm, start, end, nmask, |
| 1047 | flags | MPOL_MF_INVERT, &pagelist); | 1046 | flags | MPOL_MF_INVERT, &pagelist); |
| 1048 | 1047 | ||
| @@ -1058,9 +1057,11 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
| 1058 | 1057 | ||
| 1059 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) | 1058 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) |
| 1060 | err = -EIO; | 1059 | err = -EIO; |
| 1061 | } | 1060 | } else |
| 1061 | putback_lru_pages(&pagelist); | ||
| 1062 | 1062 | ||
| 1063 | up_write(&mm->mmap_sem); | 1063 | up_write(&mm->mmap_sem); |
| 1064 | mpol_out: | ||
| 1064 | mpol_put(new); | 1065 | mpol_put(new); |
| 1065 | return err; | 1066 | return err; |
| 1066 | } | 1067 | } |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bf720550b44d..cdcedf661616 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -2183,7 +2183,7 @@ void show_free_areas(void) | |||
| 2183 | printk("active_anon:%lu inactive_anon:%lu isolated_anon:%lu\n" | 2183 | printk("active_anon:%lu inactive_anon:%lu isolated_anon:%lu\n" |
| 2184 | " active_file:%lu inactive_file:%lu isolated_file:%lu\n" | 2184 | " active_file:%lu inactive_file:%lu isolated_file:%lu\n" |
| 2185 | " unevictable:%lu" | 2185 | " unevictable:%lu" |
| 2186 | " dirty:%lu writeback:%lu unstable:%lu buffer:%lu\n" | 2186 | " dirty:%lu writeback:%lu unstable:%lu\n" |
| 2187 | " free:%lu slab_reclaimable:%lu slab_unreclaimable:%lu\n" | 2187 | " free:%lu slab_reclaimable:%lu slab_unreclaimable:%lu\n" |
| 2188 | " mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n", | 2188 | " mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n", |
| 2189 | global_page_state(NR_ACTIVE_ANON), | 2189 | global_page_state(NR_ACTIVE_ANON), |
| @@ -2196,7 +2196,6 @@ void show_free_areas(void) | |||
| 2196 | global_page_state(NR_FILE_DIRTY), | 2196 | global_page_state(NR_FILE_DIRTY), |
| 2197 | global_page_state(NR_WRITEBACK), | 2197 | global_page_state(NR_WRITEBACK), |
| 2198 | global_page_state(NR_UNSTABLE_NFS), | 2198 | global_page_state(NR_UNSTABLE_NFS), |
| 2199 | nr_blockdev_pages(), | ||
| 2200 | global_page_state(NR_FREE_PAGES), | 2199 | global_page_state(NR_FREE_PAGES), |
| 2201 | global_page_state(NR_SLAB_RECLAIMABLE), | 2200 | global_page_state(NR_SLAB_RECLAIMABLE), |
| 2202 | global_page_state(NR_SLAB_UNRECLAIMABLE), | 2201 | global_page_state(NR_SLAB_UNRECLAIMABLE), |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 64e438898832..777af57fd8c8 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -544,6 +544,16 @@ redo: | |||
| 544 | */ | 544 | */ |
| 545 | lru = LRU_UNEVICTABLE; | 545 | lru = LRU_UNEVICTABLE; |
| 546 | add_page_to_unevictable_list(page); | 546 | add_page_to_unevictable_list(page); |
| 547 | /* | ||
| 548 | * When racing with an mlock clearing (page is | ||
| 549 | * unlocked), make sure that if the other thread does | ||
| 550 | * not observe our setting of PG_lru and fails | ||
| 551 | * isolation, we see PG_mlocked cleared below and move | ||
| 552 | * the page back to the evictable list. | ||
| 553 | * | ||
| 554 | * The other side is TestClearPageMlocked(). | ||
| 555 | */ | ||
| 556 | smp_mb(); | ||
| 547 | } | 557 | } |
| 548 | 558 | ||
| 549 | /* | 559 | /* |
| @@ -1088,7 +1098,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
| 1088 | int lumpy_reclaim = 0; | 1098 | int lumpy_reclaim = 0; |
| 1089 | 1099 | ||
| 1090 | while (unlikely(too_many_isolated(zone, file, sc))) { | 1100 | while (unlikely(too_many_isolated(zone, file, sc))) { |
| 1091 | congestion_wait(WRITE, HZ/10); | 1101 | congestion_wait(BLK_RW_ASYNC, HZ/10); |
| 1092 | 1102 | ||
| 1093 | /* We are about to die and free our memory. Return now. */ | 1103 | /* We are about to die and free our memory. Return now. */ |
| 1094 | if (fatal_signal_pending(current)) | 1104 | if (fatal_signal_pending(current)) |
| @@ -1356,7 +1366,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
| 1356 | * IO, plus JVM can create lots of anon VM_EXEC pages, | 1366 | * IO, plus JVM can create lots of anon VM_EXEC pages, |
| 1357 | * so we ignore them here. | 1367 | * so we ignore them here. |
| 1358 | */ | 1368 | */ |
| 1359 | if ((vm_flags & VM_EXEC) && !PageAnon(page)) { | 1369 | if ((vm_flags & VM_EXEC) && page_is_file_cache(page)) { |
| 1360 | list_add(&page->lru, &l_active); | 1370 | list_add(&page->lru, &l_active); |
| 1361 | continue; | 1371 | continue; |
| 1362 | } | 1372 | } |
