decnet: netdevice refcount leak
[safe/jmp/linux-2.6] / net / core / rtnetlink.c
index 6f8e077..eb42873 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/security.h>
 #include <linux/mutex.h>
 #include <linux/if_addr.h>
-#include <linux/nsproxy.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -52,6 +51,7 @@
 #include <net/pkt_sched.h>
 #include <net/fib_rules.h>
 #include <net/rtnetlink.h>
+#include <net/net_namespace.h>
 
 struct rtnl_link
 {
@@ -455,8 +455,8 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
        return nlmsg_unicast(rtnl, skb, pid);
 }
 
-int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
-               struct nlmsghdr *nlh, gfp_t flags)
+void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
+                struct nlmsghdr *nlh, gfp_t flags)
 {
        struct sock *rtnl = net->rtnl;
        int report = 0;
@@ -464,7 +464,7 @@ int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
        if (nlh)
                report = nlmsg_report(nlh);
 
-       return nlmsg_notify(rtnl, skb, pid, group, report, flags);
+       nlmsg_notify(rtnl, skb, pid, group, report, flags);
 }
 
 void rtnl_set_sk_err(struct net *net, u32 group, int error)
@@ -551,7 +551,7 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
 }
 
 static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
-                                struct net_device_stats *b)
+                                const struct net_device_stats *b)
 {
        a->rx_packets = b->rx_packets;
        a->tx_packets = b->tx_packets;
@@ -606,10 +606,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags)
 {
-       struct netdev_queue *txq;
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
-       struct net_device_stats *stats;
+       const struct net_device_stats *stats;
        struct nlattr *attr;
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@@ -637,9 +636,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (dev->master)
                NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex);
 
-       txq = netdev_get_tx_queue(dev, 0);
-       if (txq->qdisc_sleeping)
-               NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id);
+       if (dev->qdisc)
+               NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc->ops->id);
 
        if (dev->ifalias)
                NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias);
@@ -666,7 +664,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (attr == NULL)
                goto nla_put_failure;
 
-       stats = dev->get_stats(dev);
+       stats = dev_get_stats(dev);
        copy_rtnl_link_stats(nla_data(attr), stats);
 
        if (dev->rtnl_link_ops) {
@@ -725,25 +723,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
        [IFLA_INFO_DATA]        = { .type = NLA_NESTED },
 };
 
-static struct net *get_net_ns_by_pid(pid_t pid)
-{
-       struct task_struct *tsk;
-       struct net *net;
-
-       /* Lookup the network namespace */
-       net = ERR_PTR(-ESRCH);
-       rcu_read_lock();
-       tsk = find_task_by_vpid(pid);
-       if (tsk) {
-               struct nsproxy *nsproxy;
-               nsproxy = task_nsproxy(tsk);
-               if (nsproxy)
-                       net = get_net(nsproxy->net_ns);
-       }
-       rcu_read_unlock();
-       return net;
-}
-
 static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
 {
        if (dev) {
@@ -993,12 +972,20 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
 {
        int err;
        struct net_device *dev;
+       unsigned int num_queues = 1;
+       unsigned int real_num_queues = 1;
 
+       if (ops->get_tx_queues) {
+               err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues);
+               if (err)
+                       goto err;
+       }
        err = -ENOMEM;
-       dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+       dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues);
        if (!dev)
                goto err;
 
+       dev->real_num_tx_queues = real_num_queues;
        if (strchr(dev->name, '%')) {
                err = dev_alloc_name(dev, dev->name);
                if (err < 0)
@@ -1246,7 +1233,8 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       return;
 errout:
        if (err < 0)
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);