Merge git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/linux-2.6-nsfd
[pandora-kernel.git] / net / core / rtnetlink.c
index dca9602..abd936d 100644 (file)
@@ -850,6 +850,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        struct nlattr *attr, *af_spec;
        struct rtnl_af_ops *af_ops;
 
+       ASSERT_RTNL();
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
        if (nlh == NULL)
                return -EMSGSIZE;
@@ -1007,10 +1008,11 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        s_h = cb->args[0];
        s_idx = cb->args[1];
 
+       rcu_read_lock();
        for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
                idx = 0;
                head = &net->dev_index_head[h];
-               hlist_for_each_entry(dev, node, head, index_hlist) {
+               hlist_for_each_entry_rcu(dev, node, head, index_hlist) {
                        if (idx < s_idx)
                                goto cont;
                        if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
@@ -1023,6 +1025,7 @@ cont:
                }
        }
 out:
+       rcu_read_unlock();
        cb->args[1] = idx;
        cb->args[0] = h;
 
@@ -1502,6 +1505,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        char ifname[IFNAMSIZ];
        struct nlattr *tb[IFLA_MAX+1];
        int err;
+       LIST_HEAD(list_kill);
 
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
        if (err < 0)
@@ -1525,7 +1529,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        if (!ops)
                return -EOPNOTSUPP;
 
-       ops->dellink(dev, NULL);
+       ops->dellink(dev, &list_kill);
+       unregister_netdevice_many(&list_kill);
+       list_del(&list_kill);
        return 0;
 }
 
@@ -1573,12 +1579,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
        dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
        dev->real_num_tx_queues = real_num_queues;
 
-       if (strchr(dev->name, '%')) {
-               err = dev_alloc_name(dev, dev->name);
-               if (err < 0)
-                       goto err_free;
-       }
-
        if (tb[IFLA_MTU])
                dev->mtu = nla_get_u32(tb[IFLA_MTU]);
        if (tb[IFLA_ADDRESS])
@@ -1598,8 +1598,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 
        return dev;
 
-err_free:
-       free_netdev(dev);
 err:
        return ERR_PTR(err);
 }
@@ -1966,6 +1964,8 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
        case NETDEV_GOING_DOWN:
        case NETDEV_UNREGISTER:
        case NETDEV_UNREGISTER_BATCH:
+       case NETDEV_RELEASE:
+       case NETDEV_JOIN:
                break;
        default:
                rtmsg_ifinfo(RTM_NEWLINK, dev, 0);