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.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 8972ca1c654c..cfdbaf479fd1 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -45,6 +45,7 @@
45#include "netlink.h" 45#include "netlink.h"
46 46
47#define INVALID_NODE_SIG 0x10000 47#define INVALID_NODE_SIG 0x10000
48#define NODE_CLEANUP_AFTER 300000
48 49
49/* Flags used to take different actions according to flag type 50/* Flags used to take different actions according to flag type
50 * TIPC_NOTIFY_NODE_DOWN: notify node is down 51 * TIPC_NOTIFY_NODE_DOWN: notify node is down
@@ -96,6 +97,7 @@ struct tipc_bclink_entry {
96 * @link_id: local and remote bearer ids of changing link, if any 97 * @link_id: local and remote bearer ids of changing link, if any
97 * @publ_list: list of publications 98 * @publ_list: list of publications
98 * @rcu: rcu struct for tipc_node 99 * @rcu: rcu struct for tipc_node
100 * @delete_at: indicates the time for deleting a down node
99 */ 101 */
100struct tipc_node { 102struct tipc_node {
101 u32 addr; 103 u32 addr;
@@ -121,6 +123,7 @@ struct tipc_node {
121 unsigned long keepalive_intv; 123 unsigned long keepalive_intv;
122 struct timer_list timer; 124 struct timer_list timer;
123 struct rcu_head rcu; 125 struct rcu_head rcu;
126 unsigned long delete_at;
124}; 127};
125 128
126/* Node FSM states and events: 129/* Node FSM states and events:
@@ -160,6 +163,7 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr);
160static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); 163static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id);
161static void tipc_node_put(struct tipc_node *node); 164static void tipc_node_put(struct tipc_node *node);
162static bool node_is_up(struct tipc_node *n); 165static bool node_is_up(struct tipc_node *n);
166static void tipc_node_delete_from_list(struct tipc_node *node);
163 167
164struct tipc_sock_conn { 168struct tipc_sock_conn {
165 u32 port; 169 u32 port;
@@ -390,6 +394,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
390 for (i = 0; i < MAX_BEARERS; i++) 394 for (i = 0; i < MAX_BEARERS; i++)
391 spin_lock_init(&n->links[i].lock); 395 spin_lock_init(&n->links[i].lock);
392 n->state = SELF_DOWN_PEER_LEAVING; 396 n->state = SELF_DOWN_PEER_LEAVING;
397 n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
393 n->signature = INVALID_NODE_SIG; 398 n->signature = INVALID_NODE_SIG;
394 n->active_links[0] = INVALID_BEARER_ID; 399 n->active_links[0] = INVALID_BEARER_ID;
395 n->active_links[1] = INVALID_BEARER_ID; 400 n->active_links[1] = INVALID_BEARER_ID;
@@ -433,11 +438,16 @@ static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l)
433 tipc_link_set_abort_limit(l, tol / n->keepalive_intv); 438 tipc_link_set_abort_limit(l, tol / n->keepalive_intv);
434} 439}
435 440
436static void tipc_node_delete(struct tipc_node *node) 441static void tipc_node_delete_from_list(struct tipc_node *node)
437{ 442{
438 list_del_rcu(&node->list); 443 list_del_rcu(&node->list);
439 hlist_del_rcu(&node->hash); 444 hlist_del_rcu(&node->hash);
440 tipc_node_put(node); 445 tipc_node_put(node);
446}
447
448static void tipc_node_delete(struct tipc_node *node)
449{
450 tipc_node_delete_from_list(node);
441 451
442 del_timer_sync(&node->timer); 452 del_timer_sync(&node->timer);
443 tipc_node_put(node); 453 tipc_node_put(node);
@@ -544,6 +554,42 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
544 tipc_node_put(node); 554 tipc_node_put(node);
545} 555}
546 556
557static void tipc_node_clear_links(struct tipc_node *node)
558{
559 int i;
560
561 for (i = 0; i < MAX_BEARERS; i++) {
562 struct tipc_link_entry *le = &node->links[i];
563
564 if (le->link) {
565 kfree(le->link);
566 le->link = NULL;
567 node->link_cnt--;
568 }
569 }
570}
571
572/* tipc_node_cleanup - delete nodes that does not
573 * have active links for NODE_CLEANUP_AFTER time
574 */
575static int tipc_node_cleanup(struct tipc_node *peer)
576{
577 struct tipc_net *tn = tipc_net(peer->net);
578 bool deleted = false;
579
580 spin_lock_bh(&tn->node_list_lock);
581 tipc_node_write_lock(peer);
582
583 if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) {
584 tipc_node_clear_links(peer);
585 tipc_node_delete_from_list(peer);
586 deleted = true;
587 }
588 tipc_node_write_unlock(peer);
589 spin_unlock_bh(&tn->node_list_lock);
590 return deleted;
591}
592
547/* tipc_node_timeout - handle expiration of node timer 593/* tipc_node_timeout - handle expiration of node timer
548 */ 594 */
549static void tipc_node_timeout(struct timer_list *t) 595static void tipc_node_timeout(struct timer_list *t)
@@ -555,6 +601,12 @@ static void tipc_node_timeout(struct timer_list *t)
555 int bearer_id; 601 int bearer_id;
556 int rc = 0; 602 int rc = 0;
557 603
604 if (!node_is_up(n) && tipc_node_cleanup(n)) {
605 /*Removing the reference of Timer*/
606 tipc_node_put(n);
607 return;
608 }
609
558 __skb_queue_head_init(&xmitq); 610 __skb_queue_head_init(&xmitq);
559 611
560 for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) { 612 for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) {
@@ -1173,6 +1225,7 @@ static void node_lost_contact(struct tipc_node *n,
1173 uint i; 1225 uint i;
1174 1226
1175 pr_debug("Lost contact with %x\n", n->addr); 1227 pr_debug("Lost contact with %x\n", n->addr);
1228 n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
1176 1229
1177 /* Clean up broadcast state */ 1230 /* Clean up broadcast state */
1178 tipc_bcast_remove_peer(n->net, n->bc_entry.link); 1231 tipc_bcast_remove_peer(n->net, n->bc_entry.link);
@@ -1742,7 +1795,6 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
1742 struct tipc_node *peer; 1795 struct tipc_node *peer;
1743 u32 addr; 1796 u32 addr;
1744 int err; 1797 int err;
1745 int i;
1746 1798
1747 /* We identify the peer by its net */ 1799 /* We identify the peer by its net */
1748 if (!info->attrs[TIPC_NLA_NET]) 1800 if (!info->attrs[TIPC_NLA_NET])
@@ -1777,15 +1829,7 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
1777 goto err_out; 1829 goto err_out;
1778 } 1830 }
1779 1831
1780 for (i = 0; i < MAX_BEARERS; i++) { 1832 tipc_node_clear_links(peer);
1781 struct tipc_link_entry *le = &peer->links[i];
1782
1783 if (le->link) {
1784 kfree(le->link);
1785 le->link = NULL;
1786 peer->link_cnt--;
1787 }
1788 }
1789 tipc_node_write_unlock(peer); 1833 tipc_node_write_unlock(peer);
1790 tipc_node_delete(peer); 1834 tipc_node_delete(peer);
1791 1835