Commit 02583ade authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller

tcp: place all zerocopy payload in frags

This avoids an unnecessary copy of 1-2KB and improves tso_fragment,
which has to fall back to tcp_fragment if skb->len != skb_data_len.

It also avoids a surprising inconsistency in notifications:
Zerocopy packets sent over loopback have their frags copied, so set
SO_EE_CODE_ZEROCOPY_COPIED in the notification. But this currently
does not happen for small packets, because when all data fits in the
linear fragment, data is not copied in skb_orphan_frags_rx.
Reported-by: default avatarTom Deseyn <tom.deseyn@gmail.com>
Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 111856c7
...@@ -1186,7 +1186,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) ...@@ -1186,7 +1186,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
int flags, err, copied = 0; int flags, err, copied = 0;
int mss_now = 0, size_goal, copied_syn = 0; int mss_now = 0, size_goal, copied_syn = 0;
bool process_backlog = false; bool process_backlog = false;
bool sg; bool sg, zc = false;
long timeo; long timeo;
flags = msg->msg_flags; flags = msg->msg_flags;
...@@ -1204,7 +1204,8 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) ...@@ -1204,7 +1204,8 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
goto out_err; goto out_err;
} }
if (!(sk_check_csum_caps(sk) && sk->sk_route_caps & NETIF_F_SG)) zc = sk_check_csum_caps(sk) && sk->sk_route_caps & NETIF_F_SG;
if (!zc)
uarg->zerocopy = 0; uarg->zerocopy = 0;
} }
...@@ -1325,13 +1326,13 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) ...@@ -1325,13 +1326,13 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
copy = msg_data_left(msg); copy = msg_data_left(msg);
/* Where to copy to? */ /* Where to copy to? */
if (skb_availroom(skb) > 0) { if (skb_availroom(skb) > 0 && !zc) {
/* We have some space in skb head. Superb! */ /* We have some space in skb head. Superb! */
copy = min_t(int, copy, skb_availroom(skb)); copy = min_t(int, copy, skb_availroom(skb));
err = skb_add_data_nocache(sk, skb, &msg->msg_iter, copy); err = skb_add_data_nocache(sk, skb, &msg->msg_iter, copy);
if (err) if (err)
goto do_fault; goto do_fault;
} else if (!uarg || !uarg->zerocopy) { } else if (!zc) {
bool merge = true; bool merge = true;
int i = skb_shinfo(skb)->nr_frags; int i = skb_shinfo(skb)->nr_frags;
struct page_frag *pfrag = sk_page_frag(sk); struct page_frag *pfrag = sk_page_frag(sk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment