|
|
@@ -934,6 +934,22 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
|
|
|
return mss_now;
|
|
|
}
|
|
|
|
|
|
+/* In some cases, both sendpage() and sendmsg() could have added
|
|
|
+ * an skb to the write queue, but failed adding payload on it.
|
|
|
+ * We need to remove it to consume less memory, but more
|
|
|
+ * importantly be able to generate EPOLLOUT for Edge Trigger epoll()
|
|
|
+ * users.
|
|
|
+ */
|
|
|
+static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
+{
|
|
|
+ if (skb && !skb->len) {
|
|
|
+ tcp_unlink_write_queue(skb, sk);
|
|
|
+ if (tcp_write_queue_empty(sk))
|
|
|
+ tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
|
|
|
+ sk_wmem_free_skb(sk, skb);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
|
|
|
size_t size, int flags)
|
|
|
{
|
|
|
@@ -1056,6 +1072,7 @@ out:
|
|
|
return copied;
|
|
|
|
|
|
do_error:
|
|
|
+ tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk));
|
|
|
if (copied)
|
|
|
goto out;
|
|
|
out_err:
|
|
|
@@ -1409,17 +1426,11 @@ out_nopush:
|
|
|
sock_zerocopy_put(uarg);
|
|
|
return copied + copied_syn;
|
|
|
|
|
|
+do_error:
|
|
|
+ skb = tcp_write_queue_tail(sk);
|
|
|
do_fault:
|
|
|
- if (!skb->len) {
|
|
|
- tcp_unlink_write_queue(skb, sk);
|
|
|
- /* It is the one place in all of TCP, except connection
|
|
|
- * reset, where we can be unlinking the send_head.
|
|
|
- */
|
|
|
- tcp_check_send_head(sk, skb);
|
|
|
- sk_wmem_free_skb(sk, skb);
|
|
|
- }
|
|
|
+ tcp_remove_empty_skb(sk, skb);
|
|
|
|
|
|
-do_error:
|
|
|
if (copied + copied_syn)
|
|
|
goto out;
|
|
|
out_err:
|