arm64: dts: rockchip: Add reset property for rk3368 mipi
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / datagram.c
index b28e863fe0a7143b199bee51cfdf242c125f31cf..f915abff1350a86af8d5bb89725b751c061b0fb5 100644 (file)
@@ -20,7 +20,7 @@
 #include <net/route.h>
 #include <net/tcp_states.h>
 
-int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
@@ -39,8 +39,6 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        sk_dst_reset(sk);
 
-       lock_sock(sk);
-
        oif = sk->sk_bound_dev_if;
        saddr = inet->inet_saddr;
        if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
@@ -53,11 +51,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr,
                              RT_CONN_FLAGS(sk), oif,
                              sk->sk_protocol,
-                             inet->inet_sport, usin->sin_port, sk, true);
+                             inet->inet_sport, usin->sin_port, sk);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                goto out;
        }
 
@@ -76,28 +74,47 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        inet->inet_daddr = fl4->daddr;
        inet->inet_dport = usin->sin_port;
        sk->sk_state = TCP_ESTABLISHED;
+       sk_set_txhash(sk);
        inet->inet_id = jiffies;
 
        sk_dst_set(sk, &rt->dst);
        err = 0;
 out:
-       release_sock(sk);
        return err;
 }
+EXPORT_SYMBOL(__ip4_datagram_connect);
+
+int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+       int res;
+
+       lock_sock(sk);
+       res = __ip4_datagram_connect(sk, uaddr, addr_len);
+       release_sock(sk);
+       return res;
+}
 EXPORT_SYMBOL(ip4_datagram_connect);
 
+/* Because UDP xmit path can manipulate sk_dst_cache without holding
+ * socket lock, we need to use sk_dst_set() here,
+ * even if we own the socket lock.
+ */
 void ip4_datagram_release_cb(struct sock *sk)
 {
        const struct inet_sock *inet = inet_sk(sk);
        const struct ip_options_rcu *inet_opt;
        __be32 daddr = inet->inet_daddr;
+       struct dst_entry *dst;
        struct flowi4 fl4;
        struct rtable *rt;
 
-       if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0))
-               return;
-
        rcu_read_lock();
+
+       dst = __sk_dst_get(sk);
+       if (!dst || !dst->obsolete || dst->ops->check(dst, 0)) {
+               rcu_read_unlock();
+               return;
+       }
        inet_opt = rcu_dereference(inet->inet_opt);
        if (inet_opt && inet_opt->opt.srr)
                daddr = inet_opt->opt.faddr;
@@ -105,8 +122,10 @@ void ip4_datagram_release_cb(struct sock *sk)
                                   inet->inet_saddr, inet->inet_dport,
                                   inet->inet_sport, sk->sk_protocol,
                                   RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
-       if (!IS_ERR(rt))
-               __sk_dst_set(sk, &rt->dst);
+
+       dst = !IS_ERR(rt) ? &rt->dst : NULL;
+       sk_dst_set(sk, dst);
+
        rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);