From d1f38c0016bf9e1c24aa9c41efca857b6a302b4e Mon Sep 17 00:00:00 2001
From: Ying Xue <ying.xue@windriver.com>
Date: Fri, 31 Aug 2012 17:26:13 +0800
Subject: [PATCH] tipc: correctly handle -ERESTARTSYS return value of connect()
Signed-off-by: Ying Xue <ying.xue@windriver.com>
---
net/tipc/tipc_socket.c | 109 +++++++++++++++++++++++++-----------------------
1 files changed, 57 insertions(+), 52 deletions(-)
@@ -1456,21 +1456,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
goto exit;
}
- /* Issue Posix-compliant error code if socket is in the wrong state */
-
- if (sock->state == SS_LISTENING) {
- res = -EOPNOTSUPP;
- goto exit;
- }
- if (sock->state == SS_CONNECTING) {
- res = -EALREADY;
- goto exit;
- }
- if (sock->state != SS_UNCONNECTED) {
- res = -EISCONN;
- goto exit;
- }
-
/*
* Reject connection attempt using multicast address
*
@@ -1483,54 +1468,74 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
goto exit;
}
- /* Reject any messages already in receive queue (very unlikely) */
-
- reject_rx_queue(sk);
+ switch (sock->state) {
+ case SS_UNCONNECTED:
+ /* Reject any messages already in receive queue
+ * (very unlikely) */
+ reject_rx_queue(sk);
- /* Send a 'SYN-' to destination */
+ /* Send a 'SYN-' to destination */
+ m.msg_name = dest;
+ m.msg_namelen = destlen;
+ res = send_msg(NULL, sock, &m, 0);
+ if (res < 0) {
+ goto exit;
+ }
- m.msg_name = dest;
- m.msg_namelen = destlen;
- res = send_msg(NULL, sock, &m, 0);
- if (res < 0) {
- goto exit;
+ /*
+ * Just entered SS_CONNECTING state; the only
+ * difference is that return value in non-blocking
+ * case is EINPROGRESS, rather than EALREADY.
+ */
+ res = -EINPROGRESS;
+ break;
+ case SS_CONNECTING:
+ res = -EALREADY;
+ break;
+ case SS_CONNECTED:
+ res = -EISCONN;
+ break;
+ default:
+ res = -EINVAL;
+ break;
}
- /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
-
- timeout = tipc_sk(sk)->conn_timeout;
- release_sock(sk);
- res = wait_event_interruptible_timeout(*sk->sk_sleep,
- (!skb_queue_empty(&sk->sk_receive_queue) ||
- (sock->state != SS_CONNECTING)),
- timeout ? (long)msecs_to_jiffies(timeout)
- : MAX_SCHEDULE_TIMEOUT);
- lock_sock(sk);
+ if (sock->state == SS_CONNECTING) {
+ /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
+ timeout = tipc_sk(sk)->conn_timeout;
+ release_sock(sk);
+ res = wait_event_interruptible_timeout(*sk->sk_sleep,
+ (!skb_queue_empty(&sk->sk_receive_queue) ||
+ (sock->state != SS_CONNECTING)),
+ timeout ? (long)msecs_to_jiffies(timeout)
+ : MAX_SCHEDULE_TIMEOUT);
+ lock_sock(sk);
- if (res > 0) {
- buf = skb_peek(&sk->sk_receive_queue);
- if (buf != NULL) {
- msg = buf_msg(buf);
- res = auto_connect(sock, msg);
- if (!res) {
- if (!msg_data_sz(msg))
- advance_rx_queue(sk);
+ if (res > 0) {
+ buf = skb_peek(&sk->sk_receive_queue);
+ if (buf != NULL) {
+ msg = buf_msg(buf);
+ res = auto_connect(sock, msg);
+ if (!res) {
+ if (!msg_data_sz(msg))
+ advance_rx_queue(sk);
+ }
+ } else {
+ if (sock->state == SS_CONNECTED) {
+ res = -EISCONN;
+ } else {
+ res = -ECONNREFUSED;
+ }
}
} else {
- if (sock->state == SS_CONNECTED) {
- res = -EISCONN;
+ if (res == 0) {
+ sock->state = SS_DISCONNECTING;
+ res = -ETIMEDOUT;
} else {
- res = -ECONNREFUSED;
+ ; /* leave "res" unchanged */
}
}
- } else {
- if (res == 0)
- res = -ETIMEDOUT;
- else
- ; /* leave "res" unchanged */
- sock->state = SS_DISCONNECTING;
}
-
exit:
release_sock(sk);
return res;
--
1.7.1