rps: immediate send IPI in process_backlog()
[safe/jmp/linux-2.6] / net / ipv6 / ipv6_sockglue.c
index 39e10ac..1160400 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/init.h>
 #include <linux/sysctl.h>
 #include <linux/netfilter.h>
+#include <linux/slab.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -113,9 +114,9 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
                }
                opt = xchg(&inet6_sk(sk)->opt, opt);
        } else {
-               write_lock(&sk->sk_dst_lock);
+               spin_lock(&sk->sk_dst_lock);
                opt = xchg(&inet6_sk(sk)->opt, opt);
-               write_unlock(&sk->sk_dst_lock);
+               spin_unlock(&sk->sk_dst_lock);
        }
        sk_dst_reset(sk);
 
@@ -497,13 +498,17 @@ done:
                        goto e_inval;
 
                if (val) {
+                       struct net_device *dev;
+
                        if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
                                goto e_inval;
 
-                       if (__dev_get_by_index(net, val) == NULL) {
+                       dev = dev_get_by_index(net, val);
+                       if (!dev) {
                                retv = -ENODEV;
                                break;
                        }
+                       dev_put(dev);
                }
                np->mcast_oif = val;
                retv = 0;
@@ -662,7 +667,7 @@ done:
        case IPV6_MTU_DISCOVER:
                if (optlen < sizeof(int))
                        goto e_inval;
-               if (val<0 || val>3)
+               if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE)
                        goto e_inval;
                np->pmtudisc = val;
                retv = 0;
@@ -966,14 +971,13 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
        case IPV6_MTU:
        {
                struct dst_entry *dst;
+
                val = 0;
-               lock_sock(sk);
-               dst = sk_dst_get(sk);
-               if (dst) {
+               rcu_read_lock();
+               dst = __sk_dst_get(sk);
+               if (dst)
                        val = dst_mtu(dst);
-                       dst_release(dst);
-               }
-               release_sock(sk);
+               rcu_read_unlock();
                if (!val)
                        return -ENOTCONN;
                break;
@@ -1061,12 +1065,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                else
                        val = np->mcast_hops;
 
-               dst = sk_dst_get(sk);
-               if (dst) {
-                       if (val < 0)
+               if (val < 0) {
+                       rcu_read_lock();
+                       dst = __sk_dst_get(sk);
+                       if (dst)
                                val = ip6_dst_hoplimit(dst);
-                       dst_release(dst);
+                       rcu_read_unlock();
                }
+
                if (val < 0)
                        val = sock_net(sk)->ipv6.devconf_all->hop_limit;
                break;