summaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index c8341d1f995e..b2ae25ae3038 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1438,6 +1438,28 @@ static void wakeupdispatch(struct tipc_port *tport)
1438 sk->sk_write_space(sk); 1438 sk->sk_write_space(sk);
1439} 1439}
1440 1440
1441static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
1442{
1443 struct sock *sk = sock->sk;
1444 DEFINE_WAIT(wait);
1445 int done;
1446
1447 do {
1448 int err = sock_error(sk);
1449 if (err)
1450 return err;
1451 if (!*timeo_p)
1452 return -ETIMEDOUT;
1453 if (signal_pending(current))
1454 return sock_intr_errno(*timeo_p);
1455
1456 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1457 done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
1458 finish_wait(sk_sleep(sk), &wait);
1459 } while (!done);
1460 return 0;
1461}
1462
1441/** 1463/**
1442 * connect - establish a connection to another TIPC port 1464 * connect - establish a connection to another TIPC port
1443 * @sock: socket structure 1465 * @sock: socket structure
@@ -1453,7 +1475,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1453 struct sock *sk = sock->sk; 1475 struct sock *sk = sock->sk;
1454 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; 1476 struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
1455 struct msghdr m = {NULL,}; 1477 struct msghdr m = {NULL,};
1456 unsigned int timeout; 1478 long timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout;
1479 socket_state previous;
1457 int res; 1480 int res;
1458 1481
1459 lock_sock(sk); 1482 lock_sock(sk);
@@ -1475,8 +1498,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1475 goto exit; 1498 goto exit;
1476 } 1499 }
1477 1500
1478 timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; 1501 previous = sock->state;
1479
1480 switch (sock->state) { 1502 switch (sock->state) {
1481 case SS_UNCONNECTED: 1503 case SS_UNCONNECTED:
1482 /* Send a 'SYN-' to destination */ 1504 /* Send a 'SYN-' to destination */
@@ -1498,41 +1520,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
1498 * case is EINPROGRESS, rather than EALREADY. 1520 * case is EINPROGRESS, rather than EALREADY.
1499 */ 1521 */
1500 res = -EINPROGRESS; 1522 res = -EINPROGRESS;
1501 break;
1502 case SS_CONNECTING: 1523 case SS_CONNECTING:
1503 res = -EALREADY; 1524 if (previous == SS_CONNECTING)
1525 res = -EALREADY;
1526 if (!timeout)
1527 goto exit;
1528 timeout = msecs_to_jiffies(timeout);
1529 /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
1530 res = tipc_wait_for_connect(sock, &timeout);
1504 break; 1531 break;
1505 case SS_CONNECTED: 1532 case SS_CONNECTED:
1506 res = -EISCONN; 1533 res = -EISCONN;
1507 break; 1534 break;
1508 default: 1535 default:
1509 res = -EINVAL; 1536 res = -EINVAL;
1510 goto exit; 1537 break;
1511 }
1512
1513 if (sock->state == SS_CONNECTING) {
1514 if (!timeout)
1515 goto exit;
1516
1517 /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
1518 release_sock(sk);
1519 res = wait_event_interruptible_timeout(*sk_sleep(sk),
1520 sock->state != SS_CONNECTING,
1521 timeout ? (long)msecs_to_jiffies(timeout)
1522 : MAX_SCHEDULE_TIMEOUT);
1523 if (res <= 0) {
1524 if (res == 0)
1525 res = -ETIMEDOUT;
1526 return res;
1527 }
1528 lock_sock(sk);
1529 } 1538 }
1530
1531 if (unlikely(sock->state == SS_DISCONNECTING))
1532 res = sock_error(sk);
1533 else
1534 res = 0;
1535
1536exit: 1539exit:
1537 release_sock(sk); 1540 release_sock(sk);
1538 return res; 1541 return res;