Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/memory-failure: teach kill_accessing_process to accept hugetlb tail page pfn

When a hugetlb folio is being poisoned again, try_memory_failure_hugetlb()
passed head pfn to kill_accessing_process(), that is not right. The
precise pfn of the poisoned page should be used in order to determine the
precise vaddr as the SIGBUS payload.

This issue has already been taken care of in the normal path, that is,
hwpoison_user_mappings(), see [1][2]. Further more, for [3] to work
correctly in the hugetlb repoisoning case, it's essential to inform VM the
precise poisoned page, not the head page.

[1] https://lkml.kernel.org/r/20231218135837.3310403-1-willy@infradead.org
[2] https://lkml.kernel.org/r/20250224211445.2663312-1-jane.chu@oracle.com
[3] https://lore.kernel.org/lkml/20251116013223.1557158-1-jiaqiyan@google.com/

Link: https://lkml.kernel.org/r/20260120232234.3462258-2-jane.chu@oracle.com
Signed-off-by: Jane Chu <jane.chu@oracle.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
Cc: Chris Mason <clm@meta.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Jiaqi Yan <jiaqiyan@google.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: William Roche <william.roche@oracle.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Jane Chu and committed by
Andrew Morton
057a6f26 a148a204

+8 -6
+8 -6
mm/memory-failure.c
··· 692 unsigned long poisoned_pfn, struct to_kill *tk) 693 { 694 unsigned long pfn = 0; 695 696 if (pte_present(pte)) { 697 pfn = pte_pfn(pte); ··· 704 pfn = softleaf_to_pfn(entry); 705 } 706 707 - if (!pfn || pfn != poisoned_pfn) 708 return 0; 709 710 - set_to_kill(tk, addr, shift); 711 return 1; 712 } 713 ··· 2056 case MF_HUGETLB_FOLIO_PRE_POISONED: 2057 case MF_HUGETLB_PAGE_PRE_POISONED: 2058 rv = -EHWPOISON; 2059 - if (flags & MF_ACTION_REQUIRED) { 2060 - folio = page_folio(p); 2061 - rv = kill_accessing_process(current, folio_pfn(folio), flags); 2062 - } 2063 if (res == MF_HUGETLB_PAGE_PRE_POISONED) 2064 action_result(pfn, MF_MSG_ALREADY_POISONED, MF_FAILED); 2065 else
··· 692 unsigned long poisoned_pfn, struct to_kill *tk) 693 { 694 unsigned long pfn = 0; 695 + unsigned long hwpoison_vaddr; 696 + unsigned long mask; 697 698 if (pte_present(pte)) { 699 pfn = pte_pfn(pte); ··· 702 pfn = softleaf_to_pfn(entry); 703 } 704 705 + mask = ~((1UL << (shift - PAGE_SHIFT)) - 1); 706 + if (!pfn || pfn != (poisoned_pfn & mask)) 707 return 0; 708 709 + hwpoison_vaddr = addr + ((poisoned_pfn - pfn) << PAGE_SHIFT); 710 + set_to_kill(tk, hwpoison_vaddr, shift); 711 return 1; 712 } 713 ··· 2052 case MF_HUGETLB_FOLIO_PRE_POISONED: 2053 case MF_HUGETLB_PAGE_PRE_POISONED: 2054 rv = -EHWPOISON; 2055 + if (flags & MF_ACTION_REQUIRED) 2056 + rv = kill_accessing_process(current, pfn, flags); 2057 if (res == MF_HUGETLB_PAGE_PRE_POISONED) 2058 action_result(pfn, MF_MSG_ALREADY_POISONED, MF_FAILED); 2059 else