mac80211: fix sign error in pid controller
[safe/jmp/linux-2.6] / net / core / dev.c
index 1dc1374..c36a17a 100644 (file)
@@ -79,6 +79,7 @@
 #include <linux/cpu.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/hash.h>
 #include <linux/sched.h>
 #include <linux/mutex.h>
 #include <linux/string.h>
 #include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
+#include <net/xfrm.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
@@ -175,7 +177,7 @@ static struct list_head ptype_all __read_mostly;    /* Taps */
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
  *
- * Pure readers hold dev_base_lock for reading.
+ * Pure readers hold dev_base_lock for reading, or rcu_read_lock()
  *
  * Writers must hold the rtnl semaphore while they loop through the
  * dev_base_head list, and hold dev_base_lock for writing when they do the
@@ -196,7 +198,7 @@ EXPORT_SYMBOL(dev_base_lock);
 static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
 {
        unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
-       return &net->dev_name_head[hash & (NETDEV_HASHENTRIES - 1)];
+       return &net->dev_name_head[hash_32(hash, NETDEV_HASHBITS)];
 }
 
 static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
@@ -212,8 +214,8 @@ static int list_netdevice(struct net_device *dev)
        ASSERT_RTNL();
 
        write_lock_bh(&dev_base_lock);
-       list_add_tail(&dev->dev_list, &net->dev_base_head);
-       hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
+       list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);
+       hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
        hlist_add_head_rcu(&dev->index_hlist,
                           dev_index_hash(net, dev->ifindex));
        write_unlock_bh(&dev_base_lock);
@@ -229,8 +231,8 @@ static void unlist_netdevice(struct net_device *dev)
 
        /* Unlink dev from the device chain */
        write_lock_bh(&dev_base_lock);
-       list_del(&dev->dev_list);
-       hlist_del(&dev->name_hlist);
+       list_del_rcu(&dev->dev_list);
+       hlist_del_rcu(&dev->name_hlist);
        hlist_del_rcu(&dev->index_hlist);
        write_unlock_bh(&dev_base_lock);
 }
