The msk status for fallback socket is not tracked correctly. We must switch to close only after the subflow is moved there, or the worker will not run and pending mptcp data will not be spooled after close() Signed-off-by: Paolo Abeni --- net/mptcp/protocol.c | 13 +++++++++---- net/mptcp/subflow.c | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index a6bd06c724d5..1ef980d4a646 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -764,8 +764,10 @@ static void mptcp_check_for_eof(struct mptcp_sock *msk) mptcp_for_each_subflow(msk, subflow) receivers += !subflow->rx_eof; + if (receivers) + return; - if (!receivers && !(sk->sk_shutdown & RCV_SHUTDOWN)) { + if (!(sk->sk_shutdown & RCV_SHUTDOWN)) { /* hopefully temporary hack: propagate shutdown status * to msk, when all subflows agree on it */ @@ -775,6 +777,8 @@ static void mptcp_check_for_eof(struct mptcp_sock *msk) set_bit(MPTCP_DATA_READY, &msk->flags); sk->sk_data_ready(sk); } + if (sk->sk_state != TCP_CLOSE && sk->sk_shutdown == SHUTDOWN_MASK) + inet_sk_state_store(sk, TCP_CLOSE); } static bool mptcp_ext_cache_refill(struct mptcp_sock *msk) @@ -2157,11 +2161,12 @@ static void mptcp_close(struct sock *sk, long timeout) lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; - if (sk->sk_state == TCP_LISTEN || - __mptcp_check_fallback((struct mptcp_sock *)sk)) { + if ((1 << sk->sk_state) & (TCPF_LISTEN | TCP_CLOSE)) { inet_sk_state_store(sk, TCP_CLOSE); goto cleanup; - } else if (sk->sk_state == TCP_CLOSE) { + } else if (__mptcp_check_fallback((struct mptcp_sock *)sk)) { + if (!mptcp_send_pending(sk)) + inet_sk_state_store(sk, TCP_CLOSE); goto cleanup; } diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 1e9a72af67dc..fd356dc9d580 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1282,7 +1282,6 @@ static void subflow_state_change(struct sock *sk) mptcp_data_ready(parent, sk); if (__mptcp_check_fallback(mptcp_sk(parent)) && - !(parent->sk_shutdown & RCV_SHUTDOWN) && !subflow->rx_eof && subflow_is_done(sk)) { subflow->rx_eof = 1; mptcp_subflow_eof(parent); -- 2.26.2