From: Paolo Abeni <pab...@redhat.com> This clean-up a bit the send path, and allows better performances.
Signed-off-by: Paolo Abeni <pab...@redhat.com> --- net/mptcp/protocol.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index fdcfffce0ec9..da983ea4fb5e 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -65,10 +65,11 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct socket *ssock; struct sock *ssk; struct mptcp_ext *mpext = NULL; - struct page *page = NULL; + struct page_frag *pfrag; struct sk_buff *skb; size_t psize; int poffset; + long timeo; lock_sock(sk); ssock = __mptcp_fallback_get_ref(msk); @@ -97,32 +98,32 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) goto put_out; } - /* Initial experiment: new page per send. Real code will - * maintain list of active pages and DSS mappings, append to the - * end and honor zerocopy + lock_sock(ssk); + timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); + + /* use the mptcp page cache so that we can easily move the data + * from one substream to another, but do per subflow memory accounting */ - page = alloc_page(GFP_KERNEL); - if (!page) { - ret = -ENOMEM; - goto put_out; + pfrag = sk_page_frag(sk); + while (!sk_page_frag_refill(ssk, pfrag)) { + ret = sk_stream_wait_memory(ssk, &timeo); + if (ret) + goto put_out; } /* Copy to page */ - poffset = 0; + poffset = pfrag->offset; pr_debug("left=%zu", msg_data_left(msg)); - psize = copy_page_from_iter(page, poffset, + psize = copy_page_from_iter(pfrag->page, poffset, min_t(size_t, msg_data_left(msg), - PAGE_SIZE), + pfrag->size - poffset), &msg->msg_iter); pr_debug("left=%zu", msg_data_left(msg)); - if (!psize) { ret = -EINVAL; goto put_out; } - lock_sock(ssk); - /* Mark the end of the previous write so the beginning of the * next write (with its own mptcp skb extension data) is not * collapsed. @@ -132,8 +133,8 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) TCP_SKB_CB(skb)->eor = 1; mss_now = tcp_send_mss(ssk, &size_goal, msg->msg_flags); - - ret = do_tcp_sendpages(ssk, page, poffset, min_t(int, size_goal, psize), + psize = min_t(int, size_goal, psize); + ret = do_tcp_sendpages(ssk, pfrag->page, poffset, psize, msg->msg_flags | MSG_SENDPAGE_NOTLAST); if (ret <= 0) goto put_out; @@ -159,14 +160,13 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) mpext->checksum, mpext->dsn64); } /* TODO: else fallback */ + pfrag->offset += ret; msk->write_seq += ret; mptcp_subflow_ctx(ssk)->rel_write_seq += ret; tcp_push(ssk, msg->msg_flags, mss_now, tcp_sk(ssk)->nonagle, size_goal); put_out: - if (page) - put_page(page); release_sock(sk); sock_put(ssk); return ret; -- 2.23.0