diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index e1f23016ed3f8..c8f1d91bc67ed 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -590,7 +590,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, * access the skb after the sendpages call */ ret = do_tcp_sendpages(ssk, page, offset, psize, - msg->msg_flags | MSG_SENDPAGE_NOTLAST); + msg->msg_flags | MSG_SENDPAGE_NOTLAST | MSG_DONTWAIT); if (ret <= 0) return ret; @@ -714,6 +714,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct socket *ssock; size_t copied = 0; struct sock *ssk; + bool tx_ok; long timeo; if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL)) @@ -738,6 +739,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) return ret >= 0 ? ret + copied : (copied ? copied : ret); } +restart: mptcp_clean_una(sk); __mptcp_flush_join_list(msk); @@ -759,11 +761,17 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) pr_debug("conn_list->subflow=%p", ssk); lock_sock(ssk); - while (msg_data_left(msg)) { + tx_ok = msg_data_left(msg); + while (tx_ok) { ret = mptcp_sendmsg_frag(sk, ssk, msg, NULL, &timeo, &mss_now, &size_goal); - if (ret < 0) + if (ret < 0) { + if (ret == -EAGAIN && timeo > 0) { + release_sock(ssk); + goto restart; + } break; + } if (ret == 0 && unlikely(__mptcp_needs_tcp_fallback(msk))) { /* Can happen for passive sockets: * 3WHS negotiated MPTCP, but first packet after is @@ -777,6 +785,15 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) } copied += ret; + tx_ok = msg_data_left(msg); + if (!tx_ok) + break; + if (!sk_stream_memory_free(ssk)) { + tcp_push(ssk, msg->msg_flags, mss_now, + tcp_sk(ssk)->nonagle, size_goal); + release_sock(ssk); + goto restart; + } } mptcp_set_timeout(sk, ssk);