diff options
| -rw-r--r-- | fs/ocfs2/aops.c | 69 | ||||
| -rw-r--r-- | fs/ocfs2/aops.h | 14 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 80 |
3 files changed, 162 insertions, 1 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 605c82a93f01..014f4f52809c 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
| 26 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
| 27 | #include <linux/swap.h> | 27 | #include <linux/swap.h> |
| 28 | #include <linux/pipe_fs_i.h> | ||
| 28 | 29 | ||
| 29 | #define MLOG_MASK_PREFIX ML_FILE_IO | 30 | #define MLOG_MASK_PREFIX ML_FILE_IO |
| 30 | #include <cluster/masklog.h> | 31 | #include <cluster/masklog.h> |
| @@ -749,6 +750,74 @@ next_bh: | |||
| 749 | } | 750 | } |
| 750 | 751 | ||
| 751 | /* | 752 | /* |
| 753 | * This will copy user data from the buffer page in the splice | ||
| 754 | * context. | ||
| 755 | * | ||
| 756 | * For now, we ignore SPLICE_F_MOVE as that would require some extra | ||
| 757 | * communication out all the way to ocfs2_write(). | ||
| 758 | */ | ||
| 759 | int ocfs2_map_and_write_splice_data(struct inode *inode, | ||
| 760 | struct ocfs2_write_ctxt *wc, u64 *p_blkno, | ||
| 761 | unsigned int *ret_from, unsigned int *ret_to) | ||
| 762 | { | ||
| 763 | int ret; | ||
| 764 | unsigned int to, from, cluster_start, cluster_end; | ||
| 765 | char *src, *dst; | ||
| 766 | struct ocfs2_splice_write_priv *sp = wc->w_private; | ||
| 767 | struct pipe_buffer *buf = sp->s_buf; | ||
| 768 | unsigned long bytes, src_from; | ||
| 769 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 770 | |||
| 771 | ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start, | ||
| 772 | &cluster_end); | ||
| 773 | |||
| 774 | from = sp->s_offset; | ||
| 775 | src_from = sp->s_buf_offset; | ||
| 776 | bytes = wc->w_count; | ||
| 777 | |||
| 778 | if (wc->w_large_pages) { | ||
| 779 | /* | ||
| 780 | * For cluster size < page size, we have to | ||
| 781 | * calculate pos within the cluster and obey | ||
| 782 | * the rightmost boundary. | ||
| 783 | */ | ||
| 784 | bytes = min(bytes, (unsigned long)(osb->s_clustersize | ||
| 785 | - (wc->w_pos & (osb->s_clustersize - 1)))); | ||
| 786 | } | ||
| 787 | to = from + bytes; | ||
| 788 | |||
| 789 | if (wc->w_this_page_new) | ||
| 790 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, | ||
| 791 | cluster_start, cluster_end, 1); | ||
| 792 | else | ||
| 793 | ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, | ||
| 794 | from, to, 0); | ||
| 795 | if (ret) { | ||
| 796 | mlog_errno(ret); | ||
| 797 | goto out; | ||
| 798 | } | ||
| 799 | |||
| 800 | BUG_ON(from > PAGE_CACHE_SIZE); | ||
| 801 | BUG_ON(to > PAGE_CACHE_SIZE); | ||
| 802 | BUG_ON(from > osb->s_clustersize); | ||
| 803 | BUG_ON(to > osb->s_clustersize); | ||
| 804 | |||
| 805 | src = buf->ops->map(sp->s_pipe, buf, 1); | ||
| 806 | dst = kmap_atomic(wc->w_this_page, KM_USER1); | ||
| 807 | memcpy(dst + from, src + src_from, bytes); | ||
| 808 | kunmap_atomic(wc->w_this_page, KM_USER1); | ||
| 809 | buf->ops->unmap(sp->s_pipe, buf, src); | ||
| 810 | |||
| 811 | wc->w_finished_copy = 1; | ||
| 812 | |||
| 813 | *ret_from = from; | ||
| 814 | *ret_to = to; | ||
| 815 | out: | ||
| 816 | |||
| 817 | return bytes ? (unsigned int)bytes : ret; | ||
| 818 | } | ||
| 819 | |||
| 820 | /* | ||
| 752 | * This will copy user data from the iovec in the buffered write | 821 | * This will copy user data from the iovec in the buffered write |
| 753 | * context. | 822 | * context. |
| 754 | */ | 823 | */ |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index 7d94071f0ab7..1b4ba5356a42 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
| @@ -80,6 +80,20 @@ int ocfs2_map_and_write_user_data(struct inode *inode, | |||
| 80 | unsigned int *ret_from, | 80 | unsigned int *ret_from, |
| 81 | unsigned int *ret_to); | 81 | unsigned int *ret_to); |
| 82 | 82 | ||
| 83 | struct ocfs2_splice_write_priv { | ||
| 84 | struct splice_desc *s_sd; | ||
| 85 | struct pipe_buffer *s_buf; | ||
| 86 | struct pipe_inode_info *s_pipe; | ||
| 87 | /* Neither offset value is ever larger than one page */ | ||
| 88 | unsigned int s_offset; | ||
| 89 | unsigned int s_buf_offset; | ||
| 90 | }; | ||
| 91 | int ocfs2_map_and_write_splice_data(struct inode *inode, | ||
| 92 | struct ocfs2_write_ctxt *wc, | ||
| 93 | u64 *p_blkno, | ||
| 94 | unsigned int *ret_from, | ||
| 95 | unsigned int *ret_to); | ||
| 96 | |||
| 83 | /* all ocfs2_dio_end_io()'s fault */ | 97 | /* all ocfs2_dio_end_io()'s fault */ |
| 84 | #define ocfs2_iocb_is_rw_locked(iocb) \ | 98 | #define ocfs2_iocb_is_rw_locked(iocb) \ |
| 85 | test_bit(0, (unsigned long *)&iocb->private) | 99 | test_bit(0, (unsigned long *)&iocb->private) |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 5fd49ec169dc..f516619a3744 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1603,6 +1603,84 @@ out_sems: | |||
| 1603 | return written ? written : ret; | 1603 | return written ? written : ret; |
| 1604 | } | 1604 | } |
| 1605 | 1605 | ||
| 1606 | static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe, | ||
| 1607 | struct pipe_buffer *buf, | ||
| 1608 | struct splice_desc *sd) | ||
| 1609 | { | ||
| 1610 | int ret, count, total = 0; | ||
| 1611 | ssize_t copied = 0; | ||
| 1612 | struct ocfs2_splice_write_priv sp; | ||
| 1613 | |||
| 1614 | ret = buf->ops->pin(pipe, buf); | ||
| 1615 | if (ret) | ||
| 1616 | goto out; | ||
| 1617 | |||
| 1618 | sp.s_sd = sd; | ||
| 1619 | sp.s_buf = buf; | ||
| 1620 | sp.s_pipe = pipe; | ||
| 1621 | sp.s_offset = sd->pos & ~PAGE_CACHE_MASK; | ||
| 1622 | sp.s_buf_offset = buf->offset; | ||
| 1623 | |||
| 1624 | count = sd->len; | ||
| 1625 | if (count + sp.s_offset > PAGE_CACHE_SIZE) | ||
| 1626 | count = PAGE_CACHE_SIZE - sp.s_offset; | ||
| 1627 | |||
| 1628 | do { | ||
| 1629 | /* | ||
| 1630 | * splice wants us to copy up to one page at a | ||
| 1631 | * time. For pagesize > cluster size, this means we | ||
| 1632 | * might enter ocfs2_buffered_write_cluster() more | ||
| 1633 | * than once, so keep track of our progress here. | ||
| 1634 | */ | ||
| 1635 | copied = ocfs2_buffered_write_cluster(sd->file, | ||
| 1636 | (loff_t)sd->pos + total, | ||
| 1637 | count, | ||
| 1638 | ocfs2_map_and_write_splice_data, | ||
| 1639 | &sp); | ||
| 1640 | if (copied < 0) { | ||
| 1641 | mlog_errno(copied); | ||
| 1642 | ret = copied; | ||
| 1643 | goto out; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | count -= copied; | ||
| 1647 | sp.s_offset += copied; | ||
| 1648 | sp.s_buf_offset += copied; | ||
| 1649 | total += copied; | ||
| 1650 | } while (count); | ||
| 1651 | |||
| 1652 | ret = 0; | ||
| 1653 | out: | ||
| 1654 | |||
| 1655 | return total ? total : ret; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe, | ||
| 1659 | struct file *out, | ||
| 1660 | loff_t *ppos, | ||
| 1661 | size_t len, | ||
| 1662 | unsigned int flags) | ||
| 1663 | { | ||
| 1664 | int ret, err; | ||
| 1665 | struct address_space *mapping = out->f_mapping; | ||
| 1666 | struct inode *inode = mapping->host; | ||
| 1667 | |||
| 1668 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, | ||
| 1669 | ocfs2_splice_write_actor); | ||
| 1670 | if (ret > 0) { | ||
| 1671 | *ppos += ret; | ||
| 1672 | |||
| 1673 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | ||
| 1674 | err = generic_osync_inode(inode, mapping, | ||
| 1675 | OSYNC_METADATA|OSYNC_DATA); | ||
| 1676 | if (err) | ||
| 1677 | ret = err; | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | return ret; | ||
| 1682 | } | ||
| 1683 | |||
| 1606 | static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, | 1684 | static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, |
| 1607 | struct file *out, | 1685 | struct file *out, |
| 1608 | loff_t *ppos, | 1686 | loff_t *ppos, |
| @@ -1633,7 +1711,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, | |||
| 1633 | } | 1711 | } |
| 1634 | 1712 | ||
| 1635 | /* ok, we're done with i_size and alloc work */ | 1713 | /* ok, we're done with i_size and alloc work */ |
| 1636 | ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags); | 1714 | ret = __ocfs2_file_splice_write(pipe, out, ppos, len, flags); |
| 1637 | 1715 | ||
| 1638 | out_unlock: | 1716 | out_unlock: |
| 1639 | ocfs2_rw_unlock(inode, 1); | 1717 | ocfs2_rw_unlock(inode, 1); |
