diff options
author | David S. Miller <davem@davemloft.net> | 2014-08-23 14:18:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-23 14:18:41 -0400 |
commit | 5aa8dbbd5f9ae6ec6f5ab88596a29a5b5d4caf31 (patch) | |
tree | dd7368248aaf26d2476a54a345ede9f0db44eeb9 /net/tipc/node.c | |
parent | f9474ddfaa009ead12bba44fa8fd49dc4536a124 (diff) | |
parent | 301bae56f21295a4ba71367818d80735687f11ac (diff) |
Merge branch 'tipc-next'
Jon Maloy says:
====================
tipc: Merge port and socket layer code
After the removal of the TIPC native interface, there is no reason to
keep a distinction between a "generic" port layer and a "specific"
socket layer in the code. Throughout the last months, we have posted
several series that aimed at facilitating removal of the port layer,
and in particular the port_lock spinlock, which in reality duplicates
the role normally kept by lock_sock()/bh_lock_sock().
In this series, we finalize this work, by making a significant number of
changes to the link, node, port and socket code, all with the aim of
reducing dependencies between the layers. In the final commits, we then
remove the port spinlock, port.c and port.h altogether.
After this series, we have a socket layer that has only few dependencies
to the rest of the stack, so that it should be possible to continue
cleanups of its code without significantly affecting other code.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index f7069299943f..17e6378c4dfe 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "config.h" | 38 | #include "config.h" |
39 | #include "node.h" | 39 | #include "node.h" |
40 | #include "name_distr.h" | 40 | #include "name_distr.h" |
41 | #include "socket.h" | ||
41 | 42 | ||
42 | #define NODE_HTABLE_SIZE 512 | 43 | #define NODE_HTABLE_SIZE 512 |
43 | 44 | ||
@@ -50,6 +51,13 @@ static u32 tipc_num_nodes; | |||
50 | static u32 tipc_num_links; | 51 | static u32 tipc_num_links; |
51 | static DEFINE_SPINLOCK(node_list_lock); | 52 | static DEFINE_SPINLOCK(node_list_lock); |
52 | 53 | ||
54 | struct tipc_sock_conn { | ||
55 | u32 port; | ||
56 | u32 peer_port; | ||
57 | u32 peer_node; | ||
58 | struct list_head list; | ||
59 | }; | ||
60 | |||
53 | /* | 61 | /* |
54 | * A trivial power-of-two bitmask technique is used for speed, since this | 62 | * A trivial power-of-two bitmask technique is used for speed, since this |
55 | * operation is done for every incoming TIPC packet. The number of hash table | 63 | * operation is done for every incoming TIPC packet. The number of hash table |
@@ -100,6 +108,8 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
100 | INIT_HLIST_NODE(&n_ptr->hash); | 108 | INIT_HLIST_NODE(&n_ptr->hash); |
101 | INIT_LIST_HEAD(&n_ptr->list); | 109 | INIT_LIST_HEAD(&n_ptr->list); |
102 | INIT_LIST_HEAD(&n_ptr->nsub); | 110 | INIT_LIST_HEAD(&n_ptr->nsub); |
111 | INIT_LIST_HEAD(&n_ptr->conn_sks); | ||
112 | __skb_queue_head_init(&n_ptr->waiting_sks); | ||
103 | 113 | ||
104 | hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); | 114 | hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
105 | 115 | ||
@@ -136,6 +146,71 @@ void tipc_node_stop(void) | |||
136 | spin_unlock_bh(&node_list_lock); | 146 | spin_unlock_bh(&node_list_lock); |
137 | } | 147 | } |
138 | 148 | ||
149 | int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port) | ||
150 | { | ||
151 | struct tipc_node *node; | ||
152 | struct tipc_sock_conn *conn; | ||
153 | |||
154 | if (in_own_node(dnode)) | ||
155 | return 0; | ||
156 | |||
157 | node = tipc_node_find(dnode); | ||
158 | if (!node) { | ||
159 | pr_warn("Connecting sock to node 0x%x failed\n", dnode); | ||
160 | return -EHOSTUNREACH; | ||
161 | } | ||
162 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); | ||
163 | if (!conn) | ||
164 | return -EHOSTUNREACH; | ||
165 | conn->peer_node = dnode; | ||
166 | conn->port = port; | ||
167 | conn->peer_port = peer_port; | ||
168 | |||
169 | tipc_node_lock(node); | ||
170 | list_add_tail(&conn->list, &node->conn_sks); | ||
171 | tipc_node_unlock(node); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | void tipc_node_remove_conn(u32 dnode, u32 port) | ||
176 | { | ||
177 | struct tipc_node *node; | ||
178 | struct tipc_sock_conn *conn, *safe; | ||
179 | |||
180 | if (in_own_node(dnode)) | ||
181 | return; | ||
182 | |||
183 | node = tipc_node_find(dnode); | ||
184 | if (!node) | ||
185 | return; | ||
186 | |||
187 | tipc_node_lock(node); | ||
188 | list_for_each_entry_safe(conn, safe, &node->conn_sks, list) { | ||
189 | if (port != conn->port) | ||
190 | continue; | ||
191 | list_del(&conn->list); | ||
192 | kfree(conn); | ||
193 | } | ||
194 | tipc_node_unlock(node); | ||
195 | } | ||
196 | |||
197 | void tipc_node_abort_sock_conns(struct list_head *conns) | ||
198 | { | ||
199 | struct tipc_sock_conn *conn, *safe; | ||
200 | struct sk_buff *buf; | ||
201 | |||
202 | list_for_each_entry_safe(conn, safe, conns, list) { | ||
203 | buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, | ||
204 | SHORT_H_SIZE, 0, tipc_own_addr, | ||
205 | conn->peer_node, conn->port, | ||
206 | conn->peer_port, TIPC_ERR_NO_NODE); | ||
207 | if (likely(buf)) | ||
208 | tipc_sk_rcv(buf); | ||
209 | list_del(&conn->list); | ||
210 | kfree(conn); | ||
211 | } | ||
212 | } | ||
213 | |||
139 | /** | 214 | /** |
140 | * tipc_node_link_up - handle addition of link | 215 | * tipc_node_link_up - handle addition of link |
141 | * | 216 | * |
@@ -474,6 +549,8 @@ int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len) | |||
474 | void tipc_node_unlock(struct tipc_node *node) | 549 | void tipc_node_unlock(struct tipc_node *node) |
475 | { | 550 | { |
476 | LIST_HEAD(nsub_list); | 551 | LIST_HEAD(nsub_list); |
552 | LIST_HEAD(conn_sks); | ||
553 | struct sk_buff_head waiting_sks; | ||
477 | u32 addr = 0; | 554 | u32 addr = 0; |
478 | 555 | ||
479 | if (likely(!node->action_flags)) { | 556 | if (likely(!node->action_flags)) { |
@@ -481,8 +558,14 @@ void tipc_node_unlock(struct tipc_node *node) | |||
481 | return; | 558 | return; |
482 | } | 559 | } |
483 | 560 | ||
561 | __skb_queue_head_init(&waiting_sks); | ||
562 | if (node->action_flags & TIPC_WAKEUP_USERS) { | ||
563 | skb_queue_splice_init(&node->waiting_sks, &waiting_sks); | ||
564 | node->action_flags &= ~TIPC_WAKEUP_USERS; | ||
565 | } | ||
484 | if (node->action_flags & TIPC_NOTIFY_NODE_DOWN) { | 566 | if (node->action_flags & TIPC_NOTIFY_NODE_DOWN) { |
485 | list_replace_init(&node->nsub, &nsub_list); | 567 | list_replace_init(&node->nsub, &nsub_list); |
568 | list_replace_init(&node->conn_sks, &conn_sks); | ||
486 | node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN; | 569 | node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN; |
487 | } | 570 | } |
488 | if (node->action_flags & TIPC_NOTIFY_NODE_UP) { | 571 | if (node->action_flags & TIPC_NOTIFY_NODE_UP) { |
@@ -491,8 +574,15 @@ void tipc_node_unlock(struct tipc_node *node) | |||
491 | } | 574 | } |
492 | spin_unlock_bh(&node->lock); | 575 | spin_unlock_bh(&node->lock); |
493 | 576 | ||
577 | while (!skb_queue_empty(&waiting_sks)) | ||
578 | tipc_sk_rcv(__skb_dequeue(&waiting_sks)); | ||
579 | |||
580 | if (!list_empty(&conn_sks)) | ||
581 | tipc_node_abort_sock_conns(&conn_sks); | ||
582 | |||
494 | if (!list_empty(&nsub_list)) | 583 | if (!list_empty(&nsub_list)) |
495 | tipc_nodesub_notify(&nsub_list); | 584 | tipc_nodesub_notify(&nsub_list); |
585 | |||
496 | if (addr) | 586 | if (addr) |
497 | tipc_named_node_up(addr); | 587 | tipc_named_node_up(addr); |
498 | } | 588 | } |