diff options
author | Jon Maloy <jon.maloy@ericsson.com> | 2018-01-08 15:03:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-09 12:35:58 -0500 |
commit | eb929a91b213d2a72c5a8b4af9a1acf63bfb8287 (patch) | |
tree | 9562eb2a8fc216296ce455d4b124ada6b13ca965 /net/tipc/socket.c | |
parent | 232d07b74a33b9f5d48516dc1d8ce41723ada593 (diff) |
tipc: improve poll() for group member socket
The current criteria for returning POLLOUT from a group member socket is
too simplistic. It basically returns POLLOUT as soon as the group has
external destinations, something obviously leading to a lot of spinning
during destination congestion situations. At the same time, the internal
congestion handling is unnecessarily complex.
We now change this as follows.
- We introduce an 'open' flag in struct tipc_group. This flag is used
only to help poll() get the setting of POLLOUT right, and *not* for
congeston handling as such. This means that a user can choose to
ignore an EAGAIN for a destination and go on sending messages to
other destinations in the group if he wants to.
- The flag is set to false every time we return EAGAIN on a send call.
- The flag is set to true every time any member, i.e., not necessarily
the member that caused EAGAIN, is removed from the small_win list.
- We remove the group member 'usr_pending' flag. The size of the send
window and presence in the 'small_win' list is sufficient criteria
for recognizing congestion.
This solution seems to be a reasonable compromise between 'anycast',
which is normally not waiting for POLLOUT for a specific destination,
and the other three send modes, which are.
Acked-by: Ying Xue <ying.xue@windriver.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.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index b24dab3996c9..1f236271766c 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -715,7 +715,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, | |||
715 | { | 715 | { |
716 | struct sock *sk = sock->sk; | 716 | struct sock *sk = sock->sk; |
717 | struct tipc_sock *tsk = tipc_sk(sk); | 717 | struct tipc_sock *tsk = tipc_sk(sk); |
718 | struct tipc_group *grp = tsk->group; | 718 | struct tipc_group *grp; |
719 | u32 revents = 0; | 719 | u32 revents = 0; |
720 | 720 | ||
721 | sock_poll_wait(file, sk_sleep(sk), wait); | 721 | sock_poll_wait(file, sk_sleep(sk), wait); |
@@ -736,9 +736,9 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, | |||
736 | revents |= POLLIN | POLLRDNORM; | 736 | revents |= POLLIN | POLLRDNORM; |
737 | break; | 737 | break; |
738 | case TIPC_OPEN: | 738 | case TIPC_OPEN: |
739 | if (!grp || tipc_group_size(grp)) | 739 | grp = tsk->group; |
740 | if (!tsk->cong_link_cnt) | 740 | if ((!grp || tipc_group_is_open(grp)) && !tsk->cong_link_cnt) |
741 | revents |= POLLOUT; | 741 | revents |= POLLOUT; |
742 | if (!tipc_sk_type_connectionless(sk)) | 742 | if (!tipc_sk_type_connectionless(sk)) |
743 | break; | 743 | break; |
744 | if (skb_queue_empty(&sk->sk_receive_queue)) | 744 | if (skb_queue_empty(&sk->sk_receive_queue)) |