mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
ipmr: Add dedicated mutex for mrt->{mfc_hash,mfc_cache_list}.
We will no longer hold RTNL for ipmr_rtm_route() to modify the MFC hash table. Only __dev_get_by_index() in rtm_to_ipmr_mfcc() is the RTNL dependant, otherwise, we just need protection for mrt->mfc_hash and mrt->mfc_cache_list. Let's add a new mutex for ipmr_mfc_add(), ipmr_mfc_delete(), and mroute_clean_tables() (setsockopt(MRT_FLUSH or MRT_DONE)). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260228221800.1082070-15-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
4480d5fa1f
commit
3c1e53e554
@@ -281,6 +281,7 @@ struct netns_ipv4 {
|
||||
#endif
|
||||
struct fib_notifier_ops *ipmr_notifier_ops;
|
||||
atomic_t ipmr_seq;
|
||||
struct mutex mfc_mutex;
|
||||
#endif
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
struct sysctl_fib_multipath_hash_seed sysctl_fib_multipath_hash_seed;
|
||||
|
||||
+22
-6
@@ -1329,6 +1329,8 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags,
|
||||
|
||||
/* Wipe the cache */
|
||||
if (flags & (MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC)) {
|
||||
mutex_lock(&net->ipv4.mfc_mutex);
|
||||
|
||||
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
|
||||
if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT_FLUSH_MFC_STATIC)) ||
|
||||
(!(c->mfc_flags & MFC_STATIC) && !(flags & MRT_FLUSH_MFC)))
|
||||
@@ -1341,6 +1343,8 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags,
|
||||
mroute_netlink_event(mrt, cache, RTM_DELROUTE);
|
||||
mr_cache_put(c);
|
||||
}
|
||||
|
||||
mutex_unlock(&net->ipv4.mfc_mutex);
|
||||
}
|
||||
|
||||
if (flags & MRT_FLUSH_MFC) {
|
||||
@@ -1498,12 +1502,17 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
|
||||
}
|
||||
if (parent == 0)
|
||||
parent = mfc.mfcc_parent;
|
||||
|
||||
mutex_lock(&net->ipv4.mfc_mutex);
|
||||
|
||||
if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY)
|
||||
ret = ipmr_mfc_delete(mrt, &mfc, parent);
|
||||
else
|
||||
ret = ipmr_mfc_add(net, mrt, &mfc,
|
||||
sk == rtnl_dereference(mrt->mroute_sk),
|
||||
parent);
|
||||
|
||||
mutex_unlock(&net->ipv4.mfc_mutex);
|
||||
break;
|
||||
case MRT_FLUSH: {
|
||||
LIST_HEAD(dev_kill_list);
|
||||
@@ -2913,21 +2922,26 @@ static int ipmr_rtm_route(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
int ret, mrtsock, parent;
|
||||
struct mr_table *tbl;
|
||||
int ret, mrtsock = 0, parent;
|
||||
struct mr_table *tbl = NULL;
|
||||
struct mfcctl mfcc;
|
||||
|
||||
mrtsock = 0;
|
||||
tbl = NULL;
|
||||
ret = rtm_to_ipmr_mfcc(net, nlh, &mfcc, &mrtsock, &tbl, extack);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
parent = ret ? mfcc.mfcc_parent : -1;
|
||||
|
||||
mutex_lock(&net->ipv4.mfc_mutex);
|
||||
|
||||
if (nlh->nlmsg_type == RTM_NEWROUTE)
|
||||
return ipmr_mfc_add(net, tbl, &mfcc, mrtsock, parent);
|
||||
ret = ipmr_mfc_add(net, tbl, &mfcc, mrtsock, parent);
|
||||
else
|
||||
return ipmr_mfc_delete(tbl, &mfcc, parent);
|
||||
ret = ipmr_mfc_delete(tbl, &mfcc, parent);
|
||||
|
||||
mutex_unlock(&net->ipv4.mfc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool ipmr_fill_table(struct mr_table *mrt, struct sk_buff *skb)
|
||||
@@ -3269,6 +3283,8 @@ static int __net_init ipmr_net_init(struct net *net)
|
||||
LIST_HEAD(dev_kill_list);
|
||||
int err;
|
||||
|
||||
mutex_init(&net->ipv4.mfc_mutex);
|
||||
|
||||
err = ipmr_notifier_init(net);
|
||||
if (err)
|
||||
goto ipmr_notifier_fail;
|
||||
|
||||
Reference in New Issue
Block a user