diff options
author | Ying Xue <ying.xue@windriver.com> | 2014-03-27 00:54:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-27 13:08:37 -0400 |
commit | 6c7a762e70637a256229f9dc9ca793908e8bd01b (patch) | |
tree | ad8c61e1fa48fdc36e799be6f8f67d257ee080b1 /net/tipc | |
parent | 46651c59c483f14fd35cf7df2104feac0e54e258 (diff) |
tipc: tipc: convert node list and node hlist to RCU lists
Convert tipc_node_list list and node_htable hash list to RCU lists.
On read side, the two lists are protected with RCU read lock, and
on update side, node_list_lock is applied to them.
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/link.c | 16 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 6 | ||||
-rw-r--r-- | net/tipc/node.c | 28 | ||||
-rw-r--r-- | net/tipc/node.h | 2 |
4 files changed, 31 insertions, 21 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 882c5c9c52f9..c5190ab75290 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -280,13 +280,13 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
280 | return l_ptr; | 280 | return l_ptr; |
281 | } | 281 | } |
282 | 282 | ||
283 | |||
284 | void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) | 283 | void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) |
285 | { | 284 | { |
286 | struct tipc_link *l_ptr; | 285 | struct tipc_link *l_ptr; |
287 | struct tipc_node *n_ptr; | 286 | struct tipc_node *n_ptr; |
288 | 287 | ||
289 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 288 | rcu_read_lock(); |
289 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
290 | spin_lock_bh(&n_ptr->lock); | 290 | spin_lock_bh(&n_ptr->lock); |
291 | l_ptr = n_ptr->links[bearer_id]; | 291 | l_ptr = n_ptr->links[bearer_id]; |
292 | if (l_ptr) { | 292 | if (l_ptr) { |
@@ -309,6 +309,7 @@ void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) | |||
309 | } | 309 | } |
310 | spin_unlock_bh(&n_ptr->lock); | 310 | spin_unlock_bh(&n_ptr->lock); |
311 | } | 311 | } |
312 | rcu_read_unlock(); | ||
312 | } | 313 | } |
313 | 314 | ||
314 | /** | 315 | /** |
@@ -461,13 +462,15 @@ void tipc_link_reset_list(unsigned int bearer_id) | |||
461 | struct tipc_link *l_ptr; | 462 | struct tipc_link *l_ptr; |
462 | struct tipc_node *n_ptr; | 463 | struct tipc_node *n_ptr; |
463 | 464 | ||
464 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 465 | rcu_read_lock(); |
466 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
465 | spin_lock_bh(&n_ptr->lock); | 467 | spin_lock_bh(&n_ptr->lock); |
466 | l_ptr = n_ptr->links[bearer_id]; | 468 | l_ptr = n_ptr->links[bearer_id]; |
467 | if (l_ptr) | 469 | if (l_ptr) |
468 | tipc_link_reset(l_ptr); | 470 | tipc_link_reset(l_ptr); |
469 | spin_unlock_bh(&n_ptr->lock); | 471 | spin_unlock_bh(&n_ptr->lock); |
470 | } | 472 | } |
473 | rcu_read_unlock(); | ||
471 | } | 474 | } |
472 | 475 | ||
473 | static void link_activate(struct tipc_link *l_ptr) | 476 | static void link_activate(struct tipc_link *l_ptr) |
@@ -2404,13 +2407,12 @@ static struct tipc_node *tipc_link_find_owner(const char *link_name, | |||
2404 | { | 2407 | { |
2405 | struct tipc_link *l_ptr; | 2408 | struct tipc_link *l_ptr; |
2406 | struct tipc_node *n_ptr; | 2409 | struct tipc_node *n_ptr; |
2407 | struct tipc_node *tmp_n_ptr; | ||
2408 | struct tipc_node *found_node = 0; | 2410 | struct tipc_node *found_node = 0; |
2409 | |||
2410 | int i; | 2411 | int i; |
2411 | 2412 | ||
2412 | *bearer_id = 0; | 2413 | *bearer_id = 0; |
2413 | list_for_each_entry_safe(n_ptr, tmp_n_ptr, &tipc_node_list, list) { | 2414 | rcu_read_lock(); |
2415 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
2414 | tipc_node_lock(n_ptr); | 2416 | tipc_node_lock(n_ptr); |
2415 | for (i = 0; i < MAX_BEARERS; i++) { | 2417 | for (i = 0; i < MAX_BEARERS; i++) { |
2416 | l_ptr = n_ptr->links[i]; | 2418 | l_ptr = n_ptr->links[i]; |
@@ -2424,6 +2426,8 @@ static struct tipc_node *tipc_link_find_owner(const char *link_name, | |||
2424 | if (found_node) | 2426 | if (found_node) |
2425 | break; | 2427 | break; |
2426 | } | 2428 | } |
2429 | rcu_read_unlock(); | ||
2430 | |||
2427 | return found_node; | 2431 | return found_node; |
2428 | } | 2432 | } |
2429 | 2433 | ||
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c5904d196cd3..aff8041dc157 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -133,8 +133,8 @@ static void named_cluster_distribute(struct sk_buff *buf) | |||
133 | struct tipc_node *n_ptr; | 133 | struct tipc_node *n_ptr; |
134 | struct tipc_link *l_ptr; | 134 | struct tipc_link *l_ptr; |
135 | 135 | ||
136 | read_lock_bh(&tipc_net_lock); | 136 | rcu_read_lock(); |
137 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 137 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { |
138 | spin_lock_bh(&n_ptr->lock); | 138 | spin_lock_bh(&n_ptr->lock); |
139 | l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | 139 | l_ptr = n_ptr->active_links[n_ptr->addr & 1]; |
140 | if (l_ptr) { | 140 | if (l_ptr) { |
@@ -148,7 +148,7 @@ static void named_cluster_distribute(struct sk_buff *buf) | |||
148 | } | 148 | } |
149 | spin_unlock_bh(&n_ptr->lock); | 149 | spin_unlock_bh(&n_ptr->lock); |
150 | } | 150 | } |
151 | read_unlock_bh(&tipc_net_lock); | 151 | rcu_read_unlock(); |
152 | 152 | ||
153 | kfree_skb(buf); | 153 | kfree_skb(buf); |
154 | } | 154 | } |
diff --git a/net/tipc/node.c b/net/tipc/node.c index ec8360736239..4f517ff783d9 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -72,14 +72,14 @@ struct tipc_node *tipc_node_find(u32 addr) | |||
72 | if (unlikely(!in_own_cluster_exact(addr))) | 72 | if (unlikely(!in_own_cluster_exact(addr))) |
73 | return NULL; | 73 | return NULL; |
74 | 74 | ||
75 | spin_lock_bh(&node_list_lock); | 75 | rcu_read_lock(); |
76 | hlist_for_each_entry(node, &node_htable[tipc_hashfn(addr)], hash) { | 76 | hlist_for_each_entry_rcu(node, &node_htable[tipc_hashfn(addr)], hash) { |
77 | if (node->addr == addr) { | 77 | if (node->addr == addr) { |
78 | spin_unlock_bh(&node_list_lock); | 78 | rcu_read_unlock(); |
79 | return node; | 79 | return node; |
80 | } | 80 | } |
81 | } | 81 | } |
82 | spin_unlock_bh(&node_list_lock); | 82 | rcu_read_unlock(); |
83 | return NULL; | 83 | return NULL; |
84 | } | 84 | } |
85 | 85 | ||
@@ -102,13 +102,13 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
102 | INIT_LIST_HEAD(&n_ptr->list); | 102 | INIT_LIST_HEAD(&n_ptr->list); |
103 | INIT_LIST_HEAD(&n_ptr->nsub); | 103 | INIT_LIST_HEAD(&n_ptr->nsub); |
104 | 104 | ||
105 | hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); | 105 | hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
106 | 106 | ||
107 | list_for_each_entry(temp_node, &tipc_node_list, list) { | 107 | list_for_each_entry_rcu(temp_node, &tipc_node_list, list) { |
108 | if (n_ptr->addr < temp_node->addr) | 108 | if (n_ptr->addr < temp_node->addr) |
109 | break; | 109 | break; |
110 | } | 110 | } |
111 | list_add_tail(&n_ptr->list, &temp_node->list); | 111 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); |
112 | n_ptr->block_setup = WAIT_PEER_DOWN; | 112 | n_ptr->block_setup = WAIT_PEER_DOWN; |
113 | n_ptr->signature = INVALID_NODE_SIG; | 113 | n_ptr->signature = INVALID_NODE_SIG; |
114 | 114 | ||
@@ -120,9 +120,9 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
120 | 120 | ||
121 | static void tipc_node_delete(struct tipc_node *n_ptr) | 121 | static void tipc_node_delete(struct tipc_node *n_ptr) |
122 | { | 122 | { |
123 | list_del(&n_ptr->list); | 123 | list_del_rcu(&n_ptr->list); |
124 | hlist_del(&n_ptr->hash); | 124 | hlist_del_rcu(&n_ptr->hash); |
125 | kfree(n_ptr); | 125 | kfree_rcu(n_ptr, rcu); |
126 | 126 | ||
127 | tipc_num_nodes--; | 127 | tipc_num_nodes--; |
128 | } | 128 | } |
@@ -359,7 +359,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
359 | } | 359 | } |
360 | 360 | ||
361 | /* Add TLVs for all nodes in scope */ | 361 | /* Add TLVs for all nodes in scope */ |
362 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 362 | rcu_read_lock(); |
363 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
363 | if (!tipc_in_scope(domain, n_ptr->addr)) | 364 | if (!tipc_in_scope(domain, n_ptr->addr)) |
364 | continue; | 365 | continue; |
365 | node_info.addr = htonl(n_ptr->addr); | 366 | node_info.addr = htonl(n_ptr->addr); |
@@ -367,6 +368,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
367 | tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, | 368 | tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, |
368 | &node_info, sizeof(node_info)); | 369 | &node_info, sizeof(node_info)); |
369 | } | 370 | } |
371 | rcu_read_unlock(); | ||
370 | spin_unlock_bh(&node_list_lock); | 372 | spin_unlock_bh(&node_list_lock); |
371 | return buf; | 373 | return buf; |
372 | } | 374 | } |
@@ -412,7 +414,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
412 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); | 414 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); |
413 | 415 | ||
414 | /* Add TLVs for any other links in scope */ | 416 | /* Add TLVs for any other links in scope */ |
415 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 417 | rcu_read_lock(); |
418 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
416 | u32 i; | 419 | u32 i; |
417 | 420 | ||
418 | if (!tipc_in_scope(domain, n_ptr->addr)) | 421 | if (!tipc_in_scope(domain, n_ptr->addr)) |
@@ -429,6 +432,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
429 | } | 432 | } |
430 | tipc_node_unlock(n_ptr); | 433 | tipc_node_unlock(n_ptr); |
431 | } | 434 | } |
435 | rcu_read_unlock(); | ||
432 | spin_unlock_bh(&node_list_lock); | 436 | spin_unlock_bh(&node_list_lock); |
433 | return buf; | 437 | return buf; |
434 | } | 438 | } |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 42038690c540..7cbb8cec1a93 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -66,6 +66,7 @@ | |||
66 | * @link_cnt: number of links to node | 66 | * @link_cnt: number of links to node |
67 | * @signature: node instance identifier | 67 | * @signature: node instance identifier |
68 | * @bclink: broadcast-related info | 68 | * @bclink: broadcast-related info |
69 | * @rcu: rcu struct for tipc_node | ||
69 | * @acked: sequence # of last outbound b'cast message acknowledged by node | 70 | * @acked: sequence # of last outbound b'cast message acknowledged by node |
70 | * @last_in: sequence # of last in-sequence b'cast message received from node | 71 | * @last_in: sequence # of last in-sequence b'cast message received from node |
71 | * @last_sent: sequence # of last b'cast message sent by node | 72 | * @last_sent: sequence # of last b'cast message sent by node |
@@ -89,6 +90,7 @@ struct tipc_node { | |||
89 | int working_links; | 90 | int working_links; |
90 | int block_setup; | 91 | int block_setup; |
91 | u32 signature; | 92 | u32 signature; |
93 | struct rcu_head rcu; | ||
92 | struct { | 94 | struct { |
93 | u32 acked; | 95 | u32 acked; |
94 | u32 last_in; | 96 | u32 last_in; |