mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
net: expedite synchronize_net() for cleanup_net()
cleanup_net() is the single thread responsible for netns dismantles, and a serious bottleneck. Before we can get per-netns RTNL, make sure all synchronize_net() called from this thread are using rcu_synchronize_expedited(). v3: deal with CONFIG_NET_NS=n Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Jesse Brandeburg <jbrandeburg@cloudflare.com> Link: https://patch.msgid.link/20250114205531.967841-2-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
0b6f6593aa
commit
0734d7c3d9
3 changed files with 17 additions and 1 deletions
|
@ -210,6 +210,8 @@ void net_ns_barrier(void);
|
|||
|
||||
struct ns_common *get_net_ns(struct ns_common *ns);
|
||||
struct net *get_net_ns_by_fd(int fd);
|
||||
extern struct task_struct *cleanup_net_task;
|
||||
|
||||
#else /* CONFIG_NET_NS */
|
||||
#include <linux/sched.h>
|
||||
#include <linux/nsproxy.h>
|
||||
|
|
|
@ -10099,6 +10099,15 @@ static void dev_index_release(struct net *net, int ifindex)
|
|||
WARN_ON(xa_erase(&net->dev_by_index, ifindex));
|
||||
}
|
||||
|
||||
static bool from_cleanup_net(void)
|
||||
{
|
||||
#ifdef CONFIG_NET_NS
|
||||
return current == cleanup_net_task;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Delayed registration/unregisteration */
|
||||
LIST_HEAD(net_todo_list);
|
||||
DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
|
||||
|
@ -11474,7 +11483,7 @@ EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
|
|||
void synchronize_net(void)
|
||||
{
|
||||
might_sleep();
|
||||
if (rtnl_is_locked())
|
||||
if (from_cleanup_net() || rtnl_is_locked())
|
||||
synchronize_rcu_expedited();
|
||||
else
|
||||
synchronize_rcu();
|
||||
|
|
|
@ -588,6 +588,8 @@ static void unhash_nsid(struct net *net, struct net *last)
|
|||
|
||||
static LLIST_HEAD(cleanup_list);
|
||||
|
||||
struct task_struct *cleanup_net_task;
|
||||
|
||||
static void cleanup_net(struct work_struct *work)
|
||||
{
|
||||
const struct pernet_operations *ops;
|
||||
|
@ -596,6 +598,8 @@ static void cleanup_net(struct work_struct *work)
|
|||
LIST_HEAD(net_exit_list);
|
||||
LIST_HEAD(dev_kill_list);
|
||||
|
||||
cleanup_net_task = current;
|
||||
|
||||
/* Atomically snapshot the list of namespaces to cleanup */
|
||||
net_kill_list = llist_del_all(&cleanup_list);
|
||||
|
||||
|
@ -670,6 +674,7 @@ static void cleanup_net(struct work_struct *work)
|
|||
put_user_ns(net->user_ns);
|
||||
net_free(net);
|
||||
}
|
||||
cleanup_net_task = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue