Message ID | 496D25F8.2080505@cosmosbay.com |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
From: Eric Dumazet <dada1@cosmosbay.com> Date: Wed, 14 Jan 2009 00:38:32 +0100 > [PATCH] net: splice() from tcp to socket should take into account O_NONBLOCK > > Instead of using SPLICE_F_NONBLOCK to select a non blocking mode both on > source tcp socket and pipe destination, we use the underlying file flag (O_NONBLOCK) > for selecting a non blocking socket. > > Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> This needs at least some more thought. It seems, for one thing, that this change will interfere with the intentions of the code in splice_dirt_to_actor which goes: /* * Don't block on output, we have to drain the direct pipe. */ sd->flags &= ~SPLICE_F_NONBLOCK; -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller a écrit : > From: Eric Dumazet <dada1@cosmosbay.com> > Date: Wed, 14 Jan 2009 00:38:32 +0100 > >> [PATCH] net: splice() from tcp to socket should take into account O_NONBLOCK >> >> Instead of using SPLICE_F_NONBLOCK to select a non blocking mode both on >> source tcp socket and pipe destination, we use the underlying file flag (O_NONBLOCK) >> for selecting a non blocking socket. >> >> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> > > This needs at least some more thought. > > It seems, for one thing, that this change will interfere with the > intentions of the code in splice_dirt_to_actor which goes: > > /* > * Don't block on output, we have to drain the direct pipe. > */ > sd->flags &= ~SPLICE_F_NONBLOCK; Reading splice_direct_to_actor() I see nothing wrong with the patch (Patch is about splice from socket to pipe, while the sd->flags you mention in splice_direct_to_actor() only applies to the splice from internal pipe to something else, as splice_direct_to_actor() allocates an internal pipe to perform its work. Also, the meaning of SPLICE_F_NONBLOCK, as explained in include/linux/splice.h is : #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 */ If the comment is still correct, SPLICE_F_NONBLOCK only applies to the pipe implied in splice() syscall. For the other file, either its : - A regular file : nonblocking mode is not available, like a normal read()/write() syscall - A socket : We should be able to specify if its blocking or not, independantly from the SPLICE_F_NONBLOCK flag that only applies to the pipe. Normal way is using ioctl(FIONBIO) or other fcntl() call to change file->f_flags O_NONBLOCK In order to be able to efficiently use splice() from a socket to a file, we need to do a loop of : { splice(from blocking tcp socket to non blocking pipe, SPLICE_F_NONBLOCK); /* nonblocking pipe or risk deadlock */ splice(from pipe to file) } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/net.h b/include/linux/net.h index 4515efa..10e38d1 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -185,7 +185,7 @@ struct proto_ops { struct vm_area_struct * vma); ssize_t (*sendpage) (struct socket *sock, struct page *page, int offset, size_t size, int flags); - ssize_t (*splice_read)(struct socket *sock, loff_t *ppos, + ssize_t (*splice_read)(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); }; diff --git a/include/net/tcp.h b/include/net/tcp.h index 218235d..e8e7f80 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -309,7 +309,7 @@ extern int tcp_twsk_unique(struct sock *sk, extern void tcp_twsk_destructor(struct sock *sk); -extern ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, +extern ssize_t tcp_splice_read(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); static inline void tcp_dec_quickack_mode(struct sock *sk, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ce572f9..c777d88 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -548,10 +548,11 @@ static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) * Will read pages from given socket and fill them into a pipe. * **/ -ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, +ssize_t tcp_splice_read(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { + struct socket *sock = file->private_data; struct sock *sk = sock->sk; struct tcp_splice_state tss = { .pipe = pipe, @@ -572,7 +573,7 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, lock_sock(sk); - timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK); + timeo = sock_rcvtimeo(sk, file->f_flags & O_NONBLOCK); while (tss.len) { ret = __tcp_splice_read(sk, &tss); if (ret < 0)