mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[PATCH] splice: pass offset around for ->splice_read() and ->splice_write()
We need not use ->f_pos as the offset for the file input/output. If the user passed an offset pointer in through sys_splice(), just use that and leave ->f_pos alone. Signed-off-by: Jens Axboe <axboe@suse.de>
This commit is contained in:
		
							parent
							
								
									2514395ef8
								
							
						
					
					
						commit
						cbb7e577e7
					
				
					 6 changed files with 74 additions and 66 deletions
				
			
		
							
								
								
									
										86
									
								
								fs/splice.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								fs/splice.c
									
									
									
									
									
								
							| 
						 | 
					@ -231,8 +231,9 @@ static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
__generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
 | 
					__generic_file_splice_read(struct file *in, loff_t *ppos,
 | 
				
			||||||
			   size_t len, unsigned int flags)
 | 
								   struct pipe_inode_info *pipe, size_t len,
 | 
				
			||||||
 | 
								   unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct address_space *mapping = in->f_mapping;
 | 
						struct address_space *mapping = in->f_mapping;
 | 
				
			||||||
	unsigned int offset, nr_pages;
 | 
						unsigned int offset, nr_pages;
 | 
				
			||||||
| 
						 | 
					@ -241,8 +242,8 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
 | 
				
			||||||
	pgoff_t index;
 | 
						pgoff_t index;
 | 
				
			||||||
	int i, error;
 | 
						int i, error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	index = in->f_pos >> PAGE_CACHE_SHIFT;
 | 
						index = *ppos >> PAGE_CACHE_SHIFT;
 | 
				
			||||||
	offset = in->f_pos & ~PAGE_CACHE_MASK;
 | 
						offset = *ppos & ~PAGE_CACHE_MASK;
 | 
				
			||||||
	nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 | 
						nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nr_pages > PIPE_BUFFERS)
 | 
						if (nr_pages > PIPE_BUFFERS)
 | 
				
			||||||
| 
						 | 
					@ -348,8 +349,9 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Will read pages from given file and fill them into a pipe.
 | 
					 * Will read pages from given file and fill them into a pipe.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
 | 
					ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
 | 
				
			||||||
				 size_t len, unsigned int flags)
 | 
									 struct pipe_inode_info *pipe, size_t len,
 | 
				
			||||||
 | 
									 unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ssize_t spliced;
 | 
						ssize_t spliced;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -358,12 +360,12 @@ ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
 | 
				
			||||||
	spliced = 0;
 | 
						spliced = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (len) {
 | 
						while (len) {
 | 
				
			||||||
		ret = __generic_file_splice_read(in, pipe, len, flags);
 | 
							ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (ret <= 0)
 | 
							if (ret <= 0)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		in->f_pos += ret;
 | 
							*ppos += ret;
 | 
				
			||||||
		len -= ret;
 | 
							len -= ret;
 | 
				
			||||||
		spliced += ret;
 | 
							spliced += ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -561,7 +563,7 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
 | 
				
			||||||
 * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
 | 
					 * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 | 
					static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
			      size_t len, unsigned int flags,
 | 
								      loff_t *ppos, size_t len, unsigned int flags,
 | 
				
			||||||
			      splice_actor *actor)
 | 
								      splice_actor *actor)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret, do_wakeup, err;
 | 
						int ret, do_wakeup, err;
 | 
				
			||||||
| 
						 | 
					@ -573,7 +575,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
	sd.total_len = len;
 | 
						sd.total_len = len;
 | 
				
			||||||
	sd.flags = flags;
 | 
						sd.flags = flags;
 | 
				
			||||||
	sd.file = out;
 | 
						sd.file = out;
 | 
				
			||||||
	sd.pos = out->f_pos;
 | 
						sd.pos = *ppos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pipe->inode)
 | 
						if (pipe->inode)
 | 
				
			||||||
		mutex_lock(&pipe->inode->i_mutex);
 | 
							mutex_lock(&pipe->inode->i_mutex);
 | 
				
			||||||
