aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/net.c
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-04-20 22:55:48 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-22 21:17:53 -0400
commit7216cd949c9bd56a4ccd952c624ab68f8c9aa0a4 (patch)
tree9c4f86a2a04713294bbea8bbf9b19462f307f05b /net/tipc/net.c
parent2231c5af451e4b7ae3cc56eaa4653af6ede51109 (diff)
tipc: purge tipc_net_lock lock
Now tipc routing hierarchy comprises the structures 'node', 'link'and 'bearer'. The whole hierarchy is protected by a big read/write lock, tipc_net_lock, to ensure that nothing is added or removed while code is accessing any of these structures. Obviously the locking policy makes node, link and bearer components closely bound together so that their relationship becomes unnecessarily complex. In the worst case, such locking policy not only has a negative influence on performance, but also it's prone to lead to deadlock occasionally. In order o decouple the complex relationship between bearer and node as well as link, the locking policy is adjusted as follows: - Bearer level RTNL lock is used on update side, and RCU is used on read side. Meanwhile, all bearer instances including broadcast bearer are saved into bearer_list array. - Node and link level All node instances are saved into two tipc_node_list and node_htable lists. The two lists are protected by node_list_lock on write side, and they are guarded with RCU lock on read side. All members in node structure including link instances are protected by node spin lock. - The relationship between bearer and node When link accesses bearer, it first needs to find the bearer with its bearer identity from the bearer_list array. When bearer accesses node, it can iterate the node_htable hash list with the node address to find the corresponding node. In the new locking policy, every component has its private locking solution and the relationship between bearer and node is very simple, that is, they can find each other with node address or bearer identity from node_htable hash list or bearer_list array. Until now above all changes have been done, so tipc_net_lock can be removed safely. Signed-off-by: Ying Xue <ying.xue@windriver.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Tested-by: Erik Hugne <erik.hugne@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/net.c')
-rw-r--r--net/tipc/net.c59
1 files changed, 24 insertions, 35 deletions
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 24d2d21266a4..75bb39025d53 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -45,39 +45,34 @@
45/* 45/*
46 * The TIPC locking policy is designed to ensure a very fine locking 46 * The TIPC locking policy is designed to ensure a very fine locking
47 * granularity, permitting complete parallel access to individual 47 * granularity, permitting complete parallel access to individual
48 * port and node/link instances. The code consists of three major 48 * port and node/link instances. The code consists of four major
49 * locking domains, each protected with their own disjunct set of locks. 49 * locking domains, each protected with their own disjunct set of locks.
50 * 50 *
51 * 1: The routing hierarchy. 51 * 1: The bearer level.
52 * Comprises the structures 'zone', 'cluster', 'node', 'link' 52 * RTNL lock is used to serialize the process of configuring bearer
53 * and 'bearer'. The whole hierarchy is protected by a big 53 * on update side, and RCU lock is applied on read side to make
54 * read/write lock, tipc_net_lock, to enssure that nothing is added 54 * bearer instance valid on both paths of message transmission and
55 * or removed while code is accessing any of these structures. 55 * reception.
56 * This layer must not be called from the two others while they
57 * hold any of their own locks.
58 * Neither must it itself do any upcalls to the other two before
59 * it has released tipc_net_lock and other protective locks.
60 * 56 *
61 * Within the tipc_net_lock domain there are two sub-domains;'node' and 57 * 2: The node and link level.
62 * 'bearer', where local write operations are permitted, 58 * All node instances are saved into two tipc_node_list and node_htable
63 * provided that those are protected by individual spin_locks 59 * lists. The two lists are protected by node_list_lock on write side,
64 * per instance. Code holding tipc_net_lock(read) and a node spin_lock 60 * and they are guarded with RCU lock on read side. Especially node
65 * is permitted to poke around in both the node itself and its 61 * instance is destroyed only when TIPC module is removed, and we can
66 * subordinate links. I.e, it can update link counters and queues, 62 * confirm that there has no any user who is accessing the node at the
67 * change link state, send protocol messages, and alter the 63 * moment. Therefore, Except for iterating the two lists within RCU
68 * "active_links" array in the node; but it can _not_ remove a link 64 * protection, it's no needed to hold RCU that we access node instance
69 * or a node from the overall structure. 65 * in other places.
70 * Correspondingly, individual bearers may change status within a
71 * tipc_net_lock(read), protected by an individual spin_lock ber bearer
72 * instance, but it needs tipc_net_lock(write) to remove/add any bearers.
73 * 66 *
67 * In addition, all members in node structure including link instances
68 * are protected by node spin lock.
74 * 69 *
75 * 2: The transport level of the protocol. 70 * 3: The transport level of the protocol.
76 * This consists of the structures port, (and its user level 71 * This consists of the structures port, (and its user level
77 * representations, such as user_port and tipc_sock), reference and 72 * representations, such as user_port and tipc_sock), reference and
78 * tipc_user (port.c, reg.c, socket.c). 73 * tipc_user (port.c, reg.c, socket.c).
79 * 74 *
80 * This layer has four different locks: 75 * This layer has four different locks:
81 * - The tipc_port spin_lock. This is protecting each port instance 76 * - The tipc_port spin_lock. This is protecting each port instance
82 * from parallel data access and removal. Since we can not place 77 * from parallel data access and removal. Since we can not place
83 * this lock in the port itself, it has been placed in the 78 * this lock in the port itself, it has been placed in the
@@ -96,7 +91,7 @@
96 * There are two such lists; 'port_list', which is used for management, 91 * There are two such lists; 'port_list', which is used for management,
97 * and 'wait_list', which is used to queue ports during congestion. 92 * and 'wait_list', which is used to queue ports during congestion.
98 * 93 *
99 * 3: The name table (name_table.c, name_distr.c, subscription.c) 94 * 4: The name table (name_table.c, name_distr.c, subscription.c)
100 * - There is one big read/write-lock (tipc_nametbl_lock) protecting the 95 * - There is one big read/write-lock (tipc_nametbl_lock) protecting the
101 * overall name table structure. Nothing must be added/removed to 96 * overall name table structure. Nothing must be added/removed to
102 * this structure without holding write access to it. 97 * this structure without holding write access to it.
@@ -108,8 +103,6 @@
108 * - A local spin_lock protecting the queue of subscriber events. 103 * - A local spin_lock protecting the queue of subscriber events.
109*/ 104*/
110 105
111DEFINE_RWLOCK(tipc_net_lock);
112
113static void net_route_named_msg(struct sk_buff *buf) 106static void net_route_named_msg(struct sk_buff *buf)
114{ 107{
115 struct tipc_msg *msg = buf_msg(buf); 108 struct tipc_msg *msg = buf_msg(buf);
@@ -175,15 +168,13 @@ void tipc_net_start(u32 addr)
175{ 168{
176 char addr_string[16]; 169 char addr_string[16];
177 170
178 write_lock_bh(&tipc_net_lock);
179 tipc_own_addr = addr; 171 tipc_own_addr = addr;
180 tipc_named_reinit(); 172 tipc_named_reinit();
181 tipc_port_reinit(); 173 tipc_port_reinit();
182 tipc_bclink_init(); 174 tipc_bclink_init();
183 write_unlock_bh(&tipc_net_lock);
184
185 tipc_nametbl_publish(TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, 175 tipc_nametbl_publish(TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr,
186 TIPC_ZONE_SCOPE, 0, tipc_own_addr); 176 TIPC_ZONE_SCOPE, 0, tipc_own_addr);
177
187 pr_info("Started in network mode\n"); 178 pr_info("Started in network mode\n");
188 pr_info("Own node address %s, network identity %u\n", 179 pr_info("Own node address %s, network identity %u\n",
189 tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); 180 tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
@@ -196,11 +187,9 @@ void tipc_net_stop(void)
196 187
197 tipc_nametbl_withdraw(TIPC_CFG_SRV, tipc_own_addr, 0, tipc_own_addr); 188 tipc_nametbl_withdraw(TIPC_CFG_SRV, tipc_own_addr, 0, tipc_own_addr);
198 rtnl_lock(); 189 rtnl_lock();
199 write_lock_bh(&tipc_net_lock);
200 tipc_bearer_stop(); 190 tipc_bearer_stop();
201 tipc_bclink_stop(); 191 tipc_bclink_stop();
202 tipc_node_stop(); 192 tipc_node_stop();
203 write_unlock_bh(&tipc_net_lock);
204 rtnl_unlock(); 193 rtnl_unlock();
205 194
206 pr_info("Left network mode\n"); 195 pr_info("Left network mode\n");