diff options
Diffstat (limited to 'net/tipc/name_table.c')
-rw-r--r-- | net/tipc/name_table.c | 207 |
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 | ||
102 | static struct name_table table = { NULL } ; | 102 | static struct name_table table = { NULL } ; |
103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); | 103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); |
104 | rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; | 104 | DEFINE_RWLOCK(tipc_nametbl_lock); |
105 | 105 | ||
106 | 106 | ||
107 | static int hash(int x) | 107 | static 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 | ||
372 | static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, | 382 | static 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 | } |
451 | end_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)); | 481 | end_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 | ||
790 | void | 814 | void tipc_nametbl_subscribe(struct subscription *s) |
791 | tipc_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 | ||
816 | void | 841 | void tipc_nametbl_unsubscribe(struct subscription *s) |
817 | tipc_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 | ||
1050 | void tipc_nametbl_stop(void) | 1074 | void 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 | |||