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