aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorAllan Stephens <Allan.Stephens@windriver.com>2011-02-21 09:45:40 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-03-13 16:35:16 -0400
commit0232fd0ac475e5f5ec19a69d53467be11bec9833 (patch)
tree0bfb61f3302e17246165b6ea594ebd8d4e5ecea0 /net/tipc
parentbef55aebd560c5a6f8883c421abccee39978c58c (diff)
tipc: Allow receiving into iovec containing multiple entries
Enhances TIPC's socket receive routines to support iovec structures containing more than a single entry. This change leverages existing sk_buff routines to do most of the work; the only significant change to TIPC itself is that an sk_buff now records how much data has been already consumed as an numeric offset, rather than as a pointer to the first unread data byte. Signed-off-by: Allan Stephens <Allan.Stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c38
1 files changed, 15 insertions, 23 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 125dcb0737b2..d45a294f47e9 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -289,7 +289,7 @@ static int release(struct socket *sock)
289 if (buf == NULL) 289 if (buf == NULL)
290 break; 290 break;
291 atomic_dec(&tipc_queue_size); 291 atomic_dec(&tipc_queue_size);
292 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) 292 if (TIPC_SKB_CB(buf)->handle != 0)
293 buf_discard(buf); 293 buf_discard(buf);
294 else { 294 else {
295 if ((sock->state == SS_CONNECTING) || 295 if ((sock->state == SS_CONNECTING) ||
@@ -917,9 +917,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
917 917
918 /* Catch invalid receive requests */ 918 /* Catch invalid receive requests */
919 919
920 if (m->msg_iovlen != 1)
921 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
922
923 if (unlikely(!buf_len)) 920 if (unlikely(!buf_len))
924 return -EINVAL; 921 return -EINVAL;
925 922
@@ -991,11 +988,10 @@ restart:
991 sz = buf_len; 988 sz = buf_len;
992 m->msg_flags |= MSG_TRUNC; 989 m->msg_flags |= MSG_TRUNC;
993 } 990 }
994 if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), 991 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
995 sz))) { 992 m->msg_iov, sz);
996 res = -EFAULT; 993 if (res)
997 goto exit; 994 goto exit;
998 }
999 res = sz; 995 res = sz;
1000 } else { 996 } else {
1001 if ((sock->state == SS_READY) || 997 if ((sock->state == SS_READY) ||
@@ -1041,16 +1037,11 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1041 unsigned int sz; 1037 unsigned int sz;
1042 int sz_to_copy, target, needed; 1038 int sz_to_copy, target, needed;
1043 int sz_copied = 0; 1039 int sz_copied = 0;
1044 char __user *crs = m->msg_iov->iov_base;
1045 unsigned char *buf_crs;
1046 u32 err; 1040 u32 err;
1047 int res = 0; 1041 int res = 0;
1048 1042
1049 /* Catch invalid receive attempts */ 1043 /* Catch invalid receive attempts */
1050 1044
1051 if (m->msg_iovlen != 1)
1052 return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
1053
1054 if (unlikely(!buf_len)) 1045 if (unlikely(!buf_len))
1055 return -EINVAL; 1046 return -EINVAL;
1056 1047
@@ -1112,24 +1103,25 @@ restart:
1112 /* Capture message data (if valid) & compute return value (always) */ 1103 /* Capture message data (if valid) & compute return value (always) */
1113 1104
1114 if (!err) { 1105 if (!err) {
1115 buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); 1106 u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
1116 sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
1117 1107
1108 sz -= offset;
1118 needed = (buf_len - sz_copied); 1109 needed = (buf_len - sz_copied);
1119 sz_to_copy = (sz <= needed) ? sz : needed; 1110 sz_to_copy = (sz <= needed) ? sz : needed;
1120 if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { 1111
1121 res = -EFAULT; 1112 res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
1113 m->msg_iov, sz_to_copy);
1114 if (res)
1122 goto exit; 1115 goto exit;
1123 } 1116
1124 sz_copied += sz_to_copy; 1117 sz_copied += sz_to_copy;
1125 1118
1126 if (sz_to_copy < sz) { 1119 if (sz_to_copy < sz) {
1127 if (!(flags & MSG_PEEK)) 1120 if (!(flags & MSG_PEEK))
1128 TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; 1121 TIPC_SKB_CB(buf)->handle =
1122 (void *)(unsigned long)(offset + sz_to_copy);
1129 goto exit; 1123 goto exit;
1130 } 1124 }
1131
1132 crs += sz_to_copy;
1133 } else { 1125 } else {
1134 if (sz_copied != 0) 1126 if (sz_copied != 0)
1135 goto exit; /* can't add error msg to valid data */ 1127 goto exit; /* can't add error msg to valid data */
@@ -1256,7 +1248,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1256 1248
1257 /* Enqueue message (finally!) */ 1249 /* Enqueue message (finally!) */
1258 1250
1259 TIPC_SKB_CB(buf)->handle = msg_data(msg); 1251 TIPC_SKB_CB(buf)->handle = 0;
1260 atomic_inc(&tipc_queue_size); 1252 atomic_inc(&tipc_queue_size);
1261 __skb_queue_tail(&sk->sk_receive_queue, buf); 1253 __skb_queue_tail(&sk->sk_receive_queue, buf);
1262 1254
@@ -1608,7 +1600,7 @@ restart:
1608 buf = __skb_dequeue(&sk->sk_receive_queue); 1600 buf = __skb_dequeue(&sk->sk_receive_queue);
1609 if (buf) { 1601 if (buf) {
1610 atomic_dec(&tipc_queue_size); 1602 atomic_dec(&tipc_queue_size);
1611 if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { 1603 if (TIPC_SKB_CB(buf)->handle != 0) {
1612 buf_discard(buf); 1604 buf_discard(buf);
1613 goto restart; 1605 goto restart;
1614 } 1606 }