aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-27 14:26:43 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-27 18:44:13 -0500
commit0dbca9a4b5d69a7e4b8c1d55b98312fcd9aafcf7 (patch)
treed20bc5e9981a5473177b62be7c85d28179a437d0
parentd271524a3a1da99e3809afaa10903cc2905bc9a7 (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.c106
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
145static 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
190static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, 145static 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
447static 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
489size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) 402size_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
498size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 411size_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}
505EXPORT_SYMBOL(copy_from_iter); 429EXPORT_SYMBOL(copy_from_iter);
506 430