]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - net/ipv6/addrconf.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / net / ipv6 / addrconf.c
index b0e1430b64f1c3714aa332d3f98682dde3481eac..1b327f15e7e7ae7960ca8321875375673b67e385 100644 (file)
@@ -278,31 +278,31 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
 
 static int snmp6_alloc_dev(struct inet6_dev *idev)
 {
-       if (snmp_mib_init((void **)idev->stats.ipv6,
+       if (snmp_mib_init((void __percpu **)idev->stats.ipv6,
                          sizeof(struct ipstats_mib)) < 0)
                goto err_ip;
-       if (snmp_mib_init((void **)idev->stats.icmpv6,
+       if (snmp_mib_init((void __percpu **)idev->stats.icmpv6,
                          sizeof(struct icmpv6_mib)) < 0)
                goto err_icmp;
-       if (snmp_mib_init((void **)idev->stats.icmpv6msg,
+       if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg,
                          sizeof(struct icmpv6msg_mib)) < 0)
                goto err_icmpmsg;
 
        return 0;
 
 err_icmpmsg:
-       snmp_mib_free((void **)idev->stats.icmpv6);
+       snmp_mib_free((void __percpu **)idev->stats.icmpv6);
 err_icmp:
-       snmp_mib_free((void **)idev->stats.ipv6);
+       snmp_mib_free((void __percpu **)idev->stats.ipv6);
 err_ip:
        return -ENOMEM;
 }
 
 static void snmp6_free_dev(struct inet6_dev *idev)
 {
-       snmp_mib_free((void **)idev->stats.icmpv6msg);
-       snmp_mib_free((void **)idev->stats.icmpv6);
-       snmp_mib_free((void **)idev->stats.ipv6);
+       snmp_mib_free((void __percpu **)idev->stats.icmpv6msg);
+       snmp_mib_free((void __percpu **)idev->stats.icmpv6);
+       snmp_mib_free((void __percpu **)idev->stats.ipv6);
 }
 
 /* Nobody refers to this device, we may destroy it. */
@@ -502,8 +502,11 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
        if (p == &net->ipv6.devconf_dflt->forwarding)
                return 0;
 
-       if (!rtnl_trylock())
+       if (!rtnl_trylock()) {
+               /* Restore the original values before restarting */
+               *p = old;
                return restart_syscall();
+       }
 
        if (p == &net->ipv6.devconf_all->forwarding) {
                __s32 newf = net->ipv6.devconf_all->forwarding;
@@ -2802,14 +2805,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
        read_lock_bh(&idev->lock);
        if (ifp->dead)
                goto out;
-       spin_lock_bh(&ifp->lock);
 
+       spin_lock(&ifp->lock);
        if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
            idev->cnf.accept_dad < 1 ||
            !(ifp->flags&IFA_F_TENTATIVE) ||
            ifp->flags & IFA_F_NODAD) {
                ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
-               spin_unlock_bh(&ifp->lock);
+               spin_unlock(&ifp->lock);
                read_unlock_bh(&idev->lock);
 
                addrconf_dad_completed(ifp);
@@ -2817,7 +2820,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
        }
 
        if (!(idev->if_flags & IF_READY)) {
-               spin_unlock_bh(&ifp->lock);
+               spin_unlock(&ifp->lock);
                read_unlock_bh(&idev->lock);
                /*
                 * If the device is not ready:
@@ -2837,7 +2840,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
                ip6_ins_rt(ifp->rt);
 
        addrconf_dad_kick(ifp);
-       spin_unlock_bh(&ifp->lock);
+       spin_unlock(&ifp->lock);
 out:
        read_unlock_bh(&idev->lock);
 }
@@ -2853,14 +2856,15 @@ static void addrconf_dad_timer(unsigned long data)
                read_unlock_bh(&idev->lock);
                goto out;
        }
-       spin_lock_bh(&ifp->lock);
+
+       spin_lock(&ifp->lock);
        if (ifp->probes == 0) {
                /*
                 * DAD was successful
                 */
 
                ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
-               spin_unlock_bh(&ifp->lock);
+               spin_unlock(&ifp->lock);
                read_unlock_bh(&idev->lock);
 
                addrconf_dad_completed(ifp);
@@ -2870,7 +2874,7 @@ static void addrconf_dad_timer(unsigned long data)
 
        ifp->probes--;
        addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);
-       spin_unlock_bh(&ifp->lock);
+       spin_unlock(&ifp->lock);
        read_unlock_bh(&idev->lock);
 
        /* send a neighbour solicitation for our addr */
@@ -2918,12 +2922,12 @@ static void addrconf_dad_run(struct inet6_dev *idev) {
 
        read_lock_bh(&idev->lock);
        for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) {
-               spin_lock_bh(&ifp->lock);
+               spin_lock(&ifp->lock);
                if (!(ifp->flags & IFA_F_TENTATIVE)) {
-                       spin_unlock_bh(&ifp->lock);
+                       spin_unlock(&ifp->lock);
                        continue;
                }
-               spin_unlock_bh(&ifp->lock);
+               spin_unlock(&ifp->lock);
                addrconf_dad_kick(ifp);
        }
        read_unlock_bh(&idev->lock);
@@ -3765,8 +3769,8 @@ static inline size_t inet6_if_nlmsg_size(void)
                 );
 }
 
-static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items,
-                                     int bytes)
+static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib,
+                                     int items, int bytes)
 {
        int i;
        int pad = bytes - sizeof(u64) * items;
@@ -3785,10 +3789,10 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
 {
        switch(attrtype) {
        case IFLA_INET6_STATS:
-               __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
+               __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
                break;
        case IFLA_INET6_ICMP6STATS:
-               __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
+               __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
                break;
        }
 }
@@ -4041,12 +4045,15 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
 {
        int *valp = ctl->data;
        int val = *valp;
+       loff_t pos = *ppos;
        int ret;
 
        ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
        if (write)
                ret = addrconf_fixup_forwarding(ctl, valp, val);
+       if (ret)
+               *ppos = pos;
        return ret;
 }
 
@@ -4088,8 +4095,11 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
        if (p == &net->ipv6.devconf_dflt->disable_ipv6)
                return 0;
 
-       if (!rtnl_trylock())
+       if (!rtnl_trylock()) {
+               /* Restore the original values before restarting */
+               *p = old;
                return restart_syscall();
+       }
 
        if (p == &net->ipv6.devconf_all->disable_ipv6) {
                __s32 newf = net->ipv6.devconf_all->disable_ipv6;
@@ -4108,12 +4118,15 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
 {
        int *valp = ctl->data;
        int val = *valp;
+       loff_t pos = *ppos;
        int ret;
 
        ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
        if (write)
                ret = addrconf_disable_ipv6(ctl, valp, val);
+       if (ret)
+               *ppos = pos;
        return ret;
 }
 
@@ -4415,8 +4428,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
 static void addrconf_sysctl_register(struct inet6_dev *idev)
 {
-       neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6,
-                             NET_IPV6_NEIGH, "ipv6",
+       neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6",
                              &ndisc_ifinfo_sysctl_change);
        __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
                                        idev, &idev->cnf);