]> err.no Git - linux-2.6/blobdiff - drivers/net/bonding/bond_main.c
bonding: Deadlock between bonding_store_bonds and bond_destroy_sysfs.
[linux-2.6] / drivers / net / bonding / bond_main.c
index 0f0675319e9c601ff76880f001b4e07d5ad829ee..e41b3e57260c057a7269d63d8ea72d3700245541 100644 (file)
@@ -2629,7 +2629,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
        unsigned char *arp_ptr;
        __be32 sip, tip;
 
-       if (dev->nd_net != &init_net)
+       if (dev_net(dev) != &init_net)
                goto out;
 
        if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
@@ -2646,10 +2646,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
        if (!slave || !slave_do_arp_validate(bond, slave))
                goto out_unlock;
 
-       /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
-       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
-                                (2 * dev->addr_len) +
-                                (2 * sizeof(u32)))))
+       if (!pskb_may_pull(skb, arp_hdr_len(dev)))
                goto out_unlock;
 
        arp = arp_hdr(skb);
@@ -3068,8 +3065,6 @@ out:
 
 #ifdef CONFIG_PROC_FS
 
-#define SEQ_START_TOKEN ((void *)1)
-
 static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct bonding *bond = seq->private;
@@ -3287,17 +3282,14 @@ static int bond_create_proc_entry(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
 
        if (bond_proc_dir) {
-               bond->proc_entry = create_proc_entry(bond_dev->name,
-                                                    S_IRUGO,
-                                                    bond_proc_dir);
+               bond->proc_entry = proc_create_data(bond_dev->name,
+                                                   S_IRUGO, bond_proc_dir,
+                                                   &bond_info_fops, bond);
                if (bond->proc_entry == NULL) {
                        printk(KERN_WARNING DRV_NAME
                               ": Warning: Cannot create /proc/net/%s/%s\n",
                               DRV_NAME, bond_dev->name);
                } else {
-                       bond->proc_entry->data = bond;
-                       bond->proc_entry->proc_fops = &bond_info_fops;
-                       bond->proc_entry->owner = THIS_MODULE;
                        memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
                }
        }
@@ -3473,7 +3465,7 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
 {
        struct net_device *event_dev = (struct net_device *)ptr;
 
-       if (event_dev->nd_net != &init_net)
+       if (dev_net(event_dev) != &init_net)
                return NOTIFY_DONE;
 
        dprintk("event_dev: %s, event: %lx\n",
@@ -3511,6 +3503,9 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
        struct bonding *bond, *bond_next;
        struct vlan_entry *vlan, *vlan_next;
 
+       if (dev_net(ifa->ifa_dev->dev) != &init_net)
+               return NOTIFY_DONE;
+
        list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
                if (bond->dev == event_dev) {
                        switch (event) {
@@ -4941,7 +4936,9 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
        if (res < 0) {
                rtnl_lock();
                down_write(&bonding_rwsem);
-               goto out_bond;
+               bond_deinit(bond_dev);
+               unregister_netdevice(bond_dev);
+               goto out_rtnl;
        }
 
        return 0;
@@ -4995,9 +4992,10 @@ err:
                destroy_workqueue(bond->wq);
        }
 
+       bond_destroy_sysfs();
+
        rtnl_lock();
        bond_free_all();
-       bond_destroy_sysfs();
        rtnl_unlock();
 out:
        return res;
@@ -5009,9 +5007,10 @@ static void __exit bonding_exit(void)
        unregister_netdevice_notifier(&bond_netdev_notifier);
        unregister_inetaddr_notifier(&bond_inetaddr_notifier);
 
+       bond_destroy_sysfs();
+
        rtnl_lock();
        bond_free_all();
-       bond_destroy_sysfs();
        rtnl_unlock();
 }