nouveau: unlock mmap_sem on all errors from nouveau_range_fault
Currently nouveau_svm_fault expects nouveau_range_fault to never unlock mmap_sem, but the latter unlocks it for a random selection of error codes. Fix this up by always unlocking mmap_sem for non-zero return values in nouveau_range_fault, and only unlocking it in the caller for successful returns. Link: https://lore.kernel.org/r/20190724065258.16603-5-hch@lst.de Tested-by: Ralph Campbell <rcampbell@nvidia.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jason Gunthorpe <jgg@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
5fbcf5015d
commit
de4ee72846
@ -495,8 +495,10 @@ nouveau_range_fault(struct hmm_mirror *mirror, struct hmm_range *range)
|
||||
ret = hmm_range_register(range, mirror,
|
||||
range->start, range->end,
|
||||
PAGE_SHIFT);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
up_read(&range->vma->vm_mm->mmap_sem);
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
|
||||
up_read(&range->vma->vm_mm->mmap_sem);
|
||||
@ -505,10 +507,9 @@ nouveau_range_fault(struct hmm_mirror *mirror, struct hmm_range *range)
|
||||
|
||||
ret = hmm_range_fault(range, true);
|
||||
if (ret <= 0) {
|
||||
if (ret == -EBUSY || !ret) {
|
||||
up_read(&range->vma->vm_mm->mmap_sem);
|
||||
if (ret == 0)
|
||||
ret = -EBUSY;
|
||||
}
|
||||
up_read(&range->vma->vm_mm->mmap_sem);
|
||||
hmm_range_unregister(range);
|
||||
return ret;
|
||||
}
|
||||
@ -706,8 +707,8 @@ again:
|
||||
NULL);
|
||||
svmm->vmm->vmm.object.client->super = false;
|
||||
mutex_unlock(&svmm->mutex);
|
||||
up_read(&svmm->mm->mmap_sem);
|
||||
}
|
||||
up_read(&svmm->mm->mmap_sem);
|
||||
|
||||
/* Cancel any faults in the window whose pages didn't manage
|
||||
* to keep their valid bit, or stay writeable when required.
|
||||
|
Loading…
Reference in New Issue
Block a user