Commit 05fc1df9 authored by Jason Gunthorpe's avatar Jason Gunthorpe

mm/hmm: do not call hmm_vma_walk_hole() while holding a spinlock

This eventually calls into handle_mm_fault() which is a sleeping function.
Release the lock first.

hmm_vma_walk_hole() does not touch the contents of the PUD, so it does not
need the lock.

Fixes: 3afc4236 ("mm: pagewalk: add p4d_entry() and pgd_entry()")
Cc: Steven Price <steven.price@arm.com>
Reviewed-by: default avatarRalph Campbell <rcampbell@nvidia.com>
Reviewed-by: default avatarSteven Price <steven.price@arm.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent dfdc2207
...@@ -491,8 +491,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, ...@@ -491,8 +491,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end,
pud = READ_ONCE(*pudp); pud = READ_ONCE(*pudp);
if (pud_none(pud)) { if (pud_none(pud)) {
ret = hmm_vma_walk_hole(start, end, -1, walk); spin_unlock(ptl);
goto out_unlock; return hmm_vma_walk_hole(start, end, -1, walk);
} }
if (pud_huge(pud) && pud_devmap(pud)) { if (pud_huge(pud) && pud_devmap(pud)) {
...@@ -501,8 +501,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, ...@@ -501,8 +501,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end,
bool fault, write_fault; bool fault, write_fault;
if (!pud_present(pud)) { if (!pud_present(pud)) {
ret = hmm_vma_walk_hole(start, end, -1, walk); spin_unlock(ptl);
goto out_unlock; return hmm_vma_walk_hole(start, end, -1, walk);
} }
i = (addr - range->start) >> PAGE_SHIFT; i = (addr - range->start) >> PAGE_SHIFT;
...@@ -513,9 +513,9 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, ...@@ -513,9 +513,9 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end,
hmm_range_need_fault(hmm_vma_walk, pfns, npages, hmm_range_need_fault(hmm_vma_walk, pfns, npages,
cpu_flags, &fault, &write_fault); cpu_flags, &fault, &write_fault);
if (fault || write_fault) { if (fault || write_fault) {
ret = hmm_vma_walk_hole_(addr, end, fault, spin_unlock(ptl);
write_fault, walk); return hmm_vma_walk_hole_(addr, end, fault, write_fault,
goto out_unlock; walk);
} }
pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment