diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-03-06 20:24:46 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-04-26 18:02:34 -0400 |
commit | 6af67d8205cf65fbaaa743edc7ebb46e486e34ff (patch) | |
tree | 1aadef5c71e4f8905477a813b1bd0a35e62ccbee /fs/ocfs2/aops.c | |
parent | fa41045fcbf78269991d5aebb1820fc51534f05d (diff) |
ocfs2: Use own splice write actor
We need to fill holes during a splice write. Provide our own splice write
actor which can call ocfs2_file_buffered_write() with a splice-specific
callback.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 69 |
1 files changed, 69 insertions, 0 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 | */ |