@@ -587,18 +589,44 @@ __setup("netdev=", netdev_boot_setup);
 struct net_device *__dev_get_by_name(struct net *net, const char *name)
 {
        struct hlist_node *p;
+       struct net_device *dev;
+       struct hlist_head *head = dev_name_hash(net, name);
 
-       hlist_for_each(p, dev_name_hash(net, name)) {
-               struct net_device *dev
-                       = hlist_entry(p, struct net_device, name_hlist);
+       hlist_for_each_entry(dev, p, head, name_hlist)
                if (!strncmp(dev->name, name, IFNAMSIZ))
                        return dev;
-       }
+
        return NULL;
 }
 EXPORT_SYMBOL(__dev_get_by_name);
 
 /**
+ *     dev_get_by_name_rcu     - find a device by its name
+ *     @net: the applicable net namespace
+ *     @name: name to find
+ *
+ *     Find an interface by name.
+ *     If the name is found a pointer to the device is returned.
+ *     If the name is not found then %NULL is returned.
+ *     The reference counters are not incremented so the caller must be
+ *     careful with locks. The caller must hold RCU lock.
+ */
+
+struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)
+{
+       struct hlist_node *p;
+       struct net_device *dev;
+       struct hlist_head *head = dev_name_hash(net, name);
+
+       hlist_for_each_entry_rcu(dev, p, head, name_hlist)
+               if (!strncmp(dev->name, name, IFNAMSIZ))
+                       return dev;
+
+       return NULL;
+}
+EXPORT_SYMBOL(dev_get_by_name_rcu);
+
+/**
  *     dev_get_by_name         - find a device by its name
  *     @net: the applicable net namespace
  *     @name: name to find
@@ -614,11 +642,11 @@ struct net_device *dev_get_by_name(struct net *net, const char *name)
 {
        struct net_device *dev;
 
-       read_lock(&dev_base_lock);
-       dev = __dev_get_by_name(net, name);
+       rcu_read_lock();
+       dev = dev_get_by_name_rcu(net, name);
        if (dev)
                dev_hold(dev);
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
        return dev;
 }
 EXPORT_SYMBOL(dev_get_by_name);
@@ -638,13 +666,13 @@ EXPORT_SYMBOL(dev_get_by_name);
 struct net_device *__dev_get_by_index(struct net *net, int ifindex)
 {
        struct hlist_node *p;
+       struct net_device *dev;
+       struct hlist_head *head = dev_index_hash(net, ifindex);
 
-       hlist_for_each(p, dev_index_hash(net, ifindex)) {
-               struct net_device *dev
-                       = hlist_entry(p, struct net_device, index_hlist);
+       hlist_for_each_entry(dev, p, head, index_hlist)
                if (dev->ifindex == ifindex)
                        return dev;
-       }
+
        return NULL;
 }
 EXPORT_SYMBOL(__dev_get_by_index);
@@ -773,15 +801,15 @@ struct net_device *dev_get_by_flags(struct net *net, unsigned short if_flags,
        struct net_device *dev, *ret;
 
        ret = NULL;
-       read_lock(&dev_base_lock);
-       for_each_netdev(net, dev) {
+       rcu_read_lock();
+       for_each_netdev_rcu(net, dev) {
                if (((dev->flags ^ if_flags) & mask) == 0) {
                        dev_hold(dev);
                        ret = dev;
                        break;
                }
        }
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
        return ret;
 }
 EXPORT_SYMBOL(dev_get_by_flags);
@@ -866,7 +894,8 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
                free_page((unsigned long) inuse);
        }
 
-       snprintf(buf, IFNAMSIZ, name, i);
+       if (buf != name)
+               snprintf(buf, IFNAMSIZ, name, i);
        if (!__dev_get_by_name(net, buf))
                return i;
 
@@ -906,6 +935,21 @@ int dev_alloc_name(struct net_device *dev, const char *name)
 }
 EXPORT_SYMBOL(dev_alloc_name);
 
+static int dev_get_valid_name(struct net *net, const char *name, char *buf,
+                             bool fmt)
+{
+       if (!dev_valid_name(name))
+               return -EINVAL;
+
+       if (fmt && strchr(name, '%'))
+               return __dev_alloc_name(net, name, buf);
+       else if (__dev_get_by_name(net, name))
+               return -EEXIST;
+       else if (buf != name)
+               strlcpy(buf, name, IFNAMSIZ);
+
+       return 0;
+}
 
 /**
  *     dev_change_name - change name of a device
@@ -929,28 +973,20 @@ int dev_change_name(struct net_device *dev, const char *newname)
        if (dev->flags & IFF_UP)
                return -EBUSY;
 
-       if (!dev_valid_name(newname))
-               return -EINVAL;
-
        if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
                return 0;
 
        memcpy(oldname, dev->name, IFNAMSIZ);
 
-       if (strchr(newname, '%')) {
-               err = dev_alloc_name(dev, newname);
-               if (err < 0)
-                       return err;
-       } else if (__dev_get_by_name(net, newname))
-               return -EEXIST;
-       else
-               strlcpy(dev->name, newname, IFNAMSIZ);
+       err = dev_get_valid_name(net, newname, dev->name, 1);
+       if (err < 0)
+               return err;
 
 rollback:
        /* For now only devices in the initial network namespace
         * are in sysfs.
         */
-       if (net == &init_net) {
+       if (net_eq(net, &init_net)) {
                ret = device_rename(&dev->dev, dev->name);
                if (ret) {
                        memcpy(dev->name, oldname, IFNAMSIZ);
@@ -960,21 +996,27 @@ rollback:
 
        write_lock_bh(&dev_base_lock);
        hlist_del(&dev->name_hlist);
-       hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
+       write_unlock_bh(&dev_base_lock);
+
+       synchronize_rcu();
+
+       write_lock_bh(&dev_base_lock);
+       hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
        write_unlock_bh(&dev_base_lock);
 
        ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev);
        ret = notifier_to_errno(ret);
 
        if (ret) {
-               if (err) {
-                       printk(KERN_ERR
-                              "%s: name change rollback failed: %d.\n",
-                              dev->name, ret);
-               } else {
+               /* err >= 0 after dev_alloc_name() or stores the first errno */
+               if (err >= 0) {
                        err = ret;
                        memcpy(dev->name, oldname, IFNAMSIZ);
                        goto rollback;
+               } else {
+                       printk(KERN_ERR
+                              "%s: name change rollback failed: %d.\n",
+                              dev->name, ret);
                }
        }
 
@@ -1062,9 +1104,9 @@ void dev_load(struct net *net, const char *name)
 {
        struct net_device *dev;
 
-       read_lock(&dev_base_lock);
-       dev = __dev_get_by_name(net, name);
-       read_unlock(&dev_base_lock);
+       rcu_read_lock();
+       dev = dev_get_by_name_rcu(net, name);
+       rcu_read_unlock();
 
        if (!dev && capable(CAP_NET_ADMIN))
                request_module("%s", name);
@@ -1311,6 +1353,7 @@ rollback:
                                nb->notifier_call(nb, NETDEV_DOWN, dev);
                        }
                        nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+                       nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
                }
        }
 
@@ -1377,6 +1420,45 @@ static inline void net_timestamp(struct sk_buff *skb)
                skb->tstamp.tv64 = 0;
 }
 
