From 9594ab7877f27f99e43cc28174e5a550d1f3151b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 2 Apr 2006 12:47:12 -0700 Subject: [PATCH] --- yaml --- r: 25027 b: refs/heads/master c: bacd3add087770333bdce65cd3dd25e3b2cd67ac h: refs/heads/master i: 25025: 46c908966e86ed9c441b1a0b48dd584261faa846 25023: c86e3e1e87f4df570cb781041f42b7c13468cd29 v: v3 --- [refs] | 2 +- trunk/arch/powerpc/kernel/systbl.S | 1 + trunk/fs/splice.c | 25 +++++++++++++++++++++---- trunk/include/linux/pipe_fs_i.h | 3 +++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index b5f4ea991e9d..477cc376e25c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9a1875e60e61b563737d8d1fc3876b279710fe93 +refs/heads/master: bacd3add087770333bdce65cd3dd25e3b2cd67ac diff --git a/trunk/arch/powerpc/kernel/systbl.S b/trunk/arch/powerpc/kernel/systbl.S index 1ad55f0466fd..1424eab450ee 100644 --- a/trunk/arch/powerpc/kernel/systbl.S +++ b/trunk/arch/powerpc/kernel/systbl.S @@ -322,3 +322,4 @@ SYSCALL(spu_create) COMPAT_SYS(pselect6) COMPAT_SYS(ppoll) SYSCALL(unshare) +SYSCALL(splice) diff --git a/trunk/fs/splice.c b/trunk/fs/splice.c index 7c2bbf18d7a7..6081cf7d2d1b 100644 --- a/trunk/fs/splice.c +++ b/trunk/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/trunk/include/linux/pipe_fs_i.h b/trunk/include/linux/pipe_fs_i.h index 75c7f55023ab..d218fc729319 100644 --- a/trunk/include/linux/pipe_fs_i.h +++ b/trunk/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