aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2017-05-02 12:16:54 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-02 15:56:54 -0400
commitec8a09fbbeff252c80daf62c7a78342003dddf9c (patch)
treec52e9bc9f46009212362172962fe8f07e6fc6c76 /net/tipc/socket.c
parente9f8b10101c6da3ab000a2fb17162374c9bd2c69 (diff)
tipc: refactor function tipc_sk_recv_stream()
We try to make this function more readable by improving variable names and comments, using more stack variables, and doing some smaller changes to the logics. We also rename the function to make it consistent with naming conventions used elsewhere in the code. Reviewed-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c155
1 files changed, 71 insertions, 84 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3855bfd1fb1b..7e45ef938c18 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1375,9 +1375,9 @@ exit:
1375} 1375}
1376 1376
1377/** 1377/**
1378 * tipc_recv_stream - receive stream-oriented data 1378 * tipc_recvstream - receive stream-oriented data
1379 * @m: descriptor for message info 1379 * @m: descriptor for message info
1380 * @buf_len: total size of user buffer area 1380 * @buflen: total size of user buffer area
1381 * @flags: receive flags 1381 * @flags: receive flags
1382 * 1382 *
1383 * Used for SOCK_STREAM messages only. If not enough data is available 1383 * Used for SOCK_STREAM messages only. If not enough data is available
@@ -1385,111 +1385,98 @@ exit:
1385 * 1385 *
1386 * Returns size of returned message data, errno otherwise 1386 * Returns size of returned message data, errno otherwise
1387 */ 1387 */
1388static int tipc_recv_stream(struct socket *sock, struct msghdr *m, 1388static int tipc_recvstream(struct socket *sock, struct msghdr *m,
1389 size_t buf_len, int flags) 1389 size_t buflen, int flags)
1390{ 1390{
1391 struct sock *sk = sock->sk; 1391 struct sock *sk = sock->sk;
1392 struct tipc_sock *tsk = tipc_sk(sk); 1392 struct tipc_sock *tsk = tipc_sk(sk);
1393 struct sk_buff *buf; 1393 struct sk_buff *skb;
1394 struct tipc_msg *msg; 1394 struct tipc_msg *hdr;
1395 long timeo; 1395 struct tipc_skb_cb *skb_cb;
1396 unsigned int sz; 1396 bool peek = flags & MSG_PEEK;
1397 int target; 1397 int offset, required, copy, copied = 0;
1398 int sz_copied = 0; 1398 int hlen, dlen, err, rc;
1399 u32 err; 1399 long timeout;
1400 int res = 0, hlen;
1401 1400
1402 /* Catch invalid receive attempts */ 1401 /* Catch invalid receive attempts */
1403 if (unlikely(!buf_len)) 1402 if (unlikely(!buflen))
1404 return -EINVAL; 1403 return -EINVAL;
1405 1404
1406 lock_sock(sk); 1405 lock_sock(sk);
1407 1406
1408 if (unlikely(sk->sk_state == TIPC_OPEN)) { 1407 if (unlikely(sk->sk_state == TIPC_OPEN)) {
1409 res = -ENOTCONN; 1408 rc = -ENOTCONN;
1410 goto exit;
1411 }
1412
1413 target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
1414 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1415
1416restart:
1417 /* Look for a message in receive queue; wait if necessary */
1418 res = tipc_wait_for_rcvmsg(sock, &timeo);
1419 if (res)
1420 goto exit; 1409 goto exit;
1421
1422 /* Look at first message in receive queue */
1423 buf = skb_peek(&sk->sk_receive_queue);
1424 msg = buf_msg(buf);
1425 sz = msg_data_sz(msg);
1426 hlen = msg_hdr_sz(msg);
1427 err = msg_errcode(msg);
1428
1429 /* Discard an empty non-errored message & try again */
1430 if ((!sz) && (!err)) {
1431 tsk_advance_rx_queue(sk);
1432 goto restart;
1433 } 1410 }
1411 required = sock_rcvlowat(sk, flags & MSG_WAITALL, buflen);
1412 timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
1434 1413
1435 /* Optionally capture sender's address & ancillary data of first msg */ 1414 do {
1436 if (sz_copied == 0) { 1415 /* Look at first msg in receive queue; wait if necessary */
1437 set_orig_addr(m, msg); 1416 rc = tipc_wait_for_rcvmsg(sock, &timeout);
1438 res = tipc_sk_anc_data_recv(m, msg, tsk); 1417 if (unlikely(rc))
1439 if (res) 1418 break;
1440 goto exit; 1419 skb = skb_peek(&sk->sk_receive_queue);
1441 } 1420 skb_cb = TIPC_SKB_CB(skb);
1442 1421 hdr = buf_msg(skb);
1443 /* Capture message data (if valid) & compute return value (always) */ 1422 dlen = msg_data_sz(hdr);
1444 if (!err) { 1423 hlen = msg_hdr_sz(hdr);
1445 u32 offset = TIPC_SKB_CB(buf)->bytes_read; 1424 err = msg_errcode(hdr);
1446 u32 needed;
1447 int sz_to_copy;
1448
1449 sz -= offset;
1450 needed = (buf_len - sz_copied);
1451 sz_to_copy = min(sz, needed);
1452 1425
1453 res = skb_copy_datagram_msg(buf, hlen + offset, m, sz_to_copy); 1426 /* Discard any empty non-errored (SYN-) message */
1454 if (res) 1427 if (unlikely(!dlen && !err)) {
1455 goto exit; 1428 tsk_advance_rx_queue(sk);
1429 continue;
1430 }
1456 1431
1457 sz_copied += sz_to_copy; 1432 /* Collect msg meta data, incl. error code and rejected data */
1433 if (!copied) {
1434 set_orig_addr(m, hdr);
1435 rc = tipc_sk_anc_data_recv(m, hdr, tsk);
1436 if (rc)
1437 break;
1438 }
1458 1439
1459 if (sz_to_copy < sz) { 1440 /* Copy data if msg ok, otherwise return error/partial data */
1460 if (!(flags & MSG_PEEK)) 1441 if (likely(!err)) {
1461 TIPC_SKB_CB(buf)->bytes_read = 1442 offset = skb_cb->bytes_read;
1462 offset + sz_to_copy; 1443 copy = min_t(int, dlen - offset, buflen - copied);
1463 goto exit; 1444 rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
1445 if (unlikely(rc))
1446 break;
1447 copied += copy;
1448 offset += copy;
1449 if (unlikely(offset < dlen)) {
1450 if (!peek)
1451 skb_cb->bytes_read = offset;
1452 break;
1453 }
1454 } else {
1455 rc = 0;
1456 if ((err != TIPC_CONN_SHUTDOWN) && !m->msg_control)
1457 rc = -ECONNRESET;
1458 if (copied || rc)
1459 break;
1464 } 1460 }
1465 } else {
1466 if (sz_copied != 0)
1467 goto exit; /* can't add error msg to valid data */
1468 1461
1469 if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) 1462 if (unlikely(peek))
1470 res = 0; 1463 break;
1471 else
1472 res = -ECONNRESET;
1473 }
1474 1464
1475 if (unlikely(flags & MSG_PEEK)) 1465 tsk_advance_rx_queue(sk);
1476 goto exit;
1477 1466
1478 tsk->rcv_unacked += tsk_inc(tsk, hlen + msg_data_sz(msg)); 1467 /* Send connection flow control advertisement when applicable */
1479 if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4))) 1468 tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
1480 tipc_sk_send_ack(tsk); 1469 if (unlikely(tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE))
1481 tsk_advance_rx_queue(sk); 1470 tipc_sk_send_ack(tsk);
1482 1471
1483 /* Loop around if more data is required */ 1472 /* Exit if all requested data or FIN/error received */
1484 if ((sz_copied < buf_len) && /* didn't get all requested data */ 1473 if (copied == buflen || err)
1485 (!skb_queue_empty(&sk->sk_receive_queue) || 1474 break;
1486 (sz_copied < target)) && /* and more is ready or required */
1487 (!err)) /* and haven't reached a FIN */
1488 goto restart;
1489 1475
1476 } while (!skb_queue_empty(&sk->sk_receive_queue) || copied < required);
1490exit: 1477exit:
1491 release_sock(sk); 1478 release_sock(sk);
1492 return sz_copied ? sz_copied : res; 1479 return copied ? copied : rc;
1493} 1480}
1494 1481
1495/** 1482/**
@@ -2584,7 +2571,7 @@ static const struct proto_ops stream_ops = {
2584 .setsockopt = tipc_setsockopt, 2571 .setsockopt = tipc_setsockopt,
2585 .getsockopt = tipc_getsockopt, 2572 .getsockopt = tipc_getsockopt,
2586 .sendmsg = tipc_sendstream, 2573 .sendmsg = tipc_sendstream,
2587 .recvmsg = tipc_recv_stream, 2574 .recvmsg = tipc_recvstream,
2588 .mmap = sock_no_mmap, 2575 .mmap = sock_no_mmap,
2589 .sendpage = sock_no_sendpage 2576 .sendpage = sock_no_sendpage
2590}; 2577};