Skip to content

Commit

Permalink
Merge branch 'tipc-next'
Browse files Browse the repository at this point in the history
Jon Maloy says:

====================
tipc: some small fixes

During extensive testing and analysis of running dual links between
nodes, we have encountered some issues that potentially may cause
problems. We choose to fix those proactively in this series.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 5, 2015
2 parents 940288b + af9946f commit 251c005
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 45 deletions.
9 changes: 2 additions & 7 deletions net/tipc/discover.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* net/tipc/discover.c
*
* Copyright (c) 2003-2006, 2014, Ericsson AB
* Copyright (c) 2003-2006, 2014-2015, Ericsson AB
* Copyright (c) 2005-2006, 2010-2011, Wind River Systems
* All rights reserved.
*
Expand Down Expand Up @@ -47,7 +47,6 @@
/* indicates no timer in use */
#define TIPC_LINK_REQ_INACTIVE 0xffffffff


/**
* struct tipc_link_req - information about an ongoing link setup request
* @bearer_id: identity of bearer issuing requests
Expand Down Expand Up @@ -163,13 +162,9 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
if (!tipc_in_scope(bearer->domain, onode))
return;

/* Locate, or if necessary, create, node: */
node = tipc_node_find(net, onode);
if (!node)
node = tipc_node_create(net, onode);
node = tipc_node_create(net, onode);
if (!node)
return;

tipc_node_lock(node);
link = node->links[bearer->identity];

Expand Down
83 changes: 51 additions & 32 deletions net/tipc/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ static unsigned int align(unsigned int i)
return (i + 3) & ~3u;
}

static void tipc_link_release(struct kref *kref)
{
kfree(container_of(kref, struct tipc_link, ref));
}

static void tipc_link_get(struct tipc_link *l_ptr)
{
kref_get(&l_ptr->ref);
}

static void tipc_link_put(struct tipc_link *l_ptr)
{
kref_put(&l_ptr->ref, tipc_link_release);
}

static void link_init_max_pkt(struct tipc_link *l_ptr)
{
struct tipc_node *node = l_ptr->owner;
Expand Down Expand Up @@ -222,11 +237,13 @@ static void link_timeout(unsigned long data)
tipc_link_push_packets(l_ptr);

tipc_node_unlock(l_ptr->owner);
tipc_link_put(l_ptr);
}

static void link_set_timer(struct tipc_link *link, unsigned long time)
{
mod_timer(&link->timer, jiffies + time);
if (!mod_timer(&link->timer, jiffies + time))
tipc_link_get(link);
}

/**
Expand Down Expand Up @@ -267,7 +284,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
pr_warn("Link creation failed, no memory\n");
return NULL;
}

kref_init(&l_ptr->ref);
l_ptr->addr = peer;
if_name = strchr(b_ptr->name, ':') + 1;
sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
Expand Down Expand Up @@ -305,46 +322,48 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
skb_queue_head_init(&l_ptr->waiting_sks);

link_reset_statistics(l_ptr);

tipc_node_attach_link(n_ptr, l_ptr);

setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr);

link_state_event(l_ptr, STARTING_EVT);

return l_ptr;
}

/**
* link_delete - Conditional deletion of link.
* If timer still running, real delete is done when it expires
* @link: link to be deleted
*/
void tipc_link_delete(struct tipc_link *link)
{
tipc_link_reset_fragments(link);
tipc_node_detach_link(link->owner, link);
tipc_link_put(link);
}

void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
bool shutting_down)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_link *l_ptr;
struct tipc_node *n_ptr;
struct tipc_link *link;
struct tipc_node *node;

rcu_read_lock();
list_for_each_entry_rcu(n_ptr, &tn->node_list, list) {
tipc_node_lock(n_ptr);
l_ptr = n_ptr->links[bearer_id];
if (l_ptr) {
tipc_link_reset(l_ptr);
if (shutting_down || !tipc_node_is_up(n_ptr)) {
tipc_node_detach_link(l_ptr->owner, l_ptr);
tipc_link_reset_fragments(l_ptr);
tipc_node_unlock(n_ptr);

/* Nobody else can access this link now: */
del_timer_sync(&l_ptr->timer);
kfree(l_ptr);
} else {
/* Detach/delete when failover is finished: */
l_ptr->flags |= LINK_STOPPED;
tipc_node_unlock(n_ptr);
del_timer_sync(&l_ptr->timer);
}
list_for_each_entry_rcu(node, &tn->node_list, list) {
tipc_node_lock(node);
link = node->links[bearer_id];
if (!link) {
tipc_node_unlock(node);
continue;
}
tipc_node_unlock(n_ptr);
tipc_link_reset(link);
if (del_timer(&link->timer))
tipc_link_put(link);
link->flags |= LINK_STOPPED;
/* Delete link now, or when failover is finished: */
if (shutting_down || !tipc_node_is_up(node))
tipc_link_delete(link);
tipc_node_unlock(node);
}
rcu_read_unlock();
}
Expand Down Expand Up @@ -630,7 +649,9 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
break;
case STARTING_EVT:
l_ptr->flags |= LINK_STARTED;
/* fall through */
l_ptr->fsm_msg_cnt++;
link_set_timer(l_ptr, cont_intv);
break;
case TIMEOUT_EVT:
tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
l_ptr->fsm_msg_cnt++;
Expand Down Expand Up @@ -1837,10 +1858,8 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
}
}
exit:
if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) {
tipc_node_detach_link(l_ptr->owner, l_ptr);
kfree(l_ptr);
}
if ((!l_ptr->exp_msg_count) && (l_ptr->flags & LINK_STOPPED))
tipc_link_delete(l_ptr);
return buf;
}

Expand Down
3 changes: 3 additions & 0 deletions net/tipc/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ struct tipc_stats {
* @media_addr: media address to use when sending messages over link
* @timer: link timer
* @owner: pointer to peer node
* @refcnt: reference counter for permanent references (owner node & timer)
* @flags: execution state flags for link endpoint instance
* @checkpoint: reference point for triggering link continuity checking
* @peer_session: link session # being used by peer end of link
Expand Down Expand Up @@ -142,6 +143,7 @@ struct tipc_link {
struct tipc_media_addr media_addr;
struct timer_list timer;
struct tipc_node *owner;
struct kref ref;

/* Management and link supervision data */
unsigned int flags;
Expand Down Expand Up @@ -200,6 +202,7 @@ struct tipc_port;
struct tipc_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 tipc_link *link);
void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
bool shutting_down);
void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
Expand Down
15 changes: 9 additions & 6 deletions net/tipc/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
struct tipc_node *n_ptr, *temp_node;

spin_lock_bh(&tn->node_list_lock);

n_ptr = tipc_node_find(net, addr);
if (n_ptr)
goto exit;
n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
if (!n_ptr) {
spin_unlock_bh(&tn->node_list_lock);
pr_warn("Node creation failed, no memory\n");
return NULL;
goto exit;
}

n_ptr->addr = addr;
n_ptr->net = net;
spin_lock_init(&n_ptr->lock);
Expand All @@ -123,9 +123,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
list_add_tail_rcu(&n_ptr->list, &temp_node->list);
n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
n_ptr->signature = INVALID_NODE_SIG;

tn->num_nodes++;

exit:
spin_unlock_bh(&tn->node_list_lock);
return n_ptr;
}
Expand Down Expand Up @@ -406,6 +405,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
l_ptr->reset_checkpoint = l_ptr->next_in_no;
l_ptr->exp_msg_count = 0;
tipc_link_reset_fragments(l_ptr);

/* Link marked for deletion after failover? => do it now */
if (l_ptr->flags & LINK_STOPPED)
tipc_link_delete(l_ptr);
}

n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN;
Expand Down

0 comments on commit 251c005

Please sign in to comment.