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 | ||