+/**
+ * dev_forward_skb - loopback an skb to another netif
+ *
+ * @dev: destination network device
+ * @skb: buffer to forward
+ *
+ * return values:
+ *     NET_RX_SUCCESS  (no congestion)
+ *     NET_RX_DROP     (packet was dropped)
+ *
+ * dev_forward_skb can be used for injecting an skb from the
+ * start_xmit function of one device into the receive queue
+ * of another device.
+ *
+ * The receiving device may be in another namespace, so
+ * we have to clear all information in the skb that could
+ * impact namespace isolation.
+ */
+int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
+{
+       skb_orphan(skb);
+
+       if (!(dev->flags & IFF_UP))
+               return NET_RX_DROP;
+
+       if (skb->len > (dev->mtu + dev->hard_header_len))
+               return NET_RX_DROP;
+
+       skb_dst_drop(skb);
+       skb->tstamp.tv64 = 0;
+       skb->pkt_type = PACKET_HOST;
+       skb->protocol = eth_type_trans(skb, dev);
+       skb->mark = 0;
+       secpath_reset(skb);
+       nf_reset(skb);
+       return netif_rx(skb);
+}
+EXPORT_SYMBOL_GPL(dev_forward_skb);
+
 /*
  *     Support routine. Sends outgoing frames to any network
  *     taps currently in use.
@@ -1725,7 +1807,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
-       int rc;
+       int rc = NETDEV_TX_OK;
 
        if (likely(!skb->next)) {
                if (!list_empty(&ptype_all))
@@ -1773,6 +1855,8 @@ gso:
                nskb->next = NULL;
                rc = ops->ndo_start_xmit(nskb, dev);
                if (unlikely(rc != NETDEV_TX_OK)) {
+                       if (rc & ~NETDEV_TX_MASK)
+                               goto out_kfree_gso_skb;
                        nskb->next = skb->next;
                        skb->next = nskb;
                        return rc;
@@ -1782,11 +1866,12 @@ gso:
                        return NETDEV_TX_BUSY;
        } while (skb->next);
 
-       skb->destructor = DEV_GSO_CB(skb)->destructor;
-
+out_kfree_gso_skb:
+       if (likely(skb->next == NULL))
+               skb->destructor = DEV_GSO_CB(skb)->destructor;
 out_kfree_skb:
        kfree_skb(skb);
-       return NETDEV_TX_OK;
+       return rc;
 }
 
 static u32 skb_tx_hashrnd;
@@ -1813,6 +1898,20 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(skb_tx_hash);
 
+static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
+{
+       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+               if (net_ratelimit()) {
+                       WARN(1, "%s selects TX queue %d, but "
+                            "real number of TX queues is %d\n",
+                            dev->name, queue_index,
+                            dev->real_num_tx_queues);
+               }
+               return 0;
+       }
+       return queue_index;
+}
+
 static struct netdev_queue *dev_pick_tx(struct net_device *dev,
                                        struct sk_buff *skb)
 {
@@ -1826,6 +1925,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 
                if (ops->ndo_select_queue) {
                        queue_index = ops->ndo_select_queue(dev, skb);
+                       queue_index = dev_cap_txqueue(dev, queue_index);
                } else {
                        queue_index = 0;
                        if (dev->real_num_tx_queues > 1)
@@ -1971,8 +2071,8 @@ gso:
                        HARD_TX_LOCK(dev, txq, cpu);
 
                        if (!netif_tx_queue_stopped(txq)) {
-                               rc = NET_XMIT_SUCCESS;
-                               if (!dev_hard_start_xmit(skb, dev, txq)) {
+                               rc = dev_hard_start_xmit(skb, dev, txq);
+                               if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
                                        goto out;
                                }
@@ -2227,7 +2327,7 @@ static int ing_filter(struct sk_buff *skb)
        if (MAX_RED_LOOP < ttl++) {
                printk(KERN_WARNING
                       "Redir loop detected Dropping packet (%d->%d)\n",
-                      skb->iif, dev->ifindex);
+                      skb->skb_iif, dev->ifindex);
                return TC_ACT_SHOT;
        }
 
@@ -2335,8 +2435,8 @@ int netif_receive_skb(struct sk_buff *skb)
        if (netpoll_receive_skb(skb))
                return NET_RX_DROP;
 
-       if (!skb->iif)
-               skb->iif = skb->dev->ifindex;
+       if (!skb->skb_iif)
+               skb->skb_iif = skb->dev->ifindex;
 
        null_or_orig = NULL;
        orig_dev = skb->dev;
@@ -2577,27 +2677,25 @@ __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                return GRO_NORMAL;
 
        for (p = napi->gro_list; p; p = p->next) {
-               NAPI_GRO_CB(p)->same_flow = (p->dev == skb->dev)
-                       && !compare_ether_header(skb_mac_header(p),
-                                                skb_gro_mac_header(skb));
+               NAPI_GRO_CB(p)->same_flow =
+                       (p->dev == skb->dev) &&
+                       !compare_ether_header(skb_mac_header(p),
+                                             skb_gro_mac_header(skb));
                NAPI_GRO_CB(p)->flush = 0;
        }
 
        return dev_gro_receive(napi, skb);
 }
 
-int napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
+gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
-       int err = NET_RX_SUCCESS;
-
        switch (ret) {
        case GRO_NORMAL:
-               return netif_receive_skb(skb);
+               if (netif_receive_skb(skb))
+                       ret = GRO_DROP;
+               break;
 
        case GRO_DROP:
-               err = NET_RX_DROP;
-               /* fall through */
-
        case GRO_MERGED_FREE:
                kfree_skb(skb);
                break;
