net: factorize sync-rcu call in unregister_netdevice_many
Add dev_close_many and dev_deactivate_many to factorize another sync-rcu operation on the netdevice unregister path. $ modprobe dummy numdummies=10000 $ ip link set dev dummy* up $ time rmmod dummy Without the patch With the patch real 0m 24.63s real 0m 5.15s user 0m 0.00s user 0m 0.00s sys 0m 6.05s sys 0m 5.14s Signed-off-by: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Šī revīzija ir iekļauta:

revīziju iesūtīja
David S. Miller

vecāks
c6c8fea297
revīzija
443457242b
@@ -810,20 +810,35 @@ static bool some_qdisc_is_busy(struct net_device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
void dev_deactivate(struct net_device *dev)
|
||||
void dev_deactivate_many(struct list_head *head)
|
||||
{
|
||||
netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc);
|
||||
if (dev_ingress_queue(dev))
|
||||
dev_deactivate_queue(dev, dev_ingress_queue(dev), &noop_qdisc);
|
||||
struct net_device *dev;
|
||||
|
||||
dev_watchdog_down(dev);
|
||||
list_for_each_entry(dev, head, unreg_list) {
|
||||
netdev_for_each_tx_queue(dev, dev_deactivate_queue,
|
||||
&noop_qdisc);
|
||||
if (dev_ingress_queue(dev))
|
||||
dev_deactivate_queue(dev, dev_ingress_queue(dev),
|
||||
&noop_qdisc);
|
||||
|
||||
dev_watchdog_down(dev);
|
||||
}
|
||||
|
||||
/* Wait for outstanding qdisc-less dev_queue_xmit calls. */
|
||||
synchronize_rcu();
|
||||
|
||||
/* Wait for outstanding qdisc_run calls. */
|
||||
while (some_qdisc_is_busy(dev))
|
||||
yield();
|
||||
list_for_each_entry(dev, head, unreg_list)
|
||||
while (some_qdisc_is_busy(dev))
|
||||
yield();
|
||||
}
|
||||
|
||||
void dev_deactivate(struct net_device *dev)
|
||||
{
|
||||
LIST_HEAD(single);
|
||||
|
||||
list_add(&dev->unreg_list, &single);
|
||||
dev_deactivate_many(&single);
|
||||
}
|
||||
|
||||
static void dev_init_scheduler_queue(struct net_device *dev,
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user