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