diff options
author | Allan Stephens <Allan.Stephens@windriver.com> | 2011-02-21 09:45:40 -0500 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2011-03-13 16:35:16 -0400 |
commit | 0232fd0ac475e5f5ec19a69d53467be11bec9833 (patch) | |
tree | 0bfb61f3302e17246165b6ea594ebd8d4e5ecea0 /net/tipc | |
parent | bef55aebd560c5a6f8883c421abccee39978c58c (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.c | 38 |
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 | } |