]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/ipv4/tcp.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux.git] / net / ipv4 / tcp.c
index 42187a3b82f4f6280d831c34d9ca6b7bcffc191f..8a39ee79489192c02385aaadc8d1ae969fb55d23 100644 (file)
@@ -584,7 +584,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        }
        /* This barrier is coupled with smp_wmb() in tcp_reset() */
        smp_rmb();
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR;
 
        return mask;
@@ -1741,8 +1741,8 @@ static int tcp_zerocopy_receive(struct sock *sk,
                                struct tcp_zerocopy_receive *zc)
 {
        unsigned long address = (unsigned long)zc->address;
+       u32 length = 0, seq, offset, zap_len;
        const skb_frag_t *frags = NULL;
-       u32 length = 0, seq, offset;
        struct vm_area_struct *vma;
        struct sk_buff *skb = NULL;
        struct tcp_sock *tp;
@@ -1769,12 +1769,12 @@ static int tcp_zerocopy_receive(struct sock *sk,
        seq = tp->copied_seq;
        inq = tcp_inq(sk);
        zc->length = min_t(u32, zc->length, inq);
-       zc->length &= ~(PAGE_SIZE - 1);
-       if (zc->length) {
-               zap_page_range(vma, address, zc->length);
+       zap_len = zc->length & ~(PAGE_SIZE - 1);
+       if (zap_len) {
+               zap_page_range(vma, address, zap_len);
                zc->recv_skip_hint = 0;
        } else {
-               zc->recv_skip_hint = inq;
+               zc->recv_skip_hint = zc->length;
        }
        ret = 0;
        while (length + PAGE_SIZE <= zc->length) {
@@ -1864,29 +1864,33 @@ static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
                if (sock_flag(sk, SOCK_RCVTSTAMP)) {
                        if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
                                if (new_tstamp) {
-                                       struct __kernel_timespec kts = {tss->ts[0].tv_sec, tss->ts[0].tv_nsec};
-
+                                       struct __kernel_timespec kts = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_nsec = tss->ts[0].tv_nsec,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
                                                 sizeof(kts), &kts);
                                } else {
-                                       struct timespec ts_old = timespec64_to_timespec(tss->ts[0]);
-
+                                       struct __kernel_old_timespec ts_old = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_nsec = tss->ts[0].tv_nsec,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
                                                 sizeof(ts_old), &ts_old);
                                }
                        } else {
                                if (new_tstamp) {
-                                       struct __kernel_sock_timeval stv;
-
-                                       stv.tv_sec = tss->ts[0].tv_sec;
-                                       stv.tv_usec = tss->ts[0].tv_nsec / 1000;
+                                       struct __kernel_sock_timeval stv = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_usec = tss->ts[0].tv_nsec / 1000,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
                                                 sizeof(stv), &stv);
                                } else {
-                                       struct __kernel_old_timeval tv;
-
-                                       tv.tv_sec = tss->ts[0].tv_sec;
-                                       tv.tv_usec = tss->ts[0].tv_nsec / 1000;
+                                       struct __kernel_old_timeval tv = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_usec = tss->ts[0].tv_nsec / 1000,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
                                                 sizeof(tv), &tv);
                                }
@@ -1958,13 +1962,12 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
        struct sk_buff *skb, *last;
        u32 urg_hole = 0;
        struct scm_timestamping_internal tss;
-       bool has_tss = false;
-       bool has_cmsg;
+       int cmsg_flags;
 
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
 
-       if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
+       if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue) &&
            (sk->sk_state == TCP_ESTABLISHED))
                sk_busy_loop(sk, nonblock);
 
@@ -1974,7 +1977,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
        if (sk->sk_state == TCP_LISTEN)
                goto out;
 
-       has_cmsg = tp->recvmsg_inq;
+       cmsg_flags = tp->recvmsg_inq ? 1 : 0;
        timeo = sock_rcvtimeo(sk, nonblock);
 
        /* Urgent data needs to be handled specially. */
@@ -2047,7 +2050,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 
                /* Well, if we have backlog, try to process it now yet. */
 
-               if (copied >= target && !sk->sk_backlog.tail)
+               if (copied >= target && !READ_ONCE(sk->sk_backlog.tail))
                        break;
 
                if (copied) {
@@ -2157,8 +2160,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 
                if (TCP_SKB_CB(skb)->has_rxtstamp) {
                        tcp_update_recv_tstamps(skb, &tss);
-                       has_tss = true;
-                       has_cmsg = true;
+                       cmsg_flags |= 2;
                }
                if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
                        goto found_fin_ok;
@@ -2183,10 +2185,10 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 
        release_sock(sk);
 
-       if (has_cmsg) {
-               if (has_tss)
+       if (cmsg_flags) {
+               if (cmsg_flags & 2)
                        tcp_recv_timestamp(msg, sk, &tss);
-               if (tp->recvmsg_inq) {
+               if (cmsg_flags & 1) {
                        inq = tcp_inq_hint(sk);
                        put_cmsg(msg, SOL_TCP, TCP_CM_INQ, sizeof(inq), &inq);
                }
@@ -2666,6 +2668,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        /* Clean up fastopen related fields */
        tcp_free_fastopen_req(tp);
        inet->defer_connect = 0;
+       tp->fastopen_client_fail = 0;
 
        WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
 
@@ -3224,8 +3227,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
                 * tcpi_unacked -> Number of children ready for accept()
                 * tcpi_sacked  -> max backlog
                 */
-               info->tcpi_unacked = sk->sk_ack_backlog;
-               info->tcpi_sacked = sk->sk_max_ack_backlog;
+               info->tcpi_unacked = READ_ONCE(sk->sk_ack_backlog);
+               info->tcpi_sacked = READ_ONCE(sk->sk_max_ack_backlog);
                return;
        }
 
@@ -3305,6 +3308,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        info->tcpi_reord_seen = tp->reord_seen;
        info->tcpi_rcv_ooopack = tp->rcv_ooopack;
        info->tcpi_snd_wnd = tp->snd_wnd;
+       info->tcpi_fastopen_client_fail = tp->fastopen_client_fail;
        unlock_sock_fast(sk, slow);
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);