Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b985194c authored by Chen Yucong's avatar Chen Yucong Committed by Linus Torvalds
Browse files

hwpoison, hugetlb: lock_page/unlock_page does not match for handling a free hugepage



For handling a free hugepage in memory failure, the race will happen if
another thread hwpoisoned this hugepage concurrently.  So we need to
check PageHWPoison instead of !PageHWPoison.

If hwpoison_filter(p) returns true or a race happens, then we need to
unlock_page(hpage).

Signed-off-by: default avatarChen Yucong <slaoub@gmail.com>
Reviewed-by: default avatarNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Tested-by: default avatarNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Reviewed-by: default avatarAndi Kleen <ak@linux.intel.com>
Cc: <stable@vger.kernel.org>	[2.6.36+]
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4b660a7f
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -1081,16 +1081,17 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
			return 0;
		} else if (PageHuge(hpage)) {
			/*
			 * Check "just unpoisoned", "filter hit", and
			 * "race with other subpage."
			 * Check "filter hit" and "race with other subpage."
			 */
			lock_page(hpage);
			if (!PageHWPoison(hpage)
			    || (hwpoison_filter(p) && TestClearPageHWPoison(p))
			if (PageHWPoison(hpage)) {
				if ((hwpoison_filter(p) && TestClearPageHWPoison(p))
				    || (p != hpage && TestSetPageHWPoison(hpage))) {
					atomic_long_sub(nr_pages, &num_poisoned_pages);
					unlock_page(hpage);
					return 0;
				}
			}
			set_page_hwpoison_huge_page(hpage);
			res = dequeue_hwpoisoned_huge_page(hpage);
			action_result(pfn, "free huge",