diff options
| -rw-r--r-- | mm/huge_memory.c | 7 | ||||
| -rw-r--r-- | mm/memory-failure.c | 27 |
2 files changed, 28 insertions, 6 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e187454d82f6..b6c1ce3c53b5 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
| @@ -1162,7 +1162,12 @@ static void __split_huge_page_refcount(struct page *page) | |||
| 1162 | /* after clearing PageTail the gup refcount can be released */ | 1162 | /* after clearing PageTail the gup refcount can be released */ |
| 1163 | smp_mb(); | 1163 | smp_mb(); |
| 1164 | 1164 | ||
| 1165 | page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; | 1165 | /* |
| 1166 | * retain hwpoison flag of the poisoned tail page: | ||
| 1167 | * fix for the unsuitable process killed on Guest Machine(KVM) | ||
| 1168 | * by the memory-failure. | ||
| 1169 | */ | ||
| 1170 | page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP | __PG_HWPOISON; | ||
| 1166 | page_tail->flags |= (page->flags & | 1171 | page_tail->flags |= (page->flags & |
| 1167 | ((1L << PG_referenced) | | 1172 | ((1L << PG_referenced) | |
| 1168 | (1L << PG_swapbacked) | | 1173 | (1L << PG_swapbacked) | |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 1e9c30b241c3..04158d6f44d4 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -854,6 +854,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 854 | int ret; | 854 | int ret; |
| 855 | int kill = 1; | 855 | int kill = 1; |
| 856 | struct page *hpage = compound_head(p); | 856 | struct page *hpage = compound_head(p); |
| 857 | struct page *ppage; | ||
| 857 | 858 | ||
| 858 | if (PageReserved(p) || PageSlab(p)) | 859 | if (PageReserved(p) || PageSlab(p)) |
| 859 | return SWAP_SUCCESS; | 860 | return SWAP_SUCCESS; |
| @@ -894,6 +895,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 894 | } | 895 | } |
| 895 | } | 896 | } |
| 896 | 897 | ||
| 898 | /* | ||
| 899 | * ppage: poisoned page | ||
| 900 | * if p is regular page(4k page) | ||
| 901 | * ppage == real poisoned page; | ||
| 902 | * else p is hugetlb or THP, ppage == head page. | ||
| 903 | */ | ||
| 904 | ppage = hpage; | ||
| 905 | |||
| 897 | if (PageTransHuge(hpage)) { | 906 | if (PageTransHuge(hpage)) { |
| 898 | /* | 907 | /* |
| 899 | * Verify that this isn't a hugetlbfs head page, the check for | 908 | * Verify that this isn't a hugetlbfs head page, the check for |
| @@ -919,6 +928,8 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 919 | BUG_ON(!PageHWPoison(p)); | 928 | BUG_ON(!PageHWPoison(p)); |
| 920 | return SWAP_FAIL; | 929 | return SWAP_FAIL; |
| 921 | } | 930 | } |
| 931 | /* THP is split, so ppage should be the real poisoned page. */ | ||
| 932 | ppage = p; | ||
| 922 | } | 933 | } |
| 923 | } | 934 | } |
| 924 | 935 | ||
| @@ -931,12 +942,18 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 931 | * there's nothing that can be done. | 942 | * there's nothing that can be done. |
| 932 | */ | 943 | */ |
| 933 | if (kill) | 944 | if (kill) |
| 934 | collect_procs(hpage, &tokill); | 945 | collect_procs(ppage, &tokill); |
| 935 | 946 | ||
| 936 | ret = try_to_unmap(hpage, ttu); | 947 | if (hpage != ppage) |
| 948 | lock_page_nosync(ppage); | ||
| 949 | |||
| 950 | ret = try_to_unmap(ppage, ttu); | ||
| 937 | if (ret != SWAP_SUCCESS) | 951 | if (ret != SWAP_SUCCESS) |
| 938 | printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n", | 952 | printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n", |
| 939 | pfn, page_mapcount(hpage)); | 953 | pfn, page_mapcount(ppage)); |
| 954 | |||
| 955 | if (hpage != ppage) | ||
| 956 | unlock_page(ppage); | ||
| 940 | 957 | ||
| 941 | /* | 958 | /* |
| 942 | * Now that the dirty bit has been propagated to the | 959 | * Now that the dirty bit has been propagated to the |
| @@ -947,7 +964,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 947 | * use a more force-full uncatchable kill to prevent | 964 | * use a more force-full uncatchable kill to prevent |
| 948 | * any accesses to the poisoned memory. | 965 | * any accesses to the poisoned memory. |
| 949 | */ | 966 | */ |
| 950 | kill_procs_ao(&tokill, !!PageDirty(hpage), trapno, | 967 | kill_procs_ao(&tokill, !!PageDirty(ppage), trapno, |
| 951 | ret != SWAP_SUCCESS, p, pfn); | 968 | ret != SWAP_SUCCESS, p, pfn); |
| 952 | 969 | ||
| 953 | return ret; | 970 | return ret; |
| @@ -1090,7 +1107,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
| 1090 | * For error on the tail page, we should set PG_hwpoison | 1107 | * For error on the tail page, we should set PG_hwpoison |
| 1091 | * on the head page to show that the hugepage is hwpoisoned | 1108 | * on the head page to show that the hugepage is hwpoisoned |
| 1092 | */ | 1109 | */ |
| 1093 | if (PageTail(p) && TestSetPageHWPoison(hpage)) { | 1110 | if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) { |
| 1094 | action_result(pfn, "hugepage already hardware poisoned", | 1111 | action_result(pfn, "hugepage already hardware poisoned", |
| 1095 | IGNORED); | 1112 | IGNORED); |
| 1096 | unlock_page(hpage); | 1113 | unlock_page(hpage); |
