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 | |
| 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')
| -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 | ||
