Blame view
net/tipc/name_table.c
30.3 KB
b97bf3fd8 [TIPC] Initial merge |
1 2 |
/* * net/tipc/name_table.c: TIPC name table code |
c43072852 [NET] TIPC: Fix w... |
3 |
* |
e50e73e10 tipc: some name c... |
4 |
* Copyright (c) 2000-2006, 2014-2018, Ericsson AB |
993bfe5da tipc: make name t... |
5 |
* Copyright (c) 2004-2008, 2010-2014, Wind River Systems |
b97bf3fd8 [TIPC] Initial merge |
6 7 |
* All rights reserved. * |
9ea1fd3c1 [TIPC] License he... |
8 |
* Redistribution and use in source and binary forms, with or without |
b97bf3fd8 [TIPC] Initial merge |
9 10 |
* modification, are permitted provided that the following conditions are met: * |
9ea1fd3c1 [TIPC] License he... |
11 12 13 14 15 16 17 18 |
* 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. |
b97bf3fd8 [TIPC] Initial merge |
19 |
* |
9ea1fd3c1 [TIPC] License he... |
20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
* Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
b97bf3fd8 [TIPC] Initial merge |
34 35 |
* POSSIBILITY OF SUCH DAMAGE. */ |
4ac1c8d0e tipc: name tipc n... |
36 |
#include <net/sock.h> |
41b416f1f tipc: support in-... |
37 |
#include <linux/list_sort.h> |
d5162f341 tipc: fix name ta... |
38 |
#include <linux/rbtree_augmented.h> |
b97bf3fd8 [TIPC] Initial merge |
39 |
#include "core.h" |
22ae7cff5 tipc: nl compat a... |
40 |
#include "netlink.h" |
b97bf3fd8 [TIPC] Initial merge |
41 42 |
#include "name_table.h" #include "name_distr.h" |
b97bf3fd8 [TIPC] Initial merge |
43 |
#include "subscr.h" |
1da465683 tipc: make tipc b... |
44 |
#include "bcast.h" |
22ae7cff5 tipc: nl compat a... |
45 |
#include "addr.h" |
1d7e1c259 tipc: reduce code... |
46 |
#include "node.h" |
75da2163d tipc: introduce c... |
47 |
#include "group.h" |
b97bf3fd8 [TIPC] Initial merge |
48 49 |
/** |
218527fe2 tipc: replace nam... |
50 51 52 53 |
* struct service_range - container for all bindings of a service range * @lower: service range lower bound * @upper: service range upper bound * @tree_node: member of service range RB tree |
d5162f341 tipc: fix name ta... |
54 |
* @max: largest 'upper' in this node subtree |
218527fe2 tipc: replace nam... |
55 56 57 58 |
* @local_publ: list of identical publications made from this node * Used by closest_first lookup and multicast lookup algorithm * @all_publ: all publications identical to this one, whatever node and scope * Used by round-robin lookup algorithm |
b97bf3fd8 [TIPC] Initial merge |
59 |
*/ |
218527fe2 tipc: replace nam... |
60 |
struct service_range { |
b52124a50 tipc: Partition n... |
61 62 |
u32 lower; u32 upper; |
218527fe2 tipc: replace nam... |
63 |
struct rb_node tree_node; |
d5162f341 tipc: fix name ta... |
64 |
u32 max; |
218527fe2 tipc: replace nam... |
65 66 |
struct list_head local_publ; struct list_head all_publ; |
b52124a50 tipc: Partition n... |
67 68 69 |
}; /** |
218527fe2 tipc: replace nam... |
70 71 |
* struct tipc_service - container for all published instances of a service type * @type: 32 bit 'type' value for service |
41b416f1f tipc: support in-... |
72 |
* @publ_cnt: increasing counter for publications in this service |
218527fe2 tipc: replace nam... |
73 74 75 76 |
* @ranges: rb tree containing all service ranges for this service * @service_list: links to adjacent name ranges in hash chain * @subscriptions: list of subscriptions for this service type * @lock: spinlock controlling access to pertaining service ranges/publications |
97ede29e8 tipc: convert nam... |
77 |
* @rcu: RCU callback head used for deferred freeing |
b97bf3fd8 [TIPC] Initial merge |
78 |
*/ |
218527fe2 tipc: replace nam... |
79 |
struct tipc_service { |
b97bf3fd8 [TIPC] Initial merge |
80 |
u32 type; |
41b416f1f tipc: support in-... |
81 |
u32 publ_cnt; |
218527fe2 tipc: replace nam... |
82 83 |
struct rb_root ranges; struct hlist_node service_list; |
b97bf3fd8 [TIPC] Initial merge |
84 |
struct list_head subscriptions; |
218527fe2 tipc: replace nam... |
85 |
spinlock_t lock; /* Covers service range list */ |
97ede29e8 tipc: convert nam... |
86 |
struct rcu_head rcu; |
b97bf3fd8 [TIPC] Initial merge |
87 |
}; |
d5162f341 tipc: fix name ta... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
#define service_range_upper(sr) ((sr)->upper) RB_DECLARE_CALLBACKS_MAX(static, sr_callbacks, struct service_range, tree_node, u32, max, service_range_upper) #define service_range_entry(rbtree_node) \ (container_of(rbtree_node, struct service_range, tree_node)) #define service_range_overlap(sr, start, end) \ ((sr)->lower <= (end) && (sr)->upper >= (start)) /** * service_range_foreach_match - iterate over tipc service rbtree for each * range match * @sr: the service range pointer as a loop cursor * @sc: the pointer to tipc service which holds the service range rbtree * @start, end: the range (end >= start) for matching */ #define service_range_foreach_match(sr, sc, start, end) \ for (sr = service_range_match_first((sc)->ranges.rb_node, \ start, \ end); \ sr; \ sr = service_range_match_next(&(sr)->tree_node, \ start, \ end)) /** * service_range_match_first - find first service range matching a range * @n: the root node of service range rbtree for searching * @start, end: the range (end >= start) for matching * * Return: the leftmost service range node in the rbtree that overlaps the * specific range if any. Otherwise, returns NULL. */ static struct service_range *service_range_match_first(struct rb_node *n, u32 start, u32 end) { struct service_range *sr; struct rb_node *l, *r; /* Non overlaps in tree at all? */ if (!n || service_range_entry(n)->max < start) return NULL; while (n) { l = n->rb_left; if (l && service_range_entry(l)->max >= start) { /* A leftmost overlap range node must be one in the left * subtree. If not, it has lower > end, then nodes on * the right side cannot satisfy the condition either. */ n = l; continue; } /* No one in the left subtree can match, return if this node is * an overlap i.e. leftmost. */ sr = service_range_entry(n); if (service_range_overlap(sr, start, end)) return sr; /* Ok, try to lookup on the right side */ r = n->rb_right; if (sr->lower <= end && r && service_range_entry(r)->max >= start) { n = r; continue; } break; } return NULL; } /** * service_range_match_next - find next service range matching a range * @n: a node in service range rbtree from which the searching starts * @start, end: the range (end >= start) for matching * * Return: the next service range node to the given node in the rbtree that * overlaps the specific range if any. Otherwise, returns NULL. */ static struct service_range *service_range_match_next(struct rb_node *n, u32 start, u32 end) { struct service_range *sr; struct rb_node *p, *r; while (n) { r = n->rb_right; if (r && service_range_entry(r)->max >= start) /* A next overlap range node must be one in the right * subtree. If not, it has lower > end, then any next * successor (- an ancestor) of this node cannot * satisfy the condition either. */ return service_range_match_first(r, start, end); /* No one in the right subtree can match, go up to find an * ancestor of this node which is parent of a left-hand child. */ while ((p = rb_parent(n)) && n == p->rb_right) n = p; if (!p) break; /* Return if this ancestor is an overlap */ sr = service_range_entry(p); if (service_range_overlap(sr, start, end)) return sr; /* Ok, try to lookup more from this ancestor */ if (sr->lower <= end) { n = p; continue; } break; } return NULL; } |
05790c645 [TIPC]: Remove in... |
211 |
static int hash(int x) |
b97bf3fd8 [TIPC] Initial merge |
212 |
{ |
f046e7d9b tipc: convert tip... |
213 |
return x & (TIPC_NAMETBL_SIZE - 1); |
b97bf3fd8 [TIPC] Initial merge |
214 215 216 |
} /** |
218527fe2 tipc: replace nam... |
217 |
* tipc_publ_create - create a publication structure |
b97bf3fd8 [TIPC] Initial merge |
218 |
*/ |
218527fe2 tipc: replace nam... |
219 220 221 |
static struct publication *tipc_publ_create(u32 type, u32 lower, u32 upper, u32 scope, u32 node, u32 port, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
222 |
{ |
0da974f4f [NET]: Conversion... |
223 |
struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC); |
218527fe2 tipc: replace nam... |
224 225 |
if (!publ) |
1fc54d8f4 [TIPC]: Fix simpl... |
226 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
227 |
|
b97bf3fd8 [TIPC] Initial merge |
228 229 230 231 232 |
publ->type = type; publ->lower = lower; publ->upper = upper; publ->scope = scope; publ->node = node; |
e50e73e10 tipc: some name c... |
233 |
publ->port = port; |
b97bf3fd8 [TIPC] Initial merge |
234 |
publ->key = key; |
e50e73e10 tipc: some name c... |
235 |
INIT_LIST_HEAD(&publ->binding_sock); |
218527fe2 tipc: replace nam... |
236 237 238 |
INIT_LIST_HEAD(&publ->binding_node); INIT_LIST_HEAD(&publ->local_publ); INIT_LIST_HEAD(&publ->all_publ); |
41b416f1f tipc: support in-... |
239 |
INIT_LIST_HEAD(&publ->list); |
b97bf3fd8 [TIPC] Initial merge |
240 241 242 243 |
return publ; } /** |
218527fe2 tipc: replace nam... |
244 |
* tipc_service_create - create a service structure for the specified 'type' |
c43072852 [NET] TIPC: Fix w... |
245 |
* |
218527fe2 tipc: replace nam... |
246 |
* Allocates a single range structure and sets it to all 0's. |
b97bf3fd8 [TIPC] Initial merge |
247 |
*/ |
218527fe2 tipc: replace nam... |
248 |
static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd) |
b97bf3fd8 [TIPC] Initial merge |
249 |
{ |
218527fe2 tipc: replace nam... |
250 |
struct tipc_service *service = kzalloc(sizeof(*service), GFP_ATOMIC); |
b97bf3fd8 [TIPC] Initial merge |
251 |
|
218527fe2 tipc: replace nam... |
252 253 254 |
if (!service) { pr_warn("Service creation failed, no memory "); |
1fc54d8f4 [TIPC]: Fix simpl... |
255 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
256 |
} |
218527fe2 tipc: replace nam... |
257 258 259 260 261 262 263 |
spin_lock_init(&service->lock); service->type = type; service->ranges = RB_ROOT; INIT_HLIST_NODE(&service->service_list); INIT_LIST_HEAD(&service->subscriptions); hlist_add_head_rcu(&service->service_list, hd); return service; |
b97bf3fd8 [TIPC] Initial merge |
264 |
} |
5f30721c5 tipc: clean up re... |
265 266 267 268 269 |
/* tipc_service_find_range - find service range matching publication parameters */ static struct service_range *tipc_service_find_range(struct tipc_service *sc, u32 lower, u32 upper) { |
5f30721c5 tipc: clean up re... |
270 |
struct service_range *sr; |
d5162f341 tipc: fix name ta... |
271 272 273 274 |
service_range_foreach_match(sr, sc, lower, upper) { /* Look for exact match */ if (sr->lower == lower && sr->upper == upper) return sr; |
5f30721c5 tipc: clean up re... |
275 |
} |
5f30721c5 tipc: clean up re... |
276 |
|
d5162f341 tipc: fix name ta... |
277 |
return NULL; |
5f30721c5 tipc: clean up re... |
278 |
} |
218527fe2 tipc: replace nam... |
279 280 |
static struct service_range *tipc_service_create_range(struct tipc_service *sc, u32 lower, u32 upper) |
b97bf3fd8 [TIPC] Initial merge |
281 |
{ |
218527fe2 tipc: replace nam... |
282 |
struct rb_node **n, *parent = NULL; |
d5162f341 tipc: fix name ta... |
283 |
struct service_range *sr; |
218527fe2 tipc: replace nam... |
284 285 286 |
n = &sc->ranges.rb_node; while (*n) { |
218527fe2 tipc: replace nam... |
287 |
parent = *n; |
d5162f341 tipc: fix name ta... |
288 289 290 291 292 293 294 |
sr = service_range_entry(parent); if (lower == sr->lower && upper == sr->upper) return sr; if (sr->max < upper) sr->max = upper; if (lower <= sr->lower) n = &parent->rb_left; |
b97bf3fd8 [TIPC] Initial merge |
295 |
else |
d5162f341 tipc: fix name ta... |
296 |
n = &parent->rb_right; |
b97bf3fd8 [TIPC] Initial merge |
297 |
} |
218527fe2 tipc: replace nam... |
298 299 300 301 302 |
sr = kzalloc(sizeof(*sr), GFP_ATOMIC); if (!sr) return NULL; sr->lower = lower; sr->upper = upper; |
d5162f341 tipc: fix name ta... |
303 |
sr->max = upper; |
218527fe2 tipc: replace nam... |
304 305 306 |
INIT_LIST_HEAD(&sr->local_publ); INIT_LIST_HEAD(&sr->all_publ); rb_link_node(&sr->tree_node, parent, n); |
d5162f341 tipc: fix name ta... |
307 |
rb_insert_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks); |
218527fe2 tipc: replace nam... |
308 |
return sr; |
b97bf3fd8 [TIPC] Initial merge |
309 |
} |
218527fe2 tipc: replace nam... |
310 311 |
static struct publication *tipc_service_insert_publ(struct net *net, struct tipc_service *sc, |
347475395 tipc: make tipc n... |
312 313 |
u32 type, u32 lower, u32 upper, u32 scope, |
218527fe2 tipc: replace nam... |
314 315 |
u32 node, u32 port, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
316 |
{ |
218527fe2 tipc: replace nam... |
317 318 319 320 |
struct tipc_subscription *sub, *tmp; struct service_range *sr; struct publication *p; bool first = false; |
b52124a50 tipc: Partition n... |
321 |
|
37922ea4a tipc: permit over... |
322 323 324 |
sr = tipc_service_create_range(sc, lower, upper); if (!sr) goto err; |
b97bf3fd8 [TIPC] Initial merge |
325 |
|
37922ea4a tipc: permit over... |
326 |
first = list_empty(&sr->all_publ); |
b97bf3fd8 [TIPC] Initial merge |
327 |
|
218527fe2 tipc: replace nam... |
328 329 330 331 332 |
/* Return if the publication already exists */ list_for_each_entry(p, &sr->all_publ, all_publ) { if (p->key == key && (!p->node || p->node == node)) return NULL; } |
b97bf3fd8 [TIPC] Initial merge |
333 |
|
218527fe2 tipc: replace nam... |
334 335 336 337 |
/* Create and insert publication */ p = tipc_publ_create(type, lower, upper, scope, node, port, key); if (!p) goto err; |
41b416f1f tipc: support in-... |
338 339 |
/* Suppose there shouldn't be a huge gap btw publs i.e. >INT_MAX */ p->id = sc->publ_cnt++; |
ba765ec63 tipc: remove zone... |
340 |
if (in_own_node(net, node)) |
218527fe2 tipc: replace nam... |
341 342 |
list_add(&p->local_publ, &sr->local_publ); list_add(&p->all_publ, &sr->all_publ); |
b97bf3fd8 [TIPC] Initial merge |
343 |
|
617d3c7a5 tipc: compress ou... |
344 |
/* Any subscriptions waiting for notification? */ |
218527fe2 tipc: replace nam... |
345 346 347 |
list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_PUBLISHED, p->port, p->node, p->scope, first); |
b97bf3fd8 [TIPC] Initial merge |
348 |
} |
218527fe2 tipc: replace nam... |
349 350 351 352 353 |
return p; err: pr_warn("Failed to bind to %u,%u,%u, no memory ", type, lower, upper); return NULL; |
b97bf3fd8 [TIPC] Initial merge |
354 355 356 |
} /** |
218527fe2 tipc: replace nam... |
357 |
* tipc_service_remove_publ - remove a publication from a service |
b97bf3fd8 [TIPC] Initial merge |
358 |
*/ |
5f30721c5 tipc: clean up re... |
359 360 |
static struct publication *tipc_service_remove_publ(struct service_range *sr, u32 node, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
361 |
{ |
218527fe2 tipc: replace nam... |
362 |
struct publication *p; |
b52124a50 tipc: Partition n... |
363 |
|
218527fe2 tipc: replace nam... |
364 365 366 |
list_for_each_entry(p, &sr->all_publ, all_publ) { if (p->key != key || (node && node != p->node)) continue; |
5f30721c5 tipc: clean up re... |
367 368 369 |
list_del(&p->all_publ); list_del(&p->local_publ); return p; |
f6f0a4d2d tipc: Convert nam... |
370 |
} |
5f30721c5 tipc: clean up re... |
371 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
372 373 374 |
} /** |
41b416f1f tipc: support in-... |
375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
* Code reused: time_after32() for the same purpose */ #define publication_after(pa, pb) time_after32((pa)->id, (pb)->id) static int tipc_publ_sort(void *priv, struct list_head *a, struct list_head *b) { struct publication *pa, *pb; pa = container_of(a, struct publication, list); pb = container_of(b, struct publication, list); return publication_after(pa, pb); } /** |
218527fe2 tipc: replace nam... |
389 390 391 |
* tipc_service_subscribe - attach a subscription, and optionally * issue the prescribed number of events if there is any service * range overlapping with the requested range |
b97bf3fd8 [TIPC] Initial merge |
392 |
*/ |
218527fe2 tipc: replace nam... |
393 |
static void tipc_service_subscribe(struct tipc_service *service, |
8985ecc7c tipc: simplify en... |
394 |
struct tipc_subscription *sub) |
b97bf3fd8 [TIPC] Initial merge |
395 |
{ |
218527fe2 tipc: replace nam... |
396 |
struct tipc_subscr *sb = &sub->evt.s; |
41b416f1f tipc: support in-... |
397 398 |
struct publication *p, *first, *tmp; struct list_head publ_list; |
218527fe2 tipc: replace nam... |
399 |
struct service_range *sr; |
a4273c73e tipc: remove stru... |
400 |
struct tipc_name_seq ns; |
41b416f1f tipc: support in-... |
401 |
u32 filter; |
a4273c73e tipc: remove stru... |
402 |
|
218527fe2 tipc: replace nam... |
403 404 405 |
ns.type = tipc_sub_read(sb, seq.type); ns.lower = tipc_sub_read(sb, seq.lower); ns.upper = tipc_sub_read(sb, seq.upper); |
41b416f1f tipc: support in-... |
406 |
filter = tipc_sub_read(sb, filter); |
b97bf3fd8 [TIPC] Initial merge |
407 |
|
da0a75e86 tipc: some prefix... |
408 |
tipc_sub_get(sub); |
218527fe2 tipc: replace nam... |
409 |
list_add(&sub->service_list, &service->subscriptions); |
b97bf3fd8 [TIPC] Initial merge |
410 |
|
41b416f1f tipc: support in-... |
411 |
if (filter & TIPC_SUB_NO_STATUS) |
b97bf3fd8 [TIPC] Initial merge |
412 |
return; |
41b416f1f tipc: support in-... |
413 |
INIT_LIST_HEAD(&publ_list); |
d5162f341 tipc: fix name ta... |
414 |
service_range_foreach_match(sr, service, ns.lower, ns.upper) { |
41b416f1f tipc: support in-... |
415 |
first = NULL; |
218527fe2 tipc: replace nam... |
416 |
list_for_each_entry(p, &sr->all_publ, all_publ) { |
41b416f1f tipc: support in-... |
417 418 419 420 421 |
if (filter & TIPC_SUB_PORTS) list_add_tail(&p->list, &publ_list); else if (!first || publication_after(first, p)) /* Pick this range's *first* publication */ first = p; |
b97bf3fd8 [TIPC] Initial merge |
422 |
} |
41b416f1f tipc: support in-... |
423 424 425 426 427 428 429 430 431 432 433 |
if (first) list_add_tail(&first->list, &publ_list); } /* Sort the publications before reporting */ list_sort(NULL, &publ_list, tipc_publ_sort); list_for_each_entry_safe(p, tmp, &publ_list, list) { tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_PUBLISHED, p->port, p->node, p->scope, true); list_del_init(&p->list); |
b97bf3fd8 [TIPC] Initial merge |
434 435 |
} } |
218527fe2 tipc: replace nam... |
436 |
static struct tipc_service *tipc_service_find(struct net *net, u32 type) |
b97bf3fd8 [TIPC] Initial merge |
437 |
{ |
218527fe2 tipc: replace nam... |
438 439 440 |
struct name_table *nt = tipc_name_table(net); struct hlist_head *service_head; struct tipc_service *service; |
b97bf3fd8 [TIPC] Initial merge |
441 |
|
218527fe2 tipc: replace nam... |
442 443 444 445 446 |
service_head = &nt->services[hash(type)]; hlist_for_each_entry_rcu(service, service_head, service_list) { if (service->type == type) return service; } |
1fc54d8f4 [TIPC]: Fix simpl... |
447 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
448 |
}; |
4ac1c8d0e tipc: name tipc n... |
449 |
struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, |
218527fe2 tipc: replace nam... |
450 451 452 |
u32 lower, u32 upper, u32 scope, u32 node, u32 port, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
453 |
{ |
218527fe2 tipc: replace nam... |
454 455 456 |
struct name_table *nt = tipc_name_table(net); struct tipc_service *sc; struct publication *p; |
b97bf3fd8 [TIPC] Initial merge |
457 |
|
928df1880 tipc: obsolete TI... |
458 |
if (scope > TIPC_NODE_SCOPE || lower > upper) { |
218527fe2 tipc: replace nam... |
459 460 |
pr_debug("Failed to bind illegal {%u,%u,%u} with scope %u ", |
2cf8aa19f tipc: use standar... |
461 |
type, lower, upper, scope); |
1fc54d8f4 [TIPC]: Fix simpl... |
462 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
463 |
} |
218527fe2 tipc: replace nam... |
464 465 466 467 |
sc = tipc_service_find(net, type); if (!sc) sc = tipc_service_create(type, &nt->services[hash(type)]); if (!sc) |
1fc54d8f4 [TIPC]: Fix simpl... |
468 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
469 |
|
218527fe2 tipc: replace nam... |
470 471 472 473 474 |
spin_lock_bh(&sc->lock); p = tipc_service_insert_publ(net, sc, type, lower, upper, scope, node, port, key); spin_unlock_bh(&sc->lock); return p; |
b97bf3fd8 [TIPC] Initial merge |
475 |
} |
4ac1c8d0e tipc: name tipc n... |
476 |
struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, |
37922ea4a tipc: permit over... |
477 478 |
u32 lower, u32 upper, u32 node, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
479 |
{ |
218527fe2 tipc: replace nam... |
480 |
struct tipc_service *sc = tipc_service_find(net, type); |
5f30721c5 tipc: clean up re... |
481 |
struct tipc_subscription *sub, *tmp; |
be47e41d7 tipc: fix use-aft... |
482 |
struct service_range *sr = NULL; |
218527fe2 tipc: replace nam... |
483 |
struct publication *p = NULL; |
5f30721c5 tipc: clean up re... |
484 |
bool last; |
b97bf3fd8 [TIPC] Initial merge |
485 |
|
218527fe2 tipc: replace nam... |
486 |
if (!sc) |
1fc54d8f4 [TIPC]: Fix simpl... |
487 |
return NULL; |
b97bf3fd8 [TIPC] Initial merge |
488 |
|
218527fe2 tipc: replace nam... |
489 |
spin_lock_bh(&sc->lock); |
5f30721c5 tipc: clean up re... |
490 491 492 493 494 495 496 497 498 499 500 501 502 |
sr = tipc_service_find_range(sc, lower, upper); if (!sr) goto exit; p = tipc_service_remove_publ(sr, node, key); if (!p) goto exit; /* Notify any waiting subscriptions */ last = list_empty(&sr->all_publ); list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) { tipc_sub_report_overlap(sub, lower, upper, TIPC_WITHDRAWN, p->port, node, p->scope, last); } |
be47e41d7 tipc: fix use-aft... |
503 504 |
/* Remove service range item if this was its last publication */ |
5f30721c5 tipc: clean up re... |
505 |
if (list_empty(&sr->all_publ)) { |
d5162f341 tipc: fix name ta... |
506 |
rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks); |
be47e41d7 tipc: fix use-aft... |
507 508 |
kfree(sr); } |
218527fe2 tipc: replace nam... |
509 510 511 512 513 |
/* Delete service item if this no more publications and subscriptions */ if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { hlist_del_init_rcu(&sc->service_list); kfree_rcu(sc, rcu); |
fb9962f3c tipc: ensure all ... |
514 |
} |
5f30721c5 tipc: clean up re... |
515 |
exit: |
218527fe2 tipc: replace nam... |
516 517 |
spin_unlock_bh(&sc->lock); return p; |
b97bf3fd8 [TIPC] Initial merge |
518 |
} |
2c53040f0 net: Fix (nearly-... |
519 |
/** |
218527fe2 tipc: replace nam... |
520 |
* tipc_nametbl_translate - perform service instance to socket translation |
b97bf3fd8 [TIPC] Initial merge |
521 |
* |
f20889f72 tipc: refactor na... |
522 |
* On entry, 'dnode' is the search domain used during translation. |
bc9f8143e tipc: Revert name... |
523 524 |
* * On exit: |
f20889f72 tipc: refactor na... |
525 526 527 528 529 530 531 532 533 |
* - if translation is deferred to another node, leave 'dnode' unchanged and * return 0 * - if translation is attempted and succeeds, set 'dnode' to the publishing * node and return the published (non-zero) port number * - if translation is attempted and fails, set 'dnode' to 0 and return 0 * * Note that for legacy users (node configured with Z.C.N address format) the * 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0 * we must look in the local binding list first |
b97bf3fd8 [TIPC] Initial merge |
534 |
*/ |
f20889f72 tipc: refactor na... |
535 |
u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode) |
b97bf3fd8 [TIPC] Initial merge |
536 |
{ |
b89afb116 tipc: allow close... |
537 538 539 |
struct tipc_net *tn = tipc_net(net); bool legacy = tn->legacy_addr_format; u32 self = tipc_own_addr(net); |
218527fe2 tipc: replace nam... |
540 541 |
struct service_range *sr; struct tipc_service *sc; |
f20889f72 tipc: refactor na... |
542 |
struct list_head *list; |
218527fe2 tipc: replace nam... |
543 |
struct publication *p; |
e50e73e10 tipc: some name c... |
544 |
u32 port = 0; |
bc9f8143e tipc: Revert name... |
545 |
u32 node = 0; |
b97bf3fd8 [TIPC] Initial merge |
546 |
|
f20889f72 tipc: refactor na... |
547 |
if (!tipc_in_scope(legacy, *dnode, self)) |
b97bf3fd8 [TIPC] Initial merge |
548 |
return 0; |
97ede29e8 tipc: convert nam... |
549 |
rcu_read_lock(); |
218527fe2 tipc: replace nam... |
550 551 |
sc = tipc_service_find(net, type); if (unlikely(!sc)) |
d5162f341 tipc: fix name ta... |
552 |
goto exit; |
218527fe2 tipc: replace nam... |
553 554 |
spin_lock_bh(&sc->lock); |
d5162f341 tipc: fix name ta... |
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
service_range_foreach_match(sr, sc, instance, instance) { /* Select lookup algo: local, closest-first or round-robin */ if (*dnode == self) { list = &sr->local_publ; if (list_empty(list)) continue; p = list_first_entry(list, struct publication, local_publ); list_move_tail(&p->local_publ, &sr->local_publ); } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) { list = &sr->local_publ; p = list_first_entry(list, struct publication, local_publ); list_move_tail(&p->local_publ, &sr->local_publ); } else { list = &sr->all_publ; p = list_first_entry(list, struct publication, all_publ); list_move_tail(&p->all_publ, &sr->all_publ); } port = p->port; node = p->node; /* Todo: as for legacy, pick the first matching range only, a * "true" round-robin will be performed as needed. */ break; |
b97bf3fd8 [TIPC] Initial merge |
581 |
} |
218527fe2 tipc: replace nam... |
582 |
spin_unlock_bh(&sc->lock); |
d5162f341 tipc: fix name ta... |
583 584 |
exit: |
97ede29e8 tipc: convert nam... |
585 |
rcu_read_unlock(); |
f20889f72 tipc: refactor na... |
586 |
*dnode = node; |
e50e73e10 tipc: some name c... |
587 |
return port; |
b97bf3fd8 [TIPC] Initial merge |
588 |
} |
232d07b74 tipc: improve gro... |
589 |
bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope, |
ee106d7f9 tipc: introduce g... |
590 591 592 593 |
struct list_head *dsts, int *dstcnt, u32 exclude, bool all) { u32 self = tipc_own_addr(net); |
218527fe2 tipc: replace nam... |
594 595 596 |
struct service_range *sr; struct tipc_service *sc; struct publication *p; |
ee106d7f9 tipc: introduce g... |
597 |
|
ee106d7f9 tipc: introduce g... |
598 599 |
*dstcnt = 0; rcu_read_lock(); |
218527fe2 tipc: replace nam... |
600 601 |
sc = tipc_service_find(net, type); if (unlikely(!sc)) |
ee106d7f9 tipc: introduce g... |
602 |
goto exit; |
218527fe2 tipc: replace nam... |
603 604 |
spin_lock_bh(&sc->lock); |
d5162f341 tipc: fix name ta... |
605 606 |
/* Todo: a full search i.e. service_range_foreach_match() instead? */ sr = service_range_match_first(sc->ranges.rb_node, instance, instance); |
218527fe2 tipc: replace nam... |
607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
if (!sr) goto no_match; list_for_each_entry(p, &sr->all_publ, all_publ) { if (p->scope != scope) continue; if (p->port == exclude && p->node == self) continue; tipc_dest_push(dsts, p->node, p->port); (*dstcnt)++; if (all) continue; list_move_tail(&p->all_publ, &sr->all_publ); break; |
ee106d7f9 tipc: introduce g... |
621 |
} |
218527fe2 tipc: replace nam... |
622 623 |
no_match: spin_unlock_bh(&sc->lock); |
ee106d7f9 tipc: introduce g... |
624 625 626 627 |
exit: rcu_read_unlock(); return !list_empty(dsts); } |
ba765ec63 tipc: remove zone... |
628 629 |
void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper, u32 scope, bool exact, struct list_head *dports) |
b97bf3fd8 [TIPC] Initial merge |
630 |
{ |
218527fe2 tipc: replace nam... |
631 632 |
struct service_range *sr; struct tipc_service *sc; |
232d07b74 tipc: improve gro... |
633 |
struct publication *p; |
b97bf3fd8 [TIPC] Initial merge |
634 |
|
97ede29e8 tipc: convert nam... |
635 |
rcu_read_lock(); |
218527fe2 tipc: replace nam... |
636 637 |
sc = tipc_service_find(net, type); if (!sc) |
b97bf3fd8 [TIPC] Initial merge |
638 |
goto exit; |
218527fe2 tipc: replace nam... |
639 |
spin_lock_bh(&sc->lock); |
d5162f341 tipc: fix name ta... |
640 |
service_range_foreach_match(sr, sc, lower, upper) { |
218527fe2 tipc: replace nam... |
641 |
list_for_each_entry(p, &sr->local_publ, local_publ) { |
232d07b74 tipc: improve gro... |
642 |
if (p->scope == scope || (!exact && p->scope < scope)) |
e50e73e10 tipc: some name c... |
643 |
tipc_dest_push(dports, 0, p->port); |
968edbe1c tipc: Optimizatio... |
644 |
} |
b97bf3fd8 [TIPC] Initial merge |
645 |
} |
218527fe2 tipc: replace nam... |
646 |
spin_unlock_bh(&sc->lock); |
b97bf3fd8 [TIPC] Initial merge |
647 |
exit: |
97ede29e8 tipc: convert nam... |
648 |
rcu_read_unlock(); |
b97bf3fd8 [TIPC] Initial merge |
649 |
} |
2ae0b8af1 tipc: add functio... |
650 651 |
/* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes * - Creates list of nodes that overlap the given multicast address |
218527fe2 tipc: replace nam... |
652 |
* - Determines if any node local destinations overlap |
2ae0b8af1 tipc: add functio... |
653 654 |
*/ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, |
e9a034456 tipc: fix bug dur... |
655 |
u32 upper, struct tipc_nlist *nodes) |
2ae0b8af1 tipc: add functio... |
656 |
{ |
218527fe2 tipc: replace nam... |
657 658 659 |
struct service_range *sr; struct tipc_service *sc; struct publication *p; |
2ae0b8af1 tipc: add functio... |
660 661 |
rcu_read_lock(); |
218527fe2 tipc: replace nam... |
662 663 |
sc = tipc_service_find(net, type); if (!sc) |
2ae0b8af1 tipc: add functio... |
664 |
goto exit; |
218527fe2 tipc: replace nam... |
665 |
spin_lock_bh(&sc->lock); |
d5162f341 tipc: fix name ta... |
666 |
service_range_foreach_match(sr, sc, lower, upper) { |
218527fe2 tipc: replace nam... |
667 668 |
list_for_each_entry(p, &sr->all_publ, all_publ) { tipc_nlist_add(nodes, p->node); |
2ae0b8af1 tipc: add functio... |
669 670 |
} } |
218527fe2 tipc: replace nam... |
671 |
spin_unlock_bh(&sc->lock); |
2ae0b8af1 tipc: add functio... |
672 673 674 |
exit: rcu_read_unlock(); } |
75da2163d tipc: introduce c... |
675 676 677 |
/* tipc_nametbl_build_group - build list of communication group members */ void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, |
232d07b74 tipc: improve gro... |
678 |
u32 type, u32 scope) |
75da2163d tipc: introduce c... |
679 |
{ |
218527fe2 tipc: replace nam... |
680 681 |
struct service_range *sr; struct tipc_service *sc; |
75da2163d tipc: introduce c... |
682 |
struct publication *p; |
218527fe2 tipc: replace nam... |
683 |
struct rb_node *n; |
75da2163d tipc: introduce c... |
684 685 |
rcu_read_lock(); |
218527fe2 tipc: replace nam... |
686 687 |
sc = tipc_service_find(net, type); if (!sc) |
75da2163d tipc: introduce c... |
688 |
goto exit; |
218527fe2 tipc: replace nam... |
689 690 691 692 |
spin_lock_bh(&sc->lock); for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { sr = container_of(n, struct service_range, tree_node); list_for_each_entry(p, &sr->all_publ, all_publ) { |
232d07b74 tipc: improve gro... |
693 |
if (p->scope != scope) |
75da2163d tipc: introduce c... |
694 |
continue; |
e50e73e10 tipc: some name c... |
695 |
tipc_group_add_member(grp, p->node, p->port, p->lower); |
75da2163d tipc: introduce c... |
696 697 |
} } |
218527fe2 tipc: replace nam... |
698 |
spin_unlock_bh(&sc->lock); |
75da2163d tipc: introduce c... |
699 700 701 |
exit: rcu_read_unlock(); } |
218527fe2 tipc: replace nam... |
702 |
/* tipc_nametbl_publish - add service binding to name table |
b97bf3fd8 [TIPC] Initial merge |
703 |
*/ |
f2f9800d4 tipc: make tipc n... |
704 |
struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, |
218527fe2 tipc: replace nam... |
705 |
u32 upper, u32 scope, u32 port, |
f2f9800d4 tipc: make tipc n... |
706 |
u32 key) |
b97bf3fd8 [TIPC] Initial merge |
707 |
{ |
218527fe2 tipc: replace nam... |
708 709 710 711 |
struct name_table *nt = tipc_name_table(net); struct tipc_net *tn = tipc_net(net); struct publication *p = NULL; struct sk_buff *skb = NULL; |
cad2929dc tipc: update a bi... |
712 |
u32 rc_dests; |
b97bf3fd8 [TIPC] Initial merge |
713 |
|
4ac1c8d0e tipc: name tipc n... |
714 |
spin_lock_bh(&tn->nametbl_lock); |
218527fe2 tipc: replace nam... |
715 716 717 718 719 |
if (nt->local_publ_count >= TIPC_MAX_PUBL) { pr_warn("Bind failed, max limit %u reached ", TIPC_MAX_PUBL); goto exit; |
b97bf3fd8 [TIPC] Initial merge |
720 |
} |
b97bf3fd8 [TIPC] Initial merge |
721 |
|
218527fe2 tipc: replace nam... |
722 723 724 725 726 |
p = tipc_nametbl_insert_publ(net, type, lower, upper, scope, tipc_own_addr(net), port, key); if (p) { nt->local_publ_count++; skb = tipc_named_publish(net, p); |
fd6eced8a tipc: Don't recor... |
727 |
} |
cad2929dc tipc: update a bi... |
728 |
rc_dests = nt->rc_dests; |
218527fe2 tipc: replace nam... |
729 |
exit: |
4ac1c8d0e tipc: name tipc n... |
730 |
spin_unlock_bh(&tn->nametbl_lock); |
eab8c0457 tipc: move the de... |
731 |
|
218527fe2 tipc: replace nam... |
732 |
if (skb) |
cad2929dc tipc: update a bi... |
733 |
tipc_node_broadcast(net, skb, rc_dests); |
218527fe2 tipc: replace nam... |
734 |
return p; |
cad2929dc tipc: update a bi... |
735 |
|
b97bf3fd8 [TIPC] Initial merge |
736 737 738 |
} /** |
218527fe2 tipc: replace nam... |
739 |
* tipc_nametbl_withdraw - withdraw a service binding |
b97bf3fd8 [TIPC] Initial merge |
740 |
*/ |
218527fe2 tipc: replace nam... |
741 |
int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, |
37922ea4a tipc: permit over... |
742 |
u32 upper, u32 key) |
b97bf3fd8 [TIPC] Initial merge |
743 |
{ |
218527fe2 tipc: replace nam... |
744 745 746 |
struct name_table *nt = tipc_name_table(net); struct tipc_net *tn = tipc_net(net); u32 self = tipc_own_addr(net); |
5492390a9 tipc: simplify re... |
747 |
struct sk_buff *skb = NULL; |
218527fe2 tipc: replace nam... |
748 |
struct publication *p; |
cad2929dc tipc: update a bi... |
749 |
u32 rc_dests; |
b97bf3fd8 [TIPC] Initial merge |
750 |
|
4ac1c8d0e tipc: name tipc n... |
751 |
spin_lock_bh(&tn->nametbl_lock); |
218527fe2 tipc: replace nam... |
752 |
|
37922ea4a tipc: permit over... |
753 |
p = tipc_nametbl_remove_publ(net, type, lower, upper, self, key); |
218527fe2 tipc: replace nam... |
754 755 756 |
if (p) { nt->local_publ_count--; skb = tipc_named_withdraw(net, p); |
218527fe2 tipc: replace nam... |
757 758 |
list_del_init(&p->binding_sock); kfree_rcu(p, rcu); |
5492390a9 tipc: simplify re... |
759 |
} else { |
218527fe2 tipc: replace nam... |
760 761 |
pr_err("Failed to remove local publication {%u,%u,%u}/%u ", |
37922ea4a tipc: permit over... |
762 |
type, lower, upper, key); |
5492390a9 tipc: simplify re... |
763 |
} |
cad2929dc tipc: update a bi... |
764 |
rc_dests = nt->rc_dests; |
4ac1c8d0e tipc: name tipc n... |
765 |
spin_unlock_bh(&tn->nametbl_lock); |
eab8c0457 tipc: move the de... |
766 |
|
5492390a9 tipc: simplify re... |
767 |
if (skb) { |
cad2929dc tipc: update a bi... |
768 |
tipc_node_broadcast(net, skb, rc_dests); |
b97bf3fd8 [TIPC] Initial merge |
769 770 |
return 1; } |
b97bf3fd8 [TIPC] Initial merge |
771 772 773 774 |
return 0; } /** |
4323add67 [TIPC] Avoid poll... |
775 |
* tipc_nametbl_subscribe - add a subscription object to the name table |
b97bf3fd8 [TIPC] Initial merge |
776 |
*/ |
c3317f4db tipc: fix unbalan... |
777 |
bool tipc_nametbl_subscribe(struct tipc_subscription *sub) |
b97bf3fd8 [TIPC] Initial merge |
778 |
{ |
218527fe2 tipc: replace nam... |
779 |
struct name_table *nt = tipc_name_table(sub->net); |
5c45ab24a tipc: make struct... |
780 |
struct tipc_net *tn = tipc_net(sub->net); |
8985ecc7c tipc: simplify en... |
781 782 |
struct tipc_subscr *s = &sub->evt.s; u32 type = tipc_sub_read(s, seq.type); |
218527fe2 tipc: replace nam... |
783 |
struct tipc_service *sc; |
c3317f4db tipc: fix unbalan... |
784 |
bool res = true; |
b97bf3fd8 [TIPC] Initial merge |
785 |
|
4ac1c8d0e tipc: name tipc n... |
786 |
spin_lock_bh(&tn->nametbl_lock); |
218527fe2 tipc: replace nam... |
787 788 789 790 791 792 793 |
sc = tipc_service_find(sub->net, type); if (!sc) sc = tipc_service_create(type, &nt->services[hash(type)]); if (sc) { spin_lock_bh(&sc->lock); tipc_service_subscribe(sc, sub); spin_unlock_bh(&sc->lock); |
c43072852 [NET] TIPC: Fix w... |
794 |
} else { |
218527fe2 tipc: replace nam... |
795 796 797 798 |
pr_warn("Failed to subscribe for {%u,%u,%u} ", type, tipc_sub_read(s, seq.lower), tipc_sub_read(s, seq.upper)); |
c3317f4db tipc: fix unbalan... |
799 |
res = false; |
c43072852 [NET] TIPC: Fix w... |
800 |
} |
4ac1c8d0e tipc: name tipc n... |
801 |
spin_unlock_bh(&tn->nametbl_lock); |
c3317f4db tipc: fix unbalan... |
802 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
803 804 805 |
} /** |
4323add67 [TIPC] Avoid poll... |
806 |
* tipc_nametbl_unsubscribe - remove a subscription object from name table |
b97bf3fd8 [TIPC] Initial merge |
807 |
*/ |
8985ecc7c tipc: simplify en... |
808 |
void tipc_nametbl_unsubscribe(struct tipc_subscription *sub) |
b97bf3fd8 [TIPC] Initial merge |
809 |
{ |
5c45ab24a tipc: make struct... |
810 |
struct tipc_net *tn = tipc_net(sub->net); |
218527fe2 tipc: replace nam... |
811 |
struct tipc_subscr *s = &sub->evt.s; |
8985ecc7c tipc: simplify en... |
812 |
u32 type = tipc_sub_read(s, seq.type); |
218527fe2 tipc: replace nam... |
813 |
struct tipc_service *sc; |
b97bf3fd8 [TIPC] Initial merge |
814 |
|
4ac1c8d0e tipc: name tipc n... |
815 |
spin_lock_bh(&tn->nametbl_lock); |
218527fe2 tipc: replace nam... |
816 817 818 819 820 821 822 823 824 825 826 827 |
sc = tipc_service_find(sub->net, type); if (!sc) goto exit; spin_lock_bh(&sc->lock); list_del_init(&sub->service_list); tipc_sub_put(sub); /* Delete service item if no more publications and subscriptions */ if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { hlist_del_init_rcu(&sc->service_list); kfree_rcu(sc, rcu); |
c43072852 [NET] TIPC: Fix w... |
828 |
} |
218527fe2 tipc: replace nam... |
829 830 |
spin_unlock_bh(&sc->lock); exit: |
4ac1c8d0e tipc: name tipc n... |
831 |
spin_unlock_bh(&tn->nametbl_lock); |
b97bf3fd8 [TIPC] Initial merge |
832 |
} |
4ac1c8d0e tipc: name tipc n... |
833 |
int tipc_nametbl_init(struct net *net) |
b97bf3fd8 [TIPC] Initial merge |
834 |
{ |
218527fe2 tipc: replace nam... |
835 836 |
struct tipc_net *tn = tipc_net(net); struct name_table *nt; |
993bfe5da tipc: make name t... |
837 |
int i; |
04b9ce48e net: tipc: name_t... |
838 |
nt = kzalloc(sizeof(*nt), GFP_KERNEL); |
218527fe2 tipc: replace nam... |
839 |
if (!nt) |
b97bf3fd8 [TIPC] Initial merge |
840 |
return -ENOMEM; |
993bfe5da tipc: make name t... |
841 |
for (i = 0; i < TIPC_NAMETBL_SIZE; i++) |
218527fe2 tipc: replace nam... |
842 |
INIT_HLIST_HEAD(&nt->services[i]); |
993bfe5da tipc: make name t... |
843 |
|
218527fe2 tipc: replace nam... |
844 845 |
INIT_LIST_HEAD(&nt->node_scope); INIT_LIST_HEAD(&nt->cluster_scope); |
988f3f160 tipc: eliminate m... |
846 |
rwlock_init(&nt->cluster_scope_lock); |
218527fe2 tipc: replace nam... |
847 |
tn->nametbl = nt; |
4ac1c8d0e tipc: name tipc n... |
848 |
spin_lock_init(&tn->nametbl_lock); |
b97bf3fd8 [TIPC] Initial merge |
849 850 |
return 0; } |
1bb8dce57 tipc: fix memory ... |
851 |
/** |
218527fe2 tipc: replace nam... |
852 |
* tipc_service_delete - purge all publications for a service and delete it |
1bb8dce57 tipc: fix memory ... |
853 |
*/ |
218527fe2 tipc: replace nam... |
854 |
static void tipc_service_delete(struct net *net, struct tipc_service *sc) |
1bb8dce57 tipc: fix memory ... |
855 |
{ |
218527fe2 tipc: replace nam... |
856 |
struct service_range *sr, *tmpr; |
be47e41d7 tipc: fix use-aft... |
857 |
struct publication *p, *tmp; |
218527fe2 tipc: replace nam... |
858 859 860 |
spin_lock_bh(&sc->lock); rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) { |
be47e41d7 tipc: fix use-aft... |
861 |
list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) { |
5f30721c5 tipc: clean up re... |
862 |
tipc_service_remove_publ(sr, p->node, p->key); |
218527fe2 tipc: replace nam... |
863 864 |
kfree_rcu(p, rcu); } |
d5162f341 tipc: fix name ta... |
865 |
rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks); |
be47e41d7 tipc: fix use-aft... |
866 |
kfree(sr); |
1bb8dce57 tipc: fix memory ... |
867 |
} |
218527fe2 tipc: replace nam... |
868 869 870 |
hlist_del_init_rcu(&sc->service_list); spin_unlock_bh(&sc->lock); kfree_rcu(sc, rcu); |
1bb8dce57 tipc: fix memory ... |
871 |
} |
4ac1c8d0e tipc: name tipc n... |
872 |
void tipc_nametbl_stop(struct net *net) |
b97bf3fd8 [TIPC] Initial merge |
873 |
{ |
218527fe2 tipc: replace nam... |
874 875 876 877 |
struct name_table *nt = tipc_name_table(net); struct tipc_net *tn = tipc_net(net); struct hlist_head *service_head; struct tipc_service *service; |
b97bf3fd8 [TIPC] Initial merge |
878 |
u32 i; |
1bb8dce57 tipc: fix memory ... |
879 880 881 |
/* Verify name table is empty and purge any lingering * publications, then release the name table */ |
4ac1c8d0e tipc: name tipc n... |
882 |
spin_lock_bh(&tn->nametbl_lock); |
f046e7d9b tipc: convert tip... |
883 |
for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
218527fe2 tipc: replace nam... |
884 |
if (hlist_empty(&nt->services[i])) |
f705ab956 tipc: limit error... |
885 |
continue; |
218527fe2 tipc: replace nam... |
886 887 888 |
service_head = &nt->services[i]; hlist_for_each_entry_rcu(service, service_head, service_list) { tipc_service_delete(net, service); |
1bb8dce57 tipc: fix memory ... |
889 |
} |
b97bf3fd8 [TIPC] Initial merge |
890 |
} |
4ac1c8d0e tipc: name tipc n... |
891 |
spin_unlock_bh(&tn->nametbl_lock); |
993bfe5da tipc: make name t... |
892 |
|
97ede29e8 tipc: convert nam... |
893 |
synchronize_net(); |
218527fe2 tipc: replace nam... |
894 |
kfree(nt); |
b97bf3fd8 [TIPC] Initial merge |
895 |
} |
1593123a6 tipc: add name ta... |
896 |
|
d8182804c tipc: fix sparse ... |
897 |
static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, |
218527fe2 tipc: replace nam... |
898 899 900 |
struct tipc_service *service, struct service_range *sr, u32 *last_key) |
1593123a6 tipc: add name ta... |
901 |
{ |
1593123a6 tipc: add name ta... |
902 |
struct publication *p; |
218527fe2 tipc: replace nam... |
903 904 905 |
struct nlattr *attrs; struct nlattr *b; void *hdr; |
1593123a6 tipc: add name ta... |
906 |
|
218527fe2 tipc: replace nam... |
907 908 909 |
if (*last_key) { list_for_each_entry(p, &sr->all_publ, all_publ) if (p->key == *last_key) |
1593123a6 tipc: add name ta... |
910 |
break; |
218527fe2 tipc: replace nam... |
911 |
if (p->key != *last_key) |
1593123a6 tipc: add name ta... |
912 913 |
return -EPIPE; } else { |
218527fe2 tipc: replace nam... |
914 915 |
p = list_first_entry(&sr->all_publ, struct publication, |
e50e73e10 tipc: some name c... |
916 |
all_publ); |
1593123a6 tipc: add name ta... |
917 |
} |
218527fe2 tipc: replace nam... |
918 919 |
list_for_each_entry_from(p, &sr->all_publ, all_publ) { *last_key = p->key; |
1593123a6 tipc: add name ta... |
920 921 |
hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, |
bfb3e5dd8 tipc: move and re... |
922 |
&tipc_genl_family, NLM_F_MULTI, |
1593123a6 tipc: add name ta... |
923 924 925 |
TIPC_NL_NAME_TABLE_GET); if (!hdr) return -EMSGSIZE; |
ae0be8de9 netlink: make nla... |
926 |
attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE); |
1593123a6 tipc: add name ta... |
927 928 |
if (!attrs) goto msg_full; |
ae0be8de9 netlink: make nla... |
929 |
b = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE_PUBL); |
218527fe2 tipc: replace nam... |
930 |
if (!b) |
1593123a6 tipc: add name ta... |
931 |
goto attr_msg_full; |
218527fe2 tipc: replace nam... |
932 |
if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, service->type)) |
1593123a6 tipc: add name ta... |
933 |
goto publ_msg_full; |
218527fe2 tipc: replace nam... |
934 |
if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sr->lower)) |
1593123a6 tipc: add name ta... |
935 |
goto publ_msg_full; |
218527fe2 tipc: replace nam... |
936 |
if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sr->upper)) |
1593123a6 tipc: add name ta... |
937 938 939 940 941 |
goto publ_msg_full; if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope)) goto publ_msg_full; if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node)) goto publ_msg_full; |
e50e73e10 tipc: some name c... |
942 |
if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->port)) |
1593123a6 tipc: add name ta... |
943 944 945 |
goto publ_msg_full; if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key)) goto publ_msg_full; |
218527fe2 tipc: replace nam... |
946 |
nla_nest_end(msg->skb, b); |
1593123a6 tipc: add name ta... |
947 948 949 |
nla_nest_end(msg->skb, attrs); genlmsg_end(msg->skb, hdr); } |
218527fe2 tipc: replace nam... |
950 |
*last_key = 0; |
1593123a6 tipc: add name ta... |
951 952 953 954 |
return 0; publ_msg_full: |
218527fe2 tipc: replace nam... |
955 |
nla_nest_cancel(msg->skb, b); |
1593123a6 tipc: add name ta... |
956 957 958 959 960 961 962 |
attr_msg_full: nla_nest_cancel(msg->skb, attrs); msg_full: genlmsg_cancel(msg->skb, hdr); return -EMSGSIZE; } |
218527fe2 tipc: replace nam... |
963 964 965 |
static int __tipc_nl_service_range_list(struct tipc_nl_msg *msg, struct tipc_service *sc, u32 *last_lower, u32 *last_key) |
1593123a6 tipc: add name ta... |
966 |
{ |
218527fe2 tipc: replace nam... |
967 968 |
struct service_range *sr; struct rb_node *n; |
1593123a6 tipc: add name ta... |
969 |
int err; |
218527fe2 tipc: replace nam... |
970 971 972 973 974 |
for (n = rb_first(&sc->ranges); n; n = rb_next(n)) { sr = container_of(n, struct service_range, tree_node); if (sr->lower < *last_lower) continue; err = __tipc_nl_add_nametable_publ(msg, sc, sr, last_key); |
1593123a6 tipc: add name ta... |
975 |
if (err) { |
218527fe2 tipc: replace nam... |
976 |
*last_lower = sr->lower; |
1593123a6 tipc: add name ta... |
977 978 979 980 |
return err; } } *last_lower = 0; |
1593123a6 tipc: add name ta... |
981 982 |
return 0; } |
218527fe2 tipc: replace nam... |
983 984 |
static int tipc_nl_service_list(struct net *net, struct tipc_nl_msg *msg, u32 *last_type, u32 *last_lower, u32 *last_key) |
1593123a6 tipc: add name ta... |
985 |
{ |
218527fe2 tipc: replace nam... |
986 987 988 |
struct tipc_net *tn = tipc_net(net); struct tipc_service *service = NULL; struct hlist_head *head; |
1593123a6 tipc: add name ta... |
989 990 991 992 993 994 995 996 997 |
int err; int i; if (*last_type) i = hash(*last_type); else i = 0; for (; i < TIPC_NAMETBL_SIZE; i++) { |
218527fe2 tipc: replace nam... |
998 |
head = &tn->nametbl->services[i]; |
1593123a6 tipc: add name ta... |
999 |
|
d1841533e tipc: missing ent... |
1000 1001 |
if (*last_type || (!i && *last_key && (*last_lower == *last_key))) { |
218527fe2 tipc: replace nam... |
1002 1003 |
service = tipc_service_find(net, *last_type); if (!service) |
1593123a6 tipc: add name ta... |
1004 1005 |
return -EPIPE; } else { |
218527fe2 tipc: replace nam... |
1006 |
hlist_for_each_entry_rcu(service, head, service_list) |
97ede29e8 tipc: convert nam... |
1007 |
break; |
218527fe2 tipc: replace nam... |
1008 |
if (!service) |
1593123a6 tipc: add name ta... |
1009 1010 |
continue; } |
218527fe2 tipc: replace nam... |
1011 1012 1013 1014 1015 |
hlist_for_each_entry_from_rcu(service, service_list) { spin_lock_bh(&service->lock); err = __tipc_nl_service_range_list(msg, service, last_lower, last_key); |
1593123a6 tipc: add name ta... |
1016 1017 |
if (err) { |
218527fe2 tipc: replace nam... |
1018 1019 |
*last_type = service->type; spin_unlock_bh(&service->lock); |
1593123a6 tipc: add name ta... |
1020 1021 |
return err; } |
218527fe2 tipc: replace nam... |
1022 |
spin_unlock_bh(&service->lock); |
1593123a6 tipc: add name ta... |
1023 1024 1025 1026 1027 1028 1029 1030 |
} *last_type = 0; } return 0; } int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) { |
218527fe2 tipc: replace nam... |
1031 |
struct net *net = sock_net(skb->sk); |
1593123a6 tipc: add name ta... |
1032 1033 |
u32 last_type = cb->args[0]; u32 last_lower = cb->args[1]; |
218527fe2 tipc: replace nam... |
1034 1035 |
u32 last_key = cb->args[2]; int done = cb->args[3]; |
1593123a6 tipc: add name ta... |
1036 |
struct tipc_nl_msg msg; |
218527fe2 tipc: replace nam... |
1037 |
int err; |
1593123a6 tipc: add name ta... |
1038 1039 1040 1041 1042 1043 1044 |
if (done) return 0; msg.skb = skb; msg.portid = NETLINK_CB(cb->skb).portid; msg.seq = cb->nlh->nlmsg_seq; |
97ede29e8 tipc: convert nam... |
1045 |
rcu_read_lock(); |
218527fe2 tipc: replace nam... |
1046 1047 |
err = tipc_nl_service_list(net, &msg, &last_type, &last_lower, &last_key); |
1593123a6 tipc: add name ta... |
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 |
if (!err) { done = 1; } else if (err != -EMSGSIZE) { /* We never set seq or call nl_dump_check_consistent() this * means that setting prev_seq here will cause the consistence * check to fail in the netlink callback handler. Resulting in * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if * we got an error. */ cb->prev_seq = 1; } |
97ede29e8 tipc: convert nam... |
1059 |
rcu_read_unlock(); |
1593123a6 tipc: add name ta... |
1060 1061 1062 |
cb->args[0] = last_type; cb->args[1] = last_lower; |
218527fe2 tipc: replace nam... |
1063 |
cb->args[2] = last_key; |
1593123a6 tipc: add name ta... |
1064 1065 1066 1067 |
cb->args[3] = done; return skb->len; } |
3c724acdd tipc: simplify so... |
1068 |
|
a80ae5306 tipc: improve des... |
1069 |
struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port) |
3c724acdd tipc: simplify so... |
1070 |
{ |
a80ae5306 tipc: improve des... |
1071 |
struct tipc_dest *dst; |
3c724acdd tipc: simplify so... |
1072 |
|
a80ae5306 tipc: improve des... |
1073 |
list_for_each_entry(dst, l, list) { |
30935198b tipc: fix the big... |
1074 1075 |
if (dst->node == node && dst->port == port) return dst; |
3c724acdd tipc: simplify so... |
1076 |
} |
a80ae5306 tipc: improve des... |
1077 |
return NULL; |
4d8642d89 tipc: modify stru... |
1078 |
} |
a80ae5306 tipc: improve des... |
1079 |
bool tipc_dest_push(struct list_head *l, u32 node, u32 port) |
4d8642d89 tipc: modify stru... |
1080 |
{ |
a80ae5306 tipc: improve des... |
1081 |
struct tipc_dest *dst; |
4d8642d89 tipc: modify stru... |
1082 |
|
a80ae5306 tipc: improve des... |
1083 |
if (tipc_dest_find(l, node, port)) |
4d8642d89 tipc: modify stru... |
1084 |
return false; |
a80ae5306 tipc: improve des... |
1085 1086 1087 |
dst = kmalloc(sizeof(*dst), GFP_ATOMIC); if (unlikely(!dst)) return false; |
30935198b tipc: fix the big... |
1088 1089 |
dst->node = node; dst->port = port; |
a80ae5306 tipc: improve des... |
1090 |
list_add(&dst->list, l); |
4d8642d89 tipc: modify stru... |
1091 1092 |
return true; } |
a80ae5306 tipc: improve des... |
1093 |
bool tipc_dest_pop(struct list_head *l, u32 *node, u32 *port) |
4d8642d89 tipc: modify stru... |
1094 |
{ |
a80ae5306 tipc: improve des... |
1095 |
struct tipc_dest *dst; |
4d8642d89 tipc: modify stru... |
1096 1097 |
if (list_empty(l)) |
a80ae5306 tipc: improve des... |
1098 1099 1100 1101 1102 1103 1104 1105 1106 |
return false; dst = list_first_entry(l, typeof(*dst), list); if (port) *port = dst->port; if (node) *node = dst->node; list_del(&dst->list); kfree(dst); return true; |
4d8642d89 tipc: modify stru... |
1107 |
} |
a80ae5306 tipc: improve des... |
1108 |
bool tipc_dest_del(struct list_head *l, u32 node, u32 port) |
4d8642d89 tipc: modify stru... |
1109 |
{ |
a80ae5306 tipc: improve des... |
1110 |
struct tipc_dest *dst; |
4d8642d89 tipc: modify stru... |
1111 |
|
a80ae5306 tipc: improve des... |
1112 1113 1114 1115 1116 1117 |
dst = tipc_dest_find(l, node, port); if (!dst) return false; list_del(&dst->list); kfree(dst); return true; |
4d8642d89 tipc: modify stru... |
1118 |
} |
a80ae5306 tipc: improve des... |
1119 |
void tipc_dest_list_purge(struct list_head *l) |
4d8642d89 tipc: modify stru... |
1120 |
{ |
a80ae5306 tipc: improve des... |
1121 |
struct tipc_dest *dst, *tmp; |
4d8642d89 tipc: modify stru... |
1122 |
|
a80ae5306 tipc: improve des... |
1123 1124 1125 |
list_for_each_entry_safe(dst, tmp, l, list) { list_del(&dst->list); kfree(dst); |
3c724acdd tipc: simplify so... |
1126 1127 |
} } |
a80ae5306 tipc: improve des... |
1128 |
int tipc_dest_list_len(struct list_head *l) |
3c724acdd tipc: simplify so... |
1129 |
{ |
a80ae5306 tipc: improve des... |
1130 |
struct tipc_dest *dst; |
4d8642d89 tipc: modify stru... |
1131 |
int i = 0; |
3c724acdd tipc: simplify so... |
1132 |
|
a80ae5306 tipc: improve des... |
1133 |
list_for_each_entry(dst, l, list) { |
4d8642d89 tipc: modify stru... |
1134 |
i++; |
3c724acdd tipc: simplify so... |
1135 |
} |
4d8642d89 tipc: modify stru... |
1136 |
return i; |
3c724acdd tipc: simplify so... |
1137 |
} |