aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2008-07-15 01:44:58 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-15 01:44:58 -0400
commit1aad72d6cd518872c5f545320823bf7f4dafb026 (patch)
treeae5e1f5e0fbd5bed8ed75ddf6184d4f7ec71354f /net/tipc/node.c
parent08d2cf0f74b3ee5e773bb906043a0efe96ded229 (diff)
tipc: Add missing locks when inspecting node list & link list
This patch ensures that TIPC configuration commands that display info about neighboring nodes and their links take the spinlocks that protect the node list and link lists from changing while the lists are being traversed. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 34e9a2bb7c19..ee952ad60218 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -600,12 +600,14 @@ u32 tipc_available_nodes(const u32 domain)
600 struct node *n_ptr; 600 struct node *n_ptr;
601 u32 cnt = 0; 601 u32 cnt = 0;
602 602
603 read_lock_bh(&tipc_net_lock);
603 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 604 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
604 if (!in_scope(domain, n_ptr->addr)) 605 if (!in_scope(domain, n_ptr->addr))
605 continue; 606 continue;
606 if (tipc_node_is_up(n_ptr)) 607 if (tipc_node_is_up(n_ptr))
607 cnt++; 608 cnt++;
608 } 609 }
610 read_unlock_bh(&tipc_net_lock);
609 return cnt; 611 return cnt;
610} 612}
611 613
@@ -625,19 +627,26 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
625 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 627 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
626 " (network address)"); 628 " (network address)");
627 629
628 if (!tipc_nodes) 630 read_lock_bh(&tipc_net_lock);
631 if (!tipc_nodes) {
632 read_unlock_bh(&tipc_net_lock);
629 return tipc_cfg_reply_none(); 633 return tipc_cfg_reply_none();
634 }
630 635
631 /* For now, get space for all other nodes 636 /* For now, get space for all other nodes
632 (will need to modify this when slave nodes are supported */ 637 (will need to modify this when slave nodes are supported */
633 638
634 payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); 639 payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1);
635 if (payload_size > 32768u) 640 if (payload_size > 32768u) {
641 read_unlock_bh(&tipc_net_lock);
636 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 642 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
637 " (too many nodes)"); 643 " (too many nodes)");
644 }
638 buf = tipc_cfg_reply_alloc(payload_size); 645 buf = tipc_cfg_reply_alloc(payload_size);
639 if (!buf) 646 if (!buf) {
647 read_unlock_bh(&tipc_net_lock);
640 return NULL; 648 return NULL;
649 }
641 650
642 /* Add TLVs for all nodes in scope */ 651 /* Add TLVs for all nodes in scope */
643 652
@@ -650,6 +659,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
650 &node_info, sizeof(node_info)); 659 &node_info, sizeof(node_info));
651 } 660 }
652 661
662 read_unlock_bh(&tipc_net_lock);
653 return buf; 663 return buf;
654} 664}
655 665
@@ -672,16 +682,22 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
672 if (tipc_mode != TIPC_NET_MODE) 682 if (tipc_mode != TIPC_NET_MODE)
673 return tipc_cfg_reply_none(); 683 return tipc_cfg_reply_none();
674 684
685 read_lock_bh(&tipc_net_lock);
686
675 /* Get space for all unicast links + multicast link */ 687 /* Get space for all unicast links + multicast link */
676 688
677 payload_size = TLV_SPACE(sizeof(link_info)) * 689 payload_size = TLV_SPACE(sizeof(link_info)) *
678 (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); 690 (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1);
679 if (payload_size > 32768u) 691 if (payload_size > 32768u) {
692 read_unlock_bh(&tipc_net_lock);
680 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 693 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
681 " (too many links)"); 694 " (too many links)");
695 }
682 buf = tipc_cfg_reply_alloc(payload_size); 696 buf = tipc_cfg_reply_alloc(payload_size);
683 if (!buf) 697 if (!buf) {
698 read_unlock_bh(&tipc_net_lock);
684 return NULL; 699 return NULL;
700 }
685 701
686 /* Add TLV for broadcast link */ 702 /* Add TLV for broadcast link */
687 703
@@ -697,6 +713,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
697 713
698 if (!in_scope(domain, n_ptr->addr)) 714 if (!in_scope(domain, n_ptr->addr))
699 continue; 715 continue;
716 tipc_node_lock(n_ptr);
700 for (i = 0; i < MAX_BEARERS; i++) { 717 for (i = 0; i < MAX_BEARERS; i++) {
701 if (!n_ptr->links[i]) 718 if (!n_ptr->links[i])
702 continue; 719 continue;
@@ -706,7 +723,9 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
706 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 723 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
707 &link_info, sizeof(link_info)); 724 &link_info, sizeof(link_info));
708 } 725 }
726 tipc_node_unlock(n_ptr);
709 } 727 }
710 728
729 read_unlock_bh(&tipc_net_lock);
711 return buf; 730 return buf;
712} 731}