| 
						 | 
					@ -656,9 +658,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 | 
							kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	out->f_pos = sd.pos;
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -674,12 +674,12 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
ssize_t
 | 
					ssize_t
 | 
				
			||||||
generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 | 
					generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
			  size_t len, unsigned int flags)
 | 
								  loff_t *ppos, size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct address_space *mapping = out->f_mapping;
 | 
						struct address_space *mapping = out->f_mapping;
 | 
				
			||||||
	ssize_t ret;
 | 
						ssize_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = move_from_pipe(pipe, out, len, flags, pipe_to_file);
 | 
						ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If file or inode is SYNC and we actually wrote some data, sync it.
 | 
						 * If file or inode is SYNC and we actually wrote some data, sync it.
 | 
				
			||||||
| 
						 | 
					@ -715,9 +715,9 @@ EXPORT_SYMBOL(generic_file_splice_write);
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
 | 
					ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
				size_t len, unsigned int flags)
 | 
									loff_t *ppos, size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return move_from_pipe(pipe, out, len, flags, pipe_to_sendpage);
 | 
						return move_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPORT_SYMBOL(generic_splice_sendpage);
 | 
					EXPORT_SYMBOL(generic_splice_sendpage);
 | 
				
			||||||
| 
						 | 
					@ -726,9 +726,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
 | 
				
			||||||
 * Attempt to initiate a splice from pipe to file.
 | 
					 * Attempt to initiate a splice from pipe to file.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 | 
					static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
			   size_t len, unsigned int flags)
 | 
								   loff_t *ppos, size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	loff_t pos;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(!out->f_op || !out->f_op->splice_write))
 | 
						if (unlikely(!out->f_op || !out->f_op->splice_write))
 | 
				
			||||||
