aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ce572f9dff02..48ada1b2d2c4 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
529static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) 533static 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 }