Commit 2150b1f5 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller

o X25: x25_wait_for_{data,connection_establishemnt} and the death of the last cli/sti pair in X.25

parent 09d25c03
...@@ -602,6 +602,35 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -602,6 +602,35 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return 0; return 0;
} }
static int x25_wait_for_connection_establishment(struct sock *sk)
{
DECLARE_WAITQUEUE(wait, current);
int rc;
add_wait_queue_exclusive(sk->sleep, &wait);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
rc = -ERESTARTSYS;
if (signal_pending(current))
break;
rc = sock_error(sk);
if (rc) {
sk->socket->state = SS_UNCONNECTED;
break;
}
rc = 0;
if (sk->state != TCP_ESTABLISHED) {
release_sock(sk);
schedule();
lock_sock(sk);
} else
break;
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
return rc;
}
static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -610,6 +639,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len ...@@ -610,6 +639,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
struct x25_route *rt; struct x25_route *rt;
int rc = 0; int rc = 0;
lock_sock(sk);
if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
goto out; /* Connect completed during a ERESTARTSYS event */ goto out; /* Connect completed during a ERESTARTSYS event */
...@@ -673,35 +703,48 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len ...@@ -673,35 +703,48 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
goto out_put_neigh; goto out_put_neigh;
cli(); /* To avoid races on the sleep */ rc = x25_wait_for_connection_establishment(sk);
if (rc)
/* goto out_put_neigh;
* A Clear Request or timeout or failed routing will go to closed.
*/
rc = -ERESTARTSYS;
while (sk->state == TCP_SYN_SENT) {
/* FIXME: going to sleep with interrupts disabled */
interruptible_sleep_on(sk->sleep);
if (signal_pending(current))
goto out_unlock;
}
if (sk->state != TCP_ESTABLISHED) {
sock->state = SS_UNCONNECTED;
rc = sock_error(sk); /* Always set at this point */
goto out_unlock;
}
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
rc = 0; rc = 0;
out_unlock:
sti();
out_put_neigh: out_put_neigh:
if (rc) if (rc)
x25_neigh_put(x25->neighbour); x25_neigh_put(x25->neighbour);
out_put_route: out_put_route:
x25_route_put(rt); x25_route_put(rt);
out: out:
release_sock(sk);
return rc;
}
static int x25_wait_for_data(struct sock *sk, int timeout)
{
DECLARE_WAITQUEUE(wait, current);
int rc = 0;
add_wait_queue_exclusive(sk->sleep, &wait);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
if (sk->shutdown & RCV_SHUTDOWN)
break;
rc = -ERESTARTSYS;
if (signal_pending(current))
break;
rc = -EAGAIN;
if (!timeout)
break;
rc = 0;
if (skb_queue_empty(&sk->receive_queue)) {
release_sock(sk);
timeout = schedule_timeout(timeout);
lock_sock(sk);
} else
break;
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
return rc; return rc;
} }
...@@ -719,29 +762,17 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -719,29 +762,17 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
if (sk->type != SOCK_SEQPACKET) if (sk->type != SOCK_SEQPACKET)
goto out; goto out;
/* rc = x25_wait_for_data(sk, sk->rcvtimeo);
* The write queue this time is holding sockets ready to use if (rc)
* hooked into the CALL INDICATION we saved goto out;
*/ skb = skb_dequeue(&sk->receive_queue);
do { rc = -EINVAL;
cli(); if (!skb->sk)
if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { goto out;
rc = -EWOULDBLOCK;
if (flags & O_NONBLOCK)
goto out_unlock;
/* FIXME: going to sleep with interrupts disabled */
interruptible_sleep_on(sk->sleep);
rc = -ERESTARTSYS;
if (signal_pending(current))
goto out_unlock;
}
} while (!skb);
newsk = skb->sk; newsk = skb->sk;
newsk->pair = NULL; newsk->pair = NULL;
newsk->socket = newsock; newsk->socket = newsock;
newsk->sleep = &newsock->wait; newsk->sleep = &newsock->wait;
sti();
/* Now attach up the new socket */ /* Now attach up the new socket */
skb->sk = NULL; skb->sk = NULL;
...@@ -752,9 +783,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -752,9 +783,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
rc = 0; rc = 0;
out: out:
return rc; return rc;
out_unlock:
sti();
goto out;
} }
static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
......
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