On Thu, Apr 29, 2021 at 02:48:01PM -0700, Peter Collingbourne wrote: > @@ -132,9 +134,12 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, > } > > /* Avoid taking write faults for known dirty pages */ > - if (dirty_accountable && pte_dirty(ptent) && > - (pte_soft_dirty(ptent) || > - !(vma->vm_flags & VM_SOFTDIRTY))) { > + if ((dirty_accountable || > + (anon_writable && > + page_mapcount(pte_page(ptent)) == 1)) && > + pte_dirty(ptent) && > + (pte_soft_dirty(ptent) || > + !(vma->vm_flags & VM_SOFTDIRTY))) { > ptent = pte_mkwrite(ptent); > } > ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent); This breaks uffd-wp anonymous page. I think we'd at least need below to be squashed: diff --git a/mm/mprotect.c b/mm/mprotect.c index ed10a790933e..6cb531eab811 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -139,6 +139,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, (anon_writable && page_mapcount(pte_page(ptent)) == 1)) && pte_dirty(ptent) && + !pte_uffd_wp(ptent) && (pte_soft_dirty(ptent) || !(vma->vm_flags & VM_SOFTDIRTY))) { ptent = pte_mkwrite(ptent); It'll be good to start thinking about how to not continue growing this if clause condition, though.. -- Peter Xu