Skip to content

Commit ffabe98

Browse files
edumazetdavem330
authored andcommitted
net: make dev_unreg_count global
We can use a global dev_unreg_count counter instead of a per netns one. As a bonus we can factorize the changes done on it for bulk device removals. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 45a96c4 commit ffabe98

File tree

4 files changed

+11
-15
lines changed

4 files changed

+11
-15
lines changed

include/linux/rtnetlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ extern int rtnl_lock_killable(void);
4747
extern bool refcount_dec_and_rtnl_lock(refcount_t *r);
4848

4949
extern wait_queue_head_t netdev_unregistering_wq;
50+
extern atomic_t dev_unreg_count;
5051
extern struct rw_semaphore pernet_ops_rwsem;
5152
extern struct rw_semaphore net_rwsem;
5253

include/net/net_namespace.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ struct net {
6767
*/
6868
spinlock_t rules_mod_lock;
6969

70-
atomic_t dev_unreg_count;
71-
7270
unsigned int dev_base_seq; /* protected by rtnl_mutex */
7371
u32 ifindex;
7472

net/core/dev.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9698,11 +9698,11 @@ static void dev_index_release(struct net *net, int ifindex)
96989698
/* Delayed registration/unregisteration */
96999699
LIST_HEAD(net_todo_list);
97009700
DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
9701+
atomic_t dev_unreg_count = ATOMIC_INIT(0);
97019702

97029703
static void net_set_todo(struct net_device *dev)
97039704
{
97049705
list_add_tail(&dev->todo_list, &net_todo_list);
9705-
atomic_inc(&dev_net(dev)->dev_unreg_count);
97069706
}
97079707

97089708
static netdev_features_t netdev_sync_upper_features(struct net_device *lower,
@@ -10529,6 +10529,7 @@ void netdev_run_todo(void)
1052910529
{
1053010530
struct net_device *dev, *tmp;
1053110531
struct list_head list;
10532+
int cnt;
1053210533
#ifdef CONFIG_LOCKDEP
1053310534
struct list_head unlink_list;
1053410535

@@ -10565,6 +10566,7 @@ void netdev_run_todo(void)
1056510566
linkwatch_sync_dev(dev);
1056610567
}
1056710568

10569+
cnt = 0;
1056810570
while (!list_empty(&list)) {
1056910571
dev = netdev_wait_allrefs_any(&list);
1057010572
list_del(&dev->todo_list);
@@ -10582,12 +10584,13 @@ void netdev_run_todo(void)
1058210584
if (dev->needs_free_netdev)
1058310585
free_netdev(dev);
1058410586

10585-
if (atomic_dec_and_test(&dev_net(dev)->dev_unreg_count))
10586-
wake_up(&netdev_unregistering_wq);
10587+
cnt++;
1058710588

1058810589
/* Free network device */
1058910590
kobject_put(&dev->dev.kobj);
1059010591
}
10592+
if (cnt && atomic_sub_and_test(cnt, &dev_unreg_count))
10593+
wake_up(&netdev_unregistering_wq);
1059110594
}
1059210595

1059310596
/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
@@ -11034,6 +11037,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
1103411037
{
1103511038
struct net_device *dev, *tmp;
1103611039
LIST_HEAD(close_head);
11040+
int cnt = 0;
1103711041

1103811042
BUG_ON(dev_boot_phase);
1103911043
ASSERT_RTNL();
@@ -11130,7 +11134,9 @@ void unregister_netdevice_many_notify(struct list_head *head,
1113011134
list_for_each_entry(dev, head, unreg_list) {
1113111135
netdev_put(dev, &dev->dev_registered_tracker);
1113211136
net_set_todo(dev);
11137+
cnt++;
1113311138
}
11139+
atomic_add(cnt, &dev_unreg_count);
1113411140

1113511141
list_del(head);
1113611142
}

net/core/rtnetlink.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -483,24 +483,15 @@ EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
483483
*/
484484
static void rtnl_lock_unregistering_all(void)
485485
{
486-
struct net *net;
487-
bool unregistering;
488486
DEFINE_WAIT_FUNC(wait, woken_wake_function);
489487

490488
add_wait_queue(&netdev_unregistering_wq, &wait);
491489
for (;;) {
492-
unregistering = false;
493490
rtnl_lock();
494491
/* We held write locked pernet_ops_rwsem, and parallel
495492
* setup_net() and cleanup_net() are not possible.
496493
*/
497-
for_each_net(net) {
498-
if (atomic_read(&net->dev_unreg_count) > 0) {
499-
unregistering = true;
500-
break;
501-
}
502-
}
503-
if (!unregistering)
494+
if (!atomic_read(&dev_unreg_count))
504495
break;
505496
__rtnl_unlock();
506497

0 commit comments

Comments
 (0)