diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ce572f9dff02..0cd71b84e483 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -522,8 +522,12 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
522 | unsigned int offset, size_t len) | 522 | unsigned int offset, size_t len) |
523 | { | 523 | { |
524 | struct tcp_splice_state *tss = rd_desc->arg.data; | 524 | struct tcp_splice_state *tss = rd_desc->arg.data; |
525 | int ret; | ||
525 | 526 | ||
526 | return skb_splice_bits(skb, offset, tss->pipe, tss->len, tss->flags); | 527 | ret = skb_splice_bits(skb, offset, tss->pipe, rd_desc->count, tss->flags); |
528 | if (ret > 0) | ||
529 | rd_desc->count -= ret; | ||
530 | return ret; | ||
527 | } | 531 | } |
528 | 532 | ||
529 | static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) | 533 | static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) |
@@ -531,6 +535,7 @@ static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) | |||
531 | /* Store TCP splice context information in read_descriptor_t. */ | 535 | /* Store TCP splice context information in read_descriptor_t. */ |
532 | read_descriptor_t rd_desc = { | 536 | read_descriptor_t rd_desc = { |
533 | .arg.data = tss, | 537 | .arg.data = tss, |
538 | .count = tss->len, | ||
534 | }; | 539 | }; |
535 | 540 | ||
536 | return tcp_read_sock(sk, &rd_desc, tcp_splice_data_recv); | 541 | return tcp_read_sock(sk, &rd_desc, tcp_splice_data_recv); |
@@ -611,11 +616,13 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, | |||
611 | tss.len -= ret; | 616 | tss.len -= ret; |
612 | spliced += ret; | 617 | spliced += ret; |
613 | 618 | ||
619 | if (!timeo) | ||
620 | break; | ||
614 | release_sock(sk); | 621 | release_sock(sk); |
615 | lock_sock(sk); | 622 | lock_sock(sk); |
616 | 623 | ||
617 | if (sk->sk_err || sk->sk_state == TCP_CLOSE || | 624 | if (sk->sk_err || sk->sk_state == TCP_CLOSE || |
618 | (sk->sk_shutdown & RCV_SHUTDOWN) || !timeo || | 625 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
619 | signal_pending(current)) | 626 | signal_pending(current)) |
620 | break; | 627 | break; |
621 | } | 628 | } |
@@ -2382,7 +2389,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2382 | unsigned int seq; | 2389 | unsigned int seq; |
2383 | __be32 delta; | 2390 | __be32 delta; |
2384 | unsigned int oldlen; | 2391 | unsigned int oldlen; |
2385 | unsigned int len; | 2392 | unsigned int mss; |
2386 | 2393 | ||
2387 | if (!pskb_may_pull(skb, sizeof(*th))) | 2394 | if (!pskb_may_pull(skb, sizeof(*th))) |
2388 | goto out; | 2395 | goto out; |
@@ -2398,10 +2405,13 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2398 | oldlen = (u16)~skb->len; | 2405 | oldlen = (u16)~skb->len; |
2399 | __skb_pull(skb, thlen); | 2406 | __skb_pull(skb, thlen); |
2400 | 2407 | ||
2408 | mss = skb_shinfo(skb)->gso_size; | ||
2409 | if (unlikely(skb->len <= mss)) | ||
2410 | goto out; | ||
2411 | |||
2401 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | 2412 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { |
2402 | /* Packet is from an untrusted source, reset gso_segs. */ | 2413 | /* Packet is from an untrusted source, reset gso_segs. */ |
2403 | int type = skb_shinfo(skb)->gso_type; | 2414 | int type = skb_shinfo(skb)->gso_type; |
2404 | int mss; | ||
2405 | 2415 | ||
2406 | if (unlikely(type & | 2416 | if (unlikely(type & |
2407 | ~(SKB_GSO_TCPV4 | | 2417 | ~(SKB_GSO_TCPV4 | |
@@ -2412,7 +2422,6 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2412 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | 2422 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) |
2413 | goto out; | 2423 | goto out; |
2414 | 2424 | ||
2415 | mss = skb_shinfo(skb)->gso_size; | ||
2416 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); | 2425 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); |
2417 | 2426 | ||
2418 | segs = NULL; | 2427 | segs = NULL; |
@@ -2423,8 +2432,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2423 | if (IS_ERR(segs)) | 2432 | if (IS_ERR(segs)) |
2424 | goto out; | 2433 | goto out; |
2425 | 2434 | ||
2426 | len = skb_shinfo(skb)->gso_size; | 2435 | delta = htonl(oldlen + (thlen + mss)); |
2427 | delta = htonl(oldlen + (thlen + len)); | ||
2428 | 2436 | ||
2429 | skb = segs; | 2437 | skb = segs; |
2430 | th = tcp_hdr(skb); | 2438 | th = tcp_hdr(skb); |
@@ -2440,7 +2448,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2440 | csum_fold(csum_partial(skb_transport_header(skb), | 2448 | csum_fold(csum_partial(skb_transport_header(skb), |
2441 | thlen, skb->csum)); | 2449 | thlen, skb->csum)); |
2442 | 2450 | ||
2443 | seq += len; | 2451 | seq += mss; |
2444 | skb = skb->next; | 2452 | skb = skb->next; |
2445 | th = tcp_hdr(skb); | 2453 | th = tcp_hdr(skb); |
2446 | 2454 | ||