[NET] generalise wait_for_tcp_connect

This will be used by the poor cousins, look, for instance, at
x25_wait_for_connection_establishment :-)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@conectiva.com.br>
parent 44551947
...@@ -371,8 +371,6 @@ struct tcp_opt { ...@@ -371,8 +371,6 @@ struct tcp_opt {
struct open_request *accept_queue; struct open_request *accept_queue;
struct open_request *accept_queue_tail; struct open_request *accept_queue_tail;
int write_pending; /* A write to socket waits to start. */
unsigned int keepalive_time; /* time before keep alive takes place */ unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */ unsigned int keepalive_intvl; /* time interval between keep alive probes */
int linger2; int linger2;
......
...@@ -167,6 +167,7 @@ struct sock_common { ...@@ -167,6 +167,7 @@ struct sock_common {
* @sk_socket - Identd and reporting IO signals * @sk_socket - Identd and reporting IO signals
* @sk_user_data - RPC layer private data * @sk_user_data - RPC layer private data
* @sk_owner - module that owns this socket * @sk_owner - module that owns this socket
* @sk_write_pending - a write to stream socket waits to start
* @sk_state_change - callback to indicate change in the state of the sock * @sk_state_change - callback to indicate change in the state of the sock
* @sk_data_ready - callback to indicate there is data to be processed * @sk_data_ready - callback to indicate there is data to be processed
* @sk_write_space - callback to indicate there is bf sending space available * @sk_write_space - callback to indicate there is bf sending space available
...@@ -247,6 +248,7 @@ struct sock { ...@@ -247,6 +248,7 @@ struct sock {
struct socket *sk_socket; struct socket *sk_socket;
void *sk_user_data; void *sk_user_data;
struct module *sk_owner; struct module *sk_owner;
int sk_write_pending;
void *sk_security; void *sk_security;
void (*sk_state_change)(struct sock *sk); void (*sk_state_change)(struct sock *sk);
void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_data_ready)(struct sock *sk, int bytes);
...@@ -458,6 +460,8 @@ do { if (!(__sk)->sk_backlog.tail) { \ ...@@ -458,6 +460,8 @@ do { if (!(__sk)->sk_backlog.tail) { \
rc; \ rc; \
}) })
extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
extern int sk_wait_data(struct sock *sk, long *timeo); extern int sk_wait_data(struct sock *sk, long *timeo);
/* IP protocol blocks we attach to sockets. /* IP protocol blocks we attach to sockets.
......
...@@ -1176,6 +1176,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) ...@@ -1176,6 +1176,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_peercred.pid = 0; sk->sk_peercred.pid = 0;
sk->sk_peercred.uid = -1; sk->sk_peercred.uid = -1;
sk->sk_peercred.gid = -1; sk->sk_peercred.gid = -1;
sk->sk_write_pending = 0;
sk->sk_rcvlowat = 1; sk->sk_rcvlowat = 1;
sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/tcp.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <net/sock.h> #include <net/sock.h>
...@@ -39,3 +40,39 @@ void sk_stream_write_space(struct sock *sk) ...@@ -39,3 +40,39 @@ void sk_stream_write_space(struct sock *sk)
} }
EXPORT_SYMBOL(sk_stream_write_space); EXPORT_SYMBOL(sk_stream_write_space);
/**
* sk_stream_wait_connect - Wait for a socket to get into the connected state
* @sk - sock to wait on
* @timeo_p - for how long to wait
*
* 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);
while (1) {
if (sk->sk_err)
return sock_error(sk);
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);
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
sk->sk_write_pending++;
if (sk_wait_event(sk, timeo_p,
!((1 << sk->sk_state) &
~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))))
break;
finish_wait(sk->sk_sleep, &wait);
sk->sk_write_pending--;
}
return 0;
}
EXPORT_SYMBOL(sk_stream_wait_connect);
...@@ -636,46 +636,11 @@ static void tcp_listen_stop (struct sock *sk) ...@@ -636,46 +636,11 @@ static void tcp_listen_stop (struct sock *sk)
BUG_TRAP(!sk->sk_ack_backlog); BUG_TRAP(!sk->sk_ack_backlog);
} }
/*
* Wait for a socket to get into the connected state
*
* Note: Must be called with the socket locked.
*/
static int wait_for_tcp_connect(struct sock *sk, int flags, long *timeo_p)
{
struct tcp_opt *tp = tcp_sk(sk);
struct task_struct *tsk = current;
DEFINE_WAIT(wait);
while ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
if (sk->sk_err)
return sock_error(sk);
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);
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
tp->write_pending++;
release_sock(sk);
*timeo_p = schedule_timeout(*timeo_p);
lock_sock(sk);
finish_wait(sk->sk_sleep, &wait);
tp->write_pending--;
}
return 0;
}
/* /*
* Wait for more memory for a socket * Wait for more memory for a socket
*/ */
static int wait_for_tcp_memory(struct sock *sk, long *timeo) static int wait_for_tcp_memory(struct sock *sk, long *timeo)
{ {
struct tcp_opt *tp = tcp_sk(sk);
int err = 0; int err = 0;
long vm_wait = 0; long vm_wait = 0;
long current_timeo = *timeo; long current_timeo = *timeo;
...@@ -700,12 +665,12 @@ static int wait_for_tcp_memory(struct sock *sk, long *timeo) ...@@ -700,12 +665,12 @@ static int wait_for_tcp_memory(struct sock *sk, long *timeo)
break; break;
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
tp->write_pending++; sk->sk_write_pending++;
release_sock(sk); release_sock(sk);
if (!sk_stream_memory_free(sk) || vm_wait) if (!sk_stream_memory_free(sk) || vm_wait)
current_timeo = schedule_timeout(current_timeo); current_timeo = schedule_timeout(current_timeo);
lock_sock(sk); lock_sock(sk);
tp->write_pending--; sk->sk_write_pending--;
if (vm_wait) { if (vm_wait) {
vm_wait -= current_timeo; vm_wait -= current_timeo;
...@@ -812,7 +777,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse ...@@ -812,7 +777,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
/* Wait for a connection to finish. */ /* Wait for a connection to finish. */
if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
if ((err = wait_for_tcp_connect(sk, 0, &timeo)) != 0) if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
goto out_err; goto out_err;
clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
...@@ -965,7 +930,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -965,7 +930,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
/* Wait for a connection to finish. */ /* Wait for a connection to finish. */
if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
if ((err = wait_for_tcp_connect(sk, flags, &timeo)) != 0) if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
goto out_err; goto out_err;
/* This should be in poll */ /* This should be in poll */
......
...@@ -4474,7 +4474,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, ...@@ -4474,7 +4474,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
sk_wake_async(sk, 0, POLL_OUT); sk_wake_async(sk, 0, POLL_OUT);
} }
if (tp->write_pending || tp->defer_accept || tp->ack.pingpong) { if (sk->sk_write_pending || tp->defer_accept || tp->ack.pingpong) {
/* Save one ACK. Data will be ready after /* Save one ACK. Data will be ready after
* several ticks, if write_pending is set. * several ticks, if write_pending is set.
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment