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 | } |
