diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
| commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
| tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /net/tipc/node.c | |
| parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
| parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) | |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'net/tipc/node.c')
| -rw-r--r-- | net/tipc/node.c | 115 |
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 | ||
| 49 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str); | 49 | void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str); |
| 50 | static void node_lost_contact(struct node *n_ptr); | 50 | static void node_lost_contact(struct tipc_node *n_ptr); |
| 51 | static void node_established_contact(struct node *n_ptr); | 51 | static void node_established_contact(struct tipc_node *n_ptr); |
| 52 | 52 | ||
| 53 | struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ | 53 | struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ |
| 54 | |||
| 55 | static DEFINE_SPINLOCK(node_create_lock); | ||
| 54 | 56 | ||
| 55 | u32 tipc_own_tag = 0; | 57 | u32 tipc_own_tag = 0; |
| 56 | 58 | ||
| 57 | struct 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 | |||
| 69 | struct 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 | ||
| 97 | void tipc_node_delete(struct node *n_ptr) | 123 | void 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 | ||
| 123 | void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) | 149 | void 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 | ||
| 157 | static void node_select_active_links(struct node *n_ptr) | 183 | static 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 | ||
| 185 | void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr) | 211 | void 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 | ||
| 212 | int tipc_node_has_active_links(struct node *n_ptr) | 238 | int 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 | ||
| 218 | int tipc_node_has_redundant_links(struct node *n_ptr) | 244 | int 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 | ||
| 223 | static int tipc_node_has_active_routes(struct node *n_ptr) | 249 | static 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 | ||
| 228 | int tipc_node_is_up(struct node *n_ptr) | 254 | int 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 | ||
| 233 | struct node *tipc_node_attach_link(struct link *l_ptr) | 259 | struct 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 | ||
| 262 | void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr) | 288 | void 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 | ||
| 315 | static void node_established_contact(struct node *n_ptr) | 341 | static 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 | ||
| 361 | static void node_lost_contact(struct node *n_ptr) | 387 | static 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 | ||
| 443 | struct node *tipc_node_select_next_hop(u32 addr, u32 selector) | 469 | struct 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 | ||
| 490 | u32 tipc_node_select_router(struct node *n_ptr, u32 ref) | 516 | u32 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 | ||
| 528 | void tipc_node_add_router(struct node *n_ptr, u32 router) | 554 | void 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 | ||
| 539 | void tipc_node_remove_router(struct node *n_ptr, u32 router) | 565 | void 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 |
| 557 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str) | 583 | void 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 | ||
| 572 | u32 tipc_available_nodes(const u32 domain) | 598 | u32 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 | } |
