diff options
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r-- | lib/iov_iter.c | 420 |
1 files changed, 416 insertions, 4 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 7e3138cfc8c9..f0c7f1481bae 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -3,8 +3,11 @@ | |||
3 | #include <linux/pagemap.h> | 3 | #include <linux/pagemap.h> |
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/vmalloc.h> | 5 | #include <linux/vmalloc.h> |
6 | #include <linux/splice.h> | ||
6 | #include <net/checksum.h> | 7 | #include <net/checksum.h> |
7 | 8 | ||
9 | #define PIPE_PARANOIA /* for now */ | ||
10 | |||
8 | #define iterate_iovec(i, n, __v, __p, skip, STEP) { \ | 11 | #define iterate_iovec(i, n, __v, __p, skip, STEP) { \ |
9 | size_t left; \ | 12 | size_t left; \ |
10 | size_t wanted = n; \ | 13 | size_t wanted = n; \ |
@@ -290,6 +293,93 @@ done: | |||
290 | return wanted - bytes; | 293 | return wanted - bytes; |
291 | } | 294 | } |
292 | 295 | ||
296 | #ifdef PIPE_PARANOIA | ||
297 | static bool sanity(const struct iov_iter *i) | ||
298 | { | ||
299 | struct pipe_inode_info *pipe = i->pipe; | ||
300 | int idx = i->idx; | ||
301 | int next = pipe->curbuf + pipe->nrbufs; | ||
302 | if (i->iov_offset) { | ||
303 | struct pipe_buffer *p; | ||
304 | if (unlikely(!pipe->nrbufs)) | ||
305 | goto Bad; // pipe must be non-empty | ||
306 | if (unlikely(idx != ((next - 1) & (pipe->buffers - 1)))) | ||
307 | goto Bad; // must be at the last buffer... | ||
308 | |||
309 | p = &pipe->bufs[idx]; | ||
310 | if (unlikely(p->offset + p->len != i->iov_offset)) | ||
311 | goto Bad; // ... at the end of segment | ||
312 | } else { | ||
313 | if (idx != (next & (pipe->buffers - 1))) | ||
314 | goto Bad; // must be right after the last buffer | ||
315 | } | ||
316 | return true; | ||
317 | Bad: | ||
318 | printk(KERN_ERR "idx = %d, offset = %zd\n", i->idx, i->iov_offset); | ||
319 | printk(KERN_ERR "curbuf = %d, nrbufs = %d, buffers = %d\n", | ||
320 | pipe->curbuf, pipe->nrbufs, pipe->buffers); | ||
321 | for (idx = 0; idx < pipe->buffers; idx++) | ||
322 | printk(KERN_ERR "[%p %p %d %d]\n", | ||
323 | pipe->bufs[idx].ops, | ||
324 | pipe->bufs[idx].page, | ||
325 | pipe->bufs[idx].offset, | ||
326 | pipe->bufs[idx].len); | ||
327 | WARN_ON(1); | ||
328 | return false; | ||
329 | } | ||
330 | #else | ||
331 | #define sanity(i) true | ||
332 | #endif | ||
333 | |||
334 | static inline int next_idx(int idx, struct pipe_inode_info *pipe) | ||
335 | { | ||
336 | return (idx + 1) & (pipe->buffers - 1); | ||
337 | } | ||
338 | |||
339 | static size_t copy_page_to_iter_pipe(struct page *page, size_t offset, size_t bytes, | ||
340 | struct iov_iter *i) | ||
341 | { | ||
342 | struct pipe_inode_info *pipe = i->pipe; | ||
343 | struct pipe_buffer *buf; | ||
344 | size_t off; | ||
345 | int idx; | ||
346 | |||
347 | if (unlikely(bytes > i->count)) | ||
348 | bytes = i->count; | ||
349 | |||
350 | if (unlikely(!bytes)) | ||
351 | return 0; | ||
352 | |||
353 | if (!sanity(i)) | ||
354 | return 0; | ||
355 | |||
356 | off = i->iov_offset; | ||
357 | idx = i->idx; | ||
358 | buf = &pipe->bufs[idx]; | ||
359 | if (off) { | ||
360 | if (offset == off && buf->page == page) { | ||
361 | /* merge with the last one */ | ||
362 | buf->len += bytes; | ||
363 | i->iov_offset += bytes; | ||
364 | goto out; | ||
365 | } | ||
366 | idx = next_idx(idx, pipe); | ||
367 | buf = &pipe->bufs[idx]; | ||
368 | } | ||
369 | if (idx == pipe->curbuf && pipe->nrbufs) | ||
370 | return 0; | ||
371 | pipe->nrbufs++; | ||
372 | buf->ops = &page_cache_pipe_buf_ops; | ||
373 | get_page(buf->page = page); | ||
374 | buf->offset = offset; | ||
375 | buf->len = bytes; | ||
376 | i->iov_offset = offset + bytes; | ||
377 | i->idx = idx; | ||
378 | out: | ||
379 | i->count -= bytes; | ||
380 | return bytes; | ||
381 | } | ||
382 | |||
293 | /* | 383 | /* |
294 | * Fault in one or more iovecs of the given iov_iter, to a maximum length of | 384 | * Fault in one or more iovecs of the given iov_iter, to a maximum length of |
295 | * bytes. For each iovec, fault in each page that constitutes the iovec. | 385 | * bytes. For each iovec, fault in each page that constitutes the iovec. |
@@ -306,8 +396,7 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) | |||
306 | 396 | ||
307 | if (!(i->type & (ITER_BVEC|ITER_KVEC))) { | 397 | if (!(i->type & (ITER_BVEC|ITER_KVEC))) { |
308 | iterate_iovec(i, bytes, v, iov, skip, ({ | 398 | iterate_iovec(i, bytes, v, iov, skip, ({ |
309 | err = fault_in_multipages_readable(v.iov_base, | 399 | err = fault_in_pages_readable(v.iov_base, v.iov_len); |
310 | v.iov_len); | ||
311 | if (unlikely(err)) | 400 | if (unlikely(err)) |
312 | return err; | 401 | return err; |
313 | 0;})) | 402 | 0;})) |
@@ -356,9 +445,98 @@ static void memzero_page(struct page *page, size_t offset, size_t len) | |||
356 | kunmap_atomic(addr); | 445 | kunmap_atomic(addr); |
357 | } | 446 | } |
358 | 447 | ||
448 | static inline bool allocated(struct pipe_buffer *buf) | ||
449 | { | ||
450 | return buf->ops == &default_pipe_buf_ops; | ||
451 | } | ||
452 | |||
453 | static inline void data_start(const struct iov_iter *i, int *idxp, size_t *offp) | ||
454 | { | ||
455 | size_t off = i->iov_offset; | ||
456 | int idx = i->idx; | ||
457 | if (off && (!allocated(&i->pipe->bufs[idx]) || off == PAGE_SIZE)) { | ||
458 | idx = next_idx(idx, i->pipe); | ||
459 | off = 0; | ||
460 | } | ||
461 | *idxp = idx; | ||
462 | *offp = off; | ||
463 | } | ||
464 | |||
465 | static size_t push_pipe(struct iov_iter *i, size_t size, | ||
466 | int *idxp, size_t *offp) | ||
467 | { | ||
468 | struct pipe_inode_info *pipe = i->pipe; | ||
469 | size_t off; | ||
470 | int idx; | ||
471 | ssize_t left; | ||
472 | |||
473 | if (unlikely(size > i->count)) | ||
474 | size = i->count; | ||
475 | if (unlikely(!size)) | ||
476 | return 0; | ||
477 | |||
478 | left = size; | ||
479 | data_start(i, &idx, &off); | ||
480 | *idxp = idx; | ||
481 | *offp = off; | ||
482 | if (off) { | ||
483 | left -= PAGE_SIZE - off; | ||
484 | if (left <= 0) { | ||
485 | pipe->bufs[idx].len += size; | ||
486 | return size; | ||
487 | } | ||
488 | pipe->bufs[idx].len = PAGE_SIZE; | ||
489 | idx = next_idx(idx, pipe); | ||
490 | } | ||
491 | while (idx != pipe->curbuf || !pipe->nrbufs) { | ||
492 | struct page *page = alloc_page(GFP_USER); | ||
493 | if (!page) | ||
494 | break; | ||
495 | pipe->nrbufs++; | ||
496 | pipe->bufs[idx].ops = &default_pipe_buf_ops; | ||
497 | pipe->bufs[idx].page = page; | ||
498 | pipe->bufs[idx].offset = 0; | ||
499 | if (left <= PAGE_SIZE) { | ||
500 | pipe->bufs[idx].len = left; | ||
501 | return size; | ||
502 | } | ||
503 | pipe->bufs[idx].len = PAGE_SIZE; | ||
504 | left -= PAGE_SIZE; | ||
505 | idx = next_idx(idx, pipe); | ||
506 | } | ||
507 | return size - left; | ||
508 | } | ||
509 | |||
510 | static size_t copy_pipe_to_iter(const void *addr, size_t bytes, | ||
511 | struct iov_iter *i) | ||
512 | { | ||
513 | struct pipe_inode_info *pipe = i->pipe; | ||
514 | size_t n, off; | ||
515 | int idx; | ||
516 | |||
517 | if (!sanity(i)) | ||
518 | return 0; | ||
519 | |||
520 | bytes = n = push_pipe(i, bytes, &idx, &off); | ||
521 | if (unlikely(!n)) | ||
522 | return 0; | ||
523 | for ( ; n; idx = next_idx(idx, pipe), off = 0) { | ||
524 | size_t chunk = min_t(size_t, n, PAGE_SIZE - off); | ||
525 | memcpy_to_page(pipe->bufs[idx].page, off, addr, chunk); | ||
526 | i->idx = idx; | ||
527 | i->iov_offset = off + chunk; | ||
528 | n -= chunk; | ||
529 | addr += chunk; | ||
530 | } | ||
531 | i->count -= bytes; | ||
532 | return bytes; | ||
533 | } | ||
534 | |||
359 | size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) | 535 | size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) |
360 | { | 536 | { |
361 | const char *from = addr; | 537 | const char *from = addr; |
538 | if (unlikely(i->type & ITER_PIPE)) | ||
539 | return copy_pipe_to_iter(addr, bytes, i); | ||
362 | iterate_and_advance(i, bytes, v, | 540 | iterate_and_advance(i, bytes, v, |
363 | __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, | 541 | __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, |
364 | v.iov_len), | 542 | v.iov_len), |
@@ -374,6 +552,10 @@ EXPORT_SYMBOL(copy_to_iter); | |||
374 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | 552 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) |
375 | { | 553 | { |
376 | char *to = addr; | 554 | char *to = addr; |
555 | if (unlikely(i->type & ITER_PIPE)) { | ||
556 | WARN_ON(1); | ||
557 | return 0; | ||
558 | } | ||
377 | iterate_and_advance(i, bytes, v, | 559 | iterate_and_advance(i, bytes, v, |
378 | __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, | 560 | __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, |
379 | v.iov_len), | 561 | v.iov_len), |
@@ -389,6 +571,10 @@ EXPORT_SYMBOL(copy_from_iter); | |||
389 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | 571 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) |
390 | { | 572 | { |
391 | char *to = addr; | 573 | char *to = addr; |
574 | if (unlikely(i->type & ITER_PIPE)) { | ||
575 | WARN_ON(1); | ||
576 | return 0; | ||
577 | } | ||
392 | iterate_and_advance(i, bytes, v, | 578 | iterate_and_advance(i, bytes, v, |
393 | __copy_from_user_nocache((to += v.iov_len) - v.iov_len, | 579 | __copy_from_user_nocache((to += v.iov_len) - v.iov_len, |
394 | v.iov_base, v.iov_len), | 580 | v.iov_base, v.iov_len), |
@@ -409,14 +595,20 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | |||
409 | size_t wanted = copy_to_iter(kaddr + offset, bytes, i); | 595 | size_t wanted = copy_to_iter(kaddr + offset, bytes, i); |
410 | kunmap_atomic(kaddr); | 596 | kunmap_atomic(kaddr); |
411 | return wanted; | 597 | return wanted; |
412 | } else | 598 | } else if (likely(!(i->type & ITER_PIPE))) |
413 | return copy_page_to_iter_iovec(page, offset, bytes, i); | 599 | return copy_page_to_iter_iovec(page, offset, bytes, i); |
600 | else | ||
601 | return copy_page_to_iter_pipe(page, offset, bytes, i); | ||
414 | } | 602 | } |
415 | EXPORT_SYMBOL(copy_page_to_iter); | 603 | EXPORT_SYMBOL(copy_page_to_iter); |
416 | 604 | ||
417 | size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | 605 | size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, |
418 | struct iov_iter *i) | 606 | struct iov_iter *i) |
419 | { | 607 | { |
608 | if (unlikely(i->type & ITER_PIPE)) { | ||
609 | WARN_ON(1); | ||
610 | return 0; | ||
611 | } | ||
420 | if (i->type & (ITER_BVEC|ITER_KVEC)) { | 612 | if (i->type & (ITER_BVEC|ITER_KVEC)) { |
421 | void *kaddr = kmap_atomic(page); | 613 | void *kaddr = kmap_atomic(page); |
422 | size_t wanted = copy_from_iter(kaddr + offset, bytes, i); | 614 | size_t wanted = copy_from_iter(kaddr + offset, bytes, i); |
@@ -427,8 +619,34 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | |||
427 | } | 619 | } |
428 | EXPORT_SYMBOL(copy_page_from_iter); | 620 | EXPORT_SYMBOL(copy_page_from_iter); |
429 | 621 | ||
622 | static size_t pipe_zero(size_t bytes, struct iov_iter *i) | ||
623 | { | ||
624 | struct pipe_inode_info *pipe = i->pipe; | ||
625 | size_t n, off; | ||
626 | int idx; | ||
627 | |||
628 | if (!sanity(i)) | ||
629 | return 0; | ||
630 | |||
631 | bytes = n = push_pipe(i, bytes, &idx, &off); | ||
632 | if (unlikely(!n)) | ||
633 | return 0; | ||
634 | |||
635 | for ( ; n; idx = next_idx(idx, pipe), off = 0) { | ||
636 | size_t chunk = min_t(size_t, n, PAGE_SIZE - off); | ||
637 | memzero_page(pipe->bufs[idx].page, off, chunk); | ||
638 | i->idx = idx; | ||
639 | i->iov_offset = off + chunk; | ||
640 | n -= chunk; | ||
641 | } | ||
642 | i->count -= bytes; | ||
643 | return bytes; | ||
644 | } | ||
645 | |||
430 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) | 646 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) |
431 | { | 647 | { |
648 | if (unlikely(i->type & ITER_PIPE)) | ||
649 | return pipe_zero(bytes, i); | ||
432 | iterate_and_advance(i, bytes, v, | 650 | iterate_and_advance(i, bytes, v, |
433 | __clear_user(v.iov_base, v.iov_len), | 651 | __clear_user(v.iov_base, v.iov_len), |
434 | memzero_page(v.bv_page, v.bv_offset, v.bv_len), | 652 | memzero_page(v.bv_page, v.bv_offset, v.bv_len), |
@@ -443,6 +661,11 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
443 | struct iov_iter *i, unsigned long offset, size_t bytes) | 661 | struct iov_iter *i, unsigned long offset, size_t bytes) |
444 | { | 662 | { |
445 | char *kaddr = kmap_atomic(page), *p = kaddr + offset; | 663 | char *kaddr = kmap_atomic(page), *p = kaddr + offset; |
664 | if (unlikely(i->type & ITER_PIPE)) { | ||
665 | kunmap_atomic(kaddr); | ||
666 | WARN_ON(1); | ||
667 | return 0; | ||
668 | } | ||
446 | iterate_all_kinds(i, bytes, v, | 669 | iterate_all_kinds(i, bytes, v, |
447 | __copy_from_user_inatomic((p += v.iov_len) - v.iov_len, | 670 | __copy_from_user_inatomic((p += v.iov_len) - v.iov_len, |
448 | v.iov_base, v.iov_len), | 671 | v.iov_base, v.iov_len), |
@@ -455,8 +678,49 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
455 | } | 678 | } |
456 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); | 679 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); |
457 | 680 | ||
681 | static void pipe_advance(struct iov_iter *i, size_t size) | ||
682 | { | ||
683 | struct pipe_inode_info *pipe = i->pipe; | ||
684 | struct pipe_buffer *buf; | ||
685 | int idx = i->idx; | ||
686 | size_t off = i->iov_offset; | ||
687 | |||
688 | if (unlikely(i->count < size)) | ||
689 | size = i->count; | ||
690 | |||
691 | if (size) { | ||
692 | if (off) /* make it relative to the beginning of buffer */ | ||
693 | size += off - pipe->bufs[idx].offset; | ||
694 | while (1) { | ||
695 | buf = &pipe->bufs[idx]; | ||
696 | if (size <= buf->len) | ||
697 | break; | ||
698 | size -= buf->len; | ||
699 | idx = next_idx(idx, pipe); | ||
700 | } | ||
701 | buf->len = size; | ||
702 | i->idx = idx; | ||
703 | off = i->iov_offset = buf->offset + size; | ||
704 | } | ||
705 | if (off) | ||
706 | idx = next_idx(idx, pipe); | ||
707 | if (pipe->nrbufs) { | ||
708 | int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); | ||
709 | /* [curbuf,unused) is in use. Free [idx,unused) */ | ||
710 | while (idx != unused) { | ||
711 | pipe_buf_release(pipe, &pipe->bufs[idx]); | ||
712 | idx = next_idx(idx, pipe); | ||
713 | pipe->nrbufs--; | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | |||
458 | void iov_iter_advance(struct iov_iter *i, size_t size) | 718 | void iov_iter_advance(struct iov_iter *i, size_t size) |
459 | { | 719 | { |
720 | if (unlikely(i->type & ITER_PIPE)) { | ||
721 | pipe_advance(i, size); | ||
722 | return; | ||
723 | } | ||
460 | iterate_and_advance(i, size, v, 0, 0, 0) | 724 | iterate_and_advance(i, size, v, 0, 0, 0) |
461 | } | 725 | } |
462 | EXPORT_SYMBOL(iov_iter_advance); | 726 | EXPORT_SYMBOL(iov_iter_advance); |
@@ -466,6 +730,8 @@ EXPORT_SYMBOL(iov_iter_advance); | |||
466 | */ | 730 | */ |
467 | size_t iov_iter_single_seg_count(const struct iov_iter *i) | 731 | size_t iov_iter_single_seg_count(const struct iov_iter *i) |
468 | { | 732 | { |
733 | if (unlikely(i->type & ITER_PIPE)) | ||
734 | return i->count; // it is a silly place, anyway | ||
469 | if (i->nr_segs == 1) | 735 | if (i->nr_segs == 1) |
470 | return i->count; | 736 | return i->count; |
471 | else if (i->type & ITER_BVEC) | 737 | else if (i->type & ITER_BVEC) |
@@ -501,6 +767,19 @@ void iov_iter_bvec(struct iov_iter *i, int direction, | |||
501 | } | 767 | } |
502 | EXPORT_SYMBOL(iov_iter_bvec); | 768 | EXPORT_SYMBOL(iov_iter_bvec); |
503 | 769 | ||
770 | void iov_iter_pipe(struct iov_iter *i, int direction, | ||
771 | struct pipe_inode_info *pipe, | ||
772 | size_t count) | ||
773 | { | ||
774 | BUG_ON(direction != ITER_PIPE); | ||
775 | i->type = direction; | ||
776 | i->pipe = pipe; | ||
777 | i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); | ||
778 | i->iov_offset = 0; | ||
779 | i->count = count; | ||
780 | } | ||
781 | EXPORT_SYMBOL(iov_iter_pipe); | ||
782 | |||
504 | unsigned long iov_iter_alignment(const struct iov_iter *i) | 783 | unsigned long iov_iter_alignment(const struct iov_iter *i) |
505 | { | 784 | { |
506 | unsigned long res = 0; | 785 | unsigned long res = 0; |
@@ -509,6 +788,11 @@ unsigned long iov_iter_alignment(const struct iov_iter *i) | |||
509 | if (!size) | 788 | if (!size) |
510 | return 0; | 789 | return 0; |
511 | 790 | ||
791 | if (unlikely(i->type & ITER_PIPE)) { | ||
792 | if (i->iov_offset && allocated(&i->pipe->bufs[i->idx])) | ||
793 | return size | i->iov_offset; | ||
794 | return size; | ||
795 | } | ||
512 | iterate_all_kinds(i, size, v, | 796 | iterate_all_kinds(i, size, v, |
513 | (res |= (unsigned long)v.iov_base | v.iov_len, 0), | 797 | (res |= (unsigned long)v.iov_base | v.iov_len, 0), |
514 | res |= v.bv_offset | v.bv_len, | 798 | res |= v.bv_offset | v.bv_len, |
@@ -525,6 +809,11 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i) | |||
525 | if (!size) | 809 | if (!size) |
526 | return 0; | 810 | return 0; |
527 | 811 | ||
812 | if (unlikely(i->type & ITER_PIPE)) { | ||
813 | WARN_ON(1); | ||
814 | return ~0U; | ||
815 | } | ||
816 | |||
528 | iterate_all_kinds(i, size, v, | 817 | iterate_all_kinds(i, size, v, |
529 | (res |= (!res ? 0 : (unsigned long)v.iov_base) | | 818 | (res |= (!res ? 0 : (unsigned long)v.iov_base) | |
530 | (size != v.iov_len ? size : 0), 0), | 819 | (size != v.iov_len ? size : 0), 0), |
@@ -537,6 +826,47 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i) | |||
537 | } | 826 | } |
538 | EXPORT_SYMBOL(iov_iter_gap_alignment); | 827 | EXPORT_SYMBOL(iov_iter_gap_alignment); |
539 | 828 | ||
829 | static inline size_t __pipe_get_pages(struct iov_iter *i, | ||
830 | size_t maxsize, | ||
831 | struct page **pages, | ||
832 | int idx, | ||
833 | size_t *start) | ||
834 | { | ||
835 | struct pipe_inode_info *pipe = i->pipe; | ||
836 | ssize_t n = push_pipe(i, maxsize, &idx, start); | ||
837 | if (!n) | ||
838 | return -EFAULT; | ||
839 | |||
840 | maxsize = n; | ||
841 | n += *start; | ||
842 | while (n > 0) { | ||
843 | get_page(*pages++ = pipe->bufs[idx].page); | ||
844 | idx = next_idx(idx, pipe); | ||
845 | n -= PAGE_SIZE; | ||
846 | } | ||
847 | |||
848 | return maxsize; | ||
849 | } | ||
850 | |||
851 | static ssize_t pipe_get_pages(struct iov_iter *i, | ||
852 | struct page **pages, size_t maxsize, unsigned maxpages, | ||
853 | size_t *start) | ||
854 | { | ||
855 | unsigned npages; | ||
856 | size_t capacity; | ||
857 | int idx; | ||
858 | |||
859 | if (!sanity(i)) | ||
860 | return -EFAULT; | ||
861 | |||
862 | data_start(i, &idx, start); | ||
863 | /* some of this one + all after this one */ | ||
864 | npages = ((i->pipe->curbuf - idx - 1) & (i->pipe->buffers - 1)) + 1; | ||
865 | capacity = min(npages,maxpages) * PAGE_SIZE - *start; | ||
866 | |||
867 | return __pipe_get_pages(i, min(maxsize, capacity), pages, idx, start); | ||
868 | } | ||
869 | |||
540 | ssize_t iov_iter_get_pages(struct iov_iter *i, | 870 | ssize_t iov_iter_get_pages(struct iov_iter *i, |
541 | struct page **pages, size_t maxsize, unsigned maxpages, | 871 | struct page **pages, size_t maxsize, unsigned maxpages, |
542 | size_t *start) | 872 | size_t *start) |
@@ -547,6 +877,8 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, | |||
547 | if (!maxsize) | 877 | if (!maxsize) |
548 | return 0; | 878 | return 0; |
549 | 879 | ||
880 | if (unlikely(i->type & ITER_PIPE)) | ||
881 | return pipe_get_pages(i, pages, maxsize, maxpages, start); | ||
550 | iterate_all_kinds(i, maxsize, v, ({ | 882 | iterate_all_kinds(i, maxsize, v, ({ |
551 | unsigned long addr = (unsigned long)v.iov_base; | 883 | unsigned long addr = (unsigned long)v.iov_base; |
552 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | 884 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); |
@@ -582,6 +914,37 @@ static struct page **get_pages_array(size_t n) | |||
582 | return p; | 914 | return p; |
583 | } | 915 | } |
584 | 916 | ||
917 | static ssize_t pipe_get_pages_alloc(struct iov_iter *i, | ||
918 | struct page ***pages, size_t maxsize, | ||
919 | size_t *start) | ||
920 | { | ||
921 | struct page **p; | ||
922 | size_t n; | ||
923 | int idx; | ||
924 | int npages; | ||
925 | |||
926 | if (!sanity(i)) | ||
927 | return -EFAULT; | ||
928 | |||
929 | data_start(i, &idx, start); | ||
930 | /* some of this one + all after this one */ | ||
931 | npages = ((i->pipe->curbuf - idx - 1) & (i->pipe->buffers - 1)) + 1; | ||
932 | n = npages * PAGE_SIZE - *start; | ||
933 | if (maxsize > n) | ||
934 | maxsize = n; | ||
935 | else | ||
936 | npages = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE); | ||
937 | p = get_pages_array(npages); | ||
938 | if (!p) | ||
939 | return -ENOMEM; | ||
940 | n = __pipe_get_pages(i, maxsize, p, idx, start); | ||
941 | if (n > 0) | ||
942 | *pages = p; | ||
943 | else | ||
944 | kvfree(p); | ||
945 | return n; | ||
946 | } | ||
947 | |||
585 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, | 948 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, |
586 | struct page ***pages, size_t maxsize, | 949 | struct page ***pages, size_t maxsize, |
587 | size_t *start) | 950 | size_t *start) |
@@ -594,6 +957,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, | |||
594 | if (!maxsize) | 957 | if (!maxsize) |
595 | return 0; | 958 | return 0; |
596 | 959 | ||
960 | if (unlikely(i->type & ITER_PIPE)) | ||
961 | return pipe_get_pages_alloc(i, pages, maxsize, start); | ||
597 | iterate_all_kinds(i, maxsize, v, ({ | 962 | iterate_all_kinds(i, maxsize, v, ({ |
598 | unsigned long addr = (unsigned long)v.iov_base; | 963 | unsigned long addr = (unsigned long)v.iov_base; |
599 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | 964 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); |
@@ -635,6 +1000,10 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
635 | __wsum sum, next; | 1000 | __wsum sum, next; |
636 | size_t off = 0; | 1001 | size_t off = 0; |
637 | sum = *csum; | 1002 | sum = *csum; |
1003 | if (unlikely(i->type & ITER_PIPE)) { | ||
1004 | WARN_ON(1); | ||
1005 | return 0; | ||
1006 | } | ||
638 | iterate_and_advance(i, bytes, v, ({ | 1007 | iterate_and_advance(i, bytes, v, ({ |
639 | int err = 0; | 1008 | int err = 0; |
640 | next = csum_and_copy_from_user(v.iov_base, | 1009 | next = csum_and_copy_from_user(v.iov_base, |
@@ -673,6 +1042,10 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | |||
673 | __wsum sum, next; | 1042 | __wsum sum, next; |
674 | size_t off = 0; | 1043 | size_t off = 0; |
675 | sum = *csum; | 1044 | sum = *csum; |
1045 | if (unlikely(i->type & ITER_PIPE)) { | ||
1046 | WARN_ON(1); /* for now */ | ||
1047 | return 0; | ||
1048 | } | ||
676 | iterate_and_advance(i, bytes, v, ({ | 1049 | iterate_and_advance(i, bytes, v, ({ |
677 | int err = 0; | 1050 | int err = 0; |
678 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, | 1051 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, |
@@ -712,7 +1085,20 @@ int iov_iter_npages(const struct iov_iter *i, int maxpages) | |||
712 | if (!size) | 1085 | if (!size) |
713 | return 0; | 1086 | return 0; |
714 | 1087 | ||
715 | iterate_all_kinds(i, size, v, ({ | 1088 | if (unlikely(i->type & ITER_PIPE)) { |
1089 | struct pipe_inode_info *pipe = i->pipe; | ||
1090 | size_t off; | ||
1091 | int idx; | ||
1092 | |||
1093 | if (!sanity(i)) | ||
1094 | return 0; | ||
1095 | |||
1096 | data_start(i, &idx, &off); | ||
1097 | /* some of this one + all after this one */ | ||
1098 | npages = ((pipe->curbuf - idx - 1) & (pipe->buffers - 1)) + 1; | ||
1099 | if (npages >= maxpages) | ||
1100 | return maxpages; | ||
1101 | } else iterate_all_kinds(i, size, v, ({ | ||
716 | unsigned long p = (unsigned long)v.iov_base; | 1102 | unsigned long p = (unsigned long)v.iov_base; |
717 | npages += DIV_ROUND_UP(p + v.iov_len, PAGE_SIZE) | 1103 | npages += DIV_ROUND_UP(p + v.iov_len, PAGE_SIZE) |
718 | - p / PAGE_SIZE; | 1104 | - p / PAGE_SIZE; |
@@ -737,6 +1123,10 @@ EXPORT_SYMBOL(iov_iter_npages); | |||
737 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) | 1123 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) |
738 | { | 1124 | { |
739 | *new = *old; | 1125 | *new = *old; |
1126 | if (unlikely(new->type & ITER_PIPE)) { | ||
1127 | WARN_ON(1); | ||
1128 | return NULL; | ||
1129 | } | ||
740 | if (new->type & ITER_BVEC) | 1130 | if (new->type & ITER_BVEC) |
741 | return new->bvec = kmemdup(new->bvec, | 1131 | return new->bvec = kmemdup(new->bvec, |
742 | new->nr_segs * sizeof(struct bio_vec), | 1132 | new->nr_segs * sizeof(struct bio_vec), |
@@ -749,6 +1139,28 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) | |||
749 | } | 1139 | } |
750 | EXPORT_SYMBOL(dup_iter); | 1140 | EXPORT_SYMBOL(dup_iter); |
751 | 1141 | ||
1142 | /** | ||
1143 | * import_iovec() - Copy an array of &struct iovec from userspace | ||
1144 | * into the kernel, check that it is valid, and initialize a new | ||
1145 | * &struct iov_iter iterator to access it. | ||
1146 | * | ||
1147 | * @type: One of %READ or %WRITE. | ||
1148 | * @uvector: Pointer to the userspace array. | ||
1149 | * @nr_segs: Number of elements in userspace array. | ||
1150 | * @fast_segs: Number of elements in @iov. | ||
1151 | * @iov: (input and output parameter) Pointer to pointer to (usually small | ||
1152 | * on-stack) kernel array. | ||
1153 | * @i: Pointer to iterator that will be initialized on success. | ||
1154 | * | ||
1155 | * If the array pointed to by *@iov is large enough to hold all @nr_segs, | ||
1156 | * then this function places %NULL in *@iov on return. Otherwise, a new | ||
1157 | * array will be allocated and the result placed in *@iov. This means that | ||
1158 | * the caller may call kfree() on *@iov regardless of whether the small | ||
1159 | * on-stack array was used or not (and regardless of whether this function | ||
1160 | * returns an error or not). | ||
1161 | * | ||
1162 | * Return: 0 on success or negative error code on error. | ||
1163 | */ | ||
752 | int import_iovec(int type, const struct iovec __user * uvector, | 1164 | int import_iovec(int type, const struct iovec __user * uvector, |
753 | unsigned nr_segs, unsigned fast_segs, | 1165 | unsigned nr_segs, unsigned fast_segs, |
754 | struct iovec **iov, struct iov_iter *i) | 1166 | struct iovec **iov, struct iov_iter *i) |