aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/memory-failure.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 7e3601ce51c6..3b4120e38d48 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -854,14 +854,14 @@ static int page_action(struct page_state *ps, struct page *p,
854 * the pages and send SIGBUS to the processes if the data was dirty. 854 * the pages and send SIGBUS to the processes if the data was dirty.
855 */ 855 */
856static int hwpoison_user_mappings(struct page *p, unsigned long pfn, 856static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
857 int trapno, int flags) 857 int trapno, int flags, struct page **hpagep)
858{ 858{
859 enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS; 859 enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
860 struct address_space *mapping; 860 struct address_space *mapping;
861 LIST_HEAD(tokill); 861 LIST_HEAD(tokill);
862 int ret; 862 int ret;
863 int kill = 1, forcekill; 863 int kill = 1, forcekill;
864 struct page *hpage = compound_head(p); 864 struct page *hpage = *hpagep;
865 struct page *ppage; 865 struct page *ppage;
866 866
867 if (PageReserved(p) || PageSlab(p)) 867 if (PageReserved(p) || PageSlab(p))
@@ -940,11 +940,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
940 * We pinned the head page for hwpoison handling, 940 * We pinned the head page for hwpoison handling,
941 * now we split the thp and we are interested in 941 * now we split the thp and we are interested in
942 * the hwpoisoned raw page, so move the refcount 942 * the hwpoisoned raw page, so move the refcount
943 * to it. 943 * to it. Similarly, page lock is shifted.
944 */ 944 */
945 if (hpage != p) { 945 if (hpage != p) {
946 put_page(hpage); 946 put_page(hpage);
947 get_page(p); 947 get_page(p);
948 lock_page(p);
949 unlock_page(hpage);
950 *hpagep = p;
948 } 951 }
949 /* THP is split, so ppage should be the real poisoned page. */ 952 /* THP is split, so ppage should be the real poisoned page. */
950 ppage = p; 953 ppage = p;
@@ -962,17 +965,11 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
962 if (kill) 965 if (kill)
963 collect_procs(ppage, &tokill); 966 collect_procs(ppage, &tokill);
964 967
965 if (hpage != ppage)
966 lock_page(ppage);
967
968 ret = try_to_unmap(ppage, ttu); 968 ret = try_to_unmap(ppage, ttu);
969 if (ret != SWAP_SUCCESS) 969 if (ret != SWAP_SUCCESS)
970 printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n", 970 printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n",
971 pfn, page_mapcount(ppage)); 971 pfn, page_mapcount(ppage));
972 972
973 if (hpage != ppage)
974 unlock_page(ppage);
975
976 /* 973 /*
977 * Now that the dirty bit has been propagated to the 974 * Now that the dirty bit has been propagated to the
978 * struct page and all unmaps done we can decide if 975 * struct page and all unmaps done we can decide if
@@ -1189,8 +1186,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1189 /* 1186 /*
1190 * Now take care of user space mappings. 1187 * Now take care of user space mappings.
1191 * Abort on fail: __delete_from_page_cache() assumes unmapped page. 1188 * Abort on fail: __delete_from_page_cache() assumes unmapped page.
1189 *
1190 * When the raw error page is thp tail page, hpage points to the raw
1191 * page after thp split.
1192 */ 1192 */
1193 if (hwpoison_user_mappings(p, pfn, trapno, flags) != SWAP_SUCCESS) { 1193 if (hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)
1194 != SWAP_SUCCESS) {
1194 printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn); 1195 printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn);
1195 res = -EBUSY; 1196 res = -EBUSY;
1196 goto out; 1197 goto out;