| 
						 | 
					@ -737,22 +736,21 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 | 
				
			||||||
	if (unlikely(!(out->f_mode & FMODE_WRITE)))
 | 
						if (unlikely(!(out->f_mode & FMODE_WRITE)))
 | 
				
			||||||
		return -EBADF;
 | 
							return -EBADF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pos = out->f_pos;
 | 
						ret = rw_verify_area(WRITE, out, ppos, len);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = rw_verify_area(WRITE, out, &pos, len);
 | 
					 | 
				
			||||||
	if (unlikely(ret < 0))
 | 
						if (unlikely(ret < 0))
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return out->f_op->splice_write(pipe, out, len, flags);
 | 
						return out->f_op->splice_write(pipe, out, ppos, len, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Attempt to initiate a splice from a file to a pipe.
 | 
					 * Attempt to initiate a splice from a file to a pipe.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static long do_splice_to(struct file *in, struct pipe_inode_info *pipe,
 | 
					static long do_splice_to(struct file *in, loff_t *ppos,
 | 
				
			||||||
			 size_t len, unsigned int flags)
 | 
								 struct pipe_inode_info *pipe, size_t len,
 | 
				
			||||||
 | 
								 unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	loff_t pos, isize, left;
 | 
						loff_t isize, left;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(!in->f_op || !in->f_op->splice_read))
 | 
						if (unlikely(!in->f_op || !in->f_op->splice_read))
 | 
				
			||||||
| 
						 | 
					@ -761,28 +759,27 @@ static long do_splice_to(struct file *in, struct pipe_inode_info *pipe,
 | 
				
			||||||
	if (unlikely(!(in->f_mode & FMODE_READ)))
 | 
						if (unlikely(!(in->f_mode & FMODE_READ)))
 | 
				
			||||||
		return -EBADF;
 | 
							return -EBADF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pos = in->f_pos;
 | 
						ret = rw_verify_area(READ, in, ppos, len);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = rw_verify_area(READ, in, &pos, len);
 | 
					 | 
				
			||||||
	if (unlikely(ret < 0))
 | 
						if (unlikely(ret < 0))
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isize = i_size_read(in->f_mapping->host);
 | 
						isize = i_size_read(in->f_mapping->host);
 | 
				
			||||||
	if (unlikely(in->f_pos >= isize))
 | 
						if (unlikely(*ppos >= isize))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	left = isize - in->f_pos;
 | 
						left = isize - *ppos;
 | 
				
			||||||
	if (unlikely(left < len))
 | 
						if (unlikely(left < len))
 | 
				
			||||||
		len = left;
 | 
							len = left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return in->f_op->splice_read(in, pipe, len, flags);
 | 
						return in->f_op->splice_read(in, ppos, pipe, len, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
long do_splice_direct(struct file *in, struct file *out, size_t len,
 | 
					long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 | 
				
			||||||
		      unsigned int flags)
 | 
							      size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pipe_inode_info *pipe;
 | 
						struct pipe_inode_info *pipe;
 | 
				
			||||||
	long ret, bytes;
 | 
						long ret, bytes;
 | 
				
			||||||
 | 
						loff_t out_off;
 | 
				
			||||||
	umode_t i_mode;
 | 
						umode_t i_mode;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -820,6 +817,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ret = 0;
 | 
						ret = 0;
 | 
				
			||||||
	bytes = 0;
 | 
						bytes = 0;
 | 
				
			||||||
 | 
						out_off = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (len) {
 | 
						while (len) {
 | 
				
			||||||
		size_t read_len, max_read_len;
 | 
							size_t read_len, max_read_len;
 | 
				
			||||||
| 
						 | 
					@ -829,7 +827,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len,
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
 | 
							max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = do_splice_to(in, pipe, max_read_len, flags);
 | 
							ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
 | 
				
			||||||
		if (unlikely(ret < 0))
 | 
							if (unlikely(ret < 0))
 | 
				
			||||||
			goto out_release;
 | 
								goto out_release;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -840,7 +838,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len,
 | 
				
			||||||
		 * must not do the output in nonblocking mode as then we
 | 
							 * must not do the output in nonblocking mode as then we
 | 
				
			||||||
		 * could get stuck data in the internal pipe:
 | 
							 * could get stuck data in the internal pipe:
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		ret = do_splice_from(pipe, out, read_len,
 | 
							ret = do_splice_from(pipe, out, &out_off, read_len,
 | 
				
			||||||
				     flags & ~SPLICE_F_NONBLOCK);
 | 
									     flags & ~SPLICE_F_NONBLOCK);
 | 
				
			||||||
		if (unlikely(ret < 0))
 | 
							if (unlikely(ret < 0))
 | 
				
			||||||
			goto out_release;
 | 
								goto out_release;
 | 
				
			||||||
| 
						 | 
					@ -898,6 +896,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
 | 
				
			||||||
		      size_t len, unsigned int flags)
 | 
							      size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pipe_inode_info *pipe;
 | 
						struct pipe_inode_info *pipe;
 | 
				
			||||||
 | 
						loff_t offset, *off;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pipe = in->f_dentry->d_inode->i_pipe;
 | 
						pipe = in->f_dentry->d_inode->i_pipe;
 | 
				
			||||||
	if (pipe) {
 | 
						if (pipe) {
 | 
				
			||||||
| 
						 | 
					@ -906,12 +905,13 @@ static long do_splice(struct file *in, loff_t __user *off_in,
 | 
				
			||||||
		if (off_out) {
 | 
							if (off_out) {
 | 
				
			||||||
			if (out->f_op->llseek == no_llseek)
 | 
								if (out->f_op->llseek == no_llseek)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			if (copy_from_user(&out->f_pos, off_out,
 | 
								if (copy_from_user(&offset, off_out, sizeof(loff_t)))
 | 
				
			||||||
					   sizeof(loff_t)))
 | 
					 | 
				
			||||||
				return -EFAULT;
 | 
									return -EFAULT;
 | 
				
			||||||
		}
 | 
								off = &offset;
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								off = &out->f_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return do_splice_from(pipe, out, len, flags);
 | 
							return do_splice_from(pipe, out, off, len, flags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pipe = out->f_dentry->d_inode->i_pipe;
 | 
						pipe = out->f_dentry->d_inode->i_pipe;
 | 
				
			||||||
| 
						 | 
					@ -921,11 +921,13 @@ static long do_splice(struct file *in, loff_t __user *off_in,
 | 
				
			||||||
		if (off_in) {
 | 
							if (off_in) {
 | 
				
			||||||
			if (in->f_op->llseek == no_llseek)
 | 
								if (in->f_op->llseek == no_llseek)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			if (copy_from_user(&in->f_pos, off_in, sizeof(loff_t)))
 | 
								if (copy_from_user(&offset, off_in, sizeof(loff_t)))
 | 
				
			||||||
				return -EFAULT;
 | 
									return -EFAULT;
 | 
				
			||||||
		}
 | 
								off = &offset;
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								off = &in->f_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return do_splice_to(in, pipe, len, flags);
 | 
							return do_splice_to(in, off, pipe, len, flags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return -EINVAL;
 | 
						return -EINVAL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -252,6 +252,7 @@ xfs_file_sendfile_invis(
 | 
				
			||||||
STATIC ssize_t
 | 
					STATIC ssize_t
 | 
				
			||||||
xfs_file_splice_read(
 | 
					xfs_file_splice_read(
 | 
				
			||||||
	struct file		*infilp,
 | 
						struct file		*infilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	size_t			len,
 | 
						size_t			len,
 | 
				
			||||||
	unsigned int		flags)
 | 
						unsigned int		flags)
 | 
				
			||||||
| 
						 | 
					@ -259,13 +260,14 @@ xfs_file_splice_read(
 | 
				
			||||||
	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
 | 
						vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
 | 
				
			||||||
	ssize_t			rval;
 | 
						ssize_t			rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval);
 | 
						VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
 | 
				
			||||||
	return rval;
 | 
						return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STATIC ssize_t
 | 
					STATIC ssize_t
 | 
				
			||||||
xfs_file_splice_read_invis(
 | 
					xfs_file_splice_read_invis(
 | 
				
			||||||
	struct file		*infilp,
 | 
						struct file		*infilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	size_t			len,
 | 
						size_t			len,
 | 
				
			||||||
	unsigned int		flags)
 | 
						unsigned int		flags)
 | 
				
			||||||
| 
						 | 
					@ -273,7 +275,7 @@ xfs_file_splice_read_invis(
 | 
				
			||||||
	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
 | 
						vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
 | 
				
			||||||
	ssize_t			rval;
 | 
						ssize_t			rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval);
 | 
						VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
 | 
				
			||||||
	return rval;
 | 
						return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,13 +283,14 @@ STATIC ssize_t
 | 
				
			||||||
xfs_file_splice_write(
 | 
					xfs_file_splice_write(
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	struct file		*outfilp,
 | 
						struct file		*outfilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	size_t			len,
 | 
						size_t			len,
 | 
				
			||||||
	unsigned int		flags)
 | 
						unsigned int		flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
 | 
						vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
 | 
				
			||||||
	ssize_t			rval;
 | 
						ssize_t			rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval);
 | 
						VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
 | 
				
			||||||
	return rval;
 | 
						return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,13 +298,14 @@ STATIC ssize_t
 | 
				
			||||||
xfs_file_splice_write_invis(
 | 
					xfs_file_splice_write_invis(
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	struct file		*outfilp,
 | 
						struct file		*outfilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	size_t			len,
 | 
						size_t			len,
 | 
				
			||||||
	unsigned int		flags)
 | 
						unsigned int		flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
 | 
						vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
 | 
				
			||||||
	ssize_t			rval;
 | 
						ssize_t			rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval);
 | 
						VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
 | 
				
			||||||
	return rval;
 | 
						return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -338,6 +338,7 @@ ssize_t
 | 
				
			||||||
xfs_splice_read(
 | 
					xfs_splice_read(
 | 
				
			||||||
	bhv_desc_t		*bdp,
 | 
						bhv_desc_t		*bdp,
 | 
				
			||||||
	struct file		*infilp,
 | 
						struct file		*infilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	size_t			count,
 | 
						size_t			count,
 | 
				
			||||||
	int			flags,
 | 
						int			flags,
 | 
				
			||||||
| 
						 | 
					@ -360,7 +361,7 @@ xfs_splice_read(
 | 
				
			||||||
		int error;
 | 
							int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
 | 
							error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
 | 
				
			||||||
					infilp->f_pos, count,
 | 
										*ppos, count,
 | 
				
			||||||
					FILP_DELAY_FLAG(infilp), &locktype);
 | 
										FILP_DELAY_FLAG(infilp), &locktype);
 | 
				
			||||||
		if (error) {
 | 
							if (error) {
 | 
				
			||||||
			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 | 
								xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 | 
				
			||||||
| 
						 | 
					@ -368,8 +369,8 @@ xfs_splice_read(
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
 | 
						xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
 | 
				
			||||||
			   pipe, count, infilp->f_pos, ioflags);
 | 
								   pipe, count, *ppos, ioflags);
 | 
				
			||||||
	ret = generic_file_splice_read(infilp, pipe, count, flags);
 | 
						ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
 | 
				
			||||||
	if (ret > 0)
 | 
						if (ret > 0)
 | 
				
			||||||
		XFS_STATS_ADD(xs_read_bytes, ret);
 | 
							XFS_STATS_ADD(xs_read_bytes, ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,6 +383,7 @@ xfs_splice_write(
 | 
				
			||||||
	bhv_desc_t		*bdp,
 | 
						bhv_desc_t		*bdp,
 | 
				
			||||||
	struct pipe_inode_info	*pipe,
 | 
						struct pipe_inode_info	*pipe,
 | 
				
			||||||
	struct file		*outfilp,
 | 
						struct file		*outfilp,
 | 
				
			||||||
 | 
						loff_t			*ppos,
 | 
				
			||||||
	size_t			count,
 | 
						size_t			count,
 | 
				
			||||||
	int			flags,
 | 
						int			flags,
 | 
				
			||||||
	int			ioflags,
 | 
						int			ioflags,
 | 
				
			||||||
| 
						 | 
					@ -403,7 +405,7 @@ xfs_splice_write(
 | 
				
			||||||
		int error;
 | 
							int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
 | 
							error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
 | 
				
			||||||
					outfilp->f_pos, count,
 | 
										*ppos, count,
 | 
				
			||||||
					FILP_DELAY_FLAG(outfilp), &locktype);
 | 
										FILP_DELAY_FLAG(outfilp), &locktype);
 | 
				
			||||||
		if (error) {
 | 
							if (error) {
 | 
				
			||||||
			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 | 
								xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 | 
				
			||||||
| 
						 | 
					@ -411,8 +413,8 @@ xfs_splice_write(
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
 | 
						xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
 | 
				
			||||||
			   pipe, count, outfilp->f_pos, ioflags);
 | 
								   pipe, count, *ppos, ioflags);
 | 
				
			||||||
	ret = generic_file_splice_write(pipe, outfilp, count, flags);
 | 
						ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
 | 
				
			||||||
	if (ret > 0)
 | 
						if (ret > 0)
 | 
				
			||||||
		XFS_STATS_ADD(xs_write_bytes, ret);
 | 
							XFS_STATS_ADD(xs_write_bytes, ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,11 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
 | 
				
			||||||
extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
 | 
					extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
 | 
				
			||||||
				loff_t *, int, size_t, read_actor_t,
 | 
									loff_t *, int, size_t, read_actor_t,
 | 
				
			||||||
				void *, struct cred *);
 | 
									void *, struct cred *);
 | 
				
			||||||
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *,
 | 
					extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
 | 
				
			||||||
				struct pipe_inode_info *, size_t, int, int,
 | 
									struct pipe_inode_info *, size_t, int, int,
 | 
				
			||||||
				struct cred *);
 | 
									struct cred *);
 | 
				
			||||||
extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
 | 
					extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
 | 
				
			||||||
				struct file *, size_t, int, int,
 | 
									struct file *, loff_t *, size_t, int, int,
 | 
				
			||||||
				struct cred *);
 | 
									struct cred *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif	/* __XFS_LRW_H__ */
 | 
					#endif	/* __XFS_LRW_H__ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,11 +173,11 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
 | 
				
			||||||
typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
 | 
					typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
 | 
				
			||||||
				loff_t *, int, size_t, read_actor_t,
 | 
									loff_t *, int, size_t, read_actor_t,
 | 
				
			||||||
				void *, struct cred *);
 | 
									void *, struct cred *);
 | 
				
			||||||
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *,
 | 
					typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
 | 
				
			||||||
				struct pipe_inode_info *, size_t, int, int,
 | 
									struct pipe_inode_info *, size_t, int, int,
 | 
				
			||||||
				struct cred *);
 | 
									struct cred *);
 | 
				
			||||||
typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
 | 
					typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
 | 
				
			||||||
				struct file *, size_t, int, int,
 | 
									struct file *, loff_t *, size_t, int, int,
 | 
				
			||||||
				struct cred *);
 | 
									struct cred *);
 | 
				
			||||||
typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
 | 
					typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
 | 
				
			||||||
				int, unsigned int, void __user *);
 | 
									int, unsigned int, void __user *);
 | 
				
			||||||
| 
						 | 
					@ -284,10 +284,10 @@ typedef struct vnodeops {
 | 
				
			||||||
	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
 | 
						rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
 | 
				
			||||||
#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv)		\
 | 
					#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv)		\
 | 
				
			||||||
	rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
 | 
						rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
 | 
				
			||||||
#define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv)			\
 | 
					#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
 | 
				
			||||||
	rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr)
 | 
						rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
 | 
				
			||||||
#define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv)			\
 | 
					#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
 | 
				
			||||||
	rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr)
 | 
						rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
 | 
				
			||||||
#define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
 | 
					#define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
 | 
				
			||||||
	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
 | 
						rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
 | 
				
			||||||
#define VOP_OPEN(vp, cr, rv)						\
 | 
					#define VOP_OPEN(vp, cr, rv)						\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1039,8 +1039,8 @@ struct file_operations {
 | 
				
			||||||
	int (*check_flags)(int);
 | 
						int (*check_flags)(int);
 | 
				
			||||||
	int (*dir_notify)(struct file *filp, unsigned long arg);
 | 
						int (*dir_notify)(struct file *filp, unsigned long arg);
 | 
				
			||||||
	int (*flock) (struct file *, int, struct file_lock *);
 | 
						int (*flock) (struct file *, int, struct file_lock *);
 | 
				
			||||||
	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
 | 
						ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
 | 
				
			||||||
	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
 | 
						ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct inode_operations {
 | 
					struct inode_operations {
 | 
				
			||||||
| 
						 | 
					@ -1613,13 +1613,13 @@ extern void do_generic_mapping_read(struct address_space *mapping,
 | 
				
			||||||
				    loff_t *, read_descriptor_t *, read_actor_t);
 | 
									    loff_t *, read_descriptor_t *, read_actor_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* fs/splice.c */
 | 
					/* fs/splice.c */
 | 
				
			||||||
extern ssize_t generic_file_splice_read(struct file *,
 | 
					extern ssize_t generic_file_splice_read(struct file *, loff_t *,
 | 
				
			||||||
		struct pipe_inode_info *, size_t, unsigned int);
 | 
							struct pipe_inode_info *, size_t, unsigned int);
 | 
				
			||||||
extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
 | 
					extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
 | 
				
			||||||
		struct file *, size_t, unsigned int);
 | 
							struct file *, loff_t *, size_t, unsigned int);
 | 
				
			||||||
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
 | 
					extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
 | 
				
			||||||
		struct file *out, size_t len, unsigned int flags);
 | 
							struct file *out, loff_t *, size_t len, unsigned int flags);
 | 
				
			||||||
extern long do_splice_direct(struct file *in, struct file *out,
 | 
					extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 | 
				
			||||||
		size_t len, unsigned int flags);
 | 
							size_t len, unsigned int flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void
 | 
					extern void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue