Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / net / tipc / node.c
index dd3b6dc17662fc42eb0b567501c6b9e8bee67031..3469b5d4ed32c8481cf97ea8153e241d28cb917c 100644 (file)
@@ -383,6 +383,11 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
                                tipc_link_update_caps(l, capabilities);
                }
                write_unlock_bh(&n->lock);
+               /* Calculate cluster capabilities */
+               tn->capabilities = TIPC_NODE_CAPABILITIES;
+               list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
+                       tn->capabilities &= temp_node->capabilities;
+               }
                goto exit;
        }
        n = kzalloc(sizeof(*n), GFP_ATOMIC);
@@ -433,6 +438,11 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
                        break;
        }
        list_add_tail_rcu(&n->list, &temp_node->list);
+       /* Calculate cluster capabilities */
+       tn->capabilities = TIPC_NODE_CAPABILITIES;
+       list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
+               tn->capabilities &= temp_node->capabilities;
+       }
        trace_tipc_node_create(n, true, " ");
 exit:
        spin_unlock_bh(&tn->node_list_lock);
@@ -589,6 +599,7 @@ static void  tipc_node_clear_links(struct tipc_node *node)
  */
 static bool tipc_node_cleanup(struct tipc_node *peer)
 {
+       struct tipc_node *temp_node;
        struct tipc_net *tn = tipc_net(peer->net);
        bool deleted = false;
 
@@ -604,6 +615,13 @@ static bool tipc_node_cleanup(struct tipc_node *peer)
                deleted = true;
        }
        tipc_node_write_unlock(peer);
+
+       /* Calculate cluster capabilities */
+       tn->capabilities = TIPC_NODE_CAPABILITIES;
+       list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
+               tn->capabilities &= temp_node->capabilities;
+       }
+
        spin_unlock_bh(&tn->node_list_lock);
        return deleted;
 }