diff options
Diffstat (limited to 'net/tipc/node.c')
| -rw-r--r-- | net/tipc/node.c | 125 | 
1 files changed, 58 insertions, 67 deletions
| diff --git a/net/tipc/node.c b/net/tipc/node.c index 3af53e327f4..2d106ef4fa4 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -2,7 +2,7 @@   * net/tipc/node.c: TIPC node management routines   *   * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005-2006, 2010-2011, Wind River Systems   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -44,9 +44,33 @@ static void node_established_contact(struct tipc_node *n_ptr);  static DEFINE_SPINLOCK(node_create_lock); +static struct hlist_head node_htable[NODE_HTABLE_SIZE]; +LIST_HEAD(tipc_node_list); +static u32 tipc_num_nodes; + +static atomic_t tipc_num_links = ATOMIC_INIT(0);  u32 tipc_own_tag;  /** + * tipc_node_find - locate specified node object, if it exists + */ + +struct tipc_node *tipc_node_find(u32 addr) +{ +	struct tipc_node *node; +	struct hlist_node *pos; + +	if (unlikely(!in_own_cluster(addr))) +		return NULL; + +	hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { +		if (node->addr == addr) +			return node; +	} +	return NULL; +} + +/**   * tipc_node_create - create neighboring node   *   * Currently, this routine is called by neighbor discovery code, which holds @@ -58,8 +82,7 @@ u32 tipc_own_tag;  struct tipc_node *tipc_node_create(u32 addr)  { -	struct tipc_node *n_ptr; -	u32 n_num; +	struct tipc_node *n_ptr, *temp_node;  	spin_lock_bh(&node_create_lock); @@ -78,12 +101,19 @@ struct tipc_node *tipc_node_create(u32 addr)  	n_ptr->addr = addr;  	spin_lock_init(&n_ptr->lock); +	INIT_HLIST_NODE(&n_ptr->hash); +	INIT_LIST_HEAD(&n_ptr->list);  	INIT_LIST_HEAD(&n_ptr->nsub); -	n_num = tipc_node(addr); -	tipc_net.nodes[n_num] = n_ptr; -	if (n_num > tipc_net.highest_node) -		tipc_net.highest_node = n_num; +	hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); + +	list_for_each_entry(temp_node, &tipc_node_list, list) { +		if (n_ptr->addr < temp_node->addr) +			break; +	} +	list_add_tail(&n_ptr->list, &temp_node->list); + +	tipc_num_nodes++;  	spin_unlock_bh(&node_create_lock);  	return n_ptr; @@ -91,18 +121,11 @@ struct tipc_node *tipc_node_create(u32 addr)  void tipc_node_delete(struct tipc_node *n_ptr)  { -	u32 n_num; - -	if (!n_ptr) -		return; - -	n_num = tipc_node(n_ptr->addr); -	tipc_net.nodes[n_num] = NULL; +	list_del(&n_ptr->list); +	hlist_del(&n_ptr->hash);  	kfree(n_ptr); -	while (!tipc_net.nodes[tipc_net.highest_node]) -		if (--tipc_net.highest_node == 0) -			break; +	tipc_num_nodes--;  } @@ -200,54 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)  		node_lost_contact(n_ptr);  } -int tipc_node_has_active_links(struct tipc_node *n_ptr) +int tipc_node_active_links(struct tipc_node *n_ptr)  {  	return n_ptr->active_links[0] != NULL;  } -int tipc_node_has_redundant_links(struct tipc_node *n_ptr) +int tipc_node_redundant_links(struct tipc_node *n_ptr)  {  	return n_ptr->working_links > 1;  }  int tipc_node_is_up(struct tipc_node *n_ptr)  { -	return tipc_node_has_active_links(n_ptr); +	return tipc_node_active_links(n_ptr);  } -struct tipc_node *tipc_node_attach_link(struct link *l_ptr) +void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)  { -	struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); - -	if (!n_ptr) -		n_ptr = tipc_node_create(l_ptr->addr); -	if (n_ptr) { -		u32 bearer_id = l_ptr->b_ptr->identity; -		char addr_string[16]; - -		if (n_ptr->link_cnt >= 2) { -			err("Attempt to create third link to %s\n", -			    tipc_addr_string_fill(addr_string, n_ptr->addr)); -			return NULL; -		} - -		if (!n_ptr->links[bearer_id]) { -			n_ptr->links[bearer_id] = l_ptr; -			tipc_net.links++; -			n_ptr->link_cnt++; -			return n_ptr; -		} -		err("Attempt to establish second link on <%s> to %s\n", -		    l_ptr->b_ptr->publ.name, -		    tipc_addr_string_fill(addr_string, l_ptr->addr)); -	} -	return NULL; +	n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; +	atomic_inc(&tipc_num_links); +	n_ptr->link_cnt++;  }  void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)  {  	n_ptr->links[l_ptr->b_ptr->identity] = NULL; -	tipc_net.links--; +	atomic_dec(&tipc_num_links);  	n_ptr->link_cnt--;  } @@ -327,7 +328,6 @@ static void node_cleanup_finished(unsigned long node_addr)  static void node_lost_contact(struct tipc_node *n_ptr)  { -	struct tipc_node_subscr *ns, *tns;  	char addr_string[16];  	u32 i; @@ -365,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)  	}  	/* Notify subscribers */ -	list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { -		ns->node = NULL; -		list_del_init(&ns->nodesub_list); -		tipc_k_signal((Handler)ns->handle_node_down, -			      (unsigned long)ns->usr_handle); -	} +	tipc_nodesub_notify(n_ptr);  	/* Prevent re-contact with node until all cleanup is done */ @@ -385,7 +380,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)  	struct tipc_node *n_ptr;  	struct tipc_node_info node_info;  	u32 payload_size; -	u32 n_num;  	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))  		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); @@ -396,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)  						   " (network address)");  	read_lock_bh(&tipc_net_lock); -	if (!tipc_net.nodes) { +	if (!tipc_num_nodes) {  		read_unlock_bh(&tipc_net_lock);  		return tipc_cfg_reply_none();  	}  	/* For now, get space for all other nodes */ -	payload_size = TLV_SPACE(sizeof(node_info)) * -		(tipc_net.highest_node - 1); +	payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;  	if (payload_size > 32768u) {  		read_unlock_bh(&tipc_net_lock);  		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED @@ -418,9 +411,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)  	/* Add TLVs for all nodes in scope */ -	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { -		n_ptr = tipc_net.nodes[n_num]; -		if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) +	list_for_each_entry(n_ptr, &tipc_node_list, list) { +		if (!tipc_in_scope(domain, n_ptr->addr))  			continue;  		node_info.addr = htonl(n_ptr->addr);  		node_info.up = htonl(tipc_node_is_up(n_ptr)); @@ -439,7 +431,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)  	struct tipc_node *n_ptr;  	struct tipc_link_info link_info;  	u32 payload_size; -	u32 n_num;  	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))  		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); @@ -456,7 +447,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)  	/* Get space for all unicast links + multicast link */ -	payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1); +	payload_size = TLV_SPACE(sizeof(link_info)) * +		(atomic_read(&tipc_num_links) + 1);  	if (payload_size > 32768u) {  		read_unlock_bh(&tipc_net_lock);  		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED @@ -470,18 +462,17 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)  	/* Add TLV for broadcast link */ -	link_info.dest = htonl(tipc_own_addr & 0xfffff00); +	link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));  	link_info.up = htonl(1);  	strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);  	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));  	/* Add TLVs for any other links in scope */ -	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { +	list_for_each_entry(n_ptr, &tipc_node_list, list) {  		u32 i; -		n_ptr = tipc_net.nodes[n_num]; -		if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) +		if (!tipc_in_scope(domain, n_ptr->addr))  			continue;  		tipc_node_lock(n_ptr);  		for (i = 0; i < MAX_BEARERS; i++) { | 
