Merge tag 'nfs-for-3.15-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[pandora-kernel.git] / net / ipv4 / ip_tunnel.c
index a82a22d..e77381d 100644 (file)
@@ -235,13 +235,17 @@ static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
 {
        unsigned int h;
        __be32 remote;
+       __be32 i_key = parms->i_key;
 
        if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
                remote = parms->iph.daddr;
        else
                remote = 0;
 
-       h = ip_tunnel_hash(parms->i_key, remote);
+       if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
+               i_key = 0;
+
+       h = ip_tunnel_hash(i_key, remote);
        return &itn->tunnels[h];
 }
 
@@ -398,7 +402,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
        fbt = netdev_priv(itn->fb_tunnel_dev);
        dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
        if (IS_ERR(dev))
-               return NULL;
+               return ERR_CAST(dev);
 
        dev->mtu = ip_tunnel_bind_dev(dev);
 
@@ -748,9 +752,13 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
 
                t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
 
-               if (!t && (cmd == SIOCADDTUNNEL))
+               if (!t && (cmd == SIOCADDTUNNEL)) {
                        t = ip_tunnel_create(net, itn, p);
-
+                       if (IS_ERR(t)) {
+                               err = PTR_ERR(t);
+                               break;
+                       }
+               }
                if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
                        if (t != NULL) {
                                if (t->dev != dev) {
@@ -777,8 +785,9 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
                if (t) {
                        err = 0;
                        ip_tunnel_update(itn, t, dev, p, true);
-               } else
-                       err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+               } else {
+                       err = -ENOENT;
+               }
                break;
 
        case SIOCDELTUNNEL:
@@ -993,19 +1002,13 @@ int ip_tunnel_init(struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct iphdr *iph = &tunnel->parms.iph;
-       int i, err;
+       int err;
 
        dev->destructor = ip_tunnel_dev_free;
-       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
+       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
-       for_each_possible_cpu(i) {
-               struct pcpu_sw_netstats *ipt_stats;
-               ipt_stats = per_cpu_ptr(dev->tstats, i);
-               u64_stats_init(&ipt_stats->syncp);
-       }
-
        tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
        if (!tunnel->dst_cache) {
                free_percpu(dev->tstats);