patch-2.1.30 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/net/ipv4/route.c
Back to the patch index
Back to the overall index
- Lines: 219
- Date:
Thu Mar 20 18:17:14 1997
- Orig file:
v2.1.29/linux/net/ipv4/tcp.c
- Orig date:
Tue Mar 4 10:25:27 1997
diff -u --recursive --new-file v2.1.29/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: @(#)tcp.c 1.0.16 05/25/93
+ * Version: $Id: tcp.c,v 1.50 1997/03/16 03:25:59 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -196,6 +196,8 @@
* improvement.
* Stefan Magdalinski : adjusted tcp_readable() to fix FIONREAD
* Willy Konynenberg : Transparent proxying support.
+ * Keith Owens : Do proper meging with partial SKB's in
+ * tcp_do_sendmsg to avoid burstiness.
*
* To Fix:
* Fast path the code. Two things here - fix the window calculation
@@ -525,6 +527,7 @@
unsigned long flags;
SOCK_DEBUG(sk, "tcp_readable: %p - ",sk);
+
save_flags(flags);
cli();
if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)
@@ -772,11 +775,11 @@
copy = min(sk->mss - tcp_size, skb_tailroom(skb));
copy = min(copy, seglen);
-
+
tcp_size += copy;
-
+
fault = copy_from_user(skb->tail, from, copy);
-
+
if (fault)
{
return -1;
@@ -796,8 +799,7 @@
* and starts the transmit system.
*/
-int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov,
- int len, int flags)
+int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, int flags)
{
int err = 0;
int copied = 0;
@@ -808,16 +810,14 @@
*/
while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
{
-
if (copied)
return copied;
-
- if (sk->err)
+
+ if (sk->err)
return sock_error(sk);
-
+
if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
{
- printk("tcp_do_sendmsg1: EPIPE dude...\n");
if (sk->keepopen)
send_sig(SIGPIPE, current, 0);
return -EPIPE;
@@ -831,22 +831,21 @@
wait_for_tcp_connect(sk);
}
-
-
+
/*
* Ok commence sending
*/
-
+
while(--iovlen >= 0)
{
int seglen=iov->iov_len;
unsigned char * from=iov->iov_base;
- u32 actual_win;
iov++;
- while(seglen > 0)
+ while(seglen > 0)
{
+ unsigned int actual_win;
int copy;
int tmp;
struct sk_buff *skb;
@@ -870,7 +869,6 @@
{
if (copied)
return copied;
- printk("tcp_do_sendmsg2: SEND_SHUTDOWN, EPIPE...\n");
send_sig(SIGPIPE,current,0);
return -EPIPE;
}
@@ -885,11 +883,11 @@
int tcp_size;
/* Tail */
-
+
skb = sk->write_queue.prev;
- tcp_size = skb->tail -
+ tcp_size = skb->tail -
(unsigned char *)(skb->h.th + 1);
-
+
/*
* This window_seq test is somewhat dangerous
* If the remote does SWS avoidance we should
@@ -901,7 +899,7 @@
if (skb->end > skb->tail &&
sk->mss - tcp_size > 0 &&
- skb->end_seq < tp->snd_una + tp->snd_wnd)
+ tp->snd_nxt < skb->end_seq)
{
int tcopy;
@@ -912,12 +910,11 @@
{
return -EFAULT;
}
-
+
from += tcopy;
copied += tcopy;
- len -= tcopy;
seglen -= tcopy;
-
+
/*
* FIXME: if we're nagling we
* should send here.
@@ -944,7 +941,7 @@
actual_win = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
if (copy > actual_win &&
- (((long) actual_win) >= (sk->max_window >> 1))
+ (((int) actual_win) >= (sk->max_window >> 1))
&& actual_win)
{
copy = actual_win;
@@ -974,12 +971,12 @@
}
skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
-
+
/*
- * If we didn't get any memory, we need to sleep.
+ * If we didn't get any memory, we need to sleep.
*/
-
- if (skb == NULL)
+
+ if (skb == NULL)
{
sk->socket->flags |= SO_NOSPACE;
if (flags&MSG_DONTWAIT)
@@ -1037,13 +1034,16 @@
skb->csum = csum_partial_copy_from_user(from,
skb_put(skb, copy), copy, 0, &err);
-
+
from += copy;
copied += copy;
- len -= copy;
+
sk->write_seq += copy;
tcp_send_skb(sk, skb);
+
+ release_sock(sk);
+ lock_sock(sk);
}
}
@@ -1181,14 +1181,14 @@
break;
tcp_eat_skb(sk, skb);
}
-
+
SOCK_DEBUG(sk, "sk->rspace = %lu\n", sock_rspace(sk));
-
+
/*
- * We send a ACK if the sender is blocked
- * else let tcp_data deal with the acking policy.
+ * We send a ACK if the sender is blocked
+ * else let tcp_data deal with the acking policy.
*/
-
+
if (sk->delayed_acks)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
@@ -1464,7 +1464,7 @@
msg->msg_name);
}
if(addr_len)
- *addr_len= tp->af_specific->sockaddr_len;
+ *addr_len = tp->af_specific->sockaddr_len;
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov