diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2008-07-15 01:44:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-15 01:44:58 -0400 |
commit | 1aad72d6cd518872c5f545320823bf7f4dafb026 (patch) | |
tree | ae5e1f5e0fbd5bed8ed75ddf6184d4f7ec71354f | |
parent | 08d2cf0f74b3ee5e773bb906043a0efe96ded229 (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>
-rw-r--r-- | net/tipc/node.c | 29 |
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 | } |