minor tcp io_uring zc optimisations
Subsystems (4)
cover minor tcp io_uring zc optimisations
Patch 1 is a simple cleanup, patch 2 gives removes 2 atomics from the io_uring zc TCP submission path, which yielded extra 0.5% for my throughput CPU bound tests based on liburing/examples/send-zerocopy.c
Pavel Begunkov (2):
net/tcp: don't peek at tail for io_uring zc
net/tcp: optimise io_uring zc ubuf refcounting
net/ipv4/tcp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
Signature · 1 line
2.40.0
PATCH 1/2 net/tcp: don't peek at tail for io_uring zc
Move tcp_write_queue_tail() to SOCK_ZEROCOPY specific flag as zerocopy setup for msghdr->ubuf_info doesn't need to peek into the last request.
--- net/ipv4/tcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/ipv4/tcp.c +1 -2
@@ -1229,13 +1229,12 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) flags = msg->msg_flags;if ((flags &MSG_ZEROCOPY ) && size) { - skb =tcp_write_queue_tail (sk); -if (msg->msg_ubuf) { uarg = msg->msg_ubuf;net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { + skb =tcp_write_queue_tail (sk); uarg =msg_zerocopy_realloc (sk, size,skb_zcopy (skb));if (!uarg) { err = -ENOBUFS ;
Signature · 1 line
2.40.0
Re: [PATCH net-next 1/2] net/tcp: don't peek at tail for io_uring zc
Quoted 8 lines · Pavel Begunkov
Move
tcp_write_queue_tail()toSOCK_ZEROCOPYspecific flag as zerocopy setup formsghdr->ubuf_infodoesn't need to peek into the last request.Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
Eric Dumazet
Reviewed-byRe: [PATCH net-next 1/2] net/tcp: don't peek at tail for io_uring zc
Quoted 5 lines · David Ahern
Quoted 3 lines · Pavel Begunkov
Move
tcp_write_queue_tail()toSOCK_ZEROCOPYspecific flag as zerocopy setup formsghdr->ubuf_infodoesn't need to peek into the last request.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Pavel Begunkov <[email protected]>--- net/ipv4/tcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)Reviewed-by David Ahern <[email protected]>
PATCH 2/2 net/tcp: optimise io_uring zc ubuf refcounting
In reply to Pavel Begunkovio_uring keeps a reference to ubuf_info during submission, so if tcp_sendmsg_locked() sees msghdr::msg_ubuf in can be sure the buffer will be kept alive and doesn't need to additionally pin it.
--- net/ipv4/tcp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
net/ipv4/tcp.c +6 -3
@@ -1231,7 +1231,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if ((flags &MSG_ZEROCOPY ) && size) {if (msg->msg_ubuf) { uarg = msg->msg_ubuf; -net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { skb =tcp_write_queue_tail (sk);
@@ -1458,7 +1457,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)tcp_push (sk, flags, mss_now, tp->nonagle, size_goal); } out_nopush: -net_zcopy_put (uarg); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put (uarg);return copied + copied_syn; do_error:
@@ -1467,7 +1468,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if (copied + copied_syn) goto out; out_err: -net_zcopy_put_abort (uarg, true); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put_abort (uarg, true); err =sk_stream_error (sk, flags, err);/* make sure we wake any epoll edge trigger waiter */ if (unlikely (tcp_rtx_and_write_queues_empty (sk) && err == -EAGAIN )) {
Signature · 1 line
2.40.0
Re: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 24 lines · Pavel Begunkov
net/ipv4/tcp.c +3
-2@@ -1231,7 +1231,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if ((flags &MSG_ZEROCOPY ) && size) {if (msg->msg_ubuf) { uarg = msg->msg_ubuf; -net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { skb =tcp_write_queue_tail (sk);@@ -1458,7 +1457,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)tcp_push (sk, flags, mss_now, tp->nonagle, size_goal); } out_nopush: -net_zcopy_put (uarg); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put (uarg);return copied + copied_syn; do_error:
net/ipv4/tcp.c int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) · line 1476
Quoted 10 lines
net/ipv4/tcp.c +3
-1@@ -1467,7 +1468,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if (copied + copied_syn) goto out; out_err: -net_zcopy_put_abort (uarg, true); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put_abort (uarg, true); err =sk_stream_error (sk, flags, err);/* make sure we wake any epoll edge trigger waiter */ if (unlikely (tcp_rtx_and_write_queues_empty (sk) && err == -EAGAIN )) {
Both net_zcopy_put_abort and net_zcopy_put have an if (uarg) check.
Eric Dumazet
Reviewed-byRe: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 24 lines · David Ahern
Quoted 22 lines · Pavel Begunkov
net/ipv4/tcp.c +3
-2@@ -1231,7 +1231,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if ((flags &MSG_ZEROCOPY ) && size) {if (msg->msg_ubuf) { uarg = msg->msg_ubuf; -net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { skb =tcp_write_queue_tail (sk);@@ -1458,7 +1457,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)tcp_push (sk, flags, mss_now, tp->nonagle, size_goal); } out_nopush: -net_zcopy_put (uarg); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put (uarg);return copied + copied_syn;
Quoted 14 lines
net/ipv4/tcp.c int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) · line 1476
Quoted 12 lines
net/ipv4/tcp.c +3
-1do_error:@@ -1467,7 +1468,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if (copied + copied_syn) goto out; out_err: -net_zcopy_put_abort (uarg, true); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put_abort (uarg, true); err =sk_stream_error (sk, flags, err);/* make sure we wake any epoll edge trigger waiter */ if (unlikely (tcp_rtx_and_write_queues_empty (sk) && err == -EAGAIN )) {Both
net_zcopy_put_abortandnet_zcopy_puthave anif (uarg)check.
Right, but here this might avoid a read of msg->msg_ubuf, which might be more expensive to fetch.
Compiler will probably remove the second test (uarg) from net_zcopy_put()
Re: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 40 lines · Eric Dumazet
Quoted 24 lines · David Ahern
Quoted 22 lines · Pavel Begunkov
net/ipv4/tcp.c +3
-2@@ -1231,7 +1231,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if ((flags &MSG_ZEROCOPY ) && size) {if (msg->msg_ubuf) { uarg = msg->msg_ubuf; -net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { skb =tcp_write_queue_tail (sk);@@ -1458,7 +1457,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)tcp_push (sk, flags, mss_now, tp->nonagle, size_goal); } out_nopush: -net_zcopy_put (uarg); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put (uarg);return copied + copied_syn;Quoted 14 lines
net/ipv4/tcp.c int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) · line 1476
Quoted 12 lines
net/ipv4/tcp.c +3
-1do_error:@@ -1467,7 +1468,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if (copied + copied_syn) goto out; out_err: -net_zcopy_put_abort (uarg, true); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put_abort (uarg, true); err =sk_stream_error (sk, flags, err);/* make sure we wake any epoll edge trigger waiter */ if (unlikely (tcp_rtx_and_write_queues_empty (sk) && err == -EAGAIN )) {Both
net_zcopy_put_abortandnet_zcopy_puthave anif (uarg)check.
Quoted 2 lines
Right, but here this might avoid a read of
msg->msg_ubuf, which might be more expensive to fetch.
agreed.
Quoted 4 lines
Compiler will probably remove the second test (uarg) from
net_zcopy_put()Reviewed-by Eric Dumazet <[email protected]>
The one in net_zcopy_put can be removed with the above change. It's other caller is net_zcopy_put_abort which has already checked uarg is set.
Re: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 41 lines · David Ahern
Quoted 40 lines · Eric Dumazet
Quoted 38 lines · David Ahern
Quoted 24 lines · Pavel Begunkov
net/ipv4/tcp.c +3
-2@@ -1231,7 +1231,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if ((flags &MSG_ZEROCOPY ) && size) {if (msg->msg_ubuf) { uarg = msg->msg_ubuf; -net_zcopy_get (uarg); zc = sk->sk_route_caps &NETIF_F_SG ; }else if (sock_flag (sk,SOCK_ZEROCOPY )) { skb =tcp_write_queue_tail (sk);@@ -1458,7 +1457,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)tcp_push (sk, flags, mss_now, tp->nonagle, size_goal); } out_nopush: -net_zcopy_put (uarg); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put (uarg);return copied + copied_syn; do_error:net/ipv4/tcp.c int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) · line 1476
Quoted 10 lines
net/ipv4/tcp.c +3
-1@@ -1467,7 +1468,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)if (copied + copied_syn) goto out; out_err: -net_zcopy_put_abort (uarg, true); +/* msg->msg_ubuf is pinned by the caller so we don't take extra refs */ +if (uarg && !msg->msg_ubuf) +net_zcopy_put_abort (uarg, true); err =sk_stream_error (sk, flags, err);/* make sure we wake any epoll edge trigger waiter */ if (unlikely (tcp_rtx_and_write_queues_empty (sk) && err == -EAGAIN )) {Both
net_zcopy_put_abortandnet_zcopy_puthave anif (uarg)check.
Quoted 4 lines
Quoted 2 lines
Right, but here this might avoid a read of
msg->msg_ubuf, which might be more expensive to fetch.agreed.
I put it there to avoid one extra check in the non-zerocopy path. msg->msg_ubuf is null there, the conditional will pass and it'll still have to test uarg.
Quoted 3 lines
Quoted 3 lines
Compiler will probably remove the second test (uarg) from
net_zcopy_put()Reviewed-by Eric Dumazet <[email protected]>
Thank you for reviews!
Quoted 2 lines
The one in
net_zcopy_putcan be removed with the above change. It's other caller isnet_zcopy_put_abortwhich has already checked uarg is set.
Ah yes, do you want me to fold it in?
Signature · 1 line
Pavel Begunkov
Re: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 8 lines · Pavel Begunkov
Quoted 5 lines
The one in
net_zcopy_putcan be removed with the above change. It's other caller isnet_zcopy_put_abortwhich has already checked uarg is set.Ah yes, do you want me to fold it in?
no preference.
Re: [PATCH net-next 2/2] net/tcp: optimise io_uring zc ubuf refcounting
Quoted 11 lines · David Ahern
Quoted 8 lines · Pavel Begunkov
Quoted 5 lines
The one in
net_zcopy_putcan be removed with the above change. It's other caller isnet_zcopy_put_abortwhich has already checked uarg is set.Ah yes, do you want me to fold it in?
no preference.
I'll leave it for another patch then. It might be interesting to try remove null checks for all *_zcopy_* helpers, but it didn't feel right last time I tried.
Signature · 1 line
Pavel Begunkov
This series was applied to netdev/net-next.git (main) by David S. Miller <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (main) by David S. Miller <[email protected]>:
Quoted 9 lines · On Mon, 15 May 2023 17:06:35 +0100 you wrote:
Patch 1 is a simple cleanup, patch 2 gives removes 2 atomics from the
io_uringzc TCP submission path, which yielded extra 0.5% for my throughput CPU bound tests based onliburing/examples/send-zerocopy.cPavel Begunkov (2):
net/tcp: don't peek at tail forio_uringzc
net/tcp: optimiseio_uringzc ubuf refcounting[...]
Here is the summary with links:
- [net-next,1/2] net/tcp: don't peek at tail for io_uring zc
https://git.kernel.org/netdev/net-next/c/eea96a3e2c90 - [net-next,2/2] net/tcp: optimise io_uring zc ubuf refcounting https://git.kernel.org/netdev/net-next/c/a7533584728d
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html