summaryrefslogtreecommitdiff
path: root/fs/splice.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-04-02 23:46:35 +0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-02 23:46:35 +0400
commit29e350944fdc2dfca102500790d8ad6d6ff4f69d (patch)
tree7630809d75149b0053dcc45ad34e95d5506e88b3 /fs/splice.c
parentb45e516f701e0fc81fb3dbd1ba9db35f991a4465 (diff)
downloadlinux-29e350944fdc2dfca102500790d8ad6d6ff4f69d.tar.xz
splice: add SPLICE_F_NONBLOCK flag
It doesn't make the splice itself necessarily nonblocking (because the actual file descriptors that are spliced from/to may block unless they have the O_NONBLOCK flag set), but it makes the splice pipe operations nonblocking. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 7c2bbf18d7a7..6081cf7d2d1b 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;