diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 338 |
1 files changed, 197 insertions, 141 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e741416d1d24..0ed0eaa62f29 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -55,9 +55,6 @@ struct tipc_sock { | |||
55 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) | 55 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) |
56 | #define tipc_sk_port(sk) (tipc_sk(sk)->p) | 56 | #define tipc_sk_port(sk) (tipc_sk(sk)->p) |
57 | 57 | ||
58 | #define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \ | ||
59 | (sock->state == SS_DISCONNECTING)) | ||
60 | |||
61 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); | 58 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); |
62 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | 59 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); |
63 | static void wakeupdispatch(struct tipc_port *tport); | 60 | static void wakeupdispatch(struct tipc_port *tport); |
@@ -73,8 +70,6 @@ static const struct proto_ops msg_ops; | |||
73 | static struct proto tipc_proto; | 70 | static struct proto tipc_proto; |
74 | static struct proto tipc_proto_kern; | 71 | static struct proto tipc_proto_kern; |
75 | 72 | ||
76 | static int sockets_enabled; | ||
77 | |||
78 | /* | 73 | /* |
79 | * Revised TIPC socket locking policy: | 74 | * Revised TIPC socket locking policy: |
80 | * | 75 | * |
@@ -239,7 +234,6 @@ static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, | |||
239 | int tipc_sock_create_local(int type, struct socket **res) | 234 | int tipc_sock_create_local(int type, struct socket **res) |
240 | { | 235 | { |
241 | int rc; | 236 | int rc; |
242 | struct sock *sk; | ||
243 | 237 | ||
244 | rc = sock_create_lite(AF_TIPC, type, 0, res); | 238 | rc = sock_create_lite(AF_TIPC, type, 0, res); |
245 | if (rc < 0) { | 239 | if (rc < 0) { |
@@ -248,8 +242,6 @@ int tipc_sock_create_local(int type, struct socket **res) | |||
248 | } | 242 | } |
249 | tipc_sk_create(&init_net, *res, 0, 1); | 243 | tipc_sk_create(&init_net, *res, 0, 1); |
250 | 244 | ||
251 | sk = (*res)->sk; | ||
252 | |||
253 | return 0; | 245 | return 0; |
254 | } | 246 | } |
255 | 247 | ||
@@ -570,6 +562,31 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
570 | return 0; | 562 | return 0; |
571 | } | 563 | } |
572 | 564 | ||
565 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | ||
566 | { | ||
567 | struct sock *sk = sock->sk; | ||
568 | struct tipc_port *tport = tipc_sk_port(sk); | ||
569 | DEFINE_WAIT(wait); | ||
570 | int done; | ||
571 | |||
572 | do { | ||
573 | int err = sock_error(sk); | ||
574 | if (err) | ||
575 | return err; | ||
576 | if (sock->state == SS_DISCONNECTING) | ||
577 | return -EPIPE; | ||
578 | if (!*timeo_p) | ||
579 | return -EAGAIN; | ||
580 | if (signal_pending(current)) | ||
581 | return sock_intr_errno(*timeo_p); | ||
582 | |||
583 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
584 | done = sk_wait_event(sk, timeo_p, !tport->congested); | ||
585 | finish_wait(sk_sleep(sk), &wait); | ||
586 | } while (!done); | ||
587 | return 0; | ||
588 | } | ||
589 | |||
573 | /** | 590 | /** |
574 | * send_msg - send message in connectionless manner | 591 | * send_msg - send message in connectionless manner |
575 | * @iocb: if NULL, indicates that socket lock is already held | 592 | * @iocb: if NULL, indicates that socket lock is already held |
@@ -589,9 +606,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
589 | { | 606 | { |
590 | struct sock *sk = sock->sk; | 607 | struct sock *sk = sock->sk; |
591 | struct tipc_port *tport = tipc_sk_port(sk); | 608 | struct tipc_port *tport = tipc_sk_port(sk); |
592 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 609 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
593 | int needs_conn; | 610 | int needs_conn; |
594 | long timeout_val; | 611 | long timeo; |
595 | int res = -EINVAL; | 612 | int res = -EINVAL; |
596 | 613 | ||
597 | if (unlikely(!dest)) | 614 | if (unlikely(!dest)) |
@@ -628,8 +645,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
628 | reject_rx_queue(sk); | 645 | reject_rx_queue(sk); |
629 | } | 646 | } |
630 | 647 | ||
631 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 648 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
632 | |||
633 | do { | 649 | do { |
634 | if (dest->addrtype == TIPC_ADDR_NAME) { | 650 | if (dest->addrtype == TIPC_ADDR_NAME) { |
635 | res = dest_name_check(dest, m); | 651 | res = dest_name_check(dest, m); |
@@ -663,14 +679,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
663 | sock->state = SS_CONNECTING; | 679 | sock->state = SS_CONNECTING; |
664 | break; | 680 | break; |
665 | } | 681 | } |
666 | if (timeout_val <= 0L) { | 682 | res = tipc_wait_for_sndmsg(sock, &timeo); |
667 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 683 | if (res) |
668 | break; | 684 | break; |
669 | } | ||
670 | release_sock(sk); | ||
671 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
672 | !tport->congested, timeout_val); | ||
673 | lock_sock(sk); | ||
674 | } while (1); | 685 | } while (1); |
675 | 686 | ||
676 | exit: | 687 | exit: |
@@ -679,6 +690,34 @@ exit: | |||
679 | return res; | 690 | return res; |
680 | } | 691 | } |
681 | 692 | ||
693 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | ||
694 | { | ||
695 | struct sock *sk = sock->sk; | ||
696 | struct tipc_port *tport = tipc_sk_port(sk); | ||
697 | DEFINE_WAIT(wait); | ||
698 | int done; | ||
699 | |||
700 | do { | ||
701 | int err = sock_error(sk); | ||
702 | if (err) | ||
703 | return err; | ||
704 | if (sock->state == SS_DISCONNECTING) | ||
705 | return -EPIPE; | ||
706 | else if (sock->state != SS_CONNECTED) | ||
707 | return -ENOTCONN; | ||
708 | if (!*timeo_p) | ||
709 | return -EAGAIN; | ||
710 | if (signal_pending(current)) | ||
711 | return sock_intr_errno(*timeo_p); | ||
712 | |||
713 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
714 | done = sk_wait_event(sk, timeo_p, | ||
715 | (!tport->congested || !tport->connected)); | ||
716 | finish_wait(sk_sleep(sk), &wait); | ||
717 | } while (!done); | ||
718 | return 0; | ||
719 | } | ||
720 | |||
682 | /** | 721 | /** |
683 | * send_packet - send a connection-oriented message | 722 | * send_packet - send a connection-oriented message |
684 | * @iocb: if NULL, indicates that socket lock is already held | 723 | * @iocb: if NULL, indicates that socket lock is already held |
@@ -695,9 +734,9 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
695 | { | 734 | { |
696 | struct sock *sk = sock->sk; | 735 | struct sock *sk = sock->sk; |
697 | struct tipc_port *tport = tipc_sk_port(sk); | 736 | struct tipc_port *tport = tipc_sk_port(sk); |
698 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 737 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
699 | long timeout_val; | 738 | int res = -EINVAL; |
700 | int res; | 739 | long timeo; |
701 | 740 | ||
702 | /* Handle implied connection establishment */ | 741 | /* Handle implied connection establishment */ |
703 | if (unlikely(dest)) | 742 | if (unlikely(dest)) |
@@ -709,30 +748,24 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
709 | if (iocb) | 748 | if (iocb) |
710 | lock_sock(sk); | 749 | lock_sock(sk); |
711 | 750 | ||
712 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 751 | if (unlikely(sock->state != SS_CONNECTED)) { |
752 | if (sock->state == SS_DISCONNECTING) | ||
753 | res = -EPIPE; | ||
754 | else | ||
755 | res = -ENOTCONN; | ||
756 | goto exit; | ||
757 | } | ||
713 | 758 | ||
759 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
714 | do { | 760 | do { |
715 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
716 | if (sock->state == SS_DISCONNECTING) | ||
717 | res = -EPIPE; | ||
718 | else | ||
719 | res = -ENOTCONN; | ||
720 | break; | ||
721 | } | ||
722 | |||
723 | res = tipc_send(tport->ref, m->msg_iov, total_len); | 761 | res = tipc_send(tport->ref, m->msg_iov, total_len); |
724 | if (likely(res != -ELINKCONG)) | 762 | if (likely(res != -ELINKCONG)) |
725 | break; | 763 | break; |
726 | if (timeout_val <= 0L) { | 764 | res = tipc_wait_for_sndpkt(sock, &timeo); |
727 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 765 | if (res) |
728 | break; | 766 | break; |
729 | } | ||
730 | release_sock(sk); | ||
731 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
732 | (!tport->congested || !tport->connected), timeout_val); | ||
733 | lock_sock(sk); | ||
734 | } while (1); | 767 | } while (1); |
735 | 768 | exit: | |
736 | if (iocb) | 769 | if (iocb) |
737 | release_sock(sk); | 770 | release_sock(sk); |
738 | return res; | 771 | return res; |
@@ -770,16 +803,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
770 | 803 | ||
771 | /* Handle special cases where there is no connection */ | 804 | /* Handle special cases where there is no connection */ |
772 | if (unlikely(sock->state != SS_CONNECTED)) { | 805 | if (unlikely(sock->state != SS_CONNECTED)) { |
773 | if (sock->state == SS_UNCONNECTED) { | 806 | if (sock->state == SS_UNCONNECTED) |
774 | res = send_packet(NULL, sock, m, total_len); | 807 | res = send_packet(NULL, sock, m, total_len); |
775 | goto exit; | 808 | else |
776 | } else if (sock->state == SS_DISCONNECTING) { | 809 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; |
777 | res = -EPIPE; | 810 | goto exit; |
778 | goto exit; | ||
779 | } else { | ||
780 | res = -ENOTCONN; | ||
781 | goto exit; | ||
782 | } | ||
783 | } | 811 | } |
784 | 812 | ||
785 | if (unlikely(m->msg_name)) { | 813 | if (unlikely(m->msg_name)) { |
@@ -876,7 +904,7 @@ static int auto_connect(struct socket *sock, struct tipc_msg *msg) | |||
876 | */ | 904 | */ |
877 | static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) | 905 | static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) |
878 | { | 906 | { |
879 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; | 907 | DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name); |
880 | 908 | ||
881 | if (addr) { | 909 | if (addr) { |
882 | addr->family = AF_TIPC; | 910 | addr->family = AF_TIPC; |
@@ -961,6 +989,37 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
961 | return 0; | 989 | return 0; |
962 | } | 990 | } |
963 | 991 | ||
992 | static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | ||
993 | { | ||
994 | struct sock *sk = sock->sk; | ||
995 | DEFINE_WAIT(wait); | ||
996 | int err; | ||
997 | |||
998 | for (;;) { | ||
999 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1000 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { | ||
1001 | if (sock->state == SS_DISCONNECTING) { | ||
1002 | err = -ENOTCONN; | ||
1003 | break; | ||
1004 | } | ||
1005 | release_sock(sk); | ||
1006 | timeo = schedule_timeout(timeo); | ||
1007 | lock_sock(sk); | ||
1008 | } | ||
1009 | err = 0; | ||
1010 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
1011 | break; | ||
1012 | err = sock_intr_errno(timeo); | ||
1013 | if (signal_pending(current)) | ||
1014 | break; | ||
1015 | err = -EAGAIN; | ||
1016 | if (!timeo) | ||
1017 | break; | ||
1018 | } | ||
1019 | finish_wait(sk_sleep(sk), &wait); | ||
1020 | return err; | ||
1021 | } | ||
1022 | |||
964 | /** | 1023 | /** |
965 | * recv_msg - receive packet-oriented message | 1024 | * recv_msg - receive packet-oriented message |
966 | * @iocb: (unused) | 1025 | * @iocb: (unused) |
@@ -980,7 +1039,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
980 | struct tipc_port *tport = tipc_sk_port(sk); | 1039 | struct tipc_port *tport = tipc_sk_port(sk); |
981 | struct sk_buff *buf; | 1040 | struct sk_buff *buf; |
982 | struct tipc_msg *msg; | 1041 | struct tipc_msg *msg; |
983 | long timeout; | 1042 | long timeo; |
984 | unsigned int sz; | 1043 | unsigned int sz; |
985 | u32 err; | 1044 | u32 err; |
986 | int res; | 1045 | int res; |
@@ -996,25 +1055,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
996 | goto exit; | 1055 | goto exit; |
997 | } | 1056 | } |
998 | 1057 | ||
999 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1058 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
1000 | restart: | 1059 | restart: |
1001 | 1060 | ||
1002 | /* Look for a message in receive queue; wait if necessary */ | 1061 | /* Look for a message in receive queue; wait if necessary */ |
1003 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1062 | res = tipc_wait_for_rcvmsg(sock, timeo); |
1004 | if (sock->state == SS_DISCONNECTING) { | 1063 | if (res) |
1005 | res = -ENOTCONN; | 1064 | goto exit; |
1006 | goto exit; | ||
1007 | } | ||
1008 | if (timeout <= 0L) { | ||
1009 | res = timeout ? timeout : -EWOULDBLOCK; | ||
1010 | goto exit; | ||
1011 | } | ||
1012 | release_sock(sk); | ||
1013 | timeout = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
1014 | tipc_rx_ready(sock), | ||
1015 | timeout); | ||
1016 | lock_sock(sk); | ||
1017 | } | ||
1018 | 1065 | ||
1019 | /* Look at first message in receive queue */ | 1066 | /* Look at first message in receive queue */ |
1020 | buf = skb_peek(&sk->sk_receive_queue); | 1067 | buf = skb_peek(&sk->sk_receive_queue); |
@@ -1086,7 +1133,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
1086 | struct tipc_port *tport = tipc_sk_port(sk); | 1133 | struct tipc_port *tport = tipc_sk_port(sk); |
1087 | struct sk_buff *buf; | 1134 | struct sk_buff *buf; |
1088 | struct tipc_msg *msg; | 1135 | struct tipc_msg *msg; |
1089 | long timeout; | 1136 | long timeo; |
1090 | unsigned int sz; | 1137 | unsigned int sz; |
1091 | int sz_to_copy, target, needed; | 1138 | int sz_to_copy, target, needed; |
1092 | int sz_copied = 0; | 1139 | int sz_copied = 0; |
@@ -1099,31 +1146,19 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
1099 | 1146 | ||
1100 | lock_sock(sk); | 1147 | lock_sock(sk); |
1101 | 1148 | ||
1102 | if (unlikely((sock->state == SS_UNCONNECTED))) { | 1149 | if (unlikely(sock->state == SS_UNCONNECTED)) { |
1103 | res = -ENOTCONN; | 1150 | res = -ENOTCONN; |
1104 | goto exit; | 1151 | goto exit; |
1105 | } | 1152 | } |
1106 | 1153 | ||
1107 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); | 1154 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); |
1108 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1155 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
1109 | 1156 | ||
1110 | restart: | 1157 | restart: |
1111 | /* Look for a message in receive queue; wait if necessary */ | 1158 | /* Look for a message in receive queue; wait if necessary */ |
1112 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1159 | res = tipc_wait_for_rcvmsg(sock, timeo); |
1113 | if (sock->state == SS_DISCONNECTING) { | 1160 | if (res) |
1114 | res = -ENOTCONN; | 1161 | goto exit; |
1115 | goto exit; | ||
1116 | } | ||
1117 | if (timeout <= 0L) { | ||
1118 | res = timeout ? timeout : -EWOULDBLOCK; | ||
1119 | goto exit; | ||
1120 | } | ||
1121 | release_sock(sk); | ||
1122 | timeout = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
1123 | tipc_rx_ready(sock), | ||
1124 | timeout); | ||
1125 | lock_sock(sk); | ||
1126 | } | ||
1127 | 1162 | ||
1128 | /* Look at first message in receive queue */ | 1163 | /* Look at first message in receive queue */ |
1129 | buf = skb_peek(&sk->sk_receive_queue); | 1164 | buf = skb_peek(&sk->sk_receive_queue); |
@@ -1327,14 +1362,12 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) | |||
1327 | static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) | 1362 | static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) |
1328 | { | 1363 | { |
1329 | struct tipc_msg *msg = buf_msg(buf); | 1364 | struct tipc_msg *msg = buf_msg(buf); |
1330 | unsigned int limit; | ||
1331 | 1365 | ||
1332 | if (msg_connected(msg)) | 1366 | if (msg_connected(msg)) |
1333 | limit = sysctl_tipc_rmem[2]; | 1367 | return sysctl_tipc_rmem[2]; |
1334 | else | 1368 | |
1335 | limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << | 1369 | return sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << |
1336 | msg_importance(msg); | 1370 | msg_importance(msg); |
1337 | return limit; | ||
1338 | } | 1371 | } |
1339 | 1372 | ||
1340 | /** | 1373 | /** |
@@ -1448,6 +1481,28 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
1448 | sk->sk_write_space(sk); | 1481 | sk->sk_write_space(sk); |
1449 | } | 1482 | } |
1450 | 1483 | ||
1484 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | ||
1485 | { | ||
1486 | struct sock *sk = sock->sk; | ||
1487 | DEFINE_WAIT(wait); | ||
1488 | int done; | ||
1489 | |||
1490 | do { | ||
1491 | int err = sock_error(sk); | ||
1492 | if (err) | ||
1493 | return err; | ||
1494 | if (!*timeo_p) | ||
1495 | return -ETIMEDOUT; | ||
1496 | if (signal_pending(current)) | ||
1497 | return sock_intr_errno(*timeo_p); | ||
1498 | |||
1499 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1500 | done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING); | ||
1501 | finish_wait(sk_sleep(sk), &wait); | ||
1502 | } while (!done); | ||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1451 | /** | 1506 | /** |
1452 | * connect - establish a connection to another TIPC port | 1507 | * connect - establish a connection to another TIPC port |
1453 | * @sock: socket structure | 1508 | * @sock: socket structure |
@@ -1463,7 +1518,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1463 | struct sock *sk = sock->sk; | 1518 | struct sock *sk = sock->sk; |
1464 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | 1519 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; |
1465 | struct msghdr m = {NULL,}; | 1520 | struct msghdr m = {NULL,}; |
1466 | unsigned int timeout; | 1521 | long timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; |
1522 | socket_state previous; | ||
1467 | int res; | 1523 | int res; |
1468 | 1524 | ||
1469 | lock_sock(sk); | 1525 | lock_sock(sk); |
@@ -1485,8 +1541,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1485 | goto exit; | 1541 | goto exit; |
1486 | } | 1542 | } |
1487 | 1543 | ||
1488 | timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; | 1544 | previous = sock->state; |
1489 | |||
1490 | switch (sock->state) { | 1545 | switch (sock->state) { |
1491 | case SS_UNCONNECTED: | 1546 | case SS_UNCONNECTED: |
1492 | /* Send a 'SYN-' to destination */ | 1547 | /* Send a 'SYN-' to destination */ |
@@ -1508,43 +1563,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1508 | * case is EINPROGRESS, rather than EALREADY. | 1563 | * case is EINPROGRESS, rather than EALREADY. |
1509 | */ | 1564 | */ |
1510 | res = -EINPROGRESS; | 1565 | res = -EINPROGRESS; |
1511 | break; | ||
1512 | case SS_CONNECTING: | 1566 | case SS_CONNECTING: |
1513 | res = -EALREADY; | 1567 | if (previous == SS_CONNECTING) |
1568 | res = -EALREADY; | ||
1569 | if (!timeout) | ||
1570 | goto exit; | ||
1571 | timeout = msecs_to_jiffies(timeout); | ||
1572 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | ||
1573 | res = tipc_wait_for_connect(sock, &timeout); | ||
1514 | break; | 1574 | break; |
1515 | case SS_CONNECTED: | 1575 | case SS_CONNECTED: |
1516 | res = -EISCONN; | 1576 | res = -EISCONN; |
1517 | break; | 1577 | break; |
1518 | default: | 1578 | default: |
1519 | res = -EINVAL; | 1579 | res = -EINVAL; |
1520 | goto exit; | 1580 | break; |
1521 | } | ||
1522 | |||
1523 | if (sock->state == SS_CONNECTING) { | ||
1524 | if (!timeout) | ||
1525 | goto exit; | ||
1526 | |||
1527 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | ||
1528 | release_sock(sk); | ||
1529 | res = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
1530 | sock->state != SS_CONNECTING, | ||
1531 | timeout ? (long)msecs_to_jiffies(timeout) | ||
1532 | : MAX_SCHEDULE_TIMEOUT); | ||
1533 | lock_sock(sk); | ||
1534 | if (res <= 0) { | ||
1535 | if (res == 0) | ||
1536 | res = -ETIMEDOUT; | ||
1537 | else | ||
1538 | ; /* leave "res" unchanged */ | ||
1539 | goto exit; | ||
1540 | } | ||
1541 | } | 1581 | } |
1542 | |||
1543 | if (unlikely(sock->state == SS_DISCONNECTING)) | ||
1544 | res = sock_error(sk); | ||
1545 | else | ||
1546 | res = 0; | ||
1547 | |||
1548 | exit: | 1582 | exit: |
1549 | release_sock(sk); | 1583 | release_sock(sk); |
1550 | return res; | 1584 | return res; |
@@ -1575,6 +1609,42 @@ static int listen(struct socket *sock, int len) | |||
1575 | return res; | 1609 | return res; |
1576 | } | 1610 | } |
1577 | 1611 | ||
1612 | static int tipc_wait_for_accept(struct socket *sock, long timeo) | ||
1613 | { | ||
1614 | struct sock *sk = sock->sk; | ||
1615 | DEFINE_WAIT(wait); | ||
1616 | int err; | ||
1617 | |||
1618 | /* True wake-one mechanism for incoming connections: only | ||
1619 | * one process gets woken up, not the 'whole herd'. | ||
1620 | * Since we do not 'race & poll' for established sockets | ||
1621 | * anymore, the common case will execute the loop only once. | ||
1622 | */ | ||
1623 | for (;;) { | ||
1624 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, | ||
1625 | TASK_INTERRUPTIBLE); | ||
1626 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { | ||
1627 | release_sock(sk); | ||
1628 | timeo = schedule_timeout(timeo); | ||
1629 | lock_sock(sk); | ||
1630 | } | ||
1631 | err = 0; | ||
1632 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
1633 | break; | ||
1634 | err = -EINVAL; | ||
1635 | if (sock->state != SS_LISTENING) | ||
1636 | break; | ||
1637 | err = sock_intr_errno(timeo); | ||
1638 | if (signal_pending(current)) | ||
1639 | break; | ||
1640 | err = -EAGAIN; | ||
1641 | if (!timeo) | ||
1642 | break; | ||
1643 | } | ||
1644 | finish_wait(sk_sleep(sk), &wait); | ||
1645 | return err; | ||
1646 | } | ||
1647 | |||
1578 | /** | 1648 | /** |
1579 | * accept - wait for connection request | 1649 | * accept - wait for connection request |
1580 | * @sock: listening socket | 1650 | * @sock: listening socket |
@@ -1591,7 +1661,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1591 | struct tipc_port *new_tport; | 1661 | struct tipc_port *new_tport; |
1592 | struct tipc_msg *msg; | 1662 | struct tipc_msg *msg; |
1593 | u32 new_ref; | 1663 | u32 new_ref; |
1594 | 1664 | long timeo; | |
1595 | int res; | 1665 | int res; |
1596 | 1666 | ||
1597 | lock_sock(sk); | 1667 | lock_sock(sk); |
@@ -1601,18 +1671,10 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1601 | goto exit; | 1671 | goto exit; |
1602 | } | 1672 | } |
1603 | 1673 | ||
1604 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1674 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
1605 | if (flags & O_NONBLOCK) { | 1675 | res = tipc_wait_for_accept(sock, timeo); |
1606 | res = -EWOULDBLOCK; | 1676 | if (res) |
1607 | goto exit; | 1677 | goto exit; |
1608 | } | ||
1609 | release_sock(sk); | ||
1610 | res = wait_event_interruptible(*sk_sleep(sk), | ||
1611 | (!skb_queue_empty(&sk->sk_receive_queue))); | ||
1612 | lock_sock(sk); | ||
1613 | if (res) | ||
1614 | goto exit; | ||
1615 | } | ||
1616 | 1678 | ||
1617 | buf = skb_peek(&sk->sk_receive_queue); | 1679 | buf = skb_peek(&sk->sk_receive_queue); |
1618 | 1680 | ||
@@ -1963,8 +2025,6 @@ int tipc_socket_init(void) | |||
1963 | proto_unregister(&tipc_proto); | 2025 | proto_unregister(&tipc_proto); |
1964 | goto out; | 2026 | goto out; |
1965 | } | 2027 | } |
1966 | |||
1967 | sockets_enabled = 1; | ||
1968 | out: | 2028 | out: |
1969 | return res; | 2029 | return res; |
1970 | } | 2030 | } |
@@ -1974,10 +2034,6 @@ int tipc_socket_init(void) | |||
1974 | */ | 2034 | */ |
1975 | void tipc_socket_stop(void) | 2035 | void tipc_socket_stop(void) |
1976 | { | 2036 | { |
1977 | if (!sockets_enabled) | ||
1978 | return; | ||
1979 | |||
1980 | sockets_enabled = 0; | ||
1981 | sock_unregister(tipc_family_ops.family); | 2037 | sock_unregister(tipc_family_ops.family); |
1982 | proto_unregister(&tipc_proto); | 2038 | proto_unregister(&tipc_proto); |
1983 | } | 2039 | } |