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: Tom Deseyn <tom.deseyn@gmail.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
111856c758
commit
02583adeff
|
@ -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)
|
||||||
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 @@ new_segment:
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue