Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipmr: Convert ipmr_net_exit_batch() to ->exit_rtnl().

ipmr_net_ops uses ->exit_batch() to acquire RTNL only once
for dying network namespaces.

ipmr does not depend on the ordering of ->exit_rtnl() and
->exit_batch() of other pernet_operations (unlike fib_net_ops).

Once ipmr_free_table() is called and all devices are
queued for destruction in ->exit_rtnl(), later during
NETDEV_UNREGISTER, ipmr_device_event() will not see anything
in vif table and just do nothing.

Let's convert ipmr_net_exit_batch() to ->exit_rtnl().

Note that fib_rules_unregister() does not need RTNL and
we will remove RTNL and unregister_netdevice_many() in
ipmr_net_init().

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260228221800.1082070-10-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
b22b0186 b7fdc3cf

+13 -18
+13 -18
net/ipv4/ipmr.c
··· 285 285 return err; 286 286 } 287 287 288 - static void __net_exit ipmr_rules_exit(struct net *net) 288 + static void __net_exit ipmr_rules_exit_rtnl(struct net *net, 289 + struct list_head *dev_kill_list) 289 290 { 290 291 struct mr_table *mrt, *next; 291 - LIST_HEAD(dev_kill_list); 292 292 293 293 ASSERT_RTNL(); 294 294 list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { 295 295 list_del(&mrt->list); 296 - ipmr_free_table(mrt, &dev_kill_list); 296 + ipmr_free_table(mrt, dev_kill_list); 297 297 } 298 298 299 - unregister_netdevice_many(&dev_kill_list); 300 299 fib_rules_unregister(net->ipv4.mr_rules_ops); 301 300 } 302 301 ··· 352 353 return 0; 353 354 } 354 355 355 - static void __net_exit ipmr_rules_exit(struct net *net) 356 + static void __net_exit ipmr_rules_exit_rtnl(struct net *net, 357 + struct list_head *dev_kill_list) 356 358 { 357 - LIST_HEAD(dev_kill_list); 358 - 359 359 ASSERT_RTNL(); 360 360 361 - ipmr_free_table(net->ipv4.mrt, &dev_kill_list); 362 - unregister_netdevice_many(&dev_kill_list); 361 + ipmr_free_table(net->ipv4.mrt, dev_kill_list); 363 362 364 363 net->ipv4.mrt = NULL; 365 364 } ··· 3261 3264 /* Setup for IP multicast routing */ 3262 3265 static int __net_init ipmr_net_init(struct net *net) 3263 3266 { 3267 + LIST_HEAD(dev_kill_list); 3264 3268 int err; 3265 3269 3266 3270 err = ipmr_notifier_init(net); ··· 3288 3290 remove_proc_entry("ip_mr_vif", net->proc_net); 3289 3291 proc_vif_fail: 3290 3292 rtnl_lock(); 3291 - ipmr_rules_exit(net); 3293 + ipmr_rules_exit_rtnl(net, &dev_kill_list); 3294 + unregister_netdevice_many(&dev_kill_list); 3292 3295 rtnl_unlock(); 3293 3296 #endif 3294 3297 ipmr_rules_fail: ··· 3307 3308 ipmr_notifier_exit(net); 3308 3309 } 3309 3310 3310 - static void __net_exit ipmr_net_exit_batch(struct list_head *net_list) 3311 + static void __net_exit ipmr_net_exit_rtnl(struct net *net, 3312 + struct list_head *dev_kill_list) 3311 3313 { 3312 - struct net *net; 3313 - 3314 - rtnl_lock(); 3315 - list_for_each_entry(net, net_list, exit_list) 3316 - ipmr_rules_exit(net); 3317 - rtnl_unlock(); 3314 + ipmr_rules_exit_rtnl(net, dev_kill_list); 3318 3315 } 3319 3316 3320 3317 static struct pernet_operations ipmr_net_ops = { 3321 3318 .init = ipmr_net_init, 3322 3319 .exit = ipmr_net_exit, 3323 - .exit_batch = ipmr_net_exit_batch, 3320 + .exit_rtnl = ipmr_net_exit_rtnl, 3324 3321 }; 3325 3322 3326 3323 static const struct rtnl_msg_handler ipmr_rtnl_msg_handlers[] __initconst = {