mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Adjacent changes: net/mptcp/protocol.h63740448a3
("mptcp: fix accept vs worker race")2a6a870e44
("mptcp: stops worker on unaccepted sockets at listener close")ddb1a072f8
("mptcp: move first subflow allocation at mpc access time") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
681c5b51dc
186 changed files with 1670 additions and 917 deletions
|
@ -2344,7 +2344,26 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
bool need_push, dispose_it;
|
||||
bool dispose_it, need_push = false;
|
||||
|
||||
/* If the first subflow moved to a close state before accept, e.g. due
|
||||
* to an incoming reset, mptcp either:
|
||||
* - if either the subflow or the msk are dead, destroy the context
|
||||
* (the subflow socket is deleted by inet_child_forget) and the msk
|
||||
* - otherwise do nothing at the moment and take action at accept and/or
|
||||
* listener shutdown - user-space must be able to accept() the closed
|
||||
* socket.
|
||||
*/
|
||||
if (msk->in_accept_queue && msk->first == ssk) {
|
||||
if (!sock_flag(sk, SOCK_DEAD) && !sock_flag(ssk, SOCK_DEAD))
|
||||
return;
|
||||
|
||||
/* ensure later check in mptcp_worker() will dispose the msk */
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
|
||||
mptcp_subflow_drop_ctx(ssk);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
dispose_it = !msk->subflow || ssk != msk->subflow->sk;
|
||||
if (dispose_it)
|
||||
|
@ -2380,28 +2399,22 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
|
|||
if (!inet_csk(ssk)->icsk_ulp_ops) {
|
||||
WARN_ON_ONCE(!sock_flag(ssk, SOCK_DEAD));
|
||||
kfree_rcu(subflow, rcu);
|
||||
} else if (msk->in_accept_queue && msk->first == ssk) {
|
||||
/* if the first subflow moved to a close state, e.g. due to
|
||||
* incoming reset and we reach here before inet_child_forget()
|
||||
* the TCP stack could later try to close it via
|
||||
* inet_csk_listen_stop(), or deliver it to the user space via
|
||||
* accept().
|
||||
* We can't delete the subflow - or risk a double free - nor let
|
||||
* the msk survive - or will be leaked in the non accept scenario:
|
||||
* fallback and let TCP cope with the subflow cleanup.
|
||||
*/
|
||||
WARN_ON_ONCE(sock_flag(ssk, SOCK_DEAD));
|
||||
mptcp_subflow_drop_ctx(ssk);
|
||||
} else {
|
||||
/* otherwise tcp will dispose of the ssk and subflow ctx */
|
||||
if (ssk->sk_state == TCP_LISTEN)
|
||||
if (ssk->sk_state == TCP_LISTEN) {
|
||||
tcp_set_state(ssk, TCP_CLOSE);
|
||||
mptcp_subflow_queue_clean(sk, ssk);
|
||||
inet_csk_listen_stop(ssk);
|
||||
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
|
||||
}
|
||||
|
||||
__tcp_close(ssk, 0);
|
||||
|
||||
/* close acquired an extra ref */
|
||||
__sock_put(ssk);
|
||||
}
|
||||
|
||||
out_release:
|
||||
release_sock(ssk);
|
||||
|
||||
sock_put(ssk);
|
||||
|
@ -2456,21 +2469,14 @@ static void __mptcp_close_subflow(struct sock *sk)
|
|||
mptcp_close_ssk(sk, ssk, subflow);
|
||||
}
|
||||
|
||||
/* if the MPC subflow has been closed before the msk is accepted,
|
||||
* msk will never be accept-ed, close it now
|
||||
*/
|
||||
if (!msk->first && msk->in_accept_queue) {
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
static bool mptcp_check_close_timeout(const struct sock *sk)
|
||||
static bool mptcp_should_close(const struct sock *sk)
|
||||
{
|
||||
s32 delta = tcp_jiffies32 - inet_csk(sk)->icsk_mtup.probe_timestamp;
|
||||
struct mptcp_subflow_context *subflow;
|
||||
|
||||
if (delta >= TCP_TIMEWAIT_LEN)
|
||||
if (delta >= TCP_TIMEWAIT_LEN || mptcp_sk(sk)->in_accept_queue)
|
||||
return true;
|
||||
|
||||
/* if all subflows are in closed status don't bother with additional
|
||||
|
@ -2678,7 +2684,7 @@ static void mptcp_worker(struct work_struct *work)
|
|||
* even if it is orphaned and in FIN_WAIT2 state
|
||||
*/
|
||||
if (sock_flag(sk, SOCK_DEAD)) {
|
||||
if (mptcp_check_close_timeout(sk)) {
|
||||
if (mptcp_should_close(sk)) {
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
mptcp_do_fastclose(sk);
|
||||
}
|
||||
|
@ -2920,6 +2926,14 @@ static void __mptcp_destroy_sock(struct sock *sk)
|
|||
sock_put(sk);
|
||||
}
|
||||
|
||||
void __mptcp_unaccepted_force_close(struct sock *sk)
|
||||
{
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
mptcp_do_fastclose(sk);
|
||||
__mptcp_destroy_sock(sk);
|
||||
}
|
||||
|
||||
static __poll_t mptcp_check_readable(struct mptcp_sock *msk)
|
||||
{
|
||||
/* Concurrent splices from sk_receive_queue into receive_queue will
|
||||
|
@ -3764,6 +3778,18 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
|||
if (!ssk->sk_socket)
|
||||
mptcp_sock_graft(ssk, newsock);
|
||||
}
|
||||
|
||||
/* Do late cleanup for the first subflow as necessary. Also
|
||||
* deal with bad peers not doing a complete shutdown.
|
||||
*/
|
||||
if (msk->first &&
|
||||
unlikely(inet_sk_state_load(msk->first) == TCP_CLOSE)) {
|
||||
__mptcp_close_ssk(newsk, msk->first,
|
||||
mptcp_subflow_ctx(msk->first), 0);
|
||||
if (unlikely(list_empty(&msk->conn_list)))
|
||||
inet_sk_state_store(newsk, TCP_CLOSE);
|
||||
}
|
||||
|
||||
release_sock(newsk);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue