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 /mm | |
| 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>
Diffstat (limited to 'mm')
| -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 | ||
