diff options
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 384 |
1 files changed, 228 insertions, 156 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3b61851bb927..a4cf274455aa 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 | ||
| @@ -354,7 +346,7 @@ static int release(struct socket *sock) | |||
| 354 | * Delete TIPC port; this ensures no more messages are queued | 346 | * Delete TIPC port; this ensures no more messages are queued |
| 355 | * (also disconnects an active connection & sends a 'FIN-' to peer) | 347 | * (also disconnects an active connection & sends a 'FIN-' to peer) |
| 356 | */ | 348 | */ |
| 357 | res = tipc_deleteport(tport->ref); | 349 | res = tipc_deleteport(tport); |
| 358 | 350 | ||
| 359 | /* Discard any remaining (connection-based) messages in receive queue */ | 351 | /* Discard any remaining (connection-based) messages in receive queue */ |
| 360 | __skb_queue_purge(&sk->sk_receive_queue); | 352 | __skb_queue_purge(&sk->sk_receive_queue); |
| @@ -386,30 +378,46 @@ static int release(struct socket *sock) | |||
| 386 | */ | 378 | */ |
| 387 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | 379 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) |
| 388 | { | 380 | { |
| 381 | struct sock *sk = sock->sk; | ||
| 389 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 382 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
| 390 | u32 portref = tipc_sk_port(sock->sk)->ref; | 383 | struct tipc_port *tport = tipc_sk_port(sock->sk); |
| 384 | int res = -EINVAL; | ||
| 391 | 385 | ||
| 392 | if (unlikely(!uaddr_len)) | 386 | lock_sock(sk); |
| 393 | return tipc_withdraw(portref, 0, NULL); | 387 | if (unlikely(!uaddr_len)) { |
| 388 | res = tipc_withdraw(tport, 0, NULL); | ||
| 389 | goto exit; | ||
| 390 | } | ||
| 394 | 391 | ||
| 395 | if (uaddr_len < sizeof(struct sockaddr_tipc)) | 392 | if (uaddr_len < sizeof(struct sockaddr_tipc)) { |
| 396 | return -EINVAL; | 393 | res = -EINVAL; |
| 397 | if (addr->family != AF_TIPC) | 394 | goto exit; |
| 398 | return -EAFNOSUPPORT; | 395 | } |
| 396 | if (addr->family != AF_TIPC) { | ||
| 397 | res = -EAFNOSUPPORT; | ||
| 398 | goto exit; | ||
| 399 | } | ||
| 399 | 400 | ||
| 400 | if (addr->addrtype == TIPC_ADDR_NAME) | 401 | if (addr->addrtype == TIPC_ADDR_NAME) |
| 401 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; | 402 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; |
| 402 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) | 403 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { |
| 403 | return -EAFNOSUPPORT; | 404 | res = -EAFNOSUPPORT; |
| 405 | goto exit; | ||
| 406 | } | ||
| 404 | 407 | ||
| 405 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && | 408 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && |
| 406 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && | 409 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && |
| 407 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) | 410 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) { |
| 408 | return -EACCES; | 411 | res = -EACCES; |
| 412 | goto exit; | ||
| 413 | } | ||
| 409 | 414 | ||
| 410 | return (addr->scope > 0) ? | 415 | res = (addr->scope > 0) ? |
| 411 | tipc_publish(portref, addr->scope, &addr->addr.nameseq) : | 416 | tipc_publish(tport, addr->scope, &addr->addr.nameseq) : |
| 412 | tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); | 417 | tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq); |
| 418 | exit: | ||
| 419 | release_sock(sk); | ||
| 420 | return res; | ||
| 413 | } | 421 | } |
| 414 | 422 | ||
| 415 | /** | 423 | /** |
| @@ -554,6 +562,31 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
| 554 | return 0; | 562 | return 0; |
| 555 | } | 563 | } |
| 556 | 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 | |||
| 557 | /** | 590 | /** |
| 558 | * send_msg - send message in connectionless manner | 591 | * send_msg - send message in connectionless manner |
| 559 | * @iocb: if NULL, indicates that socket lock is already held | 592 | * @iocb: if NULL, indicates that socket lock is already held |
| @@ -573,9 +606,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 573 | { | 606 | { |
| 574 | struct sock *sk = sock->sk; | 607 | struct sock *sk = sock->sk; |
| 575 | struct tipc_port *tport = tipc_sk_port(sk); | 608 | struct tipc_port *tport = tipc_sk_port(sk); |
| 576 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 609 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 577 | int needs_conn; | 610 | int needs_conn; |
| 578 | long timeout_val; | 611 | long timeo; |
| 579 | int res = -EINVAL; | 612 | int res = -EINVAL; |
| 580 | 613 | ||
| 581 | if (unlikely(!dest)) | 614 | if (unlikely(!dest)) |
| @@ -612,8 +645,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 612 | reject_rx_queue(sk); | 645 | reject_rx_queue(sk); |
| 613 | } | 646 | } |
| 614 | 647 | ||
| 615 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 648 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
| 616 | |||
| 617 | do { | 649 | do { |
| 618 | if (dest->addrtype == TIPC_ADDR_NAME) { | 650 | if (dest->addrtype == TIPC_ADDR_NAME) { |
| 619 | res = dest_name_check(dest, m); | 651 | res = dest_name_check(dest, m); |
| @@ -647,14 +679,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 647 | sock->state = SS_CONNECTING; | 679 | sock->state = SS_CONNECTING; |
| 648 | break; | 680 | break; |
| 649 | } | 681 | } |
| 650 | if (timeout_val <= 0L) { | 682 | res = tipc_wait_for_sndmsg(sock, &timeo); |
| 651 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 683 | if (res) |
| 652 | break; | 684 | break; |
| 653 | } | ||
| 654 | release_sock(sk); | ||
| 655 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 656 | !tport->congested, timeout_val); | ||
| 657 | lock_sock(sk); | ||
| 658 | } while (1); | 685 | } while (1); |
| 659 | 686 | ||
| 660 | exit: | 687 | exit: |
| @@ -663,6 +690,34 @@ exit: | |||
| 663 | return res; | 690 | return res; |
| 664 | } | 691 | } |
| 665 | 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 | |||
| 666 | /** | 721 | /** |
| 667 | * send_packet - send a connection-oriented message | 722 | * send_packet - send a connection-oriented message |
| 668 | * @iocb: if NULL, indicates that socket lock is already held | 723 | * @iocb: if NULL, indicates that socket lock is already held |
| @@ -679,9 +734,9 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 679 | { | 734 | { |
| 680 | struct sock *sk = sock->sk; | 735 | struct sock *sk = sock->sk; |
| 681 | struct tipc_port *tport = tipc_sk_port(sk); | 736 | struct tipc_port *tport = tipc_sk_port(sk); |
| 682 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 737 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 683 | long timeout_val; | 738 | int res = -EINVAL; |
| 684 | int res; | 739 | long timeo; |
| 685 | 740 | ||
| 686 | /* Handle implied connection establishment */ | 741 | /* Handle implied connection establishment */ |
| 687 | if (unlikely(dest)) | 742 | if (unlikely(dest)) |
| @@ -693,30 +748,24 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 693 | if (iocb) | 748 | if (iocb) |
| 694 | lock_sock(sk); | 749 | lock_sock(sk); |
| 695 | 750 | ||
| 696 | 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 | } | ||
| 697 | 758 | ||
| 759 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
| 698 | do { | 760 | do { |
| 699 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
| 700 | if (sock->state == SS_DISCONNECTING) | ||
| 701 | res = -EPIPE; | ||
| 702 | else | ||
| 703 | res = -ENOTCONN; | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | |||
| 707 | res = tipc_send(tport->ref, m->msg_iov, total_len); | 761 | res = tipc_send(tport->ref, m->msg_iov, total_len); |
| 708 | if (likely(res != -ELINKCONG)) | 762 | if (likely(res != -ELINKCONG)) |
| 709 | break; | 763 | break; |
| 710 | if (timeout_val <= 0L) { | 764 | res = tipc_wait_for_sndpkt(sock, &timeo); |
| 711 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 765 | if (res) |
| 712 | break; | 766 | break; |
| 713 | } | ||
| 714 | release_sock(sk); | ||
| 715 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 716 | (!tport->congested || !tport->connected), timeout_val); | ||
| 717 | lock_sock(sk); | ||
| 718 | } while (1); | 767 | } while (1); |
| 719 | 768 | exit: | |
| 720 | if (iocb) | 769 | if (iocb) |
| 721 | release_sock(sk); | 770 | release_sock(sk); |
| 722 | return res; | 771 | return res; |
| @@ -754,16 +803,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 754 | 803 | ||
| 755 | /* Handle special cases where there is no connection */ | 804 | /* Handle special cases where there is no connection */ |
| 756 | if (unlikely(sock->state != SS_CONNECTED)) { | 805 | if (unlikely(sock->state != SS_CONNECTED)) { |
| 757 | if (sock->state == SS_UNCONNECTED) { | 806 | if (sock->state == SS_UNCONNECTED) |
| 758 | res = send_packet(NULL, sock, m, total_len); | 807 | res = send_packet(NULL, sock, m, total_len); |
| 759 | goto exit; | 808 | else |
| 760 | } else if (sock->state == SS_DISCONNECTING) { | 809 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; |
| 761 | res = -EPIPE; | 810 | goto exit; |
| 762 | goto exit; | ||
| 763 | } else { | ||
| 764 | res = -ENOTCONN; | ||
| 765 | goto exit; | ||
| 766 | } | ||
| 767 | } | 811 | } |
| 768 | 812 | ||
| 769 | if (unlikely(m->msg_name)) { | 813 | if (unlikely(m->msg_name)) { |
| @@ -860,7 +904,7 @@ static int auto_connect(struct socket *sock, struct tipc_msg *msg) | |||
| 860 | */ | 904 | */ |
| 861 | 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) |
| 862 | { | 906 | { |
| 863 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; | 907 | DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name); |
| 864 | 908 | ||
| 865 | if (addr) { | 909 | if (addr) { |
| 866 | addr->family = AF_TIPC; | 910 | addr->family = AF_TIPC; |
| @@ -945,6 +989,37 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 945 | return 0; | 989 | return 0; |
| 946 | } | 990 | } |
| 947 | 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 (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 | |||
| 948 | /** | 1023 | /** |
| 949 | * recv_msg - receive packet-oriented message | 1024 | * recv_msg - receive packet-oriented message |
| 950 | * @iocb: (unused) | 1025 | * @iocb: (unused) |
| @@ -964,7 +1039,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
| 964 | struct tipc_port *tport = tipc_sk_port(sk); | 1039 | struct tipc_port *tport = tipc_sk_port(sk); |
| 965 | struct sk_buff *buf; | 1040 | struct sk_buff *buf; |
| 966 | struct tipc_msg *msg; | 1041 | struct tipc_msg *msg; |
| 967 | long timeout; | 1042 | long timeo; |
| 968 | unsigned int sz; | 1043 | unsigned int sz; |
| 969 | u32 err; | 1044 | u32 err; |
| 970 | int res; | 1045 | int res; |
| @@ -980,25 +1055,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
| 980 | goto exit; | 1055 | goto exit; |
| 981 | } | 1056 | } |
| 982 | 1057 | ||
| 983 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1058 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
| 984 | restart: | 1059 | restart: |
| 985 | 1060 | ||
| 986 | /* Look for a message in receive queue; wait if necessary */ | 1061 | /* Look for a message in receive queue; wait if necessary */ |
| 987 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1062 | res = tipc_wait_for_rcvmsg(sock, timeo); |
| 988 | if (sock->state == SS_DISCONNECTING) { | 1063 | if (res) |
| 989 | res = -ENOTCONN; | 1064 | goto exit; |
| 990 | goto exit; | ||
| 991 | } | ||
| 992 | if (timeout <= 0L) { | ||
| 993 | res = timeout ? timeout : -EWOULDBLOCK; | ||
| 994 | goto exit; | ||
| 995 | } | ||
| 996 | release_sock(sk); | ||
| 997 | timeout = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 998 | tipc_rx_ready(sock), | ||
| 999 | timeout); | ||
| 1000 | lock_sock(sk); | ||
| 1001 | } | ||
| 1002 | 1065 | ||
| 1003 | /* Look at first message in receive queue */ | 1066 | /* Look at first message in receive queue */ |
| 1004 | buf = skb_peek(&sk->sk_receive_queue); | 1067 | buf = skb_peek(&sk->sk_receive_queue); |
| @@ -1070,7 +1133,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1070 | struct tipc_port *tport = tipc_sk_port(sk); | 1133 | struct tipc_port *tport = tipc_sk_port(sk); |
| 1071 | struct sk_buff *buf; | 1134 | struct sk_buff *buf; |
| 1072 | struct tipc_msg *msg; | 1135 | struct tipc_msg *msg; |
| 1073 | long timeout; | 1136 | long timeo; |
| 1074 | unsigned int sz; | 1137 | unsigned int sz; |
| 1075 | int sz_to_copy, target, needed; | 1138 | int sz_to_copy, target, needed; |
| 1076 | int sz_copied = 0; | 1139 | int sz_copied = 0; |
| @@ -1083,31 +1146,19 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1083 | 1146 | ||
| 1084 | lock_sock(sk); | 1147 | lock_sock(sk); |
| 1085 | 1148 | ||
| 1086 | if (unlikely((sock->state == SS_UNCONNECTED))) { | 1149 | if (unlikely(sock->state == SS_UNCONNECTED)) { |
| 1087 | res = -ENOTCONN; | 1150 | res = -ENOTCONN; |
| 1088 | goto exit; | 1151 | goto exit; |
| 1089 | } | 1152 | } |
| 1090 | 1153 | ||
| 1091 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); | 1154 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); |
| 1092 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1155 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
| 1093 | 1156 | ||
| 1094 | restart: | 1157 | restart: |
| 1095 | /* Look for a message in receive queue; wait if necessary */ | 1158 | /* Look for a message in receive queue; wait if necessary */ |
| 1096 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1159 | res = tipc_wait_for_rcvmsg(sock, timeo); |
| 1097 | if (sock->state == SS_DISCONNECTING) { | 1160 | if (res) |
| 1098 | res = -ENOTCONN; | 1161 | goto exit; |
| 1099 | goto exit; | ||
| 1100 | } | ||
| 1101 | if (timeout <= 0L) { | ||
| 1102 | res = timeout ? timeout : -EWOULDBLOCK; | ||
| 1103 | goto exit; | ||
| 1104 | } | ||
| 1105 | release_sock(sk); | ||
| 1106 | timeout = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 1107 | tipc_rx_ready(sock), | ||
| 1108 | timeout); | ||
| 1109 | lock_sock(sk); | ||
| 1110 | } | ||
| 1111 | 1162 | ||
| 1112 | /* Look at first message in receive queue */ | 1163 | /* Look at first message in receive queue */ |
| 1113 | buf = skb_peek(&sk->sk_receive_queue); | 1164 | buf = skb_peek(&sk->sk_receive_queue); |
| @@ -1311,14 +1362,12 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) | |||
| 1311 | 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) |
| 1312 | { | 1363 | { |
| 1313 | struct tipc_msg *msg = buf_msg(buf); | 1364 | struct tipc_msg *msg = buf_msg(buf); |
| 1314 | unsigned int limit; | ||
| 1315 | 1365 | ||
| 1316 | if (msg_connected(msg)) | 1366 | if (msg_connected(msg)) |
| 1317 | limit = sysctl_tipc_rmem[2]; | 1367 | return sysctl_tipc_rmem[2]; |
| 1318 | else | 1368 | |
| 1319 | limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << | 1369 | return sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << |
| 1320 | msg_importance(msg); | 1370 | msg_importance(msg); |
| 1321 | return limit; | ||
| 1322 | } | 1371 | } |
| 1323 | 1372 | ||
| 1324 | /** | 1373 | /** |
| @@ -1432,6 +1481,28 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
| 1432 | sk->sk_write_space(sk); | 1481 | sk->sk_write_space(sk); |
| 1433 | } | 1482 | } |
| 1434 | 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 | |||
| 1435 | /** | 1506 | /** |
| 1436 | * connect - establish a connection to another TIPC port | 1507 | * connect - establish a connection to another TIPC port |
| 1437 | * @sock: socket structure | 1508 | * @sock: socket structure |
| @@ -1447,7 +1518,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1447 | struct sock *sk = sock->sk; | 1518 | struct sock *sk = sock->sk; |
| 1448 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | 1519 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; |
| 1449 | struct msghdr m = {NULL,}; | 1520 | struct msghdr m = {NULL,}; |
| 1450 | unsigned int timeout; | 1521 | long timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; |
| 1522 | socket_state previous; | ||
| 1451 | int res; | 1523 | int res; |
| 1452 | 1524 | ||
| 1453 | lock_sock(sk); | 1525 | lock_sock(sk); |
| @@ -1469,8 +1541,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1469 | goto exit; | 1541 | goto exit; |
| 1470 | } | 1542 | } |
| 1471 | 1543 | ||
| 1472 | timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; | 1544 | previous = sock->state; |
| 1473 | |||
| 1474 | switch (sock->state) { | 1545 | switch (sock->state) { |
| 1475 | case SS_UNCONNECTED: | 1546 | case SS_UNCONNECTED: |
| 1476 | /* Send a 'SYN-' to destination */ | 1547 | /* Send a 'SYN-' to destination */ |
| @@ -1492,43 +1563,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1492 | * case is EINPROGRESS, rather than EALREADY. | 1563 | * case is EINPROGRESS, rather than EALREADY. |
| 1493 | */ | 1564 | */ |
| 1494 | res = -EINPROGRESS; | 1565 | res = -EINPROGRESS; |
| 1495 | break; | ||
| 1496 | case SS_CONNECTING: | 1566 | case SS_CONNECTING: |
| 1497 | 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); | ||
| 1498 | break; | 1574 | break; |
| 1499 | case SS_CONNECTED: | 1575 | case SS_CONNECTED: |
| 1500 | res = -EISCONN; | 1576 | res = -EISCONN; |
| 1501 | break; | 1577 | break; |
| 1502 | default: | 1578 | default: |
| 1503 | res = -EINVAL; | 1579 | res = -EINVAL; |
| 1504 | goto exit; | 1580 | break; |
| 1505 | } | ||
| 1506 | |||
| 1507 | if (sock->state == SS_CONNECTING) { | ||
| 1508 | if (!timeout) | ||
| 1509 | goto exit; | ||
| 1510 | |||
| 1511 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | ||
| 1512 | release_sock(sk); | ||
| 1513 | res = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 1514 | sock->state != SS_CONNECTING, | ||
| 1515 | timeout ? (long)msecs_to_jiffies(timeout) | ||
| 1516 | : MAX_SCHEDULE_TIMEOUT); | ||
| 1517 | lock_sock(sk); | ||
| 1518 | if (res <= 0) { | ||
| 1519 | if (res == 0) | ||
| 1520 | res = -ETIMEDOUT; | ||
| 1521 | else | ||
| 1522 | ; /* leave "res" unchanged */ | ||
| 1523 | goto exit; | ||
| 1524 | } | ||
| 1525 | } | 1581 | } |
| 1526 | |||
| 1527 | if (unlikely(sock->state == SS_DISCONNECTING)) | ||
| 1528 | res = sock_error(sk); | ||
| 1529 | else | ||
| 1530 | res = 0; | ||
| 1531 | |||
| 1532 | exit: | 1582 | exit: |
| 1533 | release_sock(sk); | 1583 | release_sock(sk); |
| 1534 | return res; | 1584 | return res; |
| @@ -1559,6 +1609,42 @@ static int listen(struct socket *sock, int len) | |||
| 1559 | return res; | 1609 | return res; |
| 1560 | } | 1610 | } |
| 1561 | 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 (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 | |||
| 1562 | /** | 1648 | /** |
| 1563 | * accept - wait for connection request | 1649 | * accept - wait for connection request |
| 1564 | * @sock: listening socket | 1650 | * @sock: listening socket |
| @@ -1575,7 +1661,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1575 | struct tipc_port *new_tport; | 1661 | struct tipc_port *new_tport; |
| 1576 | struct tipc_msg *msg; | 1662 | struct tipc_msg *msg; |
| 1577 | u32 new_ref; | 1663 | u32 new_ref; |
| 1578 | 1664 | long timeo; | |
| 1579 | int res; | 1665 | int res; |
| 1580 | 1666 | ||
| 1581 | lock_sock(sk); | 1667 | lock_sock(sk); |
| @@ -1585,18 +1671,10 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1585 | goto exit; | 1671 | goto exit; |
| 1586 | } | 1672 | } |
| 1587 | 1673 | ||
| 1588 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1674 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
| 1589 | if (flags & O_NONBLOCK) { | 1675 | res = tipc_wait_for_accept(sock, timeo); |
| 1590 | res = -EWOULDBLOCK; | 1676 | if (res) |
| 1591 | goto exit; | 1677 | goto exit; |
| 1592 | } | ||
| 1593 | release_sock(sk); | ||
| 1594 | res = wait_event_interruptible(*sk_sleep(sk), | ||
| 1595 | (!skb_queue_empty(&sk->sk_receive_queue))); | ||
| 1596 | lock_sock(sk); | ||
| 1597 | if (res) | ||
| 1598 | goto exit; | ||
| 1599 | } | ||
| 1600 | 1678 | ||
| 1601 | buf = skb_peek(&sk->sk_receive_queue); | 1679 | buf = skb_peek(&sk->sk_receive_queue); |
| 1602 | 1680 | ||
| @@ -1947,8 +2025,6 @@ int tipc_socket_init(void) | |||
| 1947 | proto_unregister(&tipc_proto); | 2025 | proto_unregister(&tipc_proto); |
| 1948 | goto out; | 2026 | goto out; |
| 1949 | } | 2027 | } |
| 1950 | |||
| 1951 | sockets_enabled = 1; | ||
| 1952 | out: | 2028 | out: |
| 1953 | return res; | 2029 | return res; |
| 1954 | } | 2030 | } |
| @@ -1958,10 +2034,6 @@ int tipc_socket_init(void) | |||
| 1958 | */ | 2034 | */ |
| 1959 | void tipc_socket_stop(void) | 2035 | void tipc_socket_stop(void) |
| 1960 | { | 2036 | { |
| 1961 | if (!sockets_enabled) | ||
| 1962 | return; | ||
| 1963 | |||
| 1964 | sockets_enabled = 0; | ||
| 1965 | sock_unregister(tipc_family_ops.family); | 2037 | sock_unregister(tipc_family_ops.family); |
| 1966 | proto_unregister(&tipc_proto); | 2038 | proto_unregister(&tipc_proto); |
| 1967 | } | 2039 | } |
