Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[NET]: Fully fix the memory leaks in sys_accept().
[NETFILTER]: iptables 32bit compat layer
[NETFILTER]: {ip,nf}_conntrack_netlink: fix expectation notifier unregistration
[NETFILTER]: fix ifdef for connmark support in nf_conntrack_netlink
[NETFILTER]: x_tables: unify IPv4/IPv6 multiport match
[NETFILTER]: x_tables: unify IPv4/IPv6 esp match
[NET]: Fix dentry leak in sys_accept().
[IPSEC]: Kill unused decap state structure
[IPSEC]: Kill unused decap state argument
[NET]: com90xx kmalloc fix
[TG3]: Update driver version and reldate.
[TG3]: Revert "Speed up SRAM access"
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 1ad55f0..1424eab 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -322,3 +322,4 @@
COMPAT_SYS(pselect6)
COMPAT_SYS(ppoll)
SYSCALL(unshare)
+SYSCALL(splice)
diff --git a/fs/splice.c b/fs/splice.c
index 7c2bbf1..6081cf7 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -106,7 +106,7 @@
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 @@
break;
}
+ if (flags & SPLICE_F_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
@@ -191,7 +197,7 @@
}
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 @@
* 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 @@
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 @@
in->f_pos += ret;
len -= ret;
spliced += ret;
+
+ if (!(flags & SPLICE_F_NONBLOCK))
+ continue;
+ ret = -EAGAIN;
+ break;
}
if (spliced)
@@ -527,6 +538,12 @@
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 75c7f55..d218fc7 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -60,5 +60,8 @@
* 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