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>
This commit is contained in:
Mark Fasheh
2007-03-06 17:24:46 -08:00
parent fa41045fcb
commit 6af67d8205
3 changed files with 162 additions and 1 deletions

View File

@@ -25,6 +25,7 @@
#include <linux/pagemap.h>
#include <asm/byteorder.h>
#include <linux/swap.h>
#include <linux/pipe_fs_i.h>
#define MLOG_MASK_PREFIX ML_FILE_IO
#include <cluster/masklog.h>
@@ -748,6 +749,74 @@ next_bh:
return ret;
}
/*
* This will copy user data from the buffer page in the splice
* context.
*
* For now, we ignore SPLICE_F_MOVE as that would require some extra
* communication out all the way to ocfs2_write().
*/
int ocfs2_map_and_write_splice_data(struct inode *inode,
struct ocfs2_write_ctxt *wc, u64 *p_blkno,
unsigned int *ret_from, unsigned int *ret_to)
{
int ret;
unsigned int to, from, cluster_start, cluster_end;
char *src, *dst;
struct ocfs2_splice_write_priv *sp = wc->w_private;
struct pipe_buffer *buf = sp->s_buf;
unsigned long bytes, src_from;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
&cluster_end);
from = sp->s_offset;
src_from = sp->s_buf_offset;
bytes = wc->w_count;
if (wc->w_large_pages) {
/*
* For cluster size < page size, we have to
* calculate pos within the cluster and obey
* the rightmost boundary.
*/
bytes = min(bytes, (unsigned long)(osb->s_clustersize
- (wc->w_pos & (osb->s_clustersize - 1))));
}
to = from + bytes;
if (wc->w_this_page_new)
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
cluster_start, cluster_end, 1);
else
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
from, to, 0);
if (ret) {
mlog_errno(ret);
goto out;
}
BUG_ON(from > PAGE_CACHE_SIZE);
BUG_ON(to > PAGE_CACHE_SIZE);
BUG_ON(from > osb->s_clustersize);
BUG_ON(to > osb->s_clustersize);
src = buf->ops->map(sp->s_pipe, buf, 1);
dst = kmap_atomic(wc->w_this_page, KM_USER1);
memcpy(dst + from, src + src_from, bytes);
kunmap_atomic(wc->w_this_page, KM_USER1);
buf->ops->unmap(sp->s_pipe, buf, src);
wc->w_finished_copy = 1;
*ret_from = from;
*ret_to = to;
out:
return bytes ? (unsigned int)bytes : ret;
}
/*
* This will copy user data from the iovec in the buffered write
* context.