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 | } |
