From patchwork Tue Nov 12 14:10:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1193547 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.01.org (client-ip=2001:19d0:306:5::1; helo=ml01.01.org; envelope-from=mptcp-bounces@lists.01.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=strlen.de Received: from ml01.01.org (ml01.01.org [IPv6:2001:19d0:306:5::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47C8XD3N0lz9sPF for ; Wed, 13 Nov 2019 01:00:27 +1100 (AEDT) Received: from new-ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id AC039100DC41C; Tue, 12 Nov 2019 06:02:11 -0800 (PST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a0a:51c0:0:12e:520::1; helo=chamillionaire.breakpoint.cc; envelope-from=fw@breakpoint.cc; receiver= Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 09406100DC419 for ; Tue, 12 Nov 2019 06:02:10 -0800 (PST) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1iUWiU-0001t5-9H; Tue, 12 Nov 2019 15:00:22 +0100 From: Florian Westphal To: Cc: Florian Westphal Date: Tue, 12 Nov 2019 15:10:35 +0100 Message-Id: <20191112141038.19213-2-fw@strlen.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191112141038.19213-1-fw@strlen.de> References: <20191112141038.19213-1-fw@strlen.de> MIME-Version: 1.0 Message-ID-Hash: PGPZT5EGXUFGRCFDQK7GF2JW5GSAORCW X-Message-ID-Hash: PGPZT5EGXUFGRCFDQK7GF2JW5GSAORCW X-MailFrom: fw@breakpoint.cc X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.1.1 Precedence: list Subject: [MPTCP] [PATCH v2 1/4] mptcp: add wmem_queued accounting List-Id: Discussions regarding MPTCP upstreaming Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Peer could ack data at TCP level but refrain from sending mptcp-level ACKs. This could result in a growing the mptcp socket backlog indefinitely. We should thus block mptcp_sendmsg until the peer has acked some of the sent data. In order to be able to do so, increment the mptcp socket wmem_queued counter on memory allocation and decrement it when releasing the memory on mptcp-level ack reception. Because TCP performns sndbuf auto-tuning up to tcp_wmem_max[2], make this the mptcp sk_sndbuf limit. In the future we could add experiment with autotuning as TCP does in tcp_sndbuf_expand(). Signed-off-by: Florian Westphal --- net/mptcp/protocol.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 7bea6b62f66e..65f10bb372aa 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -139,8 +139,11 @@ static inline bool mptcp_frag_can_collapse_to(const struct mptcp_sock *msk, static void dfrag_clear(struct sock *sk, struct mptcp_data_frag *dfrag) { + int len = dfrag->data_len + dfrag->overhead; + list_del(&dfrag->list); - sk_mem_uncharge(sk, dfrag->data_len + dfrag->overhead); + sk_mem_uncharge(sk, len); + sk_wmem_queued_add(sk, -len); put_page(dfrag->page); } @@ -304,6 +307,9 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, if (!dfrag_collapsed) { get_page(dfrag->page); list_add_tail(&dfrag->list, &msk->rtx_queue); + sk_wmem_queued_add(sk, frag_truesize); + } else { + sk_wmem_queued_add(sk, ret); } /* charge data on mptcp rtx queue to the master socket @@ -711,6 +717,7 @@ static int mptcp_init_sock(struct sock *sk) return ret; sk_sockets_allocated_inc(sk); + sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[2]; return 0; } From patchwork Tue Nov 12 14:10:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1193549 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.01.org (client-ip=198.145.21.10; helo=ml01.01.org; envelope-from=mptcp-bounces@lists.01.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=strlen.de Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47C8XJ6np8z9sNT for ; Wed, 13 Nov 2019 01:00:32 +1100 (AEDT) Received: from new-ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id B623D100DC420; Tue, 12 Nov 2019 06:02:16 -0800 (PST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a0a:51c0:0:12e:520::1; helo=chamillionaire.breakpoint.cc; envelope-from=fw@breakpoint.cc; receiver= Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 2FED3100DC41E for ; Tue, 12 Nov 2019 06:02:14 -0800 (PST) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1iUWiY-0001tH-DX; Tue, 12 Nov 2019 15:00:26 +0100 From: Florian Westphal To: Cc: Florian Westphal Date: Tue, 12 Nov 2019 15:10:36 +0100 Message-Id: <20191112141038.19213-3-fw@strlen.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191112141038.19213-1-fw@strlen.de> References: <20191112141038.19213-1-fw@strlen.de> MIME-Version: 1.0 Message-ID-Hash: 7JO6LWCSU7JL2RJ7FB7I4YHJCQBSFHVT X-Message-ID-Hash: 7JO6LWCSU7JL2RJ7FB7I4YHJCQBSFHVT X-MailFrom: fw@breakpoint.cc X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.1.1 Precedence: list Subject: [MPTCP] [PATCH v2 2/4] mptcp: allow partial cleaning of rtx head dfrag List-Id: Discussions regarding MPTCP upstreaming Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: After adding wmem accouting for the mptcp socket we could get into a situation where the mptcp socket can't transmit more data, and mptcp_clean_una doesn't reduce wmem even if snd_una has advanced because it currently will only remove entire dfrags. Allow advancing the dfrag head sequence and reduce wmem, even though this isn't correct (as we can't release the page). Because we will soon block on mptcp sk in case wmem is too large, call sk_stream_write_space() in case we reduced the backlog so userspace task blocked in sendmsg or poll will be woken up. This isn't an issue if the send buffer is large, but it is when SO_SNDBUF is used to reduce it to a lower value. Note we can still get a deadlock for low SO_SNDBUF values in case both sides of the connection write to the socket: both could be blocked due to wmem being too small -- and current mptcp stack will only increment mptcp ack_seq on recv. This doesn't happen with the selftest as it uses poll() and will always call recv if there is data to read. Signed-off-by: Florian Westphal --- net/mptcp/protocol.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 65f10bb372aa..b93050056195 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -137,13 +137,18 @@ static inline bool mptcp_frag_can_collapse_to(const struct mptcp_sock *msk, df->data_seq + df->data_len == msk->write_seq; } +static void dfrag_uncharge(struct sock *sk, int len) +{ + sk_mem_uncharge(sk, len); + sk_wmem_queued_add(sk, -len); +} + static void dfrag_clear(struct sock *sk, struct mptcp_data_frag *dfrag) { int len = dfrag->data_len + dfrag->overhead; list_del(&dfrag->list); - sk_mem_uncharge(sk, len); - sk_wmem_queued_add(sk, -len); + dfrag_uncharge(sk, len); put_page(dfrag->page); } @@ -152,14 +157,31 @@ static void mptcp_clean_una(struct sock *sk) struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_data_frag *dtmp, *dfrag; u64 snd_una = atomic64_read(&msk->snd_una); + bool cleaned = false; list_for_each_entry_safe(dfrag, dtmp, &msk->rtx_queue, list) { if (after64(dfrag->data_seq + dfrag->data_len, snd_una)) break; dfrag_clear(sk, dfrag); + cleaned = true; + } + + dfrag = mptcp_rtx_head(sk); + if (dfrag && after64(snd_una, dfrag->data_seq)) { + u64 delta = dfrag->data_seq + dfrag->data_len - snd_una; + + dfrag->data_seq += delta; + dfrag->data_len -= delta; + + dfrag_uncharge(sk, delta); + cleaned = true; + } + + if (cleaned) { + sk_mem_reclaim_partial(sk); + sk_stream_write_space(sk); } - sk_mem_reclaim_partial(sk); } /* ensure we get enough memory for the frag hdr, beyond some minimal amount of From patchwork Tue Nov 12 14:10:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1193550 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.01.org (client-ip=2001:19d0:306:5::1; helo=ml01.01.org; envelope-from=mptcp-bounces@lists.01.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=strlen.de Received: from ml01.01.org (ml01.01.org [IPv6:2001:19d0:306:5::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47C8XM6yLpz9sPF for ; Wed, 13 Nov 2019 01:00:35 +1100 (AEDT) Received: from new-ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id C243E100DC41C; Tue, 12 Nov 2019 06:02:20 -0800 (PST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a0a:51c0:0:12e:520::1; helo=chamillionaire.breakpoint.cc; envelope-from=fw@breakpoint.cc; receiver= Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5449D100DC415 for ; Tue, 12 Nov 2019 06:02:18 -0800 (PST) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1iUWic-0001tO-IC; Tue, 12 Nov 2019 15:00:30 +0100 From: Florian Westphal To: Cc: Florian Westphal Date: Tue, 12 Nov 2019 15:10:37 +0100 Message-Id: <20191112141038.19213-4-fw@strlen.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191112141038.19213-1-fw@strlen.de> References: <20191112141038.19213-1-fw@strlen.de> MIME-Version: 1.0 Message-ID-Hash: HJDZ35EDDFG55T2XUVENYJNF2KAK5QXJ X-Message-ID-Hash: HJDZ35EDDFG55T2XUVENYJNF2KAK5QXJ X-MailFrom: fw@breakpoint.cc X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.1.1 Precedence: list Subject: [MPTCP] [PATCH v2 3/4] mptcp: add and use mptcp RTX flag List-Id: Discussions regarding MPTCP upstreaming Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: This is needed in the (unlikely) case that userspace is blocked in mptcp_sendmsg because wmem is exhausted. In that case, only the rtx work queue will clean the rtx backlog, but it could take several milliseconds until it runs next. So, allow it to get scheduled as soon as possible so wmem can be reclaimed if the mptcp socket sndbuf is exhausted. Because such quick-schedule should not cause retransmits, add a flag that indicates when the work queue has been scheduled on behalf of the retransmit timer. Signed-off-by: Florian Westphal --- net/mptcp/options.c | 2 +- net/mptcp/protocol.c | 26 ++++++++++++++++++++------ net/mptcp/protocol.h | 3 ++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 80dbe7662cea..b64fb5dbc2a1 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -583,7 +583,7 @@ static void update_una(struct mptcp_sock *msk, old_snd_una = atomic64_cmpxchg(&msk->snd_una, snd_una, new_snd_una); if (old_snd_una == snd_una) { - mptcp_reset_timer((struct sock *)msk); + mptcp_data_acked((struct sock *)msk); break; } } diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index b93050056195..68171a539a02 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -40,7 +40,7 @@ static bool mptcp_timer_pending(struct sock *sk) return timer_pending(&inet_csk(sk)->icsk_retransmit_timer); } -void mptcp_reset_timer(struct sock *sk) +static void mptcp_reset_timer(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); unsigned long tout; @@ -52,6 +52,15 @@ void mptcp_reset_timer(struct sock *sk) sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + tout); } +void mptcp_data_acked(struct sock *sk) +{ + mptcp_reset_timer(sk); + + if (!sk_stream_is_writeable(sk) && + schedule_work(&mptcp_sk(sk)->rtx_work)) + sock_hold(sk); +} + static void mptcp_stop_timer(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); @@ -623,6 +632,7 @@ static void mptcp_retransmit_handler(struct sock *sk) if (atomic64_read(&msk->snd_una) == msk->write_seq) { mptcp_stop_timer(sk); } else { + set_bit(MPTCP_WORK_RTX, &msk->flags); if (schedule_work(&msk->rtx_work)) sock_hold(sk); } @@ -647,7 +657,7 @@ static void mptcp_retransmit_timer(struct timer_list *t) sock_put(sk); } -static void mptcp_retransmit(struct work_struct *work) +static void mptcp_worker(struct work_struct *work) { int orig_len, orig_offset, ret, mss_now = 0, size_goal = 0; struct mptcp_data_frag *dfrag; @@ -663,6 +673,10 @@ static void mptcp_retransmit(struct work_struct *work) lock_sock(sk); mptcp_clean_una(sk); + + if (!test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) + goto unlock; + dfrag = mptcp_rtx_head(sk); if (!dfrag) goto unlock; @@ -715,7 +729,7 @@ static int __mptcp_init_sock(struct sock *sk) INIT_LIST_HEAD(&msk->conn_list); INIT_LIST_HEAD(&msk->rtx_queue); - INIT_WORK(&msk->rtx_work, mptcp_retransmit); + INIT_WORK(&msk->rtx_work, mptcp_worker); /* re-use the csk retrans timer for MPTCP-level retrans */ timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0); @@ -755,7 +769,7 @@ static void __mptcp_clear_xmit(struct sock *sk) dfrag_clear(sk, dfrag); } -static void mptcp_cancel_rtx_work(struct sock *sk) +static void mptcp_cancel_work(struct sock *sk) { struct mptcp_sock *msk = mptcp_sk(sk); @@ -792,7 +806,7 @@ static void mptcp_close(struct sock *sk, long timeout) __mptcp_clear_xmit(sk); release_sock(sk); - mptcp_cancel_rtx_work(sk); + mptcp_cancel_work(sk); sk_common_release(sk); } @@ -802,7 +816,7 @@ static int mptcp_disconnect(struct sock *sk, int flags) lock_sock(sk); __mptcp_clear_xmit(sk); release_sock(sk); - mptcp_cancel_rtx_work(sk); + mptcp_cancel_work(sk); return tcp_disconnect(sk, flags); } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 83b06382e56a..bb599cd3a738 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -76,6 +76,7 @@ /* MPTCP socket flags */ #define MPTCP_DATA_READY BIT(0) +#define MPTCP_WORK_RTX BIT(1) static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field) { @@ -290,7 +291,7 @@ void mptcp_get_options(const struct sk_buff *skb, void mptcp_finish_connect(struct sock *sk, int mp_capable); void mptcp_finish_join(struct sock *sk); -void mptcp_reset_timer(struct sock *sk); +void mptcp_data_acked(struct sock *sk); int mptcp_token_new_request(struct request_sock *req); void mptcp_token_destroy_request(u32 token); From patchwork Tue Nov 12 14:10:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 1193551 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.01.org (client-ip=2001:19d0:306:5::1; helo=ml01.01.org; envelope-from=mptcp-bounces@lists.01.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=strlen.de Received: from ml01.01.org (ml01.01.org [IPv6:2001:19d0:306:5::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47C8XS0CMdz9sNT for ; Wed, 13 Nov 2019 01:00:39 +1100 (AEDT) Received: from new-ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D297C100DC41C; Tue, 12 Nov 2019 06:02:24 -0800 (PST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2a0a:51c0:0:12e:520::1; helo=chamillionaire.breakpoint.cc; envelope-from=fw@breakpoint.cc; receiver= Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 6F377100DC424 for ; Tue, 12 Nov 2019 06:02:22 -0800 (PST) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1iUWig-0001tV-MT; Tue, 12 Nov 2019 15:00:34 +0100 From: Florian Westphal To: Cc: Florian Westphal Date: Tue, 12 Nov 2019 15:10:38 +0100 Message-Id: <20191112141038.19213-5-fw@strlen.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191112141038.19213-1-fw@strlen.de> References: <20191112141038.19213-1-fw@strlen.de> MIME-Version: 1.0 Message-ID-Hash: OI5VBMYUBLQZ6IDL4TT4YGQDNRWH7EHI X-Message-ID-Hash: OI5VBMYUBLQZ6IDL4TT4YGQDNRWH7EHI X-MailFrom: fw@breakpoint.cc X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.1.1 Precedence: list Subject: [MPTCP] [PATCH v2 4/4] sendmsg: block until mptcp sk is writeable List-Id: Discussions regarding MPTCP upstreaming Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: This disables transmit of new data until the peer has acked enough mptcp data to get below the wspace write threshold (more than half of wspace upperlimit is available again). Also have poll not report EPOLLOUT in this case, its not relevant if a subflow is writeable. The latter is a temporary workaround that is needed because mptcp_poll walks the subflows and calls __tcp_poll on each of them. Because subflow ssk is usually writable, we will have to undo-that if the mptcp sndbuf is exhausted. This won't be needed anymore once __tcp_poll is removed, I am working on this. Signed-off-by: Florian Westphal --- net/mptcp/protocol.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 68171a539a02..4da4c702b1a5 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -406,6 +406,18 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) return ret; } + timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); + + mptcp_clean_una(sk); + + while (!sk_stream_is_writeable(sk)) { + ret = sk_stream_wait_memory(sk, &timeo); + if (ret) + goto out; + + mptcp_clean_una(sk); + } + ssk = mptcp_subflow_get(msk); if (!ssk) { release_sock(sk); @@ -421,8 +433,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) pr_debug("conn_list->subflow=%p", ssk); lock_sock(ssk); - mptcp_clean_una(sk); - timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); while (msg_data_left(msg)) { ret = mptcp_sendmsg_frag(sk, ssk, msg, NULL, &timeo, &mss_now, &size_goal); @@ -1315,6 +1325,10 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, tcp_sock = mptcp_subflow_tcp_socket(subflow); ret |= __tcp_poll(tcp_sock->sk); } + + if (!sk_stream_is_writeable(sk)) + ret &= ~(EPOLLOUT|EPOLLWRNORM); + release_sock(sk); return ret;