| From: Miaohe Lin <linmiaohe@huawei.com> |
| Subject: mm/memory-failure.c: fix race with changing page compound again |
| |
| Patch series "A few fixup patches for memory failure", v2. |
| |
| This series contains a few patches to fix the race with changing page |
| compound page, make non-LRU movable pages unhandlable and so on. More |
| details can be found in the respective changelogs. |
| |
| |
| There is a race window where we got the compound_head, the hugetlb page |
| could be freed to buddy, or even changed to another compound page just |
| before we try to get hwpoison page. Think about the below race window: |
| |
| CPU 1 CPU 2 |
| memory_failure_hugetlb |
| struct page *head = compound_head(p); |
| hugetlb page might be freed to |
| buddy, or even changed to another |
| compound page. |
| |
| get_hwpoison_page -- page is not what we want now... |
| |
| If this race happens, just bail out. Also MF_MSG_DIFFERENT_PAGE_SIZE is |
| introduced to record this event. |
| |
| [akpm@linux-foundation.org: s@/**@/*@, per Naoya Horiguchi] |
| Link: https://lkml.kernel.org/r/20220312074613.4798-1-linmiaohe@huawei.com |
| Link: https://lkml.kernel.org/r/20220312074613.4798-2-linmiaohe@huawei.com |
| Signed-off-by: Miaohe Lin <linmiaohe@huawei.com> |
| Acked-by: Naoya Horiguchi <naoya.horiguchi@nec.com> |
| Cc: Tony Luck <tony.luck@intel.com> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Mike Kravetz <mike.kravetz@oracle.com> |
| Cc: Yang Shi <shy828301@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| include/linux/mm.h | 1 + |
| include/ras/ras_event.h | 1 + |
| mm/memory-failure.c | 12 ++++++++++++ |
| 3 files changed, 14 insertions(+) |
| |
| --- a/include/linux/mm.h~mm-memory-failurec-fix-race-with-changing-page-compound-again |
| +++ a/include/linux/mm.h |
| @@ -3239,6 +3239,7 @@ enum mf_action_page_type { |
| MF_MSG_BUDDY, |
| MF_MSG_DAX, |
| MF_MSG_UNSPLIT_THP, |
| + MF_MSG_DIFFERENT_PAGE_SIZE, |
| MF_MSG_UNKNOWN, |
| }; |
| |
| --- a/include/ras/ras_event.h~mm-memory-failurec-fix-race-with-changing-page-compound-again |
| +++ a/include/ras/ras_event.h |
| @@ -374,6 +374,7 @@ TRACE_EVENT(aer_event, |
| EM ( MF_MSG_BUDDY, "free buddy page" ) \ |
| EM ( MF_MSG_DAX, "dax page" ) \ |
| EM ( MF_MSG_UNSPLIT_THP, "unsplit thp" ) \ |
| + EM ( MF_MSG_DIFFERENT_PAGE_SIZE, "different page size" ) \ |
| EMe ( MF_MSG_UNKNOWN, "unknown page" ) |
| |
| /* |
| --- a/mm/memory-failure.c~mm-memory-failurec-fix-race-with-changing-page-compound-again |
| +++ a/mm/memory-failure.c |
| @@ -732,6 +732,7 @@ static const char * const action_page_ty |
| [MF_MSG_BUDDY] = "free buddy page", |
| [MF_MSG_DAX] = "dax page", |
| [MF_MSG_UNSPLIT_THP] = "unsplit thp", |
| + [MF_MSG_DIFFERENT_PAGE_SIZE] = "different page size", |
| [MF_MSG_UNKNOWN] = "unknown page", |
| }; |
| |
| @@ -1532,6 +1533,17 @@ static int memory_failure_hugetlb(unsign |
| } |
| |
| lock_page(head); |
| + |
| + /* |
| + * The page could have changed compound pages due to race window. |
| + * If this happens just bail out. |
| + */ |
| + if (!PageHuge(p) || compound_head(p) != head) { |
| + action_result(pfn, MF_MSG_DIFFERENT_PAGE_SIZE, MF_IGNORED); |
| + res = -EBUSY; |
| + goto out; |
| + } |
| + |
| page_flags = head->flags; |
| |
| if (hwpoison_filter(p)) { |
| _ |