if (tp->ucopy.task == user_recv) { 
if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) { 
int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,		size_t len, int nonblock, int flags, int *addr_len){	struct tcp_sock *tp = tcp_sk(sk);	int copied = 0;	u32 peek_seq;	u32 *seq;	unsigned long used;	int err;	int target;		/* Read at least this many bytes */	long timeo;	struct task_struct *user_recv = NULL;	lock_sock(sk);	TCP_CHECK_TIMER(sk);	err = -ENOTCONN;	if (sk->sk_state == TCP_LISTEN)		goto out;	timeo = sock_rcvtimeo(sk, nonblock);	/* Urgent data needs to be handled specially. */	if (flags & MSG_OOB)		goto recv_urg;	seq = &tp->copied_seq;	if (flags & MSG_PEEK) {		peek_seq = tp->copied_seq;		seq = &peek_seq;	}	target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);	do {		struct sk_buff *skb;		u32 offset;		/* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */		if (tp->urg_data && tp->urg_seq == *seq) {			if (copied)				break;			if (signal_pending(current)) {				copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;				break;			}		}		/* Next get a buffer. */		skb = skb_peek(&sk->sk_receive_queue);		do {			if (!skb)				break;			/* Now that we have two receive queues this			 * shouldn't happen.			 */			if (before(*seq, TCP_SKB_CB(skb)->seq)) {				printk(KERN_INFO "recvmsg bug: copied %X "				       "seq %X\n", *seq, TCP_SKB_CB(skb)->seq);				break;			}			offset = *seq - TCP_SKB_CB(skb)->seq;			if (skb->h.th->syn)				offset--;			if (offset < skb->len)				goto found_ok_skb;			if (skb->h.th->fin)				goto found_fin_ok;			BUG_TRAP(flags & MSG_PEEK);			skb = skb->next;		} while (skb != (struct sk_buff *)&sk->sk_receive_queue);		/* Well, if we have backlog, try to process it now yet. */		if (copied >= target && !sk->sk_backlog.tail)			break;		if (copied) {			if (sk->sk_err ||			    sk->sk_state == TCP_CLOSE ||			    (sk->sk_shutdown & RCV_SHUTDOWN) ||			    !timeo ||			    signal_pending(current) ||			    (flags & MSG_PEEK))				break;		} else {			if (sock_flag(sk, SOCK_DONE))				break;			if (sk->sk_err) {				copied = sock_error(sk);				break;			}			if (sk->sk_shutdown & RCV_SHUTDOWN)				break;			if (sk->sk_state == TCP_CLOSE) {				if (!sock_flag(sk, SOCK_DONE)) {					/* This occurs when user tries to read					 * from never connected socket.					 */					copied = -ENOTCONN;					break;				}				break;			}			if (!timeo) {				copied = -EAGAIN;				break;			}			if (signal_pending(current)) {				copied = sock_intr_errno(timeo);				break;			}		}		cleanup_rbuf(sk, copied);		if (tp->ucopy.task == user_recv) {			/* Install new reader */			if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {				user_recv = current;				tp->ucopy.task = user_recv;				tp->ucopy.iov = msg->msg_iov;			}			tp->ucopy.len = len;			BUG_TRAP(tp->copied_seq == tp->rcv_nxt ||				 (flags & (MSG_PEEK | MSG_TRUNC)));			/* Ugly... If prequeue is not empty, we have to			 * process it before releasing socket, otherwise			 * order will be broken at second iteration.			 * More elegant solution is required!!!			 *			 * Look: we have the following (pseudo)queues:			 *			 * 1. packets in flight			 * 2. backlog			 * 3. prequeue			 * 4. receive_queue			 *			 * Each queue can be processed only if the next ones			 * are empty. At this point we have empty receive_queue.			 * But prequeue _can_ be not empty after 2nd iteration,			 * when we jumped to start of loop because backlog			 * processing added something to receive_queue.			 * We cannot release_sock(), because backlog contains			 * packets arrived _after_ prequeued ones.			 *			 * Shortly, algorithm is clear --- to process all			 * the queues in order. We could make it more directly,			 * requeueing packets from backlog to prequeue, if			 * is not empty. It is more elegant, but eats cycles,			 * unfortunately.			 */			if (skb_queue_len(&tp->ucopy.prequeue))				goto do_prequeue;			/* __ Set realtime policy in scheduler __ */		}		if (copied >= target) {			/* Do not sleep, just process backlog. */			release_sock(sk);			lock_sock(sk);		} else			sk_wait_data(sk, &timeo);		if (user_recv) {			int chunk;			/* __ Restore normal policy in scheduler __ */			if ((chunk = len - tp->ucopy.len) != 0) {				NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, chunk);				len -= chunk;				copied += chunk;			}			if (tp->rcv_nxt == tp->copied_seq &&			    skb_queue_len(&tp->ucopy.prequeue)) {do_prequeue:				tcp_prequeue_process(sk);				if ((chunk = len - tp->ucopy.len) != 0) {					NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);					len -= chunk;					copied += chunk;				}			}		}		if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {			if (net_ratelimit())				printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n",				       current->comm, current->pid);			peek_seq = tp->copied_seq;		}		continue;	found_ok_skb:		/* Ok so how much can we use? */		used = skb->len - offset;		if (len < used)			used = len;		/* Do we have urgent data here? */		if (tp->urg_data) {			u32 urg_offset = tp->urg_seq - *seq;			if (urg_offset < used) {				if (!urg_offset) {					if (!sock_flag(sk, SOCK_URGINLINE)) {						++*seq;						offset++;						used--;						if (!used)							goto skip_copy;					}				} else					used = urg_offset;			}		}		if (!(flags & MSG_TRUNC)) {			err = skb_copy_datagram_iovec(skb, offset,						      msg->msg_iov, used);			if (err) {				/* Exception. Bailout! */				if (!copied)					copied = -EFAULT;				break;			}		}		*seq += used;		copied += used;		len -= used;		tcp_rcv_space_adjust(sk);skip_copy:		if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {			tp->urg_data = 0;			tcp_fast_path_check(sk, tp);		}		if (used + offset < skb->len)			continue;		if (skb->h.th->fin)			goto found_fin_ok;		if (!(flags & MSG_PEEK))			sk_eat_skb(sk, skb);		continue;	found_fin_ok:		/* Process the FIN. */		++*seq;		if (!(flags & MSG_PEEK))			sk_eat_skb(sk, skb);		break;	} while (len > 0);	if (user_recv) {		if (skb_queue_len(&tp->ucopy.prequeue)) {			int chunk;			tp->ucopy.len = copied > 0 ? len : 0;			tcp_prequeue_process(sk);			if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {				NET_ADD_STATS_USER(LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);				len -= chunk;				copied += chunk;			}		}		tp->ucopy.task = NULL;		tp->ucopy.len = 0;	}	/* According to UNIX98, msg_name/msg_namelen are ignored	 * on connected socket. I was just happy when found this 8) --ANK	 */	/* Clean up data we have read: This will do ACK frames. */	cleanup_rbuf(sk, copied);	TCP_CHECK_TIMER(sk);	release_sock(sk);	return copied;out:	TCP_CHECK_TIMER(sk);	release_sock(sk);	return err;recv_urg:	err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len);	goto out;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/7df551254add79a445d2e47e8f849cef8fee6e38/tcp.c/clean/net/ipv4/tcp.c