mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-24 22:03:16 -04:00
Merge branch 'ipv4-fib-remove-rtnl-in-fib_net_exit_batch'
Kuniyuki Iwashima says: ==================== ipv4: fib: Remove RTNL in fib_net_exit_batch(). Currently, we flush all IPv4 routes at ->exit_batch() during netns dismantle, which requires an extra RTNL. IPv4 routes are not added from the fast path unlike IPv6, so we can flush routes before default_device_exit_batch(). However, there is implicit ordering between ip_fib_net_exit() and default_device_exit_batch(). This series detangles it and moves ip_fib_net_exit() to ->exit_rtnl() to save the RTNL dance. The same change for IPv6 will need more work. ==================== Link: https://patch.msgid.link/20260612063225.455191-1-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -88,7 +88,8 @@ struct fib_table *fib_new_table(struct net *net, u32 id)
|
||||
if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules)
|
||||
alias = fib_new_table(net, RT_TABLE_MAIN);
|
||||
|
||||
tb = fib_trie_table(id, alias);
|
||||
if (check_net(net))
|
||||
tb = fib_trie_table(id, alias);
|
||||
if (!tb)
|
||||
return NULL;
|
||||
|
||||
@@ -1606,7 +1607,7 @@ static void ip_fib_net_exit(struct net *net)
|
||||
struct fib_table *tb;
|
||||
|
||||
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
|
||||
hlist_del(&tb->tb_hlist);
|
||||
hlist_del_rcu(&tb->tb_hlist);
|
||||
fib_table_flush(net, tb, true);
|
||||
fib_free_table(tb);
|
||||
}
|
||||
@@ -1615,9 +1616,6 @@ static void ip_fib_net_exit(struct net *net)
|
||||
#ifdef CONFIG_IP_MULTIPLE_TABLES
|
||||
fib4_rules_exit(net);
|
||||
#endif
|
||||
|
||||
kfree(net->ipv4.fib_table_hash);
|
||||
fib4_notifier_exit(net);
|
||||
}
|
||||
|
||||
static int __net_init fib_net_init(struct net *net)
|
||||
@@ -1653,35 +1651,36 @@ static int __net_init fib_net_init(struct net *net)
|
||||
rtnl_net_lock(net);
|
||||
ip_fib_net_exit(net);
|
||||
rtnl_net_unlock(net);
|
||||
|
||||
kfree(net->ipv4.fib_table_hash);
|
||||
fib4_notifier_exit(net);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void __net_exit fib_net_exit(struct net *net)
|
||||
static void __net_exit fib_net_pre_exit(struct net *net)
|
||||
{
|
||||
fib_proc_exit(net);
|
||||
nl_fib_lookup_exit(net);
|
||||
}
|
||||
|
||||
static void __net_exit fib_net_exit_batch(struct list_head *net_list)
|
||||
static void __net_exit fib_net_exit_rtnl(struct net *net,
|
||||
struct list_head *dev_kill_list)
|
||||
{
|
||||
struct net *net;
|
||||
ip_fib_net_exit(net);
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(net, net_list, exit_list) {
|
||||
__rtnl_net_lock(net);
|
||||
ip_fib_net_exit(net);
|
||||
__rtnl_net_unlock(net);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
list_for_each_entry(net, net_list, exit_list)
|
||||
fib4_semantics_exit(net);
|
||||
static void __net_exit fib_net_exit(struct net *net)
|
||||
{
|
||||
kfree(net->ipv4.fib_table_hash);
|
||||
fib4_notifier_exit(net);
|
||||
fib4_semantics_exit(net);
|
||||
}
|
||||
|
||||
static struct pernet_operations fib_net_ops = {
|
||||
.init = fib_net_init,
|
||||
.pre_exit = fib_net_pre_exit,
|
||||
.exit_rtnl = fib_net_exit_rtnl,
|
||||
.exit = fib_net_exit,
|
||||
.exit_batch = fib_net_exit_batch,
|
||||
};
|
||||
|
||||
static const struct rtnl_msg_handler fib_rtnl_msg_handlers[] __initconst = {
|
||||
|
||||
@@ -2046,18 +2046,12 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
|
||||
hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
|
||||
struct fib_info *fi = fa->fa_info;
|
||||
|
||||
if (!fi || tb->tb_id != fa->tb_id ||
|
||||
(!(fi->fib_flags & RTNH_F_DEAD) &&
|
||||
!fib_props[fa->fa_type].error)) {
|
||||
if (!fi || tb->tb_id != fa->tb_id) {
|
||||
slen = fa->fa_slen;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* When not flushing the entire table, skip error
|
||||
* routes that are not marked for deletion.
|
||||
*/
|
||||
if (!flush_all && fib_props[fa->fa_type].error &&
|
||||
!(fi->fib_flags & RTNH_F_DEAD)) {
|
||||
if (!flush_all && !(fi->fib_flags & RTNH_F_DEAD)) {
|
||||
slen = fa->fa_slen;
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user