diff options
-rw-r--r-- | net/tipc/socket.c | 80 |
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 | |||
61 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); | 58 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); |
62 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | 59 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); |
63 | static void wakeupdispatch(struct tipc_port *tport); | 60 | static 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 | ||
994 | static 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); |
1033 | restart: | 1061 | restart: |
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 | ||
1143 | restart: | 1159 | restart: |
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); |