*
   * This function takes care of grabbing mmap_lock as necessary.
   */
- int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
+ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, bool write,
                     struct frame_vector *vec)
  {
 -      struct mm_struct *mm = current->mm;
 -      struct vm_area_struct *vma;
 -      int ret_pin_user_pages_fast = 0;
 -      int ret = 0;
 -      int err;
 +      int ret;
+       unsigned int gup_flags = FOLL_FORCE | FOLL_LONGTERM;
  
        if (nr_frames == 0)
                return 0;
  
        start = untagged_addr(start);
  
-       ret = pin_user_pages_fast(start, nr_frames,
-                                 FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM,
+       if (write)
+               gup_flags |= FOLL_WRITE;
+ 
+       ret = pin_user_pages_fast(start, nr_frames, gup_flags,
                                  (struct page **)(vec->ptrs));
 -      if (ret > 0) {
 -              vec->got_ref = true;
 -              vec->is_pfns = false;
 -              goto out_unlocked;
 -      }
 -      ret_pin_user_pages_fast = ret;
 +      vec->got_ref = true;
 +      vec->is_pfns = false;
 +      vec->nr_frames = ret;
  
 -      mmap_read_lock(mm);
 -      vec->got_ref = false;
 -      vec->is_pfns = true;
 -      ret = 0;
 -      do {
 -              unsigned long *nums = frame_vector_pfns(vec);
 +      if (likely(ret > 0))
 +              return ret;
  
 -              vma = vma_lookup(mm, start);
 -              if (!vma)
 -                      break;
 -
 -              while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
 -                      err = follow_pfn(vma, start, &nums[ret]);
 -                      if (err) {
 -                              if (ret)
 -                                      goto out;
 -                              // If follow_pfn() returns -EINVAL, then this
 -                              // is not an IO mapping or a raw PFN mapping.
 -                              // In that case, return the original error from
 -                              // pin_user_pages_fast(). Otherwise this
 -                              // function would return -EINVAL when
 -                              // pin_user_pages_fast() returned -ENOMEM,
 -                              // which makes debugging hard.
 -                              if (err == -EINVAL && ret_pin_user_pages_fast)
 -                                      ret = ret_pin_user_pages_fast;
 -                              else
 -                                      ret = err;
 -                              goto out;
 -                      }
 -                      start += PAGE_SIZE;
 -                      ret++;
 -              }
 -              /* Bail out if VMA doesn't completely cover the tail page. */
 -              if (start < vma->vm_end)
 -                      break;
 -      } while (ret < nr_frames);
 -out:
 -      mmap_read_unlock(mm);
 -out_unlocked:
 -      if (!ret)
 -              ret = -EFAULT;
 -      if (ret > 0)
 -              vec->nr_frames = ret;
 -      return ret;
 +      /* This used to (racily) return non-refcounted pfns. Let people know */
 +      WARN_ONCE(1, "get_vaddr_frames() cannot follow VM_IO mapping");
 +      vec->nr_frames = 0;
 +      return ret ? ret : -EFAULT;
  }
  EXPORT_SYMBOL(get_vaddr_frames);