diff options
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r-- | lib/iov_iter.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 7ebccb5c1637..54c248526b55 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -560,6 +560,38 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes, | |||
560 | return bytes; | 560 | return bytes; |
561 | } | 561 | } |
562 | 562 | ||
563 | static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes, | ||
564 | __wsum *csum, struct iov_iter *i) | ||
565 | { | ||
566 | struct pipe_inode_info *pipe = i->pipe; | ||
567 | size_t n, r; | ||
568 | size_t off = 0; | ||
569 | __wsum sum = *csum, next; | ||
570 | int idx; | ||
571 | |||
572 | if (!sanity(i)) | ||
573 | return 0; | ||
574 | |||
575 | bytes = n = push_pipe(i, bytes, &idx, &r); | ||
576 | if (unlikely(!n)) | ||
577 | return 0; | ||
578 | for ( ; n; idx = next_idx(idx, pipe), r = 0) { | ||
579 | size_t chunk = min_t(size_t, n, PAGE_SIZE - r); | ||
580 | char *p = kmap_atomic(pipe->bufs[idx].page); | ||
581 | next = csum_partial_copy_nocheck(addr, p + r, chunk, 0); | ||
582 | sum = csum_block_add(sum, next, off); | ||
583 | kunmap_atomic(p); | ||
584 | i->idx = idx; | ||
585 | i->iov_offset = r + chunk; | ||
586 | n -= chunk; | ||
587 | off += chunk; | ||
588 | addr += chunk; | ||
589 | } | ||
590 | i->count -= bytes; | ||
591 | *csum = sum; | ||
592 | return bytes; | ||
593 | } | ||
594 | |||
563 | size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) | 595 | size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) |
564 | { | 596 | { |
565 | const char *from = addr; | 597 | const char *from = addr; |
@@ -1438,8 +1470,12 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | |||
1438 | const char *from = addr; | 1470 | const char *from = addr; |
1439 | __wsum sum, next; | 1471 | __wsum sum, next; |
1440 | size_t off = 0; | 1472 | size_t off = 0; |
1473 | |||
1474 | if (unlikely(iov_iter_is_pipe(i))) | ||
1475 | return csum_and_copy_to_pipe_iter(addr, bytes, csum, i); | ||
1476 | |||
1441 | sum = *csum; | 1477 | sum = *csum; |
1442 | if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) { | 1478 | if (unlikely(iov_iter_is_discard(i))) { |
1443 | WARN_ON(1); /* for now */ | 1479 | WARN_ON(1); /* for now */ |
1444 | return 0; | 1480 | return 0; |
1445 | } | 1481 | } |