diff options
| -rw-r--r-- | fs/splice.c | 25 | ||||
| -rw-r--r-- | include/linux/pipe_fs_i.h | 3 | 
2 files changed, 24 insertions, 4 deletions
diff --git a/fs/splice.c b/fs/splice.c index 7c2bbf18d7a..6081cf7d2d1 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -106,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {  static ssize_t move_to_pipe(struct inode *inode, struct page **pages,  			    int nr_pages, unsigned long offset, -			    unsigned long len) +			    unsigned long len, unsigned int flags)  {  	struct pipe_inode_info *info;  	int ret, do_wakeup, i; @@ -159,6 +159,12 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,  			break;  		} +		if (flags & SPLICE_F_NONBLOCK) { +			if (!ret) +				ret = -EAGAIN; +			break; +		} +  		if (signal_pending(current)) {  			if (!ret)  				ret = -ERESTARTSYS; @@ -191,7 +197,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,  }  static int __generic_file_splice_read(struct file *in, struct inode *pipe, -				      size_t len) +				      size_t len, unsigned int flags)  {  	struct address_space *mapping = in->f_mapping;  	unsigned int offset, nr_pages; @@ -279,7 +285,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,  	 * Now we splice them into the pipe..  	 */  splice_them: -	return move_to_pipe(pipe, pages, i, offset, len); +	return move_to_pipe(pipe, pages, i, offset, len, flags);  }  ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, @@ -291,7 +297,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,  	ret = 0;  	spliced = 0;  	while (len) { -		ret = __generic_file_splice_read(in, pipe, len); +		ret = __generic_file_splice_read(in, pipe, len, flags);  		if (ret <= 0)  			break; @@ -299,6 +305,11 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,  		in->f_pos += ret;  		len -= ret;  		spliced += ret; + +		if (!(flags & SPLICE_F_NONBLOCK)) +			continue; +		ret = -EAGAIN; +		break;  	}  	if (spliced) @@ -527,6 +538,12 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,  				break;  		} +		if (flags & SPLICE_F_NONBLOCK) { +			if (!ret) +				ret = -EAGAIN; +			break; +		} +  		if (signal_pending(current)) {  			if (!ret)  				ret = -ERESTARTSYS; diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 75c7f55023a..d218fc72931 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -60,5 +60,8 @@ void free_pipe_info(struct inode* inode);   * add the splice flags here.   */  #define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */ +#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */ +				 /* we may still block on the fd we splice */ +				 /* from/to, of course */  #endif  |