diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 25ecf1201527..0a2eac309177 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -709,41 +709,43 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, | |||
709 | poll_table *wait) | 709 | poll_table *wait) |
710 | { | 710 | { |
711 | struct sock *sk = sock->sk; | 711 | struct sock *sk = sock->sk; |
712 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); | ||
712 | struct tipc_sock *tsk = tipc_sk(sk); | 713 | struct tipc_sock *tsk = tipc_sk(sk); |
713 | struct tipc_group *grp = tsk->group; | 714 | struct tipc_group *grp = tsk->group; |
714 | u32 mask = 0; | 715 | u32 revents = 0; |
715 | 716 | ||
716 | sock_poll_wait(file, sk_sleep(sk), wait); | 717 | sock_poll_wait(file, sk_sleep(sk), wait); |
717 | 718 | ||
718 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 719 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
719 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; | 720 | revents |= POLLRDHUP | POLLIN | POLLRDNORM; |
720 | if (sk->sk_shutdown == SHUTDOWN_MASK) | 721 | if (sk->sk_shutdown == SHUTDOWN_MASK) |
721 | mask |= POLLHUP; | 722 | revents |= POLLHUP; |
722 | 723 | ||
723 | switch (sk->sk_state) { | 724 | switch (sk->sk_state) { |
724 | case TIPC_ESTABLISHED: | 725 | case TIPC_ESTABLISHED: |
725 | if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk)) | 726 | if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk)) |
726 | mask |= POLLOUT; | 727 | revents |= POLLOUT; |
727 | /* fall thru' */ | 728 | /* fall thru' */ |
728 | case TIPC_LISTEN: | 729 | case TIPC_LISTEN: |
729 | case TIPC_CONNECTING: | 730 | case TIPC_CONNECTING: |
730 | if (!skb_queue_empty(&sk->sk_receive_queue)) | 731 | if (skb) |
731 | mask |= (POLLIN | POLLRDNORM); | 732 | revents |= POLLIN | POLLRDNORM; |
732 | break; | 733 | break; |
733 | case TIPC_OPEN: | 734 | case TIPC_OPEN: |
734 | if (!grp || tipc_group_size(grp)) | 735 | if (!grp || tipc_group_size(grp)) |
735 | if (!tsk->cong_link_cnt) | 736 | if (!tsk->cong_link_cnt) |
736 | mask |= POLLOUT; | 737 | revents |= POLLOUT; |
737 | if (tipc_sk_type_connectionless(sk) && | 738 | if (!tipc_sk_type_connectionless(sk)) |
738 | (!skb_queue_empty(&sk->sk_receive_queue))) | 739 | break; |
739 | mask |= (POLLIN | POLLRDNORM); | 740 | if (!skb) |
741 | break; | ||
742 | revents |= POLLIN | POLLRDNORM; | ||
740 | break; | 743 | break; |
741 | case TIPC_DISCONNECTING: | 744 | case TIPC_DISCONNECTING: |
742 | mask = (POLLIN | POLLRDNORM | POLLHUP); | 745 | revents = POLLIN | POLLRDNORM | POLLHUP; |
743 | break; | 746 | break; |
744 | } | 747 | } |
745 | 748 | return revents; | |
746 | return mask; | ||
747 | } | 749 | } |
748 | 750 | ||
749 | /** | 751 | /** |
@@ -1415,11 +1417,12 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, | |||
1415 | size_t buflen, int flags) | 1417 | size_t buflen, int flags) |
1416 | { | 1418 | { |
1417 | struct sock *sk = sock->sk; | 1419 | struct sock *sk = sock->sk; |
1418 | struct tipc_sock *tsk = tipc_sk(sk); | ||
1419 | struct sk_buff *skb; | ||
1420 | struct tipc_msg *hdr; | ||
1421 | bool connected = !tipc_sk_type_connectionless(sk); | 1420 | bool connected = !tipc_sk_type_connectionless(sk); |
1421 | struct tipc_sock *tsk = tipc_sk(sk); | ||
1422 | int rc, err, hlen, dlen, copy; | 1422 | int rc, err, hlen, dlen, copy; |
1423 | struct tipc_msg *hdr; | ||
1424 | struct sk_buff *skb; | ||
1425 | bool grp_evt; | ||
1423 | long timeout; | 1426 | long timeout; |
1424 | 1427 | ||
1425 | /* Catch invalid receive requests */ | 1428 | /* Catch invalid receive requests */ |
@@ -1443,6 +1446,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, | |||
1443 | dlen = msg_data_sz(hdr); | 1446 | dlen = msg_data_sz(hdr); |
1444 | hlen = msg_hdr_sz(hdr); | 1447 | hlen = msg_hdr_sz(hdr); |
1445 | err = msg_errcode(hdr); | 1448 | err = msg_errcode(hdr); |
1449 | grp_evt = msg_is_grp_evt(hdr); | ||
1446 | if (likely(dlen || err)) | 1450 | if (likely(dlen || err)) |
1447 | break; | 1451 | break; |
1448 | tsk_advance_rx_queue(sk); | 1452 | tsk_advance_rx_queue(sk); |
@@ -1469,11 +1473,20 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, | |||
1469 | if (unlikely(rc)) | 1473 | if (unlikely(rc)) |
1470 | goto exit; | 1474 | goto exit; |
1471 | 1475 | ||
1476 | /* Mark message as group event if applicable */ | ||
1477 | if (unlikely(grp_evt)) { | ||
1478 | if (msg_grp_evt(hdr) == TIPC_WITHDRAWN) | ||
1479 | m->msg_flags |= MSG_EOR; | ||
1480 | m->msg_flags |= MSG_OOB; | ||
1481 | copy = 0; | ||
1482 | } | ||
1483 | |||
1472 | /* Caption of data or error code/rejected data was successful */ | 1484 | /* Caption of data or error code/rejected data was successful */ |
1473 | if (unlikely(flags & MSG_PEEK)) | 1485 | if (unlikely(flags & MSG_PEEK)) |
1474 | goto exit; | 1486 | goto exit; |
1475 | 1487 | ||
1476 | tsk_advance_rx_queue(sk); | 1488 | tsk_advance_rx_queue(sk); |
1489 | |||
1477 | if (likely(!connected)) | 1490 | if (likely(!connected)) |
1478 | goto exit; | 1491 | goto exit; |
1479 | 1492 | ||
@@ -1648,10 +1661,10 @@ static void tipc_sk_proto_rcv(struct sock *sk, | |||
1648 | sk->sk_write_space(sk); | 1661 | sk->sk_write_space(sk); |
1649 | break; | 1662 | break; |
1650 | case GROUP_PROTOCOL: | 1663 | case GROUP_PROTOCOL: |
1651 | tipc_group_proto_rcv(grp, hdr, xmitq); | 1664 | tipc_group_proto_rcv(grp, hdr, inputq, xmitq); |
1652 | break; | 1665 | break; |
1653 | case TOP_SRV: | 1666 | case TOP_SRV: |
1654 | tipc_group_member_evt(tsk->group, skb, xmitq); | 1667 | tipc_group_member_evt(tsk->group, skb, inputq, xmitq); |
1655 | skb = NULL; | 1668 | skb = NULL; |
1656 | break; | 1669 | break; |
1657 | default: | 1670 | default: |