diff options
author | Ying Xue <ying.xue@windriver.com> | 2014-01-16 20:50:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-16 22:10:34 -0500 |
commit | 391a6dd1da3979be7b6fc0d9ded1b0b906bd068f (patch) | |
tree | e51f79377cd0bd655e65be9d551ea03e6acc9c3a /net/tipc | |
parent | 3f40504f7ee419eda0068e55e0ee2622e1fce40b (diff) |
tipc: standardize sendmsg routine of connected socket
Standardize the behaviour of waiting for events in TIPC send_packet()
so that all variables of socket or port structures are protected within
socket lock, allowing the process of calling sendmsg() to be woken up
at appropriate time.
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/socket.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3e019737e4b3..c4803101fbdf 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -695,6 +695,34 @@ exit: | |||
695 | return res; | 695 | return res; |
696 | } | 696 | } |
697 | 697 | ||
698 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | ||
699 | { | ||
700 | struct sock *sk = sock->sk; | ||
701 | struct tipc_port *tport = tipc_sk_port(sk); | ||
702 | DEFINE_WAIT(wait); | ||
703 | int done; | ||
704 | |||
705 | do { | ||
706 | int err = sock_error(sk); | ||
707 | if (err) | ||
708 | return err; | ||
709 | if (sock->state == SS_DISCONNECTING) | ||
710 | return -EPIPE; | ||
711 | else if (sock->state != SS_CONNECTED) | ||
712 | return -ENOTCONN; | ||
713 | if (!*timeo_p) | ||
714 | return -EAGAIN; | ||
715 | if (signal_pending(current)) | ||
716 | return sock_intr_errno(*timeo_p); | ||
717 | |||
718 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
719 | done = sk_wait_event(sk, timeo_p, | ||
720 | (!tport->congested || !tport->connected)); | ||
721 | finish_wait(sk_sleep(sk), &wait); | ||
722 | } while (!done); | ||
723 | return 0; | ||
724 | } | ||
725 | |||
698 | /** | 726 | /** |
699 | * send_packet - send a connection-oriented message | 727 | * send_packet - send a connection-oriented message |
700 | * @iocb: if NULL, indicates that socket lock is already held | 728 | * @iocb: if NULL, indicates that socket lock is already held |
@@ -712,8 +740,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
712 | struct sock *sk = sock->sk; | 740 | struct sock *sk = sock->sk; |
713 | struct tipc_port *tport = tipc_sk_port(sk); | 741 | struct tipc_port *tport = tipc_sk_port(sk); |
714 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 742 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
715 | long timeout_val; | 743 | int res = -EINVAL; |
716 | int res; | 744 | long timeo; |
717 | 745 | ||
718 | /* Handle implied connection establishment */ | 746 | /* Handle implied connection establishment */ |
719 | if (unlikely(dest)) | 747 | if (unlikely(dest)) |
@@ -725,30 +753,24 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
725 | if (iocb) | 753 | if (iocb) |
726 | lock_sock(sk); | 754 | lock_sock(sk); |
727 | 755 | ||
728 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 756 | if (unlikely(sock->state != SS_CONNECTED)) { |
757 | if (sock->state == SS_DISCONNECTING) | ||
758 | res = -EPIPE; | ||
759 | else | ||
760 | res = -ENOTCONN; | ||
761 | goto exit; | ||
762 | } | ||
729 | 763 | ||
764 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
730 | do { | 765 | do { |
731 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
732 | if (sock->state == SS_DISCONNECTING) | ||
733 | res = -EPIPE; | ||
734 | else | ||
735 | res = -ENOTCONN; | ||
736 | break; | ||
737 | } | ||
738 | |||
739 | res = tipc_send(tport->ref, m->msg_iov, total_len); | 766 | res = tipc_send(tport->ref, m->msg_iov, total_len); |
740 | if (likely(res != -ELINKCONG)) | 767 | if (likely(res != -ELINKCONG)) |
741 | break; | 768 | break; |
742 | if (timeout_val <= 0L) { | 769 | res = tipc_wait_for_sndpkt(sock, &timeo); |
743 | res = timeout_val ? timeout_val : -EWOULDBLOCK; | 770 | if (res) |
744 | break; | 771 | break; |
745 | } | ||
746 | release_sock(sk); | ||
747 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
748 | (!tport->congested || !tport->connected), timeout_val); | ||
749 | lock_sock(sk); | ||
750 | } while (1); | 772 | } while (1); |
751 | 773 | exit: | |
752 | if (iocb) | 774 | if (iocb) |
753 | release_sock(sk); | 775 | release_sock(sk); |
754 | return res; | 776 | return res; |