diff options
| -rw-r--r-- | mm/iov_iter.c | 91 |
1 files changed, 9 insertions, 82 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c index 791429d07965..666654498ccf 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c | |||
| @@ -97,51 +97,6 @@ | |||
| 97 | i->iov_offset = skip; \ | 97 | i->iov_offset = skip; \ |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static size_t copy_to_iter_iovec(void *from, size_t bytes, struct iov_iter *i) | ||
| 101 | { | ||
| 102 | size_t skip, copy, left, wanted; | ||
| 103 | const struct iovec *iov; | ||
| 104 | char __user *buf; | ||
| 105 | |||
| 106 | if (unlikely(bytes > i->count)) | ||
| 107 | bytes = i->count; | ||
| 108 | |||
| 109 | if (unlikely(!bytes)) | ||
| 110 | return 0; | ||
| 111 | |||
| 112 | wanted = bytes; | ||
| 113 | iov = i->iov; | ||
| 114 | skip = i->iov_offset; | ||
| 115 | buf = iov->iov_base + skip; | ||
| 116 | copy = min(bytes, iov->iov_len - skip); | ||
| 117 | |||
| 118 | left = __copy_to_user(buf, from, copy); | ||
| 119 | copy -= left; | ||
| 120 | skip += copy; | ||
| 121 | from += copy; | ||
| 122 | bytes -= copy; | ||
| 123 | while (unlikely(!left && bytes)) { | ||
| 124 | iov++; | ||
| 125 | buf = iov->iov_base; | ||
| 126 | copy = min(bytes, iov->iov_len); | ||
| 127 | left = __copy_to_user(buf, from, copy); | ||
| 128 | copy -= left; | ||
| 129 | skip = copy; | ||
| 130 | from += copy; | ||
| 131 | bytes -= copy; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (skip == iov->iov_len) { | ||
| 135 | iov++; | ||
| 136 | skip = 0; | ||
| 137 | } | ||
| 138 | i->count -= wanted - bytes; | ||
| 139 | i->nr_segs -= iov - i->iov; | ||
| 140 | i->iov = iov; | ||
| 141 | i->iov_offset = skip; | ||
| 142 | return wanted - bytes; | ||
| 143 | } | ||
| 144 | |||
| 145 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, | 100 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, |
| 146 | struct iov_iter *i) | 101 | struct iov_iter *i) |
| 147 | { | 102 | { |
| @@ -360,51 +315,23 @@ static void memzero_page(struct page *page, size_t offset, size_t len) | |||
| 360 | kunmap_atomic(addr); | 315 | kunmap_atomic(addr); |
| 361 | } | 316 | } |
| 362 | 317 | ||
| 363 | static size_t copy_to_iter_bvec(void *from, size_t bytes, struct iov_iter *i) | 318 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) |
| 364 | { | 319 | { |
| 365 | size_t skip, copy, wanted; | 320 | char *from = addr; |
| 366 | const struct bio_vec *bvec; | ||
| 367 | |||
| 368 | if (unlikely(bytes > i->count)) | 321 | if (unlikely(bytes > i->count)) |
| 369 | bytes = i->count; | 322 | bytes = i->count; |
| 370 | 323 | ||
| 371 | if (unlikely(!bytes)) | 324 | if (unlikely(!bytes)) |
| 372 | return 0; | 325 | return 0; |
| 373 | 326 | ||
| 374 | wanted = bytes; | 327 | iterate_and_advance(i, bytes, v, |
| 375 | bvec = i->bvec; | 328 | __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, |
| 376 | skip = i->iov_offset; | 329 | v.iov_len), |
| 377 | copy = min_t(size_t, bytes, bvec->bv_len - skip); | 330 | memcpy_to_page(v.bv_page, v.bv_offset, |
| 378 | 331 | (from += v.bv_len) - v.bv_len, v.bv_len) | |
| 379 | memcpy_to_page(bvec->bv_page, skip + bvec->bv_offset, from, copy); | 332 | ) |
| 380 | skip += copy; | ||
| 381 | from += copy; | ||
| 382 | bytes -= copy; | ||
| 383 | while (bytes) { | ||
| 384 | bvec++; | ||
| 385 | copy = min(bytes, (size_t)bvec->bv_len); | ||
| 386 | memcpy_to_page(bvec->bv_page, bvec->bv_offset, from, copy); | ||
| 387 | skip = copy; | ||
| 388 | from += copy; | ||
| 389 | bytes -= copy; | ||
| 390 | } | ||
| 391 | if (skip == bvec->bv_len) { | ||
| 392 | bvec++; | ||
| 393 | skip = 0; | ||
| 394 | } | ||
| 395 | i->count -= wanted - bytes; | ||
| 396 | i->nr_segs -= bvec - i->bvec; | ||
| 397 | i->bvec = bvec; | ||
| 398 | i->iov_offset = skip; | ||
| 399 | return wanted - bytes; | ||
| 400 | } | ||
| 401 | 333 | ||
| 402 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) | 334 | return bytes; |
| 403 | { | ||
| 404 | if (i->type & ITER_BVEC) | ||
| 405 | return copy_to_iter_bvec(addr, bytes, i); | ||
| 406 | else | ||
| 407 | return copy_to_iter_iovec(addr, bytes, i); | ||
| 408 | } | 335 | } |
| 409 | EXPORT_SYMBOL(copy_to_iter); | 336 | EXPORT_SYMBOL(copy_to_iter); |
| 410 | 337 | ||
