diff options
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 376 |
1 files changed, 228 insertions, 148 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3b61851bb927..aab4948f0aff 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); |
| @@ -239,7 +236,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) | 236 | int tipc_sock_create_local(int type, struct socket **res) |
| 240 | { | 237 | { |
| 241 | int rc; | 238 | int rc; |
| 242 | struct sock *sk; | ||
| 243 | 239 | ||
| 244 | rc = sock_create_lite(AF_TIPC, type, 0, res); | 240 | rc = sock_create_lite(AF_TIPC, type, 0, res); |
| 245 | if (rc < 0) { | 241 | if (rc < 0) { |
| @@ -248,8 +244,6 @@ int tipc_sock_create_local(int type, struct socket **res) | |||
| 248 | } | 244 | } |
| 249 | tipc_sk_create(&init_net, *res, 0, 1); | 245 | tipc_sk_create(&init_net, *res, 0, 1); |
| 250 | 246 | ||
| 251 | sk = (*res)->sk; | ||
| 252 | |||
| 253 | return 0; | 247 | return 0; |
| 254 | } | 248 | } |
| 255 | 249 | ||
| @@ -354,7 +348,7 @@ static int release(struct socket *sock) | |||
| 354 | * Delete TIPC port; this ensures no more messages are queued | 348 | * Delete TIPC port; this ensures no more messages are queued |
| 355 | * (also disconnects an active connection & sends a 'FIN-' to peer) | 349 | * (also disconnects an active connection & sends a 'FIN-' to peer) |
| 356 | */ | 350 | */ |
| 357 | res = tipc_deleteport(tport->ref); | 351 | res = tipc_deleteport(tport); |
| 358 | 352 | ||
| 359 | /* Discard any remaining (connection-based) messages in receive queue */ | 353 | /* Discard any remaining (connection-based) messages in receive queue */ |
| 360 | __skb_queue_purge(&sk->sk_receive_queue); | 354 | __skb_queue_purge(&sk->sk_receive_queue); |
| @@ -386,30 +380,46 @@ static int release(struct socket *sock) | |||
| 386 | */ | 380 | */ |
| 387 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | 381 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) |
| 388 | { | 382 | { |
| 383 | struct sock *sk = sock->sk; | ||
| 389 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 384 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
| 390 | u32 portref = tipc_sk_port(sock->sk)->ref; | 385 | struct tipc_port *tport = tipc_sk_port(sock->sk); |
| 386 | int res = -EINVAL; | ||
| 391 | 387 | ||
| 392 | if (unlikely(!uaddr_len)) | 388 | lock_sock(sk); |
| 393 | return tipc_withdraw(portref, 0, NULL); | 389 | if (unlikely(!uaddr_len)) { |
| 390 | res = tipc_withdraw(tport, 0, NULL); | ||
| 391 | goto exit; | ||
| 392 | } | ||
| 394 | 393 | ||
| 395 | if (uaddr_len < sizeof(struct sockaddr_tipc)) | 394 | if (uaddr_len < sizeof(struct sockaddr_tipc)) { |
| 396 | return -EINVAL; | 395 | res = -EINVAL; |
| 397 | if (addr->family != AF_TIPC) | 396 | goto exit; |
| 398 | return -EAFNOSUPPORT; | 397 | } |
| 398 | if (addr->family != AF_TIPC) { | ||
| 399 | res = -EAFNOSUPPORT; | ||
| 400 | goto exit; | ||
| 401 | } | ||
| 399 | 402 | ||
| 400 | if (addr->addrtype == TIPC_ADDR_NAME) | 403 | if (addr->addrtype == TIPC_ADDR_NAME) |
| 401 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; | 404 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; |
| 402 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) | 405 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { |
| 403 | return -EAFNOSUPPORT; | 406 | res = -EAFNOSUPPORT; |
| 407 | goto exit; | ||
| 408 | } | ||
| 404 | 409 | ||
| 405 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && | 410 | if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && |
| 406 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && | 411 | (addr->addr.nameseq.type != TIPC_TOP_SRV) && |
| 407 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) | 412 | (addr->addr.nameseq.type != TIPC_CFG_SRV)) { |
| 408 | return -EACCES; | 413 | res = -EACCES; |
| 414 | goto exit; | ||
| 415 | } | ||
| 409 | 416 | ||
| 410 | return (addr->scope > 0) ? | 417 | res = (addr->scope > 0) ? |
| 411 | tipc_publish(portref, addr->scope, &addr->addr.nameseq) : | 418 | tipc_publish(tport, addr->scope, &addr->addr.nameseq) : |
| 412 | tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); | 419 | tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq); |
| 420 | exit: | ||
| 421 | release_sock(sk); | ||
| 422 | return res; | ||
| 413 | } | 423 | } |
| 414 | 424 | ||
| 415 | /** | 425 | /** |
| @@ -554,6 +564,31 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
| 554 | return 0; | 564 | return 0; |
| 555 | } | 565 | } |
| 556 | 566 | ||
| 567 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | ||
| 568 | { | ||
| 569 | struct sock *sk = sock->sk; | ||
| 570 | struct tipc_port *tport = tipc_sk_port(sk); | ||
| 571 | DEFINE_WAIT(wait); | ||
| 572 | int done; | ||
| 573 | |||
| 574 | do { | ||
| 575 | int err = sock_error(sk); | ||
| 576 | if (err) | ||
| 577 | return err; | ||
| 578 | if (sock->state == SS_DISCONNECTING) | ||
| 579 | return -EPIPE; | ||
| 580 | if (!*timeo_p) | ||
| 581 | return -EAGAIN; | ||
| 582 | if (signal_pending(current)) | ||
| 583 | return sock_intr_errno(*timeo_p); | ||
| 584 | |||
| 585 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 586 | done = sk_wait_event(sk, timeo_p, !tport->congested); | ||
| 587 | finish_wait(sk_sleep(sk), &wait); | ||
| 588 | } while (!done); | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 557 | /** | 592 | /** |
| 558 | * send_msg - send message in connectionless manner | 593 | * send_msg - send message in connectionless manner |
| 559 | * @iocb: if NULL, indicates that socket lock is already held | 594 | * @iocb: if NULL, indicates that socket lock is already held |
| @@ -573,9 +608,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 573 | { | 608 | { |
| 574 | struct sock *sk = sock->sk; | 609 | struct sock *sk = sock->sk; |
| 575 | struct tipc_port *tport = tipc_sk_port(sk); | 610 | struct tipc_port *tport = tipc_sk_port(sk); |
| 576 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 611 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 577 | int needs_conn; | 612 | int needs_conn; |
| 578 | long timeout_val; | 613 | long timeo; |
| 579 | int res = -EINVAL; | 614 | int res = -EINVAL; |
| 580 | 615 | ||
| 581 | if (unlikely(!dest)) | 616 | if (unlikely(!dest)) |
| @@ -612,8 +647,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 612 | reject_rx_queue(sk); | 647 | reject_rx_queue(sk); |
| 613 | } | 648 | } |
| 614 | 649 | ||
| 615 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 650 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
| 616 | |||
| 617 | do { | 651 | do { |
| 618 | if (dest->addrtype == TIPC_ADDR_NAME) { | 652 | if (dest->addrtype == TIPC_ADDR_NAME) { |
| 619 | res = dest_name_check(dest, m); | 653 | res = dest_name_check(dest, m); |
| @@ -647,14 +681,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 647 | sock->state = SS_CONNECTING; | 681 | sock->state = SS_CONNECTING; |
| 648 | break; | 682 | break; |
| 649 | } | 683 | } |
| 650 | if (timeout_val <= 0L) { | 684 | res = tipc_wait_for_sndmsg(sock, &timeo); |
| 651 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 685 | if (res) |
| 652 | break; | 686 | 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); | 687 | } while (1); |
| 659 | 688 | ||
| 660 | exit: | 689 | exit: |
| @@ -663,6 +692,34 @@ exit: | |||
| 663 | return res; | 692 | return res; |
| 664 | } | 693 | } |
| 665 | 694 | ||
| 695 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | ||
| 696 | { | ||
| 697 | struct sock *sk = sock->sk; | ||
| 698 | struct tipc_port *tport = tipc_sk_port(sk); | ||
| 699 | DEFINE_WAIT(wait); | ||
| 700 | int done; | ||
| 701 | |||
| 702 | do { | ||
| 703 | int err = sock_error(sk); | ||
| 704 | if (err) | ||
| 705 | return err; | ||
| 706 | if (sock->state == SS_DISCONNECTING) | ||
| 707 | return -EPIPE; | ||
| 708 | else if (sock->state != SS_CONNECTED) | ||
| 709 | return -ENOTCONN; | ||
| 710 | if (!*timeo_p) | ||
| 711 | return -EAGAIN; | ||
| 712 | if (signal_pending(current)) | ||
| 713 | return sock_intr_errno(*timeo_p); | ||
| 714 | |||
| 715 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 716 | done = sk_wait_event(sk, timeo_p, | ||
| 717 | (!tport->congested || !tport->connected)); | ||
| 718 | finish_wait(sk_sleep(sk), &wait); | ||
| 719 | } while (!done); | ||
| 720 | return 0; | ||
| 721 | } | ||
| 722 | |||
| 666 | /** | 723 | /** |
| 667 | * send_packet - send a connection-oriented message | 724 | * send_packet - send a connection-oriented message |
| 668 | * @iocb: if NULL, indicates that socket lock is already held | 725 | * @iocb: if NULL, indicates that socket lock is already held |
| @@ -679,9 +736,9 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 679 | { | 736 | { |
| 680 | struct sock *sk = sock->sk; | 737 | struct sock *sk = sock->sk; |
| 681 | struct tipc_port *tport = tipc_sk_port(sk); | 738 | struct tipc_port *tport = tipc_sk_port(sk); |
| 682 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 739 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 683 | long timeout_val; | 740 | int res = -EINVAL; |
| 684 | int res; | 741 | long timeo; |
| 685 | 742 | ||
| 686 | /* Handle implied connection establishment */ | 743 | /* Handle implied connection establishment */ |
| 687 | if (unlikely(dest)) | 744 | if (unlikely(dest)) |
| @@ -693,30 +750,24 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 693 | if (iocb) | 750 | if (iocb) |
| 694 | lock_sock(sk); | 751 | lock_sock(sk); |
| 695 | 752 | ||
| 696 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 753 | if (unlikely(sock->state != SS_CONNECTED)) { |
| 754 | if (sock->state == SS_DISCONNECTING) | ||
| 755 | res = -EPIPE; | ||
| 756 | else | ||
| 757 | res = -ENOTCONN; | ||
| 758 | goto exit; | ||
| 759 | } | ||
| 697 | 760 | ||
| 761 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
| 698 | do { | 762 | 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); | 763 | res = tipc_send(tport->ref, m->msg_iov, total_len); |
| 708 | if (likely(res != -ELINKCONG)) | 764 | if (likely(res != -ELINKCONG)) |
| 709 | break; | 765 | break; |
| 710 | if (timeout_val <= 0L) { | 766 | res = tipc_wait_for_sndpkt(sock, &timeo); |
| 711 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 767 | if (res) |
| 712 | break; | 768 | 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); | 769 | } while (1); |
| 719 | 770 | exit: | |
| 720 | if (iocb) | 771 | if (iocb) |
| 721 | release_sock(sk); | 772 | release_sock(sk); |
| 722 | return res; | 773 | return res; |
| @@ -754,16 +805,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 754 | 805 | ||
| 755 | /* Handle special cases where there is no connection */ | 806 | /* Handle special cases where there is no connection */ |
| 756 | if (unlikely(sock->state != SS_CONNECTED)) { | 807 | if (unlikely(sock->state != SS_CONNECTED)) { |
| 757 | if (sock->state == SS_UNCONNECTED) { | 808 | if (sock->state == SS_UNCONNECTED) |
| 758 | res = send_packet(NULL, sock, m, total_len); | 809 | res = send_packet(NULL, sock, m, total_len); |
| 759 | goto exit; | 810 | else |
| 760 | } else if (sock->state == SS_DISCONNECTING) { | 811 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; |
| 761 | res = -EPIPE; | 812 | goto exit; |
| 762 | goto exit; | ||
| 763 | } else { | ||
| 764 | res = -ENOTCONN; | ||
| 765 | goto exit; | ||
| 766 | } | ||
| 767 | } | 813 | } |
| 768 | 814 | ||
| 769 | if (unlikely(m->msg_name)) { | 815 | if (unlikely(m->msg_name)) { |
| @@ -860,7 +906,7 @@ static int auto_connect(struct socket *sock, struct tipc_msg *msg) | |||
| 860 | */ | 906 | */ |
| 861 | static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) | 907 | static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) |
| 862 | { | 908 | { |
| 863 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; | 909 | DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name); |
| 864 | 910 | ||
| 865 | if (addr) { | 911 | if (addr) { |
| 866 | addr->family = AF_TIPC; | 912 | addr->family = AF_TIPC; |
| @@ -945,6 +991,37 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 945 | return 0; | 991 | return 0; |
| 946 | } | 992 | } |
| 947 | 993 | ||
| 994 | static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | ||
| 995 | { | ||
| 996 | struct sock *sk = sock->sk; | ||
| 997 | DEFINE_WAIT(wait); | ||
| 998 | int err; | ||
| 999 | |||
| 1000 | for (;;) { | ||
| 1001 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 1002 | if (skb_queue_empty(&sk->sk_receive_queue)) { | ||
| 1003 | if (sock->state == SS_DISCONNECTING) { | ||
| 1004 | err = -ENOTCONN; | ||
| 1005 | break; | ||
| 1006 | } | ||
| 1007 | release_sock(sk); | ||
| 1008 | timeo = schedule_timeout(timeo); | ||
| 1009 | lock_sock(sk); | ||
| 1010 | } | ||
| 1011 | err = 0; | ||
| 1012 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
| 1013 | break; | ||
| 1014 | err = sock_intr_errno(timeo); | ||
| 1015 | if (signal_pending(current)) | ||
| 1016 | break; | ||
| 1017 | err = -EAGAIN; | ||
| 1018 | if (!timeo) | ||
| 1019 | break; | ||
| 1020 | } | ||
| 1021 | finish_wait(sk_sleep(sk), &wait); | ||
| 1022 | return err; | ||
| 1023 | } | ||
| 1024 | |||
| 948 | /** | 1025 | /** |
| 949 | * recv_msg - receive packet-oriented message | 1026 | * recv_msg - receive packet-oriented message |
| 950 | * @iocb: (unused) | 1027 | * @iocb: (unused) |
| @@ -964,7 +1041,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
| 964 | struct tipc_port *tport = tipc_sk_port(sk); | 1041 | struct tipc_port *tport = tipc_sk_port(sk); |
| 965 | struct sk_buff *buf; | 1042 | struct sk_buff *buf; |
| 966 | struct tipc_msg *msg; | 1043 | struct tipc_msg *msg; |
| 967 | long timeout; | 1044 | long timeo; |
| 968 | unsigned int sz; | 1045 | unsigned int sz; |
| 969 | u32 err; | 1046 | u32 err; |
| 970 | int res; | 1047 | int res; |
| @@ -980,25 +1057,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, | |||
| 980 | goto exit; | 1057 | goto exit; |
| 981 | } | 1058 | } |
| 982 | 1059 | ||
| 983 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1060 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
| 984 | restart: | 1061 | restart: |
| 985 | 1062 | ||
| 986 | /* Look for a message in receive queue; wait if necessary */ | 1063 | /* Look for a message in receive queue; wait if necessary */ |
| 987 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1064 | res = tipc_wait_for_rcvmsg(sock, timeo); |
| 988 | if (sock->state == SS_DISCONNECTING) { | 1065 | if (res) |
| 989 | res = -ENOTCONN; | 1066 | 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 | 1067 | ||
| 1003 | /* Look at first message in receive queue */ | 1068 | /* Look at first message in receive queue */ |
| 1004 | buf = skb_peek(&sk->sk_receive_queue); | 1069 | buf = skb_peek(&sk->sk_receive_queue); |
| @@ -1070,7 +1135,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1070 | struct tipc_port *tport = tipc_sk_port(sk); | 1135 | struct tipc_port *tport = tipc_sk_port(sk); |
| 1071 | struct sk_buff *buf; | 1136 | struct sk_buff *buf; |
| 1072 | struct tipc_msg *msg; | 1137 | struct tipc_msg *msg; |
| 1073 | long timeout; | 1138 | long timeo; |
| 1074 | unsigned int sz; | 1139 | unsigned int sz; |
| 1075 | int sz_to_copy, target, needed; | 1140 | int sz_to_copy, target, needed; |
| 1076 | int sz_copied = 0; | 1141 | int sz_copied = 0; |
| @@ -1083,31 +1148,19 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1083 | 1148 | ||
| 1084 | lock_sock(sk); | 1149 | lock_sock(sk); |
| 1085 | 1150 | ||
| 1086 | if (unlikely((sock->state == SS_UNCONNECTED))) { | 1151 | if (unlikely(sock->state == SS_UNCONNECTED)) { |
| 1087 | res = -ENOTCONN; | 1152 | res = -ENOTCONN; |
| 1088 | goto exit; | 1153 | goto exit; |
| 1089 | } | 1154 | } |
| 1090 | 1155 | ||
| 1091 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); | 1156 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); |
| 1092 | timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | 1157 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
| 1093 | 1158 | ||
| 1094 | restart: | 1159 | restart: |
| 1095 | /* Look for a message in receive queue; wait if necessary */ | 1160 | /* Look for a message in receive queue; wait if necessary */ |
| 1096 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1161 | res = tipc_wait_for_rcvmsg(sock, timeo); |
| 1097 | if (sock->state == SS_DISCONNECTING) { | 1162 | if (res) |
| 1098 | res = -ENOTCONN; | 1163 | 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 | 1164 | ||
| 1112 | /* Look at first message in receive queue */ | 1165 | /* Look at first message in receive queue */ |
| 1113 | buf = skb_peek(&sk->sk_receive_queue); | 1166 | buf = skb_peek(&sk->sk_receive_queue); |
| @@ -1311,14 +1364,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) | 1364 | static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) |
| 1312 | { | 1365 | { |
| 1313 | struct tipc_msg *msg = buf_msg(buf); | 1366 | struct tipc_msg *msg = buf_msg(buf); |
| 1314 | unsigned int limit; | ||
| 1315 | 1367 | ||
| 1316 | if (msg_connected(msg)) | 1368 | if (msg_connected(msg)) |
| 1317 | limit = sysctl_tipc_rmem[2]; | 1369 | return sysctl_tipc_rmem[2]; |
| 1318 | else | 1370 | |
| 1319 | limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << | 1371 | return sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << |
| 1320 | msg_importance(msg); | 1372 | msg_importance(msg); |
| 1321 | return limit; | ||
| 1322 | } | 1373 | } |
| 1323 | 1374 | ||
| 1324 | /** | 1375 | /** |
| @@ -1432,6 +1483,28 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
| 1432 | sk->sk_write_space(sk); | 1483 | sk->sk_write_space(sk); |
| 1433 | } | 1484 | } |
| 1434 | 1485 | ||
| 1486 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | ||
| 1487 | { | ||
| 1488 | struct sock *sk = sock->sk; | ||
| 1489 | DEFINE_WAIT(wait); | ||
| 1490 | int done; | ||
| 1491 | |||
| 1492 | do { | ||
| 1493 | int err = sock_error(sk); | ||
| 1494 | if (err) | ||
| 1495 | return err; | ||
| 1496 | if (!*timeo_p) | ||
| 1497 | return -ETIMEDOUT; | ||
| 1498 | if (signal_pending(current)) | ||
| 1499 | return sock_intr_errno(*timeo_p); | ||
| 1500 | |||
| 1501 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 1502 | done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING); | ||
| 1503 | finish_wait(sk_sleep(sk), &wait); | ||
| 1504 | } while (!done); | ||
| 1505 | return 0; | ||
| 1506 | } | ||
| 1507 | |||
| 1435 | /** | 1508 | /** |
| 1436 | * connect - establish a connection to another TIPC port | 1509 | * connect - establish a connection to another TIPC port |
| 1437 | * @sock: socket structure | 1510 | * @sock: socket structure |
| @@ -1447,7 +1520,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1447 | struct sock *sk = sock->sk; | 1520 | struct sock *sk = sock->sk; |
| 1448 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | 1521 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; |
| 1449 | struct msghdr m = {NULL,}; | 1522 | struct msghdr m = {NULL,}; |
| 1450 | unsigned int timeout; | 1523 | long timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; |
| 1524 | socket_state previous; | ||
| 1451 | int res; | 1525 | int res; |
| 1452 | 1526 | ||
| 1453 | lock_sock(sk); | 1527 | lock_sock(sk); |
| @@ -1469,8 +1543,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1469 | goto exit; | 1543 | goto exit; |
| 1470 | } | 1544 | } |
| 1471 | 1545 | ||
| 1472 | timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout; | 1546 | previous = sock->state; |
| 1473 | |||
| 1474 | switch (sock->state) { | 1547 | switch (sock->state) { |
| 1475 | case SS_UNCONNECTED: | 1548 | case SS_UNCONNECTED: |
| 1476 | /* Send a 'SYN-' to destination */ | 1549 | /* Send a 'SYN-' to destination */ |
| @@ -1492,43 +1565,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1492 | * case is EINPROGRESS, rather than EALREADY. | 1565 | * case is EINPROGRESS, rather than EALREADY. |
| 1493 | */ | 1566 | */ |
| 1494 | res = -EINPROGRESS; | 1567 | res = -EINPROGRESS; |
| 1495 | break; | ||
| 1496 | case SS_CONNECTING: | 1568 | case SS_CONNECTING: |
| 1497 | res = -EALREADY; | 1569 | if (previous == SS_CONNECTING) |
| 1570 | res = -EALREADY; | ||
| 1571 | if (!timeout) | ||
| 1572 | goto exit; | ||
| 1573 | timeout = msecs_to_jiffies(timeout); | ||
| 1574 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | ||
| 1575 | res = tipc_wait_for_connect(sock, &timeout); | ||
| 1498 | break; | 1576 | break; |
| 1499 | case SS_CONNECTED: | 1577 | case SS_CONNECTED: |
| 1500 | res = -EISCONN; | 1578 | res = -EISCONN; |
| 1501 | break; | 1579 | break; |
| 1502 | default: | 1580 | default: |
| 1503 | res = -EINVAL; | 1581 | res = -EINVAL; |
| 1504 | goto exit; | 1582 | 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 | } | 1583 | } |
| 1526 | |||
| 1527 | if (unlikely(sock->state == SS_DISCONNECTING)) | ||
| 1528 | res = sock_error(sk); | ||
| 1529 | else | ||
| 1530 | res = 0; | ||
| 1531 | |||
| 1532 | exit: | 1584 | exit: |
| 1533 | release_sock(sk); | 1585 | release_sock(sk); |
| 1534 | return res; | 1586 | return res; |
| @@ -1559,6 +1611,42 @@ static int listen(struct socket *sock, int len) | |||
| 1559 | return res; | 1611 | return res; |
| 1560 | } | 1612 | } |
| 1561 | 1613 | ||
| 1614 | static int tipc_wait_for_accept(struct socket *sock, long timeo) | ||
| 1615 | { | ||
| 1616 | struct sock *sk = sock->sk; | ||
| 1617 | DEFINE_WAIT(wait); | ||
| 1618 | int err; | ||
| 1619 | |||
| 1620 | /* True wake-one mechanism for incoming connections: only | ||
| 1621 | * one process gets woken up, not the 'whole herd'. | ||
| 1622 | * Since we do not 'race & poll' for established sockets | ||
| 1623 | * anymore, the common case will execute the loop only once. | ||
| 1624 | */ | ||
| 1625 | for (;;) { | ||
| 1626 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, | ||
| 1627 | TASK_INTERRUPTIBLE); | ||
| 1628 | if (skb_queue_empty(&sk->sk_receive_queue)) { | ||
| 1629 | release_sock(sk); | ||
| 1630 | timeo = schedule_timeout(timeo); | ||
| 1631 | lock_sock(sk); | ||
| 1632 | } | ||
| 1633 | err = 0; | ||
| 1634 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
| 1635 | break; | ||
| 1636 | err = -EINVAL; | ||
| 1637 | if (sock->state != SS_LISTENING) | ||
| 1638 | break; | ||
| 1639 | err = sock_intr_errno(timeo); | ||
| 1640 | if (signal_pending(current)) | ||
| 1641 | break; | ||
| 1642 | err = -EAGAIN; | ||
| 1643 | if (!timeo) | ||
| 1644 | break; | ||
| 1645 | } | ||
| 1646 | finish_wait(sk_sleep(sk), &wait); | ||
| 1647 | return err; | ||
| 1648 | } | ||
| 1649 | |||
| 1562 | /** | 1650 | /** |
| 1563 | * accept - wait for connection request | 1651 | * accept - wait for connection request |
| 1564 | * @sock: listening socket | 1652 | * @sock: listening socket |
| @@ -1575,7 +1663,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1575 | struct tipc_port *new_tport; | 1663 | struct tipc_port *new_tport; |
| 1576 | struct tipc_msg *msg; | 1664 | struct tipc_msg *msg; |
| 1577 | u32 new_ref; | 1665 | u32 new_ref; |
| 1578 | 1666 | long timeo; | |
| 1579 | int res; | 1667 | int res; |
| 1580 | 1668 | ||
| 1581 | lock_sock(sk); | 1669 | lock_sock(sk); |
| @@ -1585,18 +1673,10 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1585 | goto exit; | 1673 | goto exit; |
| 1586 | } | 1674 | } |
| 1587 | 1675 | ||
| 1588 | while (skb_queue_empty(&sk->sk_receive_queue)) { | 1676 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
| 1589 | if (flags & O_NONBLOCK) { | 1677 | res = tipc_wait_for_accept(sock, timeo); |
| 1590 | res = -EWOULDBLOCK; | 1678 | if (res) |
| 1591 | goto exit; | 1679 | 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 | 1680 | ||
| 1601 | buf = skb_peek(&sk->sk_receive_queue); | 1681 | buf = skb_peek(&sk->sk_receive_queue); |
| 1602 | 1682 | ||