@@ -2607,7 +2705,7 @@ int napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
                break;
        }
 
-       return err;
+       return ret;
 }
 EXPORT_SYMBOL(napi_skb_finish);
 
@@ -2627,7 +2725,7 @@ void skb_gro_reset_offset(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(skb_gro_reset_offset);
 
-int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        skb_gro_reset_offset(skb);
 
@@ -2657,26 +2755,21 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_get_frags);
 
-int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
-                     gro_result_t ret)
+gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
+                              gro_result_t ret)
 {
-       int err = NET_RX_SUCCESS;
-
        switch (ret) {
        case GRO_NORMAL:
        case GRO_HELD:
                skb->protocol = eth_type_trans(skb, napi->dev);
 
-               if (ret == GRO_NORMAL)
-                       return netif_receive_skb(skb);
-
-               skb_gro_pull(skb, -ETH_HLEN);
+               if (ret == GRO_HELD)
+                       skb_gro_pull(skb, -ETH_HLEN);
+               else if (netif_receive_skb(skb))
+                       ret = GRO_DROP;
                break;
 
        case GRO_DROP:
-               err = NET_RX_DROP;
-               /* fall through */
-
        case GRO_MERGED_FREE:
                napi_reuse_skb(napi, skb);
                break;
@@ -2685,7 +2778,7 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
                break;
        }
 
-       return err;
+       return ret;
 }
 EXPORT_SYMBOL(napi_frags_finish);
 
@@ -2726,12 +2819,12 @@ out:
 }
 EXPORT_SYMBOL(napi_frags_skb);
 
-int napi_gro_frags(struct napi_struct *napi)
+gro_result_t napi_gro_frags(struct napi_struct *napi)
 {
        struct sk_buff *skb = napi_frags_skb(napi);
 
        if (!skb)
-               return NET_RX_DROP;
+               return GRO_DROP;
 
        return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb));
 }
@@ -3054,18 +3147,18 @@ static int dev_ifconf(struct net *net, char __user *arg)
  *     in detail.
  */
 void *dev_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(dev_base_lock)
