diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 008f6fdf95c3..3e019737e4b3 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -567,6 +567,31 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | 569 | ||
570 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | ||
571 | { | ||
572 | struct sock *sk = sock->sk; | ||
573 | struct tipc_port *tport = tipc_sk_port(sk); | ||
574 | DEFINE_WAIT(wait); | ||
575 | int done; | ||
576 | |||
577 | do { | ||
578 | int err = sock_error(sk); | ||
579 | if (err) | ||
580 | return err; | ||
581 | if (sock->state == SS_DISCONNECTING) | ||
582 | return -EPIPE; | ||
583 | if (!*timeo_p) | ||
584 | return -EAGAIN; | ||
585 | if (signal_pending(current)) | ||
586 | return sock_intr_errno(*timeo_p); | ||
587 | |||
588 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
589 | done = sk_wait_event(sk, timeo_p, !tport->congested); | ||
590 | finish_wait(sk_sleep(sk), &wait); | ||
591 | } while (!done); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
570 | /** | 595 | /** |
571 | * send_msg - send message in connectionless manner | 596 | * send_msg - send message in connectionless manner |
572 | * @iocb: if NULL, indicates that socket lock is already held | 597 | * @iocb: if NULL, indicates that socket lock is already held |
@@ -588,7 +613,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
588 | struct tipc_port *tport = tipc_sk_port(sk); | 613 | struct tipc_port *tport = tipc_sk_port(sk); |
589 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 614 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
590 | int needs_conn; | 615 | int needs_conn; |
591 | long timeout_val; | 616 | long timeo; |
592 | int res = -EINVAL; | 617 | int res = -EINVAL; |
593 | 618 | ||
594 | if (unlikely(!dest)) | 619 | if (unlikely(!dest)) |
@@ -625,8 +650,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
625 | reject_rx_queue(sk); | 650 | reject_rx_queue(sk); |
626 | } | 651 | } |
627 | 652 | ||
628 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 653 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
629 | |||
630 | do { | 654 | do { |
631 | if (dest->addrtype == TIPC_ADDR_NAME) { | 655 | if (dest->addrtype == TIPC_ADDR_NAME) { |
632 | res = dest_name_check(dest, m); | 656 | res = dest_name_check(dest, m); |
@@ -660,14 +684,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
660 | sock->state = SS_CONNECTING; | 684 | sock->state = SS_CONNECTING; |
661 | break; | 685 | break; |
662 | } | 686 | } |
663 | if (timeout_val <= 0L) { | 687 | res = tipc_wait_for_sndmsg(sock, &timeo); |
664 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 688 | if (res) |
665 | break; | 689 | break; |
666 | } | ||
667 | release_sock(sk); | ||
668 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
669 | !tport->congested, timeout_val); | ||
670 | lock_sock(sk); | ||
671 | } while (1); | 690 | } while (1); |
672 | 691 | ||
673 | exit: | 692 | exit: |