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/ip6mr: Convert net->ipv[46].ipmr_seq to atomic_t.

We will no longer hold RTNL for ipmr_mfc_add() and ipmr_mfc_delete().

MFC entry can be loosely connected with VIF by its index for
mrt->vif_table[] (stored in mfc_parent), but the two tables are
not synchronised. i.e. Even if VIF 1 is removed, MFC for VIF 1
is not automatically removed.

The only field that the MFC/VIF interfaces share is
net->ipv[46].ipmr_seq, which is protected by RTNL.

Adding a new mutex for both just to protect a single field is overkill.

Let's convert the field to atomic_t.

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

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
4480d5fa 1c36d186

+10 -10
+4 -4
include/linux/mroute_base.h
··· 76 76 struct vif_device *vif, 77 77 struct net_device *vif_dev, 78 78 unsigned short vif_index, u32 tb_id, 79 - unsigned int *ipmr_seq) 79 + atomic_t *ipmr_seq) 80 80 { 81 81 struct vif_entry_notifier_info info = { 82 82 .info = { ··· 89 89 }; 90 90 91 91 ASSERT_RTNL(); 92 - (*ipmr_seq)++; 92 + atomic_inc(ipmr_seq); 93 93 return call_fib_notifiers(net, event_type, &info.info); 94 94 } 95 95 ··· 198 198 unsigned short family, 199 199 enum fib_event_type event_type, 200 200 struct mr_mfc *mfc, u32 tb_id, 201 - unsigned int *ipmr_seq) 201 + atomic_t *ipmr_seq) 202 202 { 203 203 struct mfc_entry_notifier_info info = { 204 204 .info = { ··· 209 209 }; 210 210 211 211 ASSERT_RTNL(); 212 - (*ipmr_seq)++; 212 + atomic_inc(ipmr_seq); 213 213 return call_fib_notifiers(net, event_type, &info.info); 214 214 } 215 215
+1 -1
include/net/netns/ipv4.h
··· 280 280 struct fib_rules_ops *mr_rules_ops; 281 281 #endif 282 282 struct fib_notifier_ops *ipmr_notifier_ops; 283 - unsigned int ipmr_seq; /* protected by rtnl_mutex */ 283 + atomic_t ipmr_seq; 284 284 #endif 285 285 #ifdef CONFIG_IP_ROUTE_MULTIPATH 286 286 struct sysctl_fib_multipath_hash_seed sysctl_fib_multipath_hash_seed;
+1 -1
include/net/netns/ipv6.h
··· 118 118 struct seg6_pernet_data *seg6_data; 119 119 struct fib_notifier_ops *notifier_ops; 120 120 struct fib_notifier_ops *ip6mr_notifier_ops; 121 - unsigned int ipmr_seq; /* protected by rtnl_mutex */ 121 + atomic_t ipmr_seq; 122 122 struct { 123 123 struct hlist_head head; 124 124 spinlock_t lock;
+2 -2
net/ipv4/ipmr.c
··· 3226 3226 3227 3227 static unsigned int ipmr_seq_read(const struct net *net) 3228 3228 { 3229 - return READ_ONCE(net->ipv4.ipmr_seq) + ipmr_rules_seq_read(net); 3229 + return atomic_read(&net->ipv4.ipmr_seq) + ipmr_rules_seq_read(net); 3230 3230 } 3231 3231 3232 3232 static int ipmr_dump(struct net *net, struct notifier_block *nb, ··· 3247 3247 { 3248 3248 struct fib_notifier_ops *ops; 3249 3249 3250 - net->ipv4.ipmr_seq = 0; 3250 + atomic_set(&net->ipv4.ipmr_seq, 0); 3251 3251 3252 3252 ops = fib_notifier_ops_register(&ipmr_notifier_ops_template, net); 3253 3253 if (IS_ERR(ops))
+2 -2
net/ipv6/ip6mr.c
··· 1280 1280 1281 1281 static unsigned int ip6mr_seq_read(const struct net *net) 1282 1282 { 1283 - return READ_ONCE(net->ipv6.ipmr_seq) + ip6mr_rules_seq_read(net); 1283 + return atomic_read(&net->ipv6.ipmr_seq) + ip6mr_rules_seq_read(net); 1284 1284 } 1285 1285 1286 1286 static int ip6mr_dump(struct net *net, struct notifier_block *nb, ··· 1305 1305 { 1306 1306 struct fib_notifier_ops *ops; 1307 1307 1308 - net->ipv6.ipmr_seq = 0; 1308 + atomic_set(&net->ipv6.ipmr_seq, 0); 1309 1309 1310 1310 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net); 1311 1311 if (IS_ERR(ops))