On Thu, Apr 29, 2021 at 02:48:01PM -0700, Peter Collingbourne wrote:
quoted hunk ↗ jump to hunk
@@ -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