diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 14:26:43 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 18:44:13 -0500 |
commit | 0dbca9a4b5d69a7e4b8c1d55b98312fcd9aafcf7 (patch) | |
tree | d20bc5e9981a5473177b62be7c85d28179a437d0 | |
parent | d271524a3a1da99e3809afaa10903cc2905bc9a7 (diff) |
iov_iter.c: convert copy_from_iter() to iterate_and_advance
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | mm/iov_iter.c | 106 |
1 files changed, 15 insertions, 91 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c index 17b7144c3165..791429d07965 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c | |||
@@ -142,51 +142,6 @@ static size_t copy_to_iter_iovec(void *from, size_t bytes, struct iov_iter *i) | |||
142 | return wanted - bytes; | 142 | return wanted - bytes; |
143 | } | 143 | } |
144 | 144 | ||
145 | static size_t copy_from_iter_iovec(void *to, size_t bytes, struct iov_iter *i) | ||
146 | { | ||
147 | size_t skip, copy, left, wanted; | ||
148 | const struct iovec *iov; | ||
149 | char __user *buf; | ||
150 | |||
151 | if (unlikely(bytes > i->count)) | ||
152 | bytes = i->count; | ||
153 | |||
154 | if (unlikely(!bytes)) | ||
155 | return 0; | ||
156 | |||
157 | wanted = bytes; | ||
158 | iov = i->iov; | ||
159 | skip = i->iov_offset; | ||
160 | buf = iov->iov_base + skip; | ||
161 | copy = min(bytes, iov->iov_len - skip); | ||
162 | |||
163 | left = __copy_from_user(to, buf, copy); | ||
164 | copy -= left; | ||
165 | skip += copy; | ||
166 | to += copy; | ||
167 | bytes -= copy; | ||
168 | while (unlikely(!left && bytes)) { | ||
169 | iov++; | ||
170 | buf = iov->iov_base; | ||
171 | copy = min(bytes, iov->iov_len); | ||
172 | left = __copy_from_user(to, buf, copy); | ||
173 | copy -= left; | ||
174 | skip = copy; | ||
175 | to += copy; | ||
176 | bytes -= copy; | ||
177 | } | ||
178 | |||
179 | if (skip == iov->iov_len) { | ||
180 | iov++; | ||
181 | skip = 0; | ||
182 | } | ||
183 | i->count -= wanted - bytes; | ||
184 | i->nr_segs -= iov - i->iov; | ||
185 | i->iov = iov; | ||
186 | i->iov_offset = skip; | ||
187 | return wanted - bytes; | ||
188 | } | ||
189 | |||
190 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, | 145 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, |
191 | struct iov_iter *i) | 146 | struct iov_iter *i) |
192 | { | 147 | { |
@@ -444,48 +399,6 @@ static size_t copy_to_iter_bvec(void *from, size_t bytes, struct iov_iter *i) | |||
444 | return wanted - bytes; | 399 | return wanted - bytes; |
445 | } | 400 | } |
446 | 401 | ||
447 | static size_t copy_from_iter_bvec(void *to, size_t bytes, struct iov_iter *i) | ||
448 | { | ||
449 | size_t skip, copy, wanted; | ||
450 | const struct bio_vec *bvec; | ||
451 | |||
452 | if (unlikely(bytes > i->count)) | ||
453 | bytes = i->count; | ||
454 | |||
455 | if (unlikely(!bytes)) | ||
456 | return 0; | ||
457 | |||
458 | wanted = bytes; | ||
459 | bvec = i->bvec; | ||
460 | skip = i->iov_offset; | ||
461 | |||
462 | copy = min(bytes, bvec->bv_len - skip); | ||
463 | |||
464 | memcpy_from_page(to, bvec->bv_page, bvec->bv_offset + skip, copy); | ||
465 | |||
466 | to += copy; | ||
467 | skip += copy; | ||
468 | bytes -= copy; | ||
469 | |||
470 | while (bytes) { | ||
471 | bvec++; | ||
472 | copy = min(bytes, (size_t)bvec->bv_len); | ||
473 | memcpy_from_page(to, bvec->bv_page, bvec->bv_offset, copy); | ||
474 | skip = copy; | ||
475 | to += copy; | ||
476 | bytes -= copy; | ||
477 | } | ||
478 | if (skip == bvec->bv_len) { | ||
479 | bvec++; | ||
480 | skip = 0; | ||
481 | } | ||
482 | i->count -= wanted; | ||
483 | i->nr_segs -= bvec - i->bvec; | ||
484 | i->bvec = bvec; | ||
485 | i->iov_offset = skip; | ||
486 | return wanted; | ||
487 | } | ||
488 | |||
489 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) | 402 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) |
490 | { | 403 | { |
491 | if (i->type & ITER_BVEC) | 404 | if (i->type & ITER_BVEC) |
@@ -497,10 +410,21 @@ EXPORT_SYMBOL(copy_to_iter); | |||
497 | 410 | ||
498 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | 411 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) |
499 | { | 412 | { |
500 | if (i->type & ITER_BVEC) | 413 | char *to = addr; |
501 | return copy_from_iter_bvec(addr, bytes, i); | 414 | if (unlikely(bytes > i->count)) |
502 | else | 415 | bytes = i->count; |
503 | return copy_from_iter_iovec(addr, bytes, i); | 416 | |
417 | if (unlikely(!bytes)) | ||
418 | return 0; | ||
419 | |||
420 | iterate_and_advance(i, bytes, v, | ||
421 | __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, | ||
422 | v.iov_len), | ||
423 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | ||
424 | v.bv_offset, v.bv_len) | ||
425 | ) | ||
426 | |||
427 | return bytes; | ||
504 | } | 428 | } |
505 | EXPORT_SYMBOL(copy_from_iter); | 429 | EXPORT_SYMBOL(copy_from_iter); |
506 | 430 | ||