Merge tag 'spdx_identifiers-4.14-rc8' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / mm / page_vma_mapped.c
index 6a03946469a99eb535851194f519893a5e8a2d11..d22b84310f6d40903083521fb18a5e858f464d93 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 #include <linux/mm.h>
 #include <linux/rmap.h>
 #include <linux/hugetlb.h>
@@ -6,17 +7,6 @@
 
 #include "internal.h"
 
-static inline bool check_pmd(struct page_vma_mapped_walk *pvmw)
-{
-       pmd_t pmde;
-       /*
-        * Make sure we don't re-load pmd between present and !trans_huge check.
-        * We need a consistent view.
-        */
-       pmde = READ_ONCE(*pvmw->pmd);
-       return pmd_present(pmde) && !pmd_trans_huge(pmde);
-}
-
 static inline bool not_found(struct page_vma_mapped_walk *pvmw)
 {
        page_vma_mapped_walk_done(pvmw);
@@ -116,6 +106,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
        pgd_t *pgd;
        p4d_t *p4d;
        pud_t *pud;
+       pmd_t pmde;
 
        /* The only possible pmd mapping has been handled on last iteration */
        if (pvmw->pmd && !pvmw->pte)
@@ -148,7 +139,13 @@ restart:
        if (!pud_present(*pud))
                return false;
        pvmw->pmd = pmd_offset(pud, pvmw->address);
-       if (pmd_trans_huge(*pvmw->pmd) || is_pmd_migration_entry(*pvmw->pmd)) {
+       /*
+        * Make sure the pmd value isn't cached in a register by the
+        * compiler and used as a stale value after we've observed a
+        * subsequent update.
+        */
+       pmde = READ_ONCE(*pvmw->pmd);
+       if (pmd_trans_huge(pmde) || is_pmd_migration_entry(pmde)) {
                pvmw->ptl = pmd_lock(mm, pvmw->pmd);
                if (likely(pmd_trans_huge(*pvmw->pmd))) {
                        if (pvmw->flags & PVMW_MIGRATION)
@@ -167,17 +164,15 @@ restart:
                                                return not_found(pvmw);
                                        return true;
                                }
-                       } else
-                               WARN_ONCE(1, "Non present huge pmd without pmd migration enabled!");
+                       }
                        return not_found(pvmw);
                } else {
                        /* THP pmd was split under us: handle on pte level */
                        spin_unlock(pvmw->ptl);
                        pvmw->ptl = NULL;
                }
-       } else {
-               if (!check_pmd(pvmw))
-                       return false;
+       } else if (!pmd_present(pmde)) {
+               return false;
        }
        if (!map_pte(pvmw))
                goto next_pte;