The patch noted in the fixes below converted get_user_pages_fast() to get_user_pages_longterm(), however the two calls differ in a few ways. First _fast() is documented to not require the mmap_sem, while _longterm() is documented to need it. Hold the mmap sem as required. Second, _fast accepts an 'int write' while _longterm uses 'unsigned int gup_flags', so the expression '!!(prot & IOMMU_WRITE)' is only working by luck as FOLL_WRITE is currently == 0x1. Use the expected FOLL_WRITE constant instead. Fixes: 94db151dc892 ("vfio: disable filesystem-dax page pinning") Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx> --- drivers/vfio/vfio_iommu_type1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) I noticed this while trying to review some RDMA code that was touching our get_user_pages_longterm() call site and wanted to see what others are doing.. If someone can explain that get_user_pages_longterm() is safe to call without the mmap_sem held I'd love to here it! The comments in gup.c do seem to pretty clearly state the __get_user_pages_locked() called internally by get_user_pages_longterm() needs mmap_sem held.. This is confusing me because this is the only get_user_pages_longterm() callsite that doesn't hold the mmap_sem, and if it really isn't required I'd like to remove it from the RDMA code as well :) Thanks, Jason diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 2c75b33db4ac19..2612d63b1ba989 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -345,16 +345,17 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, struct vm_area_struct *vmas[1]; int ret; + down_read(&mm->mmap_sem); if (mm == current->mm) { - ret = get_user_pages_longterm(vaddr, 1, !!(prot & IOMMU_WRITE), - page, vmas); + ret = get_user_pages_longterm( + vaddr, 1, (prot & IOMMU_WRITE) ? FOLL_WRITE : 0, page, + vmas); } else { unsigned int flags = 0; if (prot & IOMMU_WRITE) flags |= FOLL_WRITE; - down_read(&mm->mmap_sem); ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page, vmas, NULL); /* @@ -368,8 +369,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, ret = -EOPNOTSUPP; put_page(page[0]); } - up_read(&mm->mmap_sem); } + up_read(&mm->mmap_sem); if (ret == 1) { *pfn = page_to_pfn(page[0]); -- 2.18.0