net: Fix lockdep regression caused by initializing netdev queues too early.
In commit aa94210411
("net: init ingress
queue") we moved the allocation and lock initialization of the queues
into alloc_netdev_mq() since register_netdevice() is way too late.
The problem is that dev->type is not setup until the setup()
callback is invoked by alloc_netdev_mq(), and the dev->type is
what determines the lockdep class to use for the locks in the
queues.
Fix this by doing the queue allocation after the setup() callback
runs.
This is safe because the setup() callback is not allowed to make any
state changes that need to be undone on error (memory allocations,
etc.). It may, however, make state changes that are undone by
free_netdev() (such as netif_napi_add(), which is done by the
ipoib driver's setup routine).
The previous code also leaked a reference to the &init_net namespace
object on RX/TX queue allocation failures.
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b2df5a8446
commit
8d3bdbd55a
|
@ -5660,18 +5660,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
|||
|
||||
dev_net_set(dev, &init_net);
|
||||
|
||||
dev->num_tx_queues = txqs;
|
||||
dev->real_num_tx_queues = txqs;
|
||||
if (netif_alloc_netdev_queues(dev))
|
||||
goto free_pcpu;
|
||||
|
||||
#ifdef CONFIG_RPS
|
||||
dev->num_rx_queues = rxqs;
|
||||
dev->real_num_rx_queues = rxqs;
|
||||
if (netif_alloc_rx_queues(dev))
|
||||
goto free_pcpu;
|
||||
#endif
|
||||
|
||||
dev->gso_max_size = GSO_MAX_SIZE;
|
||||
|
||||
INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
|
||||
|
@ -5681,9 +5669,26 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
|||
INIT_LIST_HEAD(&dev->link_watch_list);
|
||||
dev->priv_flags = IFF_XMIT_DST_RELEASE;
|
||||
setup(dev);
|
||||
|
||||
dev->num_tx_queues = txqs;
|
||||
dev->real_num_tx_queues = txqs;
|
||||
if (netif_alloc_netdev_queues(dev))
|
||||
goto free_all;
|
||||
|
||||
#ifdef CONFIG_RPS
|
||||
dev->num_rx_queues = rxqs;
|
||||
dev->real_num_rx_queues = rxqs;
|
||||
if (netif_alloc_rx_queues(dev))
|
||||
goto free_all;
|
||||
#endif
|
||||
|
||||
strcpy(dev->name, name);
|
||||
return dev;
|
||||
|
||||
free_all:
|
||||
free_netdev(dev);
|
||||
return NULL;
|
||||
|
||||
free_pcpu:
|
||||
free_percpu(dev->pcpu_refcnt);
|
||||
kfree(dev->_tx);
|
||||
|
|
Loading…
Reference in New Issue