diff options
author | David S. Miller <davem@davemloft.net> | 2018-03-31 22:19:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-03-31 22:19:59 -0400 |
commit | 6851cf28db1c4becc25a2906ecd080c0022a9f11 (patch) | |
tree | c1905f23eaf0b2aeb7195a78ca378bcb94414251 | |
parent | 24197ee2102359b59044234347dd3504302fa97d (diff) | |
parent | 7494cfa6d36d1556f17baa012dd93833620783db (diff) |
Merge branch 'tipc-slim-down-name-table'
Jon Maloy says:
====================
tipc: slim down name table
We clean up and improve the name binding table:
- Replace the memory consuming 'sub_sequence/service range' array with
an RB tree.
- Introduce support for overlapping service sequences/ranges
v2: #1: Fixed a missing initialization reported by David Miller
#4: Obsoleted and replaced a few more macros to get a consistent
terminology in the API.
#5: Added new commit to fix a potential string overflow bug (it
is still only in net-next) reported by Arnd Bergmann
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/uapi/linux/tipc.h | 59 | ||||
-rw-r--r-- | net/tipc/core.h | 1 | ||||
-rw-r--r-- | net/tipc/link.c | 5 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 90 | ||||
-rw-r--r-- | net/tipc/name_distr.h | 1 | ||||
-rw-r--r-- | net/tipc/name_table.c | 1075 | ||||
-rw-r--r-- | net/tipc/name_table.h | 10 | ||||
-rw-r--r-- | net/tipc/net.c | 2 | ||||
-rw-r--r-- | net/tipc/node.c | 4 | ||||
-rw-r--r-- | net/tipc/socket.c | 4 | ||||
-rw-r--r-- | net/tipc/subscr.h | 4 |
11 files changed, 556 insertions, 699 deletions
diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h index 4ac9f1f02b06..bf6d28677cfe 100644 --- a/include/uapi/linux/tipc.h +++ b/include/uapi/linux/tipc.h | |||
@@ -45,33 +45,33 @@ | |||
45 | * TIPC addressing primitives | 45 | * TIPC addressing primitives |
46 | */ | 46 | */ |
47 | 47 | ||
48 | struct tipc_portid { | 48 | struct tipc_socket_addr { |
49 | __u32 ref; | 49 | __u32 ref; |
50 | __u32 node; | 50 | __u32 node; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct tipc_name { | 53 | struct tipc_service_addr { |
54 | __u32 type; | 54 | __u32 type; |
55 | __u32 instance; | 55 | __u32 instance; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct tipc_name_seq { | 58 | struct tipc_service_range { |
59 | __u32 type; | 59 | __u32 type; |
60 | __u32 lower; | 60 | __u32 lower; |
61 | __u32 upper; | 61 | __u32 upper; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * Application-accessible port name types | 65 | * Application-accessible service types |
66 | */ | 66 | */ |
67 | 67 | ||
68 | #define TIPC_CFG_SRV 0 /* configuration service name type */ | 68 | #define TIPC_NODE_STATE 0 /* node state service type */ |
69 | #define TIPC_TOP_SRV 1 /* topology service name type */ | 69 | #define TIPC_TOP_SRV 1 /* topology server service type */ |
70 | #define TIPC_LINK_STATE 2 /* link state name type */ | 70 | #define TIPC_LINK_STATE 2 /* link state service type */ |
71 | #define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ | 71 | #define TIPC_RESERVED_TYPES 64 /* lowest user-allowed service type */ |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * Publication scopes when binding port names and port name sequences | 74 | * Publication scopes when binding service / service range |
75 | */ | 75 | */ |
76 | enum tipc_scope { | 76 | enum tipc_scope { |
77 | TIPC_CLUSTER_SCOPE = 2, /* 0 can also be used */ | 77 | TIPC_CLUSTER_SCOPE = 2, /* 0 can also be used */ |
@@ -108,28 +108,28 @@ enum tipc_scope { | |||
108 | * TIPC topology subscription service definitions | 108 | * TIPC topology subscription service definitions |
109 | */ | 109 | */ |
110 | 110 | ||
111 | #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ | 111 | #define TIPC_SUB_PORTS 0x01 /* filter: evt at each match */ |
112 | #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ | 112 | #define TIPC_SUB_SERVICE 0x02 /* filter: evt at first up/last down */ |
113 | #define TIPC_SUB_CANCEL 0x04 /* cancel a subscription */ | 113 | #define TIPC_SUB_CANCEL 0x04 /* filter: cancel a subscription */ |
114 | 114 | ||
115 | #define TIPC_WAIT_FOREVER (~0) /* timeout for permanent subscription */ | 115 | #define TIPC_WAIT_FOREVER (~0) /* timeout for permanent subscription */ |
116 | 116 | ||
117 | struct tipc_subscr { | 117 | struct tipc_subscr { |
118 | struct tipc_name_seq seq; /* name sequence of interest */ | 118 | struct tipc_service_range seq; /* range of interest */ |
119 | __u32 timeout; /* subscription duration (in ms) */ | 119 | __u32 timeout; /* subscription duration (in ms) */ |
120 | __u32 filter; /* bitmask of filter options */ | 120 | __u32 filter; /* bitmask of filter options */ |
121 | char usr_handle[8]; /* available for subscriber use */ | 121 | char usr_handle[8]; /* available for subscriber use */ |
122 | }; | 122 | }; |
123 | 123 | ||
124 | #define TIPC_PUBLISHED 1 /* publication event */ | 124 | #define TIPC_PUBLISHED 1 /* publication event */ |
125 | #define TIPC_WITHDRAWN 2 /* withdraw event */ | 125 | #define TIPC_WITHDRAWN 2 /* withdrawal event */ |
126 | #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ | 126 | #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ |
127 | 127 | ||
128 | struct tipc_event { | 128 | struct tipc_event { |
129 | __u32 event; /* event type */ | 129 | __u32 event; /* event type */ |
130 | __u32 found_lower; /* matching name seq instances */ | 130 | __u32 found_lower; /* matching range */ |
131 | __u32 found_upper; /* " " " " */ | 131 | __u32 found_upper; /* " " */ |
132 | struct tipc_portid port; /* associated port */ | 132 | struct tipc_socket_addr port; /* associated socket */ |
133 | struct tipc_subscr s; /* associated subscription */ | 133 | struct tipc_subscr s; /* associated subscription */ |
134 | }; | 134 | }; |
135 | 135 | ||
@@ -149,20 +149,20 @@ struct tipc_event { | |||
149 | #define SOL_TIPC 271 | 149 | #define SOL_TIPC 271 |
150 | #endif | 150 | #endif |
151 | 151 | ||
152 | #define TIPC_ADDR_NAMESEQ 1 | 152 | #define TIPC_ADDR_MCAST 1 |
153 | #define TIPC_ADDR_MCAST 1 | 153 | #define TIPC_SERVICE_RANGE 1 |
154 | #define TIPC_ADDR_NAME 2 | 154 | #define TIPC_SERVICE_ADDR 2 |
155 | #define TIPC_ADDR_ID 3 | 155 | #define TIPC_SOCKET_ADDR 3 |
156 | 156 | ||
157 | struct sockaddr_tipc { | 157 | struct sockaddr_tipc { |
158 | unsigned short family; | 158 | unsigned short family; |
159 | unsigned char addrtype; | 159 | unsigned char addrtype; |
160 | signed char scope; | 160 | signed char scope; |
161 | union { | 161 | union { |
162 | struct tipc_portid id; | 162 | struct tipc_socket_addr id; |
163 | struct tipc_name_seq nameseq; | 163 | struct tipc_service_range nameseq; |
164 | struct { | 164 | struct { |
165 | struct tipc_name name; | 165 | struct tipc_service_addr name; |
166 | __u32 domain; | 166 | __u32 domain; |
167 | } name; | 167 | } name; |
168 | } addr; | 168 | } addr; |
@@ -216,7 +216,7 @@ struct tipc_group_req { | |||
216 | #define TIPC_MAX_MEDIA_NAME 16 | 216 | #define TIPC_MAX_MEDIA_NAME 16 |
217 | #define TIPC_MAX_IF_NAME 16 | 217 | #define TIPC_MAX_IF_NAME 16 |
218 | #define TIPC_MAX_BEARER_NAME 32 | 218 | #define TIPC_MAX_BEARER_NAME 32 |
219 | #define TIPC_MAX_LINK_NAME 60 | 219 | #define TIPC_MAX_LINK_NAME 68 |
220 | 220 | ||
221 | #define SIOCGETLINKNAME SIOCPROTOPRIVATE | 221 | #define SIOCGETLINKNAME SIOCPROTOPRIVATE |
222 | 222 | ||
@@ -230,8 +230,13 @@ struct tipc_sioc_ln_req { | |||
230 | /* The macros and functions below are deprecated: | 230 | /* The macros and functions below are deprecated: |
231 | */ | 231 | */ |
232 | 232 | ||
233 | #define TIPC_CFG_SRV 0 | ||
233 | #define TIPC_ZONE_SCOPE 1 | 234 | #define TIPC_ZONE_SCOPE 1 |
234 | 235 | ||
236 | #define TIPC_ADDR_NAMESEQ 1 | ||
237 | #define TIPC_ADDR_NAME 2 | ||
238 | #define TIPC_ADDR_ID 3 | ||
239 | |||
235 | #define TIPC_NODE_BITS 12 | 240 | #define TIPC_NODE_BITS 12 |
236 | #define TIPC_CLUSTER_BITS 12 | 241 | #define TIPC_CLUSTER_BITS 12 |
237 | #define TIPC_ZONE_BITS 8 | 242 | #define TIPC_ZONE_BITS 8 |
@@ -250,6 +255,10 @@ struct tipc_sioc_ln_req { | |||
250 | 255 | ||
251 | #define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK) | 256 | #define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK) |
252 | 257 | ||
258 | #define tipc_portid tipc_socket_addr | ||
259 | #define tipc_name tipc_service_addr | ||
260 | #define tipc_name_seq tipc_service_range | ||
261 | |||
253 | static inline __u32 tipc_addr(unsigned int zone, | 262 | static inline __u32 tipc_addr(unsigned int zone, |
254 | unsigned int cluster, | 263 | unsigned int cluster, |
255 | unsigned int node) | 264 | unsigned int node) |
diff --git a/net/tipc/core.h b/net/tipc/core.h index d0f64ca62d02..8020a6c360ff 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/etherdevice.h> | 58 | #include <linux/etherdevice.h> |
59 | #include <net/netns/generic.h> | 59 | #include <net/netns/generic.h> |
60 | #include <linux/rhashtable.h> | 60 | #include <linux/rhashtable.h> |
61 | #include <net/genetlink.h> | ||
61 | 62 | ||
62 | struct tipc_node; | 63 | struct tipc_node; |
63 | struct tipc_bearer; | 64 | struct tipc_bearer; |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 1289b4ba404f..695acb783969 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -462,7 +462,8 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | |||
462 | sprintf(peer_str, "%x", peer); | 462 | sprintf(peer_str, "%x", peer); |
463 | } | 463 | } |
464 | /* Peer i/f name will be completed by reset/activate message */ | 464 | /* Peer i/f name will be completed by reset/activate message */ |
465 | sprintf(l->name, "%s:%s-%s:unknown", self_str, if_name, peer_str); | 465 | snprintf(l->name, sizeof(l->name), "%s:%s-%s:unknown", |
466 | self_str, if_name, peer_str); | ||
466 | 467 | ||
467 | strcpy(l->if_name, if_name); | 468 | strcpy(l->if_name, if_name); |
468 | l->addr = peer; | 469 | l->addr = peer; |
@@ -1810,7 +1811,7 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1810 | 1811 | ||
1811 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) | 1812 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) |
1812 | { | 1813 | { |
1813 | int max_bulk = TIPC_MAX_PUBLICATIONS / (l->mtu / ITEM_SIZE); | 1814 | int max_bulk = TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE); |
1814 | 1815 | ||
1815 | l->window = win; | 1816 | l->window = win; |
1816 | l->backlog[TIPC_LOW_IMPORTANCE].limit = max_t(u16, 50, win); | 1817 | l->backlog[TIPC_LOW_IMPORTANCE].limit = max_t(u16, 50, win); |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 8240a85b0d0c..51b4b96f89db 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -204,12 +204,12 @@ void tipc_named_node_up(struct net *net, u32 dnode) | |||
204 | */ | 204 | */ |
205 | static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) | 205 | static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) |
206 | { | 206 | { |
207 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 207 | struct tipc_net *tn = tipc_net(net); |
208 | struct publication *p; | 208 | struct publication *p; |
209 | 209 | ||
210 | spin_lock_bh(&tn->nametbl_lock); | 210 | spin_lock_bh(&tn->nametbl_lock); |
211 | p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, | 211 | p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, publ->upper, |
212 | publ->node, publ->port, publ->key); | 212 | publ->node, publ->key); |
213 | if (p) | 213 | if (p) |
214 | tipc_node_unsubscribe(net, &p->binding_node, addr); | 214 | tipc_node_unsubscribe(net, &p->binding_node, addr); |
215 | spin_unlock_bh(&tn->nametbl_lock); | 215 | spin_unlock_bh(&tn->nametbl_lock); |
@@ -261,28 +261,31 @@ void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr) | |||
261 | static bool tipc_update_nametbl(struct net *net, struct distr_item *i, | 261 | static bool tipc_update_nametbl(struct net *net, struct distr_item *i, |
262 | u32 node, u32 dtype) | 262 | u32 node, u32 dtype) |
263 | { | 263 | { |
264 | struct publication *publ = NULL; | 264 | struct publication *p = NULL; |
265 | u32 lower = ntohl(i->lower); | ||
266 | u32 upper = ntohl(i->upper); | ||
267 | u32 type = ntohl(i->type); | ||
268 | u32 port = ntohl(i->port); | ||
269 | u32 key = ntohl(i->key); | ||
265 | 270 | ||
266 | if (dtype == PUBLICATION) { | 271 | if (dtype == PUBLICATION) { |
267 | publ = tipc_nametbl_insert_publ(net, ntohl(i->type), | 272 | p = tipc_nametbl_insert_publ(net, type, lower, upper, |
268 | ntohl(i->lower), | 273 | TIPC_CLUSTER_SCOPE, node, |
269 | ntohl(i->upper), | 274 | port, key); |
270 | TIPC_CLUSTER_SCOPE, node, | 275 | if (p) { |
271 | ntohl(i->port), ntohl(i->key)); | 276 | tipc_node_subscribe(net, &p->binding_node, node); |
272 | if (publ) { | ||
273 | tipc_node_subscribe(net, &publ->binding_node, node); | ||
274 | return true; | 277 | return true; |
275 | } | 278 | } |
276 | } else if (dtype == WITHDRAWAL) { | 279 | } else if (dtype == WITHDRAWAL) { |
277 | publ = tipc_nametbl_remove_publ(net, ntohl(i->type), | 280 | p = tipc_nametbl_remove_publ(net, type, lower, |
278 | ntohl(i->lower), | 281 | upper, node, key); |
279 | node, ntohl(i->port), | 282 | if (p) { |
280 | ntohl(i->key)); | 283 | tipc_node_unsubscribe(net, &p->binding_node, node); |
281 | if (publ) { | 284 | kfree_rcu(p, rcu); |
282 | tipc_node_unsubscribe(net, &publ->binding_node, node); | ||
283 | kfree_rcu(publ, rcu); | ||
284 | return true; | 285 | return true; |
285 | } | 286 | } |
287 | pr_warn_ratelimited("Failed to remove binding %u,%u from %x\n", | ||
288 | type, lower, node); | ||
286 | } else { | 289 | } else { |
287 | pr_warn("Unrecognized name table message received\n"); | 290 | pr_warn("Unrecognized name table message received\n"); |
288 | } | 291 | } |
@@ -290,53 +293,6 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, | |||
290 | } | 293 | } |
291 | 294 | ||
292 | /** | 295 | /** |
293 | * tipc_named_add_backlog - add a failed name table update to the backlog | ||
294 | * | ||
295 | */ | ||
296 | static void tipc_named_add_backlog(struct net *net, struct distr_item *i, | ||
297 | u32 type, u32 node) | ||
298 | { | ||
299 | struct distr_queue_item *e; | ||
300 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
301 | unsigned long now = get_jiffies_64(); | ||
302 | |||
303 | e = kzalloc(sizeof(*e), GFP_ATOMIC); | ||
304 | if (!e) | ||
305 | return; | ||
306 | e->dtype = type; | ||
307 | e->node = node; | ||
308 | e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout); | ||
309 | memcpy(e, i, sizeof(*i)); | ||
310 | list_add_tail(&e->next, &tn->dist_queue); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * tipc_named_process_backlog - try to process any pending name table updates | ||
315 | * from the network. | ||
316 | */ | ||
317 | void tipc_named_process_backlog(struct net *net) | ||
318 | { | ||
319 | struct distr_queue_item *e, *tmp; | ||
320 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
321 | unsigned long now = get_jiffies_64(); | ||
322 | |||
323 | list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) { | ||
324 | if (time_after(e->expires, now)) { | ||
325 | if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype)) | ||
326 | continue; | ||
327 | } else { | ||
328 | pr_warn_ratelimited("Dropping name table update (%d) of {%u, %u, %u} from %x key=%u\n", | ||
329 | e->dtype, ntohl(e->i.type), | ||
330 | ntohl(e->i.lower), | ||
331 | ntohl(e->i.upper), | ||
332 | e->node, ntohl(e->i.key)); | ||
333 | } | ||
334 | list_del(&e->next); | ||
335 | kfree(e); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * tipc_named_rcv - process name table update messages sent by another node | 296 | * tipc_named_rcv - process name table update messages sent by another node |
341 | */ | 297 | */ |
342 | void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) | 298 | void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) |
@@ -358,12 +314,10 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) | |||
358 | count = msg_data_sz(msg) / ITEM_SIZE; | 314 | count = msg_data_sz(msg) / ITEM_SIZE; |
359 | node = msg_orignode(msg); | 315 | node = msg_orignode(msg); |
360 | while (count--) { | 316 | while (count--) { |
361 | if (!tipc_update_nametbl(net, item, node, mtype)) | 317 | tipc_update_nametbl(net, item, node, mtype); |
362 | tipc_named_add_backlog(net, item, mtype, node); | ||
363 | item++; | 318 | item++; |
364 | } | 319 | } |
365 | kfree_skb(skb); | 320 | kfree_skb(skb); |
366 | tipc_named_process_backlog(net); | ||
367 | } | 321 | } |
368 | spin_unlock_bh(&tn->nametbl_lock); | 322 | spin_unlock_bh(&tn->nametbl_lock); |
369 | } | 323 | } |
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 4753e628d7c4..63fc73e0fa6c 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h | |||
@@ -72,7 +72,6 @@ struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ); | |||
72 | void tipc_named_node_up(struct net *net, u32 dnode); | 72 | void tipc_named_node_up(struct net *net, u32 dnode); |
73 | void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); | 73 | void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); |
74 | void tipc_named_reinit(struct net *net); | 74 | void tipc_named_reinit(struct net *net); |
75 | void tipc_named_process_backlog(struct net *net); | ||
76 | void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr); | 75 | void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr); |
77 | 76 | ||
78 | #endif | 77 | #endif |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 4359605b1bec..b1fe20972aa9 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -44,52 +44,40 @@ | |||
44 | #include "addr.h" | 44 | #include "addr.h" |
45 | #include "node.h" | 45 | #include "node.h" |
46 | #include "group.h" | 46 | #include "group.h" |
47 | #include <net/genetlink.h> | ||
48 | |||
49 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ | ||
50 | 47 | ||
51 | /** | 48 | /** |
52 | * struct name_info - name sequence publication info | 49 | * struct service_range - container for all bindings of a service range |
53 | * @node_list: list of publications on own node of this <type,lower,upper> | 50 | * @lower: service range lower bound |
54 | * @all_publ: list of all publications of this <type,lower,upper> | 51 | * @upper: service range upper bound |
52 | * @tree_node: member of service range RB tree | ||
53 | * @local_publ: list of identical publications made from this node | ||
54 | * Used by closest_first lookup and multicast lookup algorithm | ||
55 | * @all_publ: all publications identical to this one, whatever node and scope | ||
56 | * Used by round-robin lookup algorithm | ||
55 | */ | 57 | */ |
56 | struct name_info { | 58 | struct service_range { |
57 | struct list_head local_publ; | ||
58 | struct list_head all_publ; | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * struct sub_seq - container for all published instances of a name sequence | ||
63 | * @lower: name sequence lower bound | ||
64 | * @upper: name sequence upper bound | ||
65 | * @info: pointer to name sequence publication info | ||
66 | */ | ||
67 | struct sub_seq { | ||
68 | u32 lower; | 59 | u32 lower; |
69 | u32 upper; | 60 | u32 upper; |
70 | struct name_info *info; | 61 | struct rb_node tree_node; |
62 | struct list_head local_publ; | ||
63 | struct list_head all_publ; | ||
71 | }; | 64 | }; |
72 | 65 | ||
73 | /** | 66 | /** |
74 | * struct name_seq - container for all published instances of a name type | 67 | * struct tipc_service - container for all published instances of a service type |
75 | * @type: 32 bit 'type' value for name sequence | 68 | * @type: 32 bit 'type' value for service |
76 | * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; | 69 | * @ranges: rb tree containing all service ranges for this service |
77 | * sub-sequences are sorted in ascending order | 70 | * @service_list: links to adjacent name ranges in hash chain |
78 | * @alloc: number of sub-sequences currently in array | 71 | * @subscriptions: list of subscriptions for this service type |
79 | * @first_free: array index of first unused sub-sequence entry | 72 | * @lock: spinlock controlling access to pertaining service ranges/publications |
80 | * @ns_list: links to adjacent name sequences in hash chain | ||
81 | * @subscriptions: list of subscriptions for this 'type' | ||
82 | * @lock: spinlock controlling access to publication lists of all sub-sequences | ||
83 | * @rcu: RCU callback head used for deferred freeing | 73 | * @rcu: RCU callback head used for deferred freeing |
84 | */ | 74 | */ |
85 | struct name_seq { | 75 | struct tipc_service { |
86 | u32 type; | 76 | u32 type; |
87 | struct sub_seq *sseqs; | 77 | struct rb_root ranges; |
88 | u32 alloc; | 78 | struct hlist_node service_list; |
89 | u32 first_free; | ||
90 | struct hlist_node ns_list; | ||
91 | struct list_head subscriptions; | 79 | struct list_head subscriptions; |
92 | spinlock_t lock; | 80 | spinlock_t lock; /* Covers service range list */ |
93 | struct rcu_head rcu; | 81 | struct rcu_head rcu; |
94 | }; | 82 | }; |
95 | 83 | ||
@@ -99,17 +87,16 @@ static int hash(int x) | |||
99 | } | 87 | } |
100 | 88 | ||
101 | /** | 89 | /** |
102 | * publ_create - create a publication structure | 90 | * tipc_publ_create - create a publication structure |
103 | */ | 91 | */ |
104 | static struct publication *publ_create(u32 type, u32 lower, u32 upper, | 92 | static struct publication *tipc_publ_create(u32 type, u32 lower, u32 upper, |
105 | u32 scope, u32 node, u32 port, | 93 | u32 scope, u32 node, u32 port, |
106 | u32 key) | 94 | u32 key) |
107 | { | 95 | { |
108 | struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC); | 96 | struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC); |
109 | if (publ == NULL) { | 97 | |
110 | pr_warn("Publication creation failure, no memory\n"); | 98 | if (!publ) |
111 | return NULL; | 99 | return NULL; |
112 | } | ||
113 | 100 | ||
114 | publ->type = type; | 101 | publ->type = type; |
115 | publ->lower = lower; | 102 | publ->lower = lower; |
@@ -119,446 +106,360 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, | |||
119 | publ->port = port; | 106 | publ->port = port; |
120 | publ->key = key; | 107 | publ->key = key; |
121 | INIT_LIST_HEAD(&publ->binding_sock); | 108 | INIT_LIST_HEAD(&publ->binding_sock); |
109 | INIT_LIST_HEAD(&publ->binding_node); | ||
110 | INIT_LIST_HEAD(&publ->local_publ); | ||
111 | INIT_LIST_HEAD(&publ->all_publ); | ||
122 | return publ; | 112 | return publ; |
123 | } | 113 | } |
124 | 114 | ||
125 | /** | 115 | /** |
126 | * tipc_subseq_alloc - allocate a specified number of sub-sequence structures | 116 | * tipc_service_create - create a service structure for the specified 'type' |
127 | */ | ||
128 | static struct sub_seq *tipc_subseq_alloc(u32 cnt) | ||
129 | { | ||
130 | return kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * tipc_nameseq_create - create a name sequence structure for the specified 'type' | ||
135 | * | 117 | * |
136 | * Allocates a single sub-sequence structure and sets it to all 0's. | 118 | * Allocates a single range structure and sets it to all 0's. |
137 | */ | 119 | */ |
138 | static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head) | 120 | static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd) |
139 | { | 121 | { |
140 | struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC); | 122 | struct tipc_service *service = kzalloc(sizeof(*service), GFP_ATOMIC); |
141 | struct sub_seq *sseq = tipc_subseq_alloc(1); | ||
142 | 123 | ||
143 | if (!nseq || !sseq) { | 124 | if (!service) { |
144 | pr_warn("Name sequence creation failed, no memory\n"); | 125 | pr_warn("Service creation failed, no memory\n"); |
145 | kfree(nseq); | ||
146 | kfree(sseq); | ||
147 | return NULL; | 126 | return NULL; |
148 | } | 127 | } |
149 | 128 | ||
150 | spin_lock_init(&nseq->lock); | 129 | spin_lock_init(&service->lock); |
151 | nseq->type = type; | 130 | service->type = type; |
152 | nseq->sseqs = sseq; | 131 | service->ranges = RB_ROOT; |
153 | nseq->alloc = 1; | 132 | INIT_HLIST_NODE(&service->service_list); |
154 | INIT_HLIST_NODE(&nseq->ns_list); | 133 | INIT_LIST_HEAD(&service->subscriptions); |
155 | INIT_LIST_HEAD(&nseq->subscriptions); | 134 | hlist_add_head_rcu(&service->service_list, hd); |
156 | hlist_add_head_rcu(&nseq->ns_list, seq_head); | 135 | return service; |
157 | return nseq; | ||
158 | } | 136 | } |
159 | 137 | ||
160 | /** | 138 | /** |
161 | * nameseq_find_subseq - find sub-sequence (if any) matching a name instance | 139 | * tipc_service_find_range - find service range matching a service instance |
162 | * | 140 | * |
163 | * Very time-critical, so binary searches through sub-sequence array. | 141 | * Very time-critical, so binary search through range rb tree |
164 | */ | 142 | */ |
165 | static struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, | 143 | static struct service_range *tipc_service_find_range(struct tipc_service *sc, |
166 | u32 instance) | 144 | u32 instance) |
167 | { | 145 | { |
168 | struct sub_seq *sseqs = nseq->sseqs; | 146 | struct rb_node *n = sc->ranges.rb_node; |
169 | int low = 0; | 147 | struct service_range *sr; |
170 | int high = nseq->first_free - 1; | 148 | |
171 | int mid; | 149 | while (n) { |
172 | 150 | sr = container_of(n, struct service_range, tree_node); | |
173 | while (low <= high) { | 151 | if (sr->lower > instance) |
174 | mid = (low + high) / 2; | 152 | n = n->rb_left; |
175 | if (instance < sseqs[mid].lower) | 153 | else if (sr->upper < instance) |
176 | high = mid - 1; | 154 | n = n->rb_right; |
177 | else if (instance > sseqs[mid].upper) | ||
178 | low = mid + 1; | ||
179 | else | 155 | else |
180 | return &sseqs[mid]; | 156 | return sr; |
181 | } | 157 | } |
182 | return NULL; | 158 | return NULL; |
183 | } | 159 | } |
184 | 160 | ||
185 | /** | 161 | static struct service_range *tipc_service_create_range(struct tipc_service *sc, |
186 | * nameseq_locate_subseq - determine position of name instance in sub-sequence | 162 | u32 lower, u32 upper) |
187 | * | ||
188 | * Returns index in sub-sequence array of the entry that contains the specified | ||
189 | * instance value; if no entry contains that value, returns the position | ||
190 | * where a new entry for it would be inserted in the array. | ||
191 | * | ||
192 | * Note: Similar to binary search code for locating a sub-sequence. | ||
193 | */ | ||
194 | static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) | ||
195 | { | 163 | { |
196 | struct sub_seq *sseqs = nseq->sseqs; | 164 | struct rb_node **n, *parent = NULL; |
197 | int low = 0; | 165 | struct service_range *sr, *tmp; |
198 | int high = nseq->first_free - 1; | 166 | |
199 | int mid; | 167 | n = &sc->ranges.rb_node; |
200 | 168 | while (*n) { | |
201 | while (low <= high) { | 169 | tmp = container_of(*n, struct service_range, tree_node); |
202 | mid = (low + high) / 2; | 170 | parent = *n; |
203 | if (instance < sseqs[mid].lower) | 171 | tmp = container_of(parent, struct service_range, tree_node); |
204 | high = mid - 1; | 172 | if (lower < tmp->lower) |
205 | else if (instance > sseqs[mid].upper) | 173 | n = &(*n)->rb_left; |
206 | low = mid + 1; | 174 | else if (lower > tmp->lower) |
175 | n = &(*n)->rb_right; | ||
176 | else if (upper < tmp->upper) | ||
177 | n = &(*n)->rb_left; | ||
178 | else if (upper > tmp->upper) | ||
179 | n = &(*n)->rb_right; | ||
207 | else | 180 | else |
208 | return mid; | 181 | return tmp; |
209 | } | 182 | } |
210 | return low; | 183 | sr = kzalloc(sizeof(*sr), GFP_ATOMIC); |
184 | if (!sr) | ||
185 | return NULL; | ||
186 | sr->lower = lower; | ||
187 | sr->upper = upper; | ||
188 | INIT_LIST_HEAD(&sr->local_publ); | ||
189 | INIT_LIST_HEAD(&sr->all_publ); | ||
190 | rb_link_node(&sr->tree_node, parent, n); | ||
191 | rb_insert_color(&sr->tree_node, &sc->ranges); | ||
192 | return sr; | ||
211 | } | 193 | } |
212 | 194 | ||
213 | /** | 195 | static struct publication *tipc_service_insert_publ(struct net *net, |
214 | * tipc_nameseq_insert_publ | 196 | struct tipc_service *sc, |
215 | */ | ||
216 | static struct publication *tipc_nameseq_insert_publ(struct net *net, | ||
217 | struct name_seq *nseq, | ||
218 | u32 type, u32 lower, | 197 | u32 type, u32 lower, |
219 | u32 upper, u32 scope, | 198 | u32 upper, u32 scope, |
220 | u32 node, u32 port, u32 key) | 199 | u32 node, u32 port, |
200 | u32 key) | ||
221 | { | 201 | { |
222 | struct tipc_subscription *s; | 202 | struct tipc_subscription *sub, *tmp; |
223 | struct tipc_subscription *st; | 203 | struct service_range *sr; |
224 | struct publication *publ; | 204 | struct publication *p; |
225 | struct sub_seq *sseq; | 205 | bool first = false; |
226 | struct name_info *info; | ||
227 | int created_subseq = 0; | ||
228 | |||
229 | sseq = nameseq_find_subseq(nseq, lower); | ||
230 | if (sseq) { | ||
231 | |||
232 | /* Lower end overlaps existing entry => need an exact match */ | ||
233 | if ((sseq->lower != lower) || (sseq->upper != upper)) { | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | info = sseq->info; | ||
238 | 206 | ||
239 | /* Check if an identical publication already exists */ | 207 | sr = tipc_service_create_range(sc, lower, upper); |
240 | list_for_each_entry(publ, &info->all_publ, all_publ) { | 208 | if (!sr) |
241 | if (publ->port == port && publ->key == key && | 209 | goto err; |
242 | (!publ->node || publ->node == node)) | ||
243 | return NULL; | ||
244 | } | ||
245 | } else { | ||
246 | u32 inspos; | ||
247 | struct sub_seq *freesseq; | ||
248 | 210 | ||
249 | /* Find where lower end should be inserted */ | 211 | first = list_empty(&sr->all_publ); |
250 | inspos = nameseq_locate_subseq(nseq, lower); | ||
251 | 212 | ||
252 | /* Fail if upper end overlaps into an existing entry */ | 213 | /* Return if the publication already exists */ |
253 | if ((inspos < nseq->first_free) && | 214 | list_for_each_entry(p, &sr->all_publ, all_publ) { |
254 | (upper >= nseq->sseqs[inspos].lower)) { | 215 | if (p->key == key && (!p->node || p->node == node)) |
255 | return NULL; | 216 | return NULL; |
256 | } | ||
257 | |||
258 | /* Ensure there is space for new sub-sequence */ | ||
259 | if (nseq->first_free == nseq->alloc) { | ||
260 | struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2); | ||
261 | |||
262 | if (!sseqs) { | ||
263 | pr_warn("Cannot publish {%u,%u,%u}, no memory\n", | ||
264 | type, lower, upper); | ||
265 | return NULL; | ||
266 | } | ||
267 | memcpy(sseqs, nseq->sseqs, | ||
268 | nseq->alloc * sizeof(struct sub_seq)); | ||
269 | kfree(nseq->sseqs); | ||
270 | nseq->sseqs = sseqs; | ||
271 | nseq->alloc *= 2; | ||
272 | } | ||
273 | |||
274 | info = kzalloc(sizeof(*info), GFP_ATOMIC); | ||
275 | if (!info) { | ||
276 | pr_warn("Cannot publish {%u,%u,%u}, no memory\n", | ||
277 | type, lower, upper); | ||
278 | return NULL; | ||
279 | } | ||
280 | |||
281 | INIT_LIST_HEAD(&info->local_publ); | ||
282 | INIT_LIST_HEAD(&info->all_publ); | ||
283 | |||
284 | /* Insert new sub-sequence */ | ||
285 | sseq = &nseq->sseqs[inspos]; | ||
286 | freesseq = &nseq->sseqs[nseq->first_free]; | ||
287 | memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof(*sseq)); | ||
288 | memset(sseq, 0, sizeof(*sseq)); | ||
289 | nseq->first_free++; | ||
290 | sseq->lower = lower; | ||
291 | sseq->upper = upper; | ||
292 | sseq->info = info; | ||
293 | created_subseq = 1; | ||
294 | } | 217 | } |
295 | 218 | ||
296 | /* Insert a publication */ | 219 | /* Create and insert publication */ |
297 | publ = publ_create(type, lower, upper, scope, node, port, key); | 220 | p = tipc_publ_create(type, lower, upper, scope, node, port, key); |
298 | if (!publ) | 221 | if (!p) |
299 | return NULL; | 222 | goto err; |
300 | |||
301 | list_add(&publ->all_publ, &info->all_publ); | ||
302 | |||
303 | if (in_own_node(net, node)) | 223 | if (in_own_node(net, node)) |
304 | list_add(&publ->local_publ, &info->local_publ); | 224 | list_add(&p->local_publ, &sr->local_publ); |
225 | list_add(&p->all_publ, &sr->all_publ); | ||
305 | 226 | ||
306 | /* Any subscriptions waiting for notification? */ | 227 | /* Any subscriptions waiting for notification? */ |
307 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | 228 | list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { |
308 | tipc_sub_report_overlap(s, publ->lower, publ->upper, | 229 | tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_PUBLISHED, |
309 | TIPC_PUBLISHED, publ->port, | 230 | p->port, p->node, p->scope, first); |
310 | publ->node, publ->scope, | ||
311 | created_subseq); | ||
312 | } | 231 | } |
313 | return publ; | 232 | return p; |
233 | err: | ||
234 | pr_warn("Failed to bind to %u,%u,%u, no memory\n", type, lower, upper); | ||
235 | return NULL; | ||
314 | } | 236 | } |
315 | 237 | ||
316 | /** | 238 | /** |
317 | * tipc_nameseq_remove_publ | 239 | * tipc_service_remove_publ - remove a publication from a service |
318 | * | ||
319 | * NOTE: There may be cases where TIPC is asked to remove a publication | ||
320 | * that is not in the name table. For example, if another node issues a | ||
321 | * publication for a name sequence that overlaps an existing name sequence | ||
322 | * the publication will not be recorded, which means the publication won't | ||
323 | * be found when the name sequence is later withdrawn by that node. | ||
324 | * A failed withdraw request simply returns a failure indication and lets the | ||
325 | * caller issue any error or warning messages associated with such a problem. | ||
326 | */ | 240 | */ |
327 | static struct publication *tipc_nameseq_remove_publ(struct net *net, | 241 | static struct publication *tipc_service_remove_publ(struct net *net, |
328 | struct name_seq *nseq, | 242 | struct tipc_service *sc, |
329 | u32 inst, u32 node, | 243 | u32 lower, u32 upper, |
330 | u32 port, u32 key) | 244 | u32 node, u32 key) |
331 | { | 245 | { |
332 | struct publication *publ; | 246 | struct tipc_subscription *sub, *tmp; |
333 | struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); | 247 | struct service_range *sr; |
334 | struct name_info *info; | 248 | struct publication *p; |
335 | struct sub_seq *free; | 249 | bool found = false; |
336 | struct tipc_subscription *s, *st; | 250 | bool last = false; |
337 | int removed_subseq = 0; | 251 | struct rb_node *n; |
338 | 252 | ||
339 | if (!sseq) | 253 | sr = tipc_service_find_range(sc, lower); |
254 | if (!sr) | ||
340 | return NULL; | 255 | return NULL; |
341 | 256 | ||
342 | info = sseq->info; | 257 | /* Find exact matching service range */ |
258 | for (n = &sr->tree_node; n; n = rb_next(n)) { | ||
259 | sr = container_of(n, struct service_range, tree_node); | ||
260 | if (sr->upper == upper) | ||
261 | break; | ||
262 | } | ||
263 | if (!n || sr->lower != lower || sr->upper != upper) | ||
264 | return NULL; | ||
343 | 265 | ||
344 | /* Locate publication, if it exists */ | 266 | /* Find publication, if it exists */ |
345 | list_for_each_entry(publ, &info->all_publ, all_publ) { | 267 | list_for_each_entry(p, &sr->all_publ, all_publ) { |
346 | if (publ->key == key && publ->port == port && | 268 | if (p->key != key || (node && node != p->node)) |
347 | (!publ->node || publ->node == node)) | 269 | continue; |
348 | goto found; | 270 | found = true; |
271 | break; | ||
349 | } | 272 | } |
350 | return NULL; | 273 | if (!found) |
274 | return NULL; | ||
351 | 275 | ||
352 | found: | 276 | list_del(&p->all_publ); |
353 | list_del(&publ->all_publ); | 277 | list_del(&p->local_publ); |
354 | if (in_own_node(net, node)) | 278 | |
355 | list_del(&publ->local_publ); | 279 | /* Remove service range item if this was its last publication */ |
356 | 280 | if (list_empty(&sr->all_publ)) { | |
357 | /* Contract subseq list if no more publications for that subseq */ | 281 | last = true; |
358 | if (list_empty(&info->all_publ)) { | 282 | rb_erase(&sr->tree_node, &sc->ranges); |
359 | kfree(info); | 283 | kfree(sr); |
360 | free = &nseq->sseqs[nseq->first_free--]; | ||
361 | memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq)); | ||
362 | removed_subseq = 1; | ||
363 | } | 284 | } |
364 | 285 | ||
365 | /* Notify any waiting subscriptions */ | 286 | /* Notify any waiting subscriptions */ |
366 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | 287 | list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { |
367 | tipc_sub_report_overlap(s, publ->lower, publ->upper, | 288 | tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_WITHDRAWN, |
368 | TIPC_WITHDRAWN, publ->port, | 289 | p->port, p->node, p->scope, last); |
369 | publ->node, publ->scope, | ||
370 | removed_subseq); | ||
371 | } | 290 | } |
372 | 291 | return p; | |
373 | return publ; | ||
374 | } | 292 | } |
375 | 293 | ||
376 | /** | 294 | /** |
377 | * tipc_nameseq_subscribe - attach a subscription, and optionally | 295 | * tipc_service_subscribe - attach a subscription, and optionally |
378 | * issue the prescribed number of events if there is any sub- | 296 | * issue the prescribed number of events if there is any service |
379 | * sequence overlapping with the requested sequence | 297 | * range overlapping with the requested range |
380 | */ | 298 | */ |
381 | static void tipc_nameseq_subscribe(struct name_seq *nseq, | 299 | static void tipc_service_subscribe(struct tipc_service *service, |
382 | struct tipc_subscription *sub) | 300 | struct tipc_subscription *sub) |
383 | { | 301 | { |
384 | struct sub_seq *sseq = nseq->sseqs; | 302 | struct tipc_subscr *sb = &sub->evt.s; |
303 | struct service_range *sr; | ||
385 | struct tipc_name_seq ns; | 304 | struct tipc_name_seq ns; |
386 | struct tipc_subscr *s = &sub->evt.s; | 305 | struct publication *p; |
387 | bool no_status; | 306 | struct rb_node *n; |
307 | bool first; | ||
388 | 308 | ||
389 | ns.type = tipc_sub_read(s, seq.type); | 309 | ns.type = tipc_sub_read(sb, seq.type); |
390 | ns.lower = tipc_sub_read(s, seq.lower); | 310 | ns.lower = tipc_sub_read(sb, seq.lower); |
391 | ns.upper = tipc_sub_read(s, seq.upper); | 311 | ns.upper = tipc_sub_read(sb, seq.upper); |
392 | no_status = tipc_sub_read(s, filter) & TIPC_SUB_NO_STATUS; | ||
393 | 312 | ||
394 | tipc_sub_get(sub); | 313 | tipc_sub_get(sub); |
395 | list_add(&sub->nameseq_list, &nseq->subscriptions); | 314 | list_add(&sub->service_list, &service->subscriptions); |
396 | 315 | ||
397 | if (no_status || !sseq) | 316 | if (tipc_sub_read(sb, filter) & TIPC_SUB_NO_STATUS) |
398 | return; | 317 | return; |
399 | 318 | ||
400 | while (sseq != &nseq->sseqs[nseq->first_free]) { | 319 | for (n = rb_first(&service->ranges); n; n = rb_next(n)) { |
401 | if (tipc_sub_check_overlap(&ns, sseq->lower, sseq->upper)) { | 320 | sr = container_of(n, struct service_range, tree_node); |
402 | struct publication *crs; | 321 | if (sr->lower > ns.upper) |
403 | struct name_info *info = sseq->info; | 322 | break; |
404 | int must_report = 1; | 323 | if (!tipc_sub_check_overlap(&ns, sr->lower, sr->upper)) |
405 | 324 | continue; | |
406 | list_for_each_entry(crs, &info->all_publ, all_publ) { | 325 | first = true; |
407 | tipc_sub_report_overlap(sub, sseq->lower, | 326 | |
408 | sseq->upper, | 327 | list_for_each_entry(p, &sr->all_publ, all_publ) { |
409 | TIPC_PUBLISHED, | 328 | tipc_sub_report_overlap(sub, sr->lower, sr->upper, |
410 | crs->port, | 329 | TIPC_PUBLISHED, p->port, |
411 | crs->node, | 330 | p->node, p->scope, first); |
412 | crs->scope, | 331 | first = false; |
413 | must_report); | ||
414 | must_report = 0; | ||
415 | } | ||
416 | } | 332 | } |
417 | sseq++; | ||
418 | } | 333 | } |
419 | } | 334 | } |
420 | 335 | ||
421 | static struct name_seq *nametbl_find_seq(struct net *net, u32 type) | 336 | static struct tipc_service *tipc_service_find(struct net *net, u32 type) |
422 | { | 337 | { |
423 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 338 | struct name_table *nt = tipc_name_table(net); |
424 | struct hlist_head *seq_head; | 339 | struct hlist_head *service_head; |
425 | struct name_seq *ns; | 340 | struct tipc_service *service; |
426 | 341 | ||
427 | seq_head = &tn->nametbl->seq_hlist[hash(type)]; | 342 | service_head = &nt->services[hash(type)]; |
428 | hlist_for_each_entry_rcu(ns, seq_head, ns_list) { | 343 | hlist_for_each_entry_rcu(service, service_head, service_list) { |
429 | if (ns->type == type) | 344 | if (service->type == type) |
430 | return ns; | 345 | return service; |
431 | } | 346 | } |
432 | |||
433 | return NULL; | 347 | return NULL; |
434 | }; | 348 | }; |
435 | 349 | ||
436 | struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, | 350 | struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, |
437 | u32 lower, u32 upper, u32 scope, | 351 | u32 lower, u32 upper, |
438 | u32 node, u32 port, u32 key) | 352 | u32 scope, u32 node, |
353 | u32 port, u32 key) | ||
439 | { | 354 | { |
440 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 355 | struct name_table *nt = tipc_name_table(net); |
441 | struct publication *publ; | 356 | struct tipc_service *sc; |
442 | struct name_seq *seq = nametbl_find_seq(net, type); | 357 | struct publication *p; |
443 | int index = hash(type); | ||
444 | 358 | ||
445 | if (scope > TIPC_NODE_SCOPE || lower > upper) { | 359 | if (scope > TIPC_NODE_SCOPE || lower > upper) { |
446 | pr_debug("Failed to publish illegal {%u,%u,%u} with scope %u\n", | 360 | pr_debug("Failed to bind illegal {%u,%u,%u} with scope %u\n", |
447 | type, lower, upper, scope); | 361 | type, lower, upper, scope); |
448 | return NULL; | 362 | return NULL; |
449 | } | 363 | } |
450 | 364 | sc = tipc_service_find(net, type); | |
451 | if (!seq) | 365 | if (!sc) |
452 | seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]); | 366 | sc = tipc_service_create(type, &nt->services[hash(type)]); |
453 | if (!seq) | 367 | if (!sc) |
454 | return NULL; | 368 | return NULL; |
455 | 369 | ||
456 | spin_lock_bh(&seq->lock); | 370 | spin_lock_bh(&sc->lock); |
457 | publ = tipc_nameseq_insert_publ(net, seq, type, lower, upper, | 371 | p = tipc_service_insert_publ(net, sc, type, lower, upper, |
458 | scope, node, port, key); | 372 | scope, node, port, key); |
459 | spin_unlock_bh(&seq->lock); | 373 | spin_unlock_bh(&sc->lock); |
460 | return publ; | 374 | return p; |
461 | } | 375 | } |
462 | 376 | ||
463 | struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, | 377 | struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, |
464 | u32 lower, u32 node, u32 port, | 378 | u32 lower, u32 upper, |
465 | u32 key) | 379 | u32 node, u32 key) |
466 | { | 380 | { |
467 | struct publication *publ; | 381 | struct tipc_service *sc = tipc_service_find(net, type); |
468 | struct name_seq *seq = nametbl_find_seq(net, type); | 382 | struct publication *p = NULL; |
469 | 383 | ||
470 | if (!seq) | 384 | if (!sc) |
471 | return NULL; | 385 | return NULL; |
472 | 386 | ||
473 | spin_lock_bh(&seq->lock); | 387 | spin_lock_bh(&sc->lock); |
474 | publ = tipc_nameseq_remove_publ(net, seq, lower, node, port, key); | 388 | p = tipc_service_remove_publ(net, sc, lower, upper, node, key); |
475 | if (!seq->first_free && list_empty(&seq->subscriptions)) { | 389 | |
476 | hlist_del_init_rcu(&seq->ns_list); | 390 | /* Delete service item if this no more publications and subscriptions */ |
477 | kfree(seq->sseqs); | 391 | if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { |
478 | spin_unlock_bh(&seq->lock); | 392 | hlist_del_init_rcu(&sc->service_list); |
479 | kfree_rcu(seq, rcu); | 393 | kfree_rcu(sc, rcu); |
480 | return publ; | ||
481 | } | 394 | } |
482 | spin_unlock_bh(&seq->lock); | 395 | spin_unlock_bh(&sc->lock); |
483 | return publ; | 396 | return p; |
484 | } | 397 | } |
485 | 398 | ||
486 | /** | 399 | /** |
487 | * tipc_nametbl_translate - perform name translation | 400 | * tipc_nametbl_translate - perform service instance to socket translation |
488 | * | 401 | * |
489 | * On entry, 'destnode' is the search domain used during translation. | 402 | * On entry, 'dnode' is the search domain used during translation. |
490 | * | 403 | * |
491 | * On exit: | 404 | * On exit: |
492 | * - if name translation is deferred to another node/cluster/zone, | 405 | * - if translation is deferred to another node, leave 'dnode' unchanged and |
493 | * leaves 'destnode' unchanged (will be non-zero) and returns 0 | 406 | * return 0 |
494 | * - if name translation is attempted and succeeds, sets 'destnode' | 407 | * - if translation is attempted and succeeds, set 'dnode' to the publishing |
495 | * to publishing node and returns port reference (will be non-zero) | 408 | * node and return the published (non-zero) port number |
496 | * - if name translation is attempted and fails, sets 'destnode' to 0 | 409 | * - if translation is attempted and fails, set 'dnode' to 0 and return 0 |
497 | * and returns 0 | 410 | * |
411 | * Note that for legacy users (node configured with Z.C.N address format) the | ||
412 | * 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0 | ||
413 | * we must look in the local binding list first | ||
498 | */ | 414 | */ |
499 | u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, | 415 | u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode) |
500 | u32 *destnode) | ||
501 | { | 416 | { |
502 | struct tipc_net *tn = tipc_net(net); | 417 | struct tipc_net *tn = tipc_net(net); |
503 | bool legacy = tn->legacy_addr_format; | 418 | bool legacy = tn->legacy_addr_format; |
504 | u32 self = tipc_own_addr(net); | 419 | u32 self = tipc_own_addr(net); |
505 | struct sub_seq *sseq; | 420 | struct service_range *sr; |
506 | struct name_info *info; | 421 | struct tipc_service *sc; |
507 | struct publication *publ; | 422 | struct list_head *list; |
508 | struct name_seq *seq; | 423 | struct publication *p; |
509 | u32 port = 0; | 424 | u32 port = 0; |
510 | u32 node = 0; | 425 | u32 node = 0; |
511 | 426 | ||
512 | if (!tipc_in_scope(legacy, *destnode, self)) | 427 | if (!tipc_in_scope(legacy, *dnode, self)) |
513 | return 0; | 428 | return 0; |
514 | 429 | ||
515 | rcu_read_lock(); | 430 | rcu_read_lock(); |
516 | seq = nametbl_find_seq(net, type); | 431 | sc = tipc_service_find(net, type); |
517 | if (unlikely(!seq)) | 432 | if (unlikely(!sc)) |
518 | goto not_found; | 433 | goto not_found; |
519 | spin_lock_bh(&seq->lock); | 434 | |
520 | sseq = nameseq_find_subseq(seq, instance); | 435 | spin_lock_bh(&sc->lock); |
521 | if (unlikely(!sseq)) | 436 | sr = tipc_service_find_range(sc, instance); |
437 | if (unlikely(!sr)) | ||
522 | goto no_match; | 438 | goto no_match; |
523 | info = sseq->info; | ||
524 | |||
525 | /* Closest-First Algorithm */ | ||
526 | if (legacy && !*destnode) { | ||
527 | if (!list_empty(&info->local_publ)) { | ||
528 | publ = list_first_entry(&info->local_publ, | ||
529 | struct publication, | ||
530 | local_publ); | ||
531 | list_move_tail(&publ->local_publ, | ||
532 | &info->local_publ); | ||
533 | } else { | ||
534 | publ = list_first_entry(&info->all_publ, | ||
535 | struct publication, | ||
536 | all_publ); | ||
537 | list_move_tail(&publ->all_publ, | ||
538 | &info->all_publ); | ||
539 | } | ||
540 | } | ||
541 | 439 | ||
542 | /* Round-Robin Algorithm */ | 440 | /* Select lookup algorithm: local, closest-first or round-robin */ |
543 | else if (*destnode == tipc_own_addr(net)) { | 441 | if (*dnode == self) { |
544 | if (list_empty(&info->local_publ)) | 442 | list = &sr->local_publ; |
443 | if (list_empty(list)) | ||
545 | goto no_match; | 444 | goto no_match; |
546 | publ = list_first_entry(&info->local_publ, struct publication, | 445 | p = list_first_entry(list, struct publication, local_publ); |
547 | local_publ); | 446 | list_move_tail(&p->local_publ, &sr->local_publ); |
548 | list_move_tail(&publ->local_publ, &info->local_publ); | 447 | } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) { |
448 | list = &sr->local_publ; | ||
449 | p = list_first_entry(list, struct publication, local_publ); | ||
450 | list_move_tail(&p->local_publ, &sr->local_publ); | ||
549 | } else { | 451 | } else { |
550 | publ = list_first_entry(&info->all_publ, struct publication, | 452 | list = &sr->all_publ; |
551 | all_publ); | 453 | p = list_first_entry(list, struct publication, all_publ); |
552 | list_move_tail(&publ->all_publ, &info->all_publ); | 454 | list_move_tail(&p->all_publ, &sr->all_publ); |
553 | } | 455 | } |
554 | 456 | port = p->port; | |
555 | port = publ->port; | 457 | node = p->node; |
556 | node = publ->node; | ||
557 | no_match: | 458 | no_match: |
558 | spin_unlock_bh(&seq->lock); | 459 | spin_unlock_bh(&sc->lock); |
559 | not_found: | 460 | not_found: |
560 | rcu_read_unlock(); | 461 | rcu_read_unlock(); |
561 | *destnode = node; | 462 | *dnode = node; |
562 | return port; | 463 | return port; |
563 | } | 464 | } |
564 | 465 | ||
@@ -567,34 +468,36 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope, | |||
567 | bool all) | 468 | bool all) |
568 | { | 469 | { |
569 | u32 self = tipc_own_addr(net); | 470 | u32 self = tipc_own_addr(net); |
570 | struct publication *publ; | 471 | struct service_range *sr; |
571 | struct name_info *info; | 472 | struct tipc_service *sc; |
572 | struct name_seq *seq; | 473 | struct publication *p; |
573 | struct sub_seq *sseq; | ||
574 | 474 | ||
575 | *dstcnt = 0; | 475 | *dstcnt = 0; |
576 | rcu_read_lock(); | 476 | rcu_read_lock(); |
577 | seq = nametbl_find_seq(net, type); | 477 | sc = tipc_service_find(net, type); |
578 | if (unlikely(!seq)) | 478 | if (unlikely(!sc)) |
579 | goto exit; | 479 | goto exit; |
580 | spin_lock_bh(&seq->lock); | 480 | |
581 | sseq = nameseq_find_subseq(seq, instance); | 481 | spin_lock_bh(&sc->lock); |
582 | if (likely(sseq)) { | 482 | |
583 | info = sseq->info; | 483 | sr = tipc_service_find_range(sc, instance); |
584 | list_for_each_entry(publ, &info->all_publ, all_publ) { | 484 | if (!sr) |
585 | if (publ->scope != scope) | 485 | goto no_match; |
586 | continue; | 486 | |
587 | if (publ->port == exclude && publ->node == self) | 487 | list_for_each_entry(p, &sr->all_publ, all_publ) { |
588 | continue; | 488 | if (p->scope != scope) |
589 | tipc_dest_push(dsts, publ->node, publ->port); | 489 | continue; |
590 | (*dstcnt)++; | 490 | if (p->port == exclude && p->node == self) |
591 | if (all) | 491 | continue; |
592 | continue; | 492 | tipc_dest_push(dsts, p->node, p->port); |
593 | list_move_tail(&publ->all_publ, &info->all_publ); | 493 | (*dstcnt)++; |
594 | break; | 494 | if (all) |
595 | } | 495 | continue; |
496 | list_move_tail(&p->all_publ, &sr->all_publ); | ||
497 | break; | ||
596 | } | 498 | } |
597 | spin_unlock_bh(&seq->lock); | 499 | no_match: |
500 | spin_unlock_bh(&sc->lock); | ||
598 | exit: | 501 | exit: |
599 | rcu_read_unlock(); | 502 | rcu_read_unlock(); |
600 | return !list_empty(dsts); | 503 | return !list_empty(dsts); |
@@ -603,61 +506,64 @@ exit: | |||
603 | void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper, | 506 | void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper, |
604 | u32 scope, bool exact, struct list_head *dports) | 507 | u32 scope, bool exact, struct list_head *dports) |
605 | { | 508 | { |
606 | struct sub_seq *sseq_stop; | 509 | struct service_range *sr; |
607 | struct name_info *info; | 510 | struct tipc_service *sc; |
608 | struct publication *p; | 511 | struct publication *p; |
609 | struct name_seq *seq; | 512 | struct rb_node *n; |
610 | struct sub_seq *sseq; | ||
611 | 513 | ||
612 | rcu_read_lock(); | 514 | rcu_read_lock(); |
613 | seq = nametbl_find_seq(net, type); | 515 | sc = tipc_service_find(net, type); |
614 | if (!seq) | 516 | if (!sc) |
615 | goto exit; | 517 | goto exit; |
616 | 518 | ||
617 | spin_lock_bh(&seq->lock); | 519 | spin_lock_bh(&sc->lock); |
618 | sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); | 520 | |
619 | sseq_stop = seq->sseqs + seq->first_free; | 521 | for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { |
620 | for (; sseq != sseq_stop; sseq++) { | 522 | sr = container_of(n, struct service_range, tree_node); |
621 | if (sseq->lower > upper) | 523 | if (sr->upper < lower) |
524 | continue; | ||
525 | if (sr->lower > upper) | ||
622 | break; | 526 | break; |
623 | info = sseq->info; | 527 | list_for_each_entry(p, &sr->local_publ, local_publ) { |
624 | list_for_each_entry(p, &info->local_publ, local_publ) { | ||
625 | if (p->scope == scope || (!exact && p->scope < scope)) | 528 | if (p->scope == scope || (!exact && p->scope < scope)) |
626 | tipc_dest_push(dports, 0, p->port); | 529 | tipc_dest_push(dports, 0, p->port); |
627 | } | 530 | } |
628 | } | 531 | } |
629 | spin_unlock_bh(&seq->lock); | 532 | spin_unlock_bh(&sc->lock); |
630 | exit: | 533 | exit: |
631 | rcu_read_unlock(); | 534 | rcu_read_unlock(); |
632 | } | 535 | } |
633 | 536 | ||
634 | /* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes | 537 | /* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes |
635 | * - Creates list of nodes that overlap the given multicast address | 538 | * - Creates list of nodes that overlap the given multicast address |
636 | * - Determines if any node local ports overlap | 539 | * - Determines if any node local destinations overlap |
637 | */ | 540 | */ |
638 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, | 541 | void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, |
639 | u32 upper, struct tipc_nlist *nodes) | 542 | u32 upper, struct tipc_nlist *nodes) |
640 | { | 543 | { |
641 | struct sub_seq *sseq, *stop; | 544 | struct service_range *sr; |
642 | struct publication *publ; | 545 | struct tipc_service *sc; |
643 | struct name_info *info; | 546 | struct publication *p; |
644 | struct name_seq *seq; | 547 | struct rb_node *n; |
645 | 548 | ||
646 | rcu_read_lock(); | 549 | rcu_read_lock(); |
647 | seq = nametbl_find_seq(net, type); | 550 | sc = tipc_service_find(net, type); |
648 | if (!seq) | 551 | if (!sc) |
649 | goto exit; | 552 | goto exit; |
650 | 553 | ||
651 | spin_lock_bh(&seq->lock); | 554 | spin_lock_bh(&sc->lock); |
652 | sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); | 555 | |
653 | stop = seq->sseqs + seq->first_free; | 556 | for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { |
654 | for (; sseq != stop && sseq->lower <= upper; sseq++) { | 557 | sr = container_of(n, struct service_range, tree_node); |
655 | info = sseq->info; | 558 | if (sr->upper < lower) |
656 | list_for_each_entry(publ, &info->all_publ, all_publ) { | 559 | continue; |
657 | tipc_nlist_add(nodes, publ->node); | 560 | if (sr->lower > upper) |
561 | break; | ||
562 | list_for_each_entry(p, &sr->all_publ, all_publ) { | ||
563 | tipc_nlist_add(nodes, p->node); | ||
658 | } | 564 | } |
659 | } | 565 | } |
660 | spin_unlock_bh(&seq->lock); | 566 | spin_unlock_bh(&sc->lock); |
661 | exit: | 567 | exit: |
662 | rcu_read_unlock(); | 568 | rcu_read_unlock(); |
663 | } | 569 | } |
@@ -667,90 +573,85 @@ exit: | |||
667 | void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, | 573 | void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, |
668 | u32 type, u32 scope) | 574 | u32 type, u32 scope) |
669 | { | 575 | { |
670 | struct sub_seq *sseq, *stop; | 576 | struct service_range *sr; |
671 | struct name_info *info; | 577 | struct tipc_service *sc; |
672 | struct publication *p; | 578 | struct publication *p; |
673 | struct name_seq *seq; | 579 | struct rb_node *n; |
674 | 580 | ||
675 | rcu_read_lock(); | 581 | rcu_read_lock(); |
676 | seq = nametbl_find_seq(net, type); | 582 | sc = tipc_service_find(net, type); |
677 | if (!seq) | 583 | if (!sc) |
678 | goto exit; | 584 | goto exit; |
679 | 585 | ||
680 | spin_lock_bh(&seq->lock); | 586 | spin_lock_bh(&sc->lock); |
681 | sseq = seq->sseqs; | 587 | for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { |
682 | stop = seq->sseqs + seq->first_free; | 588 | sr = container_of(n, struct service_range, tree_node); |
683 | for (; sseq != stop; sseq++) { | 589 | list_for_each_entry(p, &sr->all_publ, all_publ) { |
684 | info = sseq->info; | ||
685 | list_for_each_entry(p, &info->all_publ, all_publ) { | ||
686 | if (p->scope != scope) | 590 | if (p->scope != scope) |
687 | continue; | 591 | continue; |
688 | tipc_group_add_member(grp, p->node, p->port, p->lower); | 592 | tipc_group_add_member(grp, p->node, p->port, p->lower); |
689 | } | 593 | } |
690 | } | 594 | } |
691 | spin_unlock_bh(&seq->lock); | 595 | spin_unlock_bh(&sc->lock); |
692 | exit: | 596 | exit: |
693 | rcu_read_unlock(); | 597 | rcu_read_unlock(); |
694 | } | 598 | } |
695 | 599 | ||
696 | /* | 600 | /* tipc_nametbl_publish - add service binding to name table |
697 | * tipc_nametbl_publish - add name publication to network name tables | ||
698 | */ | 601 | */ |
699 | struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, | 602 | struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, |
700 | u32 upper, u32 scope, u32 port_ref, | 603 | u32 upper, u32 scope, u32 port, |
701 | u32 key) | 604 | u32 key) |
702 | { | 605 | { |
703 | struct publication *publ; | 606 | struct name_table *nt = tipc_name_table(net); |
704 | struct sk_buff *buf = NULL; | 607 | struct tipc_net *tn = tipc_net(net); |
705 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 608 | struct publication *p = NULL; |
609 | struct sk_buff *skb = NULL; | ||
706 | 610 | ||
707 | spin_lock_bh(&tn->nametbl_lock); | 611 | spin_lock_bh(&tn->nametbl_lock); |
708 | if (tn->nametbl->local_publ_count >= TIPC_MAX_PUBLICATIONS) { | 612 | |
709 | pr_warn("Publication failed, local publication limit reached (%u)\n", | 613 | if (nt->local_publ_count >= TIPC_MAX_PUBL) { |
710 | TIPC_MAX_PUBLICATIONS); | 614 | pr_warn("Bind failed, max limit %u reached\n", TIPC_MAX_PUBL); |
711 | spin_unlock_bh(&tn->nametbl_lock); | 615 | goto exit; |
712 | return NULL; | ||
713 | } | 616 | } |
714 | 617 | ||
715 | publ = tipc_nametbl_insert_publ(net, type, lower, upper, scope, | 618 | p = tipc_nametbl_insert_publ(net, type, lower, upper, scope, |
716 | tipc_own_addr(net), port_ref, key); | 619 | tipc_own_addr(net), port, key); |
717 | if (likely(publ)) { | 620 | if (p) { |
718 | tn->nametbl->local_publ_count++; | 621 | nt->local_publ_count++; |
719 | buf = tipc_named_publish(net, publ); | 622 | skb = tipc_named_publish(net, p); |
720 | /* Any pending external events? */ | ||
721 | tipc_named_process_backlog(net); | ||
722 | } | 623 | } |
624 | exit: | ||
723 | spin_unlock_bh(&tn->nametbl_lock); | 625 | spin_unlock_bh(&tn->nametbl_lock); |
724 | 626 | ||
725 | if (buf) | 627 | if (skb) |
726 | tipc_node_broadcast(net, buf); | 628 | tipc_node_broadcast(net, skb); |
727 | return publ; | 629 | return p; |
728 | } | 630 | } |
729 | 631 | ||
730 | /** | 632 | /** |
731 | * tipc_nametbl_withdraw - withdraw name publication from network name tables | 633 | * tipc_nametbl_withdraw - withdraw a service binding |
732 | */ | 634 | */ |
733 | int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 port, | 635 | int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, |
734 | u32 key) | 636 | u32 upper, u32 key) |
735 | { | 637 | { |
736 | struct publication *publ; | 638 | struct name_table *nt = tipc_name_table(net); |
639 | struct tipc_net *tn = tipc_net(net); | ||
640 | u32 self = tipc_own_addr(net); | ||
737 | struct sk_buff *skb = NULL; | 641 | struct sk_buff *skb = NULL; |
738 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 642 | struct publication *p; |
739 | 643 | ||
740 | spin_lock_bh(&tn->nametbl_lock); | 644 | spin_lock_bh(&tn->nametbl_lock); |
741 | publ = tipc_nametbl_remove_publ(net, type, lower, tipc_own_addr(net), | 645 | |
742 | port, key); | 646 | p = tipc_nametbl_remove_publ(net, type, lower, upper, self, key); |
743 | if (likely(publ)) { | 647 | if (p) { |
744 | tn->nametbl->local_publ_count--; | 648 | nt->local_publ_count--; |
745 | skb = tipc_named_withdraw(net, publ); | 649 | skb = tipc_named_withdraw(net, p); |
746 | /* Any pending external events? */ | 650 | list_del_init(&p->binding_sock); |
747 | tipc_named_process_backlog(net); | 651 | kfree_rcu(p, rcu); |
748 | list_del_init(&publ->binding_sock); | ||
749 | kfree_rcu(publ, rcu); | ||
750 | } else { | 652 | } else { |
751 | pr_err("Unable to remove local publication\n" | 653 | pr_err("Failed to remove local publication {%u,%u,%u}/%u\n", |
752 | "(type=%u, lower=%u, port=%u, key=%u)\n", | 654 | type, lower, upper, key); |
753 | type, lower, port, key); | ||
754 | } | 655 | } |
755 | spin_unlock_bh(&tn->nametbl_lock); | 656 | spin_unlock_bh(&tn->nametbl_lock); |
756 | 657 | ||
@@ -766,27 +667,24 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 port, | |||
766 | */ | 667 | */ |
767 | void tipc_nametbl_subscribe(struct tipc_subscription *sub) | 668 | void tipc_nametbl_subscribe(struct tipc_subscription *sub) |
768 | { | 669 | { |
670 | struct name_table *nt = tipc_name_table(sub->net); | ||
769 | struct tipc_net *tn = tipc_net(sub->net); | 671 | struct tipc_net *tn = tipc_net(sub->net); |
770 | struct tipc_subscr *s = &sub->evt.s; | 672 | struct tipc_subscr *s = &sub->evt.s; |
771 | u32 type = tipc_sub_read(s, seq.type); | 673 | u32 type = tipc_sub_read(s, seq.type); |
772 | int index = hash(type); | 674 | struct tipc_service *sc; |
773 | struct name_seq *seq; | ||
774 | struct tipc_name_seq ns; | ||
775 | 675 | ||
776 | spin_lock_bh(&tn->nametbl_lock); | 676 | spin_lock_bh(&tn->nametbl_lock); |
777 | seq = nametbl_find_seq(sub->net, type); | 677 | sc = tipc_service_find(sub->net, type); |
778 | if (!seq) | 678 | if (!sc) |
779 | seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]); | 679 | sc = tipc_service_create(type, &nt->services[hash(type)]); |
780 | if (seq) { | 680 | if (sc) { |
781 | spin_lock_bh(&seq->lock); | 681 | spin_lock_bh(&sc->lock); |
782 | tipc_nameseq_subscribe(seq, sub); | 682 | tipc_service_subscribe(sc, sub); |
783 | spin_unlock_bh(&seq->lock); | 683 | spin_unlock_bh(&sc->lock); |
784 | } else { | 684 | } else { |
785 | ns.type = tipc_sub_read(s, seq.type); | 685 | pr_warn("Failed to subscribe for {%u,%u,%u}\n", type, |
786 | ns.lower = tipc_sub_read(s, seq.lower); | 686 | tipc_sub_read(s, seq.lower), |
787 | ns.upper = tipc_sub_read(s, seq.upper); | 687 | tipc_sub_read(s, seq.upper)); |
788 | pr_warn("Failed to create subscription for {%u,%u,%u}\n", | ||
789 | ns.type, ns.lower, ns.upper); | ||
790 | } | 688 | } |
791 | spin_unlock_bh(&tn->nametbl_lock); | 689 | spin_unlock_bh(&tn->nametbl_lock); |
792 | } | 690 | } |
@@ -796,124 +694,122 @@ void tipc_nametbl_subscribe(struct tipc_subscription *sub) | |||
796 | */ | 694 | */ |
797 | void tipc_nametbl_unsubscribe(struct tipc_subscription *sub) | 695 | void tipc_nametbl_unsubscribe(struct tipc_subscription *sub) |
798 | { | 696 | { |
799 | struct tipc_subscr *s = &sub->evt.s; | ||
800 | struct tipc_net *tn = tipc_net(sub->net); | 697 | struct tipc_net *tn = tipc_net(sub->net); |
801 | struct name_seq *seq; | 698 | struct tipc_subscr *s = &sub->evt.s; |
802 | u32 type = tipc_sub_read(s, seq.type); | 699 | u32 type = tipc_sub_read(s, seq.type); |
700 | struct tipc_service *sc; | ||
803 | 701 | ||
804 | spin_lock_bh(&tn->nametbl_lock); | 702 | spin_lock_bh(&tn->nametbl_lock); |
805 | seq = nametbl_find_seq(sub->net, type); | 703 | sc = tipc_service_find(sub->net, type); |
806 | if (seq != NULL) { | 704 | if (!sc) |
807 | spin_lock_bh(&seq->lock); | 705 | goto exit; |
808 | list_del_init(&sub->nameseq_list); | 706 | |
809 | tipc_sub_put(sub); | 707 | spin_lock_bh(&sc->lock); |
810 | if (!seq->first_free && list_empty(&seq->subscriptions)) { | 708 | list_del_init(&sub->service_list); |
811 | hlist_del_init_rcu(&seq->ns_list); | 709 | tipc_sub_put(sub); |
812 | kfree(seq->sseqs); | 710 | |
813 | spin_unlock_bh(&seq->lock); | 711 | /* Delete service item if no more publications and subscriptions */ |
814 | kfree_rcu(seq, rcu); | 712 | if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { |
815 | } else { | 713 | hlist_del_init_rcu(&sc->service_list); |
816 | spin_unlock_bh(&seq->lock); | 714 | kfree_rcu(sc, rcu); |
817 | } | ||
818 | } | 715 | } |
716 | spin_unlock_bh(&sc->lock); | ||
717 | exit: | ||
819 | spin_unlock_bh(&tn->nametbl_lock); | 718 | spin_unlock_bh(&tn->nametbl_lock); |
820 | } | 719 | } |
821 | 720 | ||
822 | int tipc_nametbl_init(struct net *net) | 721 | int tipc_nametbl_init(struct net *net) |
823 | { | 722 | { |
824 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 723 | struct tipc_net *tn = tipc_net(net); |
825 | struct name_table *tipc_nametbl; | 724 | struct name_table *nt; |
826 | int i; | 725 | int i; |
827 | 726 | ||
828 | tipc_nametbl = kzalloc(sizeof(*tipc_nametbl), GFP_ATOMIC); | 727 | nt = kzalloc(sizeof(*nt), GFP_ATOMIC); |
829 | if (!tipc_nametbl) | 728 | if (!nt) |
830 | return -ENOMEM; | 729 | return -ENOMEM; |
831 | 730 | ||
832 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) | 731 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) |
833 | INIT_HLIST_HEAD(&tipc_nametbl->seq_hlist[i]); | 732 | INIT_HLIST_HEAD(&nt->services[i]); |
834 | 733 | ||
835 | INIT_LIST_HEAD(&tipc_nametbl->node_scope); | 734 | INIT_LIST_HEAD(&nt->node_scope); |
836 | INIT_LIST_HEAD(&tipc_nametbl->cluster_scope); | 735 | INIT_LIST_HEAD(&nt->cluster_scope); |
837 | tn->nametbl = tipc_nametbl; | 736 | tn->nametbl = nt; |
838 | spin_lock_init(&tn->nametbl_lock); | 737 | spin_lock_init(&tn->nametbl_lock); |
839 | return 0; | 738 | return 0; |
840 | } | 739 | } |
841 | 740 | ||
842 | /** | 741 | /** |
843 | * tipc_purge_publications - remove all publications for a given type | 742 | * tipc_service_delete - purge all publications for a service and delete it |
844 | * | ||
845 | * tipc_nametbl_lock must be held when calling this function | ||
846 | */ | 743 | */ |
847 | static void tipc_purge_publications(struct net *net, struct name_seq *seq) | 744 | static void tipc_service_delete(struct net *net, struct tipc_service *sc) |
848 | { | 745 | { |
849 | struct publication *publ, *safe; | 746 | struct service_range *sr, *tmpr; |
850 | struct sub_seq *sseq; | 747 | struct publication *p, *tmpb; |
851 | struct name_info *info; | 748 | |
852 | 749 | spin_lock_bh(&sc->lock); | |
853 | spin_lock_bh(&seq->lock); | 750 | rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) { |
854 | sseq = seq->sseqs; | 751 | list_for_each_entry_safe(p, tmpb, |
855 | info = sseq->info; | 752 | &sr->all_publ, all_publ) { |
856 | list_for_each_entry_safe(publ, safe, &info->all_publ, all_publ) { | 753 | tipc_service_remove_publ(net, sc, p->lower, p->upper, |
857 | tipc_nameseq_remove_publ(net, seq, publ->lower, publ->node, | 754 | p->node, p->key); |
858 | publ->port, publ->key); | 755 | kfree_rcu(p, rcu); |
859 | kfree_rcu(publ, rcu); | 756 | } |
860 | } | 757 | } |
861 | hlist_del_init_rcu(&seq->ns_list); | 758 | hlist_del_init_rcu(&sc->service_list); |
862 | kfree(seq->sseqs); | 759 | spin_unlock_bh(&sc->lock); |
863 | spin_unlock_bh(&seq->lock); | 760 | kfree_rcu(sc, rcu); |
864 | |||
865 | kfree_rcu(seq, rcu); | ||
866 | } | 761 | } |
867 | 762 | ||
868 | void tipc_nametbl_stop(struct net *net) | 763 | void tipc_nametbl_stop(struct net *net) |
869 | { | 764 | { |
765 | struct name_table *nt = tipc_name_table(net); | ||
766 | struct tipc_net *tn = tipc_net(net); | ||
767 | struct hlist_head *service_head; | ||
768 | struct tipc_service *service; | ||
870 | u32 i; | 769 | u32 i; |
871 | struct name_seq *seq; | ||
872 | struct hlist_head *seq_head; | ||
873 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
874 | struct name_table *tipc_nametbl = tn->nametbl; | ||
875 | 770 | ||
876 | /* Verify name table is empty and purge any lingering | 771 | /* Verify name table is empty and purge any lingering |
877 | * publications, then release the name table | 772 | * publications, then release the name table |
878 | */ | 773 | */ |
879 | spin_lock_bh(&tn->nametbl_lock); | 774 | spin_lock_bh(&tn->nametbl_lock); |
880 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | 775 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
881 | if (hlist_empty(&tipc_nametbl->seq_hlist[i])) | 776 | if (hlist_empty(&nt->services[i])) |
882 | continue; | 777 | continue; |
883 | seq_head = &tipc_nametbl->seq_hlist[i]; | 778 | service_head = &nt->services[i]; |
884 | hlist_for_each_entry_rcu(seq, seq_head, ns_list) { | 779 | hlist_for_each_entry_rcu(service, service_head, service_list) { |
885 | tipc_purge_publications(net, seq); | 780 | tipc_service_delete(net, service); |
886 | } | 781 | } |
887 | } | 782 | } |
888 | spin_unlock_bh(&tn->nametbl_lock); | 783 | spin_unlock_bh(&tn->nametbl_lock); |
889 | 784 | ||
890 | synchronize_net(); | 785 | synchronize_net(); |
891 | kfree(tipc_nametbl); | 786 | kfree(nt); |
892 | |||
893 | } | 787 | } |
894 | 788 | ||
895 | static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, | 789 | static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, |
896 | struct name_seq *seq, | 790 | struct tipc_service *service, |
897 | struct sub_seq *sseq, u32 *last_publ) | 791 | struct service_range *sr, |
792 | u32 *last_key) | ||
898 | { | 793 | { |
899 | void *hdr; | ||
900 | struct nlattr *attrs; | ||
901 | struct nlattr *publ; | ||
902 | struct publication *p; | 794 | struct publication *p; |
795 | struct nlattr *attrs; | ||
796 | struct nlattr *b; | ||
797 | void *hdr; | ||
903 | 798 | ||
904 | if (*last_publ) { | 799 | if (*last_key) { |
905 | list_for_each_entry(p, &sseq->info->all_publ, all_publ) | 800 | list_for_each_entry(p, &sr->all_publ, all_publ) |
906 | if (p->key == *last_publ) | 801 | if (p->key == *last_key) |
907 | break; | 802 | break; |
908 | if (p->key != *last_publ) | 803 | if (p->key != *last_key) |
909 | return -EPIPE; | 804 | return -EPIPE; |
910 | } else { | 805 | } else { |
911 | p = list_first_entry(&sseq->info->all_publ, struct publication, | 806 | p = list_first_entry(&sr->all_publ, |
807 | struct publication, | ||
912 | all_publ); | 808 | all_publ); |
913 | } | 809 | } |
914 | 810 | ||
915 | list_for_each_entry_from(p, &sseq->info->all_publ, all_publ) { | 811 | list_for_each_entry_from(p, &sr->all_publ, all_publ) { |
916 | *last_publ = p->key; | 812 | *last_key = p->key; |
917 | 813 | ||
918 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, | 814 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, |
919 | &tipc_genl_family, NLM_F_MULTI, | 815 | &tipc_genl_family, NLM_F_MULTI, |
@@ -925,15 +821,15 @@ static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, | |||
925 | if (!attrs) | 821 | if (!attrs) |
926 | goto msg_full; | 822 | goto msg_full; |
927 | 823 | ||
928 | publ = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE_PUBL); | 824 | b = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE_PUBL); |
929 | if (!publ) | 825 | if (!b) |
930 | goto attr_msg_full; | 826 | goto attr_msg_full; |
931 | 827 | ||
932 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, seq->type)) | 828 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, service->type)) |
933 | goto publ_msg_full; | 829 | goto publ_msg_full; |
934 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sseq->lower)) | 830 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sr->lower)) |
935 | goto publ_msg_full; | 831 | goto publ_msg_full; |
936 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sseq->upper)) | 832 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sr->upper)) |
937 | goto publ_msg_full; | 833 | goto publ_msg_full; |
938 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope)) | 834 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope)) |
939 | goto publ_msg_full; | 835 | goto publ_msg_full; |
@@ -944,16 +840,16 @@ static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, | |||
944 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key)) | 840 | if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key)) |
945 | goto publ_msg_full; | 841 | goto publ_msg_full; |
946 | 842 | ||
947 | nla_nest_end(msg->skb, publ); | 843 | nla_nest_end(msg->skb, b); |
948 | nla_nest_end(msg->skb, attrs); | 844 | nla_nest_end(msg->skb, attrs); |
949 | genlmsg_end(msg->skb, hdr); | 845 | genlmsg_end(msg->skb, hdr); |
950 | } | 846 | } |
951 | *last_publ = 0; | 847 | *last_key = 0; |
952 | 848 | ||
953 | return 0; | 849 | return 0; |
954 | 850 | ||
955 | publ_msg_full: | 851 | publ_msg_full: |
956 | nla_nest_cancel(msg->skb, publ); | 852 | nla_nest_cancel(msg->skb, b); |
957 | attr_msg_full: | 853 | attr_msg_full: |
958 | nla_nest_cancel(msg->skb, attrs); | 854 | nla_nest_cancel(msg->skb, attrs); |
959 | msg_full: | 855 | msg_full: |
@@ -962,39 +858,34 @@ msg_full: | |||
962 | return -EMSGSIZE; | 858 | return -EMSGSIZE; |
963 | } | 859 | } |
964 | 860 | ||
965 | static int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq, | 861 | static int __tipc_nl_service_range_list(struct tipc_nl_msg *msg, |
966 | u32 *last_lower, u32 *last_publ) | 862 | struct tipc_service *sc, |
863 | u32 *last_lower, u32 *last_key) | ||
967 | { | 864 | { |
968 | struct sub_seq *sseq; | 865 | struct service_range *sr; |
969 | struct sub_seq *sseq_start; | 866 | struct rb_node *n; |
970 | int err; | 867 | int err; |
971 | 868 | ||
972 | if (*last_lower) { | 869 | for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { |
973 | sseq_start = nameseq_find_subseq(seq, *last_lower); | 870 | sr = container_of(n, struct service_range, tree_node); |
974 | if (!sseq_start) | 871 | if (sr->lower < *last_lower) |
975 | return -EPIPE; | 872 | continue; |
976 | } else { | 873 | err = __tipc_nl_add_nametable_publ(msg, sc, sr, last_key); |
977 | sseq_start = seq->sseqs; | ||
978 | } | ||
979 | |||
980 | for (sseq = sseq_start; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
981 | err = __tipc_nl_add_nametable_publ(msg, seq, sseq, last_publ); | ||
982 | if (err) { | 874 | if (err) { |
983 | *last_lower = sseq->lower; | 875 | *last_lower = sr->lower; |
984 | return err; | 876 | return err; |
985 | } | 877 | } |
986 | } | 878 | } |
987 | *last_lower = 0; | 879 | *last_lower = 0; |
988 | |||
989 | return 0; | 880 | return 0; |
990 | } | 881 | } |
991 | 882 | ||
992 | static int tipc_nl_seq_list(struct net *net, struct tipc_nl_msg *msg, | 883 | static int tipc_nl_service_list(struct net *net, struct tipc_nl_msg *msg, |
993 | u32 *last_type, u32 *last_lower, u32 *last_publ) | 884 | u32 *last_type, u32 *last_lower, u32 *last_key) |
994 | { | 885 | { |
995 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 886 | struct tipc_net *tn = tipc_net(net); |
996 | struct hlist_head *seq_head; | 887 | struct tipc_service *service = NULL; |
997 | struct name_seq *seq = NULL; | 888 | struct hlist_head *head; |
998 | int err; | 889 | int err; |
999 | int i; | 890 | int i; |
1000 | 891 | ||
@@ -1004,30 +895,31 @@ static int tipc_nl_seq_list(struct net *net, struct tipc_nl_msg *msg, | |||
1004 | i = 0; | 895 | i = 0; |
1005 | 896 | ||
1006 | for (; i < TIPC_NAMETBL_SIZE; i++) { | 897 | for (; i < TIPC_NAMETBL_SIZE; i++) { |
1007 | seq_head = &tn->nametbl->seq_hlist[i]; | 898 | head = &tn->nametbl->services[i]; |
1008 | 899 | ||
1009 | if (*last_type) { | 900 | if (*last_type) { |
1010 | seq = nametbl_find_seq(net, *last_type); | 901 | service = tipc_service_find(net, *last_type); |
1011 | if (!seq) | 902 | if (!service) |
1012 | return -EPIPE; | 903 | return -EPIPE; |
1013 | } else { | 904 | } else { |
1014 | hlist_for_each_entry_rcu(seq, seq_head, ns_list) | 905 | hlist_for_each_entry_rcu(service, head, service_list) |
1015 | break; | 906 | break; |
1016 | if (!seq) | 907 | if (!service) |
1017 | continue; | 908 | continue; |
1018 | } | 909 | } |
1019 | 910 | ||
1020 | hlist_for_each_entry_from_rcu(seq, ns_list) { | 911 | hlist_for_each_entry_from_rcu(service, service_list) { |
1021 | spin_lock_bh(&seq->lock); | 912 | spin_lock_bh(&service->lock); |
1022 | err = __tipc_nl_subseq_list(msg, seq, last_lower, | 913 | err = __tipc_nl_service_range_list(msg, service, |
1023 | last_publ); | 914 | last_lower, |
915 | last_key); | ||
1024 | 916 | ||
1025 | if (err) { | 917 | if (err) { |
1026 | *last_type = seq->type; | 918 | *last_type = service->type; |
1027 | spin_unlock_bh(&seq->lock); | 919 | spin_unlock_bh(&service->lock); |
1028 | return err; | 920 | return err; |
1029 | } | 921 | } |
1030 | spin_unlock_bh(&seq->lock); | 922 | spin_unlock_bh(&service->lock); |
1031 | } | 923 | } |
1032 | *last_type = 0; | 924 | *last_type = 0; |
1033 | } | 925 | } |
@@ -1036,13 +928,13 @@ static int tipc_nl_seq_list(struct net *net, struct tipc_nl_msg *msg, | |||
1036 | 928 | ||
1037 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) | 929 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) |
1038 | { | 930 | { |
1039 | int err; | 931 | struct net *net = sock_net(skb->sk); |
1040 | int done = cb->args[3]; | ||
1041 | u32 last_type = cb->args[0]; | 932 | u32 last_type = cb->args[0]; |
1042 | u32 last_lower = cb->args[1]; | 933 | u32 last_lower = cb->args[1]; |
1043 | u32 last_publ = cb->args[2]; | 934 | u32 last_key = cb->args[2]; |
1044 | struct net *net = sock_net(skb->sk); | 935 | int done = cb->args[3]; |
1045 | struct tipc_nl_msg msg; | 936 | struct tipc_nl_msg msg; |
937 | int err; | ||
1046 | 938 | ||
1047 | if (done) | 939 | if (done) |
1048 | return 0; | 940 | return 0; |
@@ -1052,7 +944,8 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1052 | msg.seq = cb->nlh->nlmsg_seq; | 944 | msg.seq = cb->nlh->nlmsg_seq; |
1053 | 945 | ||
1054 | rcu_read_lock(); | 946 | rcu_read_lock(); |
1055 | err = tipc_nl_seq_list(net, &msg, &last_type, &last_lower, &last_publ); | 947 | err = tipc_nl_service_list(net, &msg, &last_type, |
948 | &last_lower, &last_key); | ||
1056 | if (!err) { | 949 | if (!err) { |
1057 | done = 1; | 950 | done = 1; |
1058 | } else if (err != -EMSGSIZE) { | 951 | } else if (err != -EMSGSIZE) { |
@@ -1068,7 +961,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1068 | 961 | ||
1069 | cb->args[0] = last_type; | 962 | cb->args[0] = last_type; |
1070 | cb->args[1] = last_lower; | 963 | cb->args[1] = last_lower; |
1071 | cb->args[2] = last_publ; | 964 | cb->args[2] = last_key; |
1072 | cb->args[3] = done; | 965 | cb->args[3] = done; |
1073 | 966 | ||
1074 | return skb->len; | 967 | return skb->len; |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 34a4ccb907aa..4b14fc28d9e2 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -97,7 +97,7 @@ struct publication { | |||
97 | * @local_publ_count: number of publications issued by this node | 97 | * @local_publ_count: number of publications issued by this node |
98 | */ | 98 | */ |
99 | struct name_table { | 99 | struct name_table { |
100 | struct hlist_head seq_hlist[TIPC_NAMETBL_SIZE]; | 100 | struct hlist_head services[TIPC_NAMETBL_SIZE]; |
101 | struct list_head node_scope; | 101 | struct list_head node_scope; |
102 | struct list_head cluster_scope; | 102 | struct list_head cluster_scope; |
103 | u32 local_publ_count; | 103 | u32 local_publ_count; |
@@ -116,16 +116,16 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, | |||
116 | struct list_head *dsts, int *dstcnt, u32 exclude, | 116 | struct list_head *dsts, int *dstcnt, u32 exclude, |
117 | bool all); | 117 | bool all); |
118 | struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, | 118 | struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, |
119 | u32 upper, u32 scope, u32 port_ref, | 119 | u32 upper, u32 scope, u32 port, |
120 | u32 key); | 120 | u32 key); |
121 | int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, | 121 | int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 upper, |
122 | u32 key); | 122 | u32 key); |
123 | struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, | 123 | struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, |
124 | u32 lower, u32 upper, u32 scope, | 124 | u32 lower, u32 upper, u32 scope, |
125 | u32 node, u32 ref, u32 key); | 125 | u32 node, u32 ref, u32 key); |
126 | struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, | 126 | struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, |
127 | u32 lower, u32 node, u32 ref, | 127 | u32 lower, u32 upper, |
128 | u32 key); | 128 | u32 node, u32 key); |
129 | void tipc_nametbl_subscribe(struct tipc_subscription *s); | 129 | void tipc_nametbl_subscribe(struct tipc_subscription *s); |
130 | void tipc_nametbl_unsubscribe(struct tipc_subscription *s); | 130 | void tipc_nametbl_unsubscribe(struct tipc_subscription *s); |
131 | int tipc_nametbl_init(struct net *net); | 131 | int tipc_nametbl_init(struct net *net); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 29538dc00857..856f9e97ea29 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -136,7 +136,7 @@ void tipc_net_stop(struct net *net) | |||
136 | if (!self) | 136 | if (!self) |
137 | return; | 137 | return; |
138 | 138 | ||
139 | tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, 0, self); | 139 | tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, self, self); |
140 | rtnl_lock(); | 140 | rtnl_lock(); |
141 | tipc_bearer_stop(net); | 141 | tipc_bearer_stop(net); |
142 | tipc_node_stop(net); | 142 | tipc_node_stop(net); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 4fb4327311bb..c77dd2f3c589 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -324,12 +324,12 @@ static void tipc_node_write_unlock(struct tipc_node *n) | |||
324 | if (flags & TIPC_NOTIFY_LINK_UP) { | 324 | if (flags & TIPC_NOTIFY_LINK_UP) { |
325 | tipc_mon_peer_up(net, addr, bearer_id); | 325 | tipc_mon_peer_up(net, addr, bearer_id); |
326 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | 326 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, |
327 | TIPC_NODE_SCOPE, link_id, addr); | 327 | TIPC_NODE_SCOPE, link_id, link_id); |
328 | } | 328 | } |
329 | if (flags & TIPC_NOTIFY_LINK_DOWN) { | 329 | if (flags & TIPC_NOTIFY_LINK_DOWN) { |
330 | tipc_mon_peer_down(net, addr, bearer_id); | 330 | tipc_mon_peer_down(net, addr, bearer_id); |
331 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | 331 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, |
332 | link_id, addr); | 332 | addr, link_id); |
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 275b666f6231..3e5eba30865e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -2634,12 +2634,12 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, | |||
2634 | if (publ->upper != seq->upper) | 2634 | if (publ->upper != seq->upper) |
2635 | break; | 2635 | break; |
2636 | tipc_nametbl_withdraw(net, publ->type, publ->lower, | 2636 | tipc_nametbl_withdraw(net, publ->type, publ->lower, |
2637 | publ->port, publ->key); | 2637 | publ->upper, publ->key); |
2638 | rc = 0; | 2638 | rc = 0; |
2639 | break; | 2639 | break; |
2640 | } | 2640 | } |
2641 | tipc_nametbl_withdraw(net, publ->type, publ->lower, | 2641 | tipc_nametbl_withdraw(net, publ->type, publ->lower, |
2642 | publ->port, publ->key); | 2642 | publ->upper, publ->key); |
2643 | rc = 0; | 2643 | rc = 0; |
2644 | } | 2644 | } |
2645 | if (list_empty(&tsk->publications)) | 2645 | if (list_empty(&tsk->publications)) |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 8b2d22b18f22..d793b4343885 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -40,7 +40,7 @@ | |||
40 | #include "topsrv.h" | 40 | #include "topsrv.h" |
41 | 41 | ||
42 | #define TIPC_MAX_SUBSCR 65535 | 42 | #define TIPC_MAX_SUBSCR 65535 |
43 | #define TIPC_MAX_PUBLICATIONS 65535 | 43 | #define TIPC_MAX_PUBL 65535 |
44 | 44 | ||
45 | struct tipc_subscription; | 45 | struct tipc_subscription; |
46 | struct tipc_conn; | 46 | struct tipc_conn; |
@@ -58,7 +58,7 @@ struct tipc_subscription { | |||
58 | struct kref kref; | 58 | struct kref kref; |
59 | struct net *net; | 59 | struct net *net; |
60 | struct timer_list timer; | 60 | struct timer_list timer; |
61 | struct list_head nameseq_list; | 61 | struct list_head service_list; |
62 | struct list_head sub_list; | 62 | struct list_head sub_list; |
63 | struct tipc_event evt; | 63 | struct tipc_event evt; |
64 | int conid; | 64 | int conid; |