diff options
Diffstat (limited to 'mm/process_vm_access.c')
-rw-r--r-- | mm/process_vm_access.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index c2a1916bacbf..83252d783482 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c | |||
@@ -41,20 +41,22 @@ | |||
41 | */ | 41 | */ |
42 | static int process_vm_rw_pages(struct page **pages, | 42 | static int process_vm_rw_pages(struct page **pages, |
43 | unsigned offset, | 43 | unsigned offset, |
44 | unsigned long len, | 44 | size_t len, |
45 | struct iov_iter *iter, | 45 | struct iov_iter *iter, |
46 | int vm_write, | 46 | int vm_write, |
47 | unsigned int nr_pages_to_copy, | ||
48 | ssize_t *bytes_copied) | 47 | ssize_t *bytes_copied) |
49 | { | 48 | { |
50 | *bytes_copied = 0; | 49 | *bytes_copied = 0; |
51 | 50 | ||
52 | /* Do the copy for each page */ | 51 | /* Do the copy for each page */ |
53 | while (iov_iter_count(iter) && nr_pages_to_copy--) { | 52 | while (iov_iter_count(iter) && len) { |
54 | struct page *page = *pages++; | 53 | struct page *page = *pages++; |
55 | size_t copy = min_t(ssize_t, PAGE_SIZE - offset, len); | 54 | size_t copy = PAGE_SIZE - offset; |
56 | size_t copied; | 55 | size_t copied; |
57 | 56 | ||
57 | if (copy > len) | ||
58 | copy = len; | ||
59 | |||
58 | if (vm_write) { | 60 | if (vm_write) { |
59 | if (copy > iov_iter_count(iter)) | 61 | if (copy > iov_iter_count(iter)) |
60 | copy = iov_iter_count(iter); | 62 | copy = iov_iter_count(iter); |
@@ -121,6 +123,7 @@ static int process_vm_rw_single_vec(unsigned long addr, | |||
121 | while ((nr_pages_copied < nr_pages) && iov_iter_count(iter)) { | 123 | while ((nr_pages_copied < nr_pages) && iov_iter_count(iter)) { |
122 | int nr_pages_to_copy; | 124 | int nr_pages_to_copy; |
123 | int pages_pinned; | 125 | int pages_pinned; |
126 | size_t n; | ||
124 | nr_pages_to_copy = min(nr_pages - nr_pages_copied, | 127 | nr_pages_to_copy = min(nr_pages - nr_pages_copied, |
125 | max_pages_per_loop); | 128 | max_pages_per_loop); |
126 | 129 | ||
@@ -134,18 +137,21 @@ static int process_vm_rw_single_vec(unsigned long addr, | |||
134 | if (pages_pinned <= 0) | 137 | if (pages_pinned <= 0) |
135 | return -EFAULT; | 138 | return -EFAULT; |
136 | 139 | ||
140 | n = pages_pinned * PAGE_SIZE - start_offset; | ||
141 | if (n > len) | ||
142 | n = len; | ||
143 | |||
137 | rc = process_vm_rw_pages(process_pages, | 144 | rc = process_vm_rw_pages(process_pages, |
138 | start_offset, len, iter, | 145 | start_offset, n, iter, |
139 | vm_write, pages_pinned, | 146 | vm_write, |
140 | &bytes_copied_loop); | 147 | &bytes_copied_loop); |
148 | len -= n; | ||
141 | start_offset = 0; | 149 | start_offset = 0; |
142 | *bytes_copied += bytes_copied_loop; | 150 | *bytes_copied += bytes_copied_loop; |
143 | len -= bytes_copied_loop; | ||
144 | nr_pages_copied += pages_pinned; | 151 | nr_pages_copied += pages_pinned; |
145 | pa += pages_pinned * PAGE_SIZE; | 152 | pa += pages_pinned * PAGE_SIZE; |
146 | while (pages_pinned) | 153 | while (pages_pinned) |
147 | put_page(process_pages[--pages_pinned]); | 154 | put_page(process_pages[--pages_pinned]); |
148 | |||
149 | if (rc < 0) | 155 | if (rc < 0) |
150 | break; | 156 | break; |
151 | } | 157 | } |