aboutsummaryrefslogtreecommitdiffstats
path: root/lib/iov_iter.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r--lib/iov_iter.c38
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
563static 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
563size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 595size_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 }