TCP splice improvements
Subsystems (3)
cover TCP splice improvements
The main part is in Patch 1, which optimises locking for successful blocking TCP splice read, following with a clean up in Patch 2.
Pavel Begunkov (2):
net/tcp: optimise locking for blocking splice
net/tcp: optimise non error splice paths
net/ipv4/tcp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
Signature · 1 line
2.40.0
PATCH 1/2 net/tcp: optimise locking for blocking splice
Even when tcp_splice_read() reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.
Check tss.len right after we adjust it, and return if we're done. That saves us one release_sock(); lock_sock(); pair per successful blocking splice read.
--- net/ipv4/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/ipv4/tcp.c +5 -3
@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely (*ppos))return -ESPIPE ; +if (unlikely (!tss.len)) +return 0 ; ret = spliced =0 ;lock_sock (sk); timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK ); -while (tss.len) { +while (true) { ret =__tcp_splice_read (sk, &tss);if (ret <0 )break ;
@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }continue ; } - tss.len -= ret; spliced += ret; + tss.len -= ret; -if (!timeo) +if (!tss.len || !timeo)break ;release_sock (sk);lock_sock (sk);
Signature · 1 line
2.40.0
Paolo Abeni
maintainerRe: [PATCH net-next 1/2] net/tcp: optimise locking for blocking splice
Quoted 35 lines · Pavel Begunkov
Even when
tcp_splice_read()reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.Check tss.len right after we adjust it, and return if we're done. That saves us one
release_sock();lock_sock(); pair per successful blocking splice read.Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)net/ipv4/tcp.c +3
-1@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely (*ppos))return -ESPIPE ; +if (unlikely (!tss.len)) +return 0 ; ret = spliced =0 ;lock_sock (sk); timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK ); -while (tss.len) { +while (true) { ret =__tcp_splice_read (sk, &tss);if (ret <0 )break ;
net/ipv4/tcp.c ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, · line 841
Quoted 6 lines
net/ipv4/tcp.c +1
-1@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }continue ; } - tss.len -= ret; spliced += ret; + tss.len -= ret;
The patch LGTM. The only minor thing that I note is that the above chunk is not needed. Perhaps avoiding unneeded delta could be worthy.
Cheers,
Paolo
Re: [PATCH net-next 1/2] net/tcp: optimise locking for blocking splice
Quoted 29 lines · Paolo Abeni
Quoted 28 lines · Pavel Begunkov
Even when
tcp_splice_read()reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.Check tss.len right after we adjust it, and return if we're done. That saves us one
release_sock();lock_sock(); pair per successful blocking splice read.Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)net/ipv4/tcp.c +2
-0@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely (*ppos))return -ESPIPE ; +if (unlikely (!tss.len)) +return 0 ; ret = spliced =0 ;lock_sock (sk);
Quoted 16 lines
net/ipv4/tcp.c ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, · line 841
Quoted 13 lines
net/ipv4/tcp.c +2
-2timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK ); -while (tss.len) { +while (true) { ret =__tcp_splice_read (sk, &tss);if (ret <0 )break ;@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }continue ; } - tss.len -= ret; spliced += ret; + tss.len -= ret;The patch LGTM. The only minor thing that I note is that the above chunk is not needed. Perhaps avoiding unneeded delta could be worthy.
It keeps it closer to the tss.len test, so I'd leave it for that reason, but on the other hand the compiler should be perfectly able to optimise it regardless (i.e. sub;cmp;jcc; vs sub;jcc;). I don't have a hard feeling on that, can change if you want.
Signature · 1 line
Pavel Begunkov
Re: [PATCH net-next 1/2] net/tcp: optimise locking for blocking splice
Quoted 44 lines · Pavel Begunkov
Quoted 34 lines · Paolo Abeni
Quoted 33 lines · Pavel Begunkov
Even when
tcp_splice_read()reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.Check tss.len right after we adjust it, and return if we're done. That saves us one
release_sock();lock_sock(); pair per successful blocking splice read.Signed-off-by Pavel Begunkov <[email protected]>---
net/ipv4/tcp.c| 8 +++++---1 file changed, 5 insertions(+), 3 deletions(-)net/ipv4/tcp.c +3
-1@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely(*ppos)) return -ESPIPE; + if (unlikely(!tss.len)) + return 0; ret = spliced = 0; lock_sock(sk); timeo = sock_rcvtimeo(sk, sock->file->f_flags & O_NONBLOCK); - while (tss.len) { + while (true) { ret = __tcp_splice_read(sk, &tss); if (ret < 0) break;@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }Quoted 8 lines
net/ipv4/tcp.c ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, · line 841
Quoted 5 lines
net/ipv4/tcp.c +1
-1continue; } - tss.len -= ret; spliced += ret; + tss.len -= ret;The patch LGTM. The only minor thing that I note is that the above chunk is not needed. Perhaps avoiding unneeded delta could be worthy.
Quoted 4 lines
It keeps it closer to the tss.len test, so I'd leave it for that reason, but on the other hand the compiler should be perfectly able to optimise it regardless (i.e. sub;cmp;jcc; vs sub;jcc;). I don't have a hard feeling on that, can change if you want.
Is there anything I can do to help here? I think the patch is fine, but can amend the change per Paolo's suggestion if required.
Signature · 1 line
Pavel Begunkov
Re: [PATCH net-next 1/2] net/tcp: optimise locking for blocking splice
Quoted 46 lines · Pavel Begunkov
Quoted 44 lines · Pavel Begunkov
Quoted 42 lines · Paolo Abeni
Quoted 32 lines · Pavel Begunkov
Even when
tcp_splice_read()reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.Check tss.len right after we adjust it, and return if we're done. That saves us one
release_sock();lock_sock(); pair per successful blocking splice read.Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)net/ipv4/tcp.c +3
-1@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely (*ppos))return -ESPIPE ; +if (unlikely (!tss.len)) +return 0 ; ret = spliced =0 ;lock_sock (sk); timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK ); -while (tss.len) { +while (true) { ret =__tcp_splice_read (sk, &tss);if (ret <0 )break ;net/ipv4/tcp.c ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, · line 841
Quoted 6 lines
net/ipv4/tcp.c +1
-1@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }continue ; } - tss.len -= ret; spliced += ret; + tss.len -= ret;The patch LGTM. The only minor thing that I note is that the above chunk is not needed. Perhaps avoiding unneeded delta could be worthy.
Quoted 8 lines
Quoted 4 lines
It keeps it closer to the tss.len test, so I'd leave it for that reason, but on the other hand the compiler should be perfectly able to optimise it regardless (i.e. sub;cmp;jcc; vs sub;jcc;). I don't have a hard feeling on that, can change if you want.
Is there anything I can do to help here? I think the patch is fine, but can amend the change per Paolo's suggestion if required.
We prefer seeing patches focusing on the change, instead of also doing arbitrary changes
making future backports more likely to conflict.
Thanks.
Re: [PATCH net-next 1/2] net/tcp: optimise locking for blocking splice
Quoted 52 lines · Eric Dumazet
Quoted 51 lines · Pavel Begunkov
Quoted 48 lines · Pavel Begunkov
Quoted 34 lines · Paolo Abeni
Quoted 33 lines · Pavel Begunkov
Even when
tcp_splice_read()reads all it was asked for, for blocking sockets it'll release and immediately regrab the socket lock, loop around and break on the while check.Check tss.len right after we adjust it, and return if we're done. That saves us one
release_sock();lock_sock(); pair per successful blocking splice read.Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)net/ipv4/tcp.c +3
-1@@ -789,13 +789,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,*/ if (unlikely (*ppos))return -ESPIPE ; +if (unlikely (!tss.len)) +return 0 ; ret = spliced =0 ;lock_sock (sk); timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK ); -while (tss.len) { +while (true) { ret =__tcp_splice_read (sk, &tss);if (ret <0 )break ;@@ -835,10 +837,10 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, }Quoted 8 lines
net/ipv4/tcp.c ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, · line 841
Quoted 5 lines
net/ipv4/tcp.c +1
-1continue ; } - tss.len -= ret; spliced += ret; + tss.len -= ret;The patch LGTM. The only minor thing that I note is that the above chunk is not needed. Perhaps avoiding unneeded delta could be worthy.
It keeps it closer to the tss.len test, so I'd leave it for that reason, but on the other hand the compiler should be perfectly able to optimise it regardless (i.e. sub;cmp;jcc; vs sub;jcc;). I don't have a hard feeling on that, can change if you want.
Quoted 7 lines
Quoted 3 lines
Is there anything I can do to help here? I think the patch is fine, but can amend the change per Paolo's suggestion if required.
We prefer seeing patches focusing on the change, instead of also doing arbitrary changes
making future backports more likely to conflict.
Thank you for taking a look! I cut it down and resent.
I don't agree it's arbitrary, it's a clean up related to the change. I'm just trying to not make the death by a thousand cuts problem worse for networking, but I guess I'm worried for nothing.
Signature · 1 line
Pavel Begunkov
PATCH 2/2 net/tcp: optimise non error splice paths
In reply to Pavel BegunkovMove post __tcp_splice_read() error checking inside the "nothing to read" block. That removes an extra if from the path where it has successfully spliced some bytes.
--- net/ipv4/tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/ipv4/tcp.c +3 -3
@@ -799,9 +799,9 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, timeo =sock_rcvtimeo (sk, sock->file->f_flags &O_NONBLOCK );while (true) { ret =__tcp_splice_read (sk, &tss); -if (ret <0 ) -break ; -else if (!ret) { +if (ret <=0 ) { +if (unlikely (ret <0 )) +break ;if (spliced)break ;if (sock_flag (sk,SOCK_DONE ))
Signature · 1 line
2.40.0