diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 14:12:09 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-27 18:44:11 -0500 |
commit | e5393fae3b49e80179f04afdc0916fcb6846ef17 (patch) | |
tree | f8b7b3671770767e9b1429dd49fc45904d4ae54e | |
parent | e0f2dc4061e6238905001e8ec6c88b15c2e3b950 (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.c | 78 |
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 | } |
429 | EXPORT_SYMBOL(iov_iter_init); | 429 | EXPORT_SYMBOL(iov_iter_init); |
430 | 430 | ||
431 | static 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 | |||
459 | static ssize_t get_pages_alloc_iovec(struct iov_iter *i, | 431 | static 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 | ||
653 | static 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 | |||
671 | static ssize_t get_pages_alloc_bvec(struct iov_iter *i, | 625 | static 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 | } |
800 | EXPORT_SYMBOL(iov_iter_get_pages); | 778 | EXPORT_SYMBOL(iov_iter_get_pages); |
801 | 779 | ||