Skip to content

Commit b79f8eb

Browse files
Jiaqi Yanakpm00
authored andcommitted
mm/hwpoison: check if a raw page in a hugetlb folio is raw HWPOISON
Add the functionality, is_raw_hwpoison_page_in_hugepage, to tell if a raw page in a hugetlb folio is HWPOISON. This functionality relies on RawHwpUnreliable to be not set; otherwise hugepage's raw HWPOISON list becomes meaningless. is_raw_hwpoison_page_in_hugepage holds mf_mutex in order to synchronize with folio_set_hugetlb_hwpoison and folio_free_raw_hwp who iterate, insert, or delete entry in raw_hwp_list. llist itself doesn't ensure insertion and removal are synchornized with the llist_for_each_entry used by is_raw_hwpoison_page_in_hugepage (unless iterated entries are already deleted from the list). Caller can minimize the overhead of lock cycles by first checking HWPOISON flag of the folio. Exports this functionality to be immediately used in the read operation for hugetlbfs. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Jiaqi Yan <[email protected]> Reviewed-by: Mike Kravetz <[email protected]> Reviewed-by: Naoya Horiguchi <[email protected]> Reviewed-by: Miaohe Lin <[email protected]> Cc: James Houghton <[email protected]> Cc: Muchun Song <[email protected]> Cc: Yang Shi <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 9e130c4 commit b79f8eb

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

include/linux/hugetlb.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,11 @@ void hugetlb_register_node(struct node *node);
997997
void hugetlb_unregister_node(struct node *node);
998998
#endif
999999

1000+
/*
1001+
* Check if a given raw @page in a hugepage is HWPOISON.
1002+
*/
1003+
bool is_raw_hwpoison_page_in_hugepage(struct page *page);
1004+
10001005
#else /* CONFIG_HUGETLB_PAGE */
10011006
struct hstate {};
10021007

mm/memory-failure.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ atomic_long_t num_poisoned_pages __read_mostly = ATOMIC_LONG_INIT(0);
7272

7373
static bool hw_memory_failure __read_mostly = false;
7474

75+
static DEFINE_MUTEX(mf_mutex);
76+
7577
void num_poisoned_pages_inc(unsigned long pfn)
7678
{
7779
atomic_long_inc(&num_poisoned_pages);
@@ -1814,6 +1816,7 @@ EXPORT_SYMBOL_GPL(mf_dax_kill_procs);
18141816
#endif /* CONFIG_FS_DAX */
18151817

18161818
#ifdef CONFIG_HUGETLB_PAGE
1819+
18171820
/*
18181821
* Struct raw_hwp_page represents information about "raw error page",
18191822
* constructing singly linked list from ->_hugetlb_hwpoison field of folio.
@@ -1828,6 +1831,41 @@ static inline struct llist_head *raw_hwp_list_head(struct folio *folio)
18281831
return (struct llist_head *)&folio->_hugetlb_hwpoison;
18291832
}
18301833

1834+
bool is_raw_hwpoison_page_in_hugepage(struct page *page)
1835+
{
1836+
struct llist_head *raw_hwp_head;
1837+
struct raw_hwp_page *p;
1838+
struct folio *folio = page_folio(page);
1839+
bool ret = false;
1840+
1841+
if (!folio_test_hwpoison(folio))
1842+
return false;
1843+
1844+
if (!folio_test_hugetlb(folio))
1845+
return PageHWPoison(page);
1846+
1847+
/*
1848+
* When RawHwpUnreliable is set, kernel lost track of which subpages
1849+
* are HWPOISON. So return as if ALL subpages are HWPOISONed.
1850+
*/
1851+
if (folio_test_hugetlb_raw_hwp_unreliable(folio))
1852+
return true;
1853+
1854+
mutex_lock(&mf_mutex);
1855+
1856+
raw_hwp_head = raw_hwp_list_head(folio);
1857+
llist_for_each_entry(p, raw_hwp_head->first, node) {
1858+
if (page == p->page) {
1859+
ret = true;
1860+
break;
1861+
}
1862+
}
1863+
1864+
mutex_unlock(&mf_mutex);
1865+
1866+
return ret;
1867+
}
1868+
18311869
static unsigned long __folio_free_raw_hwp(struct folio *folio, bool move_flag)
18321870
{
18331871
struct llist_node *t, *tnode, *head;
@@ -2110,8 +2148,6 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
21102148
return rc;
21112149
}
21122150

2113-
static DEFINE_MUTEX(mf_mutex);
2114-
21152151
/**
21162152
* memory_failure - Handle memory failure of a page.
21172153
* @pfn: Page Number of the corrupted page

0 commit comments

Comments
 (0)