aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/name_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/name_table.c')
-rw-r--r--net/tipc/name_table.c289
1 files changed, 120 insertions, 169 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 205ed4a4e18..46e6b6c2ecc 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -2,7 +2,7 @@
2 * net/tipc/name_table.c: TIPC name table code 2 * net/tipc/name_table.c: TIPC name table code
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2004-2008, Wind River Systems 5 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,7 @@
44static int tipc_nametbl_size = 1024; /* must be a power of 2 */ 44static int tipc_nametbl_size = 1024; /* must be a power of 2 */
45 45
46/** 46/**
47 * struct sub_seq - container for all published instances of a name sequence 47 * struct name_info - name sequence publication info
48 * @lower: name sequence lower bound
49 * @upper: name sequence upper bound
50 * @node_list: circular list of publications made by own node 48 * @node_list: circular list of publications made by own node
51 * @cluster_list: circular list of publications made by own cluster 49 * @cluster_list: circular list of publications made by own cluster
52 * @zone_list: circular list of publications made by own zone 50 * @zone_list: circular list of publications made by own zone
@@ -59,18 +57,29 @@ static int tipc_nametbl_size = 1024; /* must be a power of 2 */
59 * (The cluster and node lists may be empty.) 57 * (The cluster and node lists may be empty.)
60 */ 58 */
61 59
62struct sub_seq { 60struct name_info {
63 u32 lower; 61 struct list_head node_list;
64 u32 upper; 62 struct list_head cluster_list;
65 struct publication *node_list; 63 struct list_head zone_list;
66 struct publication *cluster_list;
67 struct publication *zone_list;
68 u32 node_list_size; 64 u32 node_list_size;
69 u32 cluster_list_size; 65 u32 cluster_list_size;
70 u32 zone_list_size; 66 u32 zone_list_size;
71}; 67};
72 68
73/** 69/**
70 * struct sub_seq - container for all published instances of a name sequence
71 * @lower: name sequence lower bound
72 * @upper: name sequence upper bound
73 * @info: pointer to name sequence publication info
74 */
75
76struct sub_seq {
77 u32 lower;
78 u32 upper;
79 struct name_info *info;
80};
81
82/**
74 * struct name_seq - container for all published instances of a name type 83 * struct name_seq - container for all published instances of a name type
75 * @type: 32 bit 'type' value for name sequence 84 * @type: 32 bit 'type' value for name sequence
76 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; 85 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
@@ -246,6 +255,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
246 struct subscription *st; 255 struct subscription *st;
247 struct publication *publ; 256 struct publication *publ;
248 struct sub_seq *sseq; 257 struct sub_seq *sseq;
258 struct name_info *info;
249 int created_subseq = 0; 259 int created_subseq = 0;
250 260
251 sseq = nameseq_find_subseq(nseq, lower); 261 sseq = nameseq_find_subseq(nseq, lower);
@@ -258,6 +268,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
258 type, lower, upper); 268 type, lower, upper);
259 return NULL; 269 return NULL;
260 } 270 }
271
272 info = sseq->info;
261 } else { 273 } else {
262 u32 inspos; 274 u32 inspos;
263 struct sub_seq *freesseq; 275 struct sub_seq *freesseq;
@@ -292,6 +304,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
292 nseq->alloc *= 2; 304 nseq->alloc *= 2;
293 } 305 }
294 306
307 info = kzalloc(sizeof(*info), GFP_ATOMIC);
308 if (!info) {
309 warn("Cannot publish {%u,%u,%u}, no memory\n",
310 type, lower, upper);
311 return NULL;
312 }
313
314 INIT_LIST_HEAD(&info->node_list);
315 INIT_LIST_HEAD(&info->cluster_list);
316 INIT_LIST_HEAD(&info->zone_list);
317
295 /* Insert new sub-sequence */ 318 /* Insert new sub-sequence */
296 319
297 sseq = &nseq->sseqs[inspos]; 320 sseq = &nseq->sseqs[inspos];
@@ -301,6 +324,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
301 nseq->first_free++; 324 nseq->first_free++;
302 sseq->lower = lower; 325 sseq->lower = lower;
303 sseq->upper = upper; 326 sseq->upper = upper;
327 sseq->info = info;
304 created_subseq = 1; 328 created_subseq = 1;
305 } 329 }
306 330
@@ -310,33 +334,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
310 if (!publ) 334 if (!publ)
311 return NULL; 335 return NULL;
312 336
313 sseq->zone_list_size++; 337 list_add(&publ->zone_list, &info->zone_list);
314 if (!sseq->zone_list) 338 info->zone_list_size++;
315 sseq->zone_list = publ->zone_list_next = publ;
316 else {
317 publ->zone_list_next = sseq->zone_list->zone_list_next;
318 sseq->zone_list->zone_list_next = publ;
319 }
320 339
321 if (in_own_cluster(node)) { 340 if (in_own_cluster(node)) {
322 sseq->cluster_list_size++; 341 list_add(&publ->cluster_list, &info->cluster_list);
323 if (!sseq->cluster_list) 342 info->cluster_list_size++;
324 sseq->cluster_list = publ->cluster_list_next = publ;
325 else {
326 publ->cluster_list_next =
327 sseq->cluster_list->cluster_list_next;
328 sseq->cluster_list->cluster_list_next = publ;
329 }
330 } 343 }
331 344
332 if (node == tipc_own_addr) { 345 if (node == tipc_own_addr) {
333 sseq->node_list_size++; 346 list_add(&publ->node_list, &info->node_list);
334 if (!sseq->node_list) 347 info->node_list_size++;
335 sseq->node_list = publ->node_list_next = publ;
336 else {
337 publ->node_list_next = sseq->node_list->node_list_next;
338 sseq->node_list->node_list_next = publ;
339 }
340 } 348 }
341 349
342 /* 350 /*
@@ -370,9 +378,8 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
370 u32 node, u32 ref, u32 key) 378 u32 node, u32 ref, u32 key)
371{ 379{
372 struct publication *publ; 380 struct publication *publ;
373 struct publication *curr;
374 struct publication *prev;
375 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); 381 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
382 struct name_info *info;
376 struct sub_seq *free; 383 struct sub_seq *free;
377 struct subscription *s, *st; 384 struct subscription *s, *st;
378 int removed_subseq = 0; 385 int removed_subseq = 0;
@@ -380,96 +387,41 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
380 if (!sseq) 387 if (!sseq)
381 return NULL; 388 return NULL;
382 389
383 /* Remove publication from zone scope list */ 390 info = sseq->info;
384 391
385 prev = sseq->zone_list; 392 /* Locate publication, if it exists */
386 publ = sseq->zone_list->zone_list_next;
387 while ((publ->key != key) || (publ->ref != ref) ||
388 (publ->node && (publ->node != node))) {
389 prev = publ;
390 publ = publ->zone_list_next;
391 if (prev == sseq->zone_list) {
392 393
393 /* Prevent endless loop if publication not found */ 394 list_for_each_entry(publ, &info->zone_list, zone_list) {
394 395 if ((publ->key == key) && (publ->ref == ref) &&
395 return NULL; 396 (!publ->node || (publ->node == node)))
396 } 397 goto found;
397 }
398 if (publ != sseq->zone_list)
399 prev->zone_list_next = publ->zone_list_next;
400 else if (publ->zone_list_next != publ) {
401 prev->zone_list_next = publ->zone_list_next;
402 sseq->zone_list = publ->zone_list_next;
403 } else {
404 sseq->zone_list = NULL;
405 } 398 }
406 sseq->zone_list_size--; 399 return NULL;
400
401found:
402 /* Remove publication from zone scope list */
403
404 list_del(&publ->zone_list);
405 info->zone_list_size--;
407 406
408 /* Remove publication from cluster scope list, if present */ 407 /* Remove publication from cluster scope list, if present */
409 408
410 if (in_own_cluster(node)) { 409 if (in_own_cluster(node)) {
411 prev = sseq->cluster_list; 410 list_del(&publ->cluster_list);
412 curr = sseq->cluster_list->cluster_list_next; 411 info->cluster_list_size--;
413 while (curr != publ) {
414 prev = curr;
415 curr = curr->cluster_list_next;
416 if (prev == sseq->cluster_list) {
417
418 /* Prevent endless loop for malformed list */
419
420 err("Unable to de-list cluster publication\n"
421 "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
422 publ->type, publ->lower, publ->node,
423 publ->ref, publ->key);
424 goto end_cluster;
425 }
426 }
427 if (publ != sseq->cluster_list)
428 prev->cluster_list_next = publ->cluster_list_next;
429 else if (publ->cluster_list_next != publ) {
430 prev->cluster_list_next = publ->cluster_list_next;
431 sseq->cluster_list = publ->cluster_list_next;
432 } else {
433 sseq->cluster_list = NULL;
434 }
435 sseq->cluster_list_size--;
436 } 412 }
437end_cluster:
438 413
439 /* Remove publication from node scope list, if present */ 414 /* Remove publication from node scope list, if present */
440 415
441 if (node == tipc_own_addr) { 416 if (node == tipc_own_addr) {
442 prev = sseq->node_list; 417 list_del(&publ->node_list);
443 curr = sseq->node_list->node_list_next; 418 info->node_list_size--;
444 while (curr != publ) {
445 prev = curr;
446 curr = curr->node_list_next;
447 if (prev == sseq->node_list) {
448
449 /* Prevent endless loop for malformed list */
450
451 err("Unable to de-list node publication\n"
452 "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
453 publ->type, publ->lower, publ->node,
454 publ->ref, publ->key);
455 goto end_node;
456 }
457 }
458 if (publ != sseq->node_list)
459 prev->node_list_next = publ->node_list_next;
460 else if (publ->node_list_next != publ) {
461 prev->node_list_next = publ->node_list_next;
462 sseq->node_list = publ->node_list_next;
463 } else {
464 sseq->node_list = NULL;
465 }
466 sseq->node_list_size--;
467 } 419 }
468end_node:
469 420
470 /* Contract subseq list if no more publications for that subseq */ 421 /* Contract subseq list if no more publications for that subseq */
471 422
472 if (!sseq->zone_list) { 423 if (list_empty(&info->zone_list)) {
424 kfree(info);
473 free = &nseq->sseqs[nseq->first_free--]; 425 free = &nseq->sseqs[nseq->first_free--];
474 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq)); 426 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
475 removed_subseq = 1; 427 removed_subseq = 1;
@@ -506,12 +458,12 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
506 return; 458 return;
507 459
508 while (sseq != &nseq->sseqs[nseq->first_free]) { 460 while (sseq != &nseq->sseqs[nseq->first_free]) {
509 struct publication *zl = sseq->zone_list; 461 if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
510 if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) { 462 struct publication *crs;
511 struct publication *crs = zl; 463 struct name_info *info = sseq->info;
512 int must_report = 1; 464 int must_report = 1;
513 465
514 do { 466 list_for_each_entry(crs, &info->zone_list, zone_list) {
515 tipc_subscr_report_overlap(s, 467 tipc_subscr_report_overlap(s,
516 sseq->lower, 468 sseq->lower,
517 sseq->upper, 469 sseq->upper,
@@ -520,8 +472,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
520 crs->node, 472 crs->node,
521 must_report); 473 must_report);
522 must_report = 0; 474 must_report = 0;
523 crs = crs->zone_list_next; 475 }
524 } while (crs != zl);
525 } 476 }
526 sseq++; 477 sseq++;
527 } 478 }
@@ -591,9 +542,10 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
591u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) 542u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
592{ 543{
593 struct sub_seq *sseq; 544 struct sub_seq *sseq;
594 struct publication *publ = NULL; 545 struct name_info *info;
546 struct publication *publ;
595 struct name_seq *seq; 547 struct name_seq *seq;
596 u32 ref; 548 u32 ref = 0;
597 549
598 if (!tipc_in_scope(*destnode, tipc_own_addr)) 550 if (!tipc_in_scope(*destnode, tipc_own_addr))
599 return 0; 551 return 0;
@@ -606,55 +558,57 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
606 if (unlikely(!sseq)) 558 if (unlikely(!sseq))
607 goto not_found; 559 goto not_found;
608 spin_lock_bh(&seq->lock); 560 spin_lock_bh(&seq->lock);
561 info = sseq->info;
609 562
610 /* Closest-First Algorithm: */ 563 /* Closest-First Algorithm: */
611 if (likely(!*destnode)) { 564 if (likely(!*destnode)) {
612 publ = sseq->node_list; 565 if (!list_empty(&info->node_list)) {
613 if (publ) { 566 publ = list_first_entry(&info->node_list,
614 sseq->node_list = publ->node_list_next; 567 struct publication,
615found: 568 node_list);
616 ref = publ->ref; 569 list_move_tail(&publ->node_list,
617 *destnode = publ->node; 570 &info->node_list);
618 spin_unlock_bh(&seq->lock); 571 } else if (!list_empty(&info->cluster_list)) {
619 read_unlock_bh(&tipc_nametbl_lock); 572 publ = list_first_entry(&info->cluster_list,
620 return ref; 573 struct publication,
621 } 574 cluster_list);
622 publ = sseq->cluster_list; 575 list_move_tail(&publ->cluster_list,
623 if (publ) { 576 &info->cluster_list);
624 sseq->cluster_list = publ->cluster_list_next; 577 } else {
625 goto found; 578 publ = list_first_entry(&info->zone_list,
626 } 579 struct publication,
627 publ = sseq->zone_list; 580 zone_list);
628 if (publ) { 581 list_move_tail(&publ->zone_list,
629 sseq->zone_list = publ->zone_list_next; 582 &info->zone_list);
630 goto found;
631 } 583 }
632 } 584 }
633 585
634 /* Round-Robin Algorithm: */ 586 /* Round-Robin Algorithm: */
635 else if (*destnode == tipc_own_addr) { 587 else if (*destnode == tipc_own_addr) {
636 publ = sseq->node_list; 588 if (list_empty(&info->node_list))
637 if (publ) { 589 goto no_match;
638 sseq->node_list = publ->node_list_next; 590 publ = list_first_entry(&info->node_list, struct publication,
639 goto found; 591 node_list);
640 } 592 list_move_tail(&publ->node_list, &info->node_list);
641 } else if (in_own_cluster(*destnode)) { 593 } else if (in_own_cluster(*destnode)) {
642 publ = sseq->cluster_list; 594 if (list_empty(&info->cluster_list))
643 if (publ) { 595 goto no_match;
644 sseq->cluster_list = publ->cluster_list_next; 596 publ = list_first_entry(&info->cluster_list, struct publication,
645 goto found; 597 cluster_list);
646 } 598 list_move_tail(&publ->cluster_list, &info->cluster_list);
647 } else { 599 } else {
648 publ = sseq->zone_list; 600 publ = list_first_entry(&info->zone_list, struct publication,
649 if (publ) { 601 zone_list);
650 sseq->zone_list = publ->zone_list_next; 602 list_move_tail(&publ->zone_list, &info->zone_list);
651 goto found;
652 }
653 } 603 }
604
605 ref = publ->ref;
606 *destnode = publ->node;
607no_match:
654 spin_unlock_bh(&seq->lock); 608 spin_unlock_bh(&seq->lock);
655not_found: 609not_found:
656 read_unlock_bh(&tipc_nametbl_lock); 610 read_unlock_bh(&tipc_nametbl_lock);
657 return 0; 611 return ref;
658} 612}
659 613
660/** 614/**
@@ -676,6 +630,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
676 struct name_seq *seq; 630 struct name_seq *seq;
677 struct sub_seq *sseq; 631 struct sub_seq *sseq;
678 struct sub_seq *sseq_stop; 632 struct sub_seq *sseq_stop;
633 struct name_info *info;
679 int res = 0; 634 int res = 0;
680 635
681 read_lock_bh(&tipc_nametbl_lock); 636 read_lock_bh(&tipc_nametbl_lock);
@@ -693,16 +648,13 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
693 if (sseq->lower > upper) 648 if (sseq->lower > upper)
694 break; 649 break;
695 650
696 publ = sseq->node_list; 651 info = sseq->info;
697 if (publ) { 652 list_for_each_entry(publ, &info->node_list, node_list) {
698 do { 653 if (publ->scope <= limit)
699 if (publ->scope <= limit) 654 tipc_port_list_add(dports, publ->ref);
700 tipc_port_list_add(dports, publ->ref);
701 publ = publ->node_list_next;
702 } while (publ != sseq->node_list);
703 } 655 }
704 656
705 if (sseq->cluster_list_size != sseq->node_list_size) 657 if (info->cluster_list_size != info->node_list_size)
706 res = 1; 658 res = 1;
707 } 659 }
708 660
@@ -840,16 +792,19 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
840{ 792{
841 char portIdStr[27]; 793 char portIdStr[27];
842 const char *scope_str[] = {"", " zone", " cluster", " node"}; 794 const char *scope_str[] = {"", " zone", " cluster", " node"};
843 struct publication *publ = sseq->zone_list; 795 struct publication *publ;
796 struct name_info *info;
844 797
845 tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); 798 tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
846 799
847 if (depth == 2 || !publ) { 800 if (depth == 2) {
848 tipc_printf(buf, "\n"); 801 tipc_printf(buf, "\n");
849 return; 802 return;
850 } 803 }
851 804
852 do { 805 info = sseq->info;
806
807 list_for_each_entry(publ, &info->zone_list, zone_list) {
853 sprintf(portIdStr, "<%u.%u.%u:%u>", 808 sprintf(portIdStr, "<%u.%u.%u:%u>",
854 tipc_zone(publ->node), tipc_cluster(publ->node), 809 tipc_zone(publ->node), tipc_cluster(publ->node),
855 tipc_node(publ->node), publ->ref); 810 tipc_node(publ->node), publ->ref);
@@ -858,13 +813,9 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
858 tipc_printf(buf, "%-10u %s", publ->key, 813 tipc_printf(buf, "%-10u %s", publ->key,
859 scope_str[publ->scope]); 814 scope_str[publ->scope]);
860 } 815 }
861 816 if (!list_is_last(&publ->zone_list, &info->zone_list))
862 publ = publ->zone_list_next; 817 tipc_printf(buf, "\n%33s", " ");
863 if (publ == sseq->zone_list) 818 };
864 break;
865
866 tipc_printf(buf, "\n%33s", " ");
867 } while (1);
868 819
869 tipc_printf(buf, "\n"); 820 tipc_printf(buf, "\n");
870} 821}