.. | .. |
---|
29 | 29 | * different type underlying the specified range of virtual addresses. |
---|
30 | 30 | * When the function isn't able to map a single page, it returns error. |
---|
31 | 31 | * |
---|
32 | | - * This function takes care of grabbing mmap_sem as necessary. |
---|
| 32 | + * This function takes care of grabbing mmap_lock as necessary. |
---|
33 | 33 | */ |
---|
34 | 34 | int get_vaddr_frames(unsigned long start, unsigned int nr_frames, |
---|
35 | 35 | unsigned int gup_flags, struct frame_vector *vec) |
---|
.. | .. |
---|
37 | 37 | struct mm_struct *mm = current->mm; |
---|
38 | 38 | struct vm_area_struct *vma; |
---|
39 | 39 | int ret = 0; |
---|
40 | | - int err; |
---|
41 | 40 | int locked; |
---|
42 | 41 | |
---|
43 | 42 | if (nr_frames == 0) |
---|
.. | .. |
---|
48 | 47 | |
---|
49 | 48 | start = untagged_addr(start); |
---|
50 | 49 | |
---|
51 | | - down_read(&mm->mmap_sem); |
---|
| 50 | + mmap_read_lock(mm); |
---|
52 | 51 | locked = 1; |
---|
53 | 52 | vma = find_vma_intersection(mm, start, start + 1); |
---|
54 | 53 | if (!vma) { |
---|
.. | .. |
---|
72 | 71 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) { |
---|
73 | 72 | vec->got_ref = true; |
---|
74 | 73 | vec->is_pfns = false; |
---|
75 | | - ret = get_user_pages_locked(start, nr_frames, |
---|
| 74 | + ret = pin_user_pages_locked(start, nr_frames, |
---|
76 | 75 | gup_flags, (struct page **)(vec->ptrs), &locked); |
---|
77 | | - goto out; |
---|
| 76 | + if (likely(ret > 0)) |
---|
| 77 | + goto out; |
---|
78 | 78 | } |
---|
79 | 79 | |
---|
80 | | - vec->got_ref = false; |
---|
81 | | - vec->is_pfns = true; |
---|
82 | | - do { |
---|
83 | | - unsigned long *nums = frame_vector_pfns(vec); |
---|
| 80 | + /* This used to (racily) return non-refcounted pfns. Let people know */ |
---|
| 81 | + WARN_ONCE(1, "get_vaddr_frames() cannot follow VM_IO mapping"); |
---|
| 82 | + vec->nr_frames = 0; |
---|
84 | 83 | |
---|
85 | | - while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) { |
---|
86 | | - err = follow_pfn(vma, start, &nums[ret]); |
---|
87 | | - if (err) { |
---|
88 | | - if (ret == 0) |
---|
89 | | - ret = err; |
---|
90 | | - goto out; |
---|
91 | | - } |
---|
92 | | - start += PAGE_SIZE; |
---|
93 | | - ret++; |
---|
94 | | - } |
---|
95 | | - /* |
---|
96 | | - * We stop if we have enough pages or if VMA doesn't completely |
---|
97 | | - * cover the tail page. |
---|
98 | | - */ |
---|
99 | | - if (ret >= nr_frames || start < vma->vm_end) |
---|
100 | | - break; |
---|
101 | | - vma = find_vma_intersection(mm, start, start + 1); |
---|
102 | | - } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP)); |
---|
103 | 84 | out: |
---|
104 | 85 | if (locked) |
---|
105 | | - up_read(&mm->mmap_sem); |
---|
| 86 | + mmap_read_unlock(mm); |
---|
106 | 87 | if (!ret) |
---|
107 | 88 | ret = -EFAULT; |
---|
108 | 89 | if (ret > 0) |
---|
.. | .. |
---|
122 | 103 | */ |
---|
123 | 104 | void put_vaddr_frames(struct frame_vector *vec) |
---|
124 | 105 | { |
---|
125 | | - int i; |
---|
126 | 106 | struct page **pages; |
---|
127 | 107 | |
---|
128 | 108 | if (!vec->got_ref) |
---|
.. | .. |
---|
135 | 115 | */ |
---|
136 | 116 | if (WARN_ON(IS_ERR(pages))) |
---|
137 | 117 | goto out; |
---|
138 | | - for (i = 0; i < vec->nr_frames; i++) |
---|
139 | | - put_page(pages[i]); |
---|
| 118 | + |
---|
| 119 | + unpin_user_pages(pages, vec->nr_frames); |
---|
140 | 120 | vec->got_ref = false; |
---|
141 | 121 | out: |
---|
142 | 122 | vec->nr_frames = 0; |
---|