diff for duplicates of <20180915004157.GA15678@redhat.com> diff --git a/a/1.txt b/N1/1.txt index f682f30..8ef9271 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -50,7 +50,7 @@ On Fri, Sep 14, 2018 at 03:16:11PM +0800, Peter Xu wrote: > > > > > > unwrite protect pages in a range that is write protected ie the vma > > > > > > !(vm_flags & VM_WRITE). > > > > > > -> > > > > > Signed-off-by: Jerome Glisse <jglisse@redhat.com> +> > > > > > Signed-off-by: Jérôme Glisse <jglisse@redhat.com> > > > > > > --- > > > > > > mm/userfaultfd.c | 2 +- > > > > > > 1 file changed, 1 insertion(+), 1 deletion(-) @@ -158,4 +158,371 @@ elevated, maybe you check the mapcount on the page. Cheers, -Jerome +Jérôme + + + +From 83abd3f16950a0b5cb6870a04d89d4fcc06b8865 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= <jglisse@redhat.com> +Date: Thu, 13 Sep 2018 10:16:30 -0400 +Subject: [PATCH] mm/mprotect: add a mkwrite paramater to change_protection() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mkwrite parameter allow to change read only pte to write one which +is needed by userfaultfd to un-write-protect after a fault have been +handled. + +Signed-off-by: Jérôme Glisse <jglisse@redhat.com> +--- + include/linux/huge_mm.h | 2 +- + include/linux/mm.h | 3 +- + mm/huge_memory.c | 32 +++++++++++++++++++-- + mm/mempolicy.c | 2 +- + mm/mprotect.c | 61 +++++++++++++++++++++++++++++----------- + mm/userfaultfd.c | 2 +- + tools/lib/str_error_r.c | 9 ++++-- + tools/lib/subcmd/pager.c | 5 +++- + 8 files changed, 90 insertions(+), 26 deletions(-) + +diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h +index a8a126259bc4..b51ff7f8e65c 100644 +--- a/include/linux/huge_mm.h ++++ b/include/linux/huge_mm.h +@@ -45,7 +45,7 @@ extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, + pmd_t *old_pmd, pmd_t *new_pmd, bool *need_flush); + extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, + unsigned long addr, pgprot_t newprot, +- int prot_numa); ++ int prot_numa, bool mkwrite); + int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr, + pmd_t *pmd, pfn_t pfn, bool write); + int vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr, +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 5d5c7fd07dc0..2bbf3e33bf9e 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1492,7 +1492,8 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma, + bool need_rmap_locks); + extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start, + unsigned long end, pgprot_t newprot, +- int dirty_accountable, int prot_numa); ++ int dirty_accountable, int prot_numa, ++ bool mkwrite); + extern int mprotect_fixup(struct vm_area_struct *vma, + struct vm_area_struct **pprev, unsigned long start, + unsigned long end, unsigned long newflags); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index abf621aba672..7b848b84d80c 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1842,12 +1842,13 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, + * - HPAGE_PMD_NR is protections changed and TLB flush necessary + */ + int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, +- unsigned long addr, pgprot_t newprot, int prot_numa) ++ unsigned long addr, pgprot_t newprot, int prot_numa, ++ bool mkwrite) + { + struct mm_struct *mm = vma->vm_mm; + spinlock_t *ptl; + pmd_t entry; +- bool preserve_write; ++ bool preserve_write, do_mkwrite = false; + int ret; + + ptl = __pmd_trans_huge_lock(pmd, vma); +@@ -1857,6 +1858,31 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, + preserve_write = prot_numa && pmd_write(*pmd); + ret = 1; + ++ if (mkwrite && pmd_present(*pmd) && !pmd_write(*pmd)) { ++ pmd_t orig_pmd = READ_ONCE(*pmd); ++ struct page *page = pmd_page(orig_pmd); ++ ++ VM_BUG_ON_PAGE(!PageCompound(page) || !PageHead(page), page); ++ /* ++ * We can only allow mkwrite if nobody else maps the huge page ++ * or it's part. ++ */ ++ if (!trylock_page(page)) { ++ get_page(page); ++ spin_unlock(ptl); ++ lock_page(page); ++ ++ ptl = __pmd_trans_huge_lock(pmd, vma); ++ if (!ptl) ++ return 0; ++ } ++ if (pmd_same(*pmd, orig_pmd) && reuse_swap_page(page, NULL)) { ++ do_mkwrite = true; ++ } ++ unlock_page(page); ++ put_page(page); ++ } ++ + #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION + if (is_swap_pmd(*pmd)) { + swp_entry_t entry = pmd_to_swp_entry(*pmd); +@@ -1925,6 +1951,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, + entry = pmd_modify(entry, newprot); + if (preserve_write) + entry = pmd_mk_savedwrite(entry); ++ if (do_mkwrite) ++ entry = pmd_mkwrite(entry); + ret = HPAGE_PMD_NR; + set_pmd_at(mm, addr, pmd, entry); + BUG_ON(vma_is_anonymous(vma) && !preserve_write && pmd_write(entry)); +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 4ce44d3ff03d..2d0ee09e6b26 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -579,7 +579,7 @@ unsigned long change_prot_numa(struct vm_area_struct *vma, + { + int nr_updated; + +- nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1); ++ nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1, false); + if (nr_updated) + count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated); + +diff --git a/mm/mprotect.c b/mm/mprotect.c +index 58b629bb70de..2d0c7e39f075 100644 +--- a/mm/mprotect.c ++++ b/mm/mprotect.c +@@ -36,7 +36,7 @@ + + static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + unsigned long addr, unsigned long end, pgprot_t newprot, +- int dirty_accountable, int prot_numa) ++ int dirty_accountable, int prot_numa, bool mkwrite) + { + struct mm_struct *mm = vma->vm_mm; + pte_t *pte, oldpte; +@@ -72,13 +72,15 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + if (pte_present(oldpte)) { + pte_t ptent; + bool preserve_write = prot_numa && pte_write(oldpte); ++ bool do_mkwrite = false; + + /* + * Avoid trapping faults against the zero or KSM + * pages. See similar comment in change_huge_pmd. + */ +- if (prot_numa) { ++ if (prot_numa || mkwrite) { + struct page *page; ++ int tmp; + + page = vm_normal_page(vma, addr, oldpte); + if (!page || PageKsm(page)) +@@ -94,6 +96,26 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + */ + if (target_node == page_to_nid(page)) + continue; ++ ++ if (mkwrite) { ++ if (!trylock_page(page)) { ++ pte_t orig_pte = READ_ONCE(*pte); ++ get_page(page); ++ pte_unmap_unlock(pte, ptl); ++ lock_page(page); ++ pte = pte_offset_map_lock(vma->vm_mm, pmd, ++ addr, &ptl); ++ if (!pte_same(*pte, orig_pte)) { ++ unlock_page(page); ++ put_page(page); ++ continue; ++ } ++ } ++ if (reuse_swap_page(page, &tmp)) ++ do_mkwrite = true; ++ unlock_page(page); ++ put_page(page); ++ } + } + + ptent = ptep_modify_prot_start(mm, addr, pte); +@@ -102,9 +124,9 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + ptent = pte_mk_savedwrite(ptent); + + /* Avoid taking write faults for known dirty pages */ +- if (dirty_accountable && pte_dirty(ptent) && +- (pte_soft_dirty(ptent) || +- !(vma->vm_flags & VM_SOFTDIRTY))) { ++ if (do_mkwrite || (dirty_accountable && ++ pte_dirty(ptent) && (pte_soft_dirty(ptent) || ++ !(vma->vm_flags & VM_SOFTDIRTY)))) { + ptent = pte_mkwrite(ptent); + } + ptep_modify_prot_commit(mm, addr, pte, ptent); +@@ -150,7 +172,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + + static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + pud_t *pud, unsigned long addr, unsigned long end, +- pgprot_t newprot, int dirty_accountable, int prot_numa) ++ pgprot_t newprot, int dirty_accountable, int prot_numa, ++ bool mkwrite) + { + pmd_t *pmd; + struct mm_struct *mm = vma->vm_mm; +@@ -179,7 +202,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + __split_huge_pmd(vma, pmd, addr, false, NULL); + } else { + int nr_ptes = change_huge_pmd(vma, pmd, addr, +- newprot, prot_numa); ++ newprot, prot_numa, mkwrite); + + if (nr_ptes) { + if (nr_ptes == HPAGE_PMD_NR) { +@@ -194,7 +217,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + /* fall through, the trans huge pmd just split */ + } + this_pages = change_pte_range(vma, pmd, addr, next, newprot, +- dirty_accountable, prot_numa); ++ dirty_accountable, prot_numa, mkwrite); + pages += this_pages; + next: + cond_resched(); +@@ -210,7 +233,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + + static inline unsigned long change_pud_range(struct vm_area_struct *vma, + p4d_t *p4d, unsigned long addr, unsigned long end, +- pgprot_t newprot, int dirty_accountable, int prot_numa) ++ pgprot_t newprot, int dirty_accountable, int prot_numa, ++ bool mkwrite) + { + pud_t *pud; + unsigned long next; +@@ -222,7 +246,7 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma, + if (pud_none_or_clear_bad(pud)) + continue; + pages += change_pmd_range(vma, pud, addr, next, newprot, +- dirty_accountable, prot_numa); ++ dirty_accountable, prot_numa, mkwrite); + } while (pud++, addr = next, addr != end); + + return pages; +@@ -230,7 +254,8 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma, + + static inline unsigned long change_p4d_range(struct vm_area_struct *vma, + pgd_t *pgd, unsigned long addr, unsigned long end, +- pgprot_t newprot, int dirty_accountable, int prot_numa) ++ pgprot_t newprot, int dirty_accountable, int prot_numa, ++ bool mkwrite) + { + p4d_t *p4d; + unsigned long next; +@@ -242,7 +267,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma, + if (p4d_none_or_clear_bad(p4d)) + continue; + pages += change_pud_range(vma, p4d, addr, next, newprot, +- dirty_accountable, prot_numa); ++ dirty_accountable, prot_numa, mkwrite); + } while (p4d++, addr = next, addr != end); + + return pages; +@@ -250,7 +275,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma, + + static unsigned long change_protection_range(struct vm_area_struct *vma, + unsigned long addr, unsigned long end, pgprot_t newprot, +- int dirty_accountable, int prot_numa) ++ int dirty_accountable, int prot_numa, bool mkwrite) + { + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgd; +@@ -267,7 +292,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma, + if (pgd_none_or_clear_bad(pgd)) + continue; + pages += change_p4d_range(vma, pgd, addr, next, newprot, +- dirty_accountable, prot_numa); ++ dirty_accountable, prot_numa, mkwrite); + } while (pgd++, addr = next, addr != end); + + /* Only flush the TLB if we actually modified any entries: */ +@@ -280,14 +305,16 @@ static unsigned long change_protection_range(struct vm_area_struct *vma, + + unsigned long change_protection(struct vm_area_struct *vma, unsigned long start, + unsigned long end, pgprot_t newprot, +- int dirty_accountable, int prot_numa) ++ int dirty_accountable, int prot_numa, bool mkwrite) + { + unsigned long pages; + + if (is_vm_hugetlb_page(vma)) + pages = hugetlb_change_protection(vma, start, end, newprot); + else +- pages = change_protection_range(vma, start, end, newprot, dirty_accountable, prot_numa); ++ pages = change_protection_range(vma, start, end, newprot, ++ dirty_accountable, ++ prot_numa, mkwrite); + + return pages; + } +@@ -366,7 +393,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, + vma_set_page_prot(vma); + + change_protection(vma, start, end, vma->vm_page_prot, +- dirty_accountable, 0); ++ dirty_accountable, 0, false); + + /* + * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major +diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c +index a0379c5ffa7c..c745c5d87523 100644 +--- a/mm/userfaultfd.c ++++ b/mm/userfaultfd.c +@@ -632,7 +632,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start, + newprot = vm_get_page_prot(dst_vma->vm_flags); + + change_protection(dst_vma, start, start + len, newprot, +- !enable_wp, 0); ++ 0, 0, !enable_wp); + + err = 0; + out_unlock: +diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c +index d6d65537b0d9..11c3425f272b 100644 +--- a/tools/lib/str_error_r.c ++++ b/tools/lib/str_error_r.c +@@ -21,7 +21,12 @@ + char *str_error_r(int errnum, char *buf, size_t buflen) + { + int err = strerror_r(errnum, buf, buflen); +- if (err) +- snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", errnum, buf, buflen, err); ++ if (err) { ++ char *err_buf = buf; ++ ++ snprintf(err_buf, buflen, ++ "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", ++ errnum, buf, buflen, err); ++ } + return buf; + } +diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c +index 5ba754d17952..e1895568edaf 100644 +--- a/tools/lib/subcmd/pager.c ++++ b/tools/lib/subcmd/pager.c +@@ -25,6 +25,8 @@ void pager_init(const char *pager_env) + + static void pager_preexec(void) + { ++ void *ptr; ++ + /* + * Work around bug in "less" by not starting it until we + * have real input +@@ -33,7 +35,8 @@ static void pager_preexec(void) + + FD_ZERO(&in); + FD_SET(0, &in); +- select(1, &in, NULL, &in, NULL); ++ ptr = ∈ ++ select(1, &in, NULL, ptr, NULL); + + setenv("LESS", "FRSX", 0); + } +-- +2.17.1 diff --git a/a/content_digest b/N1/content_digest index 2f92976..b0d0d27 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -77,7 +77,7 @@ "> > > > > > unwrite protect pages in a range that is write protected ie the vma\n" "> > > > > > !(vm_flags & VM_WRITE).\n" "> > > > > > \n" - "> > > > > > Signed-off-by: Jerome Glisse <jglisse@redhat.com>\n" + "> > > > > > Signed-off-by: J\303\251r\303\264me Glisse <jglisse@redhat.com>\n" "> > > > > > ---\n" "> > > > > > mm/userfaultfd.c | 2 +-\n" "> > > > > > 1 file changed, 1 insertion(+), 1 deletion(-)\n" @@ -185,6 +185,373 @@ "\n" "\n" "Cheers,\n" - Jerome + "J\303\251r\303\264me\n" + "\n" + "\n" + "\n" + "From 83abd3f16950a0b5cb6870a04d89d4fcc06b8865 Mon Sep 17 00:00:00 2001\n" + "From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= <jglisse@redhat.com>\n" + "Date: Thu, 13 Sep 2018 10:16:30 -0400\n" + "Subject: [PATCH] mm/mprotect: add a mkwrite paramater to change_protection()\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "\n" + "The mkwrite parameter allow to change read only pte to write one which\n" + "is needed by userfaultfd to un-write-protect after a fault have been\n" + "handled.\n" + "\n" + "Signed-off-by: J\303\251r\303\264me Glisse <jglisse@redhat.com>\n" + "---\n" + " include/linux/huge_mm.h | 2 +-\n" + " include/linux/mm.h | 3 +-\n" + " mm/huge_memory.c | 32 +++++++++++++++++++--\n" + " mm/mempolicy.c | 2 +-\n" + " mm/mprotect.c | 61 +++++++++++++++++++++++++++++-----------\n" + " mm/userfaultfd.c | 2 +-\n" + " tools/lib/str_error_r.c | 9 ++++--\n" + " tools/lib/subcmd/pager.c | 5 +++-\n" + " 8 files changed, 90 insertions(+), 26 deletions(-)\n" + "\n" + "diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h\n" + "index a8a126259bc4..b51ff7f8e65c 100644\n" + "--- a/include/linux/huge_mm.h\n" + "+++ b/include/linux/huge_mm.h\n" + "@@ -45,7 +45,7 @@ extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,\n" + " \t\t\t pmd_t *old_pmd, pmd_t *new_pmd, bool *need_flush);\n" + " extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \t\t\tunsigned long addr, pgprot_t newprot,\n" + "-\t\t\tint prot_numa);\n" + "+\t\t\tint prot_numa, bool mkwrite);\n" + " int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,\n" + " \t\t\tpmd_t *pmd, pfn_t pfn, bool write);\n" + " int vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,\n" + "diff --git a/include/linux/mm.h b/include/linux/mm.h\n" + "index 5d5c7fd07dc0..2bbf3e33bf9e 100644\n" + "--- a/include/linux/mm.h\n" + "+++ b/include/linux/mm.h\n" + "@@ -1492,7 +1492,8 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,\n" + " \t\tbool need_rmap_locks);\n" + " extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,\n" + " \t\t\t unsigned long end, pgprot_t newprot,\n" + "-\t\t\t int dirty_accountable, int prot_numa);\n" + "+\t\t\t int dirty_accountable, int prot_numa,\n" + "+\t\t\t bool mkwrite);\n" + " extern int mprotect_fixup(struct vm_area_struct *vma,\n" + " \t\t\t struct vm_area_struct **pprev, unsigned long start,\n" + " \t\t\t unsigned long end, unsigned long newflags);\n" + "diff --git a/mm/huge_memory.c b/mm/huge_memory.c\n" + "index abf621aba672..7b848b84d80c 100644\n" + "--- a/mm/huge_memory.c\n" + "+++ b/mm/huge_memory.c\n" + "@@ -1842,12 +1842,13 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,\n" + " * - HPAGE_PMD_NR is protections changed and TLB flush necessary\n" + " */\n" + " int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,\n" + "-\t\tunsigned long addr, pgprot_t newprot, int prot_numa)\n" + "+\t\tunsigned long addr, pgprot_t newprot, int prot_numa,\n" + "+\t\tbool mkwrite)\n" + " {\n" + " \tstruct mm_struct *mm = vma->vm_mm;\n" + " \tspinlock_t *ptl;\n" + " \tpmd_t entry;\n" + "-\tbool preserve_write;\n" + "+\tbool preserve_write, do_mkwrite = false;\n" + " \tint ret;\n" + " \n" + " \tptl = __pmd_trans_huge_lock(pmd, vma);\n" + "@@ -1857,6 +1858,31 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \tpreserve_write = prot_numa && pmd_write(*pmd);\n" + " \tret = 1;\n" + " \n" + "+\tif (mkwrite && pmd_present(*pmd) && !pmd_write(*pmd)) {\n" + "+\t\tpmd_t orig_pmd = READ_ONCE(*pmd);\n" + "+\t\tstruct page *page = pmd_page(orig_pmd);\n" + "+\n" + "+\t\tVM_BUG_ON_PAGE(!PageCompound(page) || !PageHead(page), page);\n" + "+\t\t/*\n" + "+\t\t * We can only allow mkwrite if nobody else maps the huge page\n" + "+\t\t * or it's part.\n" + "+\t\t */\n" + "+\t\tif (!trylock_page(page)) {\n" + "+\t\t\tget_page(page);\n" + "+\t\t\tspin_unlock(ptl);\n" + "+\t\t\tlock_page(page);\n" + "+\n" + "+\t\t\tptl = __pmd_trans_huge_lock(pmd, vma);\n" + "+\t\t\tif (!ptl)\n" + "+\t\t\t\treturn 0;\n" + "+\t\t}\n" + "+\t\tif (pmd_same(*pmd, orig_pmd) && reuse_swap_page(page, NULL)) {\n" + "+\t\t\tdo_mkwrite = true;\n" + "+\t\t}\n" + "+\t\tunlock_page(page);\n" + "+\t\tput_page(page);\n" + "+\t}\n" + "+\n" + " #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION\n" + " \tif (is_swap_pmd(*pmd)) {\n" + " \t\tswp_entry_t entry = pmd_to_swp_entry(*pmd);\n" + "@@ -1925,6 +1951,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \tentry = pmd_modify(entry, newprot);\n" + " \tif (preserve_write)\n" + " \t\tentry = pmd_mk_savedwrite(entry);\n" + "+\tif (do_mkwrite)\n" + "+\t\tentry = pmd_mkwrite(entry);\n" + " \tret = HPAGE_PMD_NR;\n" + " \tset_pmd_at(mm, addr, pmd, entry);\n" + " \tBUG_ON(vma_is_anonymous(vma) && !preserve_write && pmd_write(entry));\n" + "diff --git a/mm/mempolicy.c b/mm/mempolicy.c\n" + "index 4ce44d3ff03d..2d0ee09e6b26 100644\n" + "--- a/mm/mempolicy.c\n" + "+++ b/mm/mempolicy.c\n" + "@@ -579,7 +579,7 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,\n" + " {\n" + " \tint nr_updated;\n" + " \n" + "-\tnr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);\n" + "+\tnr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1, false);\n" + " \tif (nr_updated)\n" + " \t\tcount_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);\n" + " \n" + "diff --git a/mm/mprotect.c b/mm/mprotect.c\n" + "index 58b629bb70de..2d0c7e39f075 100644\n" + "--- a/mm/mprotect.c\n" + "+++ b/mm/mprotect.c\n" + "@@ -36,7 +36,7 @@\n" + " \n" + " static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \t\tunsigned long addr, unsigned long end, pgprot_t newprot,\n" + "-\t\tint dirty_accountable, int prot_numa)\n" + "+\t\tint dirty_accountable, int prot_numa, bool mkwrite)\n" + " {\n" + " \tstruct mm_struct *mm = vma->vm_mm;\n" + " \tpte_t *pte, oldpte;\n" + "@@ -72,13 +72,15 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \t\tif (pte_present(oldpte)) {\n" + " \t\t\tpte_t ptent;\n" + " \t\t\tbool preserve_write = prot_numa && pte_write(oldpte);\n" + "+\t\t\tbool do_mkwrite = false;\n" + " \n" + " \t\t\t/*\n" + " \t\t\t * Avoid trapping faults against the zero or KSM\n" + " \t\t\t * pages. See similar comment in change_huge_pmd.\n" + " \t\t\t */\n" + "-\t\t\tif (prot_numa) {\n" + "+\t\t\tif (prot_numa || mkwrite) {\n" + " \t\t\t\tstruct page *page;\n" + "+\t\t\t\tint tmp;\n" + " \n" + " \t\t\t\tpage = vm_normal_page(vma, addr, oldpte);\n" + " \t\t\t\tif (!page || PageKsm(page))\n" + "@@ -94,6 +96,26 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \t\t\t\t */\n" + " \t\t\t\tif (target_node == page_to_nid(page))\n" + " \t\t\t\t\tcontinue;\n" + "+\n" + "+\t\t\t\tif (mkwrite) {\n" + "+\t\t\t\t\tif (!trylock_page(page)) {\n" + "+\t\t\t\t\t\tpte_t orig_pte = READ_ONCE(*pte);\n" + "+\t\t\t\t\t\tget_page(page);\n" + "+\t\t\t\t\t\tpte_unmap_unlock(pte, ptl);\n" + "+\t\t\t\t\t\tlock_page(page);\n" + "+\t\t\t\t\t\tpte = pte_offset_map_lock(vma->vm_mm, pmd,\n" + "+\t\t\t\t\t\t\t\t\t addr, &ptl);\n" + "+\t\t\t\t\t\tif (!pte_same(*pte, orig_pte)) {\n" + "+\t\t\t\t\t\t\tunlock_page(page);\n" + "+\t\t\t\t\t\t\tput_page(page);\n" + "+\t\t\t\t\t\t\tcontinue;\n" + "+\t\t\t\t\t\t}\n" + "+\t\t\t\t\t}\n" + "+\t\t\t\t\tif (reuse_swap_page(page, &tmp))\n" + "+\t\t\t\t\t\tdo_mkwrite = true;\n" + "+\t\t\t\t\tunlock_page(page);\n" + "+\t\t\t\t\tput_page(page);\n" + "+\t\t\t\t}\n" + " \t\t\t}\n" + " \n" + " \t\t\tptent = ptep_modify_prot_start(mm, addr, pte);\n" + "@@ -102,9 +124,9 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \t\t\t\tptent = pte_mk_savedwrite(ptent);\n" + " \n" + " \t\t\t/* Avoid taking write faults for known dirty pages */\n" + "-\t\t\tif (dirty_accountable && pte_dirty(ptent) &&\n" + "-\t\t\t\t\t(pte_soft_dirty(ptent) ||\n" + "-\t\t\t\t\t !(vma->vm_flags & VM_SOFTDIRTY))) {\n" + "+\t\t\tif (do_mkwrite || (dirty_accountable &&\n" + "+\t\t\t pte_dirty(ptent) && (pte_soft_dirty(ptent) ||\n" + "+\t\t\t !(vma->vm_flags & VM_SOFTDIRTY)))) {\n" + " \t\t\t\tptent = pte_mkwrite(ptent);\n" + " \t\t\t}\n" + " \t\t\tptep_modify_prot_commit(mm, addr, pte, ptent);\n" + "@@ -150,7 +172,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,\n" + " \n" + " static inline unsigned long change_pmd_range(struct vm_area_struct *vma,\n" + " \t\tpud_t *pud, unsigned long addr, unsigned long end,\n" + "-\t\tpgprot_t newprot, int dirty_accountable, int prot_numa)\n" + "+\t\tpgprot_t newprot, int dirty_accountable, int prot_numa,\n" + "+\t\tbool mkwrite)\n" + " {\n" + " \tpmd_t *pmd;\n" + " \tstruct mm_struct *mm = vma->vm_mm;\n" + "@@ -179,7 +202,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,\n" + " \t\t\t\t__split_huge_pmd(vma, pmd, addr, false, NULL);\n" + " \t\t\t} else {\n" + " \t\t\t\tint nr_ptes = change_huge_pmd(vma, pmd, addr,\n" + "-\t\t\t\t\t\tnewprot, prot_numa);\n" + "+\t\t\t\t\t\tnewprot, prot_numa, mkwrite);\n" + " \n" + " \t\t\t\tif (nr_ptes) {\n" + " \t\t\t\t\tif (nr_ptes == HPAGE_PMD_NR) {\n" + "@@ -194,7 +217,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,\n" + " \t\t\t/* fall through, the trans huge pmd just split */\n" + " \t\t}\n" + " \t\tthis_pages = change_pte_range(vma, pmd, addr, next, newprot,\n" + "-\t\t\t\t dirty_accountable, prot_numa);\n" + "+\t\t\t\t dirty_accountable, prot_numa, mkwrite);\n" + " \t\tpages += this_pages;\n" + " next:\n" + " \t\tcond_resched();\n" + "@@ -210,7 +233,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,\n" + " \n" + " static inline unsigned long change_pud_range(struct vm_area_struct *vma,\n" + " \t\tp4d_t *p4d, unsigned long addr, unsigned long end,\n" + "-\t\tpgprot_t newprot, int dirty_accountable, int prot_numa)\n" + "+\t\tpgprot_t newprot, int dirty_accountable, int prot_numa,\n" + "+\t\tbool mkwrite)\n" + " {\n" + " \tpud_t *pud;\n" + " \tunsigned long next;\n" + "@@ -222,7 +246,7 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma,\n" + " \t\tif (pud_none_or_clear_bad(pud))\n" + " \t\t\tcontinue;\n" + " \t\tpages += change_pmd_range(vma, pud, addr, next, newprot,\n" + "-\t\t\t\t dirty_accountable, prot_numa);\n" + "+\t\t\t\t dirty_accountable, prot_numa, mkwrite);\n" + " \t} while (pud++, addr = next, addr != end);\n" + " \n" + " \treturn pages;\n" + "@@ -230,7 +254,8 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma,\n" + " \n" + " static inline unsigned long change_p4d_range(struct vm_area_struct *vma,\n" + " \t\tpgd_t *pgd, unsigned long addr, unsigned long end,\n" + "-\t\tpgprot_t newprot, int dirty_accountable, int prot_numa)\n" + "+\t\tpgprot_t newprot, int dirty_accountable, int prot_numa,\n" + "+\t\tbool mkwrite)\n" + " {\n" + " \tp4d_t *p4d;\n" + " \tunsigned long next;\n" + "@@ -242,7 +267,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma,\n" + " \t\tif (p4d_none_or_clear_bad(p4d))\n" + " \t\t\tcontinue;\n" + " \t\tpages += change_pud_range(vma, p4d, addr, next, newprot,\n" + "-\t\t\t\t dirty_accountable, prot_numa);\n" + "+\t\t\t\t dirty_accountable, prot_numa, mkwrite);\n" + " \t} while (p4d++, addr = next, addr != end);\n" + " \n" + " \treturn pages;\n" + "@@ -250,7 +275,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma,\n" + " \n" + " static unsigned long change_protection_range(struct vm_area_struct *vma,\n" + " \t\tunsigned long addr, unsigned long end, pgprot_t newprot,\n" + "-\t\tint dirty_accountable, int prot_numa)\n" + "+\t\tint dirty_accountable, int prot_numa, bool mkwrite)\n" + " {\n" + " \tstruct mm_struct *mm = vma->vm_mm;\n" + " \tpgd_t *pgd;\n" + "@@ -267,7 +292,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,\n" + " \t\tif (pgd_none_or_clear_bad(pgd))\n" + " \t\t\tcontinue;\n" + " \t\tpages += change_p4d_range(vma, pgd, addr, next, newprot,\n" + "-\t\t\t\t dirty_accountable, prot_numa);\n" + "+\t\t\t\t dirty_accountable, prot_numa, mkwrite);\n" + " \t} while (pgd++, addr = next, addr != end);\n" + " \n" + " \t/* Only flush the TLB if we actually modified any entries: */\n" + "@@ -280,14 +305,16 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,\n" + " \n" + " unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,\n" + " \t\t unsigned long end, pgprot_t newprot,\n" + "-\t\t int dirty_accountable, int prot_numa)\n" + "+\t\t int dirty_accountable, int prot_numa, bool mkwrite)\n" + " {\n" + " \tunsigned long pages;\n" + " \n" + " \tif (is_vm_hugetlb_page(vma))\n" + " \t\tpages = hugetlb_change_protection(vma, start, end, newprot);\n" + " \telse\n" + "-\t\tpages = change_protection_range(vma, start, end, newprot, dirty_accountable, prot_numa);\n" + "+\t\tpages = change_protection_range(vma, start, end, newprot,\n" + "+\t\t\t\t\t\tdirty_accountable,\n" + "+\t\t\t\t\t\tprot_numa, mkwrite);\n" + " \n" + " \treturn pages;\n" + " }\n" + "@@ -366,7 +393,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,\n" + " \tvma_set_page_prot(vma);\n" + " \n" + " \tchange_protection(vma, start, end, vma->vm_page_prot,\n" + "-\t\t\t dirty_accountable, 0);\n" + "+\t\t\t dirty_accountable, 0, false);\n" + " \n" + " \t/*\n" + " \t * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major\n" + "diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c\n" + "index a0379c5ffa7c..c745c5d87523 100644\n" + "--- a/mm/userfaultfd.c\n" + "+++ b/mm/userfaultfd.c\n" + "@@ -632,7 +632,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,\n" + " \t\tnewprot = vm_get_page_prot(dst_vma->vm_flags);\n" + " \n" + " \tchange_protection(dst_vma, start, start + len, newprot,\n" + "-\t\t\t\t!enable_wp, 0);\n" + "+\t\t\t 0, 0, !enable_wp);\n" + " \n" + " \terr = 0;\n" + " out_unlock:\n" + "diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c\n" + "index d6d65537b0d9..11c3425f272b 100644\n" + "--- a/tools/lib/str_error_r.c\n" + "+++ b/tools/lib/str_error_r.c\n" + "@@ -21,7 +21,12 @@\n" + " char *str_error_r(int errnum, char *buf, size_t buflen)\n" + " {\n" + " \tint err = strerror_r(errnum, buf, buflen);\n" + "-\tif (err)\n" + "-\t\tsnprintf(buf, buflen, \"INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d\", errnum, buf, buflen, err);\n" + "+\tif (err) {\n" + "+\t\tchar *err_buf = buf;\n" + "+\n" + "+\t\tsnprintf(err_buf, buflen,\n" + "+\t\t\t \"INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d\",\n" + "+\t\t\t errnum, buf, buflen, err);\n" + "+\t}\n" + " \treturn buf;\n" + " }\n" + "diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c\n" + "index 5ba754d17952..e1895568edaf 100644\n" + "--- a/tools/lib/subcmd/pager.c\n" + "+++ b/tools/lib/subcmd/pager.c\n" + "@@ -25,6 +25,8 @@ void pager_init(const char *pager_env)\n" + " \n" + " static void pager_preexec(void)\n" + " {\n" + "+\tvoid *ptr;\n" + "+\n" + " \t/*\n" + " \t * Work around bug in \"less\" by not starting it until we\n" + " \t * have real input\n" + "@@ -33,7 +35,8 @@ static void pager_preexec(void)\n" + " \n" + " \tFD_ZERO(&in);\n" + " \tFD_SET(0, &in);\n" + "-\tselect(1, &in, NULL, &in, NULL);\n" + "+\tptr = ∈\n" + "+\tselect(1, &in, NULL, ptr, NULL);\n" + " \n" + " \tsetenv(\"LESS\", \"FRSX\", 0);\n" + " }\n" + "-- \n" + 2.17.1 -c83aacbea110ce3f692a54a2beebafac89519aedc880ec1ef5e00670fe23c69a +472e62ad3026138e02619e53aa50f13500c2a83c87552cc9ea454d6ed7787df4
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.