diff options
author | Ying Xue <ying.xue@windriver.com> | 2014-12-02 02:00:24 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-08 20:39:56 -0500 |
commit | 993bfe5daf34c645a51348facdc7c28c55f488fe (patch) | |
tree | 004748177d0ee50bfad2e6b12f3364f7e047adf9 /net/tipc | |
parent | 1b61e70ad13e1c907f143c3b0a1694df640639c0 (diff) |
tipc: make name table allocated dynamically
Name table locking policy is going to be adjusted from read-write
lock protection to RCU lock protection in the future commits. But
its essential precondition is to convert the allocation way of name
table from static to dynamic mode.
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Tested-by: Erik Hugne <erik.hugne@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/name_distr.c | 44 | ||||
-rw-r--r-- | net/tipc/name_table.c | 60 | ||||
-rw-r--r-- | net/tipc/name_table.h | 16 |
3 files changed, 55 insertions, 65 deletions
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 628cd85b647e..ed00929f16c8 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -38,34 +38,6 @@ | |||
38 | #include "link.h" | 38 | #include "link.h" |
39 | #include "name_distr.h" | 39 | #include "name_distr.h" |
40 | 40 | ||
41 | /** | ||
42 | * struct publ_list - list of publications made by this node | ||
43 | * @list: circular list of publications | ||
44 | */ | ||
45 | struct publ_list { | ||
46 | struct list_head list; | ||
47 | }; | ||
48 | |||
49 | static struct publ_list publ_zone = { | ||
50 | .list = LIST_HEAD_INIT(publ_zone.list), | ||
51 | }; | ||
52 | |||
53 | static struct publ_list publ_cluster = { | ||
54 | .list = LIST_HEAD_INIT(publ_cluster.list), | ||
55 | }; | ||
56 | |||
57 | static struct publ_list publ_node = { | ||
58 | .list = LIST_HEAD_INIT(publ_node.list), | ||
59 | }; | ||
60 | |||
61 | static struct publ_list *publ_lists[] = { | ||
62 | NULL, | ||
63 | &publ_zone, /* publ_lists[TIPC_ZONE_SCOPE] */ | ||
64 | &publ_cluster, /* publ_lists[TIPC_CLUSTER_SCOPE] */ | ||
65 | &publ_node /* publ_lists[TIPC_NODE_SCOPE] */ | ||
66 | }; | ||
67 | |||
68 | |||
69 | int sysctl_tipc_named_timeout __read_mostly = 2000; | 41 | int sysctl_tipc_named_timeout __read_mostly = 2000; |
70 | 42 | ||
71 | /** | 43 | /** |
@@ -141,7 +113,8 @@ struct sk_buff *tipc_named_publish(struct publication *publ) | |||
141 | struct sk_buff *buf; | 113 | struct sk_buff *buf; |
142 | struct distr_item *item; | 114 | struct distr_item *item; |
143 | 115 | ||
144 | list_add_tail(&publ->local_list, &publ_lists[publ->scope]->list); | 116 | list_add_tail(&publ->local_list, |
117 | &tipc_nametbl->publ_list[publ->scope]); | ||
145 | 118 | ||
146 | if (publ->scope == TIPC_NODE_SCOPE) | 119 | if (publ->scope == TIPC_NODE_SCOPE) |
147 | return NULL; | 120 | return NULL; |
@@ -188,7 +161,7 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) | |||
188 | * @pls: linked list of publication items to be packed into buffer chain | 161 | * @pls: linked list of publication items to be packed into buffer chain |
189 | */ | 162 | */ |
190 | static void named_distribute(struct sk_buff_head *list, u32 dnode, | 163 | static void named_distribute(struct sk_buff_head *list, u32 dnode, |
191 | struct publ_list *pls) | 164 | struct list_head *pls) |
192 | { | 165 | { |
193 | struct publication *publ; | 166 | struct publication *publ; |
194 | struct sk_buff *skb = NULL; | 167 | struct sk_buff *skb = NULL; |
@@ -196,7 +169,7 @@ static void named_distribute(struct sk_buff_head *list, u32 dnode, | |||
196 | uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; | 169 | uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; |
197 | uint msg_rem = msg_dsz; | 170 | uint msg_rem = msg_dsz; |
198 | 171 | ||
199 | list_for_each_entry(publ, &pls->list, local_list) { | 172 | list_for_each_entry(publ, pls, local_list) { |
200 | /* Prepare next buffer: */ | 173 | /* Prepare next buffer: */ |
201 | if (!skb) { | 174 | if (!skb) { |
202 | skb = named_prepare_buf(PUBLICATION, msg_rem, dnode); | 175 | skb = named_prepare_buf(PUBLICATION, msg_rem, dnode); |
@@ -236,8 +209,10 @@ void tipc_named_node_up(u32 dnode) | |||
236 | __skb_queue_head_init(&head); | 209 | __skb_queue_head_init(&head); |
237 | 210 | ||
238 | read_lock_bh(&tipc_nametbl_lock); | 211 | read_lock_bh(&tipc_nametbl_lock); |
239 | named_distribute(&head, dnode, &publ_cluster); | 212 | named_distribute(&head, dnode, |
240 | named_distribute(&head, dnode, &publ_zone); | 213 | &tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); |
214 | named_distribute(&head, dnode, | ||
215 | &tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); | ||
241 | read_unlock_bh(&tipc_nametbl_lock); | 216 | read_unlock_bh(&tipc_nametbl_lock); |
242 | 217 | ||
243 | tipc_link_xmit(&head, dnode, dnode); | 218 | tipc_link_xmit(&head, dnode, dnode); |
@@ -427,7 +402,8 @@ void tipc_named_reinit(void) | |||
427 | write_lock_bh(&tipc_nametbl_lock); | 402 | write_lock_bh(&tipc_nametbl_lock); |
428 | 403 | ||
429 | for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) | 404 | for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) |
430 | list_for_each_entry(publ, &publ_lists[scope]->list, local_list) | 405 | list_for_each_entry(publ, &tipc_nametbl->publ_list[scope], |
406 | local_list) | ||
431 | publ->node = tipc_own_addr; | 407 | publ->node = tipc_own_addr; |
432 | 408 | ||
433 | write_unlock_bh(&tipc_nametbl_lock); | 409 | write_unlock_bh(&tipc_nametbl_lock); |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 772be1cd8bf6..df3da2924fc7 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/name_table.c: TIPC name table code | 2 | * net/tipc/name_table.c: TIPC name table code |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2006, 2014, Ericsson AB | 4 | * Copyright (c) 2000-2006, 2014, Ericsson AB |
5 | * Copyright (c) 2004-2008, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2004-2008, 2010-2014, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -103,18 +103,7 @@ struct name_seq { | |||
103 | spinlock_t lock; | 103 | spinlock_t lock; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | /** | 106 | struct name_table *tipc_nametbl; |
107 | * struct name_table - table containing all existing port name publications | ||
108 | * @types: pointer to fixed-sized array of name sequence lists, | ||
109 | * accessed via hashing on 'type'; name sequence lists are *not* sorted | ||
110 | * @local_publ_count: number of publications issued by this node | ||
111 | */ | ||
112 | struct name_table { | ||
113 | struct hlist_head *types; | ||
114 | u32 local_publ_count; | ||
115 | }; | ||
116 | |||
117 | static struct name_table table; | ||
118 | DEFINE_RWLOCK(tipc_nametbl_lock); | 107 | DEFINE_RWLOCK(tipc_nametbl_lock); |
119 | 108 | ||
120 | static int hash(int x) | 109 | static int hash(int x) |
@@ -475,7 +464,7 @@ static struct name_seq *nametbl_find_seq(u32 type) | |||
475 | struct hlist_head *seq_head; | 464 | struct hlist_head *seq_head; |
476 | struct name_seq *ns; | 465 | struct name_seq *ns; |
477 | 466 | ||
478 | seq_head = &table.types[hash(type)]; | 467 | seq_head = &tipc_nametbl->seq_hlist[hash(type)]; |
479 | hlist_for_each_entry(ns, seq_head, ns_list) { | 468 | hlist_for_each_entry(ns, seq_head, ns_list) { |
480 | if (ns->type == type) | 469 | if (ns->type == type) |
481 | return ns; | 470 | return ns; |
@@ -488,6 +477,7 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, | |||
488 | u32 scope, u32 node, u32 port, u32 key) | 477 | u32 scope, u32 node, u32 port, u32 key) |
489 | { | 478 | { |
490 | struct name_seq *seq = nametbl_find_seq(type); | 479 | struct name_seq *seq = nametbl_find_seq(type); |
480 | int index = hash(type); | ||
491 | 481 | ||
492 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE) || | 482 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE) || |
493 | (lower > upper)) { | 483 | (lower > upper)) { |
@@ -497,7 +487,8 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, | |||
497 | } | 487 | } |
498 | 488 | ||
499 | if (!seq) | 489 | if (!seq) |
500 | seq = tipc_nameseq_create(type, &table.types[hash(type)]); | 490 | seq = tipc_nameseq_create(type, |
491 | &tipc_nametbl->seq_hlist[index]); | ||
501 | if (!seq) | 492 | if (!seq) |
502 | return NULL; | 493 | return NULL; |
503 | 494 | ||
@@ -667,7 +658,7 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | |||
667 | struct publication *publ; | 658 | struct publication *publ; |
668 | struct sk_buff *buf = NULL; | 659 | struct sk_buff *buf = NULL; |
669 | 660 | ||
670 | if (table.local_publ_count >= TIPC_MAX_PUBLICATIONS) { | 661 | if (tipc_nametbl->local_publ_count >= TIPC_MAX_PUBLICATIONS) { |
671 | pr_warn("Publication failed, local publication limit reached (%u)\n", | 662 | pr_warn("Publication failed, local publication limit reached (%u)\n", |
672 | TIPC_MAX_PUBLICATIONS); | 663 | TIPC_MAX_PUBLICATIONS); |
673 | return NULL; | 664 | return NULL; |
@@ -677,7 +668,7 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | |||
677 | publ = tipc_nametbl_insert_publ(type, lower, upper, scope, | 668 | publ = tipc_nametbl_insert_publ(type, lower, upper, scope, |
678 | tipc_own_addr, port_ref, key); | 669 | tipc_own_addr, port_ref, key); |
679 | if (likely(publ)) { | 670 | if (likely(publ)) { |
680 | table.local_publ_count++; | 671 | tipc_nametbl->local_publ_count++; |
681 | buf = tipc_named_publish(publ); | 672 | buf = tipc_named_publish(publ); |
682 | /* Any pending external events? */ | 673 | /* Any pending external events? */ |
683 | tipc_named_process_backlog(); | 674 | tipc_named_process_backlog(); |
@@ -700,7 +691,7 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | |||
700 | write_lock_bh(&tipc_nametbl_lock); | 691 | write_lock_bh(&tipc_nametbl_lock); |
701 | publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); | 692 | publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); |
702 | if (likely(publ)) { | 693 | if (likely(publ)) { |
703 | table.local_publ_count--; | 694 | tipc_nametbl->local_publ_count--; |
704 | buf = tipc_named_withdraw(publ); | 695 | buf = tipc_named_withdraw(publ); |
705 | /* Any pending external events? */ | 696 | /* Any pending external events? */ |
706 | tipc_named_process_backlog(); | 697 | tipc_named_process_backlog(); |
@@ -725,12 +716,14 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | |||
725 | void tipc_nametbl_subscribe(struct tipc_subscription *s) | 716 | void tipc_nametbl_subscribe(struct tipc_subscription *s) |
726 | { | 717 | { |
727 | u32 type = s->seq.type; | 718 | u32 type = s->seq.type; |
719 | int index = hash(type); | ||
728 | struct name_seq *seq; | 720 | struct name_seq *seq; |
729 | 721 | ||
730 | write_lock_bh(&tipc_nametbl_lock); | 722 | write_lock_bh(&tipc_nametbl_lock); |
731 | seq = nametbl_find_seq(type); | 723 | seq = nametbl_find_seq(type); |
732 | if (!seq) | 724 | if (!seq) |
733 | seq = tipc_nameseq_create(type, &table.types[hash(type)]); | 725 | seq = tipc_nameseq_create(type, |
726 | &tipc_nametbl->seq_hlist[index]); | ||
734 | if (seq) { | 727 | if (seq) { |
735 | spin_lock_bh(&seq->lock); | 728 | spin_lock_bh(&seq->lock); |
736 | tipc_nameseq_subscribe(seq, s); | 729 | tipc_nameseq_subscribe(seq, s); |
@@ -882,7 +875,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info, | |||
882 | lowbound = 0; | 875 | lowbound = 0; |
883 | upbound = ~0; | 876 | upbound = ~0; |
884 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | 877 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
885 | seq_head = &table.types[i]; | 878 | seq_head = &tipc_nametbl->seq_hlist[i]; |
886 | hlist_for_each_entry(seq, seq_head, ns_list) { | 879 | hlist_for_each_entry(seq, seq_head, ns_list) { |
887 | ret += nameseq_list(seq, buf + ret, len - ret, | 880 | ret += nameseq_list(seq, buf + ret, len - ret, |
888 | depth, seq->type, | 881 | depth, seq->type, |
@@ -898,7 +891,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info, | |||
898 | } | 891 | } |
899 | ret += nametbl_header(buf + ret, len - ret, depth); | 892 | ret += nametbl_header(buf + ret, len - ret, depth); |
900 | i = hash(type); | 893 | i = hash(type); |
901 | seq_head = &table.types[i]; | 894 | seq_head = &tipc_nametbl->seq_hlist[i]; |
902 | hlist_for_each_entry(seq, seq_head, ns_list) { | 895 | hlist_for_each_entry(seq, seq_head, ns_list) { |
903 | if (seq->type == type) { | 896 | if (seq->type == type) { |
904 | ret += nameseq_list(seq, buf + ret, len - ret, | 897 | ret += nameseq_list(seq, buf + ret, len - ret, |
@@ -945,12 +938,18 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) | |||
945 | 938 | ||
946 | int tipc_nametbl_init(void) | 939 | int tipc_nametbl_init(void) |
947 | { | 940 | { |
948 | table.types = kcalloc(TIPC_NAMETBL_SIZE, sizeof(struct hlist_head), | 941 | int i; |
949 | GFP_ATOMIC); | 942 | |
950 | if (!table.types) | 943 | tipc_nametbl = kzalloc(sizeof(*tipc_nametbl), GFP_ATOMIC); |
944 | if (!tipc_nametbl) | ||
951 | return -ENOMEM; | 945 | return -ENOMEM; |
952 | 946 | ||
953 | table.local_publ_count = 0; | 947 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) |
948 | INIT_HLIST_HEAD(&tipc_nametbl->seq_hlist[i]); | ||
949 | |||
950 | INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); | ||
951 | INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); | ||
952 | INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_NODE_SCOPE]); | ||
954 | return 0; | 953 | return 0; |
955 | } | 954 | } |
956 | 955 | ||
@@ -990,16 +989,17 @@ void tipc_nametbl_stop(void) | |||
990 | */ | 989 | */ |
991 | write_lock_bh(&tipc_nametbl_lock); | 990 | write_lock_bh(&tipc_nametbl_lock); |
992 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | 991 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
993 | if (hlist_empty(&table.types[i])) | 992 | if (hlist_empty(&tipc_nametbl->seq_hlist[i])) |
994 | continue; | 993 | continue; |
995 | seq_head = &table.types[i]; | 994 | seq_head = &tipc_nametbl->seq_hlist[i]; |
996 | hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { | 995 | hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { |
997 | tipc_purge_publications(seq); | 996 | tipc_purge_publications(seq); |
998 | } | 997 | } |
999 | } | 998 | } |
1000 | kfree(table.types); | ||
1001 | table.types = NULL; | ||
1002 | write_unlock_bh(&tipc_nametbl_lock); | 999 | write_unlock_bh(&tipc_nametbl_lock); |
1000 | |||
1001 | kfree(tipc_nametbl); | ||
1002 | |||
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, | 1005 | static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, |
@@ -1113,7 +1113,7 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, | |||
1113 | i = 0; | 1113 | i = 0; |
1114 | 1114 | ||
1115 | for (; i < TIPC_NAMETBL_SIZE; i++) { | 1115 | for (; i < TIPC_NAMETBL_SIZE; i++) { |
1116 | seq_head = &table.types[i]; | 1116 | seq_head = &tipc_nametbl->seq_hlist[i]; |
1117 | 1117 | ||
1118 | if (*last_type) { | 1118 | if (*last_type) { |
1119 | seq = nametbl_find_seq(*last_type); | 1119 | seq = nametbl_find_seq(*last_type); |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index c62877826655..c1fd734eb0d5 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -43,7 +43,9 @@ struct tipc_port_list; | |||
43 | /* | 43 | /* |
44 | * TIPC name types reserved for internal TIPC use (both current and planned) | 44 | * TIPC name types reserved for internal TIPC use (both current and planned) |
45 | */ | 45 | */ |
46 | #define TIPC_ZM_SRV 3 /* zone master service name type */ | 46 | #define TIPC_ZM_SRV 3 /* zone master service name type */ |
47 | #define TIPC_PUBL_SCOPE_NUM (TIPC_NODE_SCOPE + 1) | ||
48 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ | ||
47 | 49 | ||
48 | /** | 50 | /** |
49 | * struct publication - info about a published (name or) name sequence | 51 | * struct publication - info about a published (name or) name sequence |
@@ -79,8 +81,20 @@ struct publication { | |||
79 | struct list_head zone_list; | 81 | struct list_head zone_list; |
80 | }; | 82 | }; |
81 | 83 | ||
84 | /** | ||
85 | * struct name_table - table containing all existing port name publications | ||
86 | * @seq_hlist: name sequence hash lists | ||
87 | * @publ_list: pulication lists | ||
88 | * @local_publ_count: number of publications issued by this node | ||
89 | */ | ||
90 | struct name_table { | ||
91 | struct hlist_head seq_hlist[TIPC_NAMETBL_SIZE]; | ||
92 | struct list_head publ_list[TIPC_PUBL_SCOPE_NUM]; | ||
93 | u32 local_publ_count; | ||
94 | }; | ||
82 | 95 | ||
83 | extern rwlock_t tipc_nametbl_lock; | 96 | extern rwlock_t tipc_nametbl_lock; |
97 | extern struct name_table *tipc_nametbl; | ||
84 | 98 | ||
85 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); | 99 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); |
86 | 100 | ||