aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-27 14:09:46 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-27 18:44:11 -0500
commite0f2dc4061e6238905001e8ec6c88b15c2e3b950 (patch)
tree7fa4f2829d8ae5e26099679cb649f911bf8b16ff
parent7ce2a91e51288f308bfe5ea7e5743517c15c8e25 (diff)
iov_iter.c: convert iov_iter_npages() to iterate_all_kinds
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--mm/iov_iter.c73
1 files changed, 19 insertions, 54 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c
index e91bf0accc47..bc666e79b5bd 100644
--- a/mm/iov_iter.c
+++ b/mm/iov_iter.c
@@ -493,32 +493,6 @@ static ssize_t get_pages_alloc_iovec(struct iov_iter *i,
493 return (res == n ? len : res * PAGE_SIZE) - *start; 493 return (res == n ? len : res * PAGE_SIZE) - *start;
494} 494}
495 495
496static int iov_iter_npages_iovec(const struct iov_iter *i, int maxpages)
497{
498 size_t offset = i->iov_offset;
499 size_t size = i->count;
500 const struct iovec *iov = i->iov;
501 int npages = 0;
502 int n;
503
504 for (n = 0; size && n < i->nr_segs; n++, iov++) {
505 unsigned long addr = (unsigned long)iov->iov_base + offset;
506 size_t len = iov->iov_len - offset;
507 offset = 0;
508 if (unlikely(!len)) /* empty segment */
509 continue;
510 if (len > size)
511 len = size;
512 npages += (addr + len + PAGE_SIZE - 1) / PAGE_SIZE
513 - addr / PAGE_SIZE;
514 if (npages >= maxpages) /* don't bother going further */
515 return maxpages;
516 size -= len;
517 offset = 0;
518 }
519 return min(npages, maxpages);
520}
521
522static void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) 496static void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len)
523{ 497{
524 char *from = kmap_atomic(page); 498 char *from = kmap_atomic(page);
@@ -715,30 +689,6 @@ static ssize_t get_pages_alloc_bvec(struct iov_iter *i,
715 return len; 689 return len;
716} 690}
717 691
718static int iov_iter_npages_bvec(const struct iov_iter *i, int maxpages)
719{
720 size_t offset = i->iov_offset;
721 size_t size = i->count;
722 const struct bio_vec *bvec = i->bvec;
723 int npages = 0;
724 int n;
725
726 for (n = 0; size && n < i->nr_segs; n++, bvec++) {
727 size_t len = bvec->bv_len - offset;
728 offset = 0;
729 if (unlikely(!len)) /* empty segment */
730 continue;
731 if (len > size)
732 len = size;
733 npages++;
734 if (npages >= maxpages) /* don't bother going further */
735 return maxpages;
736 size -= len;
737 offset = 0;
738 }
739 return min(npages, maxpages);
740}
741
742size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 692size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
743 struct iov_iter *i) 693 struct iov_iter *i)
744{ 694{
@@ -862,9 +812,24 @@ EXPORT_SYMBOL(iov_iter_get_pages_alloc);
862 812
863int iov_iter_npages(const struct iov_iter *i, int maxpages) 813int iov_iter_npages(const struct iov_iter *i, int maxpages)
864{ 814{
865 if (i->type & ITER_BVEC) 815 size_t size = i->count;
866 return iov_iter_npages_bvec(i, maxpages); 816 int npages = 0;
867 else 817
868 return iov_iter_npages_iovec(i, maxpages); 818 if (!size)
819 return 0;
820
821 iterate_all_kinds(i, size, v, ({
822 unsigned long p = (unsigned long)v.iov_base;
823 npages += DIV_ROUND_UP(p + v.iov_len, PAGE_SIZE)
824 - p / PAGE_SIZE;
825 if (npages >= maxpages)
826 return maxpages;
827 0;}),({
828 npages++;
829 if (npages >= maxpages)
830 return maxpages;
831 })
832 )
833 return npages;
869} 834}
870EXPORT_SYMBOL(iov_iter_npages); 835EXPORT_SYMBOL(iov_iter_npages);