]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mptcp: fix memcg accounting for passive sockets
authorPaolo Abeni <pabeni@redhat.com>
Fri, 21 Nov 2025 17:02:03 +0000 (18:02 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 25 Nov 2025 03:49:41 +0000 (19:49 -0800)
The passive sockets never got proper memcg accounting: the msk
socket is associated with the memcg at accept time, but the
passive subflows never got it right.

At accept time, traverse the subflows list and associate each of them
with the msk memcg, and try to do the same at join completion time, if
the msk has been already accepted.

Fixes: cf7da0d66cc1 ("mptcp: Create SUBFLOW socket for incoming connections")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/298
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/597
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20251121-net-next-mptcp-memcg-backlog-imp-v1-4-1f34b6c1e0b1@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c

index 2104ab1eda1df221e981483a117a2e8189faa0af..67732d3c502c08950f505bf5cb79f036f6b9f4b7 100644 (file)
@@ -3651,8 +3651,11 @@ static void mptcp_sock_check_graft(struct sock *sk, struct sock *ssk)
        write_lock_bh(&sk->sk_callback_lock);
        sock = sk->sk_socket;
        write_unlock_bh(&sk->sk_callback_lock);
-       if (sock)
+       if (sock) {
                mptcp_sock_graft(ssk, sock);
+               __mptcp_inherit_cgrp_data(sk, ssk);
+               __mptcp_inherit_memcg(sk, ssk, GFP_ATOMIC);
+       }
 }
 
 bool mptcp_finish_join(struct sock *ssk)
@@ -3970,6 +3973,28 @@ unlock:
        return err;
 }
 
+static void mptcp_graft_subflows(struct sock *sk)
+{
+       struct mptcp_subflow_context *subflow;
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       mptcp_for_each_subflow(msk, subflow) {
+               struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+
+               lock_sock(ssk);
+
+               /* Set ssk->sk_socket of accept()ed flows to mptcp socket.
+                * This is needed so NOSPACE flag can be set from tcp stack.
+                */
+               if (!ssk->sk_socket)
+                       mptcp_sock_graft(ssk, sk->sk_socket);
+
+               __mptcp_inherit_cgrp_data(sk, ssk);
+               __mptcp_inherit_memcg(sk, ssk, GFP_KERNEL);
+               release_sock(ssk);
+       }
+}
+
 static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                               struct proto_accept_arg *arg)
 {
@@ -4017,16 +4042,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                msk = mptcp_sk(newsk);
                msk->in_accept_queue = 0;
 
-               /* set ssk->sk_socket of accept()ed flows to mptcp socket.
-                * This is needed so NOSPACE flag can be set from tcp stack.
-                */
-               mptcp_for_each_subflow(msk, subflow) {
-                       struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
-
-                       if (!ssk->sk_socket)
-                               mptcp_sock_graft(ssk, newsock);
-               }
-
+               mptcp_graft_subflows(newsk);
                mptcp_rps_record_subflows(msk);
 
                /* Do late cleanup for the first subflow as necessary. Also
index 6d9de13c1f9cd75b7e6f20829bb6880e0280da43..8c27f4b1789fe29aa6738958d0f895f0d944c1e9 100644 (file)
@@ -707,6 +707,7 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated)
        return ret;
 }
 
+void __mptcp_inherit_memcg(struct sock *sk, struct sock *ssk, gfp_t gfp);
 void __mptcp_inherit_cgrp_data(struct sock *sk, struct sock *ssk);
 
 int mptcp_is_enabled(const struct net *net);
index d98d151392d2da7e1f12afd9062f5e04e9e73318..72b7efe388db9bbac75b4527becc59e8bdd671a5 100644 (file)
@@ -1712,6 +1712,16 @@ err_out:
        return err;
 }
 
+void __mptcp_inherit_memcg(struct sock *sk, struct sock *ssk, gfp_t gfp)
+{
+       /* Only if the msk has been accepted already (and not orphaned).*/
+       if (!mem_cgroup_sockets_enabled || !sk->sk_socket)
+               return;
+
+       mem_cgroup_sk_inherit(sk, ssk);
+       __sk_charge(ssk, gfp);
+}
+
 void __mptcp_inherit_cgrp_data(struct sock *sk, struct sock *ssk)
 {
 #ifdef CONFIG_SOCK_CGROUP_DATA