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.c207
1 files changed, 108 insertions, 99 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index d129422fc5c2..a6926ff07bcc 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -71,7 +71,7 @@ struct sub_seq {
71 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; 71 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
72 * sub-sequences are sorted in ascending order 72 * sub-sequences are sorted in ascending order
73 * @alloc: number of sub-sequences currently in array 73 * @alloc: number of sub-sequences currently in array
74 * @first_free: upper bound of highest sub-sequence + 1 74 * @first_free: array index of first unused sub-sequence entry
75 * @ns_list: links to adjacent name sequences in hash chain 75 * @ns_list: links to adjacent name sequences in hash chain
76 * @subscriptions: list of subscriptions for this 'type' 76 * @subscriptions: list of subscriptions for this 'type'
77 * @lock: spinlock controlling access to name sequence structure 77 * @lock: spinlock controlling access to name sequence structure
@@ -101,7 +101,7 @@ struct name_table {
101 101
102static struct name_table table = { NULL } ; 102static struct name_table table = { NULL } ;
103static atomic_t rsv_publ_ok = ATOMIC_INIT(0); 103static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
104rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; 104DEFINE_RWLOCK(tipc_nametbl_lock);
105 105
106 106
107static int hash(int x) 107static int hash(int x)
@@ -120,7 +120,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,
120 struct publication *publ = 120 struct publication *publ =
121 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); 121 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
122 if (publ == NULL) { 122 if (publ == NULL) {
123 warn("Memory squeeze; failed to create publication\n"); 123 warn("Publication creation failure, no memory\n");
124 return NULL; 124 return NULL;
125 } 125 }
126 126
@@ -165,17 +165,17 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea
165 struct sub_seq *sseq = tipc_subseq_alloc(1); 165 struct sub_seq *sseq = tipc_subseq_alloc(1);
166 166
167 if (!nseq || !sseq) { 167 if (!nseq || !sseq) {
168 warn("Memory squeeze; failed to create name sequence\n"); 168 warn("Name sequence creation failed, no memory\n");
169 kfree(nseq); 169 kfree(nseq);
170 kfree(sseq); 170 kfree(sseq);
171 return NULL; 171 return NULL;
172 } 172 }
173 173
174 memset(nseq, 0, sizeof(*nseq)); 174 memset(nseq, 0, sizeof(*nseq));
175 nseq->lock = SPIN_LOCK_UNLOCKED; 175 spin_lock_init(&nseq->lock);
176 nseq->type = type; 176 nseq->type = type;
177 nseq->sseqs = sseq; 177 nseq->sseqs = sseq;
178 dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", 178 dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u\n",
179 nseq, type, nseq->sseqs, nseq->first_free); 179 nseq, type, nseq->sseqs, nseq->first_free);
180 nseq->alloc = 1; 180 nseq->alloc = 1;
181 INIT_HLIST_NODE(&nseq->ns_list); 181 INIT_HLIST_NODE(&nseq->ns_list);
@@ -253,16 +253,16 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
253 struct sub_seq *sseq; 253 struct sub_seq *sseq;
254 int created_subseq = 0; 254 int created_subseq = 0;
255 255
256 assert(nseq->first_free <= nseq->alloc);
257 sseq = nameseq_find_subseq(nseq, lower); 256 sseq = nameseq_find_subseq(nseq, lower);
258 dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", 257 dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p\n",
259 nseq, type, lower, sseq); 258 nseq, type, lower, sseq);
260 if (sseq) { 259 if (sseq) {
261 260
262 /* Lower end overlaps existing entry => need an exact match */ 261 /* Lower end overlaps existing entry => need an exact match */
263 262
264 if ((sseq->lower != lower) || (sseq->upper != upper)) { 263 if ((sseq->lower != lower) || (sseq->upper != upper)) {
265 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 264 warn("Cannot publish {%u,%u,%u}, overlap error\n",
265 type, lower, upper);
266 return NULL; 266 return NULL;
267 } 267 }
268 } else { 268 } else {
@@ -277,25 +277,27 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
277 277
278 if ((inspos < nseq->first_free) && 278 if ((inspos < nseq->first_free) &&
279 (upper >= nseq->sseqs[inspos].lower)) { 279 (upper >= nseq->sseqs[inspos].lower)) {
280 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 280 warn("Cannot publish {%u,%u,%u}, overlap error\n",
281 type, lower, upper);
281 return NULL; 282 return NULL;
282 } 283 }
283 284
284 /* Ensure there is space for new sub-sequence */ 285 /* Ensure there is space for new sub-sequence */
285 286
286 if (nseq->first_free == nseq->alloc) { 287 if (nseq->first_free == nseq->alloc) {
287 struct sub_seq *sseqs = nseq->sseqs; 288 struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2);
288 nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2); 289
289 if (nseq->sseqs != NULL) { 290 if (!sseqs) {
290 memcpy(nseq->sseqs, sseqs, 291 warn("Cannot publish {%u,%u,%u}, no memory\n",
291 nseq->alloc * sizeof (struct sub_seq)); 292 type, lower, upper);
292 kfree(sseqs);
293 dbg("Allocated %u sseqs\n", nseq->alloc);
294 nseq->alloc *= 2;
295 } else {
296 warn("Memory squeeze; failed to create sub-sequence\n");
297 return NULL; 293 return NULL;
298 } 294 }
295 dbg("Allocated %u more sseqs\n", nseq->alloc);
296 memcpy(sseqs, nseq->sseqs,
297 nseq->alloc * sizeof(struct sub_seq));
298 kfree(nseq->sseqs);
299 nseq->sseqs = sseqs;
300 nseq->alloc *= 2;
299 } 301 }
300 dbg("Have %u sseqs for type %u\n", nseq->alloc, type); 302 dbg("Have %u sseqs for type %u\n", nseq->alloc, type);
301 303
@@ -311,7 +313,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
311 sseq->upper = upper; 313 sseq->upper = upper;
312 created_subseq = 1; 314 created_subseq = 1;
313 } 315 }
314 dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", 316 dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p\n",
315 type, lower, upper, node, port, sseq, 317 type, lower, upper, node, port, sseq,
316 sseq->lower, sseq->upper, nseq); 318 sseq->lower, sseq->upper, nseq);
317 319
@@ -320,7 +322,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
320 publ = publ_create(type, lower, upper, scope, node, port, key); 322 publ = publ_create(type, lower, upper, scope, node, port, key);
321 if (!publ) 323 if (!publ)
322 return NULL; 324 return NULL;
323 dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", 325 dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p\n",
324 publ, node, publ->node, publ->subscr.node); 326 publ, node, publ->node, publ->subscr.node);
325 327
326 if (!sseq->zone_list) 328 if (!sseq->zone_list)
@@ -367,45 +369,47 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
367 369
368/** 370/**
369 * tipc_nameseq_remove_publ - 371 * tipc_nameseq_remove_publ -
372 *
373 * NOTE: There may be cases where TIPC is asked to remove a publication
374 * that is not in the name table. For example, if another node issues a
375 * publication for a name sequence that overlaps an existing name sequence
376 * the publication will not be recorded, which means the publication won't
377 * be found when the name sequence is later withdrawn by that node.
378 * A failed withdraw request simply returns a failure indication and lets the
379 * caller issue any error or warning messages associated with such a problem.
370 */ 380 */
371 381
372static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, 382static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
373 u32 node, u32 ref, u32 key) 383 u32 node, u32 ref, u32 key)
374{ 384{
375 struct publication *publ; 385 struct publication *publ;
386 struct publication *curr;
376 struct publication *prev; 387 struct publication *prev;
377 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); 388 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
378 struct sub_seq *free; 389 struct sub_seq *free;
379 struct subscription *s, *st; 390 struct subscription *s, *st;
380 int removed_subseq = 0; 391 int removed_subseq = 0;
381 392
382 assert(nseq); 393 if (!sseq)
383
384 if (!sseq) {
385 int i;
386
387 warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst);
388 assert(nseq->sseqs);
389 dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n",
390 nseq->sseqs, nseq, nseq->alloc,
391 nseq->first_free);
392 for (i = 0; i < nseq->first_free; i++) {
393 dbg("Subseq %u(%x): lower = %u,upper = %u\n",
394 i, &nseq->sseqs[i], nseq->sseqs[i].lower,
395 nseq->sseqs[i].upper);
396 }
397 return NULL; 394 return NULL;
398 } 395
399 dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", 396 dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u\n",
400 nseq, sseq, nseq->type, inst, key); 397 nseq, sseq, nseq->type, inst, key);
401 398
399 /* Remove publication from zone scope list */
400
402 prev = sseq->zone_list; 401 prev = sseq->zone_list;
403 publ = sseq->zone_list->zone_list_next; 402 publ = sseq->zone_list->zone_list_next;
404 while ((publ->key != key) || (publ->ref != ref) || 403 while ((publ->key != key) || (publ->ref != ref) ||
405 (publ->node && (publ->node != node))) { 404 (publ->node && (publ->node != node))) {
406 prev = publ; 405 prev = publ;
407 publ = publ->zone_list_next; 406 publ = publ->zone_list_next;
408 assert(prev != sseq->zone_list); 407 if (prev == sseq->zone_list) {
408
409 /* Prevent endless loop if publication not found */
410
411 return NULL;
412 }
409 } 413 }
410 if (publ != sseq->zone_list) 414 if (publ != sseq->zone_list)
411 prev->zone_list_next = publ->zone_list_next; 415 prev->zone_list_next = publ->zone_list_next;
@@ -416,14 +420,24 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
416 sseq->zone_list = NULL; 420 sseq->zone_list = NULL;
417 } 421 }
418 422
423 /* Remove publication from cluster scope list, if present */
424
419 if (in_own_cluster(node)) { 425 if (in_own_cluster(node)) {
420 prev = sseq->cluster_list; 426 prev = sseq->cluster_list;
421 publ = sseq->cluster_list->cluster_list_next; 427 curr = sseq->cluster_list->cluster_list_next;
422 while ((publ->key != key) || (publ->ref != ref) || 428 while (curr != publ) {
423 (publ->node && (publ->node != node))) { 429 prev = curr;
424 prev = publ; 430 curr = curr->cluster_list_next;
425 publ = publ->cluster_list_next; 431 if (prev == sseq->cluster_list) {
426 assert(prev != sseq->cluster_list); 432
433 /* Prevent endless loop for malformed list */
434
435 err("Unable to de-list cluster publication\n"
436 "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
437 publ->type, publ->lower, publ->node,
438 publ->ref, publ->key);
439 goto end_cluster;
440 }
427 } 441 }
428 if (publ != sseq->cluster_list) 442 if (publ != sseq->cluster_list)
429 prev->cluster_list_next = publ->cluster_list_next; 443 prev->cluster_list_next = publ->cluster_list_next;
@@ -434,15 +448,26 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
434 sseq->cluster_list = NULL; 448 sseq->cluster_list = NULL;
435 } 449 }
436 } 450 }
451end_cluster:
452
453 /* Remove publication from node scope list, if present */
437 454
438 if (node == tipc_own_addr) { 455 if (node == tipc_own_addr) {
439 prev = sseq->node_list; 456 prev = sseq->node_list;
440 publ = sseq->node_list->node_list_next; 457 curr = sseq->node_list->node_list_next;
441 while ((publ->key != key) || (publ->ref != ref) || 458 while (curr != publ) {
442 (publ->node && (publ->node != node))) { 459 prev = curr;
443 prev = publ; 460 curr = curr->node_list_next;
444 publ = publ->node_list_next; 461 if (prev == sseq->node_list) {
445 assert(prev != sseq->node_list); 462
463 /* Prevent endless loop for malformed list */
464
465 err("Unable to de-list node publication\n"
466 "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
467 publ->type, publ->lower, publ->node,
468 publ->ref, publ->key);
469 goto end_node;
470 }
446 } 471 }
447 if (publ != sseq->node_list) 472 if (publ != sseq->node_list)
448 prev->node_list_next = publ->node_list_next; 473 prev->node_list_next = publ->node_list_next;
@@ -453,22 +478,18 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
453 sseq->node_list = NULL; 478 sseq->node_list = NULL;
454 } 479 }
455 } 480 }
456 assert(!publ->node || (publ->node == node)); 481end_node:
457 assert(publ->ref == ref);
458 assert(publ->key == key);
459 482
460 /* 483 /* Contract subseq list if no more publications for that subseq */
461 * Contract subseq list if no more publications: 484
462 */ 485 if (!sseq->zone_list) {
463 if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) {
464 free = &nseq->sseqs[nseq->first_free--]; 486 free = &nseq->sseqs[nseq->first_free--];
465 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); 487 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq));
466 removed_subseq = 1; 488 removed_subseq = 1;
467 } 489 }
468 490
469 /* 491 /* Notify any waiting subscriptions */
470 * Any subscriptions waiting ? 492
471 */
472 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { 493 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
473 tipc_subscr_report_overlap(s, 494 tipc_subscr_report_overlap(s,
474 publ->lower, 495 publ->lower,
@@ -478,6 +499,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
478 publ->node, 499 publ->node,
479 removed_subseq); 500 removed_subseq);
480 } 501 }
502
481 return publ; 503 return publ;
482} 504}
483 505
@@ -530,7 +552,7 @@ static struct name_seq *nametbl_find_seq(u32 type)
530 seq_head = &table.types[hash(type)]; 552 seq_head = &table.types[hash(type)];
531 hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { 553 hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
532 if (ns->type == type) { 554 if (ns->type == type) {
533 dbg("found %x\n", ns); 555 dbg("found %p\n", ns);
534 return ns; 556 return ns;
535 } 557 }
536 } 558 }
@@ -543,22 +565,21 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
543{ 565{
544 struct name_seq *seq = nametbl_find_seq(type); 566 struct name_seq *seq = nametbl_find_seq(type);
545 567
546 dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); 568 dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p\n", type, lower, upper, seq);
547 if (lower > upper) { 569 if (lower > upper) {
548 warn("Failed to publish illegal <%u,%u,%u>\n", 570 warn("Failed to publish illegal {%u,%u,%u}\n",
549 type, lower, upper); 571 type, lower, upper);
550 return NULL; 572 return NULL;
551 } 573 }
552 574
553 dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); 575 dbg("Publishing {%u,%u,%u} from 0x%x\n", type, lower, upper, node);
554 if (!seq) { 576 if (!seq) {
555 seq = tipc_nameseq_create(type, &table.types[hash(type)]); 577 seq = tipc_nameseq_create(type, &table.types[hash(type)]);
556 dbg("tipc_nametbl_insert_publ: created %x\n", seq); 578 dbg("tipc_nametbl_insert_publ: created %p\n", seq);
557 } 579 }
558 if (!seq) 580 if (!seq)
559 return NULL; 581 return NULL;
560 582
561 assert(seq->type == type);
562 return tipc_nameseq_insert_publ(seq, type, lower, upper, 583 return tipc_nameseq_insert_publ(seq, type, lower, upper,
563 scope, node, port, key); 584 scope, node, port, key);
564} 585}
@@ -572,7 +593,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
572 if (!seq) 593 if (!seq)
573 return NULL; 594 return NULL;
574 595
575 dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); 596 dbg("Withdrawing {%u,%u} from 0x%x\n", type, lower, node);
576 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); 597 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
577 598
578 if (!seq->first_free && list_empty(&seq->subscriptions)) { 599 if (!seq->first_free && list_empty(&seq->subscriptions)) {
@@ -738,12 +759,12 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
738 struct publication *publ; 759 struct publication *publ;
739 760
740 if (table.local_publ_count >= tipc_max_publications) { 761 if (table.local_publ_count >= tipc_max_publications) {
741 warn("Failed publish: max %u local publication\n", 762 warn("Publication failed, local publication limit reached (%u)\n",
742 tipc_max_publications); 763 tipc_max_publications);
743 return NULL; 764 return NULL;
744 } 765 }
745 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { 766 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
746 warn("Failed to publish reserved name <%u,%u,%u>\n", 767 warn("Publication failed, reserved name {%u,%u,%u}\n",
747 type, lower, upper); 768 type, lower, upper);
748 return NULL; 769 return NULL;
749 } 770 }
@@ -767,10 +788,10 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
767{ 788{
768 struct publication *publ; 789 struct publication *publ;
769 790
770 dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); 791 dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u\n", type, lower, key);
771 write_lock_bh(&tipc_nametbl_lock); 792 write_lock_bh(&tipc_nametbl_lock);
772 publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); 793 publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
773 if (publ) { 794 if (likely(publ)) {
774 table.local_publ_count--; 795 table.local_publ_count--;
775 if (publ->scope != TIPC_NODE_SCOPE) 796 if (publ->scope != TIPC_NODE_SCOPE)
776 tipc_named_withdraw(publ); 797 tipc_named_withdraw(publ);
@@ -780,6 +801,9 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
780 return 1; 801 return 1;
781 } 802 }
782 write_unlock_bh(&tipc_nametbl_lock); 803 write_unlock_bh(&tipc_nametbl_lock);
804 err("Unable to remove local publication\n"
805 "(type=%u, lower=%u, ref=%u, key=%u)\n",
806 type, lower, ref, key);
783 return 0; 807 return 0;
784} 808}
785 809
@@ -787,8 +811,7 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
787 * tipc_nametbl_subscribe - add a subscription object to the name table 811 * tipc_nametbl_subscribe - add a subscription object to the name table
788 */ 812 */
789 813
790void 814void tipc_nametbl_subscribe(struct subscription *s)
791tipc_nametbl_subscribe(struct subscription *s)
792{ 815{
793 u32 type = s->seq.type; 816 u32 type = s->seq.type;
794 struct name_seq *seq; 817 struct name_seq *seq;
@@ -800,11 +823,13 @@ tipc_nametbl_subscribe(struct subscription *s)
800 } 823 }
801 if (seq){ 824 if (seq){
802 spin_lock_bh(&seq->lock); 825 spin_lock_bh(&seq->lock);
803 dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n", 826 dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n",
804 seq, type, s->seq.lower, s->seq.upper); 827 seq, type, s->seq.lower, s->seq.upper);
805 assert(seq->type == type);
806 tipc_nameseq_subscribe(seq, s); 828 tipc_nameseq_subscribe(seq, s);
807 spin_unlock_bh(&seq->lock); 829 spin_unlock_bh(&seq->lock);
830 } else {
831 warn("Failed to create subscription for {%u,%u,%u}\n",
832 s->seq.type, s->seq.lower, s->seq.upper);
808 } 833 }
809 write_unlock_bh(&tipc_nametbl_lock); 834 write_unlock_bh(&tipc_nametbl_lock);
810} 835}
@@ -813,8 +838,7 @@ tipc_nametbl_subscribe(struct subscription *s)
813 * tipc_nametbl_unsubscribe - remove a subscription object from name table 838 * tipc_nametbl_unsubscribe - remove a subscription object from name table
814 */ 839 */
815 840
816void 841void tipc_nametbl_unsubscribe(struct subscription *s)
817tipc_nametbl_unsubscribe(struct subscription *s)
818{ 842{
819 struct name_seq *seq; 843 struct name_seq *seq;
820 844
@@ -1049,35 +1073,20 @@ int tipc_nametbl_init(void)
1049 1073
1050void tipc_nametbl_stop(void) 1074void tipc_nametbl_stop(void)
1051{ 1075{
1052 struct hlist_head *seq_head;
1053 struct hlist_node *seq_node;
1054 struct hlist_node *tmp;
1055 struct name_seq *seq;
1056 u32 i; 1076 u32 i;
1057 1077
1058 if (!table.types) 1078 if (!table.types)
1059 return; 1079 return;
1060 1080
1081 /* Verify name table is empty, then release it */
1082
1061 write_lock_bh(&tipc_nametbl_lock); 1083 write_lock_bh(&tipc_nametbl_lock);
1062 for (i = 0; i < tipc_nametbl_size; i++) { 1084 for (i = 0; i < tipc_nametbl_size; i++) {
1063 seq_head = &table.types[i]; 1085 if (!hlist_empty(&table.types[i]))
1064 hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { 1086 err("tipc_nametbl_stop(): hash chain %u is non-null\n", i);
1065 struct sub_seq *sseq = seq->sseqs;
1066
1067 for (; sseq != &seq->sseqs[seq->first_free]; sseq++) {
1068 struct publication *publ = sseq->zone_list;
1069 assert(publ);
1070 do {
1071 struct publication *next =
1072 publ->zone_list_next;
1073 kfree(publ);
1074 publ = next;
1075 }
1076 while (publ != sseq->zone_list);
1077 }
1078 }
1079 } 1087 }
1080 kfree(table.types); 1088 kfree(table.types);
1081 table.types = NULL; 1089 table.types = NULL;
1082 write_unlock_bh(&tipc_nametbl_lock); 1090 write_unlock_bh(&tipc_nametbl_lock);
1083} 1091}
1092