diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/name_distr.c | 6 | ||||
| -rw-r--r-- | net/tipc/net.c | 15 | ||||
| -rw-r--r-- | net/tipc/net.h | 4 | ||||
| -rw-r--r-- | net/tipc/node.c | 70 | ||||
| -rw-r--r-- | net/tipc/node.h | 30 |
5 files changed, 70 insertions, 55 deletions
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index f2086f684b34..1b70d5d051d0 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
| @@ -109,11 +109,9 @@ static void named_cluster_distribute(struct sk_buff *buf) | |||
| 109 | { | 109 | { |
| 110 | struct sk_buff *buf_copy; | 110 | struct sk_buff *buf_copy; |
| 111 | struct tipc_node *n_ptr; | 111 | struct tipc_node *n_ptr; |
| 112 | u32 n_num; | ||
| 113 | 112 | ||
| 114 | for (n_num = 1; n_num <= tipc_highest_node; n_num++) { | 113 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
| 115 | n_ptr = tipc_nodes[n_num]; | 114 | if (tipc_node_has_active_links(n_ptr)) { |
| 116 | if (n_ptr && tipc_node_has_active_links(n_ptr)) { | ||
| 117 | buf_copy = skb_copy(buf, GFP_ATOMIC); | 115 | buf_copy = skb_copy(buf, GFP_ATOMIC); |
| 118 | if (!buf_copy) | 116 | if (!buf_copy) |
| 119 | break; | 117 | break; |
diff --git a/net/tipc/net.c b/net/tipc/net.c index b5b337f5516d..cce8d086f173 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "name_distr.h" | 39 | #include "name_distr.h" |
| 40 | #include "subscr.h" | 40 | #include "subscr.h" |
| 41 | #include "port.h" | 41 | #include "port.h" |
| 42 | #include "node.h" | ||
| 42 | #include "config.h" | 43 | #include "config.h" |
| 43 | 44 | ||
| 44 | /* | 45 | /* |
| @@ -108,27 +109,21 @@ | |||
| 108 | */ | 109 | */ |
| 109 | 110 | ||
| 110 | DEFINE_RWLOCK(tipc_net_lock); | 111 | DEFINE_RWLOCK(tipc_net_lock); |
| 111 | struct tipc_node **tipc_nodes; | ||
| 112 | u32 tipc_highest_node; | ||
| 113 | atomic_t tipc_num_links; | 112 | atomic_t tipc_num_links; |
| 114 | 113 | ||
| 115 | static int net_start(void) | 114 | static int net_start(void) |
| 116 | { | 115 | { |
| 117 | tipc_nodes = kcalloc(4096, sizeof(*tipc_nodes), GFP_ATOMIC); | ||
| 118 | tipc_highest_node = 0; | ||
| 119 | atomic_set(&tipc_num_links, 0); | 116 | atomic_set(&tipc_num_links, 0); |
| 120 | 117 | ||
| 121 | return tipc_nodes ? 0 : -ENOMEM; | 118 | return 0; |
| 122 | } | 119 | } |
| 123 | 120 | ||
| 124 | static void net_stop(void) | 121 | static void net_stop(void) |
| 125 | { | 122 | { |
| 126 | u32 n_num; | 123 | struct tipc_node *node, *t_node; |
| 127 | 124 | ||
| 128 | for (n_num = 1; n_num <= tipc_highest_node; n_num++) | 125 | list_for_each_entry_safe(node, t_node, &tipc_node_list, list) |
| 129 | tipc_node_delete(tipc_nodes[n_num]); | 126 | tipc_node_delete(node); |
| 130 | kfree(tipc_nodes); | ||
| 131 | tipc_nodes = NULL; | ||
| 132 | } | 127 | } |
| 133 | 128 | ||
| 134 | static void net_route_named_msg(struct sk_buff *buf) | 129 | static void net_route_named_msg(struct sk_buff *buf) |
diff --git a/net/tipc/net.h b/net/tipc/net.h index b52b9748b5e2..0ba6093fb6ce 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
| @@ -37,10 +37,6 @@ | |||
| 37 | #ifndef _TIPC_NET_H | 37 | #ifndef _TIPC_NET_H |
| 38 | #define _TIPC_NET_H | 38 | #define _TIPC_NET_H |
| 39 | 39 | ||
| 40 | struct tipc_node; | ||
| 41 | |||
| 42 | extern struct tipc_node **tipc_nodes; | ||
| 43 | extern u32 tipc_highest_node; | ||
| 44 | extern atomic_t tipc_num_links; | 40 | extern atomic_t tipc_num_links; |
| 45 | 41 | ||
| 46 | extern rwlock_t tipc_net_lock; | 42 | extern rwlock_t tipc_net_lock; |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 64976f2e3c66..22aeb2b7ad00 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -44,9 +44,31 @@ static void node_established_contact(struct tipc_node *n_ptr); | |||
| 44 | 44 | ||
| 45 | static DEFINE_SPINLOCK(node_create_lock); | 45 | static DEFINE_SPINLOCK(node_create_lock); |
| 46 | 46 | ||
| 47 | static struct hlist_head node_htable[NODE_HTABLE_SIZE]; | ||
| 48 | LIST_HEAD(tipc_node_list); | ||
| 49 | static u32 tipc_num_nodes; | ||
| 47 | u32 tipc_own_tag; | 50 | u32 tipc_own_tag; |
| 48 | 51 | ||
| 49 | /** | 52 | /** |
| 53 | * tipc_node_find - locate specified node object, if it exists | ||
| 54 | */ | ||
| 55 | |||
| 56 | struct tipc_node *tipc_node_find(u32 addr) | ||
| 57 | { | ||
| 58 | struct tipc_node *node; | ||
| 59 | struct hlist_node *pos; | ||
| 60 | |||
| 61 | if (unlikely(!in_own_cluster(addr))) | ||
| 62 | return NULL; | ||
| 63 | |||
| 64 | hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { | ||
| 65 | if (node->addr == addr) | ||
| 66 | return node; | ||
| 67 | } | ||
| 68 | return NULL; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 50 | * tipc_node_create - create neighboring node | 72 | * tipc_node_create - create neighboring node |
| 51 | * | 73 | * |
| 52 | * Currently, this routine is called by neighbor discovery code, which holds | 74 | * Currently, this routine is called by neighbor discovery code, which holds |
| @@ -58,8 +80,7 @@ u32 tipc_own_tag; | |||
| 58 | 80 | ||
| 59 | struct tipc_node *tipc_node_create(u32 addr) | 81 | struct tipc_node *tipc_node_create(u32 addr) |
| 60 | { | 82 | { |
| 61 | struct tipc_node *n_ptr; | 83 | struct tipc_node *n_ptr, *temp_node; |
| 62 | u32 n_num; | ||
| 63 | 84 | ||
| 64 | spin_lock_bh(&node_create_lock); | 85 | spin_lock_bh(&node_create_lock); |
| 65 | 86 | ||
| @@ -78,12 +99,19 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
| 78 | 99 | ||
| 79 | n_ptr->addr = addr; | 100 | n_ptr->addr = addr; |
| 80 | spin_lock_init(&n_ptr->lock); | 101 | spin_lock_init(&n_ptr->lock); |
| 102 | INIT_HLIST_NODE(&n_ptr->hash); | ||
| 103 | INIT_LIST_HEAD(&n_ptr->list); | ||
| 81 | INIT_LIST_HEAD(&n_ptr->nsub); | 104 | INIT_LIST_HEAD(&n_ptr->nsub); |
| 82 | 105 | ||
| 83 | n_num = tipc_node(addr); | 106 | hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
| 84 | tipc_nodes[n_num] = n_ptr; | 107 | |
| 85 | if (n_num > tipc_highest_node) | 108 | list_for_each_entry(temp_node, &tipc_node_list, list) { |
| 86 | tipc_highest_node = n_num; | 109 | if (n_ptr->addr < temp_node->addr) |
| 110 | break; | ||
| 111 | } | ||
| 112 | list_add_tail(&n_ptr->list, &temp_node->list); | ||
| 113 | |||
| 114 | tipc_num_nodes++; | ||
| 87 | 115 | ||
| 88 | spin_unlock_bh(&node_create_lock); | 116 | spin_unlock_bh(&node_create_lock); |
| 89 | return n_ptr; | 117 | return n_ptr; |
| @@ -91,18 +119,11 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
| 91 | 119 | ||
| 92 | void tipc_node_delete(struct tipc_node *n_ptr) | 120 | void tipc_node_delete(struct tipc_node *n_ptr) |
| 93 | { | 121 | { |
| 94 | u32 n_num; | 122 | list_del(&n_ptr->list); |
| 95 | 123 | hlist_del(&n_ptr->hash); | |
| 96 | if (!n_ptr) | ||
| 97 | return; | ||
| 98 | |||
| 99 | n_num = tipc_node(n_ptr->addr); | ||
| 100 | tipc_nodes[n_num] = NULL; | ||
| 101 | kfree(n_ptr); | 124 | kfree(n_ptr); |
| 102 | 125 | ||
| 103 | while (!tipc_nodes[tipc_highest_node]) | 126 | tipc_num_nodes--; |
| 104 | if (--tipc_highest_node == 0) | ||
| 105 | break; | ||
| 106 | } | 127 | } |
| 107 | 128 | ||
| 108 | 129 | ||
| @@ -379,7 +400,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
| 379 | struct tipc_node *n_ptr; | 400 | struct tipc_node *n_ptr; |
| 380 | struct tipc_node_info node_info; | 401 | struct tipc_node_info node_info; |
| 381 | u32 payload_size; | 402 | u32 payload_size; |
| 382 | u32 n_num; | ||
| 383 | 403 | ||
| 384 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | 404 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
| 385 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 405 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| @@ -390,15 +410,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
| 390 | " (network address)"); | 410 | " (network address)"); |
| 391 | 411 | ||
| 392 | read_lock_bh(&tipc_net_lock); | 412 | read_lock_bh(&tipc_net_lock); |
| 393 | if (!tipc_nodes) { | 413 | if (!tipc_num_nodes) { |
| 394 | read_unlock_bh(&tipc_net_lock); | 414 | read_unlock_bh(&tipc_net_lock); |
| 395 | return tipc_cfg_reply_none(); | 415 | return tipc_cfg_reply_none(); |
| 396 | } | 416 | } |
| 397 | 417 | ||
| 398 | /* For now, get space for all other nodes */ | 418 | /* For now, get space for all other nodes */ |
| 399 | 419 | ||
| 400 | payload_size = TLV_SPACE(sizeof(node_info)) * | 420 | payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; |
| 401 | (tipc_highest_node - 1); | ||
| 402 | if (payload_size > 32768u) { | 421 | if (payload_size > 32768u) { |
| 403 | read_unlock_bh(&tipc_net_lock); | 422 | read_unlock_bh(&tipc_net_lock); |
| 404 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 423 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| @@ -412,9 +431,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
| 412 | 431 | ||
| 413 | /* Add TLVs for all nodes in scope */ | 432 | /* Add TLVs for all nodes in scope */ |
| 414 | 433 | ||
| 415 | for (n_num = 1; n_num <= tipc_highest_node; n_num++) { | 434 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
| 416 | n_ptr = tipc_nodes[n_num]; | 435 | if (!tipc_in_scope(domain, n_ptr->addr)) |
| 417 | if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) | ||
| 418 | continue; | 436 | continue; |
| 419 | node_info.addr = htonl(n_ptr->addr); | 437 | node_info.addr = htonl(n_ptr->addr); |
| 420 | node_info.up = htonl(tipc_node_is_up(n_ptr)); | 438 | node_info.up = htonl(tipc_node_is_up(n_ptr)); |
| @@ -433,7 +451,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 433 | struct tipc_node *n_ptr; | 451 | struct tipc_node *n_ptr; |
| 434 | struct tipc_link_info link_info; | 452 | struct tipc_link_info link_info; |
| 435 | u32 payload_size; | 453 | u32 payload_size; |
| 436 | u32 n_num; | ||
| 437 | 454 | ||
| 438 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | 455 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
| 439 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 456 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| @@ -472,11 +489,10 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 472 | 489 | ||
| 473 | /* Add TLVs for any other links in scope */ | 490 | /* Add TLVs for any other links in scope */ |
| 474 | 491 | ||
| 475 | for (n_num = 1; n_num <= tipc_highest_node; n_num++) { | 492 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
| 476 | u32 i; | 493 | u32 i; |
| 477 | 494 | ||
| 478 | n_ptr = tipc_nodes[n_num]; | 495 | if (!tipc_in_scope(domain, n_ptr->addr)) |
| 479 | if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) | ||
| 480 | continue; | 496 | continue; |
| 481 | tipc_node_lock(n_ptr); | 497 | tipc_node_lock(n_ptr); |
| 482 | for (i = 0; i < MAX_BEARERS; i++) { | 498 | for (i = 0; i < MAX_BEARERS; i++) { |
diff --git a/net/tipc/node.h b/net/tipc/node.h index c510a2afcc67..02e4927216fa 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/node.h: Include file for TIPC node management routines | 2 | * net/tipc/node.h: Include file for TIPC node management routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000-2006, Ericsson AB | 4 | * Copyright (c) 2000-2006, Ericsson AB |
| 5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| @@ -46,7 +46,8 @@ | |||
| 46 | * struct tipc_node - TIPC node structure | 46 | * struct tipc_node - TIPC node structure |
| 47 | * @addr: network address of node | 47 | * @addr: network address of node |
| 48 | * @lock: spinlock governing access to structure | 48 | * @lock: spinlock governing access to structure |
| 49 | * @next: pointer to next node in sorted list of cluster's nodes | 49 | * @hash: links to adjacent nodes in unsorted hash chain |
| 50 | * @list: links to adjacent nodes in sorted list of cluster's nodes | ||
| 50 | * @nsub: list of "node down" subscriptions monitoring node | 51 | * @nsub: list of "node down" subscriptions monitoring node |
| 51 | * @active_links: pointers to active links to node | 52 | * @active_links: pointers to active links to node |
| 52 | * @links: pointers to all links to node | 53 | * @links: pointers to all links to node |
| @@ -69,7 +70,8 @@ | |||
| 69 | struct tipc_node { | 70 | struct tipc_node { |
| 70 | u32 addr; | 71 | u32 addr; |
| 71 | spinlock_t lock; | 72 | spinlock_t lock; |
| 72 | struct tipc_node *next; | 73 | struct hlist_node hash; |
| 74 | struct list_head list; | ||
| 73 | struct list_head nsub; | 75 | struct list_head nsub; |
| 74 | struct link *active_links[2]; | 76 | struct link *active_links[2]; |
| 75 | struct link *links[MAX_BEARERS]; | 77 | struct link *links[MAX_BEARERS]; |
| @@ -90,8 +92,23 @@ struct tipc_node { | |||
| 90 | } bclink; | 92 | } bclink; |
| 91 | }; | 93 | }; |
| 92 | 94 | ||
| 95 | #define NODE_HTABLE_SIZE 512 | ||
| 96 | extern struct list_head tipc_node_list; | ||
| 97 | |||
| 98 | /* | ||
| 99 | * A trivial power-of-two bitmask technique is used for speed, since this | ||
| 100 | * operation is done for every incoming TIPC packet. The number of hash table | ||
| 101 | * entries has been chosen so that no hash chain exceeds 8 nodes and will | ||
| 102 | * usually be much smaller (typically only a single node). | ||
| 103 | */ | ||
| 104 | static inline unsigned int tipc_hashfn(u32 addr) | ||
| 105 | { | ||
| 106 | return addr & (NODE_HTABLE_SIZE - 1); | ||
| 107 | } | ||
| 108 | |||
| 93 | extern u32 tipc_own_tag; | 109 | extern u32 tipc_own_tag; |
| 94 | 110 | ||
| 111 | struct tipc_node *tipc_node_find(u32 addr); | ||
| 95 | struct tipc_node *tipc_node_create(u32 addr); | 112 | struct tipc_node *tipc_node_create(u32 addr); |
| 96 | void tipc_node_delete(struct tipc_node *n_ptr); | 113 | void tipc_node_delete(struct tipc_node *n_ptr); |
| 97 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr); | 114 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr); |
| @@ -104,13 +121,6 @@ int tipc_node_is_up(struct tipc_node *n_ptr); | |||
| 104 | struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); | 121 | struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); |
| 105 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); | 122 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); |
| 106 | 123 | ||
| 107 | static inline struct tipc_node *tipc_node_find(u32 addr) | ||
| 108 | { | ||
| 109 | if (likely(in_own_cluster(addr))) | ||
| 110 | return tipc_nodes[tipc_node(addr)]; | ||
| 111 | return NULL; | ||
| 112 | } | ||
| 113 | |||
| 114 | static inline void tipc_node_lock(struct tipc_node *n_ptr) | 124 | static inline void tipc_node_lock(struct tipc_node *n_ptr) |
| 115 | { | 125 | { |
| 116 | spin_lock_bh(&n_ptr->lock); | 126 | spin_lock_bh(&n_ptr->lock); |
