diff options
author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2016-11-10 13:46:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-11 11:12:37 -0500 |
commit | c3901e722b2975666f42748340df798114742d6d (patch) | |
tree | 9cd4508bd975e35b393982f3c61101c98c90dee6 | |
parent | dd111be69114cc867f8e826284559bfbc1c40e37 (diff) |
mm: hwpoison: fix thp split handling in memory_failure()
When memory_failure() runs on a thp tail page after pmd is split, we
trigger the following VM_BUG_ON_PAGE():
page:ffffd7cd819b0040 count:0 mapcount:0 mapping: (null) index:0x1
flags: 0x1fffc000400000(hwpoison)
page dumped because: VM_BUG_ON_PAGE(!page_count(p))
------------[ cut here ]------------
kernel BUG at /src/linux-dev/mm/memory-failure.c:1132!
memory_failure() passed refcount and page lock from tail page to head
page, which is not needed because we can pass any subpage to
split_huge_page().
Fixes: 61f5d698cc97 ("mm: re-enable THP")
Link: http://lkml.kernel.org/r/1477961577-7183-1-git-send-email-n-horiguchi@ah.jp.nec.com
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: <stable@vger.kernel.org> [4.5+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/memory-failure.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index de88f33519c0..19e796d36a62 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -1112,10 +1112,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | if (!PageHuge(p) && PageTransHuge(hpage)) { | 1114 | if (!PageHuge(p) && PageTransHuge(hpage)) { |
1115 | lock_page(hpage); | 1115 | lock_page(p); |
1116 | if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) { | 1116 | if (!PageAnon(p) || unlikely(split_huge_page(p))) { |
1117 | unlock_page(hpage); | 1117 | unlock_page(p); |
1118 | if (!PageAnon(hpage)) | 1118 | if (!PageAnon(p)) |
1119 | pr_err("Memory failure: %#lx: non anonymous thp\n", | 1119 | pr_err("Memory failure: %#lx: non anonymous thp\n", |
1120 | pfn); | 1120 | pfn); |
1121 | else | 1121 | else |
@@ -1126,9 +1126,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) | |||
1126 | put_hwpoison_page(p); | 1126 | put_hwpoison_page(p); |
1127 | return -EBUSY; | 1127 | return -EBUSY; |
1128 | } | 1128 | } |
1129 | unlock_page(hpage); | 1129 | unlock_page(p); |
1130 | get_hwpoison_page(p); | ||
1131 | put_hwpoison_page(hpage); | ||
1132 | VM_BUG_ON_PAGE(!page_count(p), p); | 1130 | VM_BUG_ON_PAGE(!page_count(p), p); |
1133 | hpage = compound_head(p); | 1131 | hpage = compound_head(p); |
1134 | } | 1132 | } |