mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
ip6mr: Replace RTNL with a dedicated mutex for MFC.
ip6mr does not have rtnetlink interface for MFC unlike ipmr, which uses dev_get_by_index_rcu() to set struct mfcctl.mfcc_parent. ip6mr_mfc_add() and ip6mr_mfc_delete() are called under RTNL from ip6_mroute_setsockopt() only. There are no RTNL dependant, but ip6_mroute_setsockopt() reuses RTNL just for mrt->mfc_hash and mrt->mfc_cache_list. Let's replace RTNL with a new per-netns mutex. Later, ip6mr_notifier_ops and ipmr_seq will be moved under CONFIG_IPV6_MROUTE. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260604224712.3209821-15-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
2290727b2f
commit
a4c9842172
|
|
@ -112,6 +112,7 @@ struct netns_ipv6 {
|
|||
struct list_head mr6_tables;
|
||||
struct fib_rules_ops *mr6_rules_ops;
|
||||
#endif
|
||||
struct mutex mfc_mutex;
|
||||
#endif
|
||||
atomic_t dev_addr_genid;
|
||||
atomic_t fib6_sernum;
|
||||
|
|
|
|||
|
|
@ -1266,7 +1266,6 @@ static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
|
|||
{
|
||||
struct mfc6_cache *c;
|
||||
|
||||
/* The entries are added/deleted only under RTNL */
|
||||
rcu_read_lock();
|
||||
c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
|
||||
&mfc->mf6cc_mcastgrp.sin6_addr, parent);
|
||||
|
|
@ -1358,6 +1357,8 @@ static int __net_init ip6mr_net_init(struct net *net)
|
|||
#endif
|
||||
int err;
|
||||
|
||||
mutex_init(&net->ipv6.mfc_mutex);
|
||||
|
||||
err = ip6mr_notifier_init(net);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -1486,7 +1487,6 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
|
|||
ttls[i] = 1;
|
||||
}
|
||||
|
||||
/* The entries are added/deleted only under RTNL */
|
||||
rcu_read_lock();
|
||||
c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
|
||||
&mfc->mf6cc_mcastgrp.sin6_addr, parent);
|
||||
|
|
@ -1581,6 +1581,8 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags,
|
|||
|
||||
/* Wipe the cache */
|
||||
if (flags & (MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC)) {
|
||||
mutex_lock(&net->ipv6.mfc_mutex);
|
||||
|
||||
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
|
||||
if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) ||
|
||||
(!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC)))
|
||||
|
|
@ -1592,6 +1594,8 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags,
|
|||
mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
|
||||
mr_cache_put(c);
|
||||
}
|
||||
|
||||
mutex_unlock(&net->ipv6.mfc_mutex);
|
||||
}
|
||||
|
||||
if (flags & MRT6_FLUSH_MFC) {
|
||||
|
|
@ -1775,15 +1779,18 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
|
|||
return -EFAULT;
|
||||
if (parent == 0)
|
||||
parent = mfc.mf6cc_parent;
|
||||
rtnl_lock();
|
||||
|
||||
mutex_lock(&net->ipv6.mfc_mutex);
|
||||
|
||||
if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
|
||||
ret = ip6mr_mfc_delete(mrt, &mfc, parent);
|
||||
else
|
||||
ret = ip6mr_mfc_add(net, mrt, &mfc,
|
||||
sk ==
|
||||
rtnl_dereference(mrt->mroute_sk),
|
||||
rcu_access_pointer(mrt->mroute_sk),
|
||||
parent);
|
||||
rtnl_unlock();
|
||||
|
||||
mutex_unlock(&net->ipv6.mfc_mutex);
|
||||
return ret;
|
||||
|
||||
case MRT6_FLUSH:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user