diff options
Diffstat (limited to 'fs/splice.c')
| -rw-r--r-- | fs/splice.c | 14 | 
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/splice.c b/fs/splice.c index de2ede048473..6489fb9436e4 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -357,7 +357,7 @@ static ssize_t kernel_readv(struct file *file, const struct kvec *vec,  	ssize_t res;  	old_fs = get_fs(); -	set_fs(get_ds()); +	set_fs(KERNEL_DS);  	/* The cast to a user pointer is valid due to the set_fs() */  	res = vfs_readv(file, (const struct iovec __user *)vec, vlen, &pos, 0);  	set_fs(old_fs); @@ -1123,6 +1123,9 @@ static long do_splice(struct file *in, loff_t __user *off_in,  		if (ipipe == opipe)  			return -EINVAL; +		if ((in->f_flags | out->f_flags) & O_NONBLOCK) +			flags |= SPLICE_F_NONBLOCK; +  		return splice_pipe_to_pipe(ipipe, opipe, len, flags);  	} @@ -1148,6 +1151,9 @@ static long do_splice(struct file *in, loff_t __user *off_in,  		if (unlikely(ret < 0))  			return ret; +		if (in->f_flags & O_NONBLOCK) +			flags |= SPLICE_F_NONBLOCK; +  		file_start_write(out);  		ret = do_splice_from(ipipe, out, &offset, len, flags);  		file_end_write(out); @@ -1172,6 +1178,9 @@ static long do_splice(struct file *in, loff_t __user *off_in,  			offset = in->f_pos;  		} +		if (out->f_flags & O_NONBLOCK) +			flags |= SPLICE_F_NONBLOCK; +  		pipe_lock(opipe);  		ret = wait_for_space(opipe, flags);  		if (!ret) @@ -1717,6 +1726,9 @@ static long do_tee(struct file *in, struct file *out, size_t len,  	 * copying the data.  	 */  	if (ipipe && opipe && ipipe != opipe) { +		if ((in->f_flags | out->f_flags) & O_NONBLOCK) +			flags |= SPLICE_F_NONBLOCK; +  		/*  		 * Keep going, unless we encounter an error. The ipipe/opipe  		 * ordering doesn't really matter.  |