diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 14:28:06 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 18:44:14 -0500 |
commit | 3d4d3e48264e24d9beb373bd0428b69889ac11ea (patch) | |
tree | 15ae8f0e3a1424e517e7514b03b915df33fffc8f /mm/iov_iter.c | |
parent | 0dbca9a4b5d69a7e4b8c1d55b98312fcd9aafcf7 (diff) |
iov_iter.c: convert copy_to_iter() to iterate_and_advance
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm/iov_iter.c')
-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 | ||