+       __acquires(RCU)
 {
        struct net *net = seq_file_net(seq);
        loff_t off;
        struct net_device *dev;
 
-       read_lock(&dev_base_lock);
+       rcu_read_lock();
        if (!*pos)
                return SEQ_START_TOKEN;
 
        off = 1;
-       for_each_netdev(net, dev)
+       for_each_netdev_rcu(net, dev)
                if (off++ == *pos)
                        return dev;
 
@@ -3074,16 +3167,18 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct net *net = seq_file_net(seq);
+       struct net_device *dev = (v == SEQ_START_TOKEN) ?
+                                 first_net_device(seq_file_net(seq)) :
+                                 next_net_device((struct net_device *)v);
+
        ++*pos;
-       return v == SEQ_START_TOKEN ?
-               first_net_device(net) : next_net_device((struct net_device *)v);
+       return rcu_dereference(dev);
 }
 
 void dev_seq_stop(struct seq_file *seq, void *v)
-       __releases(dev_base_lock)
+       __releases(RCU)
 {
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
 }
 
 static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
@@ -4292,12 +4387,12 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 EXPORT_SYMBOL(dev_set_mac_address);
 
 /*
- *     Perform the SIOCxIFxxx calls, inside read_lock(dev_base_lock)
+ *     Perform the SIOCxIFxxx calls, inside rcu_read_lock()
  */
 static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd)
 {
        int err;
-       struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
+       struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name);
 
        if (!dev)
                return -ENODEV;
@@ -4529,9 +4624,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        case SIOCGIFINDEX:
        case SIOCGIFTXQLEN:
                dev_load(net, ifr.ifr_name);
-               read_lock(&dev_base_lock);
+               rcu_read_lock();
                ret = dev_ifsioc_locked(net, &ifr, cmd);
-               read_unlock(&dev_base_lock);
+               rcu_read_unlock();
                if (!ret) {
                        if (colon)
                                *colon = ':';
@@ -4732,6 +4827,10 @@ static void rollback_registered_many(struct list_head *head)
                netdev_unregister_kobject(dev);
        }
 
+       /* Process any work delayed until the end of the batch */
+       dev = list_entry(head->next, struct net_device, unreg_list);
+       call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
+
        synchronize_net();
 
        list_for_each_entry(dev, head, unreg_list)
@@ -4802,6 +4901,33 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
 EXPORT_SYMBOL(netdev_fix_features);
 
 /**
+ *     netif_stacked_transfer_operstate -      transfer operstate
+ *     @rootdev: the root or lower level device to transfer state from
+ *     @dev: the device to transfer operstate to
+ *
+ *     Transfer operational state from root to device. This is normally
+ *     called when a stacking relationship exists between the root
+ *     device and the device(a leaf device).
+ */
+void netif_stacked_transfer_operstate(const struct net_device *rootdev,
+                                       struct net_device *dev)
+{
+       if (rootdev->operstate == IF_OPER_DORMANT)
+               netif_dormant_on(dev);
+       else
+               netif_dormant_off(dev);
+
+       if (netif_carrier_ok(rootdev)) {
+               if (!netif_carrier_ok(dev))
+                       netif_carrier_on(dev);
+       } else {
+               if (netif_carrier_ok(dev))
+                       netif_carrier_off(dev);
+       }
+}
+EXPORT_SYMBOL(netif_stacked_transfer_operstate);
+
+/**
  *     register_netdevice      - register a network device
  *     @dev: device to register
  *
@@ -4820,8 +4946,6 @@ EXPORT_SYMBOL(netdev_fix_features);
 
 int register_netdevice(struct net_device *dev)
 {
-       struct hlist_head *head;
-       struct hlist_node *p;
        int ret;
        struct net *net = dev_net(dev);
 
@@ -4850,26 +4974,14 @@ int register_netdevice(struct net_device *dev)
                }
        }
 
-       if (!dev_valid_name(dev->name)) {
-               ret = -EINVAL;
+       ret = dev_get_valid_name(net, dev->name, dev->name, 0);
+       if (ret)
                goto err_uninit;
-       }
 
        dev->ifindex = dev_new_index(net);
        if (dev->iflink == -1)
                dev->iflink = dev->ifindex;
 
-       /* Check for existence of name */
-       head = dev_name_hash(net, dev->name);
-       hlist_for_each(p, head) {
-               struct net_device *d
-                       = hlist_entry(p, struct net_device, name_hlist);
-               if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
-                       ret = -EEXIST;
-                       goto err_uninit;
-               }
-       }
-
        /* Fix illegal checksum combinations */
        if ((dev->features & NETIF_F_HW_CSUM) &&
            (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
@@ -5022,6 +5134,8 @@ static void netdev_wait_allrefs(struct net_device *dev)
 {
        unsigned long rebroadcast_time, warning_time;
 
+       linkwatch_forget_dev(dev);
+
        rebroadcast_time = warning_time = jiffies;
        while (atomic_read(&dev->refcnt) != 0) {
                if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
@@ -5029,6 +5143,8 @@ static void netdev_wait_allrefs(struct net_device *dev)
 
                        /* Rebroadcast unregister notification */
                        call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+                       /* don't resend NETDEV_UNREGISTER_BATCH, _BATCH users
+                        * should have already handle it the first time */
 
                        if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
                                     &dev->state)) {
@@ -5124,6 +5240,32 @@ void netdev_run_todo(void)
 }
 
 /**
+ *     dev_txq_stats_fold - fold tx_queues stats
+ *     @dev: device to get statistics from
+ *     @stats: struct net_device_stats to hold results
+ */
+void dev_txq_stats_fold(const struct net_device *dev,
+                       struct net_device_stats *stats)
+{
+       unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
+       unsigned int i;
+       struct netdev_queue *txq;
+
+       for (i = 0; i < dev->num_tx_queues; i++) {
+               txq = netdev_get_tx_queue(dev, i);
+               tx_bytes   += txq->tx_bytes;
+               tx_packets += txq->tx_packets;
+               tx_dropped += txq->tx_dropped;
+       }
+       if (tx_bytes || tx_packets || tx_dropped) {
+               stats->tx_bytes   = tx_bytes;
+               stats->tx_packets = tx_packets;
+               stats->tx_dropped = tx_dropped;
+       }
+}
+EXPORT_SYMBOL(dev_txq_stats_fold);
+
+/**
  *     dev_get_stats   - get network device statistics
  *     @dev: device to get statistics from
  *
@@ -5137,25 +5279,9 @@ const struct net_device_stats *dev_get_stats(struct net_device *dev)
 
        if (ops->ndo_get_stats)
                return ops->ndo_get_stats(dev);
-       else {
-               unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
-               struct net_device_stats *stats = &dev->stats;
-               unsigned int i;
-               struct netdev_queue *txq;
-
-               for (i = 0; i < dev->num_tx_queues; i++) {
-                       txq = netdev_get_tx_queue(dev, i);
-                       tx_bytes   += txq->tx_bytes;
-                       tx_packets += txq->tx_packets;
-                       tx_dropped += txq->tx_dropped;
-               }
-               if (tx_bytes || tx_packets || tx_dropped) {
-                       stats->tx_bytes   = tx_bytes;
-                       stats->tx_packets = tx_packets;
-                       stats->tx_dropped = tx_dropped;
-               }
-               return stats;
-       }
+
+       dev_txq_stats_fold(dev, &dev->stats);
+       return &dev->stats;
 }
 EXPORT_SYMBOL(dev_get_stats);
 
@@ -5235,6 +5361,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
        netdev_init_queues(dev);
 
        INIT_LIST_HEAD(&dev->napi_list);
+       INIT_LIST_HEAD(&dev->unreg_list);
+       INIT_LIST_HEAD(&dev->link_watch_list);
        dev->priv_flags = IFF_XMIT_DST_RELEASE;
        setup(dev);
        strcpy(dev->name, name);
@@ -5302,7 +5430,7 @@ EXPORT_SYMBOL(synchronize_net);
  *     unregister_netdevice_queue - remove device from the kernel
  *     @dev: device
  *     @head: list
-
+ *
  *     This function shuts down a device interface and removes it
  *     from the kernel tables.
  *     If head not NULL, device is queued to be unregistered later.
@@ -5316,7 +5444,7 @@ void unregister_netdevice_queue(struct net_device *dev, struct list_head *head)
        ASSERT_RTNL();
 
        if (head) {
-               list_add_tail(&dev->unreg_list, head);
+               list_move_tail(&dev->unreg_list, head);
        } else {
                rollback_registered(dev);
                /* Finish processing unregister after unlock */
@@ -5328,7 +5456,6 @@ EXPORT_SYMBOL(unregister_netdevice_queue);
 /**
  *     unregister_netdevice_many - unregister many devices
  *     @head: list of devices
- *
  */
 void unregister_netdevice_many(struct list_head *head)
 {
@@ -5377,8 +5504,6 @@ EXPORT_SYMBOL(unregister_netdev);
 
 int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)
 {
-       char buf[IFNAMSIZ];
-       const char *destname;
        int err;
 
        ASSERT_RTNL();
@@ -5411,20 +5536,11 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
         * we can use it in the destination network namespace.
         */
        err = -EEXIST;
-       destname = dev->name;
-       if (__dev_get_by_name(net, destname)) {
+       if (__dev_get_by_name(net, dev->name)) {
                /* We get here if we can't use the current device name */
                if (!pat)
                        goto out;
-               if (!dev_valid_name(pat))
-                       goto out;
-               if (strchr(pat, '%')) {
-                       if (__dev_alloc_name(net, pat, buf) < 0)
-                               goto out;
-                       destname = buf;
-               } else
-                       destname = pat;
-               if (__dev_get_by_name(net, destname))
+               if (dev_get_valid_name(net, pat, dev->name, 1))
                        goto out;
        }
 
@@ -5448,6 +5564,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
           this device. They should clean all the things.
        */
        call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+       call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
 
        /*
         *      Flush the unicast and multicast chains
@@ -5460,10 +5577,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        /* Actually switch the network namespace */
        dev_net_set(dev, net);
 
-       /* Assign the new device name */
-       if (destname != dev->name)
-               strcpy(dev->name, destname);
-
        /* If there is an ifindex conflict assign a new one */
        if (__dev_get_by_index(net, dev->ifindex)) {
                int iflink = (dev->iflink == dev->ifindex);
@@ -5650,14 +5763,13 @@ static struct pernet_operations __net_initdata netdev_net_ops = {
 
 static void __net_exit default_device_exit(struct net *net)
 {
-       struct net_device *dev;
+       struct net_device *dev, *aux;
        /*
-        * Push all migratable of the network devices back to the
+        * Push all migratable network devices back to the
         * initial network namespace
         */
        rtnl_lock();
-restart:
-       for_each_netdev(net, dev) {
+       for_each_netdev_safe(net, dev, aux) {
                int err;
                char fb_name[IFNAMSIZ];
 
@@ -5665,11 +5777,9 @@ restart:
                if (dev->features & NETIF_F_NETNS_LOCAL)
                        continue;
 
-               /* Delete virtual devices */
-               if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) {
-                       dev->rtnl_link_ops->dellink(dev, NULL);
-                       goto restart;
-               }
+               /* Leave virtual devices for the generic cleanup */
+               if (dev->rtnl_link_ops)
+                       continue;
 
                /* Push remaing network devices to init_net */
                snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
@@ -5679,13 +5789,37 @@ restart:
                                __func__, dev->name, err);
                        BUG();
                }
-               goto restart;
        }
        rtnl_unlock();
 }
 
+static void __net_exit default_device_exit_batch(struct list_head *net_list)
+{
+       /* At exit all network devices most be removed from a network
+        * namespace.  Do this in the reverse order of registeration.
+        * Do this across as many network namespaces as possible to
+        * improve batching efficiency.
+        */
+       struct net_device *dev;
+       struct net *net;
+       LIST_HEAD(dev_kill_list);
+
+       rtnl_lock();
+       list_for_each_entry(net, net_list, exit_list) {
+               for_each_netdev_reverse(net, dev) {
+                       if (dev->rtnl_link_ops)
+                               dev->rtnl_link_ops->dellink(dev, &dev_kill_list);
+                       else
+                               unregister_netdevice_queue(dev, &dev_kill_list);
+               }
+       }
+       unregister_netdevice_many(&dev_kill_list);
+       rtnl_unlock();
+}
+
 static struct pernet_operations __net_initdata default_device_ops = {
        .exit = default_device_exit,
+       .exit_batch = default_device_exit_batch,
 };
 
 /*