summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2020-02-28 15:30:37 -0400
committerJason Gunthorpe <jgg@mellanox.com>2020-03-26 14:33:37 -0300
commitdfdc22078f3f064d2659acdc42d886834f3a3863 (patch)
tree4f1075acec97ffc965f156d6105e966ccea95efb
parentf8788d86ab28f61f7b46eb6be375f8a726783636 (diff)
downloadlwn-dfdc22078f3f064d2659acdc42d886834f3a3863.tar.gz
lwn-dfdc22078f3f064d2659acdc42d886834f3a3863.zip
mm/hmm: add missing unmaps of the ptep during hmm_vma_handle_pte()
Many of the direct returns of error skipped doing the pte_unmap(). All non zero exit paths must unmap the pte. The pte_unmap() is split unnaturally like this because some of the error exit paths trigger a sleep and must release the lock before sleeping. Fixes: 992de9a8b751 ("mm/hmm: allow to mirror vma of a file on a DAX backed filesystem") Fixes: 53f5c3f489ec ("mm/hmm: factor out pte and pmd handling to simplify hmm_vma_walk_pmd()") Reviewed-by: Ralph Campbell <rcampbell@nvidia.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--mm/hmm.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/mm/hmm.c b/mm/hmm.c
index 72e5a6d9a417..35f85424176d 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -325,6 +325,7 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
}
/* Report error for everything else */
+ pte_unmap(ptep);
*pfn = range->values[HMM_PFN_ERROR];
return -EFAULT;
} else {
@@ -339,10 +340,13 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
if (pte_devmap(pte)) {
hmm_vma_walk->pgmap = get_dev_pagemap(pte_pfn(pte),
hmm_vma_walk->pgmap);
- if (unlikely(!hmm_vma_walk->pgmap))
+ if (unlikely(!hmm_vma_walk->pgmap)) {
+ pte_unmap(ptep);
return -EBUSY;
+ }
} else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
if (!is_zero_pfn(pte_pfn(pte))) {
+ pte_unmap(ptep);
*pfn = range->values[HMM_PFN_SPECIAL];
return -EFAULT;
}
@@ -437,7 +441,7 @@ again:
r = hmm_vma_handle_pte(walk, addr, end, pmdp, ptep, &pfns[i]);
if (r) {
- /* hmm_vma_handle_pte() did unmap pte directory */
+ /* hmm_vma_handle_pte() did pte_unmap() */
hmm_vma_walk->last = addr;
return r;
}