* [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets
@ 2026-10-15 10:42 Geliang Tang
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Geliang Tang @ 2026-10-15 10:42 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
The mptcp_nvme.sh selftest reports lockdep "possible recursive locking"
warnings when running NVMe over MPTCP. The issue occurs because MPTCP
sockets and their subflows share the same k-sk_lock-AF_INET lockdep class,
causing lockdep to flag false warnings in paths that hold the MPTCP socket
lock and then lock a subflow (setsockopt, connect, bind, worker send-ack).
This series fixes the issue by giving MPTCP sockets their own distinct
lockdep class (sk_lock-AF_INET-MPTCP for IPv4, sk_lock-AF_INET6-MPTCP for
IPv6), similar to how nvme-tcp handles it. This approach is more efficient
than reclassifying each subflow individually, properly supports IPv6, and
follows existing kernel patterns.
A KUnit test is included to verify the fix works correctly.
Geliang Tang (2):
mptcp: give MPTCP sockets a distinct lockdep class
mptcp: kunit: add sockopt test for subflow socket locking
net/mptcp/Makefile | 4 +++-
net/mptcp/protocol.c | 37 +++++++++++++++++++++++++++++++++++++
net/mptcp/sockopt_test.c | 37 +++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 1 deletion(-)
create mode 100644 net/mptcp/sockopt_test.c
--
2.55.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class
2026-10-15 10:42 [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets Geliang Tang
@ 2026-10-15 10:42 ` Geliang Tang
2026-10-15 10:59 ` sashiko-bot
2026-10-15 17:30 ` Matthieu Baerts
2026-10-15 10:42 ` [PATCH mptcp-next 2/2] mptcp: kunit: add sockopt test for subflow socket locking Geliang Tang
2026-10-15 11:48 ` [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets MPTCP CI
2 siblings, 2 replies; 6+ messages in thread
From: Geliang Tang @ 2026-10-15 10:42 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
MPTCP sockets and their subflows share the same k-sk_lock-AF_INET
lockdep class. When both are kernel sockets, lockdep flags every path
that holds the MPTCP socket lock and then locks a subflow (setsockopt,
connect, bind, worker send-ack) as "possible recursive locking".
Reclassify the MPTCP socket lock in mptcp_init_sock() to use a distinct
lock class (sk_lock-AF_INET-MPTCP for IPv4, sk_lock-AF_INET6-MPTCP for
IPv6). This approach is similar to nvme-tcp and avoids the need to
reclassify each subflow socket individually.
The implementation is based on nvme_tcp_reclassify_socket() from
drivers/nvme/host/tcp.c.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/protocol.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 60cbd91be632..e63896a60595 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -56,6 +56,41 @@ DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions) = {
};
static struct net_device *mptcp_napi_dev;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+/* distinct lockdep class for MPTCP sockets */
+static struct lock_class_key mptcp_sk_key[2];
+static struct lock_class_key mptcp_slock_key[2];
+
+static void mptcp_reclassify_socket(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ if (WARN_ON_ONCE(!sock_allow_reclassification(sk)))
+ return;
+
+ switch (sk->sk_family) {
+ case AF_INET:
+ sock_lock_init_class_and_name(sk, "slock-AF_INET-MPTCP",
+ &mptcp_slock_key[0],
+ "sk_lock-AF_INET-MPTCP",
+ &mptcp_sk_key[0]);
+ break;
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+ case AF_INET6:
+ sock_lock_init_class_and_name(sk, "slock-AF_INET6-MPTCP",
+ &mptcp_slock_key[1],
+ "sk_lock-AF_INET6-MPTCP",
+ &mptcp_sk_key[1]);
+ break;
+#endif
+ default:
+ WARN_ON_ONCE(1);
+ }
+}
+#else
+static void mptcp_reclassify_socket(struct socket *sock) { }
+#endif
+
/* Returns end sequence number of the receiver's advertised window */
u64 mptcp_wnd_end(const struct mptcp_sock *msk)
{
@@ -3292,6 +3327,8 @@ static int mptcp_init_sock(struct sock *sk)
sk->sk_sndbuf = READ_ONCE(net->ipv4.sysctl_tcp_wmem[1]);
sk->sk_write_space = sk_stream_write_space;
+ mptcp_reclassify_socket(sk->sk_socket);
+
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH mptcp-next 2/2] mptcp: kunit: add sockopt test for subflow socket locking
2026-10-15 10:42 [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets Geliang Tang
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
@ 2026-10-15 10:42 ` Geliang Tang
2026-10-15 11:48 ` [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets MPTCP CI
2 siblings, 0 replies; 6+ messages in thread
From: Geliang Tang @ 2026-10-15 10:42 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang
From: Geliang Tang <tanggeliang@kylinos.cn>
Add a KUnit test to verify that MPTCP sockets have a distinct lockdep
class from their subflows. The test creates a kernel MPTCP socket and
sets SO_REUSEADDR, which triggers the code path where
mptcp_setsockopt_sol_socket() locks the MPTCP socket and then calls
sk_setsockopt() on the subflow.
Without the lockdep fix (distinct MPTCP socket class), this triggers a
"possible recursive locking" warning:
'''
kunit_try_catch/355 is trying to acquire lock:
ffff888115c99c58 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: \
sk_setsockopt+0x1132/0x3b30
but task is already holding lock:
ffff88811ac80e98 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: \
mptcp_setsockopt_sol_socket+0xed/0x910
Possible unsafe locking scenario:
CPU0
----
lock(k-sk_lock-AF_INET);
lock(k-sk_lock-AF_INET);
*** DEADLOCK ***
'''
With the fix, the MPTCP socket has its own sk_lock-AF_INET-MPTCP class
and no warning appears.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/Makefile | 4 +++-
net/mptcp/sockopt_test.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 net/mptcp/sockopt_test.c
diff --git a/net/mptcp/Makefile b/net/mptcp/Makefile
index bd72b300a0f6..e9ae91cff940 100644
--- a/net/mptcp/Makefile
+++ b/net/mptcp/Makefile
@@ -10,7 +10,9 @@ obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o
mptcp_crypto_test-objs := crypto_test.o
mptcp_token_test-objs := token_test.o
-obj-$(CONFIG_MPTCP_KUNIT_TEST) += mptcp_crypto_test.o mptcp_token_test.o
+mptcp_sockopt_test-objs := sockopt_test.o
+obj-$(CONFIG_MPTCP_KUNIT_TEST) += mptcp_crypto_test.o mptcp_token_test.o \
+ mptcp_sockopt_test.o
obj-$(CONFIG_BPF_SYSCALL) += bpf.o
diff --git a/net/mptcp/sockopt_test.c b/net/mptcp/sockopt_test.c
new file mode 100644
index 000000000000..ebd43de02543
--- /dev/null
+++ b/net/mptcp/sockopt_test.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <kunit/test.h>
+
+#include "protocol.h"
+
+static void mptcp_sockopt_reuseaddr(struct kunit *test)
+{
+ struct socket *sock;
+ int err, reuse = 1;
+
+ err = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, IPPROTO_MPTCP,
+ &sock);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock);
+
+ err = sock_common_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ KERNEL_SOCKPTR(&reuse), sizeof(reuse));
+
+ KUNIT_EXPECT_EQ(test, err, 0);
+
+ sock_release(sock);
+}
+
+static struct kunit_case mptcp_sockopt_test_cases[] = {
+ KUNIT_CASE(mptcp_sockopt_reuseaddr),
+ {}
+};
+
+static struct kunit_suite mptcp_sockopt_suite = {
+ .name = "mptcp-sockopt",
+ .test_cases = mptcp_sockopt_test_cases,
+};
+
+kunit_test_suite(mptcp_sockopt_suite);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for MPTCP sockopt");
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
@ 2026-10-15 10:59 ` sashiko-bot
2026-10-15 17:30 ` Matthieu Baerts
1 sibling, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-15 10:59 UTC (permalink / raw)
To: Geliang Tang, mptcp
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] mptcp: passive sockets miss lockdep reclassification causing warnings
--
commit c0431dba7b7ab62b7e71ad2f4ff94fb4913cc837
Author: Geliang Tang <geliang@kernel.org>
mptcp: give MPTCP sockets a distinct lockdep class
MPTCP sockets and their subflows share the same k-sk_lock-AF_INET
lockdep class. When both are kernel sockets, lockdep flags every path
that holds the MPTCP socket lock and then locks a subflow (setsockopt,
connect, bind, worker send-ack) as "possible recursive locking".
Reclassify the MPTCP socket lock in mptcp_init_sock() to use a distinct
lock class (sk_lock-AF_INET-MPTCP for IPv4, sk_lock-AF_INET6-MPTCP for
IPv6). This approach is similar to nvme-tcp and avoids the need to
reclassify each subflow socket individually.
The implementation is based on nvme_tcp_reclassify_socket() from
drivers/nvme/host/tcp.c.
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 60cbd91be6320..e63896a605953 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
[ ... ]
> @@ -3292,6 +3327,8 @@ static int mptcp_init_sock(struct sock *sk)
> sk->sk_sndbuf = READ_ONCE(net->ipv4.sysctl_tcp_wmem[1]);
> sk->sk_write_space = sk_stream_write_space;
>
> + mptcp_reclassify_socket(sk->sk_socket);
> +
> return 0;
> }
[Severity: Medium]
Since mptcp_init_sock() is only used for active socket creation, are cloned
(passive) connections missing this lockdep reclassification?
When an incoming MPTCP connection is accepted, the socket is cloned:
net/mptcp/protocol.c:mptcp_sk_clone_init() {
...
struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
...
__mptcp_init_sock(nsk);
...
}
sk_clone_lock() initializes the lockdep class back to the generic AF_INET
default. Because mptcp_reclassify_socket() is never called for these cloned
sockets, will lockdep continue to falsely report recursive locking when an
accepted MPTCP socket and its subflow are locked simultaneously?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792060837.git.tanggeliang@kylinos.cn?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets
2026-10-15 10:42 [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets Geliang Tang
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
2026-10-15 10:42 ` [PATCH mptcp-next 2/2] mptcp: kunit: add sockopt test for subflow socket locking Geliang Tang
@ 2026-10-15 11:48 ` MPTCP CI
2 siblings, 0 replies; 6+ messages in thread
From: MPTCP CI @ 2026-10-15 11:48 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Hi Geliang,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Success! ✅
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Perf: Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/38724382972
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/e7a2821a1eae
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1186364
If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-normal
For more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
2026-10-15 10:59 ` sashiko-bot
@ 2026-10-15 17:30 ` Matthieu Baerts
1 sibling, 0 replies; 6+ messages in thread
From: Matthieu Baerts @ 2026-10-15 17:30 UTC (permalink / raw)
To: Geliang Tang, mptcp; +Cc: Geliang Tang
Hi Geliang,
Thank you for the patches!
On 15/10/2026 12:42, Geliang Tang wrote:
> From: Geliang Tang <tanggeliang@kylinos.cn>
>
> MPTCP sockets and their subflows share the same k-sk_lock-AF_INET
> lockdep class. When both are kernel sockets, lockdep flags every path
> that holds the MPTCP socket lock and then locks a subflow (setsockopt,
> connect, bind, worker send-ack) as "possible recursive locking".
>
> Reclassify the MPTCP socket lock in mptcp_init_sock() to use a distinct
> lock class (sk_lock-AF_INET-MPTCP for IPv4, sk_lock-AF_INET6-MPTCP for
> IPv6). This approach is similar to nvme-tcp and avoids the need to
> reclassify each subflow socket individually.
>
> The implementation is based on nvme_tcp_reclassify_socket() from
> drivers/nvme/host/tcp.c.
Note: we also do that in pm_kernel.c for the extra listening socket.
> Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
> ---
> net/mptcp/protocol.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 60cbd91be632..e63896a60595 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -56,6 +56,41 @@ DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions) = {
> };
> static struct net_device *mptcp_napi_dev;
>
> +#ifdef CONFIG_DEBUG_LOCK_ALLOC
In pm_kernel.c we don't have that. Do we really need it? If all the
functions are nops, maybe not?
> +/* distinct lockdep class for MPTCP sockets */
> +static struct lock_class_key mptcp_sk_key[2];
> +static struct lock_class_key mptcp_slock_key[2];
> +
> +static void mptcp_reclassify_socket(struct socket *sock)
> +{
> + struct sock *sk = sock->sk;
> +
> + if (WARN_ON_ONCE(!sock_allow_reclassification(sk)))
> + return;
> +
> + switch (sk->sk_family) {
> + case AF_INET:
> + sock_lock_init_class_and_name(sk, "slock-AF_INET-MPTCP",
> + &mptcp_slock_key[0],
> + "sk_lock-AF_INET-MPTCP",
> + &mptcp_sk_key[0]);
> + break;
> +#if IS_ENABLED(CONFIG_MPTCP_IPV6)
> + case AF_INET6:
> + sock_lock_init_class_and_name(sk, "slock-AF_INET6-MPTCP",
> + &mptcp_slock_key[1],
> + "sk_lock-AF_INET6-MPTCP",
> + &mptcp_sk_key[1]);
In pm_kernel.c we only call sock_lock_init_class_and_name() once. Maybe
we should do the same here, then no need to have a special helper?
> + break;
> +#endif
> + default:
> + WARN_ON_ONCE(1);
> + }
> +}
> +#else
> +static void mptcp_reclassify_socket(struct socket *sock) { }
> +#endif
> +
> /* Returns end sequence number of the receiver's advertised window */
> u64 mptcp_wnd_end(const struct mptcp_sock *msk)
> {
> @@ -3292,6 +3327,8 @@ static int mptcp_init_sock(struct sock *sk)
> sk->sk_sndbuf = READ_ONCE(net->ipv4.sysctl_tcp_wmem[1]);
> sk->sk_write_space = sk_stream_write_space;
>
> + mptcp_reclassify_socket(sk->sk_socket);
Indeed, better in __mptcp_init_sock().
> +
> return 0;
> }
>
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-15 17:30 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 10:42 [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets Geliang Tang
2026-10-15 10:42 ` [PATCH mptcp-next 1/2] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
2026-10-15 10:59 ` sashiko-bot
2026-10-15 17:30 ` Matthieu Baerts
2026-10-15 10:42 ` [PATCH mptcp-next 2/2] mptcp: kunit: add sockopt test for subflow socket locking Geliang Tang
2026-10-15 11:48 ` [PATCH mptcp-next 0/2] add distinct lockdep class for MPTCP sockets MPTCP CI
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.