diff options
author | Olof Johansson <olof@lixom.net> | 2013-01-30 10:04:23 -0800 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-01-30 10:04:56 -0800 |
commit | 3e93093ecd0c144e86a86cc1f165221b6cd3e7fb (patch) | |
tree | 0d6dffb90985bd90fd0ca43076a629f12e277096 /net/ipv4/tcp.c | |
parent | 43243322139194c2fea606095f82498e07536c27 (diff) | |
parent | da660b4a3b15caea9c198c4f26d1cf7023df92fc (diff) |
Merge tag 'vexpress/drivers-for-3.9' of git://git.linaro.org/people/pawelmoll/linux into next/drivers
From Pawel Moll:
Versatile Express related driver updates for 3.9:
* Move sp810 header to a more generic location,
mainly to share it with arm64
* tag 'vexpress/drivers-for-3.9' of git://git.linaro.org/people/pawelmoll/linux:
arm: Move sp810.h to include/linux/amba/
+ Linux 3.8-rc5
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1ca253635f7..2aa69c8ae60 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1428,12 +1428,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) } #endif -static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) +static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) { struct sk_buff *skb; u32 offset; - skb_queue_walk(&sk->sk_receive_queue, skb) { + while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { offset = seq - TCP_SKB_CB(skb)->seq; if (tcp_hdr(skb)->syn) offset--; @@ -1441,6 +1441,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) *off = offset; return skb; } + /* This looks weird, but this can happen if TCP collapsing + * splitted a fat GRO packet, while we released socket lock + * in skb_splice_bits() + */ + sk_eat_skb(sk, skb, false); } return NULL; } @@ -1482,7 +1487,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, break; } used = recv_actor(desc, skb, offset, len); - if (used < 0) { + if (used <= 0) { if (!copied) copied = used; break; @@ -1520,8 +1525,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, tcp_rcv_space_adjust(sk); /* Clean up data we have read: This will do ACK frames. */ - if (copied > 0) + if (copied > 0) { + tcp_recv_skb(sk, seq, &offset); tcp_cleanup_rbuf(sk, copied); + } return copied; } EXPORT_SYMBOL(tcp_read_sock); |