diff options
| -rw-r--r-- | net/tipc/socket.c | 108 |
1 files changed, 49 insertions, 59 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 800caaa699a1..f27462eeccbe 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -110,7 +110,6 @@ static void tipc_write_space(struct sock *sk); | |||
| 110 | static void tipc_sock_destruct(struct sock *sk); | 110 | static void tipc_sock_destruct(struct sock *sk); |
| 111 | static int tipc_release(struct socket *sock); | 111 | static int tipc_release(struct socket *sock); |
| 112 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); | 112 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
| 113 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); | ||
| 114 | static void tipc_sk_timeout(unsigned long data); | 113 | static void tipc_sk_timeout(unsigned long data); |
| 115 | static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, | 114 | static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, |
| 116 | struct tipc_name_seq const *seq); | 115 | struct tipc_name_seq const *seq); |
| @@ -334,6 +333,49 @@ static int tipc_set_sk_state(struct sock *sk, int state) | |||
| 334 | return res; | 333 | return res; |
| 335 | } | 334 | } |
| 336 | 335 | ||
| 336 | static int tipc_sk_sock_err(struct socket *sock, long *timeout) | ||
| 337 | { | ||
| 338 | struct sock *sk = sock->sk; | ||
| 339 | int err = sock_error(sk); | ||
| 340 | int typ = sock->type; | ||
| 341 | |||
| 342 | if (err) | ||
| 343 | return err; | ||
| 344 | if (typ == SOCK_STREAM || typ == SOCK_SEQPACKET) { | ||
| 345 | if (sk->sk_state == TIPC_DISCONNECTING) | ||
| 346 | return -EPIPE; | ||
| 347 | else if (!tipc_sk_connected(sk)) | ||
| 348 | return -ENOTCONN; | ||
| 349 | } | ||
| 350 | if (!*timeout) | ||
| 351 | return -EAGAIN; | ||
| 352 | if (signal_pending(current)) | ||
| 353 | return sock_intr_errno(*timeout); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | #define tipc_wait_for_cond(sock_, timeout_, condition_) \ | ||
| 359 | ({ \ | ||
| 360 | int rc_ = 0; \ | ||
| 361 | int done_ = 0; \ | ||
| 362 | \ | ||
| 363 | while (!(condition_) && !done_) { \ | ||
| 364 | struct sock *sk_ = sock->sk; \ | ||
| 365 | DEFINE_WAIT_FUNC(wait_, woken_wake_function); \ | ||
| 366 | \ | ||
| 367 | rc_ = tipc_sk_sock_err(sock_, timeout_); \ | ||
| 368 | if (rc_) \ | ||
| 369 | break; \ | ||
| 370 | prepare_to_wait(sk_sleep(sk_), &wait_, \ | ||
| 371 | TASK_INTERRUPTIBLE); \ | ||
| 372 | done_ = sk_wait_event(sk_, timeout_, \ | ||
| 373 | (condition_), &wait_); \ | ||
| 374 | remove_wait_queue(sk_sleep(sk_), &wait_); \ | ||
| 375 | } \ | ||
| 376 | rc_; \ | ||
| 377 | }) | ||
| 378 | |||
| 337 | /** | 379 | /** |
| 338 | * tipc_sk_create - create a TIPC socket | 380 | * tipc_sk_create - create a TIPC socket |
| 339 | * @net: network namespace (must be default network) | 381 | * @net: network namespace (must be default network) |
| @@ -721,7 +763,7 @@ new_mtu: | |||
| 721 | 763 | ||
| 722 | if (rc == -ELINKCONG) { | 764 | if (rc == -ELINKCONG) { |
| 723 | tsk->link_cong = 1; | 765 | tsk->link_cong = 1; |
| 724 | rc = tipc_wait_for_sndmsg(sock, &timeo); | 766 | rc = tipc_wait_for_cond(sock, &timeo, !tsk->link_cong); |
| 725 | if (!rc) | 767 | if (!rc) |
| 726 | continue; | 768 | continue; |
| 727 | } | 769 | } |
| @@ -830,31 +872,6 @@ exit: | |||
| 830 | kfree_skb(skb); | 872 | kfree_skb(skb); |
| 831 | } | 873 | } |
| 832 | 874 | ||
| 833 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | ||
| 834 | { | ||
| 835 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||
| 836 | struct sock *sk = sock->sk; | ||
| 837 | struct tipc_sock *tsk = tipc_sk(sk); | ||
| 838 | int done; | ||
| 839 | |||
| 840 | do { | ||
| 841 | int err = sock_error(sk); | ||
| 842 | if (err) | ||
| 843 | return err; | ||
| 844 | if (sk->sk_shutdown & SEND_SHUTDOWN) | ||
| 845 | return -EPIPE; | ||
| 846 | if (!*timeo_p) | ||
| 847 | return -EAGAIN; | ||
| 848 | if (signal_pending(current)) | ||
| 849 | return sock_intr_errno(*timeo_p); | ||
| 850 | |||
| 851 | add_wait_queue(sk_sleep(sk), &wait); | ||
| 852 | done = sk_wait_event(sk, timeo_p, !tsk->link_cong, &wait); | ||
| 853 | remove_wait_queue(sk_sleep(sk), &wait); | ||
| 854 | } while (!done); | ||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | /** | 875 | /** |
| 859 | * tipc_sendmsg - send message in connectionless manner | 876 | * tipc_sendmsg - send message in connectionless manner |
| 860 | * @sock: socket structure | 877 | * @sock: socket structure |
| @@ -970,7 +987,7 @@ new_mtu: | |||
| 970 | } | 987 | } |
| 971 | if (rc == -ELINKCONG) { | 988 | if (rc == -ELINKCONG) { |
| 972 | tsk->link_cong = 1; | 989 | tsk->link_cong = 1; |
| 973 | rc = tipc_wait_for_sndmsg(sock, &timeo); | 990 | rc = tipc_wait_for_cond(sock, &timeo, !tsk->link_cong); |
| 974 | if (!rc) | 991 | if (!rc) |
| 975 | continue; | 992 | continue; |
| 976 | } | 993 | } |
| @@ -985,36 +1002,6 @@ new_mtu: | |||
| 985 | return rc; | 1002 | return rc; |
| 986 | } | 1003 | } |
| 987 | 1004 | ||
| 988 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | ||
| 989 | { | ||
| 990 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||
| 991 | struct sock *sk = sock->sk; | ||
| 992 | struct tipc_sock *tsk = tipc_sk(sk); | ||
| 993 | int done; | ||
| 994 | |||
| 995 | do { | ||
| 996 | int err = sock_error(sk); | ||
| 997 | if (err) | ||
| 998 | return err; | ||
| 999 | if (sk->sk_state == TIPC_DISCONNECTING) | ||
| 1000 | return -EPIPE; | ||
| 1001 | else if (!tipc_sk_connected(sk)) | ||
| 1002 | return -ENOTCONN; | ||
| 1003 | if (!*timeo_p) | ||
| 1004 | return -EAGAIN; | ||
| 1005 | if (signal_pending(current)) | ||
| 1006 | return sock_intr_errno(*timeo_p); | ||
| 1007 | |||
| 1008 | add_wait_queue(sk_sleep(sk), &wait); | ||
| 1009 | done = sk_wait_event(sk, timeo_p, | ||
| 1010 | (!tsk->link_cong && | ||
| 1011 | !tsk_conn_cong(tsk)) || | ||
| 1012 | !tipc_sk_connected(sk), &wait); | ||
| 1013 | remove_wait_queue(sk_sleep(sk), &wait); | ||
| 1014 | } while (!done); | ||
| 1015 | return 0; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | /** | 1005 | /** |
| 1019 | * tipc_send_stream - send stream-oriented data | 1006 | * tipc_send_stream - send stream-oriented data |
| 1020 | * @sock: socket structure | 1007 | * @sock: socket structure |
| @@ -1109,7 +1096,10 @@ next: | |||
| 1109 | 1096 | ||
| 1110 | tsk->link_cong = 1; | 1097 | tsk->link_cong = 1; |
| 1111 | } | 1098 | } |
| 1112 | rc = tipc_wait_for_sndpkt(sock, &timeo); | 1099 | rc = tipc_wait_for_cond(sock, &timeo, |
| 1100 | (!tsk->link_cong && | ||
| 1101 | !tsk_conn_cong(tsk) && | ||
| 1102 | tipc_sk_connected(sk))); | ||
| 1113 | } while (!rc); | 1103 | } while (!rc); |
| 1114 | 1104 | ||
| 1115 | __skb_queue_purge(&pktchain); | 1105 | __skb_queue_purge(&pktchain); |
