aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-01-16 20:50:06 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-16 22:10:34 -0500
commit391a6dd1da3979be7b6fc0d9ded1b0b906bd068f (patch)
treee51f79377cd0bd655e65be9d551ea03e6acc9c3a /net/tipc
parent3f40504f7ee419eda0068e55e0ee2622e1fce40b (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.c60
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
698static 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 773exit:
752 if (iocb) 774 if (iocb)
753 release_sock(sk); 775 release_sock(sk);
754 return res; 776 return res;