diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2003-05-19 09:23:57 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-05-19 09:23:57 -0700 |
| commit | 13d6a99c44c8ff3298f4d447b321000ec4cd4d8d (patch) | |
| tree | f943d5126f299f78be722d0f134e28fb3a234bcf | |
| parent | ff936f4e8148e75b20595eda5de6d3a4bb55b631 (diff) | |
[NET]: More device register/unregister fixing.
Revert the rtnl_lock API change, it is totally unneeded.
Instead we manage the todo work inside of net/core/dev.c
Also, we have to move sbin hotplug invocation outside of
the RTNL semaphore as well, both for register and unregister.
41 files changed, 177 insertions, 169 deletions
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index a145ea2cccb3..9fda5e25bab7 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -354,7 +354,7 @@ static int eth_configure(int n, void *init, char *mac, dev->watchdog_timeo = (HZ >> 1); dev->irq = UM_ETH_IRQ; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if(err) diff --git a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c index cca7b3bc5217..c1663490b387 100644 --- a/drivers/isdn/i4l/isdn_net_lib.c +++ b/drivers/isdn/i4l/isdn_net_lib.c @@ -461,7 +461,7 @@ isdn_net_addslave(char *parm) mlp = idev->mlp; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running(&mlp->dev)) { retval = -EBUSY; @@ -482,7 +482,7 @@ isdn_net_dev_delete(isdn_net_dev *idev) isdn_net_local *mlp = idev->mlp; int retval; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running(&mlp->dev)) { retval = -EBUSY; @@ -547,7 +547,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) mlp = idev->mlp; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running(&mlp->dev)) { retval = -EBUSY; @@ -701,7 +701,7 @@ isdn_net_addphone(isdn_net_ioctl_phone *phone) if (!idev) return -ENODEV; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running(&idev->mlp->dev)) { retval = -EBUSY; @@ -733,7 +733,7 @@ isdn_net_delphone(isdn_net_ioctl_phone *phone) if (!idev) return -ENODEV; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running(&idev->mlp->dev)) { retval = -EBUSY; diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index f69a1dc97724..a730ebf418ab 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -1604,7 +1604,7 @@ static int rtl8139_thread (void *data) if (tp->time_to_die) break; - rtnl_lock (NULL); + rtnl_lock (); rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); } diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 6373a7b697f2..61f2e29f066b 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -596,13 +596,12 @@ static int sixpack_open(struct tty_struct *tty) static void sixpack_close(struct tty_struct *tty) { struct sixpack *sp = (struct sixpack *) tty->disc_data; - struct net_device *unregister_list; /* First make sure we're connected. */ if (!sp || sp->magic != SIXPACK_MAGIC) return; - rtnl_lock(&unregister_list); + rtnl_lock(); dev_close(sp->dev); del_timer(&sp->tx_t); diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 9cc82c19201d..029b51e219eb 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -325,9 +325,7 @@ void cleanup_module(void) { /* Unregister devices */ for (i = 0; i < 2; i++) { if (info->dev[i].name) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(&info->dev[i]); rtnl_unlock(); } @@ -602,7 +600,7 @@ int __init setup_adapter(int card_base, int type, int n) { dev->tx_queue_len = 64; memcpy(dev->broadcast, ax25_broadcast, 7); memcpy(dev->dev_addr, ax25_test, 7); - rtnl_lock(NULL); + rtnl_lock(); if (register_netdevice(dev)) { printk(KERN_ERR "dmascc: could not register %s\n", dev->name); } diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 6613039b3986..46223bbbb7c3 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -348,7 +348,7 @@ static int ali_ircc_open(int i, chipio_t *info) dev->do_ioctl = ali_ircc_net_ioctl; dev->get_stats = ali_ircc_net_get_stats; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { @@ -391,9 +391,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 874cf3a6db46..185035d28b17 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1578,10 +1578,8 @@ toshoboe_close (struct pci_dev *pci_dev) if (self->netdev) { - struct net_device *unregister_list; - /* Remove netdevice */ - rtnl_lock (&unregister_list); + rtnl_lock (); unregister_netdevice (self->netdev); rtnl_unlock (); } @@ -1741,7 +1739,7 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) dev->stop = toshoboe_net_close; dev->do_ioctl = toshoboe_net_ioctl; - rtnl_lock (NULL); + rtnl_lock (); err = register_netdevice (dev); rtnl_unlock (); if (err) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index ec2443e18ade..73f8554c6c8d 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1207,7 +1207,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self) netdev->get_stats = irda_usb_net_get_stats; netdev->do_ioctl = irda_usb_net_ioctl; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(netdev); rtnl_unlock(); if (err) { @@ -1232,9 +1232,7 @@ static inline int irda_usb_close(struct irda_usb_cb *self) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); self->netdev = NULL; rtnl_unlock(); diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index fa1c883ee4b2..310e7ead2f4a 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -234,7 +234,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq) dev->base_addr = iobase; dev->irq = irq; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { @@ -257,9 +257,7 @@ int irport_close(struct irport_cb *self) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c index 4bf9fe0d2bc6..579f329c4cbe 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -241,7 +241,7 @@ static int irtty_open(struct tty_struct *tty) dev->get_stats = irtty_net_get_stats; dev->do_ioctl = irtty_net_ioctl; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { @@ -283,9 +283,7 @@ static void irtty_close(struct tty_struct *tty) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 5019f88ad08e..ada9a3feda69 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -344,7 +344,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) dev->do_ioctl = nsc_ircc_net_ioctl; dev->get_stats = nsc_ircc_net_get_stats; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { @@ -392,8 +392,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index b5e07005ae63..ce059524a7a2 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -1088,7 +1088,7 @@ static int __init sa1100_irda_init(void) driver_register(&sa1100ir_driver); sys_device_register(&sa1100ir_device); - rtnl_lock(NULL); + rtnl_lock(); dev = dev_alloc("irda%d", &err); if (dev) { dev->irq = IRQ_Ser2ICP; @@ -1123,9 +1123,7 @@ static void __exit sa1100_irda_exit(void) struct net_device *dev = dev_get_drvdata(&sa1100ir_device.dev); if (dev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(dev); rtnl_unlock(); } diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c index ec1440d29182..04b1ee08bea2 100644 --- a/drivers/net/irda/toshoboe.c +++ b/drivers/net/irda/toshoboe.c @@ -680,10 +680,8 @@ toshoboe_remove (struct pci_dev *pci_dev) } if (self->netdev) { - struct net_device *unregister_list; - /* Remove netdevice */ - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } @@ -840,7 +838,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid) dev->stop = toshoboe_net_close; dev->do_ioctl = toshoboe_net_ioctl; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index 8fca6923227b..3013e4e821ab 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -247,7 +247,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq, dev->do_ioctl = w83977af_net_ioctl; dev->get_stats = w83977af_net_get_stats; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); if (err) { @@ -300,9 +300,7 @@ static int w83977af_close(struct w83977af_ir *self) /* Remove netdevice */ if (self->netdev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); } diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index d452750f47dd..df5ff08ac3b9 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2586,7 +2586,7 @@ static int natsemi_suspend (struct pci_dev *pdev, u32 state) struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running (dev)) { del_timer_sync(&np->timer); @@ -2632,7 +2632,7 @@ static int natsemi_resume (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); struct netdev_private *np = dev->priv; - rtnl_lock(NULL); + rtnl_lock(); if (netif_device_present(dev)) goto out; if (netif_running(dev)) { diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 46b68f2d572f..f864774428e6 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -166,7 +166,7 @@ static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, if (new_device) { int err; - rtnl_lock(NULL); + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); @@ -532,7 +532,7 @@ int register_netdev(struct net_device *dev) { int err; - rtnl_lock(NULL); + rtnl_lock(); /* * If the name is a format string the caller wants us to @@ -566,9 +566,7 @@ out: void unregister_netdev(struct net_device *dev) { - struct net_device *list; - - rtnl_lock(&list); + rtnl_lock(); unregister_netdevice(dev); rtnl_unlock(); } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 130cee6ba7d6..5adc75e27a5f 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2291,7 +2291,7 @@ ppp_create_interface(int unit, int *retp) dev->priv = ppp; dev->destructor = ppp_device_destructor; - rtnl_lock(NULL); + rtnl_lock(); ret = register_netdevice(dev); rtnl_unlock(); if (ret != 0) { @@ -2344,9 +2344,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) ppp->dev = 0; ppp_unlock(ppp); if (dev) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); /* This will call dev_close() for us. */ unregister_netdevice(dev); diff --git a/drivers/net/slip.c b/drivers/net/slip.c index c3d264c2e820..fd8ca72d62eb 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -834,7 +834,7 @@ slip_open(struct tty_struct *tty) opens of slip channels. There are better ways, but it is the simplest one. */ - rtnl_lock(NULL); + rtnl_lock(); /* Collect hanged up channels. */ sl_sync(); diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 583c9617849b..952d0d374914 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -2162,7 +2162,7 @@ static int de_suspend (struct pci_dev *pdev, u32 state) struct net_device *dev = pci_get_drvdata (pdev); struct de_private *de = dev->priv; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running (dev)) { del_timer_sync(&de->media_timer); @@ -2197,7 +2197,7 @@ static int de_resume (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); struct de_private *de = dev->priv; - rtnl_lock(NULL); + rtnl_lock(); if (netif_device_present(dev)) goto out; if (netif_running(dev)) { diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 5f88de25c0ea..060a376ebec3 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1659,7 +1659,7 @@ static int w840_suspend (struct pci_dev *pdev, u32 state) struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; - rtnl_lock(NULL); + rtnl_lock(); if (netif_running (dev)) { del_timer_sync(&np->timer); @@ -1695,7 +1695,7 @@ static int w840_resume (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); struct netdev_private *np = dev->priv; - rtnl_lock(NULL); + rtnl_lock(); if (netif_device_present(dev)) goto out; /* device not suspended */ if (netif_running(dev)) { diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 369a18c34874..369ad8cb2729 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -438,7 +438,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, return -EFAULT; ifr.ifr_name[IFNAMSIZ-1] = '\0'; - rtnl_lock(NULL); + rtnl_lock(); err = tun_set_iff(file, &ifr); rtnl_unlock(); @@ -531,7 +531,6 @@ static int tun_chr_open(struct inode *inode, struct file * file) static int tun_chr_close(struct inode *inode, struct file *file) { struct tun_struct *tun = (struct tun_struct *)file->private_data; - struct net_device *unregister_list; if (!tun) return 0; @@ -540,7 +539,7 @@ static int tun_chr_close(struct inode *inode, struct file *file) tun_chr_fasync(-1, file, 0); - rtnl_lock(&unregister_list); + rtnl_lock(); /* Detach from net device */ file->private_data = NULL; diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c index ed8f3a7b31f4..f003d03844d3 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc_generic.c @@ -159,9 +159,7 @@ int register_hdlc_device(hdlc_device *hdlc) void unregister_hdlc_device(hdlc_device *hdlc) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); hdlc_proto_detach(hdlc); unregister_netdevice(hdlc_to_dev(hdlc)); rtnl_unlock(); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 27716f740fb0..94d077ef70be 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -625,7 +625,7 @@ static inline int netif_rx_ni(struct sk_buff *skb) } /* Called by rtnetlink.c:rtnl_unlock() */ -extern void netdev_wait_and_finish_unregister(struct net_device **list); +extern void netdev_run_todo(void); static inline void dev_put(struct net_device *dev) { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 78f491336886..1b0998fd604f 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -607,8 +607,7 @@ extern struct semaphore rtnl_sem; rtnl->data_ready(rtnl, 0); \ } while(0) -extern struct net_device **rtnl_netdev_unregister_list; -extern void rtnl_lock(struct net_device **unregister_list); +extern void rtnl_lock(void); extern void rtnl_unlock(void); extern void rtnetlink_init(void); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index ed7cf2acba21..b166e3ea34a8 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -112,9 +112,9 @@ static int __init vlan_proto_init(void) */ static void __exit vlan_cleanup_devices(void) { - struct net_device *dev, *nxt, *unregister_list; + struct net_device *dev, *nxt; - rtnl_lock(&unregister_list); + rtnl_lock(); for (dev = dev_base; dev; dev = nxt) { nxt = dev->next; if (dev->priv_flags & IFF_802_1Q_VLAN) { @@ -304,9 +304,7 @@ static int unregister_vlan_device(const char *vlan_IF_name) ret = -EINVAL; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, VLAN_DEV_INFO(dev)->vlan_id); @@ -344,7 +342,6 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, unsigned short VLAN_ID) { struct vlan_group *grp; - struct net_device *unregister_list; struct net_device *new_dev; struct net_device *real_dev; /* the ethernet device */ int malloc_size = 0; @@ -388,7 +385,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, /* From this point on, all the data structures must remain * consistent. */ - rtnl_lock(&unregister_list); + rtnl_lock(); /* The real device must be up and operating in order to * assosciate a VLAN device with it. diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 8990d16c307b..b86a34e5be6f 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1700,7 +1700,6 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { int rc = -EINVAL; struct sock *sk = sock->sk; - struct net_device *unregister_list; switch (cmd) { /* Protocol layer */ @@ -1749,7 +1748,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCDIFADDR: case SIOCSARP: /* proxy AARP */ case SIOCDARP: /* proxy AARP */ - rtnl_lock(&unregister_list); + rtnl_lock(); rc = atif_ioctl(cmd, (void *)arg); rtnl_unlock(); break; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 69eb8eb13ce2..b98773255b90 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -272,9 +272,9 @@ void br_get_port_ifindices(struct net_bridge *br, int *ifindices) void __exit br_cleanup_bridges(void) { - struct net_device *dev, *nxt, *unregister_list; + struct net_device *dev, *nxt; - rtnl_lock(&unregister_list); + rtnl_lock(); for (dev = dev_base; dev; dev = nxt) { nxt = dev->next; if (dev->priv_flags & IFF_EBRIDGE) { diff --git a/net/core/dev.c b/net/core/dev.c index 36ebb13badd8..3315e6a1ff8c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -179,9 +179,11 @@ static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0); #endif #ifdef CONFIG_HOTPLUG -static int net_run_sbin_hotplug(struct net_device *dev, char *action); +static void net_run_sbin_hotplug(struct net_device *dev, int is_register); +static void net_run_hotplug_todo(void); #else -#define net_run_sbin_hotplug(dev, action) ({ 0; }) +#define net_run_sbin_hotplug(dev, is_register) do { } while (0) +#define net_run_hotplug_todo() do { } while (0) #endif /* @@ -2355,7 +2357,6 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) int dev_ioctl(unsigned int cmd, void *arg) { - struct net_device *rtnl_list; struct ifreq ifr; int ret; char *colon; @@ -2427,7 +2428,7 @@ int dev_ioctl(unsigned int cmd, void *arg) if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(ifr.ifr_name); - rtnl_lock(&rtnl_list); + rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); if (!ret) { @@ -2466,7 +2467,7 @@ int dev_ioctl(unsigned int cmd, void *arg) if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(ifr.ifr_name); - rtnl_lock(&rtnl_list); + rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); return ret; @@ -2488,7 +2489,7 @@ int dev_ioctl(unsigned int cmd, void *arg) (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15)) { dev_load(ifr.ifr_name); - rtnl_lock(&rtnl_list); + rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); if (!ret && copy_to_user(arg, &ifr, @@ -2507,7 +2508,7 @@ int dev_ioctl(unsigned int cmd, void *arg) return -EPERM; } dev_load(ifr.ifr_name); - rtnl_lock(&rtnl_list); + rtnl_lock(); /* Follow me in net/core/wireless.c */ ret = wireless_process_ioctl(&ifr, cmd); rtnl_unlock(); @@ -2567,6 +2568,7 @@ int register_netdevice(struct net_device *dev) int ret; BUG_ON(dev_boot_phase); + ASSERT_RTNL(); spin_lock_init(&dev->queue_lock); spin_lock_init(&dev->xmit_lock); @@ -2639,7 +2641,7 @@ int register_netdevice(struct net_device *dev) /* Notify protocols, that a new device appeared. */ notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); - net_run_sbin_hotplug(dev, "register"); + net_run_sbin_hotplug(dev, 1); ret = 0; out: @@ -2730,11 +2732,13 @@ static void netdev_wait_allrefs(struct net_device *dev) /* The sequence is: * - * struct net_device *local_list; - * - * rtnl_lock(&local_list); - * unregister_netdevice(x1); - * unregister_netdevice(x2); + * rtnl_lock(); + * ... + * register_netdevyce(x1); + * register_netdevyce(x2); + * ... + * unregister_netdevice(y1); + * unregister_netdevice(y2); * ... * rtnl_unlock(); * @@ -2745,21 +2749,32 @@ static void netdev_wait_allrefs(struct net_device *dev) * 2) Since we run with the RTNL semaphore not held, we can sleep * safely in order to wait for the netdev refcnt to drop to zero. */ -void netdev_wait_and_finish_unregister(struct net_device **devp) +static spinlock_t unregister_todo_lock = SPIN_LOCK_UNLOCKED; +static struct net_device *unregister_todo; + +void netdev_run_todo(void) { struct net_device *dev; - while ((dev = *devp) != NULL) { - *devp = dev->next; - dev->next = NULL; + net_run_hotplug_todo(); + + spin_lock(&unregister_todo_lock); + dev = unregister_todo; + unregister_todo = NULL; + spin_unlock(&unregister_todo_lock); - net_run_sbin_hotplug(dev, "unregister"); + while (dev) { + struct net_device *next = dev->next; + + dev->next = NULL; netdev_wait_allrefs(dev); BUG_ON(atomic_read(&dev->refcnt)); netdev_finish_unregister(dev); + + dev = next; } } @@ -2789,7 +2804,6 @@ int unregister_netdevice(struct net_device *dev) BUG_ON(dev_boot_phase); ASSERT_RTNL(); - BUG_ON(!rtnl_netdev_unregister_list); /* If device is running, close it first. */ if (dev->flags & IFF_UP) @@ -2803,8 +2817,6 @@ int unregister_netdevice(struct net_device *dev) if (d == dev) { write_lock_bh(&dev_base_lock); *dp = d->next; - d->next = *rtnl_netdev_unregister_list; - *rtnl_netdev_unregister_list = d; write_unlock_bh(&dev_base_lock); break; } @@ -2824,7 +2836,7 @@ int unregister_netdevice(struct net_device *dev) /* Shutdown queueing discipline. */ dev_shutdown(dev); - net_run_sbin_hotplug(dev, "unregister"); + net_run_sbin_hotplug(dev, 0); /* Notify protocols, that we are about to destroy this device. They should clean all the things. @@ -2847,6 +2859,12 @@ int unregister_netdevice(struct net_device *dev) #endif kobject_unregister(&dev->kobj); + + spin_lock(&unregister_todo_lock); + dev->next = unregister_todo; + unregister_todo = dev; + spin_unlock(&unregister_todo_lock); + dev_put(dev); return 0; } @@ -3016,18 +3034,22 @@ subsys_initcall(net_dev_init); #ifdef CONFIG_HOTPLUG -/* Notify userspace when a netdevice event occurs, - * by running '/sbin/hotplug net' with certain - * environment variables set. - */ +struct net_hotplug_todo { + struct net_hotplug_todo *next; + char ifname[IFNAMSIZ]; + int is_register; +}; +static spinlock_t net_hotplug_list_lock = SPIN_LOCK_UNLOCKED; +static struct net_hotplug_todo *net_hotplug_list; -static int net_run_sbin_hotplug(struct net_device *dev, char *action) +static void net_run_hotplug_one(struct net_hotplug_todo *ent) { char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32]; int i; - sprintf(ifname, "INTERFACE=%s", dev->name); - sprintf(action_str, "ACTION=%s", action); + sprintf(ifname, "INTERFACE=%s", ent->ifname); + sprintf(action_str, "ACTION=%s", + (ent->is_register ? "register" : "unregister")); i = 0; argv[i++] = hotplug_path; @@ -3042,6 +3064,46 @@ static int net_run_sbin_hotplug(struct net_device *dev, char *action) envp [i++] = action_str; envp [i] = 0; - return call_usermodehelper(argv [0], argv, envp, 0); + call_usermodehelper(argv [0], argv, envp, 0); +} + +static void net_run_hotplug_todo(void) +{ + struct net_hotplug_todo *list; + + spin_lock(&net_hotplug_list_lock); + list = net_hotplug_list; + net_hotplug_list = NULL; + spin_unlock(&net_hotplug_list_lock); + + while (list != NULL) { + struct net_hotplug_todo *next = list->next; + + net_run_hotplug_one(list); + + kfree(list); + list = next; + } +} + +/* Notify userspace when a netdevice event occurs, + * by running '/sbin/hotplug net' with certain + * environment variables set. + */ + +static void net_run_sbin_hotplug(struct net_device *dev, int is_register) +{ + struct net_hotplug_todo *ent = kmalloc(sizeof(*ent), GFP_KERNEL); + + if (!ent) + return; + + memcpy(ent->ifname, dev->name, IFNAMSIZ); + ent->is_register = is_register; + + spin_lock(&net_hotplug_list_lock); + ent->next = net_hotplug_list; + net_hotplug_list = ent; + spin_unlock(&net_hotplug_list_lock); } #endif diff --git a/net/core/link_watch.c b/net/core/link_watch.c index dbe4562bb573..958385890b79 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -91,7 +91,7 @@ static void linkwatch_event(void *dummy) linkwatch_nextevent = jiffies + HZ; clear_bit(LW_RUNNING, &linkwatch_flags); - rtnl_lock(NULL); + rtnl_lock(); linkwatch_run_queue(); rtnl_unlock(); } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5756d6794dba..37400a8c62e9 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -52,30 +52,18 @@ DECLARE_MUTEX(rtnl_sem); -struct net_device **rtnl_netdev_unregister_list; - -void rtnl_lock(struct net_device **unregister_list) +void rtnl_lock() { rtnl_shlock(); rtnl_exlock(); - BUG_ON(rtnl_netdev_unregister_list); - if (unregister_list) { - *unregister_list = NULL; - rtnl_netdev_unregister_list = unregister_list; - } } void rtnl_unlock(void) { - struct net_device **list = rtnl_netdev_unregister_list; - - rtnl_netdev_unregister_list = NULL; - rtnl_exunlock(); rtnl_shunlock(); - if (list) - netdev_wait_and_finish_unregister(list); + netdev_run_todo(); } int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) @@ -498,13 +486,10 @@ static void rtnetlink_rcv(struct sock *sk, int len) { do { struct sk_buff *skb; - struct net_device *unregister_list; if (rtnl_shlock_nowait()) return; - rtnl_netdev_unregister_list = &unregister_list; - while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (rtnetlink_rcv_skb(skb)) { if (skb->len) @@ -516,10 +501,9 @@ static void rtnetlink_rcv(struct sock *sk, int len) kfree_skb(skb); } - rtnl_netdev_unregister_list = NULL; - netdev_wait_and_finish_unregister(&unregister_list); - up(&rtnl_sem); + + netdev_run_todo(); } while (rtnl && rtnl->receive_queue.qlen); } diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 014af6985d3b..4711ac69f3d1 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -584,7 +584,7 @@ int dn_dev_ioctl(unsigned int cmd, void *arg) return -EINVAL; } - rtnl_lock(NULL); + rtnl_lock(); if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) { ret = -ENODEV; @@ -1258,7 +1258,7 @@ void dn_dev_devices_off(void) { struct net_device *dev; - rtnl_lock(NULL); + rtnl_lock(); for(dev = dev_base; dev; dev = dev->next) dn_dev_down(dev); rtnl_unlock(); @@ -1269,7 +1269,7 @@ void dn_dev_devices_on(void) { struct net_device *dev; - rtnl_lock(NULL); + rtnl_lock(); for(dev = dev_base; dev; dev = dev->next) { if (dev->flags & IFF_UP) dn_dev_up(dev); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 41e81826c005..b1368d019c2b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1035,7 +1035,7 @@ int arp_ioctl(unsigned int cmd, void *arg) if (!(r.arp_flags & ATF_NETMASK)) ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = htonl(0xFFFFFFFFUL); - rtnl_lock(NULL); + rtnl_lock(); if (r.arp_dev[0]) { err = -ENODEV; if ((dev = __dev_get_by_name(r.arp_dev)) == NULL) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index d092bbf1777b..c66cf0b5950b 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -493,7 +493,7 @@ int devinet_ioctl(unsigned int cmd, void *arg) struct in_device *in_dev; struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; - struct net_device *dev, *unregister_list; + struct net_device *dev; char *colon; int ret = -EFAULT; int tryaddrmatch = 0; @@ -552,7 +552,7 @@ int devinet_ioctl(unsigned int cmd, void *arg) goto out; } - rtnl_lock(&unregister_list); + rtnl_lock(); ret = -ENODEV; if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index b2c1704f59b1..bc68ff57db9b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -251,7 +251,7 @@ int ip_rt_ioctl(unsigned int cmd, void *arg) return -EPERM; if (copy_from_user(&r, arg, sizeof(struct rtentry))) return -EFAULT; - rtnl_lock(NULL); + rtnl_lock(); err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r); if (err == 0) { if (cmd == SIOCDELRT) { diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index e92e8bf4b96e..680ab028ad69 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1650,7 +1650,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) struct inet_opt *inet = inet_sk(sk); struct ip_mc_socklist *iml, **imlp; - rtnl_lock(NULL); + rtnl_lock(); for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr && iml->multi.imr_address.s_addr==imr->imr_address.s_addr && @@ -2028,7 +2028,7 @@ void ip_mc_drop_socket(struct sock *sk) if (inet->mc_list == NULL) return; - rtnl_lock(NULL); + rtnl_lock(); while ((iml = inet->mc_list) != NULL) { struct in_device *in_dev; inet->mc_list = iml->next; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index e9a57417f5b6..b6c5c1c872c4 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -825,9 +825,7 @@ static void mroute_clean_tables(struct sock *sk) static void mrtsock_destruct(struct sock *sk) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); if (sk == mroute_socket) { ipv4_devconf.mc_forwarding--; @@ -852,7 +850,6 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen) int ret; struct vifctl vif; struct mfcctl mfc; - struct net_device *unregister_list; if(optname!=MRT_INIT) { @@ -868,7 +865,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen) if(optlen!=sizeof(int)) return -ENOPROTOOPT; - rtnl_lock(NULL); + rtnl_lock(); if (mroute_socket) { rtnl_unlock(); return -EADDRINUSE; @@ -896,7 +893,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen) return -EFAULT; if(vif.vifc_vifi >= MAXVIFS) return -ENFILE; - rtnl_lock(&unregister_list); + rtnl_lock(); if (optname==MRT_ADD_VIF) { ret = vif_add(&vif, sk==mroute_socket); } else { @@ -915,7 +912,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen) return -EINVAL; if (copy_from_user(&mfc,optval, sizeof(mfc))) return -EFAULT; - rtnl_lock(NULL); + rtnl_lock(); if (optname==MRT_DEL_MFC) ret = ipmr_mfc_delete(&mfc); else @@ -940,7 +937,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen) if(get_user(v,(int *)optval)) return -EFAULT; v = (v)?1:0; - rtnl_lock(NULL); + rtnl_lock(); ret = 0; if (v != mroute_do_pim) { mroute_do_pim = v; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2e848d529730..5eac36c4cc3e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1480,7 +1480,7 @@ int addrconf_set_dstaddr(void *arg) struct net_device *dev; int err = -EINVAL; - rtnl_lock(NULL); + rtnl_lock(); err = -EFAULT; if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) @@ -1605,7 +1605,7 @@ int addrconf_add_ifaddr(void *arg) if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) return -EFAULT; - rtnl_lock(NULL); + rtnl_lock(); err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; @@ -1622,7 +1622,7 @@ int addrconf_del_ifaddr(void *arg) if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) return -EFAULT; - rtnl_lock(NULL); + rtnl_lock(); err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; @@ -2705,7 +2705,7 @@ void __init addrconf_init(void) #ifdef MODULE /* This takes sense only during module load. */ - rtnl_lock(NULL); + rtnl_lock(); for (dev = dev_base; dev; dev = dev->next) { if (!(dev->flags&IFF_UP)) continue; @@ -2754,7 +2754,7 @@ void addrconf_cleanup(void) addrconf_sysctl_unregister(&ipv6_devconf); #endif - rtnl_lock(NULL); + rtnl_lock(); /* * clean dev list. diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9c458235043b..6b2ff60d42bf 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1176,7 +1176,7 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg) if (err) return -EFAULT; - rtnl_lock(NULL); + rtnl_lock(); switch (cmd) { case SIOCADDRT: err = ip6_route_add(&rtmsg, NULL, NULL); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 18e48211c26e..c50d55b4765b 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -250,7 +250,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) goto out; /* bind to a specific mac, optional. */ if (!llc_mac_null(addr->sllc_smac)) { - rtnl_lock(NULL); + rtnl_lock(); dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); rtnl_unlock(); rc = -ENETUNREACH; @@ -414,7 +414,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, goto out; } if (!llc->dev) { - rtnl_lock(NULL); + rtnl_lock(); dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); rtnl_unlock(); if (!dev) @@ -764,7 +764,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, goto release; } if (!llc->dev) { - rtnl_lock(NULL); + rtnl_lock(); dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); rtnl_unlock(); rc = -ENETUNREACH; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c3e917a01f8e..a83a22015c04 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1170,7 +1170,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) struct net_device *dev; int err; - rtnl_lock(NULL); + rtnl_lock(); err = -ENODEV; dev = __dev_get_by_index(mreq->mr_ifindex); @@ -1217,7 +1217,7 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) { struct packet_mclist *ml, **mlp; - rtnl_lock(NULL); + rtnl_lock(); for (mlp = &pkt_sk(sk)->mclist; (ml = *mlp) != NULL; mlp = &ml->next) { if (ml->ifindex == mreq->mr_ifindex && @@ -1250,7 +1250,7 @@ static void packet_flush_mclist(struct sock *sk) if (!po->mclist) return; - rtnl_lock(NULL); + rtnl_lock(); while ((ml = po->mclist) != NULL) { struct net_device *dev; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 7f936d52556c..667cfa0a72f7 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -456,10 +456,9 @@ int init_module(void) int __init teql_init(void) #endif { - struct net_device *unregister_list; int err; - rtnl_lock(&unregister_list); + rtnl_lock(); the_master.dev.priv = (void*)&the_master; err = dev_alloc_name(&the_master.dev, "teql%d"); @@ -482,9 +481,7 @@ int __init teql_init(void) #ifdef MODULE void cleanup_module(void) { - struct net_device *unregister_list; - - rtnl_lock(&unregister_list); + rtnl_lock(); unregister_qdisc(&the_master.qops); unregister_netdevice(&the_master.dev); rtnl_unlock(); |
