diff options
-rw-r--r-- | include/net/sock.h | 11 | ||||
-rw-r--r-- | net/core/sock.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 8 |
3 files changed, 24 insertions, 2 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 3df778ccaa82..1dbb1f9f7c1b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -926,6 +926,17 @@ void sk_stream_kill_queues(struct sock *sk); | |||
926 | void sk_set_memalloc(struct sock *sk); | 926 | void sk_set_memalloc(struct sock *sk); |
927 | void sk_clear_memalloc(struct sock *sk); | 927 | void sk_clear_memalloc(struct sock *sk); |
928 | 928 | ||
929 | void __sk_flush_backlog(struct sock *sk); | ||
930 | |||
931 | static inline bool sk_flush_backlog(struct sock *sk) | ||
932 | { | ||
933 | if (unlikely(READ_ONCE(sk->sk_backlog.tail))) { | ||
934 | __sk_flush_backlog(sk); | ||
935 | return true; | ||
936 | } | ||
937 | return false; | ||
938 | } | ||
939 | |||
929 | int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb); | 940 | int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb); |
930 | 941 | ||
931 | struct request_sock_ops; | 942 | struct request_sock_ops; |
diff --git a/net/core/sock.c b/net/core/sock.c index 70744dbb6c3f..f615e9391170 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -2048,6 +2048,13 @@ static void __release_sock(struct sock *sk) | |||
2048 | sk->sk_backlog.len = 0; | 2048 | sk->sk_backlog.len = 0; |
2049 | } | 2049 | } |
2050 | 2050 | ||
2051 | void __sk_flush_backlog(struct sock *sk) | ||
2052 | { | ||
2053 | spin_lock_bh(&sk->sk_lock.slock); | ||
2054 | __release_sock(sk); | ||
2055 | spin_unlock_bh(&sk->sk_lock.slock); | ||
2056 | } | ||
2057 | |||
2051 | /** | 2058 | /** |
2052 | * sk_wait_data - wait for data to arrive at sk_receive_queue | 2059 | * sk_wait_data - wait for data to arrive at sk_receive_queue |
2053 | * @sk: sock to wait on | 2060 | * @sk: sock to wait on |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4787f86ae64c..b945c2b046c5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1136,11 +1136,12 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | |||
1136 | /* This should be in poll */ | 1136 | /* This should be in poll */ |
1137 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); | 1137 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
1138 | 1138 | ||
1139 | mss_now = tcp_send_mss(sk, &size_goal, flags); | ||
1140 | |||
1141 | /* Ok commence sending. */ | 1139 | /* Ok commence sending. */ |
1142 | copied = 0; | 1140 | copied = 0; |
1143 | 1141 | ||
1142 | restart: | ||
1143 | mss_now = tcp_send_mss(sk, &size_goal, flags); | ||
1144 | |||
1144 | err = -EPIPE; | 1145 | err = -EPIPE; |
1145 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 1146 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
1146 | goto out_err; | 1147 | goto out_err; |
@@ -1166,6 +1167,9 @@ new_segment: | |||
1166 | if (!sk_stream_memory_free(sk)) | 1167 | if (!sk_stream_memory_free(sk)) |
1167 | goto wait_for_sndbuf; | 1168 | goto wait_for_sndbuf; |
1168 | 1169 | ||
1170 | if (sk_flush_backlog(sk)) | ||
1171 | goto restart; | ||
1172 | |||
1169 | skb = sk_stream_alloc_skb(sk, | 1173 | skb = sk_stream_alloc_skb(sk, |
1170 | select_size(sk, sg), | 1174 | select_size(sk, sg), |
1171 | sk->sk_allocation, | 1175 | sk->sk_allocation, |