aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-01-16 20:50:07 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-16 22:10:34 -0500
commit9bbb4ecc681968b7cf781e08e3918604c3b699d3 (patch)
tree7c0c3aa49a645be67a43bdec3b3e354714dc1f61 /net/tipc
parent391a6dd1da3979be7b6fc0d9ded1b0b906bd068f (diff)
tipc: standardize recvmsg routine
Standardize the behaviour of waiting for events in TIPC recvmsg() so that all variables of socket or port structures are protected within socket lock, allowing the process of calling recvmsg() 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.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index c4803101fbdf..eab17eb9ca1d 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
61static int backlog_rcv(struct sock *sk, struct sk_buff *skb); 58static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
62static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); 59static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
63static void wakeupdispatch(struct tipc_port *tport); 60static void wakeupdispatch(struct tipc_port *tport);
@@ -994,6 +991,37 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
994 return 0; 991 return 0;
995} 992}
996 993
994static 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
997/** 1025/**
998 * recv_msg - receive packet-oriented message 1026 * recv_msg - receive packet-oriented message
999 * @iocb: (unused) 1027 * @iocb: (unused)
@@ -1013,7 +1041,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
1013 struct tipc_port *tport = tipc_sk_port(sk); 1041 struct tipc_port *tport = tipc_sk_port(sk);
1014 struct sk_buff *buf; 1042 struct sk_buff *buf;
1015 struct tipc_msg *msg; 1043 struct tipc_msg *msg;
1016 long timeout; 1044 long timeo;
1017 unsigned int sz; 1045 unsigned int sz;
1018 u32 err; 1046 u32 err;
1019 int res; 1047 int res;
@@ -1029,25 +1057,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
1029 goto exit; 1057 goto exit;
1030 } 1058 }
1031 1059
1032 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 1060 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1033restart: 1061restart:
1034 1062
1035 /* Look for a message in receive queue; wait if necessary */ 1063 /* Look for a message in receive queue; wait if necessary */
1036 while (skb_queue_empty(&sk->sk_receive_queue)) { 1064 res = tipc_wait_for_rcvmsg(sock, timeo);
1037 if (sock->state == SS_DISCONNECTING) { 1065 if (res)
1038 res = -ENOTCONN; 1066 goto exit;
1039 goto exit;
1040 }
1041 if (timeout <= 0L) {
1042 res = timeout ? timeout : -EWOULDBLOCK;
1043 goto exit;
1044 }
1045 release_sock(sk);
1046 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
1047 tipc_rx_ready(sock),
1048 timeout);
1049 lock_sock(sk);
1050 }
1051 1067
1052 /* Look at first message in receive queue */ 1068 /* Look at first message in receive queue */
1053 buf = skb_peek(&sk->sk_receive_queue); 1069 buf = skb_peek(&sk->sk_receive_queue);
@@ -1119,7 +1135,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1119 struct tipc_port *tport = tipc_sk_port(sk); 1135 struct tipc_port *tport = tipc_sk_port(sk);
1120 struct sk_buff *buf; 1136 struct sk_buff *buf;
1121 struct tipc_msg *msg; 1137 struct tipc_msg *msg;
1122 long timeout; 1138 long timeo;
1123 unsigned int sz; 1139 unsigned int sz;
1124 int sz_to_copy, target, needed; 1140 int sz_to_copy, target, needed;
1125 int sz_copied = 0; 1141 int sz_copied = 0;
@@ -1132,31 +1148,19 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1132 1148
1133 lock_sock(sk); 1149 lock_sock(sk);
1134 1150
1135 if (unlikely((sock->state == SS_UNCONNECTED))) { 1151 if (unlikely(sock->state == SS_UNCONNECTED)) {
1136 res = -ENOTCONN; 1152 res = -ENOTCONN;
1137 goto exit; 1153 goto exit;
1138 } 1154 }
1139 1155
1140 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); 1156 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1141 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 1157 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1142 1158
1143restart: 1159restart:
1144 /* Look for a message in receive queue; wait if necessary */ 1160 /* Look for a message in receive queue; wait if necessary */
1145 while (skb_queue_empty(&sk->sk_receive_queue)) { 1161 res = tipc_wait_for_rcvmsg(sock, timeo);
1146 if (sock->state == SS_DISCONNECTING) { 1162 if (res)
1147 res = -ENOTCONN; 1163 goto exit;
1148 goto exit;
1149 }
1150 if (timeout <= 0L) {
1151 res = timeout ? timeout : -EWOULDBLOCK;
1152 goto exit;
1153 }
1154 release_sock(sk);
1155 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
1156 tipc_rx_ready(sock),
1157 timeout);
1158 lock_sock(sk);
1159 }
1160 1164
1161 /* Look at first message in receive queue */ 1165 /* Look at first message in receive queue */
1162 buf = skb_peek(&sk->sk_receive_queue); 1166 buf = skb_peek(&sk->sk_receive_queue);