[PATCH mptcp-next 6/6] mptcp: defer sk_data_ready to the worker
Geliang Tang <[email protected]> Mon, 27 Jul 2026 19:29:21 +0800
| Newsgroups | dev.linux.lists.mptcp |
|---|---|
| Message-ID | <5ab5630bc288d5af26ecacfcf29c7fe35f1fd670.1785150300.git.tanggeliang@kylinos.cn> |
From: Geliang Tang <[email protected]> When MPTCP carries TLS, the data path runs under mptcp_data_lock(). Reaching sk->sk_data_ready(sk) synchronously ends up at tls_strp_check_rcv() -> mptcp_recv_skb() -> mptcp_move_skbs(), which calls mptcp_data_lock() on the same sk and recurses on sk_lock.slock. Fix this by deferring sk->sk_data_ready(sk) to mptcp_worker() via a new MPTCP_WORK_DATA_READY bit, re-using the existing mptcp_schedule_work()/mptcp_cancel_work() infrastructure. The wakeup bit is consumed after the SOCK_DEAD && TCP_CLOSE destroy branch, so a socket that reaches the destroy path drops the pending wakeup rather than running it post-free. No new work_struct, workqueue or cancel path is introduced; only a new flag bit and the corresponding set_bit()/test_and_clear_bit() in the mptcp_worker() body. Signed-off-by: Geliang Tang <[email protected]> --- net/mptcp/protocol.c | 9 +++++++-- net/mptcp/protocol.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 09b888ff33c7..be139718ed15 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1085,8 +1085,10 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk) mptcp_rcv_rtt_update(msk, subflow); if (!sock_owned_by_user(sk)) { /* Wake-up the reader only for in-sequence data */ - if (move_skbs_to_msk(msk, ssk) && mptcp_epollin_ready(sk)) - sk->sk_data_ready(sk); + if (move_skbs_to_msk(msk, ssk) && mptcp_epollin_ready(sk)) { + set_bit(MPTCP_WORK_DATA_READY, &msk->flags); + mptcp_schedule_work(sk); + } } else { __mptcp_move_skbs_from_subflow(msk, ssk, false); } @@ -3223,6 +3225,9 @@ static void mptcp_worker(struct work_struct *work) if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) __mptcp_retrans(sk); + if (test_and_clear_bit(MPTCP_WORK_DATA_READY, &msk->flags)) + sk->sk_data_ready(sk); + fail_tout = msk->first ? READ_ONCE(mptcp_subflow_ctx(msk->first)->fail_tout) : 0; if (fail_tout && time_after(jiffies, fail_tout)) mptcp_mp_fail_no_response(msk); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 8b16b0a4eb9f..7ba8b78ac6e4 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -115,6 +115,7 @@ #define MPTCP_WORK_RTX 1 #define MPTCP_FALLBACK_DONE 2 #define MPTCP_WORK_CLOSE_SUBFLOW 3 +#define MPTCP_WORK_DATA_READY 4 /* MPTCP socket release cb flags */ #define MPTCP_PUSH_PENDING 1 -- 2.53.0