mm/memory-failure.c: fix race with changing page more robustly
authorMiaohe Lin <linmiaohe@huawei.com>
Tue, 22 Mar 2022 21:44:21 +0000 (14:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 22:57:07 +0000 (15:57 -0700)
We're only intended to deal with the non-Compound page after we split
thp in memory_failure.  However, the page could have changed compound
pages due to race window.  If this happens, we could retry once to
hopefully handle the page next round.  Also remove unneeded orig_head.
It's always equal to the hpage.  So we can use hpage directly and remove
this redundant one.

Link: https://lkml.kernel.org/r/20220218090118.1105-5-linmiaohe@huawei.com
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Acked-by: Naoya Horiguchi <naoya.horiguchi@nec.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/memory-failure.c

index 716aebcbb0de874cfb7b4c2cf7153933704db5a8..79a32be5e7df3420a4cf065c107b2bf56442e972 100644 (file)
@@ -1686,7 +1686,6 @@ int memory_failure(unsigned long pfn, int flags)
 {
        struct page *p;
        struct page *hpage;
-       struct page *orig_head;
        struct dev_pagemap *pgmap;
        int res = 0;
        unsigned long page_flags;
@@ -1732,7 +1731,7 @@ try_again:
                goto unlock_mutex;
        }
 
-       orig_head = hpage = compound_head(p);
+       hpage = compound_head(p);
        num_poisoned_pages_inc();
 
        /*
@@ -1813,10 +1812,21 @@ try_again:
        lock_page(p);
 
        /*
-        * The page could have changed compound pages during the locking.
-        * If this happens just bail out.
+        * We're only intended to deal with the non-Compound page here.
+        * However, the page could have changed compound pages due to
+        * race window. If this happens, we could try again to hopefully
+        * handle the page next round.
         */
-       if (PageCompound(p) && compound_head(p) != orig_head) {
+       if (PageCompound(p)) {
+               if (retry) {
+                       if (TestClearPageHWPoison(p))
+                               num_poisoned_pages_dec();
+                       unlock_page(p);
+                       put_page(p);
+                       flags &= ~MF_COUNT_INCREASED;
+                       retry = false;
+                       goto try_again;
+               }
                action_result(pfn, MF_MSG_DIFFERENT_COMPOUND, MF_IGNORED);
                res = -EBUSY;
                goto unlock_page;