aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-08-23 14:18:41 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-23 14:18:41 -0400
commit5aa8dbbd5f9ae6ec6f5ab88596a29a5b5d4caf31 (patch)
treedd7368248aaf26d2476a54a345ede9f0db44eeb9 /net/tipc/node.c
parentf9474ddfaa009ead12bba44fa8fd49dc4536a124 (diff)
parent301bae56f21295a4ba71367818d80735687f11ac (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.c90
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;
50static u32 tipc_num_links; 51static u32 tipc_num_links;
51static DEFINE_SPINLOCK(node_list_lock); 52static DEFINE_SPINLOCK(node_list_lock);
52 53
54struct 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
149int 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
175void 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
197void 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)
474void tipc_node_unlock(struct tipc_node *node) 549void 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}