mm/mmu_notifier: avoid double notification when it is useless
[sfrench/cifs-2.6.git] / mm / huge_memory.c
index b521ed1170f967d37adac445eff57a394c7f0e4a..07ae73f4ef9149eb6b71b1ed9aca9b31f5a9d185 100644 (file)
 #include "internal.h"
 
 /*
- * By default transparent hugepage support is disabled in order that avoid
- * to risk increase the memory footprint of applications without a guaranteed
- * benefit. When transparent hugepage support is enabled, is for all mappings,
- * and khugepaged scans all mappings.
+ * By default, transparent hugepage support is disabled in order to avoid
+ * risking an increased memory footprint for applications that are not
+ * guaranteed to benefit from it. When transparent hugepage support is
+ * enabled, it is for all mappings, and khugepaged scans all mappings.
  * Defrag is invoked by khugepaged hugepage allocations and by page faults
  * for all hugepage allocations.
  */
@@ -1189,8 +1189,15 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd,
                goto out_free_pages;
        VM_BUG_ON_PAGE(!PageHead(page), page);
 
+       /*
+        * Leave pmd empty until pte is filled note we must notify here as
+        * concurrent CPU thread might write to new page before the call to
+        * mmu_notifier_invalidate_range_end() happens which can lead to a
+        * device seeing memory write in different order than CPU.
+        *
+        * See Documentation/vm/mmu_notifier.txt
+        */
        pmdp_huge_clear_flush_notify(vma, haddr, vmf->pmd);
-       /* leave pmd empty until pte is filled */
 
        pgtable = pgtable_trans_huge_withdraw(vma->vm_mm, vmf->pmd);
        pmd_populate(vma->vm_mm, &_pmd, pgtable);
@@ -2029,8 +2036,15 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
        pmd_t _pmd;
        int i;
 
-       /* leave pmd empty until pte is filled */
-       pmdp_huge_clear_flush_notify(vma, haddr, pmd);
+       /*
+        * Leave pmd empty until pte is filled note that it is fine to delay
+        * notification until mmu_notifier_invalidate_range_end() as we are
+        * replacing a zero pmd write protected page with a zero pte write
+        * protected page.
+        *
+        * See Documentation/vm/mmu_notifier.txt
+        */
+       pmdp_huge_clear_flush(vma, haddr, pmd);
 
        pgtable = pgtable_trans_huge_withdraw(mm, pmd);
        pmd_populate(mm, &_pmd, pgtable);