Due to how tcp_sendmsg() is implemented, we can have an empty skb at the tail of the write queue. Most [1] tcp_write_queue_empty() callers want to know if there is anything to send (payload and/or FIN) Instead of checking if the sk_write_queue is empty, we need to test if tp->write_seq == tp->snd_nxt [1] tcp_send_fin() was the only caller that expected to see if an skb was in the write queue, I have changed the code to reuse the tcp_write_queue_tail() result.
Unified · Split
| @@ -1766,9 +1766,18 @@ static inline bool tcp_skb_is_last(const struct sock *sk, · 1765 unmodified lines | ||
| 1766 | 1766 | return skb_queue_is_last(&sk->sk_write_queue, skb); |
| 1767 | 1767 | } |
| 1768 | 1768 | |
| 1769 | +/** | |
| 1770 | + * tcp_write_queue_empty - test if any payload (or FIN) is available in write queue | |
| 1771 | + * @sk: socket | |
| 1772 | + * | |
| 1773 | + * Since the write queue can have a temporary empty skb in it, | |
| 1774 | + * we must not use "return skb_queue_empty(&sk->sk_write_queue)" | |
| 1775 | + */ | |
| 1769 | 1776 | static inline bool tcp_write_queue_empty(const struct sock *sk) |
| 1770 | 1777 | { |
| 1771 | − return skb_queue_empty(&sk->sk_write_queue); | |
| 1778 | + const struct tcp_sock *tp = tcp_sk(sk); | |
| 1779 | + | |
| 1780 | + return tp->write_seq == tp->snd_nxt; | |
| 1772 | 1781 | } |
| 1773 | 1782 | |
| 1774 | 1783 | static inline bool tcp_rtx_queue_empty(const struct sock *sk) |
| @@ -3129,7 +3129,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size) · 3128 unmodified lines | ||
| 3129 | 3129 | */ |
| 3130 | 3130 | void tcp_send_fin(struct sock *sk) |
| 3131 | 3131 | { |
| 3132 | − struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk); | |
| 3132 | + struct sk_buff *skb, *tskb, *tail = tcp_write_queue_tail(sk); | |
| 3133 | 3133 | struct tcp_sock *tp = tcp_sk(sk); |
| 3134 | 3134 | |
| 3135 | 3135 | /* Optimization, tack on the FIN if we have one skb in write queue and |
| @@ -3137,6 +3137,7 @@ void tcp_send_fin(struct sock *sk) · 1 unmodified line | ||
| 3137 | 3137 | * Note: in the latter case, FIN packet will be sent after a timeout, |
| 3138 | 3138 | * as TCP stack thinks it has already been transmitted. |
| 3139 | 3139 | */ |
| 3140 | + tskb = tail; | |
| 3140 | 3141 | if (!tskb && tcp_under_memory_pressure(sk)) |
| 3141 | 3142 | tskb = skb_rb_last(&sk->tcp_rtx_queue); |
| 3142 | 3143 | |
| @@ -3144,7 +3145,7 @@ void tcp_send_fin(struct sock *sk) · 1 unmodified line | ||
| 3144 | 3145 | TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN; |
| 3145 | 3146 | TCP_SKB_CB(tskb)->end_seq++; |
| 3146 | 3147 | tp->write_seq++; |
| 3147 | − if (tcp_write_queue_empty(sk)) { | |
| 3148 | + if (!tail) { | |
| 3148 | 3149 | /* This means tskb was already sent. |
| 3149 | 3150 | * Pretend we included the FIN on previous transmit. |
| 3150 | 3151 | * We need to set tp->snd_nxt to the value it would have |