aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-12 07:08:57 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-12 07:08:57 -0500
commit871cafcc962fa1655c44b4f0e54d4c5cc14e273c (patch)
treefdb7bc65d2606c85b7be6c33ba0dfd5b4e472245 /net/ipv4/tcp.c
parentcf2592f59c0e8ed4308adbdb2e0a88655379d579 (diff)
parentb578f3fcca1e78624dfb5f358776e63711d7fda2 (diff)
Merge branch 'linus' into core/softlockup
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c25
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
529static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) 534static 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