From 2d627b92fd1e39d83c3ee0b9d410403f98cb3981 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 7 Jan 2011 13:00:11 -0500 Subject: tipc: Combine bearer structure with tipc_bearer structure Combines two distinct structures containing information about a TIPC bearer into a single structure. The structures were previously kept separate so that public information about a bearer could be made available to plug-in media types using TIPC's native API, while the remaining information was kept private for use by TIPC itself. However, now that the native API has been removed there is no longer any need for this arrangement. Since one of the structures was already embedded within the other, the change largely involves replacing instances of "publ.foo" with "foo". The changes do not otherwise alter the operation of TIPC bearers. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/node.c b/net/tipc/node.c index 3af53e327f4..e4dba1dfb6e 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 @@ -238,7 +238,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) return n_ptr; } err("Attempt to establish second link on <%s> to %s\n", - l_ptr->b_ptr->publ.name, + l_ptr->b_ptr->name, tipc_addr_string_fill(addr_string, l_ptr->addr)); } return NULL; -- cgit v1.2.3-70-g09d2 From aa8472948487432bacbd099b86e313bc16319495 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 21 Feb 2011 09:45:31 -0500 Subject: tipc: Correct broadcast link peer info when displaying links Fixes a typo in the calculation of the network address of a node's own cluster when generating a response to the configuration command that lists all of the node's links. The correct mask value for a network address uses 1's for the 8-bit zone and 12-bit cluster parts and 0's for the 12-bit node part. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/node.c b/net/tipc/node.c index e4dba1dfb6e..d040d4754e3 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -470,7 +470,7 @@ 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_own_addr & 0xfffff000); 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)); -- cgit v1.2.3-70-g09d2 From a3796f895ff2917aea331a8d40036c73452b2203 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 23 Feb 2011 11:44:49 -0500 Subject: tipc: Add network address mask helper routines Introduces a pair of helper routines that convert the network address for a TIPC node into the network address for its cluster or zone. This is a cosmetic change designed to avoid future errors caused by the incorrect use of address bitmasks, and does not alter the existing operation of TIPC. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/addr.c | 4 ++-- net/tipc/addr.h | 17 +++++++++++++---- net/tipc/node.c | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 88463d9a6f1..087e399518c 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -81,9 +81,9 @@ int tipc_in_scope(u32 domain, u32 addr) { if (!domain || (domain == addr)) return 1; - if (domain == (addr & 0xfffff000u)) /* domain */ + if (domain == tipc_cluster_mask(addr)) /* domain */ return 1; - if (domain == (addr & 0xff000000u)) /* domain */ + if (domain == tipc_zone_mask(addr)) /* domain */ return 1; return 0; } diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 2490fadd0ca..8971aba99ae 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -37,6 +37,16 @@ #ifndef _TIPC_ADDR_H #define _TIPC_ADDR_H +static inline u32 tipc_zone_mask(u32 addr) +{ + return addr & 0xff000000u; +} + +static inline u32 tipc_cluster_mask(u32 addr) +{ + return addr & 0xfffff000u; +} + static inline int in_own_cluster(u32 addr) { return !((addr ^ tipc_own_addr) >> 12); @@ -49,14 +59,13 @@ static inline int in_own_cluster(u32 addr) * after a network hop. */ -static inline int addr_domain(int sc) +static inline u32 addr_domain(u32 sc) { if (likely(sc == TIPC_NODE_SCOPE)) return tipc_own_addr; if (sc == TIPC_CLUSTER_SCOPE) - return tipc_addr(tipc_zone(tipc_own_addr), - tipc_cluster(tipc_own_addr), 0); - return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); + return tipc_cluster_mask(tipc_own_addr); + return tipc_zone_mask(tipc_own_addr); } int tipc_addr_domain_valid(u32); diff --git a/net/tipc/node.c b/net/tipc/node.c index d040d4754e3..14f98c81d31 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -470,7 +470,7 @@ 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 & 0xfffff000); + 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)); -- cgit v1.2.3-70-g09d2 From 431697eb60d2d36614096aff12bd1b826a9f9bc1 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 23 Feb 2011 13:51:15 -0500 Subject: tipc: Prevent null pointer error when removing a node subscription Prevents a null pointer dereference from occurring if a node subscription is triggered at the same time that the subscribing port or publication is terminating the subscription. The problem arises if the triggering routine asynchronously activates and deregisters the node subscription while deregistration is already underway -- the deregistration routine may find that the pointer it has just verified to be non-NULL is now NULL. To avoid this race condition the triggering routine now simply marks the node subscription as defunct (to prevent it from re-activating) instead of deregistering it. The subscription is now both deregistered and destroyed only when the subscribing port or publication code terminates the node subscription. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_distr.c | 5 +++-- net/tipc/node.c | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 483c226c958..1d4a18aa9cc 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -2,7 +2,7 @@ * net/tipc/name_distr.c: TIPC name distribution code * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,7 +221,6 @@ exit: * In rare cases the link may have come back up again when this * function is called, and we have two items representing the same * publication. Nudge this item's key to distinguish it from the other. - * (Note: Publication's node subscription is already unsubscribed.) */ static void node_is_down(struct publication *publ) @@ -232,6 +231,8 @@ static void node_is_down(struct publication *publ) publ->key += 1222345; p = tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, publ->ref, publ->key); + if (p) + tipc_nodesub_unsubscribe(&p->subscr); write_unlock_bh(&tipc_nametbl_lock); if (p != publ) { diff --git a/net/tipc/node.c b/net/tipc/node.c index 14f98c81d31..8926caaf1fc 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -327,7 +327,7 @@ 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; + struct tipc_node_subscr *ns; char addr_string[16]; u32 i; @@ -365,11 +365,12 @@ 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); + list_for_each_entry(ns, &n_ptr->nsub, nodesub_list) { + if (ns->handle_node_down) { + tipc_k_signal((Handler)ns->handle_node_down, + (unsigned long)ns->usr_handle); + ns->handle_node_down = NULL; + } } /* Prevent re-contact with node until all cleanup is done */ -- cgit v1.2.3-70-g09d2 From f1379173326de4c745c4f610501486e4f3bd9248 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Wed, 23 Feb 2011 14:13:41 -0500 Subject: tipc: Cosmetic changes to node subscription code Relocates the code that notifies users of node subscriptions so that it is adjacent to the rest of the routines that implement TIPC's node subscription capability. Renames the name table routine that is invoked by a node subscription to better reflect its purpose and to be consistent with other, similar name table routines. These changes are cosmetic in nature, and do not alter the behavior of TIPC. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_distr.c | 7 ++++--- net/tipc/node.c | 9 +-------- net/tipc/node_subscr.c | 21 ++++++++++++++++++++- net/tipc/node_subscr.h | 3 ++- 4 files changed, 27 insertions(+), 13 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 1d4a18aa9cc..d58dae78b55 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -214,7 +214,7 @@ exit: } /** - * node_is_down - remove publication associated with a failed node + * named_purge_publ - remove publication associated with a failed node * * Invoked for each publication issued by a newly failed node. * Removes publication structure from name table & deletes it. @@ -223,7 +223,7 @@ exit: * publication. Nudge this item's key to distinguish it from the other. */ -static void node_is_down(struct publication *publ) +static void named_purge_publ(struct publication *publ) { struct publication *p; @@ -269,7 +269,8 @@ void tipc_named_recv(struct sk_buff *buf) tipc_nodesub_subscribe(&publ->subscr, msg_orignode(msg), publ, - (net_ev_handler)node_is_down); + (net_ev_handler) + named_purge_publ); } } else if (msg_type(msg) == WITHDRAWAL) { publ = tipc_nametbl_remove_publ(ntohl(item->type), diff --git a/net/tipc/node.c b/net/tipc/node.c index 8926caaf1fc..713ab5d7c54 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -327,7 +327,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; char addr_string[16]; u32 i; @@ -365,13 +364,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) } /* Notify subscribers */ - list_for_each_entry(ns, &n_ptr->nsub, nodesub_list) { - if (ns->handle_node_down) { - tipc_k_signal((Handler)ns->handle_node_down, - (unsigned long)ns->usr_handle); - ns->handle_node_down = NULL; - } - } + tipc_nodesub_notify(n_ptr); /* Prevent re-contact with node until all cleanup is done */ diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index 018a55332d9..c3c2815ae63 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -2,7 +2,7 @@ * net/tipc/node_subscr.c: TIPC "node down" subscription handling * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,3 +76,22 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub) list_del_init(&node_sub->nodesub_list); tipc_node_unlock(node_sub->node); } + +/** + * tipc_nodesub_notify - notify subscribers that a node is unreachable + * + * Note: node is locked by caller + */ + +void tipc_nodesub_notify(struct tipc_node *node) +{ + struct tipc_node_subscr *ns; + + list_for_each_entry(ns, &node->nsub, nodesub_list) { + if (ns->handle_node_down) { + tipc_k_signal((Handler)ns->handle_node_down, + (unsigned long)ns->usr_handle); + ns->handle_node_down = NULL; + } + } +} diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index 006ed739f51..4bc2ca0867a 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -2,7 +2,7 @@ * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,5 +59,6 @@ struct tipc_node_subscr { void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, void *usr_handle, net_ev_handler handle_down); void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); +void tipc_nodesub_notify(struct tipc_node *node); #endif -- cgit v1.2.3-70-g09d2 From 9df3b7eb6ec1c7734482f782bf8335a2737c02f0 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Thu, 24 Feb 2011 13:20:20 -0500 Subject: tipc: Fix problem with missing link in "tipc-config -l" output Removes a race condition that could cause TIPC's internal counter of the number of links it has to neighboring nodes to have the incorrect value if two independent threads of control simultaneously create new link endpoints connecting to two different nodes using two different bearers. Such under counting would result in TIPC failing to list the final link(s) in its response to a configuration request to list all of the node's links. The counter is now updated atomically to ensure that simultaneous increments do not interfere with each other. Thanks go to Peter Butler for his assistance in diagnosing and fixing this problem. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/net.c | 3 ++- net/tipc/net.h | 4 ++-- net/tipc/node.c | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index 9bacfd00b91..dd78d869829 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -2,7 +2,7 @@ * net/tipc/net.c: TIPC network routing code * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -115,6 +115,7 @@ static int net_start(void) tipc_net.nodes = kcalloc(tipc_max_nodes + 1, sizeof(*tipc_net.nodes), GFP_ATOMIC); tipc_net.highest_node = 0; + atomic_set(&tipc_net.links, 0); return tipc_net.nodes ? 0 : -ENOMEM; } diff --git a/net/tipc/net.h b/net/tipc/net.h index 4ae59ad0489..aa431ef8b7b 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -2,7 +2,7 @@ * net/tipc/net.h: Include file for TIPC network routing code * * Copyright (c) 1995-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ struct tipc_node; struct network { struct tipc_node **nodes; u32 highest_node; - u32 links; + atomic_t links; }; diff --git a/net/tipc/node.c b/net/tipc/node.c index 713ab5d7c54..a24fad32345 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -233,7 +233,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) if (!n_ptr->links[bearer_id]) { n_ptr->links[bearer_id] = l_ptr; - tipc_net.links++; + atomic_inc(&tipc_net.links); n_ptr->link_cnt++; return n_ptr; } @@ -247,7 +247,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) 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_net.links); n_ptr->link_cnt--; } @@ -450,7 +450,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_net.links) + 1); if (payload_size > 32768u) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED -- cgit v1.2.3-70-g09d2 From d1bcb11544109114d72965afea7805cc3e16a83a Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 25 Feb 2011 10:01:58 -0500 Subject: tipc: Split up unified structure of network-related variables Converts the fields of the global "tipc_net" structure into individual variables. Since the struct was never referenced as a complete unit, its existence was pointless. This will facilitate upcoming changes to TIPC's node table and simpify upcoming relocation of the variables so they are only visible to the files that actually use them. This change is essentially cosmetic in nature, and doesn't affect the operation of TIPC. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_distr.c | 4 ++-- net/tipc/net.c | 22 ++++++++++++---------- net/tipc/net.h | 17 +++-------------- net/tipc/node.c | 30 +++++++++++++++--------------- net/tipc/node.h | 2 +- 5 files changed, 33 insertions(+), 42 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index d58dae78b55..f2086f684b3 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -111,8 +111,8 @@ static void named_cluster_distribute(struct sk_buff *buf) struct tipc_node *n_ptr; u32 n_num; - for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { - n_ptr = tipc_net.nodes[n_num]; + for (n_num = 1; n_num <= tipc_highest_node; n_num++) { + n_ptr = tipc_nodes[n_num]; if (n_ptr && tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (!buf_copy) diff --git a/net/tipc/net.c b/net/tipc/net.c index dd78d869829..f6303d79f7f 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -108,26 +108,28 @@ */ DEFINE_RWLOCK(tipc_net_lock); -struct network tipc_net; +struct tipc_node **tipc_nodes; +u32 tipc_highest_node; +atomic_t tipc_num_links; static int net_start(void) { - tipc_net.nodes = kcalloc(tipc_max_nodes + 1, - sizeof(*tipc_net.nodes), GFP_ATOMIC); - tipc_net.highest_node = 0; - atomic_set(&tipc_net.links, 0); + tipc_nodes = kcalloc(tipc_max_nodes + 1, + sizeof(*tipc_nodes), GFP_ATOMIC); + tipc_highest_node = 0; + atomic_set(&tipc_num_links, 0); - return tipc_net.nodes ? 0 : -ENOMEM; + return tipc_nodes ? 0 : -ENOMEM; } static void net_stop(void) { u32 n_num; - for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) - tipc_node_delete(tipc_net.nodes[n_num]); - kfree(tipc_net.nodes); - tipc_net.nodes = NULL; + for (n_num = 1; n_num <= tipc_highest_node; n_num++) + tipc_node_delete(tipc_nodes[n_num]); + kfree(tipc_nodes); + tipc_nodes = NULL; } static void net_route_named_msg(struct sk_buff *buf) diff --git a/net/tipc/net.h b/net/tipc/net.h index aa431ef8b7b..b52b9748b5e 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -39,21 +39,10 @@ struct tipc_node; -/** - * struct network - TIPC network structure - * @nodes: array of pointers to all nodes within cluster - * @highest_node: id of highest numbered node within cluster - * @links: number of (unicast) links to cluster - */ - -struct network { - struct tipc_node **nodes; - u32 highest_node; - atomic_t links; -}; - +extern struct tipc_node **tipc_nodes; +extern u32 tipc_highest_node; +extern atomic_t tipc_num_links; -extern struct network tipc_net; extern rwlock_t tipc_net_lock; void tipc_net_route_msg(struct sk_buff *buf); diff --git a/net/tipc/node.c b/net/tipc/node.c index a24fad32345..64976f2e3c6 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -81,9 +81,9 @@ struct tipc_node *tipc_node_create(u32 addr) 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; + tipc_nodes[n_num] = n_ptr; + if (n_num > tipc_highest_node) + tipc_highest_node = n_num; spin_unlock_bh(&node_create_lock); return n_ptr; @@ -97,11 +97,11 @@ void tipc_node_delete(struct tipc_node *n_ptr) return; n_num = tipc_node(n_ptr->addr); - tipc_net.nodes[n_num] = NULL; + tipc_nodes[n_num] = NULL; kfree(n_ptr); - while (!tipc_net.nodes[tipc_net.highest_node]) - if (--tipc_net.highest_node == 0) + while (!tipc_nodes[tipc_highest_node]) + if (--tipc_highest_node == 0) break; } @@ -233,7 +233,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) if (!n_ptr->links[bearer_id]) { n_ptr->links[bearer_id] = l_ptr; - atomic_inc(&tipc_net.links); + atomic_inc(&tipc_num_links); n_ptr->link_cnt++; return n_ptr; } @@ -247,7 +247,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) { n_ptr->links[l_ptr->b_ptr->identity] = NULL; - atomic_dec(&tipc_net.links); + atomic_dec(&tipc_num_links); n_ptr->link_cnt--; } @@ -390,7 +390,7 @@ 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_nodes) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_none(); } @@ -398,7 +398,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) /* For now, get space for all other nodes */ payload_size = TLV_SPACE(sizeof(node_info)) * - (tipc_net.highest_node - 1); + (tipc_highest_node - 1); if (payload_size > 32768u) { read_unlock_bh(&tipc_net_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED @@ -412,8 +412,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]; + for (n_num = 1; n_num <= tipc_highest_node; n_num++) { + n_ptr = tipc_nodes[n_num]; if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) continue; node_info.addr = htonl(n_ptr->addr); @@ -451,7 +451,7 @@ 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)) * - (atomic_read(&tipc_net.links) + 1); + (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 @@ -472,10 +472,10 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) /* Add TLVs for any other links in scope */ - for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { + for (n_num = 1; n_num <= tipc_highest_node; n_num++) { u32 i; - n_ptr = tipc_net.nodes[n_num]; + n_ptr = tipc_nodes[n_num]; if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) continue; tipc_node_lock(n_ptr); diff --git a/net/tipc/node.h b/net/tipc/node.h index 206a8efa410..c510a2afcc6 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -107,7 +107,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) static inline struct tipc_node *tipc_node_find(u32 addr) { if (likely(in_own_cluster(addr))) - return tipc_net.nodes[tipc_node(addr)]; + return tipc_nodes[tipc_node(addr)]; return NULL; } -- cgit v1.2.3-70-g09d2 From 672d99e19a12b703c9e2d71ead8fb8b8a85a3886 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 25 Feb 2011 18:42:52 -0500 Subject: tipc: Convert node object array to a hash table Replaces the dynamically allocated array of pointers to the cluster's node objects with a static hash table. Hash collisions are resolved using chaining, with a typical hash chain having only a single node, to avoid degrading performance during processing of incoming packets. The conversion to a hash table reduces the memory requirements for TIPC's node table to approximately the same size it had prior to the previous commit. In addition to the hash table itself, TIPC now also maintains a linked list for the node objects, sorted by ascending network address. This list allows TIPC to continue sending responses to user space applications that request node and link information in sorted order. The list also improves performance when name table update messages are sent by making it easier to identify the nodes that must be notified. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/name_distr.c | 6 ++--- net/tipc/net.c | 15 ++++------- net/tipc/net.h | 4 --- net/tipc/node.c | 70 +++++++++++++++++++++++++++++++-------------------- net/tipc/node.h | 30 ++++++++++++++-------- 5 files changed, 70 insertions(+), 55 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index f2086f684b3..1b70d5d051d 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) { struct sk_buff *buf_copy; struct tipc_node *n_ptr; - u32 n_num; - for (n_num = 1; n_num <= tipc_highest_node; n_num++) { - n_ptr = tipc_nodes[n_num]; - if (n_ptr && tipc_node_has_active_links(n_ptr)) { + list_for_each_entry(n_ptr, &tipc_node_list, list) { + if (tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (!buf_copy) break; diff --git a/net/tipc/net.c b/net/tipc/net.c index b5b337f5516..cce8d086f17 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -39,6 +39,7 @@ #include "name_distr.h" #include "subscr.h" #include "port.h" +#include "node.h" #include "config.h" /* @@ -108,27 +109,21 @@ */ DEFINE_RWLOCK(tipc_net_lock); -struct tipc_node **tipc_nodes; -u32 tipc_highest_node; atomic_t tipc_num_links; static int net_start(void) { - tipc_nodes = kcalloc(4096, sizeof(*tipc_nodes), GFP_ATOMIC); - tipc_highest_node = 0; atomic_set(&tipc_num_links, 0); - return tipc_nodes ? 0 : -ENOMEM; + return 0; } static void net_stop(void) { - u32 n_num; + struct tipc_node *node, *t_node; - for (n_num = 1; n_num <= tipc_highest_node; n_num++) - tipc_node_delete(tipc_nodes[n_num]); - kfree(tipc_nodes); - tipc_nodes = NULL; + list_for_each_entry_safe(node, t_node, &tipc_node_list, list) + tipc_node_delete(node); } static void net_route_named_msg(struct sk_buff *buf) diff --git a/net/tipc/net.h b/net/tipc/net.h index b52b9748b5e..0ba6093fb6c 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -37,10 +37,6 @@ #ifndef _TIPC_NET_H #define _TIPC_NET_H -struct tipc_node; - -extern struct tipc_node **tipc_nodes; -extern u32 tipc_highest_node; extern atomic_t tipc_num_links; extern rwlock_t tipc_net_lock; diff --git a/net/tipc/node.c b/net/tipc/node.c index 64976f2e3c6..22aeb2b7ad0 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -44,8 +44,30 @@ 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; 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 * @@ -58,8 +80,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 +99,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_nodes[n_num] = n_ptr; - if (n_num > tipc_highest_node) - tipc_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 +119,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_nodes[n_num] = NULL; + list_del(&n_ptr->list); + hlist_del(&n_ptr->hash); kfree(n_ptr); - while (!tipc_nodes[tipc_highest_node]) - if (--tipc_highest_node == 0) - break; + tipc_num_nodes--; } @@ -379,7 +400,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); @@ -390,15 +410,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_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_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 @@ -412,9 +431,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_highest_node; n_num++) { - n_ptr = tipc_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)); @@ -433,7 +451,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); @@ -472,11 +489,10 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) /* Add TLVs for any other links in scope */ - for (n_num = 1; n_num <= tipc_highest_node; n_num++) { + list_for_each_entry(n_ptr, &tipc_node_list, list) { u32 i; - n_ptr = tipc_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++) { diff --git a/net/tipc/node.h b/net/tipc/node.h index c510a2afcc6..02e4927216f 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -2,7 +2,7 @@ * net/tipc/node.h: Include file for TIPC node management routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,8 @@ * struct tipc_node - TIPC node structure * @addr: network address of node * @lock: spinlock governing access to structure - * @next: pointer to next node in sorted list of cluster's nodes + * @hash: links to adjacent nodes in unsorted hash chain + * @list: links to adjacent nodes in sorted list of cluster's nodes * @nsub: list of "node down" subscriptions monitoring node * @active_links: pointers to active links to node * @links: pointers to all links to node @@ -69,7 +70,8 @@ struct tipc_node { u32 addr; spinlock_t lock; - struct tipc_node *next; + struct hlist_node hash; + struct list_head list; struct list_head nsub; struct link *active_links[2]; struct link *links[MAX_BEARERS]; @@ -90,8 +92,23 @@ struct tipc_node { } bclink; }; +#define NODE_HTABLE_SIZE 512 +extern struct list_head tipc_node_list; + +/* + * A trivial power-of-two bitmask technique is used for speed, since this + * operation is done for every incoming TIPC packet. The number of hash table + * entries has been chosen so that no hash chain exceeds 8 nodes and will + * usually be much smaller (typically only a single node). + */ +static inline unsigned int tipc_hashfn(u32 addr) +{ + return addr & (NODE_HTABLE_SIZE - 1); +} + extern u32 tipc_own_tag; +struct tipc_node *tipc_node_find(u32 addr); struct tipc_node *tipc_node_create(u32 addr); void tipc_node_delete(struct tipc_node *n_ptr); 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); struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); -static inline struct tipc_node *tipc_node_find(u32 addr) -{ - if (likely(in_own_cluster(addr))) - return tipc_nodes[tipc_node(addr)]; - return NULL; -} - static inline void tipc_node_lock(struct tipc_node *n_ptr) { spin_lock_bh(&n_ptr->lock); -- cgit v1.2.3-70-g09d2 From 34e46258cb9f53b41e8ffd2e9acd58e0cf64b158 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Fri, 25 Feb 2011 19:11:25 -0500 Subject: tipc: manually inline net_start/stop, make assoc. vars static Relocates network-related variables into the subsystem files where they are now primarily used (following the recent rework of TIPC's node table), and converts globals into locals where possible. Changes the initialization of tipc_num_links from run-time to compile-time, and eliminates the net_start routine that becomes empty as a result. Also eliminates the corresponding net_stop routine by moving its (trivial) content into the one location that called the routine. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/net.c | 25 ++++--------------------- net/tipc/net.h | 2 -- net/tipc/node.c | 2 ++ 3 files changed, 6 insertions(+), 23 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index cce8d086f17..8fbc7e6ae3d 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -109,22 +109,6 @@ */ DEFINE_RWLOCK(tipc_net_lock); -atomic_t tipc_num_links; - -static int net_start(void) -{ - atomic_set(&tipc_num_links, 0); - - return 0; -} - -static void net_stop(void) -{ - struct tipc_node *node, *t_node; - - list_for_each_entry_safe(node, t_node, &tipc_node_list, list) - tipc_node_delete(node); -} static void net_route_named_msg(struct sk_buff *buf) { @@ -214,9 +198,6 @@ int tipc_net_start(u32 addr) tipc_named_reinit(); tipc_port_reinit(); - res = net_start(); - if (res) - return res; res = tipc_bclink_init(); if (res) return res; @@ -232,14 +213,16 @@ int tipc_net_start(u32 addr) void tipc_net_stop(void) { + struct tipc_node *node, *t_node; + if (tipc_mode != TIPC_NET_MODE) return; write_lock_bh(&tipc_net_lock); tipc_bearer_stop(); tipc_mode = TIPC_NODE_MODE; tipc_bclink_stop(); - net_stop(); + list_for_each_entry_safe(node, t_node, &tipc_node_list, list); + tipc_node_delete(node); write_unlock_bh(&tipc_net_lock); info("Left network mode\n"); } - diff --git a/net/tipc/net.h b/net/tipc/net.h index 0ba6093fb6c..9eb4b9e220e 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -37,8 +37,6 @@ #ifndef _TIPC_NET_H #define _TIPC_NET_H -extern atomic_t tipc_num_links; - extern rwlock_t tipc_net_lock; void tipc_net_route_msg(struct sk_buff *buf); diff --git a/net/tipc/node.c b/net/tipc/node.c index 22aeb2b7ad0..66099cb1d6d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -47,6 +47,8 @@ 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; /** -- cgit v1.2.3-70-g09d2 From 8f19afb2dbc885befef2a4e7931dfcb51702a212 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 28 Feb 2011 11:36:21 -0400 Subject: tipc: cosmetic - function names are not to be full sentences Function names like "tipc_node_has_redundant_links" are unweildy and result in long lines even for simple lines. The "has" doesn't contribute any value add, so dropping that is a slight step in the right direction. This is a cosmetic change, basic result of: for i in `grep -l tipc_node_has_ *` ; do sed -i s/tipc_node_has_/tipc_node_/ $i ; done Signed-off-by: Paul Gortmaker --- net/tipc/link.c | 6 +++--- net/tipc/name_distr.c | 2 +- net/tipc/node.c | 6 +++--- net/tipc/node.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/link.c b/net/tipc/link.c index d4f2780ff87..d8a4b90b029 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -548,7 +548,7 @@ void tipc_link_reset(struct link *l_ptr) tipc_node_link_down(l_ptr->owner, l_ptr); tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); - if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && + if (was_active_link && tipc_node_active_links(l_ptr->owner) && l_ptr->owner->permit_changeover) { l_ptr->reset_checkpoint = checkpoint; l_ptr->exp_msg_count = START_CHANGEOVER; @@ -1954,7 +1954,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, msg_set_max_pkt(msg, l_ptr->max_pkt_target); } - if (tipc_node_has_redundant_links(l_ptr->owner)) + if (tipc_node_redundant_links(l_ptr->owner)) msg_set_redundant_link(msg); else msg_clear_redundant_link(msg); @@ -2064,7 +2064,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) l_ptr->peer_bearer_id = msg_bearer_id(msg); /* Synchronize broadcast sequence numbers */ - if (!tipc_node_has_redundant_links(l_ptr->owner)) + if (!tipc_node_redundant_links(l_ptr->owner)) l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); break; case STATE_MSG: diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 1b70d5d051d..c9fa6dfcf28 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -111,7 +111,7 @@ static void named_cluster_distribute(struct sk_buff *buf) struct tipc_node *n_ptr; list_for_each_entry(n_ptr, &tipc_node_list, list) { - if (tipc_node_has_active_links(n_ptr)) { + if (tipc_node_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (!buf_copy) break; diff --git a/net/tipc/node.c b/net/tipc/node.c index 66099cb1d6d..ca09b33fb87 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -223,19 +223,19 @@ 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) diff --git a/net/tipc/node.h b/net/tipc/node.h index 02e4927216f..dde316576f8 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -115,8 +115,8 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr); void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); -int tipc_node_has_active_links(struct tipc_node *n_ptr); -int tipc_node_has_redundant_links(struct tipc_node *n_ptr); +int tipc_node_active_links(struct tipc_node *n_ptr); +int tipc_node_redundant_links(struct tipc_node *n_ptr); int tipc_node_is_up(struct tipc_node *n_ptr); struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); -- cgit v1.2.3-70-g09d2 From 37b9c08a88f9a82456bb11fa050cccb544e8dc60 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Mon, 28 Feb 2011 11:32:27 -0500 Subject: tipc: Optimizations to link creation code Enhances link creation code as follows: 1) Detects illegal attempts to add a requested link earlier in the link creation process. This prevents TIPC from wasting time initializing a link object it then throws away, and also eliminates the code needed to do the throwing away. 2) Passes in the node object associated with the requested link. This allows TIPC to eliminate a search to locate the node object, as well as code that attempted to create the node if it doesn't exist. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker --- net/tipc/discover.c | 2 +- net/tipc/link.c | 27 ++++++++++++++++++++------- net/tipc/link.h | 3 ++- net/tipc/node.c | 30 ++++-------------------------- net/tipc/node.h | 2 +- 5 files changed, 28 insertions(+), 36 deletions(-) (limited to 'net/tipc/node.c') diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 580b50a79e4..caac5c93b7f 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -169,7 +169,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) /* Create a link endpoint for this bearer, if necessary */ if (!link) { - link = tipc_link_create(b_ptr, orig, &media_addr); + link = tipc_link_create(n_ptr, b_ptr, &media_addr); if (!link) { tipc_node_unlock(n_ptr); return; diff --git a/net/tipc/link.c b/net/tipc/link.c index e5f96d5ef1a..b73adeb5cde 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -293,19 +293,35 @@ static void link_set_timer(struct link *l_ptr, u32 time) /** * tipc_link_create - create a new link + * @n_ptr: pointer to associated node * @b_ptr: pointer to associated bearer - * @peer: network address of node at other end of link * @media_addr: media address to use when sending messages over link * * Returns pointer to link. */ -struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, +struct link *tipc_link_create(struct tipc_node *n_ptr, + struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr) { struct link *l_ptr; struct tipc_msg *msg; char *if_name; + char addr_string[16]; + u32 peer = n_ptr->addr; + + if (n_ptr->link_cnt >= 2) { + tipc_addr_string_fill(addr_string, n_ptr->addr); + err("Attempt to establish third link to %s\n", addr_string); + return NULL; + } + + if (n_ptr->links[b_ptr->identity]) { + tipc_addr_string_fill(addr_string, n_ptr->addr); + err("Attempt to establish second link on <%s> to %s\n", + b_ptr->name, addr_string); + return NULL; + } l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC); if (!l_ptr) { @@ -322,6 +338,7 @@ struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); /* note: peer i/f is appended to link name by reset/activate */ memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); + l_ptr->owner = n_ptr; l_ptr->checkpoint = 1; l_ptr->b_ptr = b_ptr; link_set_supervision_props(l_ptr, b_ptr->media->tolerance); @@ -345,11 +362,7 @@ struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, link_reset_statistics(l_ptr); - l_ptr->owner = tipc_node_attach_link(l_ptr); - if (!l_ptr->owner) { - kfree(l_ptr); - return NULL; - } + tipc_node_attach_link(n_ptr, l_ptr); k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); list_add_tail(&l_ptr->link_list, &b_ptr->links); diff --git a/net/tipc/link.h b/net/tipc/link.h index a7794e7ede2..e6a30dbe1aa 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -207,7 +207,8 @@ struct link { struct tipc_port; -struct link *tipc_link_create(struct tipc_bearer *b_ptr, const u32 peer, +struct link *tipc_link_create(struct tipc_node *n_ptr, + struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr); void tipc_link_delete(struct link *l_ptr); void tipc_link_changeover(struct link *l_ptr); diff --git a/net/tipc/node.c b/net/tipc/node.c index ca09b33fb87..2d106ef4fa4 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -238,33 +238,11 @@ int tipc_node_is_up(struct tipc_node *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; - atomic_inc(&tipc_num_links); - n_ptr->link_cnt++; - return n_ptr; - } - err("Attempt to establish second link on <%s> to %s\n", - l_ptr->b_ptr->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) diff --git a/net/tipc/node.h b/net/tipc/node.h index dde316576f8..5c61afc7a0b 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -111,7 +111,7 @@ extern u32 tipc_own_tag; struct tipc_node *tipc_node_find(u32 addr); struct tipc_node *tipc_node_create(u32 addr); void tipc_node_delete(struct tipc_node *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); void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr); -- cgit v1.2.3-70-g09d2