Naoya Horiguchi 25182f05ff mm,hwpoison: fix race with hugetlb page allocation
When hugetlb page fault (under overcommitting situation) and
memory_failure() race, VM_BUG_ON_PAGE() is triggered by the following
race:

    CPU0:                           CPU1:

                                    gather_surplus_pages()
                                      page = alloc_surplus_huge_page()
    memory_failure_hugetlb()
      get_hwpoison_page(page)
        __get_hwpoison_page(page)
          get_page_unless_zero(page)
                                      zero = put_page_testzero(page)
                                      VM_BUG_ON_PAGE(!zero, page)
                                      enqueue_huge_page(h, page)
      put_page(page)

__get_hwpoison_page() only checks the page refcount before taking an
additional one for memory error handling, which is not enough because
there's a time window where compound pages have non-zero refcount during
hugetlb page initialization.

So make __get_hwpoison_page() check page status a bit more for hugetlb
pages with get_hwpoison_huge_page().  Checking hugetlb-specific flags
under hugetlb_lock makes sure that the hugetlb page is not transitive.
It's notable that another new function, HWPoisonHandlable(), is helpful
to prevent a race against other transitive page states (like a generic
compound page just before PageHuge becomes true).

Link: https://lkml.kernel.org/r/20210603233632.2964832-2-nao.horiguchi@gmail.com
Fixes: ead07f6a867b ("mm/memory-failure: introduce get_hwpoison_page() for consistent refcount handling")
Signed-off-by: Naoya Horiguchi <naoya.horiguchi@nec.com>
Reported-by: Muchun Song <songmuchun@bytedance.com>
Acked-by: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: <stable@vger.kernel.org>	[5.12+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2021-06-16 09:24:42 -07:00
..
2021-06-05 08:58:11 -07:00
2021-05-07 00:26:35 -07:00
2021-05-05 11:27:24 -07:00
2021-05-05 11:27:24 -07:00
2021-05-07 00:26:35 -07:00
2021-02-24 13:38:27 -08:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-14 19:41:32 -07:00
2021-05-07 00:26:35 -07:00
2021-04-30 11:20:36 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-05 11:27:27 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:34 -07:00
2021-05-07 00:26:35 -07:00
2021-03-02 17:25:46 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-04-16 16:10:37 -07:00
2021-05-07 00:26:35 -07:00
2021-05-05 11:27:27 -07:00
2021-05-07 00:26:35 -07:00
2021-05-05 11:27:19 -07:00
2021-05-05 11:27:25 -07:00
2021-05-07 00:26:35 -07:00
2021-05-05 11:27:27 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00
2021-05-07 00:26:35 -07:00