aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c70
1 files changed, 32 insertions, 38 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 125dcb0737b2..29d94d53198d 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -58,6 +58,9 @@ struct tipc_sock {
58#define tipc_sk(sk) ((struct tipc_sock *)(sk)) 58#define tipc_sk(sk) ((struct tipc_sock *)(sk))
59#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p)) 59#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
60 60
61#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
62 (sock->state == SS_DISCONNECTING))
63
61static int backlog_rcv(struct sock *sk, struct sk_buff *skb); 64static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
62static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); 65static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
63static void wakeupdispatch(struct tipc_port *tport); 66static void wakeupdispatch(struct tipc_port *tport);
@@ -289,7 +292,7 @@ static int release(struct socket *sock)
289 if (buf == NULL) 292 if (buf == NULL)
290 break; 293 break;
291 atomic_dec(&tipc_queue_size); 294 atomic_dec(&tipc_queue_size);
292 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) 295 if (TIPC_SKB_CB(buf)->handle != 0)
293 buf_discard(buf); 296 buf_discard(buf);
294 else { 297 else {
295 if ((sock->state == SS_CONNECTING) || 298 if ((sock->state == SS_CONNECTING) ||
@@ -911,15 +914,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
911 struct tipc_port *tport = tipc_sk_port(sk); 914 struct tipc_port *tport = tipc_sk_port(sk);
912 struct sk_buff *buf; 915 struct sk_buff *buf;
913 struct tipc_msg *msg; 916 struct tipc_msg *msg;
917 long timeout;
914 unsigned int sz; 918 unsigned int sz;
915 u32 err; 919 u32 err;
916 int res; 920 int res;
917 921
918 /* Catch invalid receive requests */ 922 /* Catch invalid receive requests */
919 923
920 if (m->msg_iovlen != 1)
921 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
922
923 if (unlikely(!buf_len)) 924 if (unlikely(!buf_len))
924 return -EINVAL; 925 return -EINVAL;
925 926
@@ -930,6 +931,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
930 goto exit; 931 goto exit;
931 } 932 }
932 933
934 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
933restart: 935restart:
934 936
935 /* Look for a message in receive queue; wait if necessary */ 937 /* Look for a message in receive queue; wait if necessary */
@@ -939,17 +941,15 @@ restart:
939 res = -ENOTCONN; 941 res = -ENOTCONN;
940 goto exit; 942 goto exit;
941 } 943 }
942 if (flags & MSG_DONTWAIT) { 944 if (timeout <= 0L) {
943 res = -EWOULDBLOCK; 945 res = timeout ? timeout : -EWOULDBLOCK;
944 goto exit; 946 goto exit;
945 } 947 }
946 release_sock(sk); 948 release_sock(sk);
947 res = wait_event_interruptible(*sk_sleep(sk), 949 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
948 (!skb_queue_empty(&sk->sk_receive_queue) || 950 tipc_rx_ready(sock),
949 (sock->state == SS_DISCONNECTING))); 951 timeout);
950 lock_sock(sk); 952 lock_sock(sk);
951 if (res)
952 goto exit;
953 } 953 }
954 954
955 /* Look at first message in receive queue */ 955 /* Look at first message in receive queue */
@@ -991,11 +991,10 @@ restart:
991 sz = buf_len; 991 sz = buf_len;
992 m->msg_flags |= MSG_TRUNC; 992 m->msg_flags |= MSG_TRUNC;
993 } 993 }
994 if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), 994 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
995 sz))) { 995 m->msg_iov, sz);
996 res = -EFAULT; 996 if (res)
997 goto exit; 997 goto exit;
998 }
999 res = sz; 998 res = sz;
1000 } else { 999 } else {
1001 if ((sock->state == SS_READY) || 1000 if ((sock->state == SS_READY) ||
@@ -1038,19 +1037,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1038 struct tipc_port *tport = tipc_sk_port(sk); 1037 struct tipc_port *tport = tipc_sk_port(sk);
1039 struct sk_buff *buf; 1038 struct sk_buff *buf;
1040 struct tipc_msg *msg; 1039 struct tipc_msg *msg;
1040 long timeout;
1041 unsigned int sz; 1041 unsigned int sz;
1042 int sz_to_copy, target, needed; 1042 int sz_to_copy, target, needed;
1043 int sz_copied = 0; 1043 int sz_copied = 0;
1044 char __user *crs = m->msg_iov->iov_base;
1045 unsigned char *buf_crs;
1046 u32 err; 1044 u32 err;
1047 int res = 0; 1045 int res = 0;
1048 1046
1049 /* Catch invalid receive attempts */ 1047 /* Catch invalid receive attempts */
1050 1048
1051 if (m->msg_iovlen != 1)
1052 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
1053
1054 if (unlikely(!buf_len)) 1049 if (unlikely(!buf_len))
1055 return -EINVAL; 1050 return -EINVAL;
1056 1051
@@ -1063,7 +1058,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1063 } 1058 }
1064 1059
1065 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); 1060 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1066 1061 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1067restart: 1062restart:
1068 1063
1069 /* Look for a message in receive queue; wait if necessary */ 1064 /* Look for a message in receive queue; wait if necessary */
@@ -1073,17 +1068,15 @@ restart:
1073 res = -ENOTCONN; 1068 res = -ENOTCONN;
1074 goto exit; 1069 goto exit;
1075 } 1070 }
1076 if (flags & MSG_DONTWAIT) { 1071 if (timeout <= 0L) {
1077 res = -EWOULDBLOCK; 1072 res = timeout ? timeout : -EWOULDBLOCK;
1078 goto exit; 1073 goto exit;
1079 } 1074 }
1080 release_sock(sk); 1075 release_sock(sk);
1081 res = wait_event_interruptible(*sk_sleep(sk), 1076 timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
1082 (!skb_queue_empty(&sk->sk_receive_queue) || 1077 tipc_rx_ready(sock),
1083 (sock->state == SS_DISCONNECTING))); 1078 timeout);
1084 lock_sock(sk); 1079 lock_sock(sk);
1085 if (res)
1086 goto exit;
1087 } 1080 }
1088 1081
1089 /* Look at first message in receive queue */ 1082 /* Look at first message in receive queue */
@@ -1112,24 +1105,25 @@ restart:
1112 /* Capture message data (if valid) & compute return value (always) */ 1105 /* Capture message data (if valid) & compute return value (always) */
1113 1106
1114 if (!err) { 1107 if (!err) {
1115 buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); 1108 u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
1116 sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
1117 1109
1110 sz -= offset;
1118 needed = (buf_len - sz_copied); 1111 needed = (buf_len - sz_copied);
1119 sz_to_copy = (sz <= needed) ? sz : needed; 1112 sz_to_copy = (sz <= needed) ? sz : needed;
1120 if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { 1113
1121 res = -EFAULT; 1114 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
1115 m->msg_iov, sz_to_copy);
1116 if (res)
1122 goto exit; 1117 goto exit;
1123 } 1118
1124 sz_copied += sz_to_copy; 1119 sz_copied += sz_to_copy;
1125 1120
1126 if (sz_to_copy < sz) { 1121 if (sz_to_copy < sz) {
1127 if (!(flags & MSG_PEEK)) 1122 if (!(flags & MSG_PEEK))
1128 TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; 1123 TIPC_SKB_CB(buf)->handle =
1124 (void *)(unsigned long)(offset + sz_to_copy);
1129 goto exit; 1125 goto exit;
1130 } 1126 }
1131
1132 crs += sz_to_copy;
1133 } else { 1127 } else {
1134 if (sz_copied != 0) 1128 if (sz_copied != 0)
1135 goto exit; /* can't add error msg to valid data */ 1129 goto exit; /* can't add error msg to valid data */
@@ -1256,7 +1250,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1256 1250
1257 /* Enqueue message (finally!) */ 1251 /* Enqueue message (finally!) */
1258 1252
1259 TIPC_SKB_CB(buf)->handle = msg_data(msg); 1253 TIPC_SKB_CB(buf)->handle = 0;
1260 atomic_inc(&tipc_queue_size); 1254 atomic_inc(&tipc_queue_size);
1261 __skb_queue_tail(&sk->sk_receive_queue, buf); 1255 __skb_queue_tail(&sk->sk_receive_queue, buf);
1262 1256
@@ -1608,7 +1602,7 @@ restart:
1608 buf = __skb_dequeue(&sk->sk_receive_queue); 1602 buf = __skb_dequeue(&sk->sk_receive_queue);
1609 if (buf) { 1603 if (buf) {
1610 atomic_dec(&tipc_queue_size); 1604 atomic_dec(&tipc_queue_size);
1611 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { 1605 if (TIPC_SKB_CB(buf)->handle != 0) {
1612 buf_discard(buf); 1606 buf_discard(buf);
1613 goto restart; 1607 goto restart;
1614 } 1608 }