diff options
author | Jason Gunthorpe <jgg@mellanox.com> | 2020-02-28 15:30:37 -0400 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2020-03-26 14:33:37 -0300 |
commit | dfdc22078f3f064d2659acdc42d886834f3a3863 (patch) | |
tree | 4f1075acec97ffc965f156d6105e966ccea95efb /mm/hmm.c | |
parent | f8788d86ab28f61f7b46eb6be375f8a726783636 (diff) | |
download | linux-dfdc22078f3f064d2659acdc42d886834f3a3863.tar.gz linux-dfdc22078f3f064d2659acdc42d886834f3a3863.tar.bz2 linux-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>
Diffstat (limited to 'mm/hmm.c')
-rw-r--r-- | mm/hmm.c | 8 |
1 files changed, 6 insertions, 2 deletions
@@ -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; } |