diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 63 |
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 | ||
1441 | static 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 | |||
1536 | exit: | 1539 | exit: |
1537 | release_sock(sk); | 1540 | release_sock(sk); |
1538 | return res; | 1541 | return res; |