aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c115
1 files changed, 80 insertions, 35 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 598f4d3a0098..20d98c56e152 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -46,22 +46,46 @@
46#include "bearer.h" 46#include "bearer.h"
47#include "name_distr.h" 47#include "name_distr.h"
48 48
49void node_print(struct print_buf *buf, struct node *n_ptr, char *str); 49void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str);
50static void node_lost_contact(struct node *n_ptr); 50static void node_lost_contact(struct tipc_node *n_ptr);
51static void node_established_contact(struct node *n_ptr); 51static void node_established_contact(struct tipc_node *n_ptr);
52 52
53struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ 53struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */
54
55static DEFINE_SPINLOCK(node_create_lock);
54 56
55u32 tipc_own_tag = 0; 57u32 tipc_own_tag = 0;
56 58
57struct node *tipc_node_create(u32 addr) 59/**
60 * tipc_node_create - create neighboring node
61 *
62 * Currently, this routine is called by neighbor discovery code, which holds
63 * net_lock for reading only. We must take node_create_lock to ensure a node
64 * isn't created twice if two different bearers discover the node at the same
65 * time. (It would be preferable to switch to holding net_lock in write mode,
66 * but this is a non-trivial change.)
67 */
68
69struct tipc_node *tipc_node_create(u32 addr)
58{ 70{
59 struct cluster *c_ptr; 71 struct cluster *c_ptr;
60 struct node *n_ptr; 72 struct tipc_node *n_ptr;
61 struct node **curr_node; 73 struct tipc_node **curr_node;
74
75 spin_lock_bh(&node_create_lock);
76
77 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
78 if (addr < n_ptr->addr)
79 break;
80 if (addr == n_ptr->addr) {
81 spin_unlock_bh(&node_create_lock);
82 return n_ptr;
83 }
84 }
62 85
63 n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); 86 n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC);
64 if (!n_ptr) { 87 if (!n_ptr) {
88 spin_unlock_bh(&node_create_lock);
65 warn("Node creation failed, no memory\n"); 89 warn("Node creation failed, no memory\n");
66 return NULL; 90 return NULL;
67 } 91 }
@@ -71,6 +95,7 @@ struct node *tipc_node_create(u32 addr)
71 c_ptr = tipc_cltr_create(addr); 95 c_ptr = tipc_cltr_create(addr);
72 } 96 }
73 if (!c_ptr) { 97 if (!c_ptr) {
98 spin_unlock_bh(&node_create_lock);
74 kfree(n_ptr); 99 kfree(n_ptr);
75 return NULL; 100 return NULL;
76 } 101 }
@@ -91,10 +116,11 @@ struct node *tipc_node_create(u32 addr)
91 } 116 }
92 } 117 }
93 (*curr_node) = n_ptr; 118 (*curr_node) = n_ptr;
119 spin_unlock_bh(&node_create_lock);
94 return n_ptr; 120 return n_ptr;
95} 121}
96 122
97void tipc_node_delete(struct node *n_ptr) 123void tipc_node_delete(struct tipc_node *n_ptr)
98{ 124{
99 if (!n_ptr) 125 if (!n_ptr)
100 return; 126 return;
@@ -120,7 +146,7 @@ void tipc_node_delete(struct node *n_ptr)
120 * Link becomes active (alone or shared) or standby, depending on its priority. 146 * Link becomes active (alone or shared) or standby, depending on its priority.
121 */ 147 */
122 148
123void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) 149void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr)
124{ 150{
125 struct link **active = &n_ptr->active_links[0]; 151 struct link **active = &n_ptr->active_links[0];
126 152
@@ -154,7 +180,7 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
154 * node_select_active_links - select active link 180 * node_select_active_links - select active link
155 */ 181 */
156 182
157static void node_select_active_links(struct node *n_ptr) 183static void node_select_active_links(struct tipc_node *n_ptr)
158{ 184{
159 struct link **active = &n_ptr->active_links[0]; 185 struct link **active = &n_ptr->active_links[0];
160 u32 i; 186 u32 i;
@@ -182,7 +208,7 @@ static void node_select_active_links(struct node *n_ptr)
182 * tipc_node_link_down - handle loss of link 208 * tipc_node_link_down - handle loss of link
183 */ 209 */
184 210
185void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr) 211void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
186{ 212{
187 struct link **active; 213 struct link **active;
188 214
@@ -209,30 +235,30 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
209 node_lost_contact(n_ptr); 235 node_lost_contact(n_ptr);
210} 236}
211 237
212int tipc_node_has_active_links(struct node *n_ptr) 238int tipc_node_has_active_links(struct tipc_node *n_ptr)
213{ 239{
214 return (n_ptr && 240 return (n_ptr &&
215 ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); 241 ((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
216} 242}
217 243
218int tipc_node_has_redundant_links(struct node *n_ptr) 244int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
219{ 245{
220 return (n_ptr->working_links > 1); 246 return (n_ptr->working_links > 1);
221} 247}
222 248
223static int tipc_node_has_active_routes(struct node *n_ptr) 249static int tipc_node_has_active_routes(struct tipc_node *n_ptr)
224{ 250{
225 return (n_ptr && (n_ptr->last_router >= 0)); 251 return (n_ptr && (n_ptr->last_router >= 0));
226} 252}
227 253
228int tipc_node_is_up(struct node *n_ptr) 254int tipc_node_is_up(struct tipc_node *n_ptr)
229{ 255{
230 return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr)); 256 return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
231} 257}
232 258
233struct node *tipc_node_attach_link(struct link *l_ptr) 259struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
234{ 260{
235 struct node *n_ptr = tipc_node_find(l_ptr->addr); 261 struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr);
236 262
237 if (!n_ptr) 263 if (!n_ptr)
238 n_ptr = tipc_node_create(l_ptr->addr); 264 n_ptr = tipc_node_create(l_ptr->addr);
@@ -259,7 +285,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr)
259 return NULL; 285 return NULL;
260} 286}
261 287
262void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr) 288void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
263{ 289{
264 n_ptr->links[l_ptr->b_ptr->identity] = NULL; 290 n_ptr->links[l_ptr->b_ptr->identity] = NULL;
265 tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; 291 tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
@@ -312,7 +338,7 @@ void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
312 * 338 *
313 */ 339 */
314 340
315static void node_established_contact(struct node *n_ptr) 341static void node_established_contact(struct tipc_node *n_ptr)
316{ 342{
317 struct cluster *c_ptr; 343 struct cluster *c_ptr;
318 344
@@ -358,10 +384,10 @@ static void node_established_contact(struct node *n_ptr)
358 tipc_highest_allowed_slave); 384 tipc_highest_allowed_slave);
359} 385}
360 386
361static void node_lost_contact(struct node *n_ptr) 387static void node_lost_contact(struct tipc_node *n_ptr)
362{ 388{
363 struct cluster *c_ptr; 389 struct cluster *c_ptr;
364 struct node_subscr *ns, *tns; 390 struct tipc_node_subscr *ns, *tns;
365 char addr_string[16]; 391 char addr_string[16];
366 u32 i; 392 u32 i;
367 393
@@ -440,9 +466,9 @@ static void node_lost_contact(struct node *n_ptr)
440 * Called by when cluster local lookup has failed. 466 * Called by when cluster local lookup has failed.
441 */ 467 */
442 468
443struct node *tipc_node_select_next_hop(u32 addr, u32 selector) 469struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector)
444{ 470{
445 struct node *n_ptr; 471 struct tipc_node *n_ptr;
446 u32 router_addr; 472 u32 router_addr;
447 473
448 if (!tipc_addr_domain_valid(addr)) 474 if (!tipc_addr_domain_valid(addr))
@@ -487,7 +513,7 @@ struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
487 * Uses a deterministic and fair algorithm for selecting router node. 513 * Uses a deterministic and fair algorithm for selecting router node.
488 */ 514 */
489 515
490u32 tipc_node_select_router(struct node *n_ptr, u32 ref) 516u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref)
491{ 517{
492 u32 ulim; 518 u32 ulim;
493 u32 mask; 519 u32 mask;
@@ -525,7 +551,7 @@ u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
525 return tipc_addr(own_zone(), own_cluster(), r); 551 return tipc_addr(own_zone(), own_cluster(), r);
526} 552}
527 553
528void tipc_node_add_router(struct node *n_ptr, u32 router) 554void tipc_node_add_router(struct tipc_node *n_ptr, u32 router)
529{ 555{
530 u32 r_num = tipc_node(router); 556 u32 r_num = tipc_node(router);
531 557
@@ -536,7 +562,7 @@ void tipc_node_add_router(struct node *n_ptr, u32 router)
536 !n_ptr->routers[n_ptr->last_router]); 562 !n_ptr->routers[n_ptr->last_router]);
537} 563}
538 564
539void tipc_node_remove_router(struct node *n_ptr, u32 router) 565void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router)
540{ 566{
541 u32 r_num = tipc_node(router); 567 u32 r_num = tipc_node(router);
542 568
@@ -554,7 +580,7 @@ void tipc_node_remove_router(struct node *n_ptr, u32 router)
554} 580}
555 581
556#if 0 582#if 0
557void node_print(struct print_buf *buf, struct node *n_ptr, char *str) 583void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str)
558{ 584{
559 u32 i; 585 u32 i;
560 586
@@ -571,15 +597,17 @@ void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
571 597
572u32 tipc_available_nodes(const u32 domain) 598u32 tipc_available_nodes(const u32 domain)
573{ 599{
574 struct node *n_ptr; 600 struct tipc_node *n_ptr;
575 u32 cnt = 0; 601 u32 cnt = 0;
576 602
603 read_lock_bh(&tipc_net_lock);
577 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 604 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
578 if (!in_scope(domain, n_ptr->addr)) 605 if (!in_scope(domain, n_ptr->addr))
579 continue; 606 continue;
580 if (tipc_node_is_up(n_ptr)) 607 if (tipc_node_is_up(n_ptr))
581 cnt++; 608 cnt++;
582 } 609 }
610 read_unlock_bh(&tipc_net_lock);
583 return cnt; 611 return cnt;
584} 612}
585 613
@@ -587,7 +615,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
587{ 615{
588 u32 domain; 616 u32 domain;
589 struct sk_buff *buf; 617 struct sk_buff *buf;
590 struct node *n_ptr; 618 struct tipc_node *n_ptr;
591 struct tipc_node_info node_info; 619 struct tipc_node_info node_info;
592 u32 payload_size; 620 u32 payload_size;
593 621
@@ -599,19 +627,26 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
599 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 627 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
600 " (network address)"); 628 " (network address)");
601 629
602 if (!tipc_nodes) 630 read_lock_bh(&tipc_net_lock);
631 if (!tipc_nodes) {
632 read_unlock_bh(&tipc_net_lock);
603 return tipc_cfg_reply_none(); 633 return tipc_cfg_reply_none();
634 }
604 635
605 /* For now, get space for all other nodes 636 /* For now, get space for all other nodes
606 (will need to modify this when slave nodes are supported */ 637 (will need to modify this when slave nodes are supported */
607 638
608 payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); 639 payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1);
609 if (payload_size > 32768u) 640 if (payload_size > 32768u) {
641 read_unlock_bh(&tipc_net_lock);
610 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 642 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
611 " (too many nodes)"); 643 " (too many nodes)");
644 }
612 buf = tipc_cfg_reply_alloc(payload_size); 645 buf = tipc_cfg_reply_alloc(payload_size);
613 if (!buf) 646 if (!buf) {
647 read_unlock_bh(&tipc_net_lock);
614 return NULL; 648 return NULL;
649 }
615 650
616 /* Add TLVs for all nodes in scope */ 651 /* Add TLVs for all nodes in scope */
617 652
@@ -624,6 +659,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
624 &node_info, sizeof(node_info)); 659 &node_info, sizeof(node_info));
625 } 660 }
626 661
662 read_unlock_bh(&tipc_net_lock);
627 return buf; 663 return buf;
628} 664}
629 665
@@ -631,7 +667,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
631{ 667{
632 u32 domain; 668 u32 domain;
633 struct sk_buff *buf; 669 struct sk_buff *buf;
634 struct node *n_ptr; 670 struct tipc_node *n_ptr;
635 struct tipc_link_info link_info; 671 struct tipc_link_info link_info;
636 u32 payload_size; 672 u32 payload_size;
637 673
@@ -646,16 +682,22 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
646 if (tipc_mode != TIPC_NET_MODE) 682 if (tipc_mode != TIPC_NET_MODE)
647 return tipc_cfg_reply_none(); 683 return tipc_cfg_reply_none();
648 684
685 read_lock_bh(&tipc_net_lock);
686
649 /* Get space for all unicast links + multicast link */ 687 /* Get space for all unicast links + multicast link */
650 688
651 payload_size = TLV_SPACE(sizeof(link_info)) * 689 payload_size = TLV_SPACE(sizeof(link_info)) *
652 (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); 690 (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1);
653 if (payload_size > 32768u) 691 if (payload_size > 32768u) {
692 read_unlock_bh(&tipc_net_lock);
654 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 693 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
655 " (too many links)"); 694 " (too many links)");
695 }
656 buf = tipc_cfg_reply_alloc(payload_size); 696 buf = tipc_cfg_reply_alloc(payload_size);
657 if (!buf) 697 if (!buf) {
698 read_unlock_bh(&tipc_net_lock);
658 return NULL; 699 return NULL;
700 }
659 701
660 /* Add TLV for broadcast link */ 702 /* Add TLV for broadcast link */
661 703
@@ -671,6 +713,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
671 713
672 if (!in_scope(domain, n_ptr->addr)) 714 if (!in_scope(domain, n_ptr->addr))
673 continue; 715 continue;
716 tipc_node_lock(n_ptr);
674 for (i = 0; i < MAX_BEARERS; i++) { 717 for (i = 0; i < MAX_BEARERS; i++) {
675 if (!n_ptr->links[i]) 718 if (!n_ptr->links[i])
676 continue; 719 continue;
@@ -680,7 +723,9 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
680 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 723 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
681 &link_info, sizeof(link_info)); 724 &link_info, sizeof(link_info));
682 } 725 }
726 tipc_node_unlock(n_ptr);
683 } 727 }
684 728
729 read_unlock_bh(&tipc_net_lock);
685 return buf; 730 return buf;
686} 731}