This is a note to let you know that I've just added the patch titled mm: add follow_pte_pmd() to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: mm-add-follow_pte_pmd.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Mon Jan 24 07:28:36 PM CET 2022 From: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Date: Mon, 24 Jan 2022 17:41:12 +0100 Subject: mm: add follow_pte_pmd() To: stable@xxxxxxxxxxxxxxx Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx>, Ross Zwisler <ross.zwisler@xxxxxxxxxxxxxxx>, ". Andrew Morton" <akpm@xxxxxxxxxxxxxxxxxxxx> Message-ID: <Ye7WqMoYNyxOqWId@xxxxxxxxxxxxxxx> Content-Disposition: inline From: Ross Zwisler <ross.zwisler@xxxxxxxxxxxxxxx> commit 097963959594c5eccaba42510f7033f703211bda upstream. Patch series "Write protect DAX PMDs in *sync path". Currently dax_mapping_entry_mkclean() fails to clean and write protect the pmd_t of a DAX PMD entry during an *sync operation. This can result in data loss, as detailed in patch 2. This series is based on Dan's "libnvdimm-pending" branch, which is the current home for Jan's "dax: Page invalidation fixes" series. You can find a working tree here: https://git.kernel.org/cgit/linux/kernel/git/zwisler/linux.git/log/?h=dax_pmd_clean This patch (of 2): Similar to follow_pte(), follow_pte_pmd() allows either a PTE leaf or a huge page PMD leaf to be found and returned. Link: http://lkml.kernel.org/r/1482272586-21177-2-git-send-email-ross.zwisler@xxxxxxxxxxxxxxx Signed-off-by: Ross Zwisler <ross.zwisler@xxxxxxxxxxxxxxx> Suggested-by: Dave Hansen <dave.hansen@xxxxxxxxx> Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Dan Williams <dan.j.williams@xxxxxxxxx> Cc: Dave Chinner <david@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> [bwh: Backported to 4.9: adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- include/linux/mm.h | 2 ++ mm/memory.c | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-) --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1269,6 +1269,8 @@ int copy_page_range(struct mm_struct *ds struct vm_area_struct *vma); void unmap_mapping_range(struct address_space *mapping, loff_t const holebegin, loff_t const holelen, int even_cows); +int follow_pte_pmd(struct mm_struct *mm, unsigned long address, + pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp); int follow_pfn(struct vm_area_struct *vma, unsigned long address, unsigned long *pfn); int follow_phys(struct vm_area_struct *vma, unsigned long address, --- a/mm/memory.c +++ b/mm/memory.c @@ -3780,8 +3780,8 @@ int __pmd_alloc(struct mm_struct *mm, pu } #endif /* __PAGETABLE_PMD_FOLDED */ -static int __follow_pte(struct mm_struct *mm, unsigned long address, - pte_t **ptepp, spinlock_t **ptlp) +static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address, + pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp) { pgd_t *pgd; pud_t *pud; @@ -3798,11 +3798,20 @@ static int __follow_pte(struct mm_struct pmd = pmd_offset(pud, address); VM_BUG_ON(pmd_trans_huge(*pmd)); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - goto out; - /* We cannot handle huge page PFN maps. Luckily they don't exist. */ - if (pmd_huge(*pmd)) + if (pmd_huge(*pmd)) { + if (!pmdpp) + goto out; + + *ptlp = pmd_lock(mm, pmd); + if (pmd_huge(*pmd)) { + *pmdpp = pmd; + return 0; + } + spin_unlock(*ptlp); + } + + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) goto out; ptep = pte_offset_map_lock(mm, pmd, address, ptlp); @@ -3825,9 +3834,23 @@ static inline int follow_pte(struct mm_s /* (void) is needed to make gcc happy */ (void) __cond_lock(*ptlp, - !(res = __follow_pte(mm, address, ptepp, ptlp))); + !(res = __follow_pte_pmd(mm, address, ptepp, NULL, + ptlp))); + return res; +} + +int follow_pte_pmd(struct mm_struct *mm, unsigned long address, + pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp) +{ + int res; + + /* (void) is needed to make gcc happy */ + (void) __cond_lock(*ptlp, + !(res = __follow_pte_pmd(mm, address, ptepp, pmdpp, + ptlp))); return res; } +EXPORT_SYMBOL(follow_pte_pmd); /** * follow_pfn - look up PFN at a user virtual address Patches currently in stable-queue which might be from ben@xxxxxxxxxxxxxxx are queue-4.9/lib-timerqueue-rely-on-rbtree-semantics-for-next-timer.patch queue-4.9/gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/fuse-fix-live-lock-in-fuse_iget.patch queue-4.9/kvm-do-not-assume-pte-is-writable-after-follow_pfn.patch queue-4.9/drm-ttm-nouveau-don-t-call-tt-destroy-callback-on-alloc-failure.patch queue-4.9/gianfar-simplify-fcs-handling-and-fix-memory-leak.patch queue-4.9/mm-add-follow_pte_pmd.patch queue-4.9/revert-gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/gianfar-fix-jumbo-packets-napi-rx-overrun-crash.patch queue-4.9/cipso-calipso-resolve-a-number-of-problems-with-the-doi-refcounts.patch queue-4.9/rbtree-cache-leftmost-node-internally.patch queue-4.9/kvm-use-kvm_pfn_t-for-local-pfn-variable-in-hva_to_pfn_remapped.patch queue-4.9/kvm-do-not-allow-mapping-valid-but-non-reference-counted-pages.patch queue-4.9/fuse-fix-bad-inode.patch