aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c126
1 files changed, 25 insertions, 101 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 12028fa41def..9bc07d2b53cf 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -136,8 +136,6 @@ error:
136 136
137const struct pipe_buf_operations page_cache_pipe_buf_ops = { 137const struct pipe_buf_operations page_cache_pipe_buf_ops = {
138 .can_merge = 0, 138 .can_merge = 0,
139 .map = generic_pipe_buf_map,
140 .unmap = generic_pipe_buf_unmap,
141 .confirm = page_cache_pipe_buf_confirm, 139 .confirm = page_cache_pipe_buf_confirm,
142 .release = page_cache_pipe_buf_release, 140 .release = page_cache_pipe_buf_release,
143 .steal = page_cache_pipe_buf_steal, 141 .steal = page_cache_pipe_buf_steal,
@@ -156,8 +154,6 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
156 154
157static const struct pipe_buf_operations user_page_pipe_buf_ops = { 155static const struct pipe_buf_operations user_page_pipe_buf_ops = {
158 .can_merge = 0, 156 .can_merge = 0,
159 .map = generic_pipe_buf_map,
160 .unmap = generic_pipe_buf_unmap,
161 .confirm = generic_pipe_buf_confirm, 157 .confirm = generic_pipe_buf_confirm,
162 .release = page_cache_pipe_buf_release, 158 .release = page_cache_pipe_buf_release,
163 .steal = user_page_pipe_buf_steal, 159 .steal = user_page_pipe_buf_steal,
@@ -547,8 +543,6 @@ EXPORT_SYMBOL(generic_file_splice_read);
547 543
548static const struct pipe_buf_operations default_pipe_buf_ops = { 544static const struct pipe_buf_operations default_pipe_buf_ops = {
549 .can_merge = 0, 545 .can_merge = 0,
550 .map = generic_pipe_buf_map,
551 .unmap = generic_pipe_buf_unmap,
552 .confirm = generic_pipe_buf_confirm, 546 .confirm = generic_pipe_buf_confirm,
553 .release = generic_pipe_buf_release, 547 .release = generic_pipe_buf_release,
554 .steal = generic_pipe_buf_steal, 548 .steal = generic_pipe_buf_steal,
@@ -564,8 +558,6 @@ static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe,
564/* Pipe buffer operations for a socket and similar. */ 558/* Pipe buffer operations for a socket and similar. */
565const struct pipe_buf_operations nosteal_pipe_buf_ops = { 559const struct pipe_buf_operations nosteal_pipe_buf_ops = {
566 .can_merge = 0, 560 .can_merge = 0,
567 .map = generic_pipe_buf_map,
568 .unmap = generic_pipe_buf_unmap,
569 .confirm = generic_pipe_buf_confirm, 561 .confirm = generic_pipe_buf_confirm,
570 .release = generic_pipe_buf_release, 562 .release = generic_pipe_buf_release,
571 .steal = generic_pipe_buf_nosteal, 563 .steal = generic_pipe_buf_nosteal,
@@ -767,13 +759,13 @@ int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
767 goto out; 759 goto out;
768 760
769 if (buf->page != page) { 761 if (buf->page != page) {
770 char *src = buf->ops->map(pipe, buf, 1); 762 char *src = kmap_atomic(buf->page);
771 char *dst = kmap_atomic(page); 763 char *dst = kmap_atomic(page);
772 764
773 memcpy(dst + offset, src + buf->offset, this_len); 765 memcpy(dst + offset, src + buf->offset, this_len);
774 flush_dcache_page(page); 766 flush_dcache_page(page);
775 kunmap_atomic(dst); 767 kunmap_atomic(dst);
776 buf->ops->unmap(pipe, buf, src); 768 kunmap_atomic(src);
777 } 769 }
778 ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len, 770 ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len,
779 page, fsdata); 771 page, fsdata);
@@ -1067,9 +1059,9 @@ static int write_pipe_buf(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
1067 void *data; 1059 void *data;
1068 loff_t tmp = sd->pos; 1060 loff_t tmp = sd->pos;
1069 1061
1070 data = buf->ops->map(pipe, buf, 0); 1062 data = kmap(buf->page);
1071 ret = __kernel_write(sd->u.file, data + buf->offset, sd->len, &tmp); 1063 ret = __kernel_write(sd->u.file, data + buf->offset, sd->len, &tmp);
1072 buf->ops->unmap(pipe, buf, data); 1064 kunmap(buf->page);
1073 1065
1074 return ret; 1066 return ret;
1075} 1067}
@@ -1528,116 +1520,48 @@ static int get_iovec_page_array(const struct iovec __user *iov,
1528static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, 1520static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
1529 struct splice_desc *sd) 1521 struct splice_desc *sd)
1530{ 1522{
1531 char *src; 1523 int n = copy_page_to_iter(buf->page, buf->offset, sd->len, sd->u.data);
1532 int ret; 1524 return n == sd->len ? n : -EFAULT;
1533
1534 /*
1535 * See if we can use the atomic maps, by prefaulting in the
1536 * pages and doing an atomic copy
1537 */
1538 if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
1539 src = buf->ops->map(pipe, buf, 1);
1540 ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset,
1541 sd->len);
1542 buf->ops->unmap(pipe, buf, src);
1543 if (!ret) {
1544 ret = sd->len;
1545 goto out;
1546 }
1547 }
1548
1549 /*
1550 * No dice, use slow non-atomic map and copy
1551 */
1552 src = buf->ops->map(pipe, buf, 0);
1553
1554 ret = sd->len;
1555 if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
1556 ret = -EFAULT;
1557
1558 buf->ops->unmap(pipe, buf, src);
1559out:
1560 if (ret > 0)
1561 sd->u.userptr += ret;
1562 return ret;
1563} 1525}
1564 1526
1565/* 1527/*
1566 * For lack of a better implementation, implement vmsplice() to userspace 1528 * For lack of a better implementation, implement vmsplice() to userspace
1567 * as a simple copy of the pipes pages to the user iov. 1529 * as a simple copy of the pipes pages to the user iov.
1568 */ 1530 */
1569static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, 1531static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
1570 unsigned long nr_segs, unsigned int flags) 1532 unsigned long nr_segs, unsigned int flags)
1571{ 1533{
1572 struct pipe_inode_info *pipe; 1534 struct pipe_inode_info *pipe;
1573 struct splice_desc sd; 1535 struct splice_desc sd;
1574 ssize_t size;
1575 int error;
1576 long ret; 1536 long ret;
1537 struct iovec iovstack[UIO_FASTIOV];
1538 struct iovec *iov = iovstack;
1539 struct iov_iter iter;
1540 ssize_t count = 0;
1577 1541
1578 pipe = get_pipe_info(file); 1542 pipe = get_pipe_info(file);
1579 if (!pipe) 1543 if (!pipe)
1580 return -EBADF; 1544 return -EBADF;
1581 1545
1582 pipe_lock(pipe); 1546 ret = rw_copy_check_uvector(READ, uiov, nr_segs,
1583 1547 ARRAY_SIZE(iovstack), iovstack, &iov);
1584 error = ret = 0; 1548 if (ret <= 0)
1585 while (nr_segs) { 1549 return ret;
1586 void __user *base;
1587 size_t len;
1588
1589 /*
1590 * Get user address base and length for this iovec.
1591 */
1592 error = get_user(base, &iov->iov_base);
1593 if (unlikely(error))
1594 break;
1595 error = get_user(len, &iov->iov_len);
1596 if (unlikely(error))
1597 break;
1598
1599 /*
1600 * Sanity check this iovec. 0 read succeeds.
1601 */
1602 if (unlikely(!len))
1603 break;
1604 if (unlikely(!base)) {
1605 error = -EFAULT;
1606 break;
1607 }
1608
1609 if (unlikely(!access_ok(VERIFY_WRITE, base, len))) {
1610 error = -EFAULT;
1611 break;
1612 }
1613
1614 sd.len = 0;
1615 sd.total_len = len;
1616 sd.flags = flags;
1617 sd.u.userptr = base;
1618 sd.pos = 0;
1619
1620 size = __splice_from_pipe(pipe, &sd, pipe_to_user);
1621 if (size < 0) {
1622 if (!ret)
1623 ret = size;
1624
1625 break;
1626 }
1627
1628 ret += size;
1629 1550
1630 if (size < len) 1551 iov_iter_init(&iter, iov, nr_segs, count, 0);
1631 break;
1632 1552
1633 nr_segs--; 1553 sd.len = 0;
1634 iov++; 1554 sd.total_len = count;
1635 } 1555 sd.flags = flags;
1556 sd.u.data = &iter;
1557 sd.pos = 0;
1636 1558
1559 pipe_lock(pipe);
1560 ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
1637 pipe_unlock(pipe); 1561 pipe_unlock(pipe);
1638 1562
1639 if (!ret) 1563 if (iov != iovstack)
1640 ret = error; 1564 kfree(iov);
1641 1565
1642 return ret; 1566 return ret;
1643} 1567}