This reverts commit 3c34688e71b6b30763cb03682e0e374e80471199. The functionality of leaking VE net devices in case we cannot unregister them for too long had been added long ago, at least in VZ6.
And since Virtuozzo 7 birth is has been broken and we never hit it before, thus we can assume the original issues (when network devices failed to be released in several minutes) are gone and we don't need this crutch, so revert it. With this broken functionality - in case we really leak a net device, netdev_run_todo() does not dec net->dev_unreg_count and thus rtnl_lock_unregistering() in default_device_exit_batch() waits forever holding net_mutex which stucks lot of other operations, most noticeable - copy_net_ns(). https://jira.sw.ru/browse/PSBM-96057 Signed-off-by: Konstantin Khorenko <[email protected]> --- include/linux/netdevice.h | 1 - net/core/dev.c | 90 +++-------------------------------------------- net/core/neighbour.c | 7 ---- 3 files changed, 4 insertions(+), 94 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f287c41a5a05..bec955f1b67f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1789,7 +1789,6 @@ struct net_device { because most packets are unicast) */ - unsigned char is_leaked; #ifdef CONFIG_RPS struct netdev_rx_queue *_rx; diff --git a/net/core/dev.c b/net/core/dev.c index 0437f7769c98..4c3399f8b6d5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7745,58 +7745,6 @@ int register_netdevice(struct net_device *dev) } EXPORT_SYMBOL(register_netdevice); -/* - * We do horrible things -- we left a netdevice - * in "leaked" state, which means we release as much - * resources as possible but the device will remain - * present in namespace because someone holds a reference. - * - * The idea is to be able to force stop VE. - */ -static void ve_netdev_leak(struct net_device *dev) -{ - struct napi_struct *p, *n; - - dev->is_leaked = 1; - barrier(); - - /* - * Make sure we're unable to tx/rx - * network packets to outside. - */ - WARN_ON_ONCE(dev->flags & IFF_UP); - WARN_ON_ONCE(dev->qdisc != &noop_qdisc); - - rtnl_lock(); - - /* - * No address and napi after that. - */ - dev_addr_flush(dev); - list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) - netif_napi_del(p); - - /* - * No release_net() here since the device remains - * present in the namespace. - */ - - __rtnl_unlock(); - - /* - * Since we've already screwed the device and releasing - * it in a normal way is not possible anymore, we're - * to be sure the device will remain here forever. - */ - dev_hold(dev); - - synchronize_net(); - - pr_emerg("Device (%s:%d:%s:%p) marked as leaked\n", - dev->name, netdev_refcnt_read(dev) - 1, - ve_name(dev_net(dev)->owner_ve), dev); -} - /** * init_dummy_netdev - init a dummy network device for NAPI * @dev: device to init @@ -7884,11 +7832,10 @@ EXPORT_SYMBOL(netdev_refcnt_read); * We can get stuck here if buggy protocols don't correctly * call dev_put. */ -static int netdev_wait_allrefs(struct net_device *dev) +static void netdev_wait_allrefs(struct net_device *dev) { unsigned long rebroadcast_time, warning_time; int refcnt; - int i = 0; linkwatch_forget_dev(dev); @@ -7928,25 +7875,11 @@ static int netdev_wait_allrefs(struct net_device *dev) refcnt = netdev_refcnt_read(dev); if (time_after(jiffies, warning_time + 10 * HZ)) { - pr_emerg("unregister_netdevice: waiting for %s=%p to " - "become free. Usage count = %d\n ve=%s", - dev->name, dev, refcnt, - ve_name(dev_net(dev)->owner_ve)); + pr_emerg("unregister_netdevice: waiting for %s to become free. Usage count = %d\n", + dev->name, refcnt); warning_time = jiffies; } - - /* - * If device has lost the reference we might stuck - * in this loop forever not having a chance the VE - * to stop. - */ - if (++i > 200) { /* give 50 seconds to try */ - ve_netdev_leak(dev); - return -EBUSY; - } } - - return 0; } /* The sequence is: @@ -8005,12 +7938,7 @@ void netdev_run_todo(void) dev->reg_state = NETREG_UNREGISTERED; - /* - * Even if device get stuck here we are - * to proceed the rest of the list. - */ - if (netdev_wait_allrefs(dev)) - continue; + netdev_wait_allrefs(dev); /* paranoia */ BUG_ON(netdev_refcnt_read(dev)); @@ -8022,9 +7950,6 @@ void netdev_run_todo(void) atomic_inc(&dev_net(dev)->owner_ve->netif_avail_nr); - /* It must be the very last action, - * after this 'dev' may point to freed up memory. - */ if (dev->destructor) { dev->destructor(dev); } else { @@ -8278,13 +8203,6 @@ void free_netdev(struct net_device *dev) { struct napi_struct *p, *n; - if (dev->is_leaked) { - pr_emerg("%s: device %s=%p is leaked\n", - __func__, dev->name, dev); - dump_stack(); - return; - } - might_sleep(); netif_free_tx_queues(dev); #ifdef CONFIG_RPS diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 7a0e4b420022..bfb2a55e291b 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -766,13 +766,6 @@ void neigh_destroy(struct neighbour *neigh) NEIGH_CACHE_STAT_INC(neigh->tbl, destroys); - if (neigh->dev->is_leaked) { - printk(KERN_WARNING - "Destroying neighbour %p on leaked device\n", neigh); - dump_stack(); - return; - } - if (!neigh->dead) { pr_warn("Destroying alive neighbour %p\n", neigh); dump_stack(); -- 2.15.1 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
