diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-11-02 23:56:40 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-11-02 23:56:40 -0400 |
commit | 31cbecb4ab538f433145bc5a46f3bea9b9627031 (patch) | |
tree | d6206d42dea7298f7ef05fd1f7bf474245f0d43a /net/tipc/link.c | |
parent | 2b72c9ccd22c4a3299e5a358dcd639fb253730f4 (diff) | |
parent | 278c023a99b0d6b471d0f4a79835c703482e29ac (diff) | |
download | linux-stable-31cbecb4ab538f433145bc5a46f3bea9b9627031.tar.gz linux-stable-31cbecb4ab538f433145bc5a46f3bea9b9627031.tar.bz2 linux-stable-31cbecb4ab538f433145bc5a46f3bea9b9627031.zip |
Merge branch 'osd-devel' into nfs-for-next
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r-- | net/tipc/link.c | 111 |
1 files changed, 80 insertions, 31 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index f89570c54f54..ae98a72da11a 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -332,15 +332,16 @@ struct link *tipc_link_create(struct tipc_node *n_ptr, l_ptr->addr = peer; if_name = strchr(b_ptr->name, ':') + 1; - sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", + sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown", tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), tipc_node(tipc_own_addr), if_name, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); - /* note: peer i/f is appended to link name by reset/activate */ + /* note: peer i/f name is updated by reset/activate message */ memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); l_ptr->owner = n_ptr; l_ptr->checkpoint = 1; + l_ptr->peer_session = INVALID_SESSION; l_ptr->b_ptr = b_ptr; link_set_supervision_props(l_ptr, b_ptr->media->tolerance); l_ptr->state = RESET_UNKNOWN; @@ -536,9 +537,6 @@ void tipc_link_stop(struct link *l_ptr) l_ptr->proto_msg_queue = NULL; } -/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ -#define link_send_event(fcn, l_ptr, up) do { } while (0) - void tipc_link_reset(struct link *l_ptr) { struct sk_buff *buf; @@ -596,10 +594,6 @@ void tipc_link_reset(struct link *l_ptr) l_ptr->fsm_msg_cnt = 0; l_ptr->stale_count = 0; link_reset_statistics(l_ptr); - - link_send_event(tipc_cfg_link_event, l_ptr, 0); - if (!in_own_cluster(l_ptr->addr)) - link_send_event(tipc_disc_link_event, l_ptr, 0); } @@ -608,9 +602,6 @@ static void link_activate(struct link *l_ptr) l_ptr->next_in_no = l_ptr->stats.recv_info = 1; tipc_node_link_up(l_ptr->owner, l_ptr); tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); - link_send_event(tipc_cfg_link_event, l_ptr, 1); - if (!in_own_cluster(l_ptr->addr)) - link_send_event(tipc_disc_link_event, l_ptr, 1); } /** @@ -985,6 +976,51 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) } /* + * tipc_link_send_names - send name table entries to new neighbor + * + * Send routine for bulk delivery of name table messages when contact + * with a new neighbor occurs. No link congestion checking is performed + * because name table messages *must* be delivered. The messages must be + * small enough not to require fragmentation. + * Called without any locks held. + */ + +void tipc_link_send_names(struct list_head *message_list, u32 dest) +{ + struct tipc_node *n_ptr; + struct link *l_ptr; + struct sk_buff *buf; + struct sk_buff *temp_buf; + + if (list_empty(message_list)) + return; + + read_lock_bh(&tipc_net_lock); + n_ptr = tipc_node_find(dest); + if (n_ptr) { + tipc_node_lock(n_ptr); + l_ptr = n_ptr->active_links[0]; + if (l_ptr) { + /* convert circular list to linear list */ + ((struct sk_buff *)message_list->prev)->next = NULL; + link_add_chain_to_outqueue(l_ptr, + (struct sk_buff *)message_list->next, 0); + tipc_link_push_queue(l_ptr); + INIT_LIST_HEAD(message_list); + } + tipc_node_unlock(n_ptr); + } + read_unlock_bh(&tipc_net_lock); + + /* discard the messages if they couldn't be sent */ + + list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { + list_del((struct list_head *)buf); + buf_discard(buf); + } +} + +/* * link_send_buf_fast: Entry for data messages where the * destination link is known and the header is complete, * inclusive total message length. Very time critical. @@ -1031,9 +1067,6 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) u32 selector = msg_origport(buf_msg(buf)) & 1; u32 dummy; - if (destnode == tipc_own_addr) - return tipc_port_recv_msg(buf); - read_lock_bh(&tipc_net_lock); n_ptr = tipc_node_find(destnode); if (likely(n_ptr)) { @@ -1658,19 +1691,12 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) continue; } + /* Discard unicast link messages destined for another node */ + if (unlikely(!msg_short(msg) && (msg_destnode(msg) != tipc_own_addr))) goto cont; - /* Discard non-routeable messages destined for another node */ - - if (unlikely(!msg_isdata(msg) && - (msg_destnode(msg) != tipc_own_addr))) { - if ((msg_user(msg) != CONN_MANAGER) && - (msg_user(msg) != MSG_FRAGMENTER)) - goto cont; - } - /* Locate neighboring node that sent message */ n_ptr = tipc_node_find(msg_prevnode(msg)); @@ -1678,17 +1704,24 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) goto cont; tipc_node_lock(n_ptr); - /* Don't talk to neighbor during cleanup after last session */ + /* Locate unicast link endpoint that should handle message */ - if (n_ptr->cleanup_required) { + l_ptr = n_ptr->links[b_ptr->identity]; + if (unlikely(!l_ptr)) { tipc_node_unlock(n_ptr); goto cont; } - /* Locate unicast link endpoint that should handle message */ + /* Verify that communication with node is currently allowed */ - l_ptr = n_ptr->links[b_ptr->identity]; - if (unlikely(!l_ptr)) { + if ((n_ptr->block_setup & WAIT_PEER_DOWN) && + msg_user(msg) == LINK_PROTOCOL && + (msg_type(msg) == RESET_MSG || + msg_type(msg) == ACTIVATE_MSG) && + !msg_redundant_link(msg)) + n_ptr->block_setup &= ~WAIT_PEER_DOWN; + + if (n_ptr->block_setup) { tipc_node_unlock(n_ptr); goto cont; } @@ -1923,6 +1956,12 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, if (link_blocked(l_ptr)) return; + + /* Abort non-RESET send if communication with node is prohibited */ + + if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) + return; + msg_set_type(msg, msg_typ); msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); @@ -2051,9 +2090,19 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) case RESET_MSG: if (!link_working_unknown(l_ptr) && (l_ptr->peer_session != INVALID_SESSION)) { - if (msg_session(msg) == l_ptr->peer_session) - break; /* duplicate: ignore */ + if (less_eq(msg_session(msg), l_ptr->peer_session)) + break; /* duplicate or old reset: ignore */ + } + + if (!msg_redundant_link(msg) && (link_working_working(l_ptr) || + link_working_unknown(l_ptr))) { + /* + * peer has lost contact -- don't allow peer's links + * to reactivate before we recognize loss & clean up + */ + l_ptr->owner->block_setup = WAIT_NODE_DOWN; } + /* fall thru' */ case ACTIVATE_MSG: /* Update link settings according other endpoint's values */ |