Skip to content

Commit 0734d7c

Browse files
edumazetkuba-moo
authored andcommitted
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 <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0b6f659 commit 0734d7c

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

include/net/net_namespace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ void net_ns_barrier(void);
210210

211211
struct ns_common *get_net_ns(struct ns_common *ns);
212212
struct net *get_net_ns_by_fd(int fd);
213+
extern struct task_struct *cleanup_net_task;
214+
213215
#else /* CONFIG_NET_NS */
214216
#include <linux/sched.h>
215217
#include <linux/nsproxy.h>

net/core/dev.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10099,6 +10099,15 @@ static void dev_index_release(struct net *net, int ifindex)
1009910099
WARN_ON(xa_erase(&net->dev_by_index, ifindex));
1010010100
}
1010110101

10102+
static bool from_cleanup_net(void)
10103+
{
10104+
#ifdef CONFIG_NET_NS
10105+
return current == cleanup_net_task;
10106+
#else
10107+
return false;
10108+
#endif
10109+
}
10110+
1010210111
/* Delayed registration/unregisteration */
1010310112
LIST_HEAD(net_todo_list);
1010410113
DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
@@ -11474,7 +11483,7 @@ EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
1147411483
void synchronize_net(void)
1147511484
{
1147611485
might_sleep();
11477-
if (rtnl_is_locked())
11486+
if (from_cleanup_net() || rtnl_is_locked())
1147811487
synchronize_rcu_expedited();
1147911488
else
1148011489
synchronize_rcu();

net/core/net_namespace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,8 @@ static void unhash_nsid(struct net *net, struct net *last)
588588

589589
static LLIST_HEAD(cleanup_list);
590590

591+
struct task_struct *cleanup_net_task;
592+
591593
static void cleanup_net(struct work_struct *work)
592594
{
593595
const struct pernet_operations *ops;
@@ -596,6 +598,8 @@ static void cleanup_net(struct work_struct *work)
596598
LIST_HEAD(net_exit_list);
597599
LIST_HEAD(dev_kill_list);
598600

601+
cleanup_net_task = current;
602+
599603
/* Atomically snapshot the list of namespaces to cleanup */
600604
net_kill_list = llist_del_all(&cleanup_list);
601605

@@ -670,6 +674,7 @@ static void cleanup_net(struct work_struct *work)
670674
put_user_ns(net->user_ns);
671675
net_free(net);
672676
}
677+
cleanup_net_task = NULL;
673678
}
674679

675680
/**

0 commit comments

Comments
 (0)