off = 0; 
int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,		size_t size){	struct iovec *iov;	struct tcp_sock *tp = tcp_sk(sk);	struct sk_buff *skb;	int iovlen, flags;	int mss_now, size_goal;	int err, copied;	long timeo;	lock_sock(sk);	TCP_CHECK_TIMER(sk);	flags = msg->msg_flags;	timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);	/* Wait for a connection to finish. */	if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))		if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)			goto out_err;	/* This should be in poll */	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);	mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));	size_goal = tp->xmit_size_goal;	/* Ok commence sending. */	iovlen = msg->msg_iovlen;	iov = msg->msg_iov;	copied = 0;	err = -EPIPE;	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))		goto do_error;	while (--iovlen >= 0) {		int seglen = iov->iov_len;		unsigned char __user *from = iov->iov_base;		iov++;		while (seglen > 0) {			int copy;			skb = sk->sk_write_queue.prev;			if (!sk->sk_send_head ||			    (copy = size_goal - skb->len) <= 0) {new_segment:				/* Allocate new segment. If the interface is SG,				 * allocate skb fitting to single page.				 */				if (!sk_stream_memory_free(sk))					goto wait_for_sndbuf;				skb = sk_stream_alloc_pskb(sk, select_size(sk, tp),							   0, sk->sk_allocation);				if (!skb)					goto wait_for_memory;				/*				 * Check whether we can use HW checksum.				 */				if (sk->sk_route_caps &				    (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |				     NETIF_F_HW_CSUM))					skb->ip_summed = CHECKSUM_HW;				skb_entail(sk, tp, skb);				copy = size_goal;			}			/* Try to append data to the end of skb. */			if (copy > seglen)				copy = seglen;			/* Where to copy to? */			if (skb_tailroom(skb) > 0) {				/* We have some space in skb head. Superb! */				if (copy > skb_tailroom(skb))					copy = skb_tailroom(skb);				if ((err = skb_add_data(skb, from, copy)) != 0)					goto do_fault;			} else {				int merge = 0;				int i = skb_shinfo(skb)->nr_frags;				struct page *page = TCP_PAGE(sk);				int off = TCP_OFF(sk);				if (skb_can_coalesce(skb, i, page, off) &&				    off != PAGE_SIZE) {					/* We can extend the last page					 * fragment. */					merge = 1;				} else if (i == MAX_SKB_FRAGS ||					   (!i &&					   !(sk->sk_route_caps & NETIF_F_SG))) {					/* Need to add new fragment and cannot					 * do this because interface is non-SG,					 * or because all the page slots are					 * busy. */					tcp_mark_push(tp, skb);					goto new_segment;				} else if (page) {					if (off == PAGE_SIZE) {						put_page(page);						TCP_PAGE(sk) = page = NULL;					}				}				if (!page) {					/* Allocate new cache page. */					if (!(page = sk_stream_alloc_page(sk)))						goto wait_for_memory;					off = 0;				}				if (copy > PAGE_SIZE - off)					copy = PAGE_SIZE - off;				/* Time to copy data. We are close to				 * the end! */				err = skb_copy_to_page(sk, from, skb, page,						       off, copy);				if (err) {					/* If this page was new, give it to the					 * socket so it does not get leaked.					 */					if (!TCP_PAGE(sk)) {						TCP_PAGE(sk) = page;						TCP_OFF(sk) = 0;					}					goto do_error;				}				/* Update the skb. */				if (merge) {					skb_shinfo(skb)->frags[i - 1].size +=									copy;				} else {					skb_fill_page_desc(skb, i, page, off, copy);					if (TCP_PAGE(sk)) {						get_page(page);					} else if (off + copy < PAGE_SIZE) {						get_page(page);						TCP_PAGE(sk) = page;					}				}				TCP_OFF(sk) = off + copy;			}			if (!copied)				TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;			tp->write_seq += copy;			TCP_SKB_CB(skb)->end_seq += copy;			skb_shinfo(skb)->tso_segs = 0;			from += copy;			copied += copy;			if ((seglen -= copy) == 0 && iovlen == 0)				goto out;			if (skb->len < mss_now || (flags & MSG_OOB))				continue;			if (forced_push(tp)) {				tcp_mark_push(tp, skb);				__tcp_push_pending_frames(sk, tp, mss_now, TCP_NAGLE_PUSH);			} else if (skb == sk->sk_send_head)				tcp_push_one(sk, mss_now);			continue;wait_for_sndbuf:			set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);wait_for_memory:			if (copied)				tcp_push(sk, tp, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);			if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)				goto do_error;			mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));			size_goal = tp->xmit_size_goal;		}	}out:	if (copied)		tcp_push(sk, tp, flags, mss_now, tp->nonagle);	TCP_CHECK_TIMER(sk);	release_sock(sk);	return copied;do_fault:	if (!skb->len) {		if (sk->sk_send_head == skb)			sk->sk_send_head = NULL;		__skb_unlink(skb, &sk->sk_write_queue);		sk_stream_free_skb(sk, skb);	}do_error:	if (copied)		goto out;out_err:	err = sk_stream_error(sk, flags, err);	TCP_CHECK_TIMER(sk);	release_sock(sk);	return err;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/ef015786152adaff5a6a8bf0c8ea2f70cee8059d/tcp.c/clean/net/ipv4/tcp.c