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: 992de9a8b7 ("mm/hmm: allow to mirror vma of a file on a DAX backed filesystem")
Fixes: 53f5c3f489 ("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>
This commit is contained in:
Jason Gunthorpe 2020-02-28 15:30:37 -04:00
Родитель f8788d86ab
Коммит dfdc22078f
1 изменённых файлов: 6 добавлений и 2 удалений

Просмотреть файл

@ -325,6 +325,7 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
} }
/* Report error for everything else */ /* Report error for everything else */
pte_unmap(ptep);
*pfn = range->values[HMM_PFN_ERROR]; *pfn = range->values[HMM_PFN_ERROR];
return -EFAULT; return -EFAULT;
} else { } else {
@ -339,10 +340,13 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
if (pte_devmap(pte)) { if (pte_devmap(pte)) {
hmm_vma_walk->pgmap = get_dev_pagemap(pte_pfn(pte), hmm_vma_walk->pgmap = get_dev_pagemap(pte_pfn(pte),
hmm_vma_walk->pgmap); hmm_vma_walk->pgmap);
if (unlikely(!hmm_vma_walk->pgmap)) if (unlikely(!hmm_vma_walk->pgmap)) {
pte_unmap(ptep);
return -EBUSY; return -EBUSY;
}
} else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) { } else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
if (!is_zero_pfn(pte_pfn(pte))) { if (!is_zero_pfn(pte_pfn(pte))) {
pte_unmap(ptep);
*pfn = range->values[HMM_PFN_SPECIAL]; *pfn = range->values[HMM_PFN_SPECIAL];
return -EFAULT; return -EFAULT;
} }
@ -437,7 +441,7 @@ again:
r = hmm_vma_handle_pte(walk, addr, end, pmdp, ptep, &pfns[i]); r = hmm_vma_handle_pte(walk, addr, end, pmdp, ptep, &pfns[i]);
if (r) { if (r) {
/* hmm_vma_handle_pte() did unmap pte directory */ /* hmm_vma_handle_pte() did pte_unmap() */
hmm_vma_walk->last = addr; hmm_vma_walk->last = addr;
return r; return r;
} }