[PATCH mptcp-next v2 5/5] Squash to "bpf: Add mptcp packet scheduler struct_ops"

Gang Yan <[email protected]>
Newsgroups dev.linux.lists.mptcp
Message-ID <[email protected]>
From: Gang Yan <[email protected]>

The pernet sysctl patches in this series swap the scheduler pointer
with xchg() without taking any module reference: this is fine while
ops can only be registered from built-in code.

This commit is what makes BPF schedulers registerable, i.e. the first
one whose ops can be unloaded while a pernet still stores them. Take
the reference accordingly:

  - mptcp_pernet_set_defaults() pins &mptcp_sched_default, mirroring
    tcp_sk_init() pinning &tcp_reno;
  - mptcp_set_scheduler() takes a reference on the new ops and
    releases the one held on the ops it replaces, mirroring
    tcp_set_default_congestion_control();
  - mptcp_net_exit() releases the last reference, mirroring
    tcp_sk_exit().

Assisted-by: Claude:GLM5.2
Co-developed-by: Tao Cui <[email protected]>
Signed-off-by: Tao Cui <[email protected]>
Signed-off-by: Gang Yan <[email protected]>
---
 net/mptcp/ctrl.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 32268aa26097..309bbb2a4eb0 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -123,7 +123,8 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 	pernet->stale_loss_cnt = 4;
 	pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
 
-	RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default);
+	if (bpf_try_module_get(&mptcp_sched_default, mptcp_sched_default.owner))
+		RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default);
 
 	if (bpf_try_module_get(&mptcp_pm_kernel, mptcp_pm_kernel.owner))
 		RCU_INIT_POINTER(pernet->path_manager, &mptcp_pm_kernel);
@@ -134,15 +135,22 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 #ifdef CONFIG_SYSCTL
 static int mptcp_set_scheduler(struct mptcp_pernet *pernet, const char *name)
 {
-	struct mptcp_sched_ops *sched;
+	struct mptcp_sched_ops *sched, *prev;
 	int ret = 0;
 
 	rcu_read_lock();
 	sched = mptcp_sched_find(name);
-	if (sched)
-		xchg(&pernet->scheduler, sched);
-	else
+	if (sched) {
+		if (bpf_try_module_get(sched, sched->owner)) {
+			prev = xchg(&pernet->scheduler, sched);
+			if (prev)
+				bpf_module_put(prev, prev->owner);
+		} else {
+			ret = -EBUSY;
+		}
+	} else {
 		ret = -ENOENT;
+	}
 	rcu_read_unlock();
 
 	return ret;
@@ -603,10 +611,15 @@ static int __net_init mptcp_net_init(struct net *net)
 static void __net_exit mptcp_net_exit(struct net *net)
 {
 	struct mptcp_pernet *pernet = mptcp_get_pernet(net);
+	struct mptcp_sched_ops *sched;
 	struct mptcp_pm_ops *pm;
 
 	mptcp_pernet_del_table(pernet);
 
+	sched = rcu_dereference_protected(pernet->scheduler, true);
+	if (sched)
+		bpf_module_put(sched, sched->owner);
+
 	pm = rcu_dereference_protected(pernet->path_manager, true);
 	if (pm)
 		bpf_module_put(pm, pm->owner);
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.