aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-08-22 18:09:07 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-23 14:18:33 -0400
commit50100a5e39461b2a61d6040e73c384766c29975d (patch)
tree7f632d0f22af7f38c282603e5c9f4de3139bce59 /net/tipc/socket.c
parent1dd0bd2b14032037d40a316dd52370f1713fa62b (diff)
tipc: use pseudo message to wake up sockets after link congestion
The current link implementation keeps a linked list of blocked ports/ sockets that is populated when there is link congestion. The purpose of this is to let the link know which users to wake up when the congestion abates. This adds unnecessary complexity to the data structure and the code, since it forces us to involve the link each time we want to delete a socket. It also forces us to grab the spinlock port_lock within the scope of node_lock. We want to get rid of this direct dependence, as well as the deadlock hazard resulting from the usage of port_lock. In this commit, we instead let the link keep list of a "wakeup" pseudo messages for use in such situations. Those messages are sent to the pending sockets via the ordinary message reception path, and wake up the socket's owner when they are received. This enables us to get rid of the 'waiting_ports' linked lists in struct tipc_port that manifest this direct reference. As a consequence, we can eliminate another BH entry into the socket, and hence the need to grab port_lock. This is a further step in our effort to remove port_lock altogether. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index ff8c8118d56e..a8be4d2001f7 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -579,6 +579,7 @@ new_mtu:
579 goto new_mtu; 579 goto new_mtu;
580 if (rc != -ELINKCONG) 580 if (rc != -ELINKCONG)
581 break; 581 break;
582 tipc_sk(sk)->link_cong = 1;
582 rc = tipc_wait_for_sndmsg(sock, &timeo); 583 rc = tipc_wait_for_sndmsg(sock, &timeo);
583 if (rc) 584 if (rc)
584 kfree_skb_list(buf); 585 kfree_skb_list(buf);
@@ -651,7 +652,7 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode,
651 conn_cong = tipc_sk_conn_cong(tsk); 652 conn_cong = tipc_sk_conn_cong(tsk);
652 tsk->sent_unacked -= msg_msgcnt(msg); 653 tsk->sent_unacked -= msg_msgcnt(msg);
653 if (conn_cong) 654 if (conn_cong)
654 tipc_sock_wakeup(tsk); 655 tsk->sk.sk_write_space(&tsk->sk);
655 } else if (msg_type(msg) == CONN_PROBE) { 656 } else if (msg_type(msg) == CONN_PROBE) {
656 if (!tipc_msg_reverse(buf, dnode, TIPC_OK)) 657 if (!tipc_msg_reverse(buf, dnode, TIPC_OK))
657 return TIPC_OK; 658 return TIPC_OK;
@@ -826,6 +827,7 @@ new_mtu:
826 goto exit; 827 goto exit;
827 828
828 do { 829 do {
830 TIPC_SKB_CB(buf)->wakeup_pending = tsk->link_cong;
829 rc = tipc_link_xmit(buf, dnode, tsk->port.ref); 831 rc = tipc_link_xmit(buf, dnode, tsk->port.ref);
830 if (likely(rc >= 0)) { 832 if (likely(rc >= 0)) {
831 if (sock->state != SS_READY) 833 if (sock->state != SS_READY)
@@ -835,10 +837,9 @@ new_mtu:
835 } 837 }
836 if (rc == -EMSGSIZE) 838 if (rc == -EMSGSIZE)
837 goto new_mtu; 839 goto new_mtu;
838
839 if (rc != -ELINKCONG) 840 if (rc != -ELINKCONG)
840 break; 841 break;
841 842 tsk->link_cong = 1;
842 rc = tipc_wait_for_sndmsg(sock, &timeo); 843 rc = tipc_wait_for_sndmsg(sock, &timeo);
843 if (rc) 844 if (rc)
844 kfree_skb_list(buf); 845 kfree_skb_list(buf);
@@ -953,6 +954,7 @@ next:
953 } 954 }
954 if (rc != -ELINKCONG) 955 if (rc != -ELINKCONG)
955 break; 956 break;
957 tsk->link_cong = 1;
956 } 958 }
957 rc = tipc_wait_for_sndpkt(sock, &timeo); 959 rc = tipc_wait_for_sndpkt(sock, &timeo);
958 if (rc) 960 if (rc)
@@ -1518,6 +1520,13 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf)
1518 if (unlikely(msg_user(msg) == CONN_MANAGER)) 1520 if (unlikely(msg_user(msg) == CONN_MANAGER))
1519 return tipc_sk_proto_rcv(tsk, &onode, buf); 1521 return tipc_sk_proto_rcv(tsk, &onode, buf);
1520 1522
1523 if (unlikely(msg_user(msg) == SOCK_WAKEUP)) {
1524 kfree_skb(buf);
1525 tsk->link_cong = 0;
1526 sk->sk_write_space(sk);
1527 return TIPC_OK;
1528 }
1529
1521 /* Reject message if it is wrong sort of message for socket */ 1530 /* Reject message if it is wrong sort of message for socket */
1522 if (msg_type(msg) > TIPC_DIRECT_MSG) 1531 if (msg_type(msg) > TIPC_DIRECT_MSG)
1523 return -TIPC_ERR_NO_PORT; 1532 return -TIPC_ERR_NO_PORT;