OSDN Git Service

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
[uclinux-h8/linux.git] / net / core / sock.c
index 080a880..6aa2e7e 100644 (file)
@@ -567,6 +567,8 @@ static int sock_setbindtodevice(struct sock *sk, char __user *optval,
 
        lock_sock(sk);
        sk->sk_bound_dev_if = index;
+       if (sk->sk_prot->rehash)
+               sk->sk_prot->rehash(sk);
        sk_dst_reset(sk);
        release_sock(sk);
 
@@ -698,6 +700,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                break;
        case SO_DONTROUTE:
                sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
+               sk_dst_reset(sk);
                break;
        case SO_BROADCAST:
                sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
@@ -950,10 +953,12 @@ set_rcvbuf:
                        clear_bit(SOCK_PASSSEC, &sock->flags);
                break;
        case SO_MARK:
-               if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+               if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
                        ret = -EPERM;
-               else
+               } else if (val != sk->sk_mark) {
                        sk->sk_mark = val;
+                       sk_dst_reset(sk);
+               }
                break;
 
        case SO_RXQ_OVFL:
@@ -1014,7 +1019,10 @@ set_rcvbuf:
 
        case SO_ZEROCOPY:
                if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6) {
-                       if (sk->sk_protocol != IPPROTO_TCP)
+                       if (!((sk->sk_type == SOCK_STREAM &&
+                              sk->sk_protocol == IPPROTO_TCP) ||
+                             (sk->sk_type == SOCK_DGRAM &&
+                              sk->sk_protocol == IPPROTO_UDP)))
                                ret = -ENOTSUPP;
                } else if (sk->sk_family != PF_RDS) {
                        ret = -ENOTSUPP;
@@ -2743,6 +2751,9 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_sndtimeo         =       MAX_SCHEDULE_TIMEOUT;
 
        sk->sk_stamp = SK_DEFAULT_STAMP;
+#if BITS_PER_LONG==32
+       seqlock_init(&sk->sk_stamp_seq);
+#endif
        atomic_set(&sk->sk_zckey, 0);
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
@@ -2842,12 +2853,13 @@ int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
        struct timeval tv;
 
        sock_enable_timestamp(sk, SOCK_TIMESTAMP);
-       tv = ktime_to_timeval(sk->sk_stamp);
+       tv = ktime_to_timeval(sock_read_timestamp(sk));
        if (tv.tv_sec == -1)
                return -ENOENT;
        if (tv.tv_sec == 0) {
-               sk->sk_stamp = ktime_get_real();
-               tv = ktime_to_timeval(sk->sk_stamp);
+               ktime_t kt = ktime_get_real();
+               sock_write_timestamp(sk, kt);
+               tv = ktime_to_timeval(kt);
        }
        return copy_to_user(userstamp, &tv, sizeof(tv)) ? -EFAULT : 0;
 }
@@ -2858,11 +2870,12 @@ int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
        struct timespec ts;
 
        sock_enable_timestamp(sk, SOCK_TIMESTAMP);
-       ts = ktime_to_timespec(sk->sk_stamp);
+       ts = ktime_to_timespec(sock_read_timestamp(sk));
        if (ts.tv_sec == -1)
                return -ENOENT;
        if (ts.tv_sec == 0) {
-               sk->sk_stamp = ktime_get_real();
+               ktime_t kt = ktime_get_real();
+               sock_write_timestamp(sk, kt);
                ts = ktime_to_timespec(sk->sk_stamp);
        }
        return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0;