Blame view

net/core/stream.c 5.11 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
   *     SUCS NET3:
   *
   *     Generic stream handling routines. These are generic for most
   *     protocols. Even IP. Tonight 8-).
   *     This is used because TCP, LLC (others too) layer all have mostly
   *     identical sendmsg() and recvmsg() code.
   *     So we (will) share it here.
   *
   *     Authors:        Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   *                     (from old tcp.c code)
113aa838e   Alan Cox   net: Rationalise ...
12
   *                     Alan Cox <alan@lxorguk.ukuu.org.uk> (Borrowed comments 8-))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
18
19
20
21
22
23
   */
  
  #include <linux/module.h>
  #include <linux/net.h>
  #include <linux/signal.h>
  #include <linux/tcp.h>
  #include <linux/wait.h>
  #include <net/sock.h>
  
  /**
   * sk_stream_write_space - stream socket write_space callback.
4dc3b16ba   Pavel Pisa   [PATCH] DocBook: ...
24
   * @sk: socket
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
   *
   * FIXME: write proper description
   */
  void sk_stream_write_space(struct sock *sk)
  {
  	struct socket *sock = sk->sk_socket;
438154823   Eric Dumazet   net: sock_def_rea...
31
  	struct socket_wq *wq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  
  	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) {
  		clear_bit(SOCK_NOSPACE, &sock->flags);
438154823   Eric Dumazet   net: sock_def_rea...
35
36
37
38
  		rcu_read_lock();
  		wq = rcu_dereference(sk->sk_wq);
  		if (wq_has_sleeper(wq))
  			wake_up_interruptible_poll(&wq->wait, POLLOUT |
9dc20c5f7   John Dykstra   tcp: tcp_prequeue...
39
  						POLLWRNORM | POLLWRBAND);
438154823   Eric Dumazet   net: sock_def_rea...
40
  		if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN))
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
41
  			sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT);
438154823   Eric Dumazet   net: sock_def_rea...
42
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  EXPORT_SYMBOL(sk_stream_write_space);
  
  /**
   * sk_stream_wait_connect - Wait for a socket to get into the connected state
4dc3b16ba   Pavel Pisa   [PATCH] DocBook: ...
49
50
   * @sk: sock to wait on
   * @timeo_p: for how long to wait
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
   *
   * Must be called with the socket locked.
   */
  int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
  {
  	struct task_struct *tsk = current;
  	DEFINE_WAIT(wait);
6151b31c9   Herbert Xu   [NET]: Fix race c...
58
  	int done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

6151b31c9   Herbert Xu   [NET]: Fix race c...
60
  	do {
c1cbe4b7a   Benjamin LaHaise   [NET]: Avoid atom...
61
62
63
  		int err = sock_error(sk);
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
  		if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
  			return -EPIPE;
  		if (!*timeo_p)
  			return -EAGAIN;
  		if (signal_pending(tsk))
  			return sock_intr_errno(*timeo_p);
aa3951451   Eric Dumazet   net: sk_sleep() h...
70
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  		sk->sk_write_pending++;
6151b31c9   Herbert Xu   [NET]: Fix race c...
72
  		done = sk_wait_event(sk, timeo_p,
c1cbe4b7a   Benjamin LaHaise   [NET]: Avoid atom...
73
  				     !sk->sk_err &&
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
74
  				     !((1 << sk->sk_state) &
6151b31c9   Herbert Xu   [NET]: Fix race c...
75
  				       ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
aa3951451   Eric Dumazet   net: sk_sleep() h...
76
  		finish_wait(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  		sk->sk_write_pending--;
6151b31c9   Herbert Xu   [NET]: Fix race c...
78
  	} while (!done);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
  EXPORT_SYMBOL(sk_stream_wait_connect);
  
  /**
   * sk_stream_closing - Return 1 if we still have things to send in our buffers.
4dc3b16ba   Pavel Pisa   [PATCH] DocBook: ...
85
   * @sk: socket to verify
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
95
96
97
98
   */
  static inline int sk_stream_closing(struct sock *sk)
  {
  	return (1 << sk->sk_state) &
  	       (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK);
  }
  
  void sk_stream_wait_close(struct sock *sk, long timeout)
  {
  	if (timeout) {
  		DEFINE_WAIT(wait);
  
  		do {
aa3951451   Eric Dumazet   net: sk_sleep() h...
99
  			prepare_to_wait(sk_sleep(sk), &wait,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
  					TASK_INTERRUPTIBLE);
  			if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk)))
  				break;
  		} while (!signal_pending(current) && timeout);
aa3951451   Eric Dumazet   net: sk_sleep() h...
104
  		finish_wait(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
  EXPORT_SYMBOL(sk_stream_wait_close);
  
  /**
   * sk_stream_wait_memory - Wait for more memory for a socket
4dc3b16ba   Pavel Pisa   [PATCH] DocBook: ...
111
112
   * @sk: socket to wait for memory
   * @timeo_p: for how long
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
119
120
121
122
123
124
125
   */
  int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
  {
  	int err = 0;
  	long vm_wait = 0;
  	long current_timeo = *timeo_p;
  	DEFINE_WAIT(wait);
  
  	if (sk_stream_memory_free(sk))
  		current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2;
  
  	while (1) {
  		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
aa3951451   Eric Dumazet   net: sk_sleep() h...
126
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
134
135
136
137
138
139
  
  		if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
  			goto do_error;
  		if (!*timeo_p)
  			goto do_nonblock;
  		if (signal_pending(current))
  			goto do_interrupted;
  		clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
  		if (sk_stream_memory_free(sk) && !vm_wait)
  			break;
  
  		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
  		sk->sk_write_pending++;
482964e56   Nagendra Tomar   net: Fix the cond...
140
141
142
143
  		sk_wait_event(sk, &current_timeo, sk->sk_err ||
  						  (sk->sk_shutdown & SEND_SHUTDOWN) ||
  						  (sk_stream_memory_free(sk) &&
  						  !vm_wait));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
151
152
153
154
155
156
  		sk->sk_write_pending--;
  
  		if (vm_wait) {
  			vm_wait -= current_timeo;
  			current_timeo = *timeo_p;
  			if (current_timeo != MAX_SCHEDULE_TIMEOUT &&
  			    (current_timeo -= vm_wait) < 0)
  				current_timeo = 0;
  			vm_wait = 0;
  		}
  		*timeo_p = current_timeo;
  	}
  out:
aa3951451   Eric Dumazet   net: sk_sleep() h...
157
  	finish_wait(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
163
164
165
166
167
168
169
  	return err;
  
  do_error:
  	err = -EPIPE;
  	goto out;
  do_nonblock:
  	err = -EAGAIN;
  	goto out;
  do_interrupted:
  	err = sock_intr_errno(*timeo_p);
  	goto out;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  EXPORT_SYMBOL(sk_stream_wait_memory);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
176
177
178
  int sk_stream_error(struct sock *sk, int flags, int err)
  {
  	if (err == -EPIPE)
  		err = sock_error(sk) ? : -EPIPE;
  	if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
  		send_sig(SIGPIPE, current, 0);
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  EXPORT_SYMBOL(sk_stream_error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
186
187
188
  void sk_stream_kill_queues(struct sock *sk)
  {
  	/* First the read buffer. */
  	__skb_queue_purge(&sk->sk_receive_queue);
  
  	/* Next, the error queue. */
  	__skb_queue_purge(&sk->sk_error_queue);
  
  	/* Next, the write queue. */
547b792ca   Ilpo Järvinen   net: convert BUG_...
189
  	WARN_ON(!skb_queue_empty(&sk->sk_write_queue));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
  
  	/* Account for returned memory. */
3ab224be6   Hideo Aoki   [NET] CORE: Intro...
192
  	sk_mem_reclaim(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

547b792ca   Ilpo Järvinen   net: convert BUG_...
194
195
  	WARN_ON(sk->sk_wmem_queued);
  	WARN_ON(sk->sk_forward_alloc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
200
201
  
  	/* It is _impossible_ for the backlog to contain anything
  	 * when we get here.  All user references to this socket
  	 * have gone away, only the net layer knows can touch it.
  	 */
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  EXPORT_SYMBOL(sk_stream_kill_queues);