The patch titled mm: optimize the new mprotect() code a bit has been added to the -mm tree. Its filename is mm-optimize-the-new-mprotect-code-a-bit.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: mm: optimize the new mprotect() code a bit From: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> mprotect() resets the page protections, which could result in extra write faults for those pages whos dirty state we track using write faults and are dirty already. Signed-off-by: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- mm/mprotect.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff -puN mm/mprotect.c~mm-optimize-the-new-mprotect-code-a-bit mm/mprotect.c --- a/mm/mprotect.c~mm-optimize-the-new-mprotect-code-a-bit +++ a/mm/mprotect.c @@ -28,7 +28,8 @@ #include <asm/tlbflush.h> static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, - unsigned long addr, unsigned long end, pgprot_t newprot) + unsigned long addr, unsigned long end, pgprot_t newprot, + int is_accountable) { pte_t *pte, oldpte; spinlock_t *ptl; @@ -43,7 +44,13 @@ static void change_pte_range(struct mm_s * bits by wiping the pte and then setting the new pte * into place. */ - ptent = pte_modify(ptep_get_and_clear(mm, addr, pte), newprot); + ptent = ptep_get_and_clear(mm, addr, pte); + ptent = pte_modify(ptent, newprot); + /* Avoid taking write faults for pages we know to be + * dirty. + */ + if (is_accountable && pte_dirty(ptent)) + ptent = pte_mkwrite(ptent); set_pte_at(mm, addr, pte, ptent); lazy_mmu_prot_update(ptent); #ifdef CONFIG_MIGRATION @@ -67,7 +74,8 @@ static void change_pte_range(struct mm_s } static inline void change_pmd_range(struct mm_struct *mm, pud_t *pud, - unsigned long addr, unsigned long end, pgprot_t newprot) + unsigned long addr, unsigned long end, pgprot_t newprot, + int is_accountable) { pmd_t *pmd; unsigned long next; @@ -77,12 +85,13 @@ static inline void change_pmd_range(stru next = pmd_addr_end(addr, end); if (pmd_none_or_clear_bad(pmd)) continue; - change_pte_range(mm, pmd, addr, next, newprot); + change_pte_range(mm, pmd, addr, next, newprot, is_accountable); } while (pmd++, addr = next, addr != end); } static inline void change_pud_range(struct mm_struct *mm, pgd_t *pgd, - unsigned long addr, unsigned long end, pgprot_t newprot) + unsigned long addr, unsigned long end, pgprot_t newprot, + int is_accountable) { pud_t *pud; unsigned long next; @@ -92,12 +101,13 @@ static inline void change_pud_range(stru next = pud_addr_end(addr, end); if (pud_none_or_clear_bad(pud)) continue; - change_pmd_range(mm, pud, addr, next, newprot); + change_pmd_range(mm, pud, addr, next, newprot, is_accountable); } while (pud++, addr = next, addr != end); } static void change_protection(struct vm_area_struct *vma, - unsigned long addr, unsigned long end, pgprot_t newprot) + unsigned long addr, unsigned long end, pgprot_t newprot, + int is_accountable) { struct mm_struct *mm = vma->vm_mm; pgd_t *pgd; @@ -111,7 +121,7 @@ static void change_protection(struct vm_ next = pgd_addr_end(addr, end); if (pgd_none_or_clear_bad(pgd)) continue; - change_pud_range(mm, pgd, addr, next, newprot); + change_pud_range(mm, pgd, addr, next, newprot, is_accountable); } while (pgd++, addr = next, addr != end); flush_tlb_range(vma, start, end); } @@ -129,6 +139,7 @@ mprotect_fixup(struct vm_area_struct *vm pgprot_t newprot; pgoff_t pgoff; int error; + int is_accountable = 0; if (newflags == oldflags) { *pprev = vma; @@ -184,8 +195,10 @@ success: if (is_shared_writable(newflags) && vma->vm_file) mapping = vma->vm_file->f_mapping; if ((mapping && mapping_cap_account_dirty(mapping)) || - (vma->vm_ops && vma->vm_ops->page_mkwrite)) + (vma->vm_ops && vma->vm_ops->page_mkwrite)) { mask &= ~VM_SHARED; + is_accountable = 1; + } newprot = protection_map[newflags & mask]; @@ -198,7 +211,7 @@ success: if (is_vm_hugetlb_page(vma)) hugetlb_change_protection(vma, start, end, newprot); else - change_protection(vma, start, end, newprot); + change_protection(vma, start, end, newprot, is_accountable); vm_stat_account(mm, oldflags, vma->vm_file, -nrpages); vm_stat_account(mm, newflags, vma->vm_file, nrpages); return 0; _ Patches currently in -mm which might be from a.p.zijlstra@xxxxxxxxx are buglet-in-radix_tree_tag_set.patch add-page_mkwrite-vm_operations-method-fix.patch mm-tracking-shared-dirty-pages.patch mm-balance-dirty-pages.patch mm-msync-cleanup.patch mm-optimize-the-new-mprotect-code-a-bit.patch mm-small-cleanup-of-install_page.patch mm-remove-some-update_mmu_cache-calls.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html