@@ -1567,17 +1567,11 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len)
1567
1567
* calculation of whether or not we must ACK for the sake of
1568
1568
* a window update.
1569
1569
*/
1570
- void tcp_cleanup_rbuf (struct sock * sk , int copied )
1570
+ static void __tcp_cleanup_rbuf (struct sock * sk , int copied )
1571
1571
{
1572
1572
struct tcp_sock * tp = tcp_sk (sk );
1573
1573
bool time_to_ack = false;
1574
1574
1575
- struct sk_buff * skb = skb_peek (& sk -> sk_receive_queue );
1576
-
1577
- WARN (skb && !before (tp -> copied_seq , TCP_SKB_CB (skb )-> end_seq ),
1578
- "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n" ,
1579
- tp -> copied_seq , TCP_SKB_CB (skb )-> end_seq , tp -> rcv_nxt );
1580
-
1581
1575
if (inet_csk_ack_scheduled (sk )) {
1582
1576
const struct inet_connection_sock * icsk = inet_csk (sk );
1583
1577
@@ -1623,6 +1617,17 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
1623
1617
tcp_send_ack (sk );
1624
1618
}
1625
1619
1620
+ void tcp_cleanup_rbuf (struct sock * sk , int copied )
1621
+ {
1622
+ struct sk_buff * skb = skb_peek (& sk -> sk_receive_queue );
1623
+ struct tcp_sock * tp = tcp_sk (sk );
1624
+
1625
+ WARN (skb && !before (tp -> copied_seq , TCP_SKB_CB (skb )-> end_seq ),
1626
+ "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n" ,
1627
+ tp -> copied_seq , TCP_SKB_CB (skb )-> end_seq , tp -> rcv_nxt );
1628
+ __tcp_cleanup_rbuf (sk , copied );
1629
+ }
1630
+
1626
1631
static void tcp_eat_recv_skb (struct sock * sk , struct sk_buff * skb )
1627
1632
{
1628
1633
__skb_unlink (skb , & sk -> sk_receive_queue );
@@ -1756,34 +1761,26 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
1756
1761
if (sk -> sk_state == TCP_LISTEN )
1757
1762
return - ENOTCONN ;
1758
1763
1759
- while ((skb = tcp_recv_skb (sk , seq , & offset )) != NULL ) {
1760
- int used ;
1761
-
1762
- __skb_unlink (skb , & sk -> sk_receive_queue );
1763
- used = recv_actor (sk , skb );
1764
- if (used <= 0 ) {
1765
- if (!copied )
1766
- copied = used ;
1767
- break ;
1768
- }
1769
- seq += used ;
1770
- copied += used ;
1764
+ skb = tcp_recv_skb (sk , seq , & offset );
1765
+ if (!skb )
1766
+ return 0 ;
1771
1767
1772
- if (TCP_SKB_CB (skb )-> tcp_flags & TCPHDR_FIN ) {
1773
- consume_skb (skb );
1768
+ __skb_unlink (skb , & sk -> sk_receive_queue );
1769
+ WARN_ON (!skb_set_owner_sk_safe (skb , sk ));
1770
+ copied = recv_actor (sk , skb );
1771
+ if (copied >= 0 ) {
1772
+ seq += copied ;
1773
+ if (TCP_SKB_CB (skb )-> tcp_flags & TCPHDR_FIN )
1774
1774
++ seq ;
1775
- break ;
1776
- }
1777
- consume_skb (skb );
1778
- break ;
1779
1775
}
1776
+ consume_skb (skb );
1780
1777
WRITE_ONCE (tp -> copied_seq , seq );
1781
1778
1782
1779
tcp_rcv_space_adjust (sk );
1783
1780
1784
1781
/* Clean up data we have read: This will do ACK frames. */
1785
1782
if (copied > 0 )
1786
- tcp_cleanup_rbuf (sk , copied );
1783
+ __tcp_cleanup_rbuf (sk , copied );
1787
1784
1788
1785
return copied ;
1789
1786
}
0 commit comments