This is a note to let you know that I've just added the patch titled vfio/type1: Change success value of vaddr_get_pfn() to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: vfio-type1-change-success-value-of-vaddr_get_pfn.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 20bfdcd0744517441b99b14570d7ee4d9deb16e6 Author: Daniel Jordan <daniel.m.jordan@xxxxxxxxxx> Date: Fri Feb 19 11:13:03 2021 -0500 vfio/type1: Change success value of vaddr_get_pfn() [ Upstream commit be16c1fd99f41abebc0bf965d5d29cd18c9d271e ] vaddr_get_pfn() simply returns 0 on success. Have it report the number of pfns successfully gotten instead, whether from page pinning or follow_fault_pfn(), which will be used later when batching pinning. Change the last check in vfio_pin_pages_remote() for consistency with the other two. Signed-off-by: Daniel Jordan <daniel.m.jordan@xxxxxxxxxx> Signed-off-by: Alex Williamson <alex.williamson@xxxxxxxxxx> Stable-dep-of: 873aefb376bb ("vfio/type1: Unpin zero pages") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index fbd438e9b9b0..2d26244f9c32 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -464,6 +464,10 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, return ret; } +/* + * Returns the positive number of pfns successfully obtained or a negative + * error code. + */ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, int prot, unsigned long *pfn) { @@ -480,7 +484,6 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, page, NULL, NULL); if (ret == 1) { *pfn = page_to_pfn(page[0]); - ret = 0; goto done; } @@ -494,8 +497,12 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, if (ret == -EAGAIN) goto retry; - if (!ret && !is_invalid_reserved_pfn(*pfn)) - ret = -EFAULT; + if (!ret) { + if (is_invalid_reserved_pfn(*pfn)) + ret = 1; + else + ret = -EFAULT; + } } done: mmap_read_unlock(mm); @@ -521,7 +528,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, return -ENODEV; ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, pfn_base); - if (ret) + if (ret < 0) return ret; pinned++; @@ -548,7 +555,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; pinned < npage; pinned++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) { ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, &pfn); - if (ret) + if (ret < 0) break; if (pfn != *pfn_base + pinned || @@ -574,7 +581,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, ret = vfio_lock_acct(dma, lock_acct, false); unpin_out: - if (ret) { + if (ret < 0) { if (!rsvd) { for (pfn = *pfn_base ; pinned ; pfn++, pinned--) put_pfn(pfn, dma->prot); @@ -618,7 +625,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr, return -ENODEV; ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base); - if (!ret && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) { + if (ret == 1 && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) { ret = vfio_lock_acct(dma, 1, true); if (ret) { put_pfn(*pfn_base, dma->prot);