|
@@ -691,8 +691,8 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
|
|
|
pgoff_t index, unsigned long pfn)
|
|
|
{
|
|
|
struct vm_area_struct *vma;
|
|
|
- pte_t *ptep;
|
|
|
- pte_t pte;
|
|
|
+ pte_t pte, *ptep = NULL;
|
|
|
+ pmd_t *pmdp = NULL;
|
|
|
spinlock_t *ptl;
|
|
|
bool changed;
|
|
|
|
|
@@ -707,21 +707,42 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
|
|
|
|
|
|
address = pgoff_address(index, vma);
|
|
|
changed = false;
|
|
|
- if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
|
|
|
+ if (follow_pte_pmd(vma->vm_mm, address, &ptep, &pmdp, &ptl))
|
|
|
continue;
|
|
|
- if (pfn != pte_pfn(*ptep))
|
|
|
- goto unlock;
|
|
|
- if (!pte_dirty(*ptep) && !pte_write(*ptep))
|
|
|
- goto unlock;
|
|
|
|
|
|
- flush_cache_page(vma, address, pfn);
|
|
|
- pte = ptep_clear_flush(vma, address, ptep);
|
|
|
- pte = pte_wrprotect(pte);
|
|
|
- pte = pte_mkclean(pte);
|
|
|
- set_pte_at(vma->vm_mm, address, ptep, pte);
|
|
|
- changed = true;
|
|
|
-unlock:
|
|
|
- pte_unmap_unlock(ptep, ptl);
|
|
|
+ if (pmdp) {
|
|
|
+#ifdef CONFIG_FS_DAX_PMD
|
|
|
+ pmd_t pmd;
|
|
|
+
|
|
|
+ if (pfn != pmd_pfn(*pmdp))
|
|
|
+ goto unlock_pmd;
|
|
|
+ if (!pmd_dirty(*pmdp) && !pmd_write(*pmdp))
|
|
|
+ goto unlock_pmd;
|
|
|
+
|
|
|
+ flush_cache_page(vma, address, pfn);
|
|
|
+ pmd = pmdp_huge_clear_flush(vma, address, pmdp);
|
|
|
+ pmd = pmd_wrprotect(pmd);
|
|
|
+ pmd = pmd_mkclean(pmd);
|
|
|
+ set_pmd_at(vma->vm_mm, address, pmdp, pmd);
|
|
|
+ changed = true;
|
|
|
+unlock_pmd:
|
|
|
+ spin_unlock(ptl);
|
|
|
+#endif
|
|
|
+ } else {
|
|
|
+ if (pfn != pte_pfn(*ptep))
|
|
|
+ goto unlock_pte;
|
|
|
+ if (!pte_dirty(*ptep) && !pte_write(*ptep))
|
|
|
+ goto unlock_pte;
|
|
|
+
|
|
|
+ flush_cache_page(vma, address, pfn);
|
|
|
+ pte = ptep_clear_flush(vma, address, ptep);
|
|
|
+ pte = pte_wrprotect(pte);
|
|
|
+ pte = pte_mkclean(pte);
|
|
|
+ set_pte_at(vma->vm_mm, address, ptep, pte);
|
|
|
+ changed = true;
|
|
|
+unlock_pte:
|
|
|
+ pte_unmap_unlock(ptep, ptl);
|
|
|
+ }
|
|
|
|
|
|
if (changed)
|
|
|
mmu_notifier_invalidate_page(vma->vm_mm, address);
|