aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-27 14:12:09 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-27 18:44:11 -0500
commite5393fae3b49e80179f04afdc0916fcb6846ef17 (patch)
treef8b7b3671770767e9b1429dd49fc45904d4ae54e
parente0f2dc4061e6238905001e8ec6c88b15c2e3b950 (diff)
iov_iter.c: convert iov_iter_get_pages() to iterate_all_kinds
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--mm/iov_iter.c78
1 files changed, 28 insertions, 50 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c
index bc666e79b5bd..75e29ef59b0e 100644
--- a/mm/iov_iter.c
+++ b/mm/iov_iter.c
@@ -428,34 +428,6 @@ void iov_iter_init(struct iov_iter *i, int direction,
428} 428}
429EXPORT_SYMBOL(iov_iter_init); 429EXPORT_SYMBOL(iov_iter_init);
430 430
431static ssize_t get_pages_iovec(struct iov_iter *i,
432 struct page **pages, size_t maxsize, unsigned maxpages,
433 size_t *start)
434{
435 size_t offset = i->iov_offset;
436 const struct iovec *iov = i->iov;
437 size_t len;
438 unsigned long addr;
439 int n;
440 int res;
441
442 len = iov->iov_len - offset;
443 if (len > i->count)
444 len = i->count;
445 if (len > maxsize)
446 len = maxsize;
447 addr = (unsigned long)iov->iov_base + offset;
448 len += *start = addr & (PAGE_SIZE - 1);
449 if (len > maxpages * PAGE_SIZE)
450 len = maxpages * PAGE_SIZE;
451 addr &= ~(PAGE_SIZE - 1);
452 n = (len + PAGE_SIZE - 1) / PAGE_SIZE;
453 res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
454 if (unlikely(res < 0))
455 return res;
456 return (res == n ? len : res * PAGE_SIZE) - *start;
457}
458
459static ssize_t get_pages_alloc_iovec(struct iov_iter *i, 431static ssize_t get_pages_alloc_iovec(struct iov_iter *i,
460 struct page ***pages, size_t maxsize, 432 struct page ***pages, size_t maxsize,
461 size_t *start) 433 size_t *start)
@@ -650,24 +622,6 @@ static size_t zero_bvec(size_t bytes, struct iov_iter *i)
650 return wanted - bytes; 622 return wanted - bytes;
651} 623}
652 624
653static ssize_t get_pages_bvec(struct iov_iter *i,
654 struct page **pages, size_t maxsize, unsigned maxpages,
655 size_t *start)
656{
657 const struct bio_vec *bvec = i->bvec;
658 size_t len = bvec->bv_len - i->iov_offset;
659 if (len > i->count)
660 len = i->count;
661 if (len > maxsize)
662 len = maxsize;
663 /* can't be more than PAGE_SIZE */
664 *start = bvec->bv_offset + i->iov_offset;
665
666 get_page(*pages = bvec->bv_page);
667
668 return len;
669}
670
671static ssize_t get_pages_alloc_bvec(struct iov_iter *i, 625static ssize_t get_pages_alloc_bvec(struct iov_iter *i,
672 struct page ***pages, size_t maxsize, 626 struct page ***pages, size_t maxsize,
673 size_t *start) 627 size_t *start)
@@ -792,10 +746,34 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
792 struct page **pages, size_t maxsize, unsigned maxpages, 746 struct page **pages, size_t maxsize, unsigned maxpages,
793 size_t *start) 747 size_t *start)
794{ 748{
795 if (i->type & ITER_BVEC) 749 if (maxsize > i->count)
796 return get_pages_bvec(i, pages, maxsize, maxpages, start); 750 maxsize = i->count;
797 else 751
798 return get_pages_iovec(i, pages, maxsize, maxpages, start); 752 if (!maxsize)
753 return 0;
754
755 iterate_all_kinds(i, maxsize, v, ({
756 unsigned long addr = (unsigned long)v.iov_base;
757 size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1));
758 int n;
759 int res;
760
761 if (len > maxpages * PAGE_SIZE)
762 len = maxpages * PAGE_SIZE;
763 addr &= ~(PAGE_SIZE - 1);
764 n = DIV_ROUND_UP(len, PAGE_SIZE);
765 res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
766 if (unlikely(res < 0))
767 return res;
768 return (res == n ? len : res * PAGE_SIZE) - *start;
769 0;}),({
770 /* can't be more than PAGE_SIZE */
771 *start = v.bv_offset;
772 get_page(*pages = v.bv_page);
773 return v.bv_len;
774 })
775 )
776 return 0;
799} 777}
800EXPORT_SYMBOL(iov_iter_get_pages); 778EXPORT_SYMBOL(iov_iter_get_pages);
801 779