Skip to content

Commit 6da6b1d

Browse files
nhoriguchiakpm00
authored andcommitted
mm/hwpoison: convert TTU_IGNORE_HWPOISON to TTU_HWPOISON
After a memory error happens on a clean folio, a process unexpectedly receives SIGBUS when it accesses the error page. This SIGBUS killing is pointless and simply degrades the level of RAS of the system, because the clean folio can be dropped without any data lost on memory error handling as we do for a clean pagecache. When memory_failure() is called on a clean folio, try_to_unmap() is called twice (one from split_huge_page() and one from hwpoison_user_mappings()). The root cause of the issue is that pte conversion to hwpoisoned entry is now done in the first call of try_to_unmap() because PageHWPoison is already set at this point, while it's actually expected to be done in the second call. This behavior disturbs the error handling operation like removing pagecache, which results in the malfunction described above. So convert TTU_IGNORE_HWPOISON into TTU_HWPOISON and set TTU_HWPOISON only when we really intend to convert pte to hwpoison entry. This can prevent other callers of try_to_unmap() from accidentally converting to hwpoison entries. Link: https://lkml.kernel.org/r/[email protected] Fixes: a42634a ("readahead: Use a folio in read_pages()") Signed-off-by: Naoya Horiguchi <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Miaohe Lin <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 1c0a0af commit 6da6b1d

File tree

3 files changed

+6
-6
lines changed

3 files changed

+6
-6
lines changed

include/linux/rmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ enum ttu_flags {
9494
TTU_SPLIT_HUGE_PMD = 0x4, /* split huge PMD if any */
9595
TTU_IGNORE_MLOCK = 0x8, /* ignore mlock */
9696
TTU_SYNC = 0x10, /* avoid racy checks with PVMW_SYNC */
97-
TTU_IGNORE_HWPOISON = 0x20, /* corrupted page is recoverable */
97+
TTU_HWPOISON = 0x20, /* do convert pte to hwpoison entry */
9898
TTU_BATCH_FLUSH = 0x40, /* Batch TLB flushes where possible
9999
* and caller guarantees they will
100100
* do a final flush if necessary */

mm/memory-failure.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ static int me_pagecache_dirty(struct page_state *ps, struct page *p)
10691069
* cache and swap cache(ie. page is freshly swapped in). So it could be
10701070
* referenced concurrently by 2 types of PTEs:
10711071
* normal PTEs and swap PTEs. We try to handle them consistently by calling
1072-
* try_to_unmap(TTU_IGNORE_HWPOISON) to convert the normal PTEs to swap PTEs,
1072+
* try_to_unmap(!TTU_HWPOISON) to convert the normal PTEs to swap PTEs,
10731073
* and then
10741074
* - clear dirty bit to prevent IO
10751075
* - remove from LRU
@@ -1486,7 +1486,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
14861486
int flags, struct page *hpage)
14871487
{
14881488
struct folio *folio = page_folio(hpage);
1489-
enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC;
1489+
enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_HWPOISON;
14901490
struct address_space *mapping;
14911491
LIST_HEAD(tokill);
14921492
bool unmap_success;
@@ -1516,7 +1516,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
15161516

15171517
if (PageSwapCache(p)) {
15181518
pr_err("%#lx: keeping poisoned page in swap cache\n", pfn);
1519-
ttu |= TTU_IGNORE_HWPOISON;
1519+
ttu &= ~TTU_HWPOISON;
15201520
}
15211521

15221522
/*
@@ -1531,7 +1531,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
15311531
if (page_mkclean(hpage)) {
15321532
SetPageDirty(hpage);
15331533
} else {
1534-
ttu |= TTU_IGNORE_HWPOISON;
1534+
ttu &= ~TTU_HWPOISON;
15351535
pr_info("%#lx: corrupted page was clean: dropped without side effects\n",
15361536
pfn);
15371537
}

mm/rmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
16021602
/* Update high watermark before we lower rss */
16031603
update_hiwater_rss(mm);
16041604

1605-
if (PageHWPoison(subpage) && !(flags & TTU_IGNORE_HWPOISON)) {
1605+
if (PageHWPoison(subpage) && (flags & TTU_HWPOISON)) {
16061606
pteval = swp_entry_to_pte(make_hwpoison_entry(subpage));
16071607
if (folio_test_hugetlb(folio)) {
16081608
hugetlb_count_sub(folio_nr_pages(folio), mm);

0 commit comments

Comments
